From 3df6e6f4b7720a0877a7ec4c8fc3a4cb0a2c6cd5 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 01:26:41 -0700 Subject: [PATCH 01/42] Another lost function --- nmod_sparse_vec/dot_dense.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 nmod_sparse_vec/dot_dense.c diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c new file mode 100644 index 0000000000..e3a025fb7e --- /dev/null +++ b/nmod_sparse_vec/dot_dense.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) { + slong i; + mp_limb_t ret = UWORD(0); + for(i=0; innz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); + return ret; +} From 320ed326c53494d53a80ed1eadc2122e08d3d902 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 25 Mar 2020 18:50:39 -0700 Subject: [PATCH 02/42] Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters --- CMakeLists.txt | 4 +- Makefile.in | 2 +- nmod_mat.h | 7 + nmod_sparse_mat.h | 225 +++++++++++++++++++++ nmod_sparse_mat/add.c | 54 +++++ nmod_sparse_mat/append_row.c | 33 +++ nmod_sparse_mat/clear.c | 31 +++ nmod_sparse_mat/concat_horizontal.c | 48 +++++ nmod_sparse_mat/concat_vertical.c | 32 +++ nmod_sparse_mat/equal.c | 50 +++++ nmod_sparse_mat/from_dense.c | 47 +++++ nmod_sparse_mat/from_entries.c | 40 ++++ nmod_sparse_mat/init.c | 31 +++ nmod_sparse_mat/mul_mat.c | 34 ++++ nmod_sparse_mat/mul_vec.c | 34 ++++ nmod_sparse_mat/neg.c | 26 +++ nmod_sparse_mat/one.c | 31 +++ nmod_sparse_mat/print_pretty.c | 60 ++++++ nmod_sparse_mat/randtest.c | 53 +++++ nmod_sparse_mat/scalar_mul.c | 49 +++++ nmod_sparse_mat/set.c | 35 ++++ nmod_sparse_mat/sub.c | 57 ++++++ nmod_sparse_mat/swap.c | 24 +++ nmod_sparse_mat/test/t-add.c | 65 ++++++ nmod_sparse_mat/test/t-concat_horizontal.c | 81 ++++++++ nmod_sparse_mat/test/t-concat_vertical.c | 79 ++++++++ nmod_sparse_mat/test/t-construct.c | 88 ++++++++ nmod_sparse_mat/test/t-dense.c | 77 +++++++ nmod_sparse_mat/test/t-init_clear.c | 80 ++++++++ nmod_sparse_mat/test/t-mul.c | 87 ++++++++ nmod_sparse_mat/test/t-neg.c | 75 +++++++ nmod_sparse_mat/test/t-scalar_mul.c | 81 ++++++++ nmod_sparse_mat/test/t-transpose.c | 65 ++++++ nmod_sparse_mat/to_dense.c | 28 +++ nmod_sparse_mat/transpose.c | 50 +++++ nmod_sparse_mat/window_clear.c | 23 +++ nmod_sparse_mat/window_init.c | 52 +++++ nmod_sparse_mat/zero.c | 26 +++ 38 files changed, 1961 insertions(+), 3 deletions(-) create mode 100644 nmod_sparse_mat.h create mode 100644 nmod_sparse_mat/add.c create mode 100644 nmod_sparse_mat/append_row.c create mode 100644 nmod_sparse_mat/clear.c create mode 100644 nmod_sparse_mat/concat_horizontal.c create mode 100644 nmod_sparse_mat/concat_vertical.c create mode 100644 nmod_sparse_mat/equal.c create mode 100644 nmod_sparse_mat/from_dense.c create mode 100644 nmod_sparse_mat/from_entries.c create mode 100644 nmod_sparse_mat/init.c create mode 100644 nmod_sparse_mat/mul_mat.c create mode 100644 nmod_sparse_mat/mul_vec.c create mode 100644 nmod_sparse_mat/neg.c create mode 100644 nmod_sparse_mat/one.c create mode 100644 nmod_sparse_mat/print_pretty.c create mode 100644 nmod_sparse_mat/randtest.c create mode 100644 nmod_sparse_mat/scalar_mul.c create mode 100644 nmod_sparse_mat/set.c create mode 100644 nmod_sparse_mat/sub.c create mode 100644 nmod_sparse_mat/swap.c create mode 100644 nmod_sparse_mat/test/t-add.c create mode 100644 nmod_sparse_mat/test/t-concat_horizontal.c create mode 100644 nmod_sparse_mat/test/t-concat_vertical.c create mode 100644 nmod_sparse_mat/test/t-construct.c create mode 100644 nmod_sparse_mat/test/t-dense.c create mode 100644 nmod_sparse_mat/test/t-init_clear.c create mode 100644 nmod_sparse_mat/test/t-mul.c create mode 100644 nmod_sparse_mat/test/t-neg.c create mode 100644 nmod_sparse_mat/test/t-scalar_mul.c create mode 100644 nmod_sparse_mat/test/t-transpose.c create mode 100644 nmod_sparse_mat/to_dense.c create mode 100644 nmod_sparse_mat/transpose.c create mode 100644 nmod_sparse_mat/window_clear.c create mode 100644 nmod_sparse_mat/window_init.c create mode 100644 nmod_sparse_mat/zero.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2616d0669f..cc693bd107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,8 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly - nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic - fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_mat + nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic + fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve double_extras d_vec d_mat padic_poly padic_mat qadic fq fq_vec fq_mat fq_poly fq_poly_factor diff --git a/Makefile.in b/Makefile.in index e2ad7de956..fe5a1ae56d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,7 +8,7 @@ AT=@ BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly \ fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly \ - nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic \ + nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic \ fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly \ fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve \ double_extras d_vec d_mat padic_poly padic_mat qadic \ diff --git a/nmod_mat.h b/nmod_mat.h index c1190a5c72..1cae3a31bf 100644 --- a/nmod_mat.h +++ b/nmod_mat.h @@ -192,6 +192,13 @@ void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c /* Matrix multiplication */ +NMOD_MAT_INLINE +void nmod_mat_mul_vec(mp_ptr y, const nmod_mat_t A, const mp_ptr x) { + slong i; + slong limbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); + for(i=0; ir; ++i) + y[i] = _nmod_vec_dot(A->rows[i], x, A->c, A->mod, limbs); +} FLINT_DLL void nmod_mat_mul(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); FLINT_DLL int nmod_mat_mul_blas(nmod_mat_t C, const nmod_mat_t A, const nmod_mat_t B); diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h new file mode 100644 index 0000000000..1954f81e2e --- /dev/null +++ b/nmod_sparse_mat.h @@ -0,0 +1,225 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef NMOD_SPARSE_MAT_H +#define NMOD_SPARSE_MAT_H + +#ifdef NMOD_SPARSE_MAT_INLINES_C +#define NMOD_SPARSE_MAT_INLINE FLINT_DLL +#else +#define NMOD_SPARSE_MAT_INLINE static __inline__ +#endif + +#undef ulong +#define ulong ulongxx /* interferes with system includes */ +#include +#undef ulong +#include +#define ulong mp_limb_t + +#include "flint.h" +#include "longlong.h" +#include "ulong_extras.h" +#include "nmod_vec.h" +#include "nmod_mat.h" +#include "fmpz.h" +#include "thread_support.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Sparse matrix stored in compressed sparse row format */ +/* Each entry is a column and a value */ +typedef struct +{ + mp_limb_t val; + slong col; +} nmod_sparse_mat_entry_struct; + +typedef nmod_sparse_mat_entry_struct nmod_sparse_mat_entry_t[1]; + +/* A sparse matrix is a list of sparse sparse elements */ +typedef struct +{ + nmod_sparse_mat_entry_struct *entries; + slong *row_starts; + slong *row_nnz; + slong r; + slong c; + slong c_off; + slong nnz; + nmod_t mod; +} +nmod_sparse_mat_struct; + +typedef nmod_sparse_mat_struct nmod_sparse_mat_t[1]; + +NMOD_SPARSE_MAT_INLINE +void _nmod_sparse_mat_set_c(nmod_sparse_mat_t mat) +{ + slong i; + mat->c = 0; + for(i=0; innz; ++i) + if(mat->entries[i].col >= mat->c) + mat->c = mat->entries[i].col + 1; +} + +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_nrows(const nmod_sparse_mat_t mat) +{ + return mat->r; +} + +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_ncols(const nmod_sparse_mat_t mat) +{ + return mat->c; +} + +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_nnz(const nmod_sparse_mat_t mat) +{ + return mat->nnz; +} + +NMOD_SPARSE_MAT_INLINE +void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t mat, mp_limb_t n) +{ + mat->mod.n = n; + count_leading_zeros(mat->mod.norm, n); + invert_limb(mat->mod.ninv, n << mat->mod.norm); +} + +/* Memory management */ +FLINT_DLL void nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n); +FLINT_DLL void nmod_sparse_mat_clear(nmod_sparse_mat_t mat); +FLINT_DLL void nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2); + +/* One-time instantiation */ +FLINT_DLL void nmod_sparse_mat_zero(nmod_sparse_mat_t mat); +FLINT_DLL void nmod_sparse_mat_one(nmod_sparse_mat_t mat); +FLINT_DLL void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src); +FLINT_DLL void nmod_sparse_mat_set_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); + +/* Incremental instantiation */ +FLINT_DLL void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong *cols, mp_limb_t *vals, slong nnz); + +/* Convert from/to dense matrix */ +FLINT_DLL void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src); +FLINT_DLL void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src); + +/* Windows and concatenation */ +FLINT_DLL void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2); +FLINT_DLL void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window); + +/* res->r must equal mat1->r + mat2->r, and res->c, mat1->c, and mat2->c must be equal */ +FLINT_DLL void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, + const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); +/* res->r, mat1->r, and mat2->r must be equal, and res->c must equal mat1->c + mat2->c */ +FLINT_DLL void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, + const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); + +/* Random matrix generation */ +FLINT_DLL void nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state); +/* +FLINT_DLL void nmod_sparse_mat_randfull(nmod_sparse_mat_t mat, flint_rand_t state); +FLINT_DLL int nmod_sparse_mat_randpermdiag(nmod_sparse_mat_t mat, flint_rand_t state, + mp_srcptr diag, slong n); +FLINT_DLL void nmod_sparse_mat_randrank(nmod_sparse_mat_t, flint_rand_t state, slong rank); +FLINT_DLL void nmod_sparse_mat_randops(nmod_sparse_mat_t mat, slong count, flint_rand_t state); +FLINT_DLL void nmod_sparse_mat_randtril(nmod_sparse_mat_t mat, flint_rand_t state, int unit); +FLINT_DLL void nmod_sparse_mat_randtriu(nmod_sparse_mat_t mat, flint_rand_t state, int unit); + */ + +FLINT_DLL void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat); + +FLINT_DLL int nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); + +NMOD_SPARSE_MAT_INLINE +int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t mat) { + return mat->nnz == 0; +} + +NMOD_SPARSE_MAT_INLINE +int +nmod_sparse_mat_is_zero_row(const nmod_sparse_mat_t mat, slong i) +{ + return mat->row_nnz[i]==0; +} + +NMOD_SPARSE_MAT_INLINE +int nmod_sparse_mat_is_square(const nmod_sparse_mat_t mat) +{ + return (mat->r == mat->c); +} + +/* Must have A->r == B->c and A->c == B->r */ +FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A); + +/* Addition and subtraction */ +/* Arguments must be distinct */ +FLINT_DLL void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B); +FLINT_DLL void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B); + +FLINT_DLL void nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A); + +/* Matrix-scalar arithmetic */ + +FLINT_DLL void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c); + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t res, const nmod_sparse_mat_t M, const fmpz_t c) +{ + fmpz_t d; + fmpz_init(d); + fmpz_mod_ui(d, c, res->mod.n); + nmod_sparse_mat_scalar_mul(res, M, fmpz_get_ui(d)); + fmpz_clear(d); +} + +/* Matrix-vector and matrix-matrix multipliciation */ +FLINT_DLL void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x); +FLINT_DLL void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X); + +/* Permutations */ +/* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t mat, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t mat, slong * perm); +FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t mat, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t mat, slong * perm); +FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, slong n); + */ +/* Nonsingular solving */ + +/* FLINT_DLL int nmod_sparse_mat_solve(nmod_mat_t X, const nmod_sparse_mat_t A, const nmod_mat_t B); +FLINT_DLL int nmod_sparse_mat_solve_vec(mp_ptr x, const nmod_sparse_mat_t A, mp_srcptr b); + */ +/* Nullspace */ + +/* FLINT_DLL slong nmod_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); + */ +/* + Suggested initial modulus size for multimodular algorithms. This should + be chosen so that we get the most number of bits per cycle + in matrix multiplication. On x86-64 it appears to be optimal to use + moduli giving nlimbs = 2. This should hold both in the classical + range and in Strassen blocks. + */ +#define NMOD_SPARSE_MAT_OPTIMAL_MODULUS_BITS (FLINT_BITS-5) + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/nmod_sparse_mat/add.c b/nmod_sparse_mat/add.c new file mode 100644 index 0000000000..b92d218d38 --- /dev/null +++ b/nmod_sparse_mat/add.c @@ -0,0 +1,54 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + +void +nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + slong i; + + C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); + memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); + C->nnz = 0; + + for (i = 0; i < C->r; i++) + { + C->row_starts[i] = C->nnz; + nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; + nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; + nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; + slong j = 0; + slong k = 0; + slong nnz = 0; + /* Interleave ith rows until one runs out */ + while(j < A->row_nnz[i] && k < B->row_nnz[i]) { + slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); + if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; + if(Be[k].col == col) Ce[nnz].val = nmod_add(Ce[nnz].val, Be[k++].val, C->mod); + if(Ce[nnz].val != UWORD(0)) ++nnz; + } + /* Add remainder of A row */ + for(; jrow_nnz[i]; ++j, ++nnz) Ce[nnz] = Ae[j]; + /* Add remainder of B row */ + for(; krow_nnz[i]; ++k, ++nnz) Ce[nnz]= Be[k]; + + C->row_nnz[i] = nnz; + C->nnz += nnz; + } + _nmod_sparse_mat_set_c(C); + C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); +} diff --git a/nmod_sparse_mat/append_row.c b/nmod_sparse_mat/append_row.c new file mode 100644 index 0000000000..1d0e4ad872 --- /dev/null +++ b/nmod_sparse_mat/append_row.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Elements must be ordered by row then col */ +void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong * cols, mp_limb_t * vals, slong nnz) +{ + slong i; + mat->entries = flint_realloc(mat->entries, (mat->nnz + nnz)* sizeof(*mat->entries)); + mat->row_starts[row] = mat->nnz; + mat->row_nnz[row] = nnz; + + nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[row]; + for(i = 0; i < nnz; i++) { + e[i].col = cols[i]; + e[i].val = vals[i]; + if(e[i].col >= mat->c) mat->c = e->col + 1; + } + mat->nnz += nnz; +} diff --git a/nmod_sparse_mat/clear.c b/nmod_sparse_mat/clear.c new file mode 100644 index 0000000000..9aec210a46 --- /dev/null +++ b/nmod_sparse_mat/clear.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_clear(nmod_sparse_mat_t mat) +{ + if(mat->entries) + { + flint_free(mat->entries); + } + if(mat->row_starts) { + flint_free(mat->row_starts); + } + if(mat->row_nnz) { + flint_free(mat->row_nnz); + } +} diff --git a/nmod_sparse_mat/concat_horizontal.c b/nmod_sparse_mat/concat_horizontal.c new file mode 100644 index 0000000000..b41849a0ef --- /dev/null +++ b/nmod_sparse_mat/concat_horizontal.c @@ -0,0 +1,48 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + if(res->r == 0) return; + if(mat1->c == 0) { + nmod_sparse_mat_set(res, mat2); + return; + } + if(mat2->c == 0) { + nmod_sparse_mat_set(res, mat1); + return; + } + slong i, j; + res->c = mat1->c + mat2->c; + res->nnz = mat1->nnz + mat2->nnz; + res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); + + for (i = 0; i < res->r; i++) + { + res->row_starts[i] = mat1->row_starts[i] + mat2->row_starts[i]; + nmod_sparse_mat_entry_struct *e = res->entries + res->row_starts[i]; + nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; + nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; + for(j = 0; j < mat1->row_nnz[i]; ++j, ++e, ++e1) { + e->col = e1->col; + e->val = e1->val; + } + for(j = 0; j < mat2->row_nnz[i]; ++j, ++e, ++e2) { + e->col = e2->col + mat1->c; + e->val = e2->val; + } + res->row_nnz[i] = mat1->row_nnz[i] + mat2->row_nnz[i]; + } +} diff --git a/nmod_sparse_mat/concat_vertical.c b/nmod_sparse_mat/concat_vertical.c new file mode 100644 index 0000000000..a964bf0f83 --- /dev/null +++ b/nmod_sparse_mat/concat_vertical.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + + res->c = (mat1->c > mat2->c)?(mat1->c):(mat2->c); + res->nnz = mat1->nnz + mat2->nnz; + res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); + memcpy(res->entries, mat1->entries, mat1->nnz * sizeof(*res->entries)); + memcpy(res->entries + mat1->nnz, mat2->entries, mat2->nnz * sizeof(*res->entries)); + memcpy(res->row_starts, mat1->row_starts, mat1->r * sizeof(*res->row_starts)); + memcpy(res->row_starts+mat1->r, mat2->row_starts, mat2->r * sizeof(*res->row_starts)); + memcpy(res->row_nnz, mat1->row_nnz, mat1->r*sizeof(*res->row_nnz)); + memcpy(res->row_nnz+mat1->r, mat2->row_nnz, mat2->r*sizeof(*res->row_nnz)); + + for (i = 0; i < mat2->r; i++) + res->row_starts[mat1->r + i] += mat1->nnz; +} diff --git a/nmod_sparse_mat/equal.c b/nmod_sparse_mat/equal.c new file mode 100644 index 0000000000..98d0ad1922 --- /dev/null +++ b/nmod_sparse_mat/equal.c @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +int +nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + if (mat1->r != mat2->r) { + printf("Different number of rows\n"); + return 0; + } + + if (mat1->nnz != mat2->nnz) { + printf("Different number of nonzeroes\n"); + return 0; + } + + if (mat1->nnz == 0) + return 1; + + if(memcmp(mat1->row_nnz, mat2->row_nnz, mat1->r * sizeof(*mat1->row_nnz))) { + printf("Different row_nnz\n"); return 0; + } + + slong i, j; + for(i=0; ir; ++i) { + nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; + nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; + for(j=0; jrow_nnz[i]; ++j, ++e1, ++e2) { + if((e1->col - mat1->c_off != e2->col - mat2->c_off) || (e1->val != e2->val)) { + flint_printf("Mismatched row %d, entry %d\n", i, j); + return 0; + } + } + } + return 1; +} diff --git a/nmod_sparse_mat/from_dense.c b/nmod_sparse_mat/from_dense.c new file mode 100644 index 0000000000..ef7fdc6dba --- /dev/null +++ b/nmod_sparse_mat/from_dense.c @@ -0,0 +1,47 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Assumes B->c == A->r */ +void +nmod_sparse_mat_from_dense(nmod_sparse_mat_t B, const nmod_mat_t A) +{ + slong i, j; + if(A->r == 0) return; + if(A->c == 0) {nmod_sparse_mat_zero(B); return;} + B->entries = flint_realloc(B->entries, A->r * A->c * sizeof(*B->entries)); + B->nnz = 0; + B->c = 0; + for(i=0; i < A->r; ++i) { + B->row_starts[i] = B->nnz; + B->row_nnz[i] = 0; + for(j=0; j < A->c; ++j) { + if(A->rows[i][j] != UWORD(0)) { + B->entries[B->nnz].col = j; + B->entries[B->nnz].val = A->rows[i][j]; + B->row_nnz[i]++; + B->nnz++; + } + } + } + _nmod_sparse_mat_set_c(B); + if(B->nnz > 0) + B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); + else { + flint_free(B->entries); + B->entries = NULL; + } +} diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c new file mode 100644 index 0000000000..f05cfe298f --- /dev/null +++ b/nmod_sparse_mat/from_entries.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Elements must be ordered by row then col */ +void nmod_sparse_mat_set_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) +{ + if(nnz==0) { + nmod_sparse_mat_zero(mat); + return; + } + slong i; + mat->entries = flint_realloc(mat->entries, nnz * sizeof(*mat->entries)); + memset(mat->row_starts, 0, sizeof(*mat->row_starts)); + memset(mat->row_nnz, 0, sizeof(*mat->row_nnz)); + mat->c = 0; + for(i = 0; i < nnz; i++) { + if(i > 0 && rows[i] != rows[i-1]) { + mat->row_starts[rows[i]] = i; + } + mat->entries[i].col = cols[i]; + mat->entries[i].val = vals[i]; + mat->row_nnz[rows[i]]++; + } + _nmod_sparse_mat_set_c(mat); + mat->nnz = nnz; +} diff --git a/nmod_sparse_mat/init.c b/nmod_sparse_mat/init.c new file mode 100644 index 0000000000..4601dcdc25 --- /dev/null +++ b/nmod_sparse_mat/init.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + + +void +nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n) +{ + memset(mat, 0, sizeof(*mat)); + mat->r = rows; + mat->c = 0; + if(rows > 0) { + mat->row_starts = flint_calloc(rows, rows*sizeof(*mat->row_starts)); + mat->row_nnz = flint_calloc(rows, rows*sizeof(*mat->row_nnz)); + } + _nmod_sparse_mat_set_mod(mat, n); +} diff --git a/nmod_sparse_mat/mul_mat.c b/nmod_sparse_mat/mul_mat.c new file mode 100644 index 0000000000..28164c782b --- /dev/null +++ b/nmod_sparse_mat/mul_mat.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* TODO: save reductions to end? */ +void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) { + slong i,j,k; + if(Y->r == 0 || Y->c == 0) return; + memset(Y->entries, 0, Y->r * Y->c * sizeof(*Y->entries)); + nmod_sparse_mat_entry_struct *e = A->entries; + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++e) { + if(e->val==1) + _nmod_vec_add(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); + else if(e->val==A->mod.n-1) + _nmod_vec_sub(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); + else + _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->col], X->c, e->val, A->mod); + } + } +} diff --git a/nmod_sparse_mat/mul_vec.c b/nmod_sparse_mat/mul_vec.c new file mode 100644 index 0000000000..4e47c6f939 --- /dev/null +++ b/nmod_sparse_mat/mul_vec.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* TODO: save reductions to end? */ +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) { + slong i,j; + memset(y, 0, A->r * sizeof(*y)); + nmod_sparse_mat_entry_struct *e = A->entries; + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++e) { + if(e->val==1) + y[i] = nmod_add(y[i], x[e->col], A->mod); + else if(e->val==A->mod.n-1) + y[i] = nmod_sub(y[i], x[e->col], A->mod); + else + y[i] = nmod_add(y[i], nmod_mul(x[e->col], e->val, A->mod), A->mod); + } + } +} + diff --git a/nmod_sparse_mat/neg.c b/nmod_sparse_mat/neg.c new file mode 100644 index 0000000000..970bf71f17 --- /dev/null +++ b/nmod_sparse_mat/neg.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + +void +nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + slong i; + + nmod_sparse_mat_set(B, A); + for (i = 0; i < A->nnz; i++) + B->entries[i].val = nmod_neg(B->entries[i].val, B->mod); +} diff --git a/nmod_sparse_mat/one.c b/nmod_sparse_mat/one.c new file mode 100644 index 0000000000..3257bd97f8 --- /dev/null +++ b/nmod_sparse_mat/one.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/*Function to convert a square matrix to an identity matrix + The matrix is assumed to be a square one*/ +void +nmod_sparse_mat_one(nmod_sparse_mat_t mat) +{ + mat->c = mat->nnz = mat->r; + mat->entries = flint_realloc(mat->entries, mat->r*sizeof(*mat->entries)); + slong i; + for(i = 0; i < mat->r; i++) { + mat->entries[i].val = 1; + mat->entries[i].col = i; + mat->row_starts[i] = i; + mat->row_nnz[i] = 1; + } +} diff --git a/nmod_sparse_mat/print_pretty.c b/nmod_sparse_mat/print_pretty.c new file mode 100644 index 0000000000..fd965e57cf --- /dev/null +++ b/nmod_sparse_mat/print_pretty.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +void +nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat) +{ + slong i, j, k=0;; + int width; + char row_fmt[FLINT_BITS + 5]; + char col_fmt[FLINT_BITS + 5]; + char val_fmt[FLINT_BITS + 5]; + + flint_printf("<%wd x %wd sparse integer matrix mod %wu (%wd nonzeroes)>\n", + mat->r, mat->c, mat->mod.n, mat->nnz); + + if (!(mat->c) || !(mat->r)) + return; + + width = n_sizeinbase(mat->r, 10); + flint_sprintf(row_fmt, "%%%dwd: [", width); + + width = n_sizeinbase(mat->c, 10); + flint_sprintf(col_fmt, "%%%dwd:", width); + + width = n_sizeinbase(mat->mod.n, 10); + flint_sprintf(val_fmt, "%%%dwd", width); + + for (i = 0; i < mat->r; i++) + { + flint_printf(row_fmt, i); + + nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[i]; + + for (j = 0; j < mat->row_nnz[i]; j++, e++) + { + flint_printf(col_fmt, e->col - mat->c_off); + flint_printf(val_fmt, e->val); + if (j + 1 < mat->row_nnz[i]) + flint_printf(" "); + } + + flint_printf("]\n"); + } +} + diff --git a/nmod_sparse_mat/randtest.c b/nmod_sparse_mat/randtest.c new file mode 100644 index 0000000000..1b99cdf1b0 --- /dev/null +++ b/nmod_sparse_mat/randtest.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +static int smat_ecmp(const void *va, const void *vb) { + const nmod_sparse_mat_entry_struct *a = va; + const nmod_sparse_mat_entry_struct *b = vb; + if(a->col < b->col) return -1; + if(b->col < a->col) return 1; + return 0; +} +void +nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state) +{ + slong i,j, entries_per_row = 0, m; + + if(mat->r >= 30) entries_per_row = 1+ n_randint(state, mat->r/10); + if(entries_per_row < 2) entries_per_row = 2; + mat->nnz = entries_per_row * mat->r; + mat->entries = flint_malloc(mat->nnz*sizeof(*mat->entries)); + for (i = 0; i < mat->r; i++) + { + mat->row_starts[i] = i*entries_per_row; + mat->row_nnz[i] = entries_per_row; + nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[i]; + for(j = 0; j < entries_per_row; ++j) { + e[j].col = j; + do + e[j].val = n_randtest(state) % mat->mod.n; + while(e[j].val==UWORD(0)); + } + + /* Use resevoir sampling to get random support */ + for(j = entries_per_row; j < mat->r; ++j) { + m = n_randint(state, j+1); + if(m < entries_per_row) e[m].col = j; + } + qsort(e, entries_per_row, sizeof(*e), smat_ecmp); + } + _nmod_sparse_mat_set_c(mat); +} diff --git a/nmod_sparse_mat/scalar_mul.c b/nmod_sparse_mat/scalar_mul.c new file mode 100644 index 0000000000..ff50dd81b8 --- /dev/null +++ b/nmod_sparse_mat/scalar_mul.c @@ -0,0 +1,49 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +void +nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) +{ + if (c == UWORD(0)) + { + nmod_sparse_mat_zero(B); + } + else if(c == UWORD(1)) + { + nmod_sparse_mat_set(B, A); + } + else if(c == B->mod.n - UWORD(1)) + { + nmod_sparse_mat_neg(B, A); + } + else + { + slong i; + nmod_sparse_mat_set(B, A); + if (A->nnz > 10 && A->mod.n < UWORD_HALF) + { + mp_limb_t w_pr = n_mulmod_precomp_shoup(c, A->mod.n); + for (i = 0; innz; i++) + B->entries[i].val = n_mulmod_shoup(c, B->entries[i].val, w_pr, A->mod.n); + } + else + { + for (i = 0; innz; i++) + B->entries[i].val = nmod_mul(c, B->entries[i].val, B->mod); + } + } +} diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c new file mode 100644 index 0000000000..76c1315409 --- /dev/null +++ b/nmod_sparse_mat/set.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Assumes B->r == A->r */ +void +nmod_sparse_mat_set(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + if (B == A) + return; + B->c = A->c; + B->nnz = A->nnz; + if(B->nnz == 0) { + flint_free(B->entries); + B->entries = NULL; + } else { + B->entries = flint_realloc(B->entries, A->nnz * sizeof(*B->entries)); + memcpy(B->entries, A->entries, A->nnz * sizeof(*B->entries)); + } + memcpy(B->row_starts, A->row_starts, A->r * sizeof(*B->row_starts)); + memcpy(B->row_nnz, A->row_nnz, A->r * sizeof(*B->row_nnz)); +} diff --git a/nmod_sparse_mat/sub.c b/nmod_sparse_mat/sub.c new file mode 100644 index 0000000000..80afd51edd --- /dev/null +++ b/nmod_sparse_mat/sub.c @@ -0,0 +1,57 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + + +void +nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + slong i; + + C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); + memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); + C->nnz = 0; + + for (i = 0; i < C->r; i++) + { + C->row_starts[i] = C->nnz; + nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; + nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; + nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; + slong j = 0; + slong k = 0; + slong nnz = 0; + /* Interleave ith rows until one runs out */ + while(j < A->row_nnz[i] && k < B->row_nnz[i]) { + slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); + if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; + if(Be[k].col == col) Ce[nnz].val = nmod_sub(Ce[nnz].val, Be[k++].val, C->mod); + if(Ce[nnz].val != UWORD(0)) ++nnz; + } + /* Add remainder of A row */ + for(; jrow_nnz[i]; ++j, ++nnz) + Ce[nnz] = Ae[j]; + /* Subtract remainder of B row */ + for(; krow_nnz[i]; ++k, ++nnz) + Ce[nnz] = Be[k], Ce[nnz].val = nmod_neg(Ce[nnz].val, C->mod); + + C->row_nnz[i] = nnz; + C->nnz += nnz; + } + _nmod_sparse_mat_set_c(C); + C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); +} diff --git a/nmod_sparse_mat/swap.c b/nmod_sparse_mat/swap.c new file mode 100644 index 0000000000..5657b63b05 --- /dev/null +++ b/nmod_sparse_mat/swap.c @@ -0,0 +1,24 @@ +/* + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) +{ + nmod_sparse_mat_t temp; + *temp = *mat1; + *mat1 = *mat2; + *mat2 = *temp; +} diff --git a/nmod_sparse_mat/test/t-add.c b/nmod_sparse_mat/test/t-add.c new file mode 100644 index 0000000000..cdc5c9a843 --- /dev/null +++ b/nmod_sparse_mat/test/t-add.c @@ -0,0 +1,65 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, B, C, D; + + m = n_randint(state, 200); + do + mod = n_randtest_not_zero(state); + while(mod <= UWORD(1)); + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_init(B, m, mod); + nmod_sparse_mat_init(C, m, mod); + nmod_sparse_mat_init(D, m, mod); + + nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_randtest(B, state); + + nmod_sparse_mat_add(C, A, B); + nmod_sparse_mat_sub(D, C, B); + + if (!nmod_sparse_mat_equal(D, A)) + { + flint_printf("FAIL\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + nmod_sparse_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c new file mode 100644 index 0000000000..143ba2e3d5 --- /dev/null +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -0,0 +1,81 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int main(void) +{ + nmod_sparse_mat_t A, B, C; + nmod_sparse_mat_t window1, window2; + slong i; + FLINT_TEST_INIT(state); + + flint_printf("concat_horizontal...."); + fflush(stdout); + + + for (i = 0; i < 100; i++) + { + slong r, mod; + + r = n_randint(state, 200); + do + mod = n_randlimb(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, r, mod); + nmod_sparse_mat_init(B, r, mod); + nmod_sparse_mat_init(C, r, mod); + + nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_randtest(B, state); + nmod_sparse_mat_randtest(C, state); + + nmod_sparse_mat_concat_horizontal(C, A, B); + + nmod_sparse_mat_window_init(window1, C, 0, 0, r, A->c); + nmod_sparse_mat_window_init(window2, C, 0, A->c, r, A->c + B->c); + + if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + nmod_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + nmod_sparse_mat_print_pretty(B); + flint_printf("A concat_horizontal B = \n"); + nmod_sparse_mat_print_pretty(C); + flint_printf("window1 = \n"); + nmod_sparse_mat_print_pretty(window1); + flint_printf("window2 = \n"); + nmod_sparse_mat_print_pretty(window2); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c new file mode 100644 index 0000000000..b4d545d419 --- /dev/null +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_vec.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int main(void) +{ + nmod_sparse_mat_t A, B, C; + nmod_sparse_mat_t window1, window2; + slong i; + FLINT_TEST_INIT(state); + + + flint_printf("concat_vertical...."); + fflush(stdout); + + for (i = 0; i < 100; i++) + { + slong r1, r2, c1, mod; + + r1 = n_randint(state, 50); + r2 = n_randint(state, 50); + do + mod = n_randlimb(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, r1, mod); + nmod_sparse_mat_init(B, r2, mod); + nmod_sparse_mat_init(C, (r1+r2), mod); + + nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_randtest(B, state); + nmod_sparse_mat_randtest(C, state); + + nmod_sparse_mat_concat_vertical(C, A, B); + + nmod_sparse_mat_window_init(window1, C, 0, 0, r1, C->c); + nmod_sparse_mat_window_init(window2, C, r1, 0, (r1+r2), C->c); + + if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + nmod_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + nmod_sparse_mat_print_pretty(B); + flint_printf("A concat_vertical B = \n"); + nmod_sparse_mat_print_pretty(C); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c new file mode 100644 index 0000000000..695ae6747a --- /dev/null +++ b/nmod_sparse_mat/test/t-construct.c @@ -0,0 +1,88 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, mod, rep; + FLINT_TEST_INIT(state); + + flint_printf("conversion to/from dense matrix...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + slong i, j, k; + nmod_sparse_mat_t A, B, C; + slong *rows, *cols; + mp_limb_t *vals; + nmod_sparse_mat_entry_struct *Ae; + + m = n_randint(state, 200); + + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_init(B, m, mod); + nmod_sparse_mat_init(C, m, mod); + nmod_sparse_mat_randtest(A, state); + + /* Construct B from entries of A */ + rows = flint_malloc(A->nnz * sizeof(*rows)); + cols = flint_malloc(A->nnz * sizeof(*cols)); + vals = flint_malloc(A->nnz * sizeof(*vals)); + for(i=0, k=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++k) { + rows[k] = i; + cols[k] = A->entries[k].col; + vals[k] = A->entries[k].val; + } + } + nmod_sparse_mat_set_from_entries(B, rows, cols, vals, A->nnz); + + if (!nmod_sparse_mat_equal(A, B)) + { + flint_printf("FAIL: A != B\n"); + abort(); + } + /* Construct C from rows of A */ + for(i=0; ir; ++i) { + nmod_sparse_mat_append_row(C, i, cols + A->row_starts[i], vals + A->row_starts[i], A->row_nnz[i]); + } + + if (!nmod_sparse_mat_equal(A, C)) + { + flint_printf("FAIL: A != C\n"); + abort(); + } + flint_free(rows); + flint_free(cols); + flint_free(vals); + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-dense.c b/nmod_sparse_mat/test/t-dense.c new file mode 100644 index 0000000000..517e0e8f94 --- /dev/null +++ b/nmod_sparse_mat/test/t-dense.c @@ -0,0 +1,77 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("conversion to/from dense matrix...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, B; + nmod_mat_t C, D; + + m = n_randint(state, 20); + + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_randtest(A, state); + + + nmod_mat_init(C, m, A->c, mod); + nmod_sparse_mat_to_dense(C, A); + + nmod_sparse_mat_init(B, m, mod); + nmod_sparse_mat_randtest(B, state); + nmod_sparse_mat_from_dense(B, C); + + if (!nmod_sparse_mat_equal(A, B)) + { + flint_printf("FAIL: A != B\n"); + abort(); + } + + nmod_mat_randtest(C, state); + nmod_sparse_mat_from_dense(A, C); + + nmod_mat_init(D, m, C->c, mod); + nmod_sparse_mat_to_dense(D, A); + + if(!nmod_mat_equal(C, D)) { + flint_printf("FAIL: C != D\n"); + abort(); + } + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_mat_clear(C); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-init_clear.c b/nmod_sparse_mat/test/t-init_clear.c new file mode 100644 index 0000000000..9f5b941d9a --- /dev/null +++ b/nmod_sparse_mat/test/t-init_clear.c @@ -0,0 +1,80 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, i, j, rep; + FLINT_TEST_INIT(state); + + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + nmod_sparse_mat_t A; + + m = n_randint(state, 50); + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + if(A->nnz != UWORD(0)) { + flint_printf("FAIL: nnz not zero!\n"); + abort(); + } + if(A->entries != NULL) { + flint_printf("FAIL: entries not null!\n"); + abort(); + } + if(A->c != UWORD(0)) { + flint_printf("FAIL: c not 0!\n"); + abort(); + } + + for (i = 0; i < m; i++) + { + if (A->row_starts[i] != UWORD(0)) + { + flint_printf("FAIL: row start not zero!\n"); + abort(); + } + if (A->row_nnz[i] != UWORD(0)) + { + flint_printf("FAIL: row nnz not zero!\n"); + abort(); + } + } + + if (A->mod.n != mod) + { + flint_printf("FAIL: bad modulus\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-mul.c b/nmod_sparse_mat/test/t-mul.c new file mode 100644 index 0000000000..56f6d1d1a6 --- /dev/null +++ b/nmod_sparse_mat/test/t-mul.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("multiplication by vec/mat...."); + fflush(stdout); + + for (rep = 0; rep < 10; rep++) + { + nmod_sparse_mat_t A; + mp_ptr x, y, y2; + nmod_mat_t B, X, Y, Y2; + + m = n_randint(state, 20); + n = n_randint(state, 20); + + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_randtest(A, state); + nmod_mat_init(B, m, A->c, mod); + nmod_sparse_mat_to_dense(B, A); + + x = _nmod_vec_init(A->c); + y = _nmod_vec_init(A->r); + y2 = _nmod_vec_init(A->r); + _nmod_vec_randtest(x, state, A->c, A->mod); + nmod_sparse_mat_mul_vec(y, A, x); + nmod_mat_mul_vec(y2, B, x); + + if (!_nmod_vec_equal(y, y2, A->r)) + { + flint_printf("FAIL: y != y2\n"); + abort(); + } + + nmod_mat_init(X, A->c, n, mod); + nmod_mat_init(Y, A->r, n, mod); + nmod_mat_init(Y2, A->r, n, mod); + nmod_mat_randtest(X, state); + nmod_sparse_mat_mul_mat(Y, A, X); + nmod_mat_mul(Y2, B, X); + + if (!nmod_mat_equal(Y, Y2)) { + flint_printf("Fail: Y != Y2\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_mat_clear(B); + nmod_mat_clear(X); + nmod_mat_clear(Y); + nmod_mat_clear(Y2); + _nmod_vec_clear(x); + _nmod_vec_clear(y); + _nmod_vec_clear(y2); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-neg.c b/nmod_sparse_mat/test/t-neg.c new file mode 100644 index 0000000000..42b1f00293 --- /dev/null +++ b/nmod_sparse_mat/test/t-neg.c @@ -0,0 +1,75 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, B, C, D; + + m = n_randint(state, 200); + do + mod = n_randlimb(state); + while(mod <= UWORD(1)); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_init(B, m, mod); + nmod_sparse_mat_init(C, m, mod); + nmod_sparse_mat_init(D, m, mod); + + nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_randtest(B, state); + + nmod_sparse_mat_sub(C, A, B); + nmod_sparse_mat_neg(B, B); + nmod_sparse_mat_add(D, A, B); + + if (!nmod_sparse_mat_equal(C, D)) + { + flint_printf("FAIL\n"); + abort(); + } + + nmod_sparse_mat_neg(C, B); + nmod_sparse_mat_neg(B, B); + + if (!nmod_sparse_mat_equal(C, B)) + { + flint_printf("FAIL\n"); + abort(); + } + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + nmod_sparse_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c new file mode 100644 index 0000000000..010e91a627 --- /dev/null +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -0,0 +1,81 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("scalar_mul...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, B, C, D; + mp_limb_t c; + + m = n_randint(state, 200); + do + mod = n_randtest_not_zero(state); + while(mod <= UWORD(1)); + + c = n_randint(state, mod); + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_init(B, m, mod); + nmod_sparse_mat_init(C, m, mod); + nmod_sparse_mat_init(D, m, mod); + + nmod_sparse_mat_randtest(A, state); + + nmod_sparse_mat_scalar_mul(B, A, c); + nmod_sparse_mat_scalar_mul(C, A, nmod_sub(c, UWORD(1), A->mod)); + + /* c*A - (c-1)*A == A */ + nmod_sparse_mat_sub(D, B, C); + + if (!nmod_sparse_mat_equal(A, D)) + { + flint_printf("FAIL\n"); + abort(); + } + + /* Aliasing */ + nmod_sparse_mat_scalar_mul(C, A, c); + nmod_sparse_mat_scalar_mul(A, A, c); + + if (!nmod_sparse_mat_equal(A, C)) + { + flint_printf("FAIL\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + nmod_sparse_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c new file mode 100644 index 0000000000..a9409c5e31 --- /dev/null +++ b/nmod_sparse_mat/test/t-transpose.c @@ -0,0 +1,65 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, mod2, rep; + FLINT_TEST_INIT(state); + + + flint_printf("transpose...."); + fflush(stdout); + + /* Rectangular transpose, same modulus */ + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, B, C; + + m = n_randint(state, 40); + + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_randtest(A, state); + + nmod_sparse_mat_init(B, A->c, mod); + nmod_sparse_mat_transpose(B, A); + + nmod_sparse_mat_init(C, m, mod); + nmod_sparse_mat_transpose(C, B); + + if (!nmod_sparse_mat_equal(C, A)) + { + flint_printf("FAIL: C != A\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/to_dense.c b/nmod_sparse_mat/to_dense.c new file mode 100644 index 0000000000..8fe597983c --- /dev/null +++ b/nmod_sparse_mat/to_dense.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) +{ + if(mat->r == 0 || mat->c == 0) return; + slong i, j, k=0; + memset(mat->entries, 0, mat->r * mat->c * sizeof(*mat->entries)); + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++k) { + mat->rows[i][src->entries[k].col] = src->entries[k].val; + } + } +} diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c new file mode 100644 index 0000000000..d79b911a89 --- /dev/null +++ b/nmod_sparse_mat/transpose.c @@ -0,0 +1,50 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + + slong i, j; + B->c = A->r; + B->nnz = A->nnz; + B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); + memset(B->row_starts, 0, B->r * sizeof(*B->row_starts)); + memset(B->row_nnz, 0, B->r * sizeof(*B->row_nnz)); + if(A->nnz == 0) return; + + /* Clear row counts for B and set row starts */ + nmod_sparse_mat_entry_struct *Ae, *Be; + Ae = A->entries; + for(i=0; innz; ++i) + if(Ae[i].col + 1 < B->r) + B->row_starts[Ae[i].col + 1] += 1; + for(i=1; ir; ++i) + B->row_starts[i] += B->row_starts[i-1]; + + /* Assign entries */ + Ae = A->entries; + Be = B->entries; + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++Ae) { + slong pos = B->row_starts[Ae->col] + B->row_nnz[Ae->col]++; + Be[pos].col = i; + Be[pos].val = Ae->val; + } + flint_printf("\n"); + } +} diff --git a/nmod_sparse_mat/window_clear.c b/nmod_sparse_mat/window_clear.c new file mode 100644 index 0000000000..476fadfb22 --- /dev/null +++ b/nmod_sparse_mat/window_clear.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_window_clear(nmod_sparse_mat_t B) +{ + flint_free(B->row_starts); + flint_free(B->row_nnz); +} diff --git a/nmod_sparse_mat/window_init.c b/nmod_sparse_mat/window_init.c new file mode 100644 index 0000000000..f18a898054 --- /dev/null +++ b/nmod_sparse_mat/window_init.c @@ -0,0 +1,52 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_window_init(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, slong r1, slong c1, slong r2, slong c2) +{ + slong i, j; + r1 = FLINT_MIN(r1, A->r); + r2 = FLINT_MIN(r2, A->r); + if(r2 < r1) r2 = r1; + if(c2 < c1) c2 = c1; + + B->entries = A->entries; + B->mod = A->mod; + B->r = r2-r1; + B->c_off = c1; + B->c = c2-c1; + B->nnz = 0; + if(B->r == 0) {B->row_starts = B->row_nnz = NULL; return;} + B->row_starts = flint_malloc(B->r * sizeof(*B->row_starts)); + B->row_nnz = flint_malloc(B->r * sizeof(*B->row_nnz)); + memcpy(B->row_starts, A->row_starts + r1, B->r*sizeof(*B->row_starts)); + memcpy(B->row_nnz, A->row_nnz + r1, B->r*sizeof(*B->row_nnz)); + + for(i = r1; ientries + A->row_starts[i]; + for(j=0; jrow_nnz[i]; ++j) { + if(c1 > 0 && Ae[j].col < c1) { + B->row_starts[i-r1] += 1; + B->row_nnz[i-r1] -= 1; + } else if(Ae[j].col >= c2) { + B->row_nnz[i-r1] -= 1; + } else { + B->nnz++; + } + } + } +} diff --git a/nmod_sparse_mat/zero.c b/nmod_sparse_mat/zero.c new file mode 100644 index 0000000000..f543a910da --- /dev/null +++ b/nmod_sparse_mat/zero.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_zero(nmod_sparse_mat_t mat) +{ + memset(mat->row_nnz, 0, mat->r*sizeof(*mat->row_nnz)); + memset(mat->row_starts, 0, mat->r*sizeof(*mat->row_starts)); + flint_free(mat->entries); + mat->entries = NULL; + mat->nnz = 0; +} From 002ed933223463a21b7cda6416a30acd9f18acc6 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 26 Mar 2020 19:20:18 -0700 Subject: [PATCH 03/42] Basic lanczos, assumes non-symmetric matrix, returns any pseudosolution (x s.t. AtAx = Ab) --- nmod_sparse_mat.h | 1 + nmod_sparse_mat/solve_lanczos.c | 76 +++++++++++++++++++++++++++ nmod_sparse_mat/test/t-solve.c | 93 +++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 nmod_sparse_mat/solve_lanczos.c create mode 100644 nmod_sparse_mat/test/t-solve.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 1954f81e2e..b5d9b1b4a3 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -200,6 +200,7 @@ FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t mat, slong * perm); FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, slong n); */ /* Nonsingular solving */ +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); /* FLINT_DLL int nmod_sparse_mat_solve(nmod_mat_t X, const nmod_sparse_mat_t A, const nmod_mat_t B); FLINT_DLL int nmod_sparse_mat_solve_vec(mp_ptr x, const nmod_sparse_mat_t A, mp_srcptr b); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c new file mode 100644 index 0000000000..209e967f58 --- /dev/null +++ b/nmod_sparse_mat/solve_lanczos.c @@ -0,0 +1,76 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + + +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state) { + _nmod_vec_zero(x, A->c); + + /* Construct transpose */ + nmod_sparse_mat_t At; + nmod_sparse_mat_init(At, A->c, A->mod.n); + nmod_sparse_mat_transpose(At, A); + + /* Construct auxiliary vectors */ + /* Rather than storing the whole sequence of values w_j, we alternate between two vectors */ + slong j, iter; + const slong nlimbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); + mp_ptr w[2], Aw, AtAw, Atb; + mp_limb_t delta[2]; + w[0] = _nmod_vec_init(A->c); + w[1] = _nmod_vec_init(A->c); + Aw = _nmod_vec_init(A->r); + AtAw = _nmod_vec_init(A->c); + Atb = _nmod_vec_init(A->c); + nmod_sparse_mat_mul_vec(Atb, At, b); + + /* Make 0th vector random (and -1st vector trivial) */ + _nmod_vec_randtest(w[0], state, A->c, A->mod); + _nmod_vec_zero(w[1], A->c); delta[1] = 1; + for(j=0; ; j=1-j) { + /* Compute A^T A w_j and check if it is orthogonal to w_j */ + nmod_sparse_mat_mul_vec(Aw, A, w[j]); + nmod_sparse_mat_mul_vec(AtAw, At, Aw); + delta[j] = _nmod_vec_dot(w[j], AtAw, A->c, A->mod, nlimbs); + if (delta[j]==UWORD(0)) break; // Can't make any more progress + + /* Update putative solution by /delta_j * w_j */ + const mp_limb_t wAtb = nmod_div(_nmod_vec_dot(w[j], Atb, A->c, A->mod, nlimbs), delta[j], A->mod); + _nmod_vec_scalar_addmul_nmod(x, w[j], A->c, wAtb, A->mod); + + /* w_{j+1} = AtAw - alpha*w_j - beta*w_{j-1}, where */ + /* alpha = /delta_j, and */ + /* beta = delta_j/delta_{j-1} */ + const mp_limb_t alpha = nmod_div(_nmod_vec_dot(AtAw, AtAw, A->c, A->mod, nlimbs), delta[j], A->mod); + const mp_limb_t beta = nmod_div(delta[j], delta[1-j], A->mod); + _nmod_vec_scalar_mul_nmod(w[1-j], w[1-j], A->c, nmod_neg(beta, A->mod), A->mod); + _nmod_vec_scalar_addmul_nmod(w[1-j], w[j], A->c, nmod_neg(alpha, A->mod), A->mod); + _nmod_vec_add(w[1-j], w[1-j], AtAw, A->c, A->mod); + } + /* Check result */ + nmod_sparse_mat_mul_vec(Aw, A, x); + nmod_sparse_mat_mul_vec(AtAw, At, Aw); + int ret = _nmod_vec_equal(AtAw, Atb, A->c); + + /* Clear auxiliary vectors and transpose */ + _nmod_vec_clear(w[0]); + _nmod_vec_clear(w[1]); + _nmod_vec_clear(Aw); + _nmod_vec_clear(AtAw); + _nmod_vec_clear(Atb); + nmod_sparse_mat_clear(At); + return ret; +} diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c new file mode 100644 index 0000000000..ccea3f2c68 --- /dev/null +++ b/nmod_sparse_mat/test/t-solve.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong m, n, mod, rep; + FLINT_TEST_INIT(state); + + + flint_printf("solving Ax=b...."); + fflush(stdout); + int niters = 0, nosol = 0, psolved = 0, nusolved = 0; + + for (rep = 0; rep < 1000; rep++) + { + nmod_sparse_mat_t A, At; + mp_ptr x, x2, b, Atb, Ax, AtAx; + + m = n_randint(state, 20); + n = n_randint(state, 20); + + do + mod = n_randtest_not_zero(state); + while(mod <= 32 || !n_is_prime(mod)); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_init(At, A->c, mod); + nmod_sparse_mat_transpose(At, A); + x = _nmod_vec_init(A->c); + x2 = _nmod_vec_init(A->c); + b = _nmod_vec_init(A->r); + Ax = _nmod_vec_init(A->r); + AtAx = _nmod_vec_init(A->c); + Atb = _nmod_vec_init(A->c); + + _nmod_vec_randtest(x, state, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + nmod_sparse_mat_mul_vec(Atb, At, b); + int iter, ret; + for(iter=1; iter<=10; ++iter) + if(ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; + if(iter==11) { + nosol += 1; + continue; + } + niters += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL: AtAx != Atb for mod=%wd, got ret %d\n", mod, ret); + abort(); + } else if(!_nmod_vec_equal(b, Ax, A->r)) { + psolved += 1; + } else if(!_nmod_vec_equal(x, x2, A->c)) { + nusolved += 1; + } + flint_free(x); + flint_free(x2); + flint_free(b); + flint_free(Ax); + flint_free(AtAx); + flint_free(Atb); + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(At); + } + flint_printf("No solution found for %wd/%wd examples\n", nosol, 1000); + flint_printf("Average number of iters to find solution: %f\n", niters/1000.); + flint_printf("Pseudo-solution found for %wd/%wd examples\n", psolved, 1000); + flint_printf("Alternate solution found for %wd/%wd examples\n", nusolved, 1000); + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} From 31cbf650d1474b9d71cbb4c41ca72e44d15c52c8 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 21:43:25 -0700 Subject: [PATCH 04/42] Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition --- CMakeLists.txt | 2 +- Makefile.in | 2 +- nmod_sparse_mat.h | 246 +++++++++++------- nmod_sparse_mat/add.c | 54 ---- nmod_sparse_mat/append_row.c | 33 --- nmod_sparse_mat/clear.c | 31 --- nmod_sparse_mat/concat_horizontal.c | 48 ---- nmod_sparse_mat/concat_vertical.c | 32 --- nmod_sparse_mat/equal.c | 50 ---- nmod_sparse_mat/from_dense.c | 47 ---- nmod_sparse_mat/from_entries.c | 28 +- nmod_sparse_mat/init.c | 31 --- nmod_sparse_mat/lu.c | 133 ++++++++++ nmod_sparse_mat/mul_mat.c | 34 --- nmod_sparse_mat/mul_vec.c | 34 --- nmod_sparse_mat/one.c | 31 --- nmod_sparse_mat/print_pretty.c | 35 +-- nmod_sparse_mat/randtest.c | 38 +-- nmod_sparse_mat/scalar_mul.c | 49 ---- nmod_sparse_mat/set.c | 26 +- nmod_sparse_mat/solve_lanczos.c | 2 +- .../{window_clear.c => solve_lu.c} | 9 +- nmod_sparse_mat/sub.c | 57 ---- nmod_sparse_mat/swap.c | 24 -- nmod_sparse_mat/test/t-add.c | 29 ++- nmod_sparse_mat/test/t-concat_horizontal.c | 31 +-- nmod_sparse_mat/test/t-concat_vertical.c | 34 +-- nmod_sparse_mat/test/t-construct.c | 67 +++-- nmod_sparse_mat/test/t-dense.c | 35 ++- nmod_sparse_mat/test/t-init_clear.c | 50 ++-- nmod_sparse_mat/test/t-mul.c | 50 ++-- nmod_sparse_mat/test/t-neg.c | 31 ++- nmod_sparse_mat/test/t-scalar_mul.c | 30 +-- nmod_sparse_mat/test/t-solve.c | 40 +-- nmod_sparse_mat/test/t-transpose.c | 28 +- nmod_sparse_mat/to_dense.c | 28 -- nmod_sparse_mat/transpose.c | 59 +++-- nmod_sparse_mat/window_init.c | 47 +--- nmod_sparse_mat/zero.c | 26 -- nmod_sparse_vec.h | 196 ++++++++++++++ nmod_sparse_mat/neg.c => nmod_sparse_vec/at.c | 21 +- nmod_sparse_vec/concat.c | 29 +++ nmod_sparse_vec/dot.c | 30 +++ nmod_sparse_vec/equal.c | 27 ++ nmod_sparse_vec/from_dense.c | 32 +++ nmod_sparse_vec/from_entries.c | 30 +++ nmod_sparse_vec/print_pretty.c | 38 +++ nmod_sparse_vec/randtest.c | 47 ++++ nmod_sparse_vec/scalar_addmul.c | 52 ++++ nmod_sparse_vec/scalar_mul.c | 27 ++ nmod_sparse_vec/set.c | 27 ++ nmod_sparse_vec/test/t-add.c | 79 ++++++ nmod_sparse_vec/test/t-concat.c | 79 ++++++ nmod_sparse_vec/test/t-construct.c | 72 +++++ nmod_sparse_vec/test/t-dense.c | 82 ++++++ nmod_sparse_vec/test/t-dot.c | 80 ++++++ nmod_sparse_vec/test/t-init_clear.c | 84 ++++++ nmod_sparse_vec/test/t-neg.c | 77 ++++++ nmod_sparse_vec/test/t-scalar_mul.c | 88 +++++++ nmod_sparse_vec/window_init.c | 25 ++ nmod_vec.h | 21 ++ 61 files changed, 1803 insertions(+), 1101 deletions(-) delete mode 100644 nmod_sparse_mat/add.c delete mode 100644 nmod_sparse_mat/append_row.c delete mode 100644 nmod_sparse_mat/clear.c delete mode 100644 nmod_sparse_mat/concat_horizontal.c delete mode 100644 nmod_sparse_mat/concat_vertical.c delete mode 100644 nmod_sparse_mat/equal.c delete mode 100644 nmod_sparse_mat/from_dense.c delete mode 100644 nmod_sparse_mat/init.c create mode 100644 nmod_sparse_mat/lu.c delete mode 100644 nmod_sparse_mat/mul_mat.c delete mode 100644 nmod_sparse_mat/mul_vec.c delete mode 100644 nmod_sparse_mat/one.c delete mode 100644 nmod_sparse_mat/scalar_mul.c rename nmod_sparse_mat/{window_clear.c => solve_lu.c} (68%) delete mode 100644 nmod_sparse_mat/sub.c delete mode 100644 nmod_sparse_mat/swap.c delete mode 100644 nmod_sparse_mat/to_dense.c delete mode 100644 nmod_sparse_mat/zero.c create mode 100644 nmod_sparse_vec.h rename nmod_sparse_mat/neg.c => nmod_sparse_vec/at.c (51%) create mode 100644 nmod_sparse_vec/concat.c create mode 100644 nmod_sparse_vec/dot.c create mode 100644 nmod_sparse_vec/equal.c create mode 100644 nmod_sparse_vec/from_dense.c create mode 100644 nmod_sparse_vec/from_entries.c create mode 100644 nmod_sparse_vec/print_pretty.c create mode 100644 nmod_sparse_vec/randtest.c create mode 100644 nmod_sparse_vec/scalar_addmul.c create mode 100644 nmod_sparse_vec/scalar_mul.c create mode 100644 nmod_sparse_vec/set.c create mode 100644 nmod_sparse_vec/test/t-add.c create mode 100644 nmod_sparse_vec/test/t-concat.c create mode 100644 nmod_sparse_vec/test/t-construct.c create mode 100644 nmod_sparse_vec/test/t-dense.c create mode 100644 nmod_sparse_vec/test/t-dot.c create mode 100644 nmod_sparse_vec/test/t-init_clear.c create mode 100644 nmod_sparse_vec/test/t-neg.c create mode 100644 nmod_sparse_vec/test/t-scalar_mul.c create mode 100644 nmod_sparse_vec/window_init.c diff --git a/CMakeLists.txt b/CMakeLists.txt index cc693bd107..8e7813cf80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly + fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve diff --git a/Makefile.in b/Makefile.in index fe5a1ae56d..6489b7c241 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ QUIET_AR = @echo ' ' AR ' ' $@; AT=@ BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly \ - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly \ + fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly \ nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic \ fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly \ fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve \ diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index b5d9b1b4a3..1de6864a9b 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -31,6 +31,7 @@ #include "longlong.h" #include "ulong_extras.h" #include "nmod_vec.h" +#include "nmod_sparse_vec.h" #include "nmod_mat.h" #include "fmpz.h" #include "thread_support.h" @@ -39,26 +40,13 @@ extern "C" { #endif -/* Sparse matrix stored in compressed sparse row format */ -/* Each entry is a column and a value */ -typedef struct -{ - mp_limb_t val; - slong col; -} nmod_sparse_mat_entry_struct; - -typedef nmod_sparse_mat_entry_struct nmod_sparse_mat_entry_t[1]; - -/* A sparse matrix is a list of sparse sparse elements */ +/* A sparse matrix is a list of sparse vectors */ typedef struct { - nmod_sparse_mat_entry_struct *entries; - slong *row_starts; - slong *row_nnz; + nmod_sparse_vec_struct *rows; slong r; slong c; slong c_off; - slong nnz; nmod_t mod; } nmod_sparse_mat_struct; @@ -66,72 +54,115 @@ nmod_sparse_mat_struct; typedef nmod_sparse_mat_struct nmod_sparse_mat_t[1]; NMOD_SPARSE_MAT_INLINE -void _nmod_sparse_mat_set_c(nmod_sparse_mat_t mat) +void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t mat, mp_limb_t n) { - slong i; - mat->c = 0; - for(i=0; innz; ++i) - if(mat->entries[i].col >= mat->c) - mat->c = mat->entries[i].col + 1; + mat->mod.n = n; + count_leading_zeros(mat->mod.norm, n); + invert_limb(mat->mod.ninv, n << mat->mod.norm); } +/* Memory management */ NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nrows(const nmod_sparse_mat_t mat) +void nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, slong cols, nmod_t mod) { - return mat->r; + mat->rows = flint_calloc(rows, sizeof(*mat->rows)); + mat->r = rows; + mat->c = cols; + mat->c_off = 0; + mat->mod = mod; } - NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_ncols(const nmod_sparse_mat_t mat) +void nmod_sparse_mat_clear(nmod_sparse_mat_t mat) { - return mat->c; + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_clear(&mat->rows[i]); + flint_free(mat->rows); + memset(mat, 0, sizeof(*mat)); } - NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nnz(const nmod_sparse_mat_t mat) +void nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) { - return mat->nnz; + nmod_sparse_mat_t tmp; + *tmp = *mat1; *mat1 = *mat2; *mat2 = *tmp; } +/* One-time instantiation */ NMOD_SPARSE_MAT_INLINE -void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t mat, mp_limb_t n) +void nmod_sparse_mat_zero(nmod_sparse_mat_t mat) { - mat->mod.n = n; - count_leading_zeros(mat->mod.norm, n); - invert_limb(mat->mod.ninv, n << mat->mod.norm); + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_zero(&mat->rows[i]); } -/* Memory management */ -FLINT_DLL void nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n); -FLINT_DLL void nmod_sparse_mat_clear(nmod_sparse_mat_t mat); -FLINT_DLL void nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_one(nmod_sparse_mat_t mat) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_one(&mat->rows[i], i); +} -/* One-time instantiation */ -FLINT_DLL void nmod_sparse_mat_zero(nmod_sparse_mat_t mat); -FLINT_DLL void nmod_sparse_mat_one(nmod_sparse_mat_t mat); -FLINT_DLL void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src); -FLINT_DLL void nmod_sparse_mat_set_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); +FLINT_DLL +void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src); -/* Incremental instantiation */ -FLINT_DLL void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong *cols, mp_limb_t *vals, slong nnz); +FLINT_DLL +void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); /* Convert from/to dense matrix */ -FLINT_DLL void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src); -FLINT_DLL void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); +} +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) { + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); +} /* Windows and concatenation */ -FLINT_DLL void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2); -FLINT_DLL void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window); +FLINT_DLL +void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2); + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) +{ + flint_free(window->rows); + memset(window, 0, sizeof(*window)); +} + +/* res->r must equal mat1->r and mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, + const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = mat1->c + mat2->c; + for(i=0; ir; ++i) + nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); +} +/* res->r must equal mat1->r + mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = FLINT_MAX(mat1->c, mat2->c); + for(i=0; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); + for(i=mat1->r; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); +} -/* res->r must equal mat1->r + mat2->r, and res->c, mat1->c, and mat2->c must be equal */ -FLINT_DLL void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, - const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); -/* res->r, mat1->r, and mat2->r must be equal, and res->c must equal mat1->c + mat2->c */ -FLINT_DLL void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, - const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); +/* Matrix permutation */ +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); +} /* Random matrix generation */ -FLINT_DLL void nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state); +FLINT_DLL void nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state, slong min_nnz, slong max_nnz); /* FLINT_DLL void nmod_sparse_mat_randfull(nmod_sparse_mat_t mat, flint_rand_t state); FLINT_DLL int nmod_sparse_mat_randpermdiag(nmod_sparse_mat_t mat, flint_rand_t state, @@ -144,18 +175,23 @@ FLINT_DLL void nmod_sparse_mat_randtriu(nmod_sparse_mat_t mat, flint_rand_t stat FLINT_DLL void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat); -FLINT_DLL int nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2); - NMOD_SPARSE_MAT_INLINE -int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t mat) { - return mat->nnz == 0; +int nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + if(mat1->r != mat2->r) return 0; + for(i=0; ir; ++i) + if(nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off)==0) return 0; + return 1; } NMOD_SPARSE_MAT_INLINE -int -nmod_sparse_mat_is_zero_row(const nmod_sparse_mat_t mat, slong i) +int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t mat) { - return mat->row_nnz[i]==0; + slong i; + for(i=0; ir; ++i) + if(!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; + return 1; } NMOD_SPARSE_MAT_INLINE @@ -167,16 +203,25 @@ int nmod_sparse_mat_is_square(const nmod_sparse_mat_t mat) /* Must have A->r == B->c and A->c == B->r */ FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A); -/* Addition and subtraction */ -/* Arguments must be distinct */ -FLINT_DLL void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B); -FLINT_DLL void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B); - -FLINT_DLL void nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A); - -/* Matrix-scalar arithmetic */ +/* Arithmetic */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + slong i; + nmod_sparse_mat_set(B, A); + for(i=0; ir; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); +} -FLINT_DLL void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) +{ + if(c==UWORD(0)) nmod_sparse_mat_zero(B); + else { + slong i; + nmod_sparse_mat_set(B, A); + for(i=0; ir; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); + } +} NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t res, const nmod_sparse_mat_t M, const fmpz_t c) @@ -188,9 +233,43 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t res, const nmod_sparse_ma fmpz_clear(d); } +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + nmod_sparse_mat_addmul(C, A, B, UWORD(1)); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + nmod_sparse_mat_addmul(C, A, B, C->mod.n-UWORD(1)); +} + /* Matrix-vector and matrix-matrix multipliciation */ -FLINT_DLL void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x); -FLINT_DLL void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) +{ + slong i; + for(i=0; ir; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); +} +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) +{ + slong i, j; + for(i=0; ir; ++i) { + for(j=0; jrows[i].nnz; ++j) { + nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; + _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); + } + } +} /* Permutations */ /* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t mat, slong * perm, slong r, slong s); @@ -199,24 +278,17 @@ FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t mat, slong * perm, sl FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t mat, slong * perm); FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, slong n); */ + +/* Decomposition */ +void nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); + /* Nonsingular solving */ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); -/* FLINT_DLL int nmod_sparse_mat_solve(nmod_mat_t X, const nmod_sparse_mat_t A, const nmod_mat_t B); -FLINT_DLL int nmod_sparse_mat_solve_vec(mp_ptr x, const nmod_sparse_mat_t A, mp_srcptr b); - */ /* Nullspace */ - -/* FLINT_DLL slong nmod_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); - */ -/* - Suggested initial modulus size for multimodular algorithms. This should - be chosen so that we get the most number of bits per cycle - in matrix multiplication. On x86-64 it appears to be optimal to use - moduli giving nlimbs = 2. This should hold both in the classical - range and in Strassen blocks. - */ -#define NMOD_SPARSE_MAT_OPTIMAL_MODULUS_BITS (FLINT_BITS-5) +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); #ifdef __cplusplus } diff --git a/nmod_sparse_mat/add.c b/nmod_sparse_mat/add.c deleted file mode 100644 index b92d218d38..0000000000 --- a/nmod_sparse_mat/add.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" - -void -nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) -{ - slong i; - - C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); - memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); - C->nnz = 0; - - for (i = 0; i < C->r; i++) - { - C->row_starts[i] = C->nnz; - nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; - nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; - nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; - slong j = 0; - slong k = 0; - slong nnz = 0; - /* Interleave ith rows until one runs out */ - while(j < A->row_nnz[i] && k < B->row_nnz[i]) { - slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); - if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; - if(Be[k].col == col) Ce[nnz].val = nmod_add(Ce[nnz].val, Be[k++].val, C->mod); - if(Ce[nnz].val != UWORD(0)) ++nnz; - } - /* Add remainder of A row */ - for(; jrow_nnz[i]; ++j, ++nnz) Ce[nnz] = Ae[j]; - /* Add remainder of B row */ - for(; krow_nnz[i]; ++k, ++nnz) Ce[nnz]= Be[k]; - - C->row_nnz[i] = nnz; - C->nnz += nnz; - } - _nmod_sparse_mat_set_c(C); - C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); -} diff --git a/nmod_sparse_mat/append_row.c b/nmod_sparse_mat/append_row.c deleted file mode 100644 index 1d0e4ad872..0000000000 --- a/nmod_sparse_mat/append_row.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* Elements must be ordered by row then col */ -void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong * cols, mp_limb_t * vals, slong nnz) -{ - slong i; - mat->entries = flint_realloc(mat->entries, (mat->nnz + nnz)* sizeof(*mat->entries)); - mat->row_starts[row] = mat->nnz; - mat->row_nnz[row] = nnz; - - nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[row]; - for(i = 0; i < nnz; i++) { - e[i].col = cols[i]; - e[i].val = vals[i]; - if(e[i].col >= mat->c) mat->c = e->col + 1; - } - mat->nnz += nnz; -} diff --git a/nmod_sparse_mat/clear.c b/nmod_sparse_mat/clear.c deleted file mode 100644 index 9aec210a46..0000000000 --- a/nmod_sparse_mat/clear.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2010 William Hart - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_clear(nmod_sparse_mat_t mat) -{ - if(mat->entries) - { - flint_free(mat->entries); - } - if(mat->row_starts) { - flint_free(mat->row_starts); - } - if(mat->row_nnz) { - flint_free(mat->row_nnz); - } -} diff --git a/nmod_sparse_mat/concat_horizontal.c b/nmod_sparse_mat/concat_horizontal.c deleted file mode 100644 index b41849a0ef..0000000000 --- a/nmod_sparse_mat/concat_horizontal.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2015 Elena Sergeicheva - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - if(res->r == 0) return; - if(mat1->c == 0) { - nmod_sparse_mat_set(res, mat2); - return; - } - if(mat2->c == 0) { - nmod_sparse_mat_set(res, mat1); - return; - } - slong i, j; - res->c = mat1->c + mat2->c; - res->nnz = mat1->nnz + mat2->nnz; - res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); - - for (i = 0; i < res->r; i++) - { - res->row_starts[i] = mat1->row_starts[i] + mat2->row_starts[i]; - nmod_sparse_mat_entry_struct *e = res->entries + res->row_starts[i]; - nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; - nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; - for(j = 0; j < mat1->row_nnz[i]; ++j, ++e, ++e1) { - e->col = e1->col; - e->val = e1->val; - } - for(j = 0; j < mat2->row_nnz[i]; ++j, ++e, ++e2) { - e->col = e2->col + mat1->c; - e->val = e2->val; - } - res->row_nnz[i] = mat1->row_nnz[i] + mat2->row_nnz[i]; - } -} diff --git a/nmod_sparse_mat/concat_vertical.c b/nmod_sparse_mat/concat_vertical.c deleted file mode 100644 index a964bf0f83..0000000000 --- a/nmod_sparse_mat/concat_vertical.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2015 Elena Sergeicheva - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - slong i; - - res->c = (mat1->c > mat2->c)?(mat1->c):(mat2->c); - res->nnz = mat1->nnz + mat2->nnz; - res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); - memcpy(res->entries, mat1->entries, mat1->nnz * sizeof(*res->entries)); - memcpy(res->entries + mat1->nnz, mat2->entries, mat2->nnz * sizeof(*res->entries)); - memcpy(res->row_starts, mat1->row_starts, mat1->r * sizeof(*res->row_starts)); - memcpy(res->row_starts+mat1->r, mat2->row_starts, mat2->r * sizeof(*res->row_starts)); - memcpy(res->row_nnz, mat1->row_nnz, mat1->r*sizeof(*res->row_nnz)); - memcpy(res->row_nnz+mat1->r, mat2->row_nnz, mat2->r*sizeof(*res->row_nnz)); - - for (i = 0; i < mat2->r; i++) - res->row_starts[mat1->r + i] += mat1->nnz; -} diff --git a/nmod_sparse_mat/equal.c b/nmod_sparse_mat/equal.c deleted file mode 100644 index 98d0ad1922..0000000000 --- a/nmod_sparse_mat/equal.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -int -nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - if (mat1->r != mat2->r) { - printf("Different number of rows\n"); - return 0; - } - - if (mat1->nnz != mat2->nnz) { - printf("Different number of nonzeroes\n"); - return 0; - } - - if (mat1->nnz == 0) - return 1; - - if(memcmp(mat1->row_nnz, mat2->row_nnz, mat1->r * sizeof(*mat1->row_nnz))) { - printf("Different row_nnz\n"); return 0; - } - - slong i, j; - for(i=0; ir; ++i) { - nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; - nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; - for(j=0; jrow_nnz[i]; ++j, ++e1, ++e2) { - if((e1->col - mat1->c_off != e2->col - mat2->c_off) || (e1->val != e2->val)) { - flint_printf("Mismatched row %d, entry %d\n", i, j); - return 0; - } - } - } - return 1; -} diff --git a/nmod_sparse_mat/from_dense.c b/nmod_sparse_mat/from_dense.c deleted file mode 100644 index ef7fdc6dba..0000000000 --- a/nmod_sparse_mat/from_dense.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* Assumes B->c == A->r */ -void -nmod_sparse_mat_from_dense(nmod_sparse_mat_t B, const nmod_mat_t A) -{ - slong i, j; - if(A->r == 0) return; - if(A->c == 0) {nmod_sparse_mat_zero(B); return;} - B->entries = flint_realloc(B->entries, A->r * A->c * sizeof(*B->entries)); - B->nnz = 0; - B->c = 0; - for(i=0; i < A->r; ++i) { - B->row_starts[i] = B->nnz; - B->row_nnz[i] = 0; - for(j=0; j < A->c; ++j) { - if(A->rows[i][j] != UWORD(0)) { - B->entries[B->nnz].col = j; - B->entries[B->nnz].val = A->rows[i][j]; - B->row_nnz[i]++; - B->nnz++; - } - } - } - _nmod_sparse_mat_set_c(B); - if(B->nnz > 0) - B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); - else { - flint_free(B->entries); - B->entries = NULL; - } -} diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index f05cfe298f..921987f023 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. @@ -15,26 +15,12 @@ #include "flint.h" #include "nmod_sparse_mat.h" -/* Elements must be ordered by row then col */ -void nmod_sparse_mat_set_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) +void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) { - if(nnz==0) { - nmod_sparse_mat_zero(mat); - return; + slong r, i, j; + for(r=i=0; rr; ++r, i=j) { + mat->rows[r].nnz = 0; + for(j=i; jrows[r], cols+i, vals+i, j-i); } - slong i; - mat->entries = flint_realloc(mat->entries, nnz * sizeof(*mat->entries)); - memset(mat->row_starts, 0, sizeof(*mat->row_starts)); - memset(mat->row_nnz, 0, sizeof(*mat->row_nnz)); - mat->c = 0; - for(i = 0; i < nnz; i++) { - if(i > 0 && rows[i] != rows[i-1]) { - mat->row_starts[rows[i]] = i; - } - mat->entries[i].col = cols[i]; - mat->entries[i].val = vals[i]; - mat->row_nnz[rows[i]]++; - } - _nmod_sparse_mat_set_c(mat); - mat->nnz = nnz; } diff --git a/nmod_sparse_mat/init.c b/nmod_sparse_mat/init.c deleted file mode 100644 index 4601dcdc25..0000000000 --- a/nmod_sparse_mat/init.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2010 William Hart - Copyright (C) 2010,2011 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - - -void -nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n) -{ - memset(mat, 0, sizeof(*mat)); - mat->r = rows; - mat->c = 0; - if(rows > 0) { - mat->row_starts = flint_calloc(rows, rows*sizeof(*mat->row_starts)); - mat->row_nnz = flint_calloc(rows, rows*sizeof(*mat->row_nnz)); - } - _nmod_sparse_mat_set_mod(mat, n); -} diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c new file mode 100644 index 0000000000..9686aab543 --- /dev/null +++ b/nmod_sparse_mat/lu.c @@ -0,0 +1,133 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) { + const slong c = heap[pos]; + slong nc, npos; + for(; pos > 0; pos = npos) { + npos = (pos-1)/2; + nc = heap[npos]; + if(scores[c] >= scores[nc]) break; + + heap[pos] = nc; + heap_idx[nc] = pos; + } + heap[pos] = c; + heap_idx[c] = pos; +} + +static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong size, slong pos) { + const slong c = heap[pos]; + slong nc, npos; + for(; pos < (size-1)/2; pos = npos) { + npos = 2*pos+1; + if(npos+1 < size && scores[heap[npos]] > scores[heap[npos+1]]) ++npos; + nc = heap[npos]; + if(scores[c] <= scores[nc]) break; + + heap[pos] = nc; + heap_idx[nc] = pos; + } + heap[pos] = c; + heap_idx[c] = pos; +} + +void nmod_sparse_mat_lu(slong *P, slong *Q, + nmod_sparse_mat_t L, nmod_sparse_mat_t U, + const nmod_sparse_mat_t A) { + slong i, j, r, c; + nmod_sparse_mat_t Lt; + nmod_sparse_mat_init(Lt, A->c, A->r, A->mod); + nmod_sparse_mat_set(U, A); + nmod_sparse_mat_transpose(Lt, A); + + // Set up permutations + slong remr = U->r, remc = Lt->r; + for(r=0; rr; ++r) + { + if(!U->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + for(c=0; cr; ++c) + { + if(!Lt->rows[c].nnz) Q[c] = --remc; + else Q[c] = -1; + } + + /* Make heap of nonzero columns by size */ + slong *heap, *heap_idx, *scores, heap_size = A->c; + heap = flint_malloc(A->c*sizeof(*heap)); + scores = flint_malloc(A->c*sizeof(*scores)); + heap_idx = flint_malloc(A->c*sizeof(*heap_idx)); + for(i=0; ic; ++i) { + scores[i] = Lt->rows[i].nnz; // TODO: randomized tiebreaker + heap[i] = i; + heap_up(heap, heap_idx, scores, i); + } + + /* Run elimination */ + slong pc, pr; + slong numr = 0, numc = 0; + nmod_sparse_vec_struct *pcol, *prow, *row, *col; + for(heap_size=A->c; heap_size > 0; --heap_size) { + /* Get lowest weight column (top of heap) */ + pc = heap[0]; + pcol = &Lt->rows[pc]; + heap[0] = heap[heap_size-1]; + heap_down(heap, heap_idx, scores, heap_size, 0); + if(pcol->nnz==0) continue; // Empty columns already dealt with + Q[pc] = numc++; // Move pivot column to front + + /* Get lowest weight incident row */ + pr = pcol->entries[0].ind, prow = &U->rows[pr]; + for(j=1; jnnz; ++j) { + r = pcol->entries[j].ind, row = &U->rows[r]; + if(row->nnz < prow->nnz) pr = r, prow = row; + } + P[pr] = numr++; // Move pivot row to front + + /* Invert pivot */ + mp_limb_t cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); + + /* Gaussian eliminate rows */ + mp_limb_t cc; + for(j=0; jnnz; ++j) { + r = pcol->entries[j].ind, row = &U->rows[r]; + if(P[r] >= 0) continue; // Skip previous pivot rows + cc = nmod_mul(cinv, nmod_sparse_vec_at(row, c), A->mod); + nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); + if(row->nnz==0) P[r] = --remr; + } + + /* Gaussian eliminate cols */ + for(j=0; jnnz; ++j) { + c = prow->entries[j].ind, col = &Lt->rows[c]; + if(Q[c] >= 0) continue; // Skip previous pivot columns + cc = nmod_mul(cinv, nmod_sparse_vec_at(col, c), A->mod); + nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); + if(col->nnz==0) Q[c] = --remc; + } + } + /* Reorder cols in U and L^t */ + nmod_sparse_mat_permute_cols(U, Q); + nmod_sparse_mat_permute_cols(Lt, P); + + /* Transpose L^t */ + nmod_sparse_mat_transpose(L, Lt); + nmod_sparse_mat_clear(Lt); +} diff --git a/nmod_sparse_mat/mul_mat.c b/nmod_sparse_mat/mul_mat.c deleted file mode 100644 index 28164c782b..0000000000 --- a/nmod_sparse_mat/mul_mat.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* TODO: save reductions to end? */ -void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) { - slong i,j,k; - if(Y->r == 0 || Y->c == 0) return; - memset(Y->entries, 0, Y->r * Y->c * sizeof(*Y->entries)); - nmod_sparse_mat_entry_struct *e = A->entries; - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++e) { - if(e->val==1) - _nmod_vec_add(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); - else if(e->val==A->mod.n-1) - _nmod_vec_sub(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); - else - _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->col], X->c, e->val, A->mod); - } - } -} diff --git a/nmod_sparse_mat/mul_vec.c b/nmod_sparse_mat/mul_vec.c deleted file mode 100644 index 4e47c6f939..0000000000 --- a/nmod_sparse_mat/mul_vec.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* TODO: save reductions to end? */ -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) { - slong i,j; - memset(y, 0, A->r * sizeof(*y)); - nmod_sparse_mat_entry_struct *e = A->entries; - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++e) { - if(e->val==1) - y[i] = nmod_add(y[i], x[e->col], A->mod); - else if(e->val==A->mod.n-1) - y[i] = nmod_sub(y[i], x[e->col], A->mod); - else - y[i] = nmod_add(y[i], nmod_mul(x[e->col], e->val, A->mod), A->mod); - } - } -} - diff --git a/nmod_sparse_mat/one.c b/nmod_sparse_mat/one.c deleted file mode 100644 index 3257bd97f8..0000000000 --- a/nmod_sparse_mat/one.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2014 Ashish Kedia - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/*Function to convert a square matrix to an identity matrix - The matrix is assumed to be a square one*/ -void -nmod_sparse_mat_one(nmod_sparse_mat_t mat) -{ - mat->c = mat->nnz = mat->r; - mat->entries = flint_realloc(mat->entries, mat->r*sizeof(*mat->entries)); - slong i; - for(i = 0; i < mat->r; i++) { - mat->entries[i].val = 1; - mat->entries[i].col = i; - mat->row_starts[i] = i; - mat->row_nnz[i] = 1; - } -} diff --git a/nmod_sparse_mat/print_pretty.c b/nmod_sparse_mat/print_pretty.c index fd965e57cf..8cb51e9806 100644 --- a/nmod_sparse_mat/print_pretty.c +++ b/nmod_sparse_mat/print_pretty.c @@ -19,42 +19,17 @@ void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat) { - slong i, j, k=0;; - int width; + slong i;; char row_fmt[FLINT_BITS + 5]; - char col_fmt[FLINT_BITS + 5]; - char val_fmt[FLINT_BITS + 5]; + flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(mat->r, 10)); - flint_printf("<%wd x %wd sparse integer matrix mod %wu (%wd nonzeroes)>\n", - mat->r, mat->c, mat->mod.n, mat->nnz); - - if (!(mat->c) || !(mat->r)) - return; - - width = n_sizeinbase(mat->r, 10); - flint_sprintf(row_fmt, "%%%dwd: [", width); - - width = n_sizeinbase(mat->c, 10); - flint_sprintf(col_fmt, "%%%dwd:", width); - - width = n_sizeinbase(mat->mod.n, 10); - flint_sprintf(val_fmt, "%%%dwd", width); + flint_printf("<%wd x %wd sparse integer matrix mod %w>\n", + mat->r, mat->c, mat->mod.n); for (i = 0; i < mat->r; i++) { flint_printf(row_fmt, i); - - nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[i]; - - for (j = 0; j < mat->row_nnz[i]; j++, e++) - { - flint_printf(col_fmt, e->col - mat->c_off); - flint_printf(val_fmt, e->val); - if (j + 1 < mat->row_nnz[i]) - flint_printf(" "); - } - - flint_printf("]\n"); + nmod_sparse_vec_print_pretty(&mat->rows[i], mat->c_off, mat->c, mat->mod); } } diff --git a/nmod_sparse_mat/randtest.c b/nmod_sparse_mat/randtest.c index 1b99cdf1b0..ed3928f478 100644 --- a/nmod_sparse_mat/randtest.c +++ b/nmod_sparse_mat/randtest.c @@ -14,40 +14,14 @@ #include "flint.h" #include "nmod_sparse_mat.h" -static int smat_ecmp(const void *va, const void *vb) { - const nmod_sparse_mat_entry_struct *a = va; - const nmod_sparse_mat_entry_struct *b = vb; - if(a->col < b->col) return -1; - if(b->col < a->col) return 1; - return 0; -} void -nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state) +nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state, slong min_nnz, slong max_nnz) { - slong i,j, entries_per_row = 0, m; - - if(mat->r >= 30) entries_per_row = 1+ n_randint(state, mat->r/10); - if(entries_per_row < 2) entries_per_row = 2; - mat->nnz = entries_per_row * mat->r; - mat->entries = flint_malloc(mat->nnz*sizeof(*mat->entries)); - for (i = 0; i < mat->r; i++) - { - mat->row_starts[i] = i*entries_per_row; - mat->row_nnz[i] = entries_per_row; - nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[i]; - for(j = 0; j < entries_per_row; ++j) { - e[j].col = j; - do - e[j].val = n_randtest(state) % mat->mod.n; - while(e[j].val==UWORD(0)); - } + slong i, nnz; - /* Use resevoir sampling to get random support */ - for(j = entries_per_row; j < mat->r; ++j) { - m = n_randint(state, j+1); - if(m < entries_per_row) e[m].col = j; - } - qsort(e, entries_per_row, sizeof(*e), smat_ecmp); + for(i=0; ir; ++i) { + nnz = n_randint(state, max_nnz+1); + nnz = FLINT_MAX(nnz, min_nnz); + nmod_sparse_vec_randtest(&mat->rows[i], state, nnz, mat->c, mat->mod); } - _nmod_sparse_mat_set_c(mat); } diff --git a/nmod_sparse_mat/scalar_mul.c b/nmod_sparse_mat/scalar_mul.c deleted file mode 100644 index ff50dd81b8..0000000000 --- a/nmod_sparse_mat/scalar_mul.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "ulong_extras.h" - -void -nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) -{ - if (c == UWORD(0)) - { - nmod_sparse_mat_zero(B); - } - else if(c == UWORD(1)) - { - nmod_sparse_mat_set(B, A); - } - else if(c == B->mod.n - UWORD(1)) - { - nmod_sparse_mat_neg(B, A); - } - else - { - slong i; - nmod_sparse_mat_set(B, A); - if (A->nnz > 10 && A->mod.n < UWORD_HALF) - { - mp_limb_t w_pr = n_mulmod_precomp_shoup(c, A->mod.n); - for (i = 0; innz; i++) - B->entries[i].val = n_mulmod_shoup(c, B->entries[i].val, w_pr, A->mod.n); - } - else - { - for (i = 0; innz; i++) - B->entries[i].val = nmod_mul(c, B->entries[i].val, B->mod); - } - } -} diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c index 76c1315409..084ec19c4d 100644 --- a/nmod_sparse_mat/set.c +++ b/nmod_sparse_mat/set.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. @@ -15,21 +15,13 @@ #include "flint.h" #include "nmod_sparse_mat.h" -/* Assumes B->r == A->r */ -void -nmod_sparse_mat_set(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) { - if (B == A) - return; - B->c = A->c; - B->nnz = A->nnz; - if(B->nnz == 0) { - flint_free(B->entries); - B->entries = NULL; - } else { - B->entries = flint_realloc(B->entries, A->nnz * sizeof(*B->entries)); - memcpy(B->entries, A->entries, A->nnz * sizeof(*B->entries)); - } - memcpy(B->row_starts, A->row_starts, A->r * sizeof(*B->row_starts)); - memcpy(B->row_nnz, A->row_nnz, A->r * sizeof(*B->row_nnz)); + slong i; + if(mat==src || mat->r==0) return; + mat->r = src->r; + mat->c = src->c; + mat->c_off = src->c_off; + mat->rows = realloc(mat->rows, mat->r*sizeof(*mat->rows)); + for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); } diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 209e967f58..e4d6950c3a 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -21,7 +21,7 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ /* Construct transpose */ nmod_sparse_mat_t At; - nmod_sparse_mat_init(At, A->c, A->mod.n); + nmod_sparse_mat_init(At, A->c, A->r, A->mod); nmod_sparse_mat_transpose(At, A); /* Construct auxiliary vectors */ diff --git a/nmod_sparse_mat/window_clear.c b/nmod_sparse_mat/solve_lu.c similarity index 68% rename from nmod_sparse_mat/window_clear.c rename to nmod_sparse_mat/solve_lu.c index 476fadfb22..96c2c403ca 100644 --- a/nmod_sparse_mat/window_clear.c +++ b/nmod_sparse_mat/solve_lu.c @@ -5,7 +5,7 @@ FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or + by th e Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ @@ -14,10 +14,5 @@ #include #include "flint.h" #include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_window_clear(nmod_sparse_mat_t B) -{ - flint_free(B->row_starts); - flint_free(B->row_nnz); +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) { } diff --git a/nmod_sparse_mat/sub.c b/nmod_sparse_mat/sub.c deleted file mode 100644 index 80afd51edd..0000000000 --- a/nmod_sparse_mat/sub.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" - - -void -nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) -{ - slong i; - - C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); - memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); - C->nnz = 0; - - for (i = 0; i < C->r; i++) - { - C->row_starts[i] = C->nnz; - nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; - nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; - nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; - slong j = 0; - slong k = 0; - slong nnz = 0; - /* Interleave ith rows until one runs out */ - while(j < A->row_nnz[i] && k < B->row_nnz[i]) { - slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); - if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; - if(Be[k].col == col) Ce[nnz].val = nmod_sub(Ce[nnz].val, Be[k++].val, C->mod); - if(Ce[nnz].val != UWORD(0)) ++nnz; - } - /* Add remainder of A row */ - for(; jrow_nnz[i]; ++j, ++nnz) - Ce[nnz] = Ae[j]; - /* Subtract remainder of B row */ - for(; krow_nnz[i]; ++k, ++nnz) - Ce[nnz] = Be[k], Ce[nnz].val = nmod_neg(Ce[nnz].val, C->mod); - - C->row_nnz[i] = nnz; - C->nnz += nnz; - } - _nmod_sparse_mat_set_c(C); - C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); -} diff --git a/nmod_sparse_mat/swap.c b/nmod_sparse_mat/swap.c deleted file mode 100644 index 5657b63b05..0000000000 --- a/nmod_sparse_mat/swap.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2014 Ashish Kedia - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) -{ - nmod_sparse_mat_t temp; - *temp = *mat1; - *mat1 = *mat2; - *mat2 = *temp; -} diff --git a/nmod_sparse_mat/test/t-add.c b/nmod_sparse_mat/test/t-add.c index cdc5c9a843..97d4329261 100644 --- a/nmod_sparse_mat/test/t-add.c +++ b/nmod_sparse_mat/test/t-add.c @@ -20,28 +20,29 @@ int main(void) { - slong m, n, mod, rep; + slong rep, r, c; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); - flint_printf("add/sub...."); fflush(stdout); for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, B, C, D; - - m = n_randint(state, 200); - do - mod = n_randtest_not_zero(state); - while(mod <= UWORD(1)); - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_init(B, m, mod); - nmod_sparse_mat_init(C, m, mod); - nmod_sparse_mat_init(D, m, mod); + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); + nmod_sparse_mat_init(C, r, c, mod); + nmod_sparse_mat_init(D, r, c, mod); - nmod_sparse_mat_randtest(A, state); - nmod_sparse_mat_randtest(B, state); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_sparse_mat_randtest(B, state, 0, c); nmod_sparse_mat_add(C, A, B); nmod_sparse_mat_sub(D, C, B); diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index 143ba2e3d5..f77dea80fe 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -18,9 +18,11 @@ int main(void) { + slong rep, r, c1, c2, i; + mp_limb_t n; + nmod_t mod; nmod_sparse_mat_t A, B, C; nmod_sparse_mat_t window1, window2; - slong i; FLINT_TEST_INIT(state); flint_printf("concat_horizontal...."); @@ -29,25 +31,24 @@ int main(void) for (i = 0; i < 100; i++) { - slong r, mod; - r = n_randint(state, 200); - do - mod = n_randlimb(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, r, mod); - nmod_sparse_mat_init(B, r, mod); - nmod_sparse_mat_init(C, r, mod); + c1 = n_randint(state, 200); + c2 = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c1, mod); + nmod_sparse_mat_init(B, r, c2, mod); + nmod_sparse_mat_init(C, r, c1+c2, mod); - nmod_sparse_mat_randtest(A, state); - nmod_sparse_mat_randtest(B, state); - nmod_sparse_mat_randtest(C, state); + nmod_sparse_mat_randtest(A, state, 0, c1); + nmod_sparse_mat_randtest(B, state, 0, c2); + nmod_sparse_mat_randtest(C, state, 0, c1+c2); nmod_sparse_mat_concat_horizontal(C, A, B); - nmod_sparse_mat_window_init(window1, C, 0, 0, r, A->c); - nmod_sparse_mat_window_init(window2, C, 0, A->c, r, A->c + B->c); + nmod_sparse_mat_window_init(window1, C, 0, 0, r, c1); + nmod_sparse_mat_window_init(window2, C, 0, c1, r, c1+c2); if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) { diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index b4d545d419..a62a360217 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -19,9 +19,11 @@ int main(void) { + slong rep, r1, r2, c, i; + mp_limb_t n; + nmod_t mod; nmod_sparse_mat_t A, B, C; nmod_sparse_mat_t window1, window2; - slong i; FLINT_TEST_INIT(state); @@ -30,26 +32,24 @@ int main(void) for (i = 0; i < 100; i++) { - slong r1, r2, c1, mod; + r1 = n_randint(state, 100); + r2 = n_randint(state, 100); + c = n_randint(state, 100); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r1, c, mod); + nmod_sparse_mat_init(B, r2, c, mod); + nmod_sparse_mat_init(C, r1+r2, c, mod); - r1 = n_randint(state, 50); - r2 = n_randint(state, 50); - do - mod = n_randlimb(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, r1, mod); - nmod_sparse_mat_init(B, r2, mod); - nmod_sparse_mat_init(C, (r1+r2), mod); - - nmod_sparse_mat_randtest(A, state); - nmod_sparse_mat_randtest(B, state); - nmod_sparse_mat_randtest(C, state); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_sparse_mat_randtest(B, state, 0, c); + nmod_sparse_mat_randtest(C, state, 0, c); nmod_sparse_mat_concat_vertical(C, A, B); - nmod_sparse_mat_window_init(window1, C, 0, 0, r1, C->c); - nmod_sparse_mat_window_init(window2, C, r1, 0, (r1+r2), C->c); + nmod_sparse_mat_window_init(window1, C, 0, 0, r1, c); + nmod_sparse_mat_window_init(window2, C, r1, 0, r1+r2, c); if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) { diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 695ae6747a..91c27ca8ad 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -20,57 +20,53 @@ int main(void) { - slong m, mod, rep; + slong rep, r, c, i, j, k, nnz; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A, B; + slong *rows; + slong *cols; + mp_limb_t *vals; FLINT_TEST_INIT(state); - flint_printf("conversion to/from dense matrix...."); + flint_printf("construction from entries...."); fflush(stdout); for (rep = 0; rep < 1000; rep++) { - slong i, j, k; - nmod_sparse_mat_t A, B, C; - slong *rows, *cols; - mp_limb_t *vals; - nmod_sparse_mat_entry_struct *Ae; + r = n_randint(state, 10); + c = n_randint(state, 10); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); - m = n_randint(state, 200); + nmod_sparse_mat_randtest(A, state, 2, 2); + nmod_sparse_mat_randtest(B, state, 2, 2); + nnz = 0; + for(i=0; irows[i].nnz; - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_init(B, m, mod); - nmod_sparse_mat_init(C, m, mod); - nmod_sparse_mat_randtest(A, state); - /* Construct B from entries of A */ - rows = flint_malloc(A->nnz * sizeof(*rows)); - cols = flint_malloc(A->nnz * sizeof(*cols)); - vals = flint_malloc(A->nnz * sizeof(*vals)); - for(i=0, k=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++k) { + rows = flint_malloc(nnz * sizeof(*rows)); + cols = flint_malloc(nnz * sizeof(*cols)); + vals = flint_malloc(nnz * sizeof(*vals)); + for(i=k=0; irows[i].nnz; ++j, ++k) { rows[k] = i; - cols[k] = A->entries[k].col; - vals[k] = A->entries[k].val; + cols[k] = A->rows[i].entries[j].ind; + vals[k] = A->rows[i].entries[j].val; } } - nmod_sparse_mat_set_from_entries(B, rows, cols, vals, A->nnz); + nmod_sparse_mat_from_entries(B, rows, cols, vals, nnz); if (!nmod_sparse_mat_equal(A, B)) { flint_printf("FAIL: A != B\n"); - abort(); - } - /* Construct C from rows of A */ - for(i=0; ir; ++i) { - nmod_sparse_mat_append_row(C, i, cols + A->row_starts[i], vals + A->row_starts[i], A->row_nnz[i]); - } - - if (!nmod_sparse_mat_equal(A, C)) - { - flint_printf("FAIL: A != C\n"); + flint_printf("A = "); + nmod_sparse_mat_print_pretty(A); + flint_printf("B = "); + nmod_sparse_mat_print_pretty(B); abort(); } flint_free(rows); @@ -78,7 +74,6 @@ main(void) flint_free(vals); nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); - nmod_sparse_mat_clear(C); } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/test/t-dense.c b/nmod_sparse_mat/test/t-dense.c index 517e0e8f94..fcd6281042 100644 --- a/nmod_sparse_mat/test/t-dense.c +++ b/nmod_sparse_mat/test/t-dense.c @@ -20,7 +20,11 @@ int main(void) { - slong m, mod, rep; + slong rep, r, c, i, j, k, nnz; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A, B; + nmod_mat_t C, D; FLINT_TEST_INIT(state); @@ -29,24 +33,18 @@ main(void) for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, B; - nmod_mat_t C, D; - - m = n_randint(state, 20); - - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_randtest(A, state); - + r = n_randint(state, 10); + c = n_randint(state, 10); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); + nmod_mat_init(C, r, c, n); + nmod_mat_init(D, r, c, n); - nmod_mat_init(C, m, A->c, mod); + nmod_sparse_mat_randtest(A, state, 0, c); nmod_sparse_mat_to_dense(C, A); - - nmod_sparse_mat_init(B, m, mod); - nmod_sparse_mat_randtest(B, state); nmod_sparse_mat_from_dense(B, C); if (!nmod_sparse_mat_equal(A, B)) @@ -57,8 +55,6 @@ main(void) nmod_mat_randtest(C, state); nmod_sparse_mat_from_dense(A, C); - - nmod_mat_init(D, m, C->c, mod); nmod_sparse_mat_to_dense(D, A); if(!nmod_mat_equal(C, D)) { @@ -68,6 +64,7 @@ main(void) nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_mat_clear(C); + nmod_mat_clear(D); } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/test/t-init_clear.c b/nmod_sparse_mat/test/t-init_clear.c index 9f5b941d9a..acfb5dad76 100644 --- a/nmod_sparse_mat/test/t-init_clear.c +++ b/nmod_sparse_mat/test/t-init_clear.c @@ -20,7 +20,10 @@ int main(void) { - slong m, n, mod, i, j, rep; + slong rep, r, c, i; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A; FLINT_TEST_INIT(state); @@ -29,45 +32,24 @@ main(void) for (rep = 0; rep < 100; rep++) { - nmod_sparse_mat_t A; - - m = n_randint(state, 50); - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - if(A->nnz != UWORD(0)) { - flint_printf("FAIL: nnz not zero!\n"); - abort(); - } - if(A->entries != NULL) { - flint_printf("FAIL: entries not null!\n"); + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + + if(!nmod_sparse_mat_is_zero(A)) { + flint_printf("FAIL: A not zero!\n"); abort(); } - if(A->c != UWORD(0)) { - flint_printf("FAIL: c not 0!\n"); - abort(); - } - - for (i = 0; i < m; i++) + for (i = 0; i < r; i++) { - if (A->row_starts[i] != UWORD(0)) + if(!nmod_sparse_vec_is_zero(&A->rows[i])) { - flint_printf("FAIL: row start not zero!\n"); + flint_printf("FAIL: row %wd not zero!\n", i); abort(); } - if (A->row_nnz[i] != UWORD(0)) - { - flint_printf("FAIL: row nnz not zero!\n"); - abort(); - } - } - - if (A->mod.n != mod) - { - flint_printf("FAIL: bad modulus\n"); - abort(); } nmod_sparse_mat_clear(A); diff --git a/nmod_sparse_mat/test/t-mul.c b/nmod_sparse_mat/test/t-mul.c index 56f6d1d1a6..33663a684a 100644 --- a/nmod_sparse_mat/test/t-mul.c +++ b/nmod_sparse_mat/test/t-mul.c @@ -20,7 +20,12 @@ int main(void) { - slong m, n, mod, rep; + slong rep, r, c, i, k; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A; + mp_ptr x, y, y2; + nmod_mat_t B, X, Y, Y2; FLINT_TEST_INIT(state); @@ -29,26 +34,21 @@ main(void) for (rep = 0; rep < 10; rep++) { - nmod_sparse_mat_t A; - mp_ptr x, y, y2; - nmod_mat_t B, X, Y, Y2; - - m = n_randint(state, 20); - n = n_randint(state, 20); - - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_randtest(A, state); - nmod_mat_init(B, m, A->c, mod); + r = n_randint(state, 200); + c = n_randint(state, 200); + k = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_mat_init(B, r, c, n); nmod_sparse_mat_to_dense(B, A); - x = _nmod_vec_init(A->c); - y = _nmod_vec_init(A->r); - y2 = _nmod_vec_init(A->r); - _nmod_vec_randtest(x, state, A->c, A->mod); + x = _nmod_vec_init(c); + y = _nmod_vec_init(r); + y2 = _nmod_vec_init(r); + _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(y, A, x); nmod_mat_mul_vec(y2, B, x); @@ -58,9 +58,9 @@ main(void) abort(); } - nmod_mat_init(X, A->c, n, mod); - nmod_mat_init(Y, A->r, n, mod); - nmod_mat_init(Y2, A->r, n, mod); + nmod_mat_init(X, c, k, n); + nmod_mat_init(Y, r, k, n); + nmod_mat_init(Y2, r, k, n); nmod_mat_randtest(X, state); nmod_sparse_mat_mul_mat(Y, A, X); nmod_mat_mul(Y2, B, X); @@ -72,12 +72,12 @@ main(void) nmod_sparse_mat_clear(A); nmod_mat_clear(B); - nmod_mat_clear(X); - nmod_mat_clear(Y); - nmod_mat_clear(Y2); _nmod_vec_clear(x); _nmod_vec_clear(y); _nmod_vec_clear(y2); + nmod_mat_clear(X); + nmod_mat_clear(Y); + nmod_mat_clear(Y2); } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/test/t-neg.c b/nmod_sparse_mat/test/t-neg.c index 42b1f00293..2f571d2595 100644 --- a/nmod_sparse_mat/test/t-neg.c +++ b/nmod_sparse_mat/test/t-neg.c @@ -20,7 +20,10 @@ int main(void) { - slong m, n, mod, rep; + slong rep, r, c, i; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); @@ -29,20 +32,20 @@ main(void) for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, B, C, D; + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); + nmod_sparse_mat_init(C, r, c, mod); + nmod_sparse_mat_init(D, r, c, mod); - m = n_randint(state, 200); - do - mod = n_randlimb(state); - while(mod <= UWORD(1)); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_init(B, m, mod); - nmod_sparse_mat_init(C, m, mod); - nmod_sparse_mat_init(D, m, mod); - - nmod_sparse_mat_randtest(A, state); - nmod_sparse_mat_randtest(B, state); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_sparse_mat_randtest(B, state, 0, c); + nmod_sparse_mat_randtest(C, state, 0, c); + nmod_sparse_mat_randtest(D, state, 0, c); nmod_sparse_mat_sub(C, A, B); nmod_sparse_mat_neg(B, B); diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c index 010e91a627..9bee70da0d 100644 --- a/nmod_sparse_mat/test/t-scalar_mul.c +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -21,7 +21,10 @@ int main(void) { - slong m, n, mod, rep; + slong rep, r, c, i; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); @@ -30,21 +33,18 @@ main(void) for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, B, C, D; - mp_limb_t c; + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + a = n_randint(state, n); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); + nmod_sparse_mat_init(C, r, c, mod); + nmod_sparse_mat_init(D, r, c, mod); - m = n_randint(state, 200); - do - mod = n_randtest_not_zero(state); - while(mod <= UWORD(1)); - - c = n_randint(state, mod); - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_init(B, m, mod); - nmod_sparse_mat_init(C, m, mod); - nmod_sparse_mat_init(D, m, mod); - - nmod_sparse_mat_randtest(A, state); + nmod_sparse_mat_randtest(A, state, 0, c); nmod_sparse_mat_scalar_mul(B, A, c); nmod_sparse_mat_scalar_mul(C, A, nmod_sub(c, UWORD(1), A->mod)); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index ccea3f2c68..e31c5353e7 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -20,7 +20,11 @@ int main(void) { - slong m, n, mod, rep; + slong rep, r, c, i; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A, At; + mp_ptr x, x2, b, Atb, Ax, AtAx; FLINT_TEST_INIT(state); @@ -30,28 +34,24 @@ main(void) for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, At; - mp_ptr x, x2, b, Atb, Ax, AtAx; + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n <= 32 || !n_is_prime(n)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(At, c, r, mod); - m = n_randint(state, 20); - n = n_randint(state, 20); - - do - mod = n_randtest_not_zero(state); - while(mod <= 32 || !n_is_prime(mod)); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_randtest(A, state); - nmod_sparse_mat_init(At, A->c, mod); + nmod_sparse_mat_randtest(A, state, 0, c); nmod_sparse_mat_transpose(At, A); - x = _nmod_vec_init(A->c); - x2 = _nmod_vec_init(A->c); - b = _nmod_vec_init(A->r); - Ax = _nmod_vec_init(A->r); - AtAx = _nmod_vec_init(A->c); - Atb = _nmod_vec_init(A->c); + x = _nmod_vec_init(c); + x2 = _nmod_vec_init(c); + b = _nmod_vec_init(r); + Ax = _nmod_vec_init(r); + AtAx = _nmod_vec_init(c); + Atb = _nmod_vec_init(c); - _nmod_vec_randtest(x, state, A->c, A->mod); + _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(b, A, x); nmod_sparse_mat_mul_vec(Atb, At, b); int iter, ret; diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index a9409c5e31..fe0bc4ae09 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,7 +20,10 @@ int main(void) { - slong m, n, mod, mod2, rep; + slong rep, r, c, i; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A, B, C; FLINT_TEST_INIT(state); @@ -30,21 +33,20 @@ main(void) /* Rectangular transpose, same modulus */ for (rep = 0; rep < 1000; rep++) { - nmod_sparse_mat_t A, B, C; + r = n_randint(state, 200); + c = n_randint(state, 200); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, c, r, mod); + nmod_sparse_mat_init(C, r, c, mod); - m = n_randint(state, 40); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_sparse_mat_randtest(B, state, 0, r); + nmod_sparse_mat_randtest(C, state, 0, c); - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_randtest(A, state); - - nmod_sparse_mat_init(B, A->c, mod); nmod_sparse_mat_transpose(B, A); - - nmod_sparse_mat_init(C, m, mod); nmod_sparse_mat_transpose(C, B); if (!nmod_sparse_mat_equal(C, A)) diff --git a/nmod_sparse_mat/to_dense.c b/nmod_sparse_mat/to_dense.c deleted file mode 100644 index 8fe597983c..0000000000 --- a/nmod_sparse_mat/to_dense.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) -{ - if(mat->r == 0 || mat->c == 0) return; - slong i, j, k=0; - memset(mat->entries, 0, mat->r * mat->c * sizeof(*mat->entries)); - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++k) { - mat->rows[i][src->entries[k].col] = src->entries[k].val; - } - } -} diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index d79b911a89..7a2c2dd8ab 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -18,33 +18,38 @@ void nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { - - slong i, j; - B->c = A->r; - B->nnz = A->nnz; - B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); - memset(B->row_starts, 0, B->r * sizeof(*B->row_starts)); - memset(B->row_nnz, 0, B->r * sizeof(*B->row_nnz)); - if(A->nnz == 0) return; - - /* Clear row counts for B and set row starts */ - nmod_sparse_mat_entry_struct *Ae, *Be; - Ae = A->entries; - for(i=0; innz; ++i) - if(Ae[i].col + 1 < B->r) - B->row_starts[Ae[i].col + 1] += 1; - for(i=1; ir; ++i) - B->row_starts[i] += B->row_starts[i-1]; - - /* Assign entries */ - Ae = A->entries; - Be = B->entries; - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++Ae) { - slong pos = B->row_starts[Ae->col] + B->row_nnz[Ae->col]++; - Be[pos].col = i; - Be[pos].val = Ae->val; + slong r, c, i, j; + /* Get number of nnzs in each column of A (thus each row of B) */ + for(c=0; cc; ++c) + { + B->rows[c].nnz = 0; + } + for(r=0; rr; ++r) + { + for(i=0; irows[r].nnz; ++i) + { + c = A->rows[r].entries[i].ind; + B->rows[c].nnz += 1; + } + } + /* Allocate space for nnz and reset counters */ + for(c=0; cc; ++c) + { + nmod_sparse_vec_struct *row = &B->rows[c]; + if(row->nnz == 0) nmod_sparse_vec_clear(row); + else row->entries = flint_realloc(row->entries, row->nnz*sizeof(*row->entries)); + row->nnz = 0; + } + /* Put entries into transposed matrix */ + for(r=0; rr; ++r) + { + for(i=0; irows[r].nnz; ++i) + { + nmod_sparse_entry_struct *Ae = &A->rows[r].entries[i]; + c = Ae->ind, j = B->rows[c].nnz++; + nmod_sparse_entry_struct *Be = &B->rows[c].entries[j]; + Be->ind = r, Be->val = Ae->val; } - flint_printf("\n"); } + B->c_off = 0; } diff --git a/nmod_sparse_mat/window_init.c b/nmod_sparse_mat/window_init.c index f18a898054..3d6b6d5f30 100644 --- a/nmod_sparse_mat/window_init.c +++ b/nmod_sparse_mat/window_init.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. @@ -15,38 +15,15 @@ #include "flint.h" #include "nmod_sparse_mat.h" -void -nmod_sparse_mat_window_init(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, slong r1, slong c1, slong r2, slong c2) -{ - slong i, j; - r1 = FLINT_MIN(r1, A->r); - r2 = FLINT_MIN(r2, A->r); - if(r2 < r1) r2 = r1; - if(c2 < c1) c2 = c1; - - B->entries = A->entries; - B->mod = A->mod; - B->r = r2-r1; - B->c_off = c1; - B->c = c2-c1; - B->nnz = 0; - if(B->r == 0) {B->row_starts = B->row_nnz = NULL; return;} - B->row_starts = flint_malloc(B->r * sizeof(*B->row_starts)); - B->row_nnz = flint_malloc(B->r * sizeof(*B->row_nnz)); - memcpy(B->row_starts, A->row_starts + r1, B->r*sizeof(*B->row_starts)); - memcpy(B->row_nnz, A->row_nnz + r1, B->r*sizeof(*B->row_nnz)); - - for(i = r1; ientries + A->row_starts[i]; - for(j=0; jrow_nnz[i]; ++j) { - if(c1 > 0 && Ae[j].col < c1) { - B->row_starts[i-r1] += 1; - B->row_nnz[i-r1] -= 1; - } else if(Ae[j].col >= c2) { - B->row_nnz[i-r1] -= 1; - } else { - B->nnz++; - } - } - } +void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2) { + slong i; + r2 = FLINT_MIN(r2, mat->r), r1 = FLINT_MIN(r1, r2); + c2 = FLINT_MIN(c2, mat->c), c1 = FLINT_MIN(c1, c2); + window->mod = mat->mod; + window->r = r2-r1; + window->c = c2-c1; + window->c_off = c1; + window->rows = flint_malloc(window->r*sizeof(*window->rows)); + for(i=0; ir; ++i) + nmod_sparse_vec_window_init(&window->rows[i], &mat->rows[i+r1], c1, c2); } diff --git a/nmod_sparse_mat/zero.c b/nmod_sparse_mat/zero.c deleted file mode 100644 index f543a910da..0000000000 --- a/nmod_sparse_mat/zero.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_zero(nmod_sparse_mat_t mat) -{ - memset(mat->row_nnz, 0, mat->r*sizeof(*mat->row_nnz)); - memset(mat->row_starts, 0, mat->r*sizeof(*mat->row_starts)); - flint_free(mat->entries); - mat->entries = NULL; - mat->nnz = 0; -} diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h new file mode 100644 index 0000000000..53f6fedd35 --- /dev/null +++ b/nmod_sparse_vec.h @@ -0,0 +1,196 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef NMOD_SPARSE_VEC_H +#define NMOD_SPARSE_VEC_H + +#ifdef NMOD_SPARSE_VEC_INLINES_C +#define NMOD_SPARSE_VEC_INLINE FLINT_DLL +#else +#define NMOD_SPARSE_VEC_INLINE static __inline__ +#endif + +#undef ulong +#define ulong ulongxx /* interferes with system includes */ +#include +#include +#undef ulong +#include +#define ulong mp_limb_t + +#include "flint.h" +#include "longlong.h" +#include "ulong_extras.h" +#include "nmod_vec.h" +#include "fmpz.h" +#include "thread_support.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + slong ind; + mp_limb_t val; +} nmod_sparse_entry_struct; + +typedef nmod_sparse_entry_struct nmod_sparse_entry_t[1]; + +typedef struct { + nmod_sparse_entry_struct *entries; + slong nnz; +} nmod_sparse_vec_struct; + +typedef nmod_sparse_vec_struct nmod_sparse_vec_t[1]; + +/* Memory management */ +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_init(nmod_sparse_vec_t vec) +{ + memset(vec, 0, sizeof(*vec)); +} +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_clear(nmod_sparse_vec_t vec) +{ + flint_free(vec->entries); + memset(vec, 0, sizeof(*vec)); +} +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_swap(nmod_sparse_vec_t vec1, nmod_sparse_vec_t vec2) +{ + nmod_sparse_vec_t tmp; + *tmp = *vec1, *vec1 = *vec2, *vec2 = *tmp; +} + +/* One-time instantiation */ +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_zero(nmod_sparse_vec_t vec) +{ + nmod_sparse_vec_clear(vec); +} + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_one(nmod_sparse_vec_t vec, slong ind) +{ + vec->entries = realloc(vec->entries, sizeof(*vec->entries)); + vec->entries[0].ind = ind; + vec->entries[0].val = UWORD(1); +} + +FLINT_DLL +void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src); + +FLINT_DLL +void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz); + + +/* Vector comparison */ +NMOD_SPARSE_VEC_INLINE +int nmod_sparse_vec_is_zero(const nmod_sparse_vec_t vec) +{ + return vec->nnz == 0; +} + +FLINT_DLL +int nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff); + +/* Vector indexing */ +FLINT_DLL +mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i); + +/* Convert from/to dense vector */ +FLINT_DLL +void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len); + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_to_dense(mp_ptr vec, const nmod_sparse_vec_t src, slong len) { + slong i; + _nmod_vec_zero(vec, len); + for(i=0; innz; ++i) vec[src->entries[i].ind] = src->entries[i].val; +} + +/* Windows and concatenation */ +FLINT_DLL +void nmod_sparse_vec_window_init(nmod_sparse_vec_t window, const nmod_sparse_vec_t vec, slong i1, slong i2); + + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_window_clear(nmod_sparse_vec_t window) +{ + memset(window, 0, sizeof(*window)); +} + +FLINT_DLL +void nmod_sparse_vec_concat(nmod_sparse_vec_t res, const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong len1); + +/* Vector permutation */ +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_permute_inds(nmod_sparse_vec_t vec, slong *P) +{ + slong i; + for(i=0; innz; ++i) vec->entries[i].ind = P[vec->entries[i].ind]; +} + +/* Random vector generation */ +FLINT_DLL +void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, nmod_t mod); + +/* Vector display */ +FLINT_DLL +void nmod_sparse_vec_print_pretty(const nmod_sparse_vec_t vec, slong ioff, slong maxi, nmod_t mod); + +/* Vector operations */ +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t mod) { + slong i; + nmod_sparse_vec_set(v, u); + for(i=0; innz; ++i) v->entries[i].val = nmod_neg(v->entries[i].val, mod); +} + +FLINT_DLL +void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod); + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, const fmpz_t c, nmod_t mod) { + fmpz_t d; + fmpz_init(d); + fmpz_mod_ui(d, c, mod.n); + nmod_sparse_vec_scalar_mul(v, u, fmpz_get_ui(d), mod); + fmpz_clear(d); +} + +FLINT_DLL +void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod); + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { + nmod_sparse_vec_scalar_addmul(w, u, v, UWORD(1), mod); +} + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { + nmod_sparse_vec_scalar_addmul(w, u, v, mod.n-1, mod); +} + +FLINT_DLL +mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod); + +FLINT_DLL +mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/nmod_sparse_mat/neg.c b/nmod_sparse_vec/at.c similarity index 51% rename from nmod_sparse_mat/neg.c rename to nmod_sparse_vec/at.c index 970bf71f17..cb1fcfcb52 100644 --- a/nmod_sparse_mat/neg.c +++ b/nmod_sparse_vec/at.c @@ -5,22 +5,21 @@ FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or + by th e Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include +#include #include #include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" +#include "nmod_sparse_vec.h" -void -nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) -{ - slong i; - - nmod_sparse_mat_set(B, A); - for (i = 0; i < A->nnz; i++) - B->entries[i].val = nmod_neg(B->entries[i].val, B->mod); +mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) { + /* TODO: binary search */ + slong j; + for(j=0; jnnz; ++j) + if(vec->entries[j].ind==i) return vec->entries[j].val; + return 0; } + diff --git a/nmod_sparse_vec/concat.c b/nmod_sparse_vec/concat.c new file mode 100644 index 0000000000..d0aee990d9 --- /dev/null +++ b/nmod_sparse_vec/concat.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_concat(nmod_sparse_vec_t res, const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong len1) +{ + res->nnz = vec1->nnz+vec2->nnz; + if(res->nnz == 0) nmod_sparse_vec_clear(res); + else { + slong i; + res->entries = flint_realloc(res->entries, res->nnz*sizeof(*res->entries)); + memcpy(res->entries, vec1->entries, vec1->nnz*sizeof(*res->entries)); + memcpy(res->entries+vec1->nnz, vec2->entries, vec2->nnz*sizeof(*res->entries)); + for(i=vec1->nnz; innz; ++i) res->entries[i].ind += len1; + } +} diff --git a/nmod_sparse_vec/dot.c b/nmod_sparse_vec/dot.c new file mode 100644 index 0000000000..b56ca4a124 --- /dev/null +++ b/nmod_sparse_vec/dot.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { + slong i, j; + mp_limb_t ret = UWORD(0); + for(i=j=0; innz && jnnz; ) { + if(u->entries[i].ind == v->entries[j].ind) { + ret = nmod_addmul(ret, u->entries[i].val, v->entries[j].val, mod); + ++i; ++j; + } + else if(u->entries[i].ind < v->entries[j].ind) ++i; + else if(u->entries[i].ind > v->entries[j].ind) ++j; + } + return ret; +} diff --git a/nmod_sparse_vec/equal.c b/nmod_sparse_vec/equal.c new file mode 100644 index 0000000000..24562a9b16 --- /dev/null +++ b/nmod_sparse_vec/equal.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +int nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff) +{ + if(vec1->nnz != vec2->nnz) return 0; + slong i; + for(i=0; innz; ++i) { + if((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || + (vec1->entries[i].val != vec2->entries[i].val)) return 0; + } + return 1; +} diff --git a/nmod_sparse_vec/from_dense.c b/nmod_sparse_vec/from_dense.c new file mode 100644 index 0000000000..4208ade6b4 --- /dev/null +++ b/nmod_sparse_vec/from_dense.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len) { + if(len == 0) nmod_sparse_vec_clear(vec); + else { + slong i; + vec->entries = flint_realloc(vec->entries, len*sizeof(*vec->entries)); + vec->nnz = 0; + for(i=0; ientries[vec->nnz++]; + e->ind = i, e->val = src[i]; + } + if(vec->nnz == 0) nmod_sparse_vec_clear(vec); + else vec->entries = flint_realloc(vec->entries, vec->nnz*sizeof(*vec->entries)); + } +} \ No newline at end of file diff --git a/nmod_sparse_vec/from_entries.c b/nmod_sparse_vec/from_entries.c new file mode 100644 index 0000000000..110cc1f411 --- /dev/null +++ b/nmod_sparse_vec/from_entries.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz) +{ + if(nnz == 0) nmod_sparse_vec_clear(vec); + else { + slong i; + vec->nnz = nnz; + vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); + for(i=0; ientries[i].ind = inds[i]; + vec->entries[i].val = vals[i]; + } + } +} diff --git a/nmod_sparse_vec/print_pretty.c b/nmod_sparse_vec/print_pretty.c new file mode 100644 index 0000000000..106fff9da1 --- /dev/null +++ b/nmod_sparse_vec/print_pretty.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +void +nmod_sparse_vec_print_pretty(const nmod_sparse_vec_t vec, slong ioff, slong maxi, nmod_t mod) +{ + slong i; + char ind_fmt[FLINT_BITS + 5]; + char val_fmt[FLINT_BITS + 5]; + + flint_sprintf(ind_fmt, "%%%dwd:", n_sizeinbase(maxi, 10)); + flint_sprintf(val_fmt, "%%%dwd", n_sizeinbase(mod.n, 10)); + + flint_printf("["); + for (i = 0; i < vec->nnz; i++) + { + flint_printf(ind_fmt, vec->entries[i].ind - ioff); + flint_printf(val_fmt, vec->entries[i].val); + if (i + 1 < vec->nnz) flint_printf(" "); + } + flint_printf("]\n"); +} + diff --git a/nmod_sparse_vec/randtest.c b/nmod_sparse_vec/randtest.c new file mode 100644 index 0000000000..9a69e83a0a --- /dev/null +++ b/nmod_sparse_vec/randtest.c @@ -0,0 +1,47 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +static int nmod_sparse_entry_cmp(const void *va, const void *vb) { + const nmod_sparse_entry_struct *a = va; + const nmod_sparse_entry_struct *b = vb; + if(a->ind < b->ind) return -1; + if(b->ind < a->ind) return 1; + return 0; +} + +void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, mp_limb_signed_t nnz, mp_limb_signed_t len, nmod_t mod) { + nnz = FLINT_MIN(nnz, len); + vec->nnz = nnz; + if(nnz == 0) {vec->entries = NULL; return;} + + vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); + slong i, j; + mp_limb_t v; + for(i = 0; i < nnz; ++i) { + do v = n_randtest(state) % mod.n; + while(v==UWORD(0)); + vec->entries[i].ind = i; + vec->entries[i].val = v; + } + + /* Use resevoir sampling to get random support */ + for(j = nnz; j < len; ++j) { + i = n_randint(state, j+1); + if(i < nnz) vec->entries[i].ind = j; + } + qsort(vec->entries, nnz, sizeof(*vec->entries), nmod_sparse_entry_cmp); +} diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c new file mode 100644 index 0000000000..ff8e0c3d16 --- /dev/null +++ b/nmod_sparse_vec/scalar_addmul.c @@ -0,0 +1,52 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) { + if(c==UWORD(0) || (u->nnz==0 && v->nnz==0)) {nmod_sparse_vec_zero(w); return;} + if(v->nnz==0) {nmod_sparse_vec_set(w, u); return;} + if(u->nnz==0) {nmod_sparse_vec_scalar_mul(w, v, c, mod); return;} + + nmod_sparse_vec_t u2; u2->nnz = u->nnz; + if(u==w) { + /* Handle inplace operations */ + u2->entries = flint_malloc(u->nnz*sizeof(*u2->entries)); + memcpy(u2->entries, u->entries, u->nnz*sizeof(*u2->entries)); + } + else u2->entries = u->entries; + + w->entries = flint_realloc(w->entries, (u->nnz+v->nnz)*sizeof(*w->entries)); + memset(w->entries, 0, (u->nnz+v->nnz)*sizeof(*w->entries)); + slong i=0, j=0, k=0; + nmod_sparse_entry_struct *ue = u2->entries; + nmod_sparse_entry_struct *ve = v->entries; + nmod_sparse_entry_struct *we = w->entries; + + /* Interleave u and v */ + while(i < u->nnz && j < v->nnz) { + we[k].ind = FLINT_MIN(ue[i].ind, ve[j].ind); + if(ue[i].ind == we[k].ind) we[k].val = ue[i].val, ++i; + if(ve[j].ind == we[k].ind) we[k].val = nmod_addmul(we[k].val, ve[j].val, c, mod), ++j; + if(we[k].val != UWORD(0)) ++k; + } + while(i < u->nnz) we[k].ind = ue[i].ind, we[k].val = ue[i].val, ++i, ++k; + while(j < v->nnz) we[k].ind = ve[j].ind, we[k].val = nmod_mul(ve[j].val, c, mod), ++j, ++k; + + if(u==w) flint_free(u2->entries); + if(k==0) nmod_sparse_vec_clear(w); + else w->entries = realloc(w->entries, k*sizeof(*w->entries)); + w->nnz = k; +} diff --git a/nmod_sparse_vec/scalar_mul.c b/nmod_sparse_vec/scalar_mul.c new file mode 100644 index 0000000000..c0952ddf46 --- /dev/null +++ b/nmod_sparse_vec/scalar_mul.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) { + if(c==UWORD(0)) nmod_sparse_vec_zero(v); + else if(c==UWORD(1)) nmod_sparse_vec_set(v, u); + else if(c==mod.n-UWORD(1)) nmod_sparse_vec_neg(v, u, mod); + else { + slong i; + nmod_sparse_vec_set(v, u); + for(i=0; innz; ++i) v->entries[i].val = nmod_mul(v->entries[i].val, c, mod); + } +} \ No newline at end of file diff --git a/nmod_sparse_vec/set.c b/nmod_sparse_vec/set.c new file mode 100644 index 0000000000..48e46b0dbb --- /dev/null +++ b/nmod_sparse_vec/set.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src) +{ + if(vec==src) return; + if(src->nnz == 0) nmod_sparse_vec_clear(vec); + else { + vec->entries = flint_realloc(vec->entries, src->nnz*sizeof(*vec->entries)); + memcpy(vec->entries, src->entries, src->nnz*sizeof(*vec->entries)); + vec->nnz = src->nnz; + } +} \ No newline at end of file diff --git a/nmod_sparse_vec/test/t-add.c b/nmod_sparse_vec/test/t-add.c new file mode 100644 index 0000000000..27baa11121 --- /dev/null +++ b/nmod_sparse_vec/test/t-add.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t u, v, w, x; + + FLINT_TEST_INIT(state); + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 40); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + nmod_sparse_vec_init(w); + nmod_sparse_vec_init(x); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + + nmod_sparse_vec_add(w, u, v, mod); + nmod_sparse_vec_sub(x, w, v, mod); + + if (!nmod_sparse_vec_equal(u, x, 0)) + { + flint_printf("FAIL: u != u+v-v\n"); + abort(); + } + + nmod_sparse_vec_add(u, u, v, mod); + if (!nmod_sparse_vec_equal(u, w, 0)) { + flint_printf("FAIL: (u += v) != u + v\n"); + abort(); + } + + nmod_sparse_vec_sub(u, u, v, mod); + if (!nmod_sparse_vec_equal(u, x, 0)) { + flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); + abort(); + } + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + nmod_sparse_vec_clear(w); + nmod_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-concat.c b/nmod_sparse_vec/test/t-concat.c new file mode 100644 index 0000000000..08d44411de --- /dev/null +++ b/nmod_sparse_vec/test/t-concat.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int main(void) +{ + slong rep, len, nnz; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t u, v, w; + nmod_sparse_vec_t window1, window2; + FLINT_TEST_INIT(state); + + flint_printf("concat...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n==UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + nmod_sparse_vec_init(w); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + nmod_sparse_vec_randtest(w, state, nnz, len, mod); + + nmod_sparse_vec_concat(w, u, v, len); + + nmod_sparse_vec_window_init(window1, w, 0, len); + nmod_sparse_vec_window_init(window2, w, len, 2*len); + + if (!(nmod_sparse_vec_equal(window1, u, 0) && nmod_sparse_vec_equal(window2, v, len))) + { + flint_printf("u = "); + nmod_sparse_vec_print_pretty(u, 0, len, mod); + flint_printf("v = \n"); + nmod_sparse_vec_print_pretty(v, 0, len, mod); + flint_printf("A concat_horizontal B = \n"); + nmod_sparse_vec_print_pretty(w, 0, len, mod); + flint_printf("window1 = \n"); + nmod_sparse_vec_print_pretty(window1, 0, len, mod); + flint_printf("window2 = \n"); + nmod_sparse_vec_print_pretty(window2, len, len, mod); + flint_printf("FAIL: results not equal\n"); + abort(); + } + nmod_sparse_vec_window_clear(window1); + nmod_sparse_vec_window_clear(window2); + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + nmod_sparse_vec_clear(w); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-construct.c b/nmod_sparse_vec/test/t-construct.c new file mode 100644 index 0000000000..fc74013748 --- /dev/null +++ b/nmod_sparse_vec/test/t-construct.c @@ -0,0 +1,72 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz, i, j; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t u, v; + slong *inds; + mp_limb_t *vals; + FLINT_TEST_INIT(state); + + flint_printf("construction from elements...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + + /* Construct v from entries of u */ + inds = flint_malloc(nnz * sizeof(*inds)); + vals = flint_malloc(nnz * sizeof(*vals)); + for(i=0; ientries[i].ind; + vals[i] = u->entries[i].val; + } + nmod_sparse_vec_from_entries(v, inds, vals, nnz); + + if (!nmod_sparse_vec_equal(u, v, 0)) + { + flint_printf("FAIL: u != v\n"); + abort(); + } + flint_free(inds); + flint_free(vals); + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-dense.c b/nmod_sparse_vec/test/t-dense.c new file mode 100644 index 0000000000..f93b5cfb32 --- /dev/null +++ b/nmod_sparse_vec/test/t-dense.c @@ -0,0 +1,82 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz, i; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t u, v; + mp_ptr w, x; + FLINT_TEST_INIT(state); + + flint_printf("conversion to/from dense vector...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + w = _nmod_vec_init(len); + x = _nmod_vec_init(len); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + + nmod_sparse_vec_to_dense(w, u, len); + nmod_sparse_vec_from_dense(v, w, len); + + for(i=0; i. +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + int limbs; + slong rep, len, nnz; + mp_limb_t n, a, b; + nmod_t mod; + nmod_sparse_vec_t u, v; + mp_ptr w, x; + FLINT_TEST_INIT(state); + + + flint_printf("dot product....\n"); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + w = _nmod_vec_init(len); + x = _nmod_vec_init(len); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + nmod_sparse_vec_to_dense(w, u, len); + nmod_sparse_vec_to_dense(x, v, len); + + a = nmod_sparse_vec_dot(u, v, mod); + limbs = _nmod_vec_dot_bound_limbs(len, mod); + b = _nmod_vec_dot(w, x, len, mod, limbs); + + if (a != b) + { + flint_printf("Fail: sparse dot sparse\n"); + abort(); + } + + a = nmod_sparse_vec_dot_dense(u, x, mod); + + if (a != b) { + flint_printf("Fail: sparse dot dense\n"); + abort(); + } + + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + _nmod_vec_clear(w); + _nmod_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-init_clear.c b/nmod_sparse_vec/test/t-init_clear.c new file mode 100644 index 0000000000..79d71a4e3d --- /dev/null +++ b/nmod_sparse_vec/test/t-init_clear.c @@ -0,0 +1,84 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +static void check_zero(nmod_sparse_vec_t vec) { + if(vec->nnz != UWORD(0)) { + flint_printf("FAIL: nnz not zero!\n"); + abort(); + } + if(vec->entries != NULL) { + flint_printf("FAIL: entries not null!\n"); + abort(); + } +} + +int +main(void) +{ + slong rep, len, nnz, i; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t vec; + FLINT_TEST_INIT(state); + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n == UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(vec); + check_zero(vec); + + nmod_sparse_vec_randtest(vec, state, nnz, len, mod); + + if(nnz == 0) check_zero(vec); + else + { + for(i = 0; ientries[i]; + if(e->ind >= len) { + flint_printf("FAIL: found index %wd >= %wd!\n", e->ind, len); + abort(); + } + if(e->val==UWORD(0) || e->val >= n) { + flint_printf("FAIL: found value %wd (not in (0,%wd))\n", e->val, n); + abort(); + } + if(i>0 && e->ind <= e[-1].ind) { + flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); + abort(); + } + } + } + + nmod_sparse_vec_clear(vec); + check_zero(vec); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-neg.c b/nmod_sparse_vec/test/t-neg.c new file mode 100644 index 0000000000..9f0c6bf344 --- /dev/null +++ b/nmod_sparse_vec/test/t-neg.c @@ -0,0 +1,77 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + mp_limb_t n; + nmod_t mod; + nmod_sparse_vec_t u, v, w, x; + FLINT_TEST_INIT(state); + + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n==UWORD(1)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + nmod_sparse_vec_init(w); + nmod_sparse_vec_init(x); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + + nmod_sparse_vec_sub(w, u, v, mod); + nmod_sparse_vec_neg(v, v, mod); + nmod_sparse_vec_add(x, u, v, mod); + + if (!nmod_sparse_vec_equal(w, x, 0)) + { + flint_printf("FAIL: u - v != u + (-v)\n"); + abort(); + } + + nmod_sparse_vec_neg(w, u, mod); + nmod_sparse_vec_neg(u, u, mod); + + if (!nmod_sparse_vec_equal(w, w, 0)) + { + flint_printf("FAIL\n"); + abort(); + } + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + nmod_sparse_vec_clear(w); + nmod_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/test/t-scalar_mul.c b/nmod_sparse_vec/test/t-scalar_mul.c new file mode 100644 index 0000000000..cb710af70c --- /dev/null +++ b/nmod_sparse_vec/test/t-scalar_mul.c @@ -0,0 +1,88 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + mp_limb_t n, c; + nmod_t mod; + nmod_sparse_vec_t u, v, w, x; + FLINT_TEST_INIT(state); + + flint_printf("scalar_mul and muladd...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + len = n_randint(state, 50); + nnz = 2; //n_randint(state, len+1); + do n = n_randtest_not_zero(state); + while(n==UWORD(1)); + c = 2; //n_randint(state, n); + nmod_init(&mod, n); + + nmod_sparse_vec_init(u); + nmod_sparse_vec_init(v); + nmod_sparse_vec_init(w); + nmod_sparse_vec_init(x); + + nmod_sparse_vec_randtest(u, state, nnz, len, mod); + nmod_sparse_vec_randtest(v, state, nnz, len, mod); + + nmod_sparse_vec_scalar_addmul(w, u, v, c, mod); + nmod_sparse_vec_scalar_mul(x, v, c, mod); + nmod_sparse_vec_add(x, x, u, mod); + + if (!nmod_sparse_vec_equal(w, x, 0)) + { + flint_printf("FAIL: u + c*v != u + (c*v)\n"); + abort(); + } + + nmod_sparse_vec_scalar_addmul(w, u, v, c, mod); + nmod_sparse_vec_scalar_addmul(u, u, v, c, mod); + + if (!nmod_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + nmod_sparse_vec_scalar_mul(x, v, c, mod); + nmod_sparse_vec_scalar_mul(v, v, c, mod); + + if (!nmod_sparse_vec_equal(v, x, 0)) + { + flint_printf("FAIL: c*v != (c *= v)\n"); + abort(); + } + + nmod_sparse_vec_clear(u); + nmod_sparse_vec_clear(v); + nmod_sparse_vec_clear(w); + nmod_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_vec/window_init.c b/nmod_sparse_vec/window_init.c new file mode 100644 index 0000000000..24b6183c76 --- /dev/null +++ b/nmod_sparse_vec/window_init.c @@ -0,0 +1,25 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_window_init(nmod_sparse_vec_t window, const nmod_sparse_vec_t vec, slong i1, slong i2) +{ + slong start, end; + for(start=0; startnnz && vec->entries[start].ind < i1; ++start); + for(end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + window->entries = vec->entries + start; + window->nnz = end - start; +} diff --git a/nmod_vec.h b/nmod_vec.h index c3d910754f..9637379201 100644 --- a/nmod_vec.h +++ b/nmod_vec.h @@ -123,6 +123,15 @@ mp_limb_t nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) return diff; } +NMOD_VEC_INLINE +mp_limb_t nmod_addmul(mp_limb_t a, mp_limb_t b, mp_limb_t c, nmod_t mod) +{ + if(c==UWORD(1)) return nmod_add(a, b, mod); + if(c==mod.n-UWORD(1)) return nmod_sub(a, b, mod); + NMOD_ADDMUL(a, b, c, mod); + return a; +} + NMOD_VEC_INLINE mp_limb_t nmod_neg(mp_limb_t a, nmod_t mod) { @@ -220,6 +229,18 @@ void _nmod_vec_swap(mp_ptr a, mp_ptr b, slong length) } } +NMOD_VEC_INLINE +void _nmod_vec_print_pretty(mp_ptr a, slong length, nmod_t mod) +{ + slong i; + flint_printf("["); + for(i=0; i Date: Tue, 24 Mar 2020 15:13:22 -0500 Subject: [PATCH 05/42] change #cmakedefine to #cmakedefine01 for HAVE_CPU_SET_T --- config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.h.in b/config.h.in index d6e68ca591..9baa1db0e2 100644 --- a/config.h.in +++ b/config.h.in @@ -8,7 +8,7 @@ #cmakedefine01 FLINT_WANT_ASSERT /* Define if you cpu_set_t in sched.h */ -#cmakedefine01 FLINT_USES_CPUSET +#cmakedefine01 HAVE_CPU_SET_T #cmakedefine01 FLINT_USES_PTHREAD From 05b52a876b7deae50fa8062e5774412054258aff Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 00:00:01 -0700 Subject: [PATCH 06/42] Rebased and merged --- nmod_sparse_mat.h | 4 ++-- nmod_sparse_mat/from_entries.c | 4 ++++ nmod_sparse_mat/set.c | 4 ++++ nmod_sparse_mat/test/t-concat_horizontal.c | 4 ++-- nmod_sparse_mat/test/t-transpose.c | 22 ++++++++++++++++++++++ nmod_sparse_mat/window_init.c | 4 ++++ 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 1de6864a9b..7e2e5fa7d7 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -287,9 +287,9 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); /* Nullspace */ -NMOD_SPARSE_MAT_INLINE +/* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); - + */ #ifdef __cplusplus } #endif diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index 921987f023..7a667b0db8 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -1,5 +1,9 @@ /* +<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters This file is part of FLINT. diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c index 084ec19c4d..ad5d7abb3e 100644 --- a/nmod_sparse_mat/set.c +++ b/nmod_sparse_mat/set.c @@ -1,5 +1,9 @@ /* +<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index f77dea80fe..3800adf698 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -65,12 +65,12 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } - + nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_sparse_mat_clear(C); - nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); } diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index fe0bc4ae09..4823668912 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,10 +20,14 @@ int main(void) { +<<<<<<< HEAD slong rep, r, c, i; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, B, C; +======= + slong m, n, mod, mod2, rep; +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters FLINT_TEST_INIT(state); @@ -33,6 +37,7 @@ main(void) /* Rectangular transpose, same modulus */ for (rep = 0; rep < 1000; rep++) { +<<<<<<< HEAD r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); @@ -47,6 +52,23 @@ main(void) nmod_sparse_mat_randtest(C, state, 0, c); nmod_sparse_mat_transpose(B, A); +======= + nmod_sparse_mat_t A, B, C; + + m = n_randint(state, 40); + + do + mod = n_randtest_not_zero(state); + while(mod <= 1); + + nmod_sparse_mat_init(A, m, mod); + nmod_sparse_mat_randtest(A, state); + + nmod_sparse_mat_init(B, A->c, mod); + nmod_sparse_mat_transpose(B, A); + + nmod_sparse_mat_init(C, m, mod); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_transpose(C, B); if (!nmod_sparse_mat_equal(C, A)) diff --git a/nmod_sparse_mat/window_init.c b/nmod_sparse_mat/window_init.c index 3d6b6d5f30..8ec13ddbd8 100644 --- a/nmod_sparse_mat/window_init.c +++ b/nmod_sparse_mat/window_init.c @@ -1,5 +1,9 @@ /* +<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters This file is part of FLINT. From 8f02984b13197f698215621e24ba6048482a0011 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 21:43:25 -0700 Subject: [PATCH 07/42] Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition --- nmod_sparse_mat.h | 32 ++++++++++++++++++++++++++++++ nmod_sparse_mat/from_entries.c | 4 ++++ nmod_sparse_mat/set.c | 31 ----------------------------- nmod_sparse_mat/solve_lu.c | 18 ----------------- nmod_sparse_mat/test/t-transpose.c | 22 -------------------- nmod_sparse_mat/window_init.c | 5 +---- nmod_sparse_vec/dot_dense.c | 23 --------------------- 7 files changed, 37 insertions(+), 98 deletions(-) delete mode 100644 nmod_sparse_mat/set.c delete mode 100644 nmod_sparse_mat/solve_lu.c delete mode 100644 nmod_sparse_vec/dot_dense.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 7e2e5fa7d7..8891301b21 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -130,6 +130,7 @@ void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) flint_free(window->rows); memset(window, 0, sizeof(*window)); } +<<<<<<< HEAD /* res->r must equal mat1->r and mat2->r */ NMOD_SPARSE_MAT_INLINE @@ -153,6 +154,31 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_ma nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); } +======= + +/* res->r must equal mat1->r and mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, + const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = mat1->c + mat2->c; + for(i=0; ir; ++i) + nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); +} +/* res->r must equal mat1->r + mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = FLINT_MAX(mat1->c, mat2->c); + for(i=0; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); + for(i=mat1->r; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); +} + +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) @@ -287,9 +313,15 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); /* Nullspace */ +<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); */ +======= +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); + +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus } #endif diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index 7a667b0db8..31030c54a9 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -1,9 +1,13 @@ /* +<<<<<<< HEAD <<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson ======= Copyright (C) 2010 Fredrik Johansson >>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters +======= + Copyright (C) 2011 Fredrik Johansson +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition This file is part of FLINT. diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c deleted file mode 100644 index ad5d7abb3e..0000000000 --- a/nmod_sparse_mat/set.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -<<<<<<< HEAD - Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) -{ - slong i; - if(mat==src || mat->r==0) return; - mat->r = src->r; - mat->c = src->c; - mat->c_off = src->c_off; - mat->rows = realloc(mat->rows, mat->r*sizeof(*mat->rows)); - for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); -} diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c deleted file mode 100644 index 96c2c403ca..0000000000 --- a/nmod_sparse_mat/solve_lu.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by th e Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) { -} diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index 4823668912..fe0bc4ae09 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,14 +20,10 @@ int main(void) { -<<<<<<< HEAD slong rep, r, c, i; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, B, C; -======= - slong m, n, mod, mod2, rep; ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters FLINT_TEST_INIT(state); @@ -37,7 +33,6 @@ main(void) /* Rectangular transpose, same modulus */ for (rep = 0; rep < 1000; rep++) { -<<<<<<< HEAD r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); @@ -52,23 +47,6 @@ main(void) nmod_sparse_mat_randtest(C, state, 0, c); nmod_sparse_mat_transpose(B, A); -======= - nmod_sparse_mat_t A, B, C; - - m = n_randint(state, 40); - - do - mod = n_randtest_not_zero(state); - while(mod <= 1); - - nmod_sparse_mat_init(A, m, mod); - nmod_sparse_mat_randtest(A, state); - - nmod_sparse_mat_init(B, A->c, mod); - nmod_sparse_mat_transpose(B, A); - - nmod_sparse_mat_init(C, m, mod); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_transpose(C, B); if (!nmod_sparse_mat_equal(C, A)) diff --git a/nmod_sparse_mat/window_init.c b/nmod_sparse_mat/window_init.c index 8ec13ddbd8..9b97baae06 100644 --- a/nmod_sparse_mat/window_init.c +++ b/nmod_sparse_mat/window_init.c @@ -1,9 +1,6 @@ /* -<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c deleted file mode 100644 index e3a025fb7e..0000000000 --- a/nmod_sparse_vec/dot_dense.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by th e Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_vec.h" - -mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) { - slong i; - mp_limb_t ret = UWORD(0); - for(i=0; innz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); - return ret; -} From 6de1379b8c7da31a0ce0ac28a4e80fadb5b7cf46 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 23:17:40 -0700 Subject: [PATCH 08/42] Spacing and cuddling fixed --- nmod_sparse_mat.h | 77 ++++++++------------ nmod_sparse_mat/from_entries.c | 5 +- nmod_sparse_mat/lu.c | 81 ++++++++++++---------- nmod_sparse_mat/randtest.c | 3 +- nmod_sparse_mat/solve_lanczos.c | 21 +++--- nmod_sparse_mat/test/t-add.c | 2 +- nmod_sparse_mat/test/t-concat_horizontal.c | 2 +- nmod_sparse_mat/test/t-concat_vertical.c | 2 +- nmod_sparse_mat/test/t-construct.c | 10 +-- nmod_sparse_mat/test/t-dense.c | 5 +- nmod_sparse_mat/test/t-init_clear.c | 7 +- nmod_sparse_mat/test/t-mul.c | 5 +- nmod_sparse_mat/test/t-neg.c | 3 +- nmod_sparse_mat/test/t-scalar_mul.c | 3 +- nmod_sparse_mat/test/t-solve.c | 20 +++--- nmod_sparse_mat/test/t-transpose.c | 2 +- nmod_sparse_mat/transpose.c | 14 ++-- nmod_sparse_mat/window_init.c | 5 +- nmod_sparse_vec.h | 21 +++--- nmod_sparse_vec/at.c | 11 ++- nmod_sparse_vec/concat.c | 7 +- nmod_sparse_vec/dot.c | 13 ++-- nmod_sparse_vec/equal.c | 7 +- nmod_sparse_vec/from_dense.c | 12 ++-- nmod_sparse_vec/from_entries.c | 5 +- nmod_sparse_vec/randtest.c | 22 +++--- nmod_sparse_vec/scalar_addmul.c | 33 +++++---- nmod_sparse_vec/scalar_mul.c | 14 ++-- nmod_sparse_vec/set.c | 7 +- nmod_sparse_vec/test/t-add.c | 8 ++- nmod_sparse_vec/test/t-concat.c | 2 +- nmod_sparse_vec/test/t-construct.c | 4 +- nmod_sparse_vec/test/t-dense.c | 11 +-- nmod_sparse_vec/test/t-dot.c | 5 +- nmod_sparse_vec/test/t-init_clear.c | 25 ++++--- nmod_sparse_vec/test/t-neg.c | 2 +- nmod_sparse_vec/test/t-scalar_mul.c | 2 +- nmod_sparse_vec/window_init.c | 4 +- 38 files changed, 264 insertions(+), 218 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 8891301b21..69c6ba17b2 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -75,7 +75,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_clear(nmod_sparse_mat_t mat) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_clear(&mat->rows[i]); + for (i = 0; i < mat->r; ++i) nmod_sparse_vec_clear(&mat->rows[i]); flint_free(mat->rows); memset(mat, 0, sizeof(*mat)); } @@ -91,14 +91,14 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_zero(nmod_sparse_mat_t mat) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_zero(&mat->rows[i]); + for (i = 0; i < mat->r; ++i) nmod_sparse_vec_zero(&mat->rows[i]); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_one(nmod_sparse_mat_t mat) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_one(&mat->rows[i], i); + for (i = 0; i < mat->r; ++i) nmod_sparse_vec_one(&mat->rows[i], i); } FLINT_DLL @@ -112,12 +112,13 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); + for (i = 0; i < src->r; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) { +void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) +{ slong i; - for(i=0; ir; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); + for (i = 0; i < src->r; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); } /* Windows and concatenation */ @@ -130,31 +131,6 @@ void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) flint_free(window->rows); memset(window, 0, sizeof(*window)); } -<<<<<<< HEAD - -/* res->r must equal mat1->r and mat2->r */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, - const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - slong i; - res->c = mat1->c + mat2->c; - for(i=0; ir; ++i) - nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); -} -/* res->r must equal mat1->r + mat2->r */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - slong i; - res->c = FLINT_MAX(mat1->c, mat2->c); - for(i=0; ir; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); - for(i=mat1->r; ir; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); -} - -======= /* res->r must equal mat1->r and mat2->r */ NMOD_SPARSE_MAT_INLINE @@ -163,7 +139,7 @@ void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, { slong i; res->c = mat1->c + mat2->c; - for(i=0; ir; ++i) + for (i = 0; i < res->r; ++i) nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); } /* res->r must equal mat1->r + mat2->r */ @@ -172,19 +148,18 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_ma { slong i; res->c = FLINT_MAX(mat1->c, mat2->c); - for(i=0; ir; ++i) + for (i = 0; i < mat1->r; ++i) nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); - for(i=mat1->r; ir; ++i) + for (i = mat1->r; i < res->r; ++i) nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); } ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); + for (i = 0; i < mat->r; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); } /* Random matrix generation */ @@ -205,9 +180,9 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) { slong i; - if(mat1->r != mat2->r) return 0; - for(i=0; ir; ++i) - if(nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off)==0) return 0; + if (mat1->r != mat2->r) return 0; + for (i = 0; i < mat1->r; ++i) + if (nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off) == 0) return 0; return 1; } @@ -215,8 +190,8 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t mat) { slong i; - for(i=0; ir; ++i) - if(!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; + for (i = 0; i < mat->r; ++i) + if (!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; return 1; } @@ -235,17 +210,17 @@ void nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { slong i; nmod_sparse_mat_set(B, A); - for(i=0; ir; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) { - if(c==UWORD(0)) nmod_sparse_mat_zero(B); + if (c == UWORD(0)) nmod_sparse_mat_zero(B); else { slong i; nmod_sparse_mat_set(B, A); - for(i=0; ir; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); } } @@ -263,7 +238,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); + for (i = 0; i < C->r; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); } NMOD_SPARSE_MAT_INLINE @@ -283,14 +258,16 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) { slong i; - for(i=0; ir; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); + for (i = 0; i < A->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) { slong i, j; - for(i=0; ir; ++i) { - for(j=0; jrows[i].nnz; ++j) { + for (i = 0; i < A->r; ++i) +{ + for (j = 0; j < A->rows[i].nnz; ++j) +{ nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } @@ -314,12 +291,16 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b /* Nullspace */ <<<<<<< HEAD +<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); */ ======= NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); +======= +// slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); +>>>>>>> Spacing and cuddling fixed >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index 31030c54a9..f1e66b5bdd 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -26,9 +26,10 @@ void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) { slong r, i, j; - for(r=i=0; rr; ++r, i=j) { + for (r = i = 0; r < mat->r; ++r, i = j) + { mat->rows[r].nnz = 0; - for(j=i; jrows[r], cols+i, vals+i, j-i); } } diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 9686aab543..1415308fdc 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -16,13 +16,15 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) { +static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) +{ const slong c = heap[pos]; slong nc, npos; - for(; pos > 0; pos = npos) { + for (; pos > 0; pos = npos) + { npos = (pos-1)/2; nc = heap[npos]; - if(scores[c] >= scores[nc]) break; + if (scores[c] >= scores[nc]) break; heap[pos] = nc; heap_idx[nc] = pos; @@ -31,14 +33,16 @@ static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) { heap_idx[c] = pos; } -static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong size, slong pos) { +static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong size, slong pos) +{ const slong c = heap[pos]; slong nc, npos; - for(; pos < (size-1)/2; pos = npos) { + for (; pos < (size-1)/2; pos = npos) + { npos = 2*pos+1; - if(npos+1 < size && scores[heap[npos]] > scores[heap[npos+1]]) ++npos; + if (npos+1 < size && scores[heap[npos]] > scores[heap[npos+1]]) ++npos; nc = heap[npos]; - if(scores[c] <= scores[nc]) break; + if (scores[c] <= scores[nc]) break; heap[pos] = nc; heap_idx[nc] = pos; @@ -49,78 +53,85 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong s void nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, - const nmod_sparse_mat_t A) { - slong i, j, r, c; + const nmod_sparse_mat_t A) +{ + slong i, j, r, c, pr, pc, numr, numc, remr, remc; + slong *heap, *heap_idx, *scores, heap_size; nmod_sparse_mat_t Lt; + nmod_sparse_vec_struct *pcol, *prow, *row, *col; + mp_limb_t cinv, cc; + nmod_sparse_mat_init(Lt, A->c, A->r, A->mod); nmod_sparse_mat_set(U, A); nmod_sparse_mat_transpose(Lt, A); - // Set up permutations - slong remr = U->r, remc = Lt->r; - for(r=0; rr; ++r) + /* Set up permutations */ + remr = U->r, remc = Lt->r; + for (r = 0; rr; ++r) { - if(!U->rows[r].nnz) P[r] = --remr; + if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for(c=0; cr; ++c) + for (c = 0; cr; ++c) { - if(!Lt->rows[c].nnz) Q[c] = --remc; + if (!Lt->rows[c].nnz) Q[c] = --remc; else Q[c] = -1; } /* Make heap of nonzero columns by size */ - slong *heap, *heap_idx, *scores, heap_size = A->c; + heap_size = A->c; heap = flint_malloc(A->c*sizeof(*heap)); scores = flint_malloc(A->c*sizeof(*scores)); heap_idx = flint_malloc(A->c*sizeof(*heap_idx)); - for(i=0; ic; ++i) { - scores[i] = Lt->rows[i].nnz; // TODO: randomized tiebreaker + for (i = 0; i < A->c; ++i) + { + scores[i] = Lt->rows[i].nnz; /* TODO: randomized tiebreaker */ heap[i] = i; heap_up(heap, heap_idx, scores, i); } /* Run elimination */ - slong pc, pr; - slong numr = 0, numc = 0; - nmod_sparse_vec_struct *pcol, *prow, *row, *col; - for(heap_size=A->c; heap_size > 0; --heap_size) { + numr = numc = 0; + for (heap_size=A->c; heap_size > 0; --heap_size) + { /* Get lowest weight column (top of heap) */ pc = heap[0]; pcol = &Lt->rows[pc]; heap[0] = heap[heap_size-1]; heap_down(heap, heap_idx, scores, heap_size, 0); - if(pcol->nnz==0) continue; // Empty columns already dealt with - Q[pc] = numc++; // Move pivot column to front + if (pcol->nnz == 0) continue; /* Empty columns already dealt with */ + Q[pc] = numc++; /* Move pivot column to front */ /* Get lowest weight incident row */ pr = pcol->entries[0].ind, prow = &U->rows[pr]; - for(j=1; jnnz; ++j) { + for (j = 1; j < pcol->nnz; ++j) + { r = pcol->entries[j].ind, row = &U->rows[r]; - if(row->nnz < prow->nnz) pr = r, prow = row; + if (row->nnz < prow->nnz) pr = r, prow = row; } - P[pr] = numr++; // Move pivot row to front + P[pr] = numr++; /* Move pivot row to front */ /* Invert pivot */ - mp_limb_t cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); + cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); /* Gaussian eliminate rows */ - mp_limb_t cc; - for(j=0; jnnz; ++j) { + for (j = 0; j < pcol->nnz; ++j) + { r = pcol->entries[j].ind, row = &U->rows[r]; - if(P[r] >= 0) continue; // Skip previous pivot rows + if (P[r] >= 0) continue; /* Skip previous pivot rows */ cc = nmod_mul(cinv, nmod_sparse_vec_at(row, c), A->mod); nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); - if(row->nnz==0) P[r] = --remr; + if (row->nnz == 0) P[r] = --remr; } /* Gaussian eliminate cols */ - for(j=0; jnnz; ++j) { + for (j = 0; j < prow->nnz; ++j) + { c = prow->entries[j].ind, col = &Lt->rows[c]; - if(Q[c] >= 0) continue; // Skip previous pivot columns + if (Q[c] >= 0) continue; /* Skip previous pivot columns */ cc = nmod_mul(cinv, nmod_sparse_vec_at(col, c), A->mod); nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); - if(col->nnz==0) Q[c] = --remc; + if (col->nnz == 0) Q[c] = --remc; } } /* Reorder cols in U and L^t */ diff --git a/nmod_sparse_mat/randtest.c b/nmod_sparse_mat/randtest.c index ed3928f478..69fe3190c0 100644 --- a/nmod_sparse_mat/randtest.c +++ b/nmod_sparse_mat/randtest.c @@ -19,7 +19,8 @@ nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state, slong min_nn { slong i, nnz; - for(i=0; ir; ++i) { + for (i = 0; i < mat->r; ++i) + { nnz = n_randint(state, max_nnz+1); nnz = FLINT_MAX(nnz, min_nnz); nmod_sparse_vec_randtest(&mat->rows[i], state, nnz, mat->c, mat->mod); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index e4d6950c3a..4b468506ab 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -16,20 +16,22 @@ #include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state) { +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state) +{ + slong j, ret; + const slong nlimbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); + nmod_sparse_mat_t At; + mp_ptr w[2], Aw, AtAw, Atb; + mp_limb_t delta[2]; + _nmod_vec_zero(x, A->c); /* Construct transpose */ - nmod_sparse_mat_t At; nmod_sparse_mat_init(At, A->c, A->r, A->mod); nmod_sparse_mat_transpose(At, A); /* Construct auxiliary vectors */ /* Rather than storing the whole sequence of values w_j, we alternate between two vectors */ - slong j, iter; - const slong nlimbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); - mp_ptr w[2], Aw, AtAw, Atb; - mp_limb_t delta[2]; w[0] = _nmod_vec_init(A->c); w[1] = _nmod_vec_init(A->c); Aw = _nmod_vec_init(A->r); @@ -40,12 +42,13 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ /* Make 0th vector random (and -1st vector trivial) */ _nmod_vec_randtest(w[0], state, A->c, A->mod); _nmod_vec_zero(w[1], A->c); delta[1] = 1; - for(j=0; ; j=1-j) { + for (j = 0; ; j = 1-j) + { /* Compute A^T A w_j and check if it is orthogonal to w_j */ nmod_sparse_mat_mul_vec(Aw, A, w[j]); nmod_sparse_mat_mul_vec(AtAw, At, Aw); delta[j] = _nmod_vec_dot(w[j], AtAw, A->c, A->mod, nlimbs); - if (delta[j]==UWORD(0)) break; // Can't make any more progress + if (delta[j] == UWORD(0)) break; /* Can't make any more progress */ /* Update putative solution by /delta_j * w_j */ const mp_limb_t wAtb = nmod_div(_nmod_vec_dot(w[j], Atb, A->c, A->mod, nlimbs), delta[j], A->mod); @@ -63,7 +66,7 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ /* Check result */ nmod_sparse_mat_mul_vec(Aw, A, x); nmod_sparse_mat_mul_vec(AtAw, At, Aw); - int ret = _nmod_vec_equal(AtAw, Atb, A->c); + ret = _nmod_vec_equal(AtAw, Atb, A->c); /* Clear auxiliary vectors and transpose */ _nmod_vec_clear(w[0]); diff --git a/nmod_sparse_mat/test/t-add.c b/nmod_sparse_mat/test/t-add.c index 97d4329261..b298df7332 100644 --- a/nmod_sparse_mat/test/t-add.c +++ b/nmod_sparse_mat/test/t-add.c @@ -34,7 +34,7 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index 3800adf698..7c429c8484 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -35,7 +35,7 @@ int main(void) c1 = n_randint(state, 200); c2 = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c1, mod); nmod_sparse_mat_init(B, r, c2, mod); diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index a62a360217..97ba8f7286 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -36,7 +36,7 @@ int main(void) r2 = n_randint(state, 100); c = n_randint(state, 100); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r1, c, mod); nmod_sparse_mat_init(B, r2, c, mod); diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 91c27ca8ad..9c62e518a0 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -37,7 +37,7 @@ main(void) r = n_randint(state, 10); c = n_randint(state, 10); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); @@ -45,14 +45,16 @@ main(void) nmod_sparse_mat_randtest(A, state, 2, 2); nmod_sparse_mat_randtest(B, state, 2, 2); nnz = 0; - for(i=0; irows[i].nnz; + for (i = 0; i < r; ++i) nnz += A->rows[i].nnz; /* Construct B from entries of A */ rows = flint_malloc(nnz * sizeof(*rows)); cols = flint_malloc(nnz * sizeof(*cols)); vals = flint_malloc(nnz * sizeof(*vals)); - for(i=k=0; irows[i].nnz; ++j, ++k) { + for (i = k = 0; i < r; ++i) + { + for (j = 0; j < A->rows[i].nnz; ++j, ++k) + { rows[k] = i; cols[k] = A->rows[i].entries[j].ind; vals[k] = A->rows[i].entries[j].val; diff --git a/nmod_sparse_mat/test/t-dense.c b/nmod_sparse_mat/test/t-dense.c index fcd6281042..4a0ab379f8 100644 --- a/nmod_sparse_mat/test/t-dense.c +++ b/nmod_sparse_mat/test/t-dense.c @@ -36,7 +36,7 @@ main(void) r = n_randint(state, 10); c = n_randint(state, 10); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); @@ -57,7 +57,8 @@ main(void) nmod_sparse_mat_from_dense(A, C); nmod_sparse_mat_to_dense(D, A); - if(!nmod_mat_equal(C, D)) { + if (!nmod_mat_equal(C, D)) + { flint_printf("FAIL: C != D\n"); abort(); } diff --git a/nmod_sparse_mat/test/t-init_clear.c b/nmod_sparse_mat/test/t-init_clear.c index acfb5dad76..913e56c30a 100644 --- a/nmod_sparse_mat/test/t-init_clear.c +++ b/nmod_sparse_mat/test/t-init_clear.c @@ -35,17 +35,18 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); - if(!nmod_sparse_mat_is_zero(A)) { + if (!nmod_sparse_mat_is_zero(A)) + { flint_printf("FAIL: A not zero!\n"); abort(); } for (i = 0; i < r; i++) { - if(!nmod_sparse_vec_is_zero(&A->rows[i])) + if (!nmod_sparse_vec_is_zero(&A->rows[i])) { flint_printf("FAIL: row %wd not zero!\n", i); abort(); diff --git a/nmod_sparse_mat/test/t-mul.c b/nmod_sparse_mat/test/t-mul.c index 33663a684a..df34d1f56b 100644 --- a/nmod_sparse_mat/test/t-mul.c +++ b/nmod_sparse_mat/test/t-mul.c @@ -38,7 +38,7 @@ main(void) c = n_randint(state, 200); k = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_randtest(A, state, 0, c); @@ -65,7 +65,8 @@ main(void) nmod_sparse_mat_mul_mat(Y, A, X); nmod_mat_mul(Y2, B, X); - if (!nmod_mat_equal(Y, Y2)) { + if (!nmod_mat_equal(Y, Y2)) + { flint_printf("Fail: Y != Y2\n"); abort(); } diff --git a/nmod_sparse_mat/test/t-neg.c b/nmod_sparse_mat/test/t-neg.c index 2f571d2595..03d8a3a159 100644 --- a/nmod_sparse_mat/test/t-neg.c +++ b/nmod_sparse_mat/test/t-neg.c @@ -26,7 +26,6 @@ main(void) nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); - flint_printf("neg...."); fflush(stdout); @@ -35,7 +34,7 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c index 9bee70da0d..93ae5e7385 100644 --- a/nmod_sparse_mat/test/t-scalar_mul.c +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -27,7 +27,6 @@ main(void) nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); - flint_printf("scalar_mul...."); fflush(stdout); @@ -36,7 +35,7 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); a = n_randint(state, n); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index e31c5353e7..66d40b1acc 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -27,7 +27,6 @@ main(void) mp_ptr x, x2, b, Atb, Ax, AtAx; FLINT_TEST_INIT(state); - flint_printf("solving Ax=b...."); fflush(stdout); int niters = 0, nosol = 0, psolved = 0, nusolved = 0; @@ -37,7 +36,7 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n <= 32 || !n_is_prime(n)); + while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(At, c, r, mod); @@ -55,9 +54,10 @@ main(void) nmod_sparse_mat_mul_vec(b, A, x); nmod_sparse_mat_mul_vec(Atb, At, b); int iter, ret; - for(iter=1; iter<=10; ++iter) - if(ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; - if(iter==11) { + for (iter=1; iter<=10; ++iter) + if (ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; + if (iter==11) + { nosol += 1; continue; } @@ -68,9 +68,13 @@ main(void) { flint_printf("FAIL: AtAx != Atb for mod=%wd, got ret %d\n", mod, ret); abort(); - } else if(!_nmod_vec_equal(b, Ax, A->r)) { + } + else if (!_nmod_vec_equal(b, Ax, A->r)) + { psolved += 1; - } else if(!_nmod_vec_equal(x, x2, A->c)) { + } + else if (!_nmod_vec_equal(x, x2, A->c)) + { nusolved += 1; } flint_free(x); @@ -81,7 +85,7 @@ main(void) flint_free(Atb); nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(At); - } + } flint_printf("No solution found for %wd/%wd examples\n", nosol, 1000); flint_printf("Average number of iters to find solution: %f\n", niters/1000.); flint_printf("Pseudo-solution found for %wd/%wd examples\n", psolved, 1000); diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index fe0bc4ae09..7062b8565c 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -36,7 +36,7 @@ main(void) r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, c, r, mod); diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index 7a2c2dd8ab..8a5bac0466 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -20,30 +20,30 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { slong r, c, i, j; /* Get number of nnzs in each column of A (thus each row of B) */ - for(c=0; cc; ++c) + for (c = 0; c < A->c; ++c) { B->rows[c].nnz = 0; } - for(r=0; rr; ++r) + for (r = 0; r < A->r; ++r) { - for(i=0; irows[r].nnz; ++i) + for (i = 0; i < A->rows[r].nnz; ++i) { c = A->rows[r].entries[i].ind; B->rows[c].nnz += 1; } } /* Allocate space for nnz and reset counters */ - for(c=0; cc; ++c) + for (c = 0; c < A->c; ++c) { nmod_sparse_vec_struct *row = &B->rows[c]; - if(row->nnz == 0) nmod_sparse_vec_clear(row); + if (row->nnz == 0) nmod_sparse_vec_clear(row); else row->entries = flint_realloc(row->entries, row->nnz*sizeof(*row->entries)); row->nnz = 0; } /* Put entries into transposed matrix */ - for(r=0; rr; ++r) + for (r = 0; r < A->r; ++r) { - for(i=0; irows[r].nnz; ++i) + for (i = 0; i < A->rows[r].nnz; ++i) { nmod_sparse_entry_struct *Ae = &A->rows[r].entries[i]; c = Ae->ind, j = B->rows[c].nnz++; diff --git a/nmod_sparse_mat/window_init.c b/nmod_sparse_mat/window_init.c index 9b97baae06..ee87c93f1f 100644 --- a/nmod_sparse_mat/window_init.c +++ b/nmod_sparse_mat/window_init.c @@ -16,7 +16,8 @@ #include "flint.h" #include "nmod_sparse_mat.h" -void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2) { +void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2) +{ slong i; r2 = FLINT_MIN(r2, mat->r), r1 = FLINT_MIN(r1, r2); c2 = FLINT_MIN(c2, mat->c), c1 = FLINT_MIN(c1, c2); @@ -25,6 +26,6 @@ void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat window->c = c2-c1; window->c_off = c1; window->rows = flint_malloc(window->r*sizeof(*window->rows)); - for(i=0; ir; ++i) + for (i = 0; i < window->r; ++i) nmod_sparse_vec_window_init(&window->rows[i], &mat->rows[i+r1], c1, c2); } diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 53f6fedd35..0e8eed0160 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -113,10 +113,11 @@ FLINT_DLL void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len); NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_to_dense(mp_ptr vec, const nmod_sparse_vec_t src, slong len) { +void nmod_sparse_vec_to_dense(mp_ptr vec, const nmod_sparse_vec_t src, slong len) +{ slong i; _nmod_vec_zero(vec, len); - for(i=0; innz; ++i) vec[src->entries[i].ind] = src->entries[i].val; + for (i = 0; i < src->nnz; ++i) vec[src->entries[i].ind] = src->entries[i].val; } /* Windows and concatenation */ @@ -138,7 +139,7 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_permute_inds(nmod_sparse_vec_t vec, slong *P) { slong i; - for(i=0; innz; ++i) vec->entries[i].ind = P[vec->entries[i].ind]; + for (i = 0; i < vec->nnz; ++i) vec->entries[i].ind = P[vec->entries[i].ind]; } /* Random vector generation */ @@ -151,17 +152,19 @@ void nmod_sparse_vec_print_pretty(const nmod_sparse_vec_t vec, slong ioff, slong /* Vector operations */ NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t mod) { +void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t mod) +{ slong i; nmod_sparse_vec_set(v, u); - for(i=0; innz; ++i) v->entries[i].val = nmod_neg(v->entries[i].val, mod); + for (i = 0; i < v->nnz; ++i) v->entries[i].val = nmod_neg(v->entries[i].val, mod); } FLINT_DLL void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod); NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, const fmpz_t c, nmod_t mod) { +void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, const fmpz_t c, nmod_t mod) +{ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, mod.n); @@ -173,12 +176,14 @@ FLINT_DLL void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod); NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { +void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +{ nmod_sparse_vec_scalar_addmul(w, u, v, UWORD(1), mod); } NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { +void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +{ nmod_sparse_vec_scalar_addmul(w, u, v, mod.n-1, mod); } diff --git a/nmod_sparse_vec/at.c b/nmod_sparse_vec/at.c index cb1fcfcb52..67f8979528 100644 --- a/nmod_sparse_vec/at.c +++ b/nmod_sparse_vec/at.c @@ -15,11 +15,16 @@ #include "flint.h" #include "nmod_sparse_vec.h" -mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) { +mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) +{ + slong pc, pr; + slong numr = 0, numc = 0; + nmod_sparse_vec_struct *pcol, *prow, *row, *col; + /* TODO: binary search */ slong j; - for(j=0; jnnz; ++j) - if(vec->entries[j].ind==i) return vec->entries[j].val; + for (j = 0; j < vec->nnz; ++j) + if (vec->entries[j].ind==i) return vec->entries[j].val; return 0; } diff --git a/nmod_sparse_vec/concat.c b/nmod_sparse_vec/concat.c index d0aee990d9..fedaabe317 100644 --- a/nmod_sparse_vec/concat.c +++ b/nmod_sparse_vec/concat.c @@ -18,12 +18,13 @@ void nmod_sparse_vec_concat(nmod_sparse_vec_t res, const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong len1) { res->nnz = vec1->nnz+vec2->nnz; - if(res->nnz == 0) nmod_sparse_vec_clear(res); - else { + if (res->nnz == 0) nmod_sparse_vec_clear(res); + else + { slong i; res->entries = flint_realloc(res->entries, res->nnz*sizeof(*res->entries)); memcpy(res->entries, vec1->entries, vec1->nnz*sizeof(*res->entries)); memcpy(res->entries+vec1->nnz, vec2->entries, vec2->nnz*sizeof(*res->entries)); - for(i=vec1->nnz; innz; ++i) res->entries[i].ind += len1; + for (i = vec1->nnz; i < res->nnz; ++i) res->entries[i].ind += len1; } } diff --git a/nmod_sparse_vec/dot.c b/nmod_sparse_vec/dot.c index b56ca4a124..f640e7827e 100644 --- a/nmod_sparse_vec/dot.c +++ b/nmod_sparse_vec/dot.c @@ -15,16 +15,19 @@ #include "flint.h" #include "nmod_sparse_vec.h" -mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { +mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +{ slong i, j; mp_limb_t ret = UWORD(0); - for(i=j=0; innz && jnnz; ) { - if(u->entries[i].ind == v->entries[j].ind) { + for (i = j = 0; i < u->nnz && j < v->nnz; ) + { + if (u->entries[i].ind == v->entries[j].ind) + { ret = nmod_addmul(ret, u->entries[i].val, v->entries[j].val, mod); ++i; ++j; } - else if(u->entries[i].ind < v->entries[j].ind) ++i; - else if(u->entries[i].ind > v->entries[j].ind) ++j; + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; } return ret; } diff --git a/nmod_sparse_vec/equal.c b/nmod_sparse_vec/equal.c index 24562a9b16..10e7726848 100644 --- a/nmod_sparse_vec/equal.c +++ b/nmod_sparse_vec/equal.c @@ -17,10 +17,11 @@ int nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff) { - if(vec1->nnz != vec2->nnz) return 0; + if (vec1->nnz != vec2->nnz) return 0; slong i; - for(i=0; innz; ++i) { - if((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || + for (i = 0; i < vec1->nnz; ++i) + { + if ((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || (vec1->entries[i].val != vec2->entries[i].val)) return 0; } return 1; diff --git a/nmod_sparse_vec/from_dense.c b/nmod_sparse_vec/from_dense.c index 4208ade6b4..82d51ff13c 100644 --- a/nmod_sparse_vec/from_dense.c +++ b/nmod_sparse_vec/from_dense.c @@ -15,18 +15,20 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len) { - if(len == 0) nmod_sparse_vec_clear(vec); +void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len) +{ + if (len == 0) nmod_sparse_vec_clear(vec); else { slong i; vec->entries = flint_realloc(vec->entries, len*sizeof(*vec->entries)); vec->nnz = 0; - for(i=0; ientries[vec->nnz++]; e->ind = i, e->val = src[i]; } - if(vec->nnz == 0) nmod_sparse_vec_clear(vec); + if (vec->nnz == 0) nmod_sparse_vec_clear(vec); else vec->entries = flint_realloc(vec->entries, vec->nnz*sizeof(*vec->entries)); } } \ No newline at end of file diff --git a/nmod_sparse_vec/from_entries.c b/nmod_sparse_vec/from_entries.c index 110cc1f411..479d3d1d75 100644 --- a/nmod_sparse_vec/from_entries.c +++ b/nmod_sparse_vec/from_entries.c @@ -17,12 +17,13 @@ void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz) { - if(nnz == 0) nmod_sparse_vec_clear(vec); + if (nnz == 0) nmod_sparse_vec_clear(vec); else { slong i; vec->nnz = nnz; vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); - for(i=0; ientries[i].ind = inds[i]; vec->entries[i].val = vals[i]; } diff --git a/nmod_sparse_vec/randtest.c b/nmod_sparse_vec/randtest.c index 9a69e83a0a..340fc82a6c 100644 --- a/nmod_sparse_vec/randtest.c +++ b/nmod_sparse_vec/randtest.c @@ -15,33 +15,37 @@ #include "flint.h" #include "nmod_sparse_vec.h" -static int nmod_sparse_entry_cmp(const void *va, const void *vb) { +static int nmod_sparse_entry_cmp(const void *va, const void *vb) +{ const nmod_sparse_entry_struct *a = va; const nmod_sparse_entry_struct *b = vb; - if(a->ind < b->ind) return -1; - if(b->ind < a->ind) return 1; + if (a->ind < b->ind) return -1; + if (b->ind < a->ind) return 1; return 0; } -void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, mp_limb_signed_t nnz, mp_limb_signed_t len, nmod_t mod) { +void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, mp_limb_signed_t nnz, mp_limb_signed_t len, nmod_t mod) +{ nnz = FLINT_MIN(nnz, len); vec->nnz = nnz; - if(nnz == 0) {vec->entries = NULL; return;} + if (nnz == 0) {vec->entries = NULL; return;} vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); slong i, j; mp_limb_t v; - for(i = 0; i < nnz; ++i) { + for (i = 0; i < nnz; ++i) + { do v = n_randtest(state) % mod.n; - while(v==UWORD(0)); + while (v == UWORD(0)); vec->entries[i].ind = i; vec->entries[i].val = v; } /* Use resevoir sampling to get random support */ - for(j = nnz; j < len; ++j) { + for (j = nnz; j < len; ++j) + { i = n_randint(state, j+1); - if(i < nnz) vec->entries[i].ind = j; + if (i < nnz) vec->entries[i].ind = j; } qsort(vec->entries, nnz, sizeof(*vec->entries), nmod_sparse_entry_cmp); } diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c index ff8e0c3d16..dab0b03a47 100644 --- a/nmod_sparse_vec/scalar_addmul.c +++ b/nmod_sparse_vec/scalar_addmul.c @@ -15,13 +15,15 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) { - if(c==UWORD(0) || (u->nnz==0 && v->nnz==0)) {nmod_sparse_vec_zero(w); return;} - if(v->nnz==0) {nmod_sparse_vec_set(w, u); return;} - if(u->nnz==0) {nmod_sparse_vec_scalar_mul(w, v, c, mod); return;} - +void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) +{ + if (c == UWORD(0) || (u->nnz == 0 && v->nnz == 0)) {nmod_sparse_vec_zero(w); return;} + if (v->nnz == 0) {nmod_sparse_vec_set(w, u); return;} + if (u->nnz == 0) {nmod_sparse_vec_scalar_mul(w, v, c, mod); return;} + nmod_sparse_vec_t u2; u2->nnz = u->nnz; - if(u==w) { + if (u==w) + { /* Handle inplace operations */ u2->entries = flint_malloc(u->nnz*sizeof(*u2->entries)); memcpy(u2->entries, u->entries, u->nnz*sizeof(*u2->entries)); @@ -30,23 +32,24 @@ void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t w->entries = flint_realloc(w->entries, (u->nnz+v->nnz)*sizeof(*w->entries)); memset(w->entries, 0, (u->nnz+v->nnz)*sizeof(*w->entries)); - slong i=0, j=0, k=0; + slong i = 0, j = 0, k = 0; nmod_sparse_entry_struct *ue = u2->entries; nmod_sparse_entry_struct *ve = v->entries; nmod_sparse_entry_struct *we = w->entries; /* Interleave u and v */ - while(i < u->nnz && j < v->nnz) { + while (i < u->nnz && j < v->nnz) + { we[k].ind = FLINT_MIN(ue[i].ind, ve[j].ind); - if(ue[i].ind == we[k].ind) we[k].val = ue[i].val, ++i; - if(ve[j].ind == we[k].ind) we[k].val = nmod_addmul(we[k].val, ve[j].val, c, mod), ++j; - if(we[k].val != UWORD(0)) ++k; + if (ue[i].ind == we[k].ind) we[k].val = ue[i].val, ++i; + if (ve[j].ind == we[k].ind) we[k].val = nmod_addmul(we[k].val, ve[j].val, c, mod), ++j; + if (we[k].val != UWORD(0)) ++k; } - while(i < u->nnz) we[k].ind = ue[i].ind, we[k].val = ue[i].val, ++i, ++k; - while(j < v->nnz) we[k].ind = ve[j].ind, we[k].val = nmod_mul(ve[j].val, c, mod), ++j, ++k; + while (i < u->nnz) we[k].ind = ue[i].ind, we[k].val = ue[i].val, ++i, ++k; + while (j < v->nnz) we[k].ind = ve[j].ind, we[k].val = nmod_mul(ve[j].val, c, mod), ++j, ++k; - if(u==w) flint_free(u2->entries); - if(k==0) nmod_sparse_vec_clear(w); + if (u==w) flint_free(u2->entries); + if (k == 0) nmod_sparse_vec_clear(w); else w->entries = realloc(w->entries, k*sizeof(*w->entries)); w->nnz = k; } diff --git a/nmod_sparse_vec/scalar_mul.c b/nmod_sparse_vec/scalar_mul.c index c0952ddf46..d1dd28e182 100644 --- a/nmod_sparse_vec/scalar_mul.c +++ b/nmod_sparse_vec/scalar_mul.c @@ -15,13 +15,15 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) { - if(c==UWORD(0)) nmod_sparse_vec_zero(v); - else if(c==UWORD(1)) nmod_sparse_vec_set(v, u); - else if(c==mod.n-UWORD(1)) nmod_sparse_vec_neg(v, u, mod); - else { +void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) +{ + if (c == UWORD(0)) nmod_sparse_vec_zero(v); + else if (c == UWORD(1)) nmod_sparse_vec_set(v, u); + else if (c==mod.n-UWORD(1)) nmod_sparse_vec_neg(v, u, mod); + else + { slong i; nmod_sparse_vec_set(v, u); - for(i=0; innz; ++i) v->entries[i].val = nmod_mul(v->entries[i].val, c, mod); + for (i = 0; i < v->nnz; ++i) v->entries[i].val = nmod_mul(v->entries[i].val, c, mod); } } \ No newline at end of file diff --git a/nmod_sparse_vec/set.c b/nmod_sparse_vec/set.c index 48e46b0dbb..a637c64abe 100644 --- a/nmod_sparse_vec/set.c +++ b/nmod_sparse_vec/set.c @@ -17,9 +17,10 @@ void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src) { - if(vec==src) return; - if(src->nnz == 0) nmod_sparse_vec_clear(vec); - else { + if (vec==src) return; + if (src->nnz == 0) nmod_sparse_vec_clear(vec); + else + { vec->entries = flint_realloc(vec->entries, src->nnz*sizeof(*vec->entries)); memcpy(vec->entries, src->entries, src->nnz*sizeof(*vec->entries)); vec->nnz = src->nnz; diff --git a/nmod_sparse_vec/test/t-add.c b/nmod_sparse_vec/test/t-add.c index 27baa11121..5c9116eb22 100644 --- a/nmod_sparse_vec/test/t-add.c +++ b/nmod_sparse_vec/test/t-add.c @@ -35,7 +35,7 @@ main(void) len = n_randint(state, 40); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(u); @@ -56,13 +56,15 @@ main(void) } nmod_sparse_vec_add(u, u, v, mod); - if (!nmod_sparse_vec_equal(u, w, 0)) { + if (!nmod_sparse_vec_equal(u, w, 0)) + { flint_printf("FAIL: (u += v) != u + v\n"); abort(); } nmod_sparse_vec_sub(u, u, v, mod); - if (!nmod_sparse_vec_equal(u, x, 0)) { + if (!nmod_sparse_vec_equal(u, x, 0)) + { flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); abort(); } diff --git a/nmod_sparse_vec/test/t-concat.c b/nmod_sparse_vec/test/t-concat.c index 08d44411de..470b2d3a28 100644 --- a/nmod_sparse_vec/test/t-concat.c +++ b/nmod_sparse_vec/test/t-concat.c @@ -33,7 +33,7 @@ int main(void) len = n_randint(state, 200); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n==UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(u); diff --git a/nmod_sparse_vec/test/t-construct.c b/nmod_sparse_vec/test/t-construct.c index fc74013748..418a4b8b18 100644 --- a/nmod_sparse_vec/test/t-construct.c +++ b/nmod_sparse_vec/test/t-construct.c @@ -36,7 +36,7 @@ main(void) len = n_randint(state, 200); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(u); @@ -47,7 +47,7 @@ main(void) /* Construct v from entries of u */ inds = flint_malloc(nnz * sizeof(*inds)); vals = flint_malloc(nnz * sizeof(*vals)); - for(i=0; ientries[i].ind; vals[i] = u->entries[i].val; diff --git a/nmod_sparse_vec/test/t-dense.c b/nmod_sparse_vec/test/t-dense.c index f93b5cfb32..da97f6617d 100644 --- a/nmod_sparse_vec/test/t-dense.c +++ b/nmod_sparse_vec/test/t-dense.c @@ -35,7 +35,7 @@ main(void) len = n_randint(state, 200); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(u); @@ -49,8 +49,10 @@ main(void) nmod_sparse_vec_to_dense(w, u, len); nmod_sparse_vec_from_dense(v, w, len); - for(i=0; innz != UWORD(0)) { +static void check_zero(nmod_sparse_vec_t vec) +{ + if (vec->nnz != UWORD(0)) +{ flint_printf("FAIL: nnz not zero!\n"); abort(); } - if(vec->entries != NULL) { + if (vec->entries != NULL) +{ flint_printf("FAIL: entries not null!\n"); abort(); } @@ -45,7 +48,7 @@ main(void) len = n_randint(state, 50); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n == UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(vec); @@ -53,20 +56,24 @@ main(void) nmod_sparse_vec_randtest(vec, state, nnz, len, mod); - if(nnz == 0) check_zero(vec); + if (nnz == 0) check_zero(vec); else { - for(i = 0; ientries[i]; - if(e->ind >= len) { + if (e->ind >= len) + { flint_printf("FAIL: found index %wd >= %wd!\n", e->ind, len); abort(); } - if(e->val==UWORD(0) || e->val >= n) { + if (e->val == UWORD(0) || e->val >= n) + { flint_printf("FAIL: found value %wd (not in (0,%wd))\n", e->val, n); abort(); } - if(i>0 && e->ind <= e[-1].ind) { + if (i>0 && e->ind <= e[-1].ind) + { flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); abort(); } diff --git a/nmod_sparse_vec/test/t-neg.c b/nmod_sparse_vec/test/t-neg.c index 9f0c6bf344..70bae31051 100644 --- a/nmod_sparse_vec/test/t-neg.c +++ b/nmod_sparse_vec/test/t-neg.c @@ -35,7 +35,7 @@ main(void) len = n_randint(state, 200); nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n==UWORD(1)); + while (n == UWORD(1)); nmod_init(&mod, n); nmod_sparse_vec_init(u); diff --git a/nmod_sparse_vec/test/t-scalar_mul.c b/nmod_sparse_vec/test/t-scalar_mul.c index cb710af70c..4ba2d3df3e 100644 --- a/nmod_sparse_vec/test/t-scalar_mul.c +++ b/nmod_sparse_vec/test/t-scalar_mul.c @@ -35,7 +35,7 @@ main(void) len = n_randint(state, 50); nnz = 2; //n_randint(state, len+1); do n = n_randtest_not_zero(state); - while(n==UWORD(1)); + while (n == UWORD(1)); c = 2; //n_randint(state, n); nmod_init(&mod, n); diff --git a/nmod_sparse_vec/window_init.c b/nmod_sparse_vec/window_init.c index 24b6183c76..40b50078a3 100644 --- a/nmod_sparse_vec/window_init.c +++ b/nmod_sparse_vec/window_init.c @@ -18,8 +18,8 @@ void nmod_sparse_vec_window_init(nmod_sparse_vec_t window, const nmod_sparse_vec_t vec, slong i1, slong i2) { slong start, end; - for(start=0; startnnz && vec->entries[start].ind < i1; ++start); - for(end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + for (start = 0; startnnz && vec->entries[start].ind < i1; ++start); + for (end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); window->entries = vec->entries + start; window->nnz = end - start; } From 18f39a003bcbe47cfe9202c7bd4cf13b687f744f Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 00:41:31 -0700 Subject: [PATCH 09/42] Lost a function in the last commit, fixed --- nmod_sparse_mat.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 69c6ba17b2..feb5407b57 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -101,8 +101,14 @@ void nmod_sparse_mat_one(nmod_sparse_mat_t mat) for (i = 0; i < mat->r; ++i) nmod_sparse_vec_one(&mat->rows[i], i); } -FLINT_DLL -void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) +{ + slong i; + if(mat==src || mat->r == 0) return; + mat->c_off = src->c_off; + for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); +} FLINT_DLL void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); @@ -290,19 +296,9 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); /* Nullspace */ -<<<<<<< HEAD -<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); */ -======= -NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); -======= -// slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); ->>>>>>> Spacing and cuddling fixed - ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus } #endif From 693533b6d4b87cd7aff000ccec7218b8db84520c Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 01:26:41 -0700 Subject: [PATCH 10/42] Another lost function --- nmod_sparse_vec/dot_dense.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 nmod_sparse_vec/dot_dense.c diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c new file mode 100644 index 0000000000..e3a025fb7e --- /dev/null +++ b/nmod_sparse_vec/dot_dense.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) { + slong i; + mp_limb_t ret = UWORD(0); + for(i=0; innz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); + return ret; +} From 070ec4d939b1cded164274b4fb21fb67828def0c Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 31 Mar 2020 16:59:41 -0700 Subject: [PATCH 11/42] Working LU code (with test) and direct solving --- nmod_sparse_mat.h | 31 ++++++--- nmod_sparse_mat/lu.c | 93 ++++++++++++++++++------- nmod_sparse_mat/solve_lu.c | 63 +++++++++++++++++ nmod_sparse_mat/test/t-lu.c | 124 +++++++++++++++++++++++++++++++++ nmod_sparse_mat/test/t-solve.c | 48 +++++++++---- nmod_sparse_vec.h | 11 +++ nmod_sparse_vec/randtest.c | 9 --- 7 files changed, 322 insertions(+), 57 deletions(-) create mode 100644 nmod_sparse_mat/solve_lu.c create mode 100644 nmod_sparse_mat/test/t-lu.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index feb5407b57..8a6a597d7b 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -104,10 +104,10 @@ void nmod_sparse_mat_one(nmod_sparse_mat_t mat) NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) { - slong i; + slong i, rmax = FLINT_MIN(mat->r, src->r); if(mat==src || mat->r == 0) return; mat->c_off = src->c_off; - for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); + for(i=0; irows[i], &src->rows[i]); } FLINT_DLL @@ -117,14 +117,14 @@ void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * c NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src) { - slong i; - for (i = 0; i < src->r; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); + slong i, rmax = FLINT_MIN(mat->r, src->r); + for (i = 0; i < rmax; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) { - slong i; - for (i = 0; i < src->r; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); + slong i, rmax = FLINT_MIN(mat->r, src->r); + for (i = 0; i < rmax; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); } /* Windows and concatenation */ @@ -165,7 +165,22 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) { slong i; - for (i = 0; i < mat->r; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); + for (i = 0; i < mat->r; ++i) { + if(!mat->rows[i].nnz) continue; + nmod_sparse_vec_permute_inds(&mat->rows[i], Q); + qsort(mat->rows[i].entries, mat->rows[i].nnz, sizeof(*mat->rows[i].entries), nmod_sparse_entry_cmp); + } +} + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t mat, slong *P) +{ + slong i; + nmod_sparse_vec_struct *prows; + prows = flint_calloc(mat->r, sizeof(*prows)); + for (i = 0; i < mat->r; ++i) prows[P[i]] = mat->rows[i]; + memcpy(mat->rows, prows, mat->r*sizeof(*mat->rows)); + flint_free(prows); } /* Random matrix generation */ @@ -289,7 +304,7 @@ FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, */ /* Decomposition */ -void nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); /* Nonsingular solving */ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 1415308fdc..5540c9dd10 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -33,7 +33,7 @@ static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) heap_idx[c] = pos; } -static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong size, slong pos) +static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, slong pos) { const slong c = heap[pos]; slong nc, npos; @@ -51,33 +51,53 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, const slong s heap_idx[c] = pos; } -void nmod_sparse_mat_lu(slong *P, slong *Q, +static void print_heap(slong *heap, slong *scores, slong size) { + slong level, i; + for(level=1; level<=size; level<<=1) { + for(i=level; i<=size && i<2*level; ++i) { + flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); + } + flint_printf("\n"); + } +} + +slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A) { - slong i, j, r, c, pr, pc, numr, numc, remr, remc; +/* flint_printf("Decomposing sparse matrix: "); + nmod_sparse_mat_print_pretty(A); */ + slong i, j, r, c, pr, pc, rank, remr, remc; slong *heap, *heap_idx, *scores, heap_size; nmod_sparse_mat_t Lt; nmod_sparse_vec_struct *pcol, *prow, *row, *col; mp_limb_t cinv, cc; - nmod_sparse_mat_init(Lt, A->c, A->r, A->mod); - nmod_sparse_mat_set(U, A); + if (A->r == 0 || A->c == 0) + { + nmod_sparse_mat_zero(L); + nmod_sparse_mat_zero(U); + memset(P, 0, (A->r)*sizeof(*P)); + memset(Q, 0, (A->c)*sizeof(*Q)); + return 0; + } + nmod_sparse_mat_init(Lt, L->c, L->r, A->mod); nmod_sparse_mat_transpose(Lt, A); - + nmod_sparse_mat_set(U, A); + /* Set up permutations */ - remr = U->r, remc = Lt->r; - for (r = 0; rr; ++r) + remr = A->r, remc = A->c; + for (r = 0; rr; ++r) { if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for (c = 0; cr; ++c) + for (c = 0; cc; ++c) { if (!Lt->rows[c].nnz) Q[c] = --remc; else Q[c] = -1; } - + /* Make heap of nonzero columns by size */ heap_size = A->c; heap = flint_malloc(A->c*sizeof(*heap)); @@ -89,18 +109,21 @@ void nmod_sparse_mat_lu(slong *P, slong *Q, heap[i] = i; heap_up(heap, heap_idx, scores, i); } - /* Run elimination */ - numr = numc = 0; - for (heap_size=A->c; heap_size > 0; --heap_size) + rank = 0; + for (heap_size=A->c; heap_size > 0; ) { +/* print_heap(heap, scores, heap_size); */ /* Get lowest weight column (top of heap) */ pc = heap[0]; pcol = &Lt->rows[pc]; - heap[0] = heap[heap_size-1]; + heap[0] = heap[--heap_size]; heap_down(heap, heap_idx, scores, heap_size, 0); +/* print_heap(heap, scores, heap_size); */ if (pcol->nnz == 0) continue; /* Empty columns already dealt with */ - Q[pc] = numc++; /* Move pivot column to front */ + Q[pc] = rank; /* Move pivot column to front */ +/* flint_printf("Pivot col %wd: ", pc); + nmod_sparse_vec_print_pretty(pcol, 0, A->r, A->mod); */ /* Get lowest weight incident row */ pr = pcol->entries[0].ind, prow = &U->rows[pr]; @@ -109,36 +132,56 @@ void nmod_sparse_mat_lu(slong *P, slong *Q, r = pcol->entries[j].ind, row = &U->rows[r]; if (row->nnz < prow->nnz) pr = r, prow = row; } - P[pr] = numr++; /* Move pivot row to front */ - + P[pr] = rank; /* Move pivot row to front */ +/* flint_printf("Pivot row %wd: ", pr); + nmod_sparse_vec_print_pretty(prow, 0, A->c, A->mod); */ + /* Invert pivot */ - cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); +/* flint_printf("\tPivot: %wd\n", nmod_sparse_vec_at(prow, pc)); */ + cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), A->mod); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) { r = pcol->entries[j].ind, row = &U->rows[r]; if (P[r] >= 0) continue; /* Skip previous pivot rows */ - cc = nmod_mul(cinv, nmod_sparse_vec_at(row, c), A->mod); + cc = nmod_neg(nmod_mul(cinv, nmod_sparse_vec_at(row, pc), A->mod), A->mod); +/* flint_printf("\t\tRow %wd: ", r); + nmod_sparse_vec_print_pretty(row, 0, A->c, A->mod); */ nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); +/* flint_printf("\t\t\t-> "); + nmod_sparse_vec_print_pretty(row, 0, A->c, A->mod); */ if (row->nnz == 0) P[r] = --remr; } - /* Gaussian eliminate cols */ + nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, A->mod); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Lt->rows[c]; if (Q[c] >= 0) continue; /* Skip previous pivot columns */ - cc = nmod_mul(cinv, nmod_sparse_vec_at(col, c), A->mod); + cc = nmod_neg(nmod_sparse_vec_at(col, pr), A->mod); +/* flint_printf("\t\t%Col wd: ", c); + nmod_sparse_vec_print_pretty(col, 0, A->r, A->mod); */ nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); +/* flint_printf("\t\t\t-> "); + nmod_sparse_vec_print_pretty(col, 0, A->r, A->mod); */ if (col->nnz == 0) Q[c] = --remc; + scores[c] = col->nnz; + heap_up(heap, heap_idx, scores, heap_idx[c]); + heap_down(heap, heap_idx, scores, heap_size, heap_idx[c]); +/* print_heap(heap, scores, heap_size); */ + } + rank += 1; } - /* Reorder cols in U and L^t */ - nmod_sparse_mat_permute_cols(U, Q); - nmod_sparse_mat_permute_cols(Lt, P); - /* Transpose L^t */ nmod_sparse_mat_transpose(L, Lt); nmod_sparse_mat_clear(Lt); + + /* Reorder rows and cols in L and U */ + nmod_sparse_mat_permute_cols(L, Q); + nmod_sparse_mat_permute_rows(L, P); + nmod_sparse_mat_permute_cols(U, Q); + nmod_sparse_mat_permute_rows(U, P); + return rank; } diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c new file mode 100644 index 0000000000..2bd83a48c4 --- /dev/null +++ b/nmod_sparse_mat/solve_lu.c @@ -0,0 +1,63 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x=Qx' */ +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +{ + int good = 1; + slong rk, *P, *Q, i, j; + nmod_sparse_mat_t L, U; + mp_ptr bp, y, xp; + P = flint_malloc(A->r * sizeof(*P)); + Q = flint_malloc(A->c * sizeof(*Q)); + nmod_sparse_mat_init(L, A->r, A->c, A->mod); + nmod_sparse_mat_init(U, A->r, A->c, A->mod); + rk = nmod_sparse_mat_lu(P, Q, L, U, A); + L->c = U->r = rk; + + /* Solve Ly = b' = Pb */ + bp = flint_malloc(A->r * sizeof(*bp)); + y = flint_calloc(rk, sizeof(*y)); + for (i = 0; i < A->r; ++i) bp[P[i]] = b[i]; + + flint_free(P); + for (i = 0; i < rk; ++i) + y[i] = nmod_sub(bp[i], nmod_sparse_vec_dot_dense(&L->rows[i], y, A->mod), A->mod); + for (i = rk; i < A->r; ++i) + if (bp[i] != nmod_sparse_vec_dot_dense(&L->rows[i], y, A->mod)) {good = 0; break;} + nmod_sparse_mat_mul_vec(bp, L, y); + + flint_free(bp); + nmod_sparse_mat_clear(L); + + if (good) + { + /* Find a solution for Ux' = y */ + xp = flint_calloc(A->c, sizeof(*xp)); + for (i = rk-1; i >= 0; --i) + xp[i] = nmod_div(nmod_sub(y[i], nmod_sparse_vec_dot_dense(&U->rows[i], xp, A->mod), A->mod), U->rows[i].entries[0].val, A->mod); + nmod_sparse_mat_mul_vec(y, U, xp); + + for(i = 0; i < A->c; ++i) x[i] = xp[Q[i]]; + flint_free(xp); + } + flint_free(y); + U->r = A->r; + nmod_sparse_mat_clear(U); + return good; +} diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c new file mode 100644 index 0000000000..52cd5a215e --- /dev/null +++ b/nmod_sparse_mat/test/t-lu.c @@ -0,0 +1,124 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, r, c, i, j, m, rk; + mp_limb_t n, *P, *Q; + nmod_t mod; + nmod_sparse_mat_t A, LU, L, U; + nmod_mat_t dL, dU, dLU; + FLINT_TEST_INIT(state); + + flint_printf("decomposing PAQ=LU...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + if (rep % 50 == 0) {flint_printf("."); fflush(stdout);} + r = n_randint(state, 200); + c = n_randint(state, 200); + + do n = n_randtest_not_zero(state); + while (!n_is_prime(n)); + nmod_init(&mod, n); + P = flint_malloc(r*sizeof(*P)); + Q = flint_malloc(c*sizeof(*P)); + m = FLINT_MIN(r, c); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(LU, r, c, mod); + nmod_sparse_mat_init(L, r, c, mod); + nmod_sparse_mat_init(U, r, c, mod); + nmod_sparse_mat_randtest(A, state, 1, c); + rk = nmod_sparse_mat_lu(P, Q, L, U, A); + nmod_mat_init(dL, r, rk, n); + nmod_mat_init(dU, rk, c, n); + nmod_mat_init(dLU, r, c, n); + + /* Check that L is lower triangular (with ones on diagonal up to rank) */ + for(i=0; irows[i], i) != UWORD(1)) + { + flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); + } + for(j=0; jrows[i].nnz; ++j) { + nmod_sparse_entry_struct *e = &L->rows[i].entries[j]; + if(e->ind > i) { + flint_printf("FAIL: L not lower triangular\n"); + abort(); + } + if(e->ind >= rk) { + flint_printf("FAIL: L not trivial past the rank\n"); + nmod_sparse_mat_print_pretty(L); + abort(); + } + } + } + /* Check that U is upper triangular (with nonzero diagonal up to rank) */ + for(i=0; irows[i], i) == UWORD(0)) + { + flint_printf("FAIL: U does not have nonzero diagonal\n"); + abort(); + } + if(i >= rk && U->rows[i].nnz != UWORD(0)) + { + flint_printf("FAIL: U not trivial pas the rank\n"); + abort(); + } + for(j=0; jrows[i].nnz; ++j) { + nmod_sparse_entry_struct *e = &U->rows[i].entries[j]; + if(e->ind < i) { + flint_printf("FAIL: U not upper triangular\n"); + abort(); + } + } + } + nmod_sparse_mat_to_dense(dL, L); + nmod_sparse_mat_to_dense(dU, U); + nmod_mat_mul(dLU, dL, dU); + nmod_sparse_mat_from_dense(LU, dLU); + nmod_sparse_mat_permute_rows(A, P); + nmod_sparse_mat_permute_cols(A, Q); + if(!nmod_sparse_mat_equal(A, LU)) { + flint_printf("FAIL: PAQ != LU\n"); + flint_printf("PAQ="); + nmod_sparse_mat_print_pretty(A); + flint_printf("LU="); + nmod_sparse_mat_print_pretty(LU); + abort(); + } + + flint_free(P); + flint_free(Q); + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(U); + nmod_sparse_mat_clear(L); + nmod_sparse_mat_clear(LU); + nmod_mat_clear(dL); + nmod_mat_clear(dU); + nmod_mat_clear(dLU); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 66d40b1acc..b366b93b97 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "flint.h" #include "nmod_sparse_mat.h" #include "ulong_extras.h" @@ -20,19 +21,23 @@ int main(void) { + int iter, ret; + int niters = 0, nosol = 0, psolved = 0; slong rep, r, c, i; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, At; mp_ptr x, x2, b, Atb, Ax, AtAx; + double l_elapsed = 0, d_elapsed = 0; + struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("solving Ax=b...."); fflush(stdout); - int niters = 0, nosol = 0, psolved = 0, nusolved = 0; - - for (rep = 0; rep < 1000; rep++) + + for (rep = 0; rep < 100; rep++) { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} r = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); @@ -52,10 +57,26 @@ main(void) _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(b, A, x); - nmod_sparse_mat_mul_vec(Atb, At, b); - int iter, ret; - for (iter=1; iter<=10; ++iter) + + /* Solve directly */ + gettimeofday(&start, NULL); + ret = nmod_sparse_mat_solve_lu(x2, A, b); + gettimeofday(&end, NULL); + d_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + nmod_sparse_mat_mul_vec(Ax, A, x2); + if(!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve iteratively */ + gettimeofday(&start, NULL); + for (iter=1; iter<=10; ++iter) /* TODO: set number of trials based on params */ if (ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; + gettimeofday(&end, NULL); + l_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (iter==11) { nosol += 1; @@ -64,19 +85,17 @@ main(void) niters += iter; nmod_sparse_mat_mul_vec(Ax, A, x2); nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); if (!_nmod_vec_equal(AtAx, Atb, A->c)) { - flint_printf("FAIL: AtAx != Atb for mod=%wd, got ret %d\n", mod, ret); + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); abort(); } else if (!_nmod_vec_equal(b, Ax, A->r)) { psolved += 1; } - else if (!_nmod_vec_equal(x, x2, A->c)) - { - nusolved += 1; - } + flint_free(x); flint_free(x2); flint_free(b); @@ -86,12 +105,11 @@ main(void) nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(At); } - flint_printf("No solution found for %wd/%wd examples\n", nosol, 1000); - flint_printf("Average number of iters to find solution: %f\n", niters/1000.); - flint_printf("Pseudo-solution found for %wd/%wd examples\n", psolved, 1000); - flint_printf("Alternate solution found for %wd/%wd examples\n", nusolved, 1000); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); + flint_printf("Average time for Lanzcos: %lf\n", l_elapsed/1000); + flint_printf("Average time for direct: %lf\n", d_elapsed/1000); + flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f iters per solution.\n", nosol, 1000, psolved, 1000, niters/1000.); return 0; } diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 0e8eed0160..200a9065f9 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -53,6 +53,17 @@ typedef struct { typedef nmod_sparse_vec_struct nmod_sparse_vec_t[1]; +NMOD_SPARSE_VEC_INLINE +int nmod_sparse_entry_cmp(const void *va, const void *vb) +{ + const nmod_sparse_entry_struct *a = va; + const nmod_sparse_entry_struct *b = vb; + if (a->ind < b->ind) return -1; + if (b->ind < a->ind) return 1; + return 0; +} + + /* Memory management */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_init(nmod_sparse_vec_t vec) diff --git a/nmod_sparse_vec/randtest.c b/nmod_sparse_vec/randtest.c index 340fc82a6c..8c1ce08282 100644 --- a/nmod_sparse_vec/randtest.c +++ b/nmod_sparse_vec/randtest.c @@ -15,15 +15,6 @@ #include "flint.h" #include "nmod_sparse_vec.h" -static int nmod_sparse_entry_cmp(const void *va, const void *vb) -{ - const nmod_sparse_entry_struct *a = va; - const nmod_sparse_entry_struct *b = vb; - if (a->ind < b->ind) return -1; - if (b->ind < a->ind) return 1; - return 0; -} - void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, mp_limb_signed_t nnz, mp_limb_signed_t len, nmod_t mod) { nnz = FLINT_MIN(nnz, len); From 81118155ec4d49078f082e6933e27d10d5726c37 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 31 Mar 2020 23:31:23 -0700 Subject: [PATCH 12/42] Added code to construct reduced row echelon form and associated solver, another construction option, and (untested) inversion code --- nmod_sparse_mat.h | 30 +++++++++++ nmod_sparse_mat/inv.c | 41 ++++++++++++++ nmod_sparse_mat/rref.c | 87 ++++++++++++++++++++++++++++++ nmod_sparse_mat/solve_rref.c | 46 ++++++++++++++++ nmod_sparse_mat/test/t-construct.c | 14 ++++- nmod_sparse_mat/test/t-rref.c | 63 ++++++++++++++++++++++ nmod_sparse_mat/test/t-solve.c | 31 +++++++---- nmod_sparse_mat/transpose.c | 5 +- nmod_sparse_vec.h | 10 ++++ 9 files changed, 316 insertions(+), 11 deletions(-) create mode 100644 nmod_sparse_mat/inv.c create mode 100644 nmod_sparse_mat/rref.c create mode 100644 nmod_sparse_mat/solve_rref.c create mode 100644 nmod_sparse_mat/test/t-rref.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 8a6a597d7b..93ebf9dbf1 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -113,6 +113,23 @@ void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) FLINT_DLL void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_append_col(nmod_sparse_mat_t mat, const mp_ptr vec) +{ + slong i; + for(i=0; ir; ++i) _nmod_sparse_vec_append_entry(&mat->rows[i], mat->c, vec[i]); + mat->c += 1; +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, const nmod_sparse_vec_t vec) +{ + mat->rows = realloc(mat->rows, (mat->r+1)*sizeof(*mat->rows)); + memset(mat->rows + mat->r, 0, sizeof(*mat->rows)); + nmod_sparse_vec_set(&mat->rows[mat->r], vec); + mat->r += 1; +} + /* Convert from/to dense matrix */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src) @@ -304,12 +321,25 @@ FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, */ /* Decomposition */ +FLINT_DLL slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); +FLINT_DLL +slong nmod_sparse_mat_rref(nmod_sparse_mat_t A); + /* Nonsingular solving */ +FLINT_DLL int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); + +FLINT_DLL int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +FLINT_DLL +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); + +FLINT_DLL +void nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); + /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); diff --git a/nmod_sparse_mat/inv.c b/nmod_sparse_mat/inv.c new file mode 100644 index 0000000000..dfbe611d5c --- /dev/null +++ b/nmod_sparse_mat/inv.c @@ -0,0 +1,41 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" +void nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A) +{ + nmod_sparse_mat_t I, AI, window; + nmod_sparse_vec_struct *row; + nmod_sparse_entry_struct *le, *re; + + /* Create block matrix [A | I] */ + nmod_sparse_mat_init(I, A->r, A->r, A->mod); + nmod_sparse_mat_one(I); + nmod_sparse_mat_init(AI, A->r, A->c, A->mod); + nmod_sparse_mat_concat_horizontal(AI, A, I); + nmod_sparse_mat_clear(I); + + /* Run Gaussian elimination on first half */ + AI->c = A->c; + nmod_sparse_mat_rref(AI); + AI->c = A->c+A->r; + nmod_sparse_mat_window_init(window, AI, 0, A->c, A->r, A->c+A->r); + nmod_sparse_mat_set(Ai, window); + + /* TODO: ?? not invertible */ + nmod_sparse_mat_window_clear(window); + nmod_sparse_mat_clear(AI); +} diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c new file mode 100644 index 0000000000..8ab4af6cb7 --- /dev/null +++ b/nmod_sparse_mat/rref.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_rref(nmod_sparse_mat_t A) +{ + if (A->r == 0 || A->c == 0) return 0; + slong *P; + slong i, j, r, c, pr, pc, rank, remr; + nmod_sparse_mat_t At; + nmod_sparse_vec_struct *pcol, *prow, *row, *col; + mp_limb_t cinv, cc; + + nmod_sparse_mat_init(At, A->c, A->r, A->mod); + nmod_sparse_mat_transpose(At, A); + + /* Set up permutations */ + P = flint_malloc(A->r*sizeof(*P)); + remr = A->r; + for (r = 0; rr; ++r) + { + if (!A->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + + /* Run elimination */ + rank = 0; + for (pc=0; pcc; ++pc) + { + pcol = &At->rows[pc]; + + /* Get lowest weight incident row not used as previous pivot */ + pr = -1, prow = NULL; + for (j = 0; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &A->rows[r]; + if (P[r] >= 0) continue; + if (pr==-1 || (row->nnz < prow->nnz)) pr = r, prow = row; + } + if(pr == -1) continue; + P[pr] = rank; + + cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), A->mod); + nmod_sparse_vec_scalar_mul(prow, prow, cinv, A->mod); + + /* Gaussian eliminate rows */ + for (j = 0; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &A->rows[r]; + if(r==pr) {pcol->entries[j].val = UWORD(0); continue;} + + cc = nmod_neg(nmod_sparse_vec_at(row, pc), A->mod); + nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); + if (row->nnz == 0) P[r] = --remr; + } + /* Gaussian eliminate cols */ + nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, A->mod); + for (j = 0; j < prow->nnz; ++j) + { + c = prow->entries[j].ind, col = &At->rows[c]; + if(c >= A->c || c==pc) continue; + cc = nmod_neg(nmod_sparse_vec_at(col, pr), A->mod); + nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); + } + rank += 1; + } + nmod_sparse_mat_clear(At); + + /* Reorder rows */ + nmod_sparse_mat_permute_rows(A, P); + flint_free(P); + return rank; +} diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c new file mode 100644 index 0000000000..856fe9dace --- /dev/null +++ b/nmod_sparse_mat/solve_rref.c @@ -0,0 +1,46 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +{ + int good = 1; + slong i; + nmod_sparse_mat_t AB; + nmod_sparse_vec_struct *row; + nmod_sparse_entry_struct *le, *re; + nmod_sparse_mat_init(AB, A->r, A->c, A->mod); + nmod_sparse_mat_set(AB, A); + nmod_sparse_mat_append_col(AB, b); + AB->c = A->c; + nmod_sparse_mat_rref(AB); + AB->c = A->c+1; + + memset(x, 0, A->c*sizeof(*x)); + for (i = 0; i < A->r; ++i) + { + row = &AB->rows[i]; + if (row->nnz == 0) continue; + le = &row->entries[0]; + re = &row->entries[row->nnz-1]; + /* If any row has leading col A->c, system is not solvable */ + if (le->ind==A->c) {good = 0; break;} + /* Otherwise, x[lc] = lagging value */ + if (re->ind==A->c) {x[le->ind] = re->val;} + } + nmod_sparse_mat_clear(AB); +} diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 9c62e518a0..9ebecbf031 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -23,7 +23,7 @@ main(void) slong rep, r, c, i, j, k, nnz; mp_limb_t n; nmod_t mod; - nmod_sparse_mat_t A, B; + nmod_sparse_mat_t A, B, C; slong *rows; slong *cols; mp_limb_t *vals; @@ -41,6 +41,7 @@ main(void) nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); + nmod_sparse_mat_init(C, 0, c, mod); nmod_sparse_mat_randtest(A, state, 2, 2); nmod_sparse_mat_randtest(B, state, 2, 2); @@ -71,6 +72,17 @@ main(void) nmod_sparse_mat_print_pretty(B); abort(); } + + for (i = 0; i < r; ++i) nmod_sparse_mat_append_row(C, &A->rows[i]); + if (!nmod_sparse_mat_equal(A, C)) + { + flint_printf("FAIL: A != C\n"); + flint_printf("A = "); + nmod_sparse_mat_print_pretty(A); + flint_printf("C = "); + nmod_sparse_mat_print_pretty(C); + abort(); + } flint_free(rows); flint_free(cols); flint_free(vals); diff --git a/nmod_sparse_mat/test/t-rref.c b/nmod_sparse_mat/test/t-rref.c new file mode 100644 index 0000000000..5c678219e5 --- /dev/null +++ b/nmod_sparse_mat/test/t-rref.c @@ -0,0 +1,63 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + mp_limb_t n; + nmod_t mod; + nmod_sparse_mat_t A, B; + nmod_mat_t dA; + FLINT_TEST_INIT(state); + + flint_printf("converting A to reduced row echelon form...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + r = n_randint(state, 100); + c = n_randint(state, 100); + do n = n_randtest_not_zero(state); + while (n <= 32 || !n_is_prime(n)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(B, r, c, mod); + nmod_mat_init(dA, r, c, n); + + nmod_sparse_mat_randtest(A, state, 0, n); + nmod_sparse_mat_to_dense(dA, A); + nmod_sparse_mat_rref(A); + nmod_mat_rref(dA); + nmod_sparse_mat_from_dense(B, dA); + if(!nmod_sparse_mat_equal(A, B)) { + flint_printf("FAIL!\n"); + abort(); + } + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_mat_clear(dA); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index b366b93b97..6a72dc3870 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -28,7 +28,7 @@ main(void) nmod_t mod; nmod_sparse_mat_t A, At; mp_ptr x, x2, b, Atb, Ax, AtAx; - double l_elapsed = 0, d_elapsed = 0; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; struct timeval start, end; FLINT_TEST_INIT(state); @@ -38,15 +38,15 @@ main(void) for (rep = 0; rep < 100; rep++) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - r = n_randint(state, 200); - c = n_randint(state, 200); + r = n_randint(state, 400); + c = n_randint(state, 400); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(At, c, r, mod); - nmod_sparse_mat_randtest(A, state, 0, c); + nmod_sparse_mat_randtest(A, state, c/20, c/10); nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); @@ -58,11 +58,23 @@ main(void) _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(b, A, x); - /* Solve directly */ + /* Solve via reduced row echelon form */ + gettimeofday(&start, NULL); + ret = nmod_sparse_mat_solve_rref(x2, A, b); + gettimeofday(&end, NULL); + rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + nmod_sparse_mat_mul_vec(Ax, A, x2); + if(!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve via lu decomposition */ gettimeofday(&start, NULL); ret = nmod_sparse_mat_solve_lu(x2, A, b); gettimeofday(&end, NULL); - d_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); nmod_sparse_mat_mul_vec(Ax, A, x2); if(!_nmod_vec_equal(b, Ax, A->r)) { @@ -75,7 +87,7 @@ main(void) for (iter=1; iter<=10; ++iter) /* TODO: set number of trials based on params */ if (ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; gettimeofday(&end, NULL); - l_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); if (iter==11) { @@ -108,8 +120,9 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for Lanzcos: %lf\n", l_elapsed/1000); - flint_printf("Average time for direct: %lf\n", d_elapsed/1000); + flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/1000); + flint_printf("Average time for LU: %lf\n", lu_elapsed/1000); + flint_printf("Average time for rref: %lf\n", rref_elapsed/1000); flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f iters per solution.\n", nosol, 1000, psolved, 1000, niters/1000.); return 0; } diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index 8a5bac0466..318f7a0e15 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -29,6 +29,7 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) for (i = 0; i < A->rows[r].nnz; ++i) { c = A->rows[r].entries[i].ind; + if(c >= A->c) break; B->rows[c].nnz += 1; } } @@ -46,7 +47,9 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) for (i = 0; i < A->rows[r].nnz; ++i) { nmod_sparse_entry_struct *Ae = &A->rows[r].entries[i]; - c = Ae->ind, j = B->rows[c].nnz++; + c = Ae->ind; + if(c >= A->c) break; + j = B->rows[c].nnz++; nmod_sparse_entry_struct *Be = &B->rows[c].entries[j]; Be->ind = r, Be->val = Ae->val; } diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 200a9065f9..ffb8043bcb 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -101,6 +101,16 @@ void nmod_sparse_vec_one(nmod_sparse_vec_t vec, slong ind) FLINT_DLL void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src); +NMOD_SPARSE_VEC_INLINE +void _nmod_sparse_vec_append_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) +{ + if (val == UWORD(0)) return; + v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); + v->entries[v->nnz].ind = ind; + v->entries[v->nnz].val = val; + v->nnz += 1; +} + FLINT_DLL void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz); From 502acdf639b9030c1ee2e582769ef248a3feb76f Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 1 Apr 2020 17:32:26 -0700 Subject: [PATCH 13/42] Now with additional utilities, more correct basic functions, and nullspace and inversion functions --- nmod_sparse_mat.h | 43 +++++++++-- nmod_sparse_mat/inv.c | 20 +++-- nmod_sparse_mat/lu.c | 4 +- nmod_sparse_mat/nullspace_lanczos.c | 83 ++++++++++++++++++++ nmod_sparse_mat/nullspace_lu.c | 61 +++++++++++++++ nmod_sparse_mat/nullspace_rref.c | 53 +++++++++++++ nmod_sparse_mat/rref.c | 4 +- nmod_sparse_mat/solve_lu.c | 1 + nmod_sparse_mat/test/t-concat_horizontal.c | 33 ++++++-- nmod_sparse_mat/test/t-concat_vertical.c | 25 +++++- nmod_sparse_mat/test/t-inv.c | 73 ++++++++++++++++++ nmod_sparse_mat/test/t-nullspace.c | 90 ++++++++++++++++++++++ nmod_sparse_vec.h | 8 +- nmod_sparse_vec/scalar_addmul.c | 2 +- nmod_sparse_vec/scalar_mul.c | 4 +- nmod_sparse_vec/set.c | 7 +- nmod_sparse_vec/split.c | 35 +++++++++ nmod_sparse_vec/test/t-concat.c | 23 +++++- 18 files changed, 531 insertions(+), 38 deletions(-) create mode 100644 nmod_sparse_mat/nullspace_lanczos.c create mode 100644 nmod_sparse_mat/nullspace_lu.c create mode 100644 nmod_sparse_mat/nullspace_rref.c create mode 100644 nmod_sparse_mat/test/t-inv.c create mode 100644 nmod_sparse_mat/test/t-nullspace.c create mode 100644 nmod_sparse_vec/split.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 93ebf9dbf1..8406242bdf 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -106,8 +106,7 @@ void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) { slong i, rmax = FLINT_MIN(mat->r, src->r); if(mat==src || mat->r == 0) return; - mat->c_off = src->c_off; - for(i=0; irows[i], &src->rows[i]); + for(i=0; irows[i], &src->rows[i], src->c_off); } FLINT_DLL @@ -126,7 +125,7 @@ void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, const nmod_sparse_vec_t v { mat->rows = realloc(mat->rows, (mat->r+1)*sizeof(*mat->rows)); memset(mat->rows + mat->r, 0, sizeof(*mat->rows)); - nmod_sparse_vec_set(&mat->rows[mat->r], vec); + nmod_sparse_vec_set(&mat->rows[mat->r], vec, 0); mat->r += 1; } @@ -155,6 +154,7 @@ void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) memset(window, 0, sizeof(*window)); } + /* res->r must equal mat1->r and mat2->r */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, @@ -172,11 +172,28 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_ma slong i; res->c = FLINT_MAX(mat1->c, mat2->c); for (i = 0; i < mat1->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); + nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i], mat1->c_off); for (i = mat1->r; i < res->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); + nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r], mat2->c_off); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong c) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_split(&res1->rows[i], &res2->rows[i], &mat->rows[i], c); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong r) +{ + slong i; + r = FLINT_MIN(r, mat->r); + for(i=0; irows[i], &mat->rows[i], mat->c_off); + for(i=r; ir; ++i) nmod_sparse_vec_set(&res2->rows[i-r], &mat->rows[i], mat->c_off); } + /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) @@ -320,14 +337,14 @@ FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t mat, slong * perm); FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, slong n); */ -/* Decomposition */ +/* Decomposition/reduction */ FLINT_DLL slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t A); -/* Nonsingular solving */ +/* Solving */ FLINT_DLL int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); @@ -337,8 +354,18 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b FLINT_DLL int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +/* Note: this should take in uninitialized matrix X */ +FLINT_DLL +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); + FLINT_DLL -void nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE diff --git a/nmod_sparse_mat/inv.c b/nmod_sparse_mat/inv.c index dfbe611d5c..4396bcead9 100644 --- a/nmod_sparse_mat/inv.c +++ b/nmod_sparse_mat/inv.c @@ -15,27 +15,25 @@ #include "flint.h" #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -void nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A) +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A) { - nmod_sparse_mat_t I, AI, window; + slong rk; + nmod_sparse_mat_t I, AI; nmod_sparse_vec_struct *row; nmod_sparse_entry_struct *le, *re; /* Create block matrix [A | I] */ nmod_sparse_mat_init(I, A->r, A->r, A->mod); nmod_sparse_mat_one(I); - nmod_sparse_mat_init(AI, A->r, A->c, A->mod); + nmod_sparse_mat_init(AI, A->r, A->r + A->c, A->mod); nmod_sparse_mat_concat_horizontal(AI, A, I); - nmod_sparse_mat_clear(I); /* Run Gaussian elimination on first half */ AI->c = A->c; - nmod_sparse_mat_rref(AI); + rk = nmod_sparse_mat_rref(AI); AI->c = A->c+A->r; - nmod_sparse_mat_window_init(window, AI, 0, A->c, A->r, A->c+A->r); - nmod_sparse_mat_set(Ai, window); - - /* TODO: ?? not invertible */ - nmod_sparse_mat_window_clear(window); - nmod_sparse_mat_clear(AI); + nmod_sparse_mat_split_horizontal(I, Ai, AI, A->c); + nmod_sparse_mat_clear(I); + nmod_sparse_mat_clear(AI); + return rk; } diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 5540c9dd10..3df388caa2 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -77,8 +77,8 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, { nmod_sparse_mat_zero(L); nmod_sparse_mat_zero(U); - memset(P, 0, (A->r)*sizeof(*P)); - memset(Q, 0, (A->c)*sizeof(*Q)); + for (i = 0; i < A->r; ++i) P[i] = i; + for (i = 0; i < A->c; ++i) Q[i] = i; return 0; } nmod_sparse_mat_init(Lt, L->c, L->r, A->mod); diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c new file mode 100644 index 0000000000..d87d51e921 --- /dev/null +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -0,0 +1,83 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters) +{ + /* Generate random solutions to a random system Ax=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + mp_ptr x, x2, b, Ax, *xs; + x = _nmod_vec_init(A->c); + x2 = _nmod_vec_init(A->c); + b = _nmod_vec_init(A->r); + Ax = _nmod_vec_init(A->r); + nxs = 0; + xs = NULL; + xps = NULL; + for(iter = 0; iter < max_iters; ) + { + _nmod_vec_randtest(x, state, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) {++iter; continue;} /* Lanczos failed */ + _nmod_vec_sub(x, x, x2, A->c, A->mod); + if(_nmod_vec_is_zero(x, A->c)) {++iter; continue;}; /* Probably no nullspace */ + nmod_sparse_mat_mul_vec(Ax, A, x); + if(!_nmod_vec_is_zero(Ax, A->c)) {++iter; continue;} /* In preimage of nullspace of A^t */ + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + _nmod_vec_scalar_addmul_nmod(x, xs[j], A->c, nmod_neg(x[xps[j]], A->mod), A->mod); + } + + /* Normalize last nonzero entry to 1 */ + for (i = A->c-1; i >= 0 && x[i] == UWORD(0); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + _nmod_vec_scalar_mul_nmod(x, x, A->c, nmod_inv(x[i], A->mod), A->mod); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + _nmod_vec_scalar_addmul_nmod(xs[j], x, A->c, nmod_neg(xs[j][i], A->mod), A->mod); + } + + /* Insert into list of vectors in nullspace */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _nmod_vec_init(A->c); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + flint_free(x); + flint_free(x2); + flint_free(b); + flint_free(Ax); + nmod_mat_init(X, A->c, nxs, A->mod.n); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < A->c; ++j) + X->rows[j][i] = xs[i][j]; + flint_free(xs[i]); + } + flint_free(xs); + return X->c; +} diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c new file mode 100644 index 0000000000..322dc33693 --- /dev/null +++ b/nmod_sparse_mat/nullspace_lu.c @@ -0,0 +1,61 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A) +{ + int good = 1; + slong rk, *P, *Q, *Qi, i, j; + nmod_sparse_mat_t L, U; + nmod_sparse_entry_struct *e; + nmod_sparse_vec_struct *Urow; + mp_limb_t *Xrow; + P = flint_malloc(A->r * sizeof(*P)); + Q = flint_malloc(A->c * sizeof(*Q)); + nmod_sparse_mat_init(L, A->r, A->c, A->mod); + nmod_sparse_mat_init(U, A->r, A->c, A->mod); + rk = nmod_sparse_mat_lu(P, Q, L, U, A); + flint_free(P); + nmod_sparse_mat_clear(L); + for(i=0; irows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, A->mod), A->mod); + nmod_mat_init(X, A->c, A->c-rk, A->mod.n); + if (rk != A->c) + { + /* Invert permutation */ + Qi = flint_malloc(A->c * sizeof(*Qi)); + for (i = 0; i < A->c; ++i) Qi[Q[i]] = i; + + /* Assign unit vectors to non-pivot columns */ + for (i = A->c-1; i >= rk; --i) X->rows[Qi[i]][i-rk] = 1; + for (i = rk-1; i >= 0; --i) { + Urow = &U->rows[i]; + Xrow = X->rows[Qi[i]]; + for(j = 1; jnnz; ++j) { + e = &Urow->entries[j]; + /* Do in-place row elimination */ + if(e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, A->mod), A->mod); + else Xrow[e->ind-rk] = nmod_sub(Xrow[e->ind-rk], e->val, A->mod); + } + + } + flint_free(Qi); + } + flint_free(Q); + nmod_sparse_mat_clear(U); + return X->c; +} diff --git a/nmod_sparse_mat/nullspace_rref.c b/nmod_sparse_mat/nullspace_rref.c new file mode 100644 index 0000000000..15bc97c3c8 --- /dev/null +++ b/nmod_sparse_mat/nullspace_rref.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A) +{ + slong i, j, rk, numc, *Q; + nmod_sparse_mat_t R; + nmod_sparse_vec_struct *Rrow; + mp_limb_t *Xrow; + nmod_sparse_entry_struct *le, *e; + nmod_sparse_mat_init(R, A->r, A->c, A->mod); + nmod_sparse_mat_set(R, A); + rk = nmod_sparse_mat_rref(R); + nmod_mat_init(X, A->c, A->c-rk, A->mod.n); + if(rk != A->c) + { + numc = 0; + /* Mark which cols are pivots and enumerate the nonpivots */ + Q = flint_calloc(A->c, sizeof(*Q)); + for (i = 0; i < rk; ++i) + Q[R->rows[i].entries->ind] = -1; + for (i = 0; i < A->c; ++i) + if(Q[i]==UWORD(0)) Q[i] = numc++, X->rows[i][Q[i]] = 1; + + /* For each pivot col, set the corresponding row in X as */ + /* the negative of the associated row in R (reordered by Q) */ + for (i = 0; i < rk; ++i) + { + Rrow = &R->rows[i]; + Xrow = X->rows[Rrow->entries[0].ind]; + for (j = 1; j < Rrow->nnz; ++j) + Xrow[Q[Rrow->entries[j].ind]] = nmod_neg(Rrow->entries[j].val, A->mod); + } + flint_free(Q); + } + nmod_sparse_mat_clear(R); + return X->c; +} diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index 8ab4af6cb7..ec6a98923b 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -33,7 +33,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t A) remr = A->r; for (r = 0; rr; ++r) { - if (!A->rows[r].nnz) P[r] = --remr; + if (!A->rows[r].nnz || A->rows[r].entries[0].ind >= A->c) P[r] = --remr; else P[r] = -1; } @@ -65,7 +65,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t A) cc = nmod_neg(nmod_sparse_vec_at(row, pc), A->mod); nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); - if (row->nnz == 0) P[r] = --remr; + if (row->nnz == 0 || row->entries[0].ind >= A->c) P[r] = --remr; } /* Gaussian eliminate cols */ nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, A->mod); diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 2bd83a48c4..50cf4ca8ce 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -56,6 +56,7 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b for(i = 0; i < A->c; ++i) x[i] = xp[Q[i]]; flint_free(xp); } + flint_free(Q); flint_free(y); U->r = A->r; nmod_sparse_mat_clear(U); diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index 7c429c8484..dcb8b7b081 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -56,7 +56,30 @@ int main(void) nmod_sparse_mat_print_pretty(A); flint_printf("B = \n"); nmod_sparse_mat_print_pretty(B); - flint_printf("A concat_horizontal B = \n"); + flint_printf("A | B = \n"); + nmod_sparse_mat_print_pretty(C); + flint_printf("window1 = \n"); + nmod_sparse_mat_print_pretty(window1); + flint_printf("window2 = \n"); + nmod_sparse_mat_print_pretty(window2); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); + + nmod_sparse_mat_init(window1, r, c1, mod); + nmod_sparse_mat_init(window2, r, c2, mod); + nmod_sparse_mat_split_horizontal(window1, window2, C, c1); + + if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + nmod_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + nmod_sparse_mat_print_pretty(B); + flint_printf("A | B = \n"); nmod_sparse_mat_print_pretty(C); flint_printf("window1 = \n"); nmod_sparse_mat_print_pretty(window1); @@ -65,13 +88,13 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } - - nmod_sparse_mat_clear(A); - nmod_sparse_mat_clear(B); - nmod_sparse_mat_clear(C); nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); } diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index 97ba8f7286..12a992efa8 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -62,13 +62,32 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); + + nmod_sparse_mat_init(window1, r1, c, mod); + nmod_sparse_mat_init(window2, r2, c, mod); + nmod_sparse_mat_split_vertical(window1, window2, C, r1); - nmod_sparse_mat_clear(A); - nmod_sparse_mat_clear(B); - nmod_sparse_mat_clear(C); + if (!(nmod_sparse_mat_equal(window1, A) && nmod_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + nmod_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + nmod_sparse_mat_print_pretty(B); + flint_printf("A concat_vertical B = \n"); + nmod_sparse_mat_print_pretty(C); + flint_printf("FAIL: results not equal\n"); + abort(); + } nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); } diff --git a/nmod_sparse_mat/test/t-inv.c b/nmod_sparse_mat/test/t-inv.c new file mode 100644 index 0000000000..99eccb4a07 --- /dev/null +++ b/nmod_sparse_mat/test/t-inv.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + int ret, badct = 0; + slong rep, r, c, i, rk; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A, Ai; + nmod_mat_t dA, dAiA; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("inverting A...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + do r = n_randint(state, 200), c = n_randint(state, 200); + while (r==UWORD(0) || c==UWORD(0)); + + do n = n_randtest_not_zero(state); + while (n <= 32 || !n_is_prime(n)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(Ai, r, r, mod); + nmod_sparse_mat_randtest(A, state, 0, c); + nmod_mat_init(dA, r, c, n); + nmod_mat_init(dAiA, r, c, n); + nmod_sparse_mat_to_dense(dA, A); + + rk = nmod_sparse_mat_inv(Ai, A); + nmod_sparse_mat_mul_mat(dAiA, Ai, dA); + nmod_mat_rref(dA); + if(!nmod_mat_equal(dAiA, dA)) { + flint_printf("FAIL!\n"); + flint_printf("A^-1 x A = "); + nmod_mat_print_pretty(dAiA); + flint_printf("rref(A) = "); + nmod_mat_print_pretty(dA); + abort(); + } + + nmod_sparse_mat_clear(Ai); + nmod_mat_clear(dA); + nmod_mat_clear(dAiA); + nmod_sparse_mat_clear(A); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c new file mode 100644 index 0000000000..d0ab6e041b --- /dev/null +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -0,0 +1,90 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + int iter, ret; + slong rep, nreps = 100, r, c, i, lanczos_discrep = 0; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A; + nmod_mat_t X, AX; + slong rk[3]; + double elapsed[3] = {0, 0, 0}; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("finding nullspace of A...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + r = n_randint(state, 500); + c = r + n_randint(state, 10); + do n = n_randtest_not_zero(state); + while (n <= 32 || !n_is_prime(n)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_randtest(A, state, c/20, c/10); + for (i = 0; i < 3; ++i) + { + gettimeofday(&start, NULL); + switch (i) + { + case 0: rk[0] = nmod_sparse_mat_nullspace_rref(X, A); break; + case 1: rk[1] = nmod_sparse_mat_nullspace_lu(X, A); break; + case 2: rk[2] = nmod_sparse_mat_nullspace_lanczos(X, A, state, 2); break; + } + gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if(X->c==0) continue; + nmod_mat_init(AX, A->r, X->c, n); + nmod_sparse_mat_mul_mat(AX, A, X); + /*nmod_mat_print_pretty(AX); */ + if (!nmod_mat_is_zero(AX)) + { + flint_printf("FAIL: %d!\n", i); + if (i != 0) + flint_printf("Nullity should be %wd\n", rk[i-1]); + nmod_sparse_mat_print_pretty(A); + nmod_mat_print_pretty(X); + abort(); + } + if (i == 2 && rk[i] != rk[i-1]) + { + lanczos_discrep += 1; + } + + nmod_mat_clear(X); + nmod_mat_clear(AX); + } + nmod_sparse_mat_clear(A); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + flint_printf("Average time for rref: %lf\n", elapsed[0]/nreps); + flint_printf("Average time for LU: %lf\n", elapsed[1]/nreps); + flint_printf("Average time for Lanzcos: %lf\n", elapsed[2]/nreps); + flint_printf("Lanczos did not find full nullspace for %wd/%wd examples\n", lanczos_discrep, nreps); + return 0; +} diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index ffb8043bcb..4c6ba410d4 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -93,13 +93,14 @@ void nmod_sparse_vec_zero(nmod_sparse_vec_t vec) NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_one(nmod_sparse_vec_t vec, slong ind) { + vec->nnz = 1; vec->entries = realloc(vec->entries, sizeof(*vec->entries)); vec->entries[0].ind = ind; vec->entries[0].val = UWORD(1); } FLINT_DLL -void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src); +void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src, slong ioff); NMOD_SPARSE_VEC_INLINE void _nmod_sparse_vec_append_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) @@ -155,6 +156,9 @@ void nmod_sparse_vec_window_clear(nmod_sparse_vec_t window) FLINT_DLL void nmod_sparse_vec_concat(nmod_sparse_vec_t res, const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong len1); +FLINT_DLL +void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res2, const nmod_sparse_vec_t vec, slong ind); + /* Vector permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_permute_inds(nmod_sparse_vec_t vec, slong *P) @@ -176,7 +180,7 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t mod) { slong i; - nmod_sparse_vec_set(v, u); + nmod_sparse_vec_set(v, u, 0); for (i = 0; i < v->nnz; ++i) v->entries[i].val = nmod_neg(v->entries[i].val, mod); } diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c index dab0b03a47..0cee0b1a53 100644 --- a/nmod_sparse_vec/scalar_addmul.c +++ b/nmod_sparse_vec/scalar_addmul.c @@ -18,7 +18,7 @@ void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) { if (c == UWORD(0) || (u->nnz == 0 && v->nnz == 0)) {nmod_sparse_vec_zero(w); return;} - if (v->nnz == 0) {nmod_sparse_vec_set(w, u); return;} + if (v->nnz == 0) {nmod_sparse_vec_set(w, u, 0); return;} if (u->nnz == 0) {nmod_sparse_vec_scalar_mul(w, v, c, mod); return;} nmod_sparse_vec_t u2; u2->nnz = u->nnz; diff --git a/nmod_sparse_vec/scalar_mul.c b/nmod_sparse_vec/scalar_mul.c index d1dd28e182..3a86fac860 100644 --- a/nmod_sparse_vec/scalar_mul.c +++ b/nmod_sparse_vec/scalar_mul.c @@ -18,12 +18,12 @@ void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) { if (c == UWORD(0)) nmod_sparse_vec_zero(v); - else if (c == UWORD(1)) nmod_sparse_vec_set(v, u); + else if (c == UWORD(1)) nmod_sparse_vec_set(v, u, 0); else if (c==mod.n-UWORD(1)) nmod_sparse_vec_neg(v, u, mod); else { slong i; - nmod_sparse_vec_set(v, u); + nmod_sparse_vec_set(v, u, 0); for (i = 0; i < v->nnz; ++i) v->entries[i].val = nmod_mul(v->entries[i].val, c, mod); } } \ No newline at end of file diff --git a/nmod_sparse_vec/set.c b/nmod_sparse_vec/set.c index a637c64abe..9d7d105192 100644 --- a/nmod_sparse_vec/set.c +++ b/nmod_sparse_vec/set.c @@ -15,8 +15,9 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src) +void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src, slong ioff) { + slong i; if (vec==src) return; if (src->nnz == 0) nmod_sparse_vec_clear(vec); else @@ -24,5 +25,9 @@ void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src) vec->entries = flint_realloc(vec->entries, src->nnz*sizeof(*vec->entries)); memcpy(vec->entries, src->entries, src->nnz*sizeof(*vec->entries)); vec->nnz = src->nnz; + for(i=0; innz; ++i) + { + vec->entries[i].ind -= ioff; + } } } \ No newline at end of file diff --git a/nmod_sparse_vec/split.c b/nmod_sparse_vec/split.c new file mode 100644 index 0000000000..83a8e11c25 --- /dev/null +++ b/nmod_sparse_vec/split.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res2, const nmod_sparse_vec_t vec, slong ind) +{ + slong i; + for(i=0; innz; ++i) if(vec->entries[i].ind >= ind) break; + if(i==0) nmod_sparse_vec_clear(res1); + else { + res1->nnz = i; + res1->entries = flint_realloc(res1->entries, res1->nnz*sizeof(*res1->entries)); + memcpy(res1->entries, vec->entries, res1->nnz*sizeof(*res1->entries)); + } + if(i==vec->nnz) nmod_sparse_vec_clear(res2); + else { + res2->nnz = vec->nnz - i; + res2->entries = flint_realloc(res2->entries, res2->nnz*sizeof(*res2->entries)); + memcpy(res2->entries, vec->entries+i, res2->nnz*sizeof(*res2->entries)); + for(i=0; innz; ++i) res2->entries[i].ind -= ind; + } +} diff --git a/nmod_sparse_vec/test/t-concat.c b/nmod_sparse_vec/test/t-concat.c index 470b2d3a28..9b63ba3759 100644 --- a/nmod_sparse_vec/test/t-concat.c +++ b/nmod_sparse_vec/test/t-concat.c @@ -55,7 +55,7 @@ int main(void) nmod_sparse_vec_print_pretty(u, 0, len, mod); flint_printf("v = \n"); nmod_sparse_vec_print_pretty(v, 0, len, mod); - flint_printf("A concat_horizontal B = \n"); + flint_printf("u | v = \n"); nmod_sparse_vec_print_pretty(w, 0, len, mod); flint_printf("window1 = \n"); nmod_sparse_vec_print_pretty(window1, 0, len, mod); @@ -66,6 +66,27 @@ int main(void) } nmod_sparse_vec_window_clear(window1); nmod_sparse_vec_window_clear(window2); + + nmod_sparse_vec_init(window1); + nmod_sparse_vec_init(window2); + nmod_sparse_vec_split(window1, window2, w, len); + if (!(nmod_sparse_vec_equal(window1, u, 0) && nmod_sparse_vec_equal(window2, v, 0))) + { + flint_printf("u = "); + nmod_sparse_vec_print_pretty(u, 0, len, mod); + flint_printf("v = \n"); + nmod_sparse_vec_print_pretty(v, 0, len, mod); + flint_printf("u | v = \n"); + nmod_sparse_vec_print_pretty(w, 0, len, mod); + flint_printf("window1 = \n"); + nmod_sparse_vec_print_pretty(window1, 0, len, mod); + flint_printf("window2 = \n"); + nmod_sparse_vec_print_pretty(window2, 0, len, mod); + flint_printf("FAIL: results not equal\n"); + abort(); + } + nmod_sparse_vec_window_clear(window1); + nmod_sparse_vec_window_clear(window2); nmod_sparse_vec_clear(u); nmod_sparse_vec_clear(v); nmod_sparse_vec_clear(w); From ed471623a5115f233eba1ea7fc5542496c68dd06 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 2 Apr 2020 14:16:09 -0700 Subject: [PATCH 14/42] Added nullvector functions for Lanzcos, everything for basic Wiedemann --- nmod_sparse_mat.h | 19 ++- nmod_sparse_mat/nullspace_lanczos.c | 18 +-- nmod_sparse_mat/nullspace_wiedemann.c | 71 +++++++++++ nmod_sparse_mat/solve_lanczos.c | 22 ++++ nmod_sparse_mat/solve_wiedemann.c | 165 ++++++++++++++++++++++++++ nmod_sparse_mat/test/t-nullspace.c | 15 ++- nmod_sparse_mat/test/t-solve.c | 79 +++++++----- 7 files changed, 339 insertions(+), 50 deletions(-) create mode 100644 nmod_sparse_mat/nullspace_wiedemann.c create mode 100644 nmod_sparse_mat/solve_wiedemann.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 8406242bdf..6407b38876 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -344,25 +344,36 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t A); -/* Solving */ +/* Solve Ax=b */ FLINT_DLL int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); +FLINT_DLL +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); + FLINT_DLL int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); FLINT_DLL int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +/* Find single nullvector */ +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); + +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); + /* Note: this should take in uninitialized matrix X */ FLINT_DLL -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); FLINT_DLL slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index d87d51e921..02a42e147f 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -21,23 +21,14 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, /* Generate random solutions to a random system Ax=b and stop when nullspace filled */ int ret; slong i, j, iter, nxs, *xps; - mp_ptr x, x2, b, Ax, *xs; + mp_ptr x, *xs; x = _nmod_vec_init(A->c); - x2 = _nmod_vec_init(A->c); - b = _nmod_vec_init(A->r); - Ax = _nmod_vec_init(A->r); nxs = 0; xs = NULL; xps = NULL; for(iter = 0; iter < max_iters; ) { - _nmod_vec_randtest(x, state, A->c, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); - if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) {++iter; continue;} /* Lanczos failed */ - _nmod_vec_sub(x, x, x2, A->c, A->mod); - if(_nmod_vec_is_zero(x, A->c)) {++iter; continue;}; /* Probably no nullspace */ - nmod_sparse_mat_mul_vec(Ax, A, x); - if(!_nmod_vec_is_zero(Ax, A->c)) {++iter; continue;} /* In preimage of nullspace of A^t */ + if(nmod_sparse_mat_nullvector_lanczos(x, A, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ for (j = nxs-1; j >= 0; --j) { @@ -54,7 +45,7 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, _nmod_vec_scalar_addmul_nmod(xs[j], x, A->c, nmod_neg(xs[j][i], A->mod), A->mod); } - /* Insert into list of vectors in nullspace */ + /* Insert into list of vectors in nullspace (ordered by pivot) */ xs = realloc(xs, (nxs+1)*sizeof(*xs)); xps = realloc(xps, (nxs+1)*sizeof(*xps)); for (j = 0; j < nxs && i > xps[j]; ++j); @@ -68,9 +59,6 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, } flint_free(xps); flint_free(x); - flint_free(x2); - flint_free(b); - flint_free(Ax); nmod_mat_init(X, A->c, nxs, A->mod.n); for (i = 0; i < nxs; ++i) { diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c new file mode 100644 index 0000000000..33056affba --- /dev/null +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -0,0 +1,71 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters) +{ + /* Generate random solutions to a random system Ax=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + mp_ptr x, *xs; + x = _nmod_vec_init(A->c); + nxs = 0; + xs = NULL; + xps = NULL; + for(iter = 0; iter < max_iters; ) + { + if(nmod_sparse_mat_nullvector_wiedemann(x, A, state) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + _nmod_vec_scalar_addmul_nmod(x, xs[j], A->c, nmod_neg(x[xps[j]], A->mod), A->mod); + } + + /* Normalize last nonzero entry to 1 */ + for (i = A->c-1; i >= 0 && x[i] == UWORD(0); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + _nmod_vec_scalar_mul_nmod(x, x, A->c, nmod_inv(x[i], A->mod), A->mod); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + _nmod_vec_scalar_addmul_nmod(xs[j], x, A->c, nmod_neg(xs[j][i], A->mod), A->mod); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _nmod_vec_init(A->c); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + flint_free(x); + nmod_mat_init(X, A->c, nxs, A->mod.n); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < A->c; ++j) + X->rows[j][i] = xs[i][j]; + flint_free(xs[i]); + } + flint_free(xs); + return X->c; +} diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 4b468506ab..6f5df306a0 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -40,6 +40,8 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ nmod_sparse_mat_mul_vec(Atb, At, b); /* Make 0th vector random (and -1st vector trivial) */ + //_nmod_vec_set(w[0], Atb, A->c); + //for(j = 0; j < A->c; ++j) w[0][j] = n_randint(state, A->mod.n); _nmod_vec_randtest(w[0], state, A->c, A->mod); _nmod_vec_zero(w[1], A->c); delta[1] = 1; for (j = 0; ; j = 1-j) @@ -77,3 +79,23 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ nmod_sparse_mat_clear(At); return ret; } + +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) { + int ret = 1; + mp_ptr x2, b; + x2 = _nmod_vec_init(A->c); + b = _nmod_vec_init(A->r); + + _nmod_vec_randtest(x, state, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) ret = 0; /* Lanczos failed */ + if (ret) + { + _nmod_vec_sub(x, x, x2, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + ret = _nmod_vec_is_zero(x, A->c) || !_nmod_vec_is_zero(b, A->r); + } + _nmod_vec_clear(x2); + _nmod_vec_clear(b); + return ret; +} \ No newline at end of file diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c new file mode 100644 index 0000000000..c629ef1107 --- /dev/null +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -0,0 +1,165 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +// Berlekamp - Massey algorithm +static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) +{ + slong L = 0, m, n, i; + mp_limb_t c, d_C, d_B = 1; + + slong deg_C = 0, deg_B = 0, deg_T = -1; + mp_limb_t *B, *C, *T; + B = flint_calloc(N, sizeof(*B)); + C = flint_calloc(N, sizeof(*C)); + T = flint_calloc(N, sizeof(*T)); + B[0] = C[0] = UWORD(1); + + for (n = 0, m = 1; n < N; n++, m++) + { + /* d_C = sum_{i=0}^L C_i * s_{n-i} */ + d_C = s[n]; + for (i = 1; i <= L; i++) + d_C = nmod_addmul(d_C, C[i], s[n-i], mod); + if (d_C == 0) continue; /* C and L currently valid */ + + /* C(x) = C(x) - (d_C/d_B) x^m B(x); */ + if (L <= 2*n) deg_T = deg_C, memcpy(T, C, (deg_C+1)*sizeof(*T)); /* T(X) = C(X) */ + c = nmod_neg(nmod_div(d_C, d_B, mod), mod); + for (i = 0; i <= deg_B; ++i) + C[m+i] = nmod_addmul(C[m+i], B[i], c, mod); + deg_C = FLINT_MAX(deg_C, deg_B + m); + while(C[deg_C] == UWORD(0)) --deg_C; /* Probably unnecessary */ + + if (2*L <= n) /* Increase number of errors */ + { + L = n + 1 - L, m = 0; + d_B = d_C, deg_B = deg_T; + memcpy(B, T, (deg_T+1)*sizeof(*B)); /* B(x) = C(x) */ + } + } + /* Reverse C into s */ + for (i = 0; i <= L; ++i) s[i] = C[L-i]; + flint_free(B); + flint_free(C); + flint_free(T); + return L; +} + +/* Compute s_ij=(A^j y)_i for i=0,...,ns-1, j=0,...,num-1*/ +static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse_mat_t A, mp_srcptr b) +{ + slong i, j; + mp_ptr y, Ay; + y = _nmod_vec_init(A->r); + Ay = _nmod_vec_init(A->r); + memcpy(y, b, A->r*sizeof(*y)); + for (j = 0; j < len; ++j) + { + if(j > 0) nmod_sparse_mat_mul_vec(Ay, A, y), memcpy(y, Ay, A->r*sizeof(*y)); + for(i = 0; i < ns; ++i) s[i][j] = y[i]; + } + _nmod_vec_clear(y); + _nmod_vec_clear(Ay); +} + +/* Compute x = \Sigma_{i=0}^{L-1} s_i * A^i * b = 0 */ +static void make_sum(mp_ptr x, mp_limb_t *s, slong L, const nmod_sparse_mat_t A, mp_srcptr b) +{ + slong i; + mp_ptr y, Ay; + y = _nmod_vec_init(A->r); + Ay = _nmod_vec_init(A->r); + memcpy(y, b, A->r*sizeof(*y)); + _nmod_vec_scalar_mul_nmod(x, b, A->r, s[0], A->mod); + for (i = 1; i < L; ++i) + { + nmod_sparse_mat_mul_vec(Ay, A, y), memcpy(y, Ay, A->r*sizeof(*y)); + _nmod_vec_scalar_addmul_nmod(x, y, A->r, s[i], A->mod); + } + _nmod_vec_clear(y); + _nmod_vec_clear(Ay); +} + +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +{ + slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + mp_limb_t **s; + mp_ptr Ax; + if(A->r != A->c) return 0; /* TBD: reduce to square */ + + Ax = _nmod_vec_init(A->r); + s = flint_malloc(ns * sizeof(*s)); + for (i = 0; i < ns; ++i) s[i] = flint_malloc(len*sizeof(*s[i])); + + make_sequences(s, ns, len, A, b); + + /* Don't have block Berlekamp yet, just try each one */ + for (i = 0; i < ns && ret == 0; ++i) + { + /* Get minimal polynomial */ + L = find_min_poly(s[i], len, A->mod); + if(s[i][0]==0) continue; + + /* If \sum_{j=0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j=0}^{L-1} s_i(j-1) A^jb solves Ax=b */ + make_sum(x, s[i]+1, L, A, b); + _nmod_vec_scalar_mul_nmod(x, x, A->r, nmod_neg(nmod_inv(s[i][0], A->mod), A->mod), A->mod); + + /* Check if successful */ + nmod_sparse_mat_mul_vec(Ax, A, x); + ret = _nmod_vec_equal(Ax, b, A->r); + } + + _nmod_vec_clear(Ax); + for (i = 0; i < ns; ++i) flint_free(s[i]); + flint_free(s); + return ret; +} + +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) +{ + slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + mp_limb_t **s; + mp_ptr Ax, b; + Ax = _nmod_vec_init(A->r); + b = _nmod_vec_init(A->r); + + s = flint_malloc(ns * sizeof(*s)); + for (i = 0; i < ns; ++i) s[i] = flint_malloc(len*sizeof(*s[i])); + + _nmod_vec_randtest(x, state, A->r, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + + if(A->r != A->c) return 0; /* TBD: reduce to square */ + make_sequences(s, ns, len, A, b); + + for (i = 0; i < ns && ret == 0; ++i) + { + /* Get minimal polynomial */ + L = find_min_poly(s[i], len, A->mod); + + /* \sum_{j=0}^L s_ijA^jb = 0 => x = \sum_{j=0}^L s_ijA^jx solves Ax=0 */ + make_sum(x, s[i], L+1, A, x); + nmod_sparse_mat_mul_vec(Ax, A, x); + ret = _nmod_vec_is_zero(Ax, A->r); + } + + _nmod_vec_clear(Ax); + _nmod_vec_clear(b); + for (i = 0; i < ns; ++i) flint_free(s[i]); + flint_free(s); + return ret; +} \ No newline at end of file diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c index d0ab6e041b..17ba11a8c8 100644 --- a/nmod_sparse_mat/test/t-nullspace.c +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -22,13 +22,13 @@ int main(void) { int iter, ret; - slong rep, nreps = 100, r, c, i, lanczos_discrep = 0; + slong rep, nreps = 100, r, c, i, lanczos_discrep = 0, wied_discrep = 0; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A; nmod_mat_t X, AX; slong rk[3]; - double elapsed[3] = {0, 0, 0}; + double elapsed[4] = {0, 0, 0, 0}; struct timeval start, end; FLINT_TEST_INIT(state); @@ -45,7 +45,7 @@ main(void) nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_randtest(A, state, c/20, c/10); - for (i = 0; i < 3; ++i) + for (i = 0; i < 4; ++i) { gettimeofday(&start, NULL); switch (i) @@ -53,6 +53,7 @@ main(void) case 0: rk[0] = nmod_sparse_mat_nullspace_rref(X, A); break; case 1: rk[1] = nmod_sparse_mat_nullspace_lu(X, A); break; case 2: rk[2] = nmod_sparse_mat_nullspace_lanczos(X, A, state, 2); break; + case 3: rk[3] = nmod_sparse_mat_nullspace_wiedemann(X, A, state, 2); break; } gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); @@ -69,10 +70,14 @@ main(void) nmod_mat_print_pretty(X); abort(); } - if (i == 2 && rk[i] != rk[i-1]) + if (i == 2 && rk[i] != rk[0]) { lanczos_discrep += 1; } + if (i == 3 && rk[i] != rk[0]) + { + wied_discrep += 1; + } nmod_mat_clear(X); nmod_mat_clear(AX); @@ -85,6 +90,8 @@ main(void) flint_printf("Average time for rref: %lf\n", elapsed[0]/nreps); flint_printf("Average time for LU: %lf\n", elapsed[1]/nreps); flint_printf("Average time for Lanzcos: %lf\n", elapsed[2]/nreps); + flint_printf("Average time for Wiedemann: %lf\n", elapsed[3]/nreps); flint_printf("Lanczos did not find full nullspace for %wd/%wd examples\n", lanczos_discrep, nreps); + flint_printf("Wiedemann did not find full nullspace for %wd/%wd examples\n", lanczos_discrep, nreps); return 0; } diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 6a72dc3870..3315828a40 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -22,31 +22,33 @@ int main(void) { int iter, ret; - int niters = 0, nosol = 0, psolved = 0; - slong rep, r, c, i; + int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + slong rep, r, c, i, nrep = 100; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, At; mp_ptr x, x2, b, Atb, Ax, AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("solving Ax=b...."); fflush(stdout); - for (rep = 0; rep < 100; rep++) + for (rep = 0; rep < nrep; rep++) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - r = n_randint(state, 400); - c = n_randint(state, 400); + + do c = r = n_randint(state, 200); + while(c == 0 || r == 0); + do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(At, c, r, mod); - nmod_sparse_mat_randtest(A, state, c/20, c/10); + nmod_sparse_mat_randtest(A, state, 30, 30); nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); @@ -84,29 +86,50 @@ main(void) /* Solve iteratively */ gettimeofday(&start, NULL); - for (iter=1; iter<=10; ++iter) /* TODO: set number of trials based on params */ - if (ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state)) break; + ret=nmod_sparse_mat_solve_wiedemann(x2, A, b); gettimeofday(&end, NULL); - lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) + { + wied_nosol += 1; + } + else + { + nmod_sparse_mat_mul_vec(Ax, A, x2); + if (!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b\n"); + abort(); + } + } - if (iter==11) + gettimeofday(&start, NULL); + iter = 0; + do ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state); + while(ret==0 && ++iter < 30); + gettimeofday(&end, NULL); + lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) { nosol += 1; continue; } - niters += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) + else { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); - abort(); - } - else if (!_nmod_vec_equal(b, Ax, A->r)) - { - psolved += 1; - } + niters += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_nmod_vec_equal(b, Ax, A->r)) + { + psolved += 1; + } + } flint_free(x); flint_free(x2); @@ -120,9 +143,11 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/1000); - flint_printf("Average time for LU: %lf\n", lu_elapsed/1000); - flint_printf("Average time for rref: %lf\n", rref_elapsed/1000); - flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f iters per solution.\n", nosol, 1000, psolved, 1000, niters/1000.); + flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); + flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); + flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); + flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); + flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); return 0; } From 2cb2ea826370c2934fa13af86df0830b4165de41 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 7 Apr 2020 21:46:34 -0700 Subject: [PATCH 15/42] Created sparse vector and matrix utilities for all the fq variants --- CMakeLists.txt | 4 +- fq_mat/addmul.c | 22 ++ fq_mat/mul_vec.c | 22 ++ fq_mat/scalar_addmul.c | 22 ++ fq_mat/scalar_mul.c | 22 ++ fq_mat/scalar_submul.c | 22 ++ fq_mat/transpose.c | 22 ++ fq_mat_templates.h | 33 ++ fq_mat_templates/addmul.c | 32 ++ fq_mat_templates/mul_vec.c | 27 ++ fq_mat_templates/scalar_addmul.c | 33 ++ fq_mat_templates/scalar_mul.c | 31 ++ fq_mat_templates/scalar_submul.c | 33 ++ fq_mat_templates/transpose.c | 53 +++ fq_nmod_mat/addmul.c | 22 ++ fq_nmod_mat/mul_vec.c | 22 ++ fq_nmod_mat/scalar_addmul.c | 22 ++ fq_nmod_mat/scalar_mul.c | 22 ++ fq_nmod_mat/scalar_submul.c | 22 ++ fq_nmod_mat/transpose.c | 22 ++ fq_nmod_sparse_mat.h | 35 ++ fq_nmod_sparse_mat/from_entries.c | 22 ++ fq_nmod_sparse_mat/inv.c | 23 ++ fq_nmod_sparse_mat/lu.c | 23 ++ fq_nmod_sparse_mat/nullspace_lanczos.c | 23 ++ fq_nmod_sparse_mat/nullspace_lu.c | 23 ++ fq_nmod_sparse_mat/nullspace_rref.c | 23 ++ fq_nmod_sparse_mat/nullspace_wiedemann.c | 23 ++ fq_nmod_sparse_mat/print_pretty.c | 23 ++ fq_nmod_sparse_mat/randtest.c | 23 ++ fq_nmod_sparse_mat/rref.c | 23 ++ fq_nmod_sparse_mat/solve_block_lanczos.c | 28 ++ fq_nmod_sparse_mat/solve_block_wiedemann.c | 23 ++ fq_nmod_sparse_mat/solve_lanczos.c | 22 ++ fq_nmod_sparse_mat/solve_lu.c | 22 ++ fq_nmod_sparse_mat/solve_rref.c | 22 ++ fq_nmod_sparse_mat/solve_wiedemann.c | 22 ++ fq_nmod_sparse_mat/test/t-add.c | 22 ++ fq_nmod_sparse_mat/test/t-concat_horizontal.c | 22 ++ fq_nmod_sparse_mat/test/t-concat_vertical.c | 22 ++ fq_nmod_sparse_mat/test/t-construct.c | 22 ++ fq_nmod_sparse_mat/test/t-dense.c | 22 ++ fq_nmod_sparse_mat/test/t-init_clear.c | 22 ++ fq_nmod_sparse_mat/test/t-inv.c | 22 ++ fq_nmod_sparse_mat/test/t-lu.c | 22 ++ fq_nmod_sparse_mat/test/t-mul.c | 22 ++ fq_nmod_sparse_mat/test/t-neg.c | 22 ++ fq_nmod_sparse_mat/test/t-nullspace.c | 22 ++ fq_nmod_sparse_mat/test/t-rref.c | 22 ++ fq_nmod_sparse_mat/test/t-scalar_mul.c | 22 ++ fq_nmod_sparse_mat/test/t-solve.c | 22 ++ fq_nmod_sparse_mat/test/t-transpose.c | 22 ++ fq_nmod_sparse_mat/transpose.c | 22 ++ fq_nmod_sparse_mat/window_init.c | 23 ++ fq_nmod_sparse_vec.h | 32 ++ fq_nmod_sparse_vec/add.c | 22 ++ fq_nmod_sparse_vec/print_pretty.c | 23 ++ fq_nmod_sparse_vec/randtest.c | 23 ++ fq_nmod_sparse_vec/scalar_addmul.c | 22 ++ fq_nmod_sparse_vec/sub.c | 23 ++ fq_nmod_sparse_vec/test/t-add.c | 21 + fq_nmod_sparse_vec/test/t-concat.c | 22 ++ fq_nmod_sparse_vec/test/t-construct.c | 22 ++ fq_nmod_sparse_vec/test/t-dense.c | 22 ++ fq_nmod_sparse_vec/test/t-dot.c | 22 ++ fq_nmod_sparse_vec/test/t-init_clear.c | 22 ++ fq_nmod_sparse_vec/test/t-neg.c | 23 ++ fq_nmod_sparse_vec/test/t-scalar_mul.c | 23 ++ fq_sparse_mat.h | 35 ++ fq_sparse_mat/from_entries.c | 30 ++ fq_sparse_mat/inv.c | 23 ++ fq_sparse_mat/lu.c | 23 ++ fq_sparse_mat/nullspace_lanczos.c | 23 ++ fq_sparse_mat/nullspace_lu.c | 23 ++ fq_sparse_mat/nullspace_rref.c | 23 ++ fq_sparse_mat/nullspace_wiedemann.c | 23 ++ fq_sparse_mat/print_pretty.c | 23 ++ fq_sparse_mat/randtest.c | 23 ++ fq_sparse_mat/rref.c | 23 ++ fq_sparse_mat/solve_block_lanczos.c | 28 ++ fq_sparse_mat/solve_block_wiedemann.c | 23 ++ fq_sparse_mat/solve_lanczos.c | 22 ++ fq_sparse_mat/solve_lu.c | 22 ++ fq_sparse_mat/solve_rref.c | 22 ++ fq_sparse_mat/solve_wiedemann.c | 22 ++ fq_sparse_mat/test/t-add.c | 22 ++ fq_sparse_mat/test/t-concat_horizontal.c | 22 ++ fq_sparse_mat/test/t-concat_vertical.c | 22 ++ fq_sparse_mat/test/t-construct.c | 22 ++ fq_sparse_mat/test/t-dense.c | 22 ++ fq_sparse_mat/test/t-init_clear.c | 22 ++ fq_sparse_mat/test/t-inv.c | 22 ++ fq_sparse_mat/test/t-lu.c | 22 ++ fq_sparse_mat/test/t-mul.c | 22 ++ fq_sparse_mat/test/t-neg.c | 22 ++ fq_sparse_mat/test/t-nullspace.c | 22 ++ fq_sparse_mat/test/t-rref.c | 22 ++ fq_sparse_mat/test/t-scalar_mul.c | 22 ++ fq_sparse_mat/test/t-solve.c | 22 ++ fq_sparse_mat/test/t-transpose.c | 22 ++ fq_sparse_mat/transpose.c | 22 ++ fq_sparse_mat/window_init.c | 23 ++ fq_sparse_mat_templates.h | 371 ++++++++++++++++++ fq_sparse_mat_templates/from_entries.c | 36 ++ fq_sparse_mat_templates/inv.c | 40 ++ fq_sparse_mat_templates/lu.c | 179 +++++++++ fq_sparse_mat_templates/nullspace_lanczos.c | 78 ++++ fq_sparse_mat_templates/nullspace_lu.c | 69 ++++ fq_sparse_mat_templates/nullspace_rref.c | 53 +++ fq_sparse_mat_templates/nullspace_wiedemann.c | 79 ++++ fq_sparse_mat_templates/print_pretty.c | 35 ++ fq_sparse_mat_templates/randtest.c | 30 ++ fq_sparse_mat_templates/rref.c | 94 +++++ fq_sparse_mat_templates/solve_block_lanczos.c | 246 ++++++++++++ .../solve_block_wiedemann.c | 266 +++++++++++++ fq_sparse_mat_templates/solve_lanczos.c | 125 ++++++ fq_sparse_mat_templates/solve_lu.c | 75 ++++ fq_sparse_mat_templates/solve_rref.c | 53 +++ fq_sparse_mat_templates/solve_wiedemann.c | 182 +++++++++ fq_sparse_mat_templates/test/t-add.c | 67 ++++ .../test/t-concat_horizontal.c | 105 +++++ .../test/t-concat_vertical.c | 98 +++++ fq_sparse_mat_templates/test/t-construct.c | 98 +++++ fq_sparse_mat_templates/test/t-dense.c | 75 ++++ fq_sparse_mat_templates/test/t-init_clear.c | 63 +++ fq_sparse_mat_templates/test/t-inv.c | 74 ++++ fq_sparse_mat_templates/test/t-lu.c | 126 ++++++ fq_sparse_mat_templates/test/t-mul.c | 89 +++++ fq_sparse_mat_templates/test/t-neg.c | 77 ++++ fq_sparse_mat_templates/test/t-nullspace.c | 97 +++++ fq_sparse_mat_templates/test/t-rref.c | 64 +++ fq_sparse_mat_templates/test/t-scalar_mul.c | 86 ++++ fq_sparse_mat_templates/test/t-solve.c | 153 ++++++++ fq_sparse_mat_templates/test/t-transpose.c | 67 ++++ fq_sparse_mat_templates/tmp | 31 ++ fq_sparse_mat_templates/transpose.c | 61 +++ fq_sparse_mat_templates/window_init.c | 31 ++ fq_sparse_vec.h | 33 ++ fq_sparse_vec/add.c | 22 ++ fq_sparse_vec/print_pretty.c | 23 ++ fq_sparse_vec/randtest.c | 23 ++ fq_sparse_vec/scalar_addmul.c | 22 ++ fq_sparse_vec/sub.c | 23 ++ fq_sparse_vec/test/t-add.c | 21 + fq_sparse_vec/test/t-concat.c | 22 ++ fq_sparse_vec/test/t-construct.c | 22 ++ fq_sparse_vec/test/t-dense.c | 22 ++ fq_sparse_vec/test/t-dot.c | 22 ++ fq_sparse_vec/test/t-init_clear.c | 22 ++ fq_sparse_vec/test/t-neg.c | 23 ++ fq_sparse_vec/test/t-scalar_mul.c | 23 ++ fq_sparse_vec_templates.h | 371 ++++++++++++++++++ fq_sparse_vec_templates/add.c | 56 +++ fq_sparse_vec_templates/print_pretty.c | 37 ++ fq_sparse_vec_templates/randtest.c | 35 ++ fq_sparse_vec_templates/scalar_addmul.c | 59 +++ fq_sparse_vec_templates/sub.c | 55 +++ fq_sparse_vec_templates/test/t-add.c | 81 ++++ fq_sparse_vec_templates/test/t-concat.c | 102 +++++ fq_sparse_vec_templates/test/t-construct.c | 77 ++++ fq_sparse_vec_templates/test/t-dense.c | 87 ++++ fq_sparse_vec_templates/test/t-dot.c | 84 ++++ fq_sparse_vec_templates/test/t-init_clear.c | 93 +++++ fq_sparse_vec_templates/test/t-neg.c | 76 ++++ fq_sparse_vec_templates/test/t-scalar_mul.c | 90 +++++ fq_vec_templates.h | 14 + fq_zech_mat/addmul.c | 22 ++ fq_zech_mat/mul_vec.c | 22 ++ fq_zech_mat/scalar_addmul.c | 22 ++ fq_zech_mat/scalar_mul.c | 22 ++ fq_zech_mat/scalar_submul.c | 22 ++ fq_zech_mat/transpose.c | 22 ++ fq_zech_sparse_mat.h | 35 ++ fq_zech_sparse_mat/from_entries.c | 22 ++ fq_zech_sparse_mat/inv.c | 23 ++ fq_zech_sparse_mat/lu.c | 23 ++ fq_zech_sparse_mat/nullspace_lanczos.c | 23 ++ fq_zech_sparse_mat/nullspace_lu.c | 23 ++ fq_zech_sparse_mat/nullspace_rref.c | 23 ++ fq_zech_sparse_mat/nullspace_wiedemann.c | 23 ++ fq_zech_sparse_mat/print_pretty.c | 23 ++ fq_zech_sparse_mat/randtest.c | 23 ++ fq_zech_sparse_mat/rref.c | 23 ++ fq_zech_sparse_mat/solve_block_lanczos.c | 28 ++ fq_zech_sparse_mat/solve_block_wiedemann.c | 23 ++ fq_zech_sparse_mat/solve_lanczos.c | 22 ++ fq_zech_sparse_mat/solve_lu.c | 22 ++ fq_zech_sparse_mat/solve_rref.c | 22 ++ fq_zech_sparse_mat/solve_wiedemann.c | 22 ++ fq_zech_sparse_mat/test/t-add.c | 22 ++ fq_zech_sparse_mat/test/t-concat_horizontal.c | 22 ++ fq_zech_sparse_mat/test/t-concat_vertical.c | 22 ++ fq_zech_sparse_mat/test/t-construct.c | 22 ++ fq_zech_sparse_mat/test/t-dense.c | 22 ++ fq_zech_sparse_mat/test/t-init_clear.c | 22 ++ fq_zech_sparse_mat/test/t-inv.c | 22 ++ fq_zech_sparse_mat/test/t-lu.c | 22 ++ fq_zech_sparse_mat/test/t-mul.c | 22 ++ fq_zech_sparse_mat/test/t-neg.c | 22 ++ fq_zech_sparse_mat/test/t-nullspace.c | 22 ++ fq_zech_sparse_mat/test/t-rref.c | 22 ++ fq_zech_sparse_mat/test/t-scalar_mul.c | 22 ++ fq_zech_sparse_mat/test/t-solve.c | 22 ++ fq_zech_sparse_mat/test/t-transpose.c | 22 ++ fq_zech_sparse_mat/transpose.c | 22 ++ fq_zech_sparse_mat/window_init.c | 23 ++ fq_zech_sparse_vec.h | 32 ++ fq_zech_sparse_vec/add.c | 22 ++ fq_zech_sparse_vec/print_pretty.c | 23 ++ fq_zech_sparse_vec/randtest.c | 23 ++ fq_zech_sparse_vec/scalar_addmul.c | 22 ++ fq_zech_sparse_vec/sub.c | 23 ++ fq_zech_sparse_vec/test/t-add.c | 21 + fq_zech_sparse_vec/test/t-concat.c | 22 ++ fq_zech_sparse_vec/test/t-construct.c | 22 ++ fq_zech_sparse_vec/test/t-dense.c | 22 ++ fq_zech_sparse_vec/test/t-dot.c | 22 ++ fq_zech_sparse_vec/test/t-init_clear.c | 22 ++ fq_zech_sparse_vec/test/t-neg.c | 23 ++ fq_zech_sparse_vec/test/t-scalar_mul.c | 23 ++ nmod_mat.h | 2 +- nmod_sparse_mat.h | 281 ++++++------- nmod_sparse_mat/from_entries.c | 8 +- nmod_sparse_mat/inv.c | 22 +- nmod_sparse_mat/lu.c | 66 ++-- nmod_sparse_mat/nullspace_lanczos.c | 22 +- nmod_sparse_mat/nullspace_lu.c | 30 +- nmod_sparse_mat/nullspace_rref.c | 16 +- nmod_sparse_mat/nullspace_wiedemann.c | 22 +- nmod_sparse_mat/print_pretty.c | 10 +- nmod_sparse_mat/randtest.c | 6 +- nmod_sparse_mat/rref.c | 50 +-- nmod_sparse_mat/solve_block_lanczos.c | 239 +++++++++++ nmod_sparse_mat/solve_block_wiedemann.c | 247 ++++++++++++ nmod_sparse_mat/solve_lanczos.c | 107 ++--- nmod_sparse_mat/solve_lu.c | 30 +- nmod_sparse_mat/solve_rref.c | 30 +- 237 files changed, 9576 insertions(+), 353 deletions(-) create mode 100644 fq_mat/addmul.c create mode 100644 fq_mat/mul_vec.c create mode 100644 fq_mat/scalar_addmul.c create mode 100644 fq_mat/scalar_mul.c create mode 100644 fq_mat/scalar_submul.c create mode 100644 fq_mat/transpose.c create mode 100644 fq_mat_templates/addmul.c create mode 100644 fq_mat_templates/mul_vec.c create mode 100644 fq_mat_templates/scalar_addmul.c create mode 100644 fq_mat_templates/scalar_mul.c create mode 100644 fq_mat_templates/scalar_submul.c create mode 100644 fq_mat_templates/transpose.c create mode 100644 fq_nmod_mat/addmul.c create mode 100644 fq_nmod_mat/mul_vec.c create mode 100644 fq_nmod_mat/scalar_addmul.c create mode 100644 fq_nmod_mat/scalar_mul.c create mode 100644 fq_nmod_mat/scalar_submul.c create mode 100644 fq_nmod_mat/transpose.c create mode 100644 fq_nmod_sparse_mat.h create mode 100644 fq_nmod_sparse_mat/from_entries.c create mode 100644 fq_nmod_sparse_mat/inv.c create mode 100644 fq_nmod_sparse_mat/lu.c create mode 100644 fq_nmod_sparse_mat/nullspace_lanczos.c create mode 100644 fq_nmod_sparse_mat/nullspace_lu.c create mode 100644 fq_nmod_sparse_mat/nullspace_rref.c create mode 100644 fq_nmod_sparse_mat/nullspace_wiedemann.c create mode 100644 fq_nmod_sparse_mat/print_pretty.c create mode 100644 fq_nmod_sparse_mat/randtest.c create mode 100644 fq_nmod_sparse_mat/rref.c create mode 100644 fq_nmod_sparse_mat/solve_block_lanczos.c create mode 100644 fq_nmod_sparse_mat/solve_block_wiedemann.c create mode 100644 fq_nmod_sparse_mat/solve_lanczos.c create mode 100644 fq_nmod_sparse_mat/solve_lu.c create mode 100644 fq_nmod_sparse_mat/solve_rref.c create mode 100644 fq_nmod_sparse_mat/solve_wiedemann.c create mode 100644 fq_nmod_sparse_mat/test/t-add.c create mode 100644 fq_nmod_sparse_mat/test/t-concat_horizontal.c create mode 100644 fq_nmod_sparse_mat/test/t-concat_vertical.c create mode 100644 fq_nmod_sparse_mat/test/t-construct.c create mode 100644 fq_nmod_sparse_mat/test/t-dense.c create mode 100644 fq_nmod_sparse_mat/test/t-init_clear.c create mode 100644 fq_nmod_sparse_mat/test/t-inv.c create mode 100644 fq_nmod_sparse_mat/test/t-lu.c create mode 100644 fq_nmod_sparse_mat/test/t-mul.c create mode 100644 fq_nmod_sparse_mat/test/t-neg.c create mode 100644 fq_nmod_sparse_mat/test/t-nullspace.c create mode 100644 fq_nmod_sparse_mat/test/t-rref.c create mode 100644 fq_nmod_sparse_mat/test/t-scalar_mul.c create mode 100644 fq_nmod_sparse_mat/test/t-solve.c create mode 100644 fq_nmod_sparse_mat/test/t-transpose.c create mode 100644 fq_nmod_sparse_mat/transpose.c create mode 100644 fq_nmod_sparse_mat/window_init.c create mode 100644 fq_nmod_sparse_vec.h create mode 100644 fq_nmod_sparse_vec/add.c create mode 100644 fq_nmod_sparse_vec/print_pretty.c create mode 100644 fq_nmod_sparse_vec/randtest.c create mode 100644 fq_nmod_sparse_vec/scalar_addmul.c create mode 100644 fq_nmod_sparse_vec/sub.c create mode 100644 fq_nmod_sparse_vec/test/t-add.c create mode 100644 fq_nmod_sparse_vec/test/t-concat.c create mode 100644 fq_nmod_sparse_vec/test/t-construct.c create mode 100644 fq_nmod_sparse_vec/test/t-dense.c create mode 100644 fq_nmod_sparse_vec/test/t-dot.c create mode 100644 fq_nmod_sparse_vec/test/t-init_clear.c create mode 100644 fq_nmod_sparse_vec/test/t-neg.c create mode 100644 fq_nmod_sparse_vec/test/t-scalar_mul.c create mode 100644 fq_sparse_mat.h create mode 100644 fq_sparse_mat/from_entries.c create mode 100644 fq_sparse_mat/inv.c create mode 100644 fq_sparse_mat/lu.c create mode 100644 fq_sparse_mat/nullspace_lanczos.c create mode 100644 fq_sparse_mat/nullspace_lu.c create mode 100644 fq_sparse_mat/nullspace_rref.c create mode 100644 fq_sparse_mat/nullspace_wiedemann.c create mode 100644 fq_sparse_mat/print_pretty.c create mode 100644 fq_sparse_mat/randtest.c create mode 100644 fq_sparse_mat/rref.c create mode 100644 fq_sparse_mat/solve_block_lanczos.c create mode 100644 fq_sparse_mat/solve_block_wiedemann.c create mode 100644 fq_sparse_mat/solve_lanczos.c create mode 100644 fq_sparse_mat/solve_lu.c create mode 100644 fq_sparse_mat/solve_rref.c create mode 100644 fq_sparse_mat/solve_wiedemann.c create mode 100644 fq_sparse_mat/test/t-add.c create mode 100644 fq_sparse_mat/test/t-concat_horizontal.c create mode 100644 fq_sparse_mat/test/t-concat_vertical.c create mode 100644 fq_sparse_mat/test/t-construct.c create mode 100644 fq_sparse_mat/test/t-dense.c create mode 100644 fq_sparse_mat/test/t-init_clear.c create mode 100644 fq_sparse_mat/test/t-inv.c create mode 100644 fq_sparse_mat/test/t-lu.c create mode 100644 fq_sparse_mat/test/t-mul.c create mode 100644 fq_sparse_mat/test/t-neg.c create mode 100644 fq_sparse_mat/test/t-nullspace.c create mode 100644 fq_sparse_mat/test/t-rref.c create mode 100644 fq_sparse_mat/test/t-scalar_mul.c create mode 100644 fq_sparse_mat/test/t-solve.c create mode 100644 fq_sparse_mat/test/t-transpose.c create mode 100644 fq_sparse_mat/transpose.c create mode 100644 fq_sparse_mat/window_init.c create mode 100644 fq_sparse_mat_templates.h create mode 100644 fq_sparse_mat_templates/from_entries.c create mode 100644 fq_sparse_mat_templates/inv.c create mode 100644 fq_sparse_mat_templates/lu.c create mode 100644 fq_sparse_mat_templates/nullspace_lanczos.c create mode 100644 fq_sparse_mat_templates/nullspace_lu.c create mode 100644 fq_sparse_mat_templates/nullspace_rref.c create mode 100644 fq_sparse_mat_templates/nullspace_wiedemann.c create mode 100644 fq_sparse_mat_templates/print_pretty.c create mode 100644 fq_sparse_mat_templates/randtest.c create mode 100644 fq_sparse_mat_templates/rref.c create mode 100644 fq_sparse_mat_templates/solve_block_lanczos.c create mode 100644 fq_sparse_mat_templates/solve_block_wiedemann.c create mode 100644 fq_sparse_mat_templates/solve_lanczos.c create mode 100644 fq_sparse_mat_templates/solve_lu.c create mode 100644 fq_sparse_mat_templates/solve_rref.c create mode 100644 fq_sparse_mat_templates/solve_wiedemann.c create mode 100644 fq_sparse_mat_templates/test/t-add.c create mode 100644 fq_sparse_mat_templates/test/t-concat_horizontal.c create mode 100644 fq_sparse_mat_templates/test/t-concat_vertical.c create mode 100644 fq_sparse_mat_templates/test/t-construct.c create mode 100644 fq_sparse_mat_templates/test/t-dense.c create mode 100644 fq_sparse_mat_templates/test/t-init_clear.c create mode 100644 fq_sparse_mat_templates/test/t-inv.c create mode 100644 fq_sparse_mat_templates/test/t-lu.c create mode 100644 fq_sparse_mat_templates/test/t-mul.c create mode 100644 fq_sparse_mat_templates/test/t-neg.c create mode 100644 fq_sparse_mat_templates/test/t-nullspace.c create mode 100644 fq_sparse_mat_templates/test/t-rref.c create mode 100644 fq_sparse_mat_templates/test/t-scalar_mul.c create mode 100644 fq_sparse_mat_templates/test/t-solve.c create mode 100644 fq_sparse_mat_templates/test/t-transpose.c create mode 100644 fq_sparse_mat_templates/tmp create mode 100644 fq_sparse_mat_templates/transpose.c create mode 100644 fq_sparse_mat_templates/window_init.c create mode 100644 fq_sparse_vec.h create mode 100644 fq_sparse_vec/add.c create mode 100644 fq_sparse_vec/print_pretty.c create mode 100644 fq_sparse_vec/randtest.c create mode 100644 fq_sparse_vec/scalar_addmul.c create mode 100644 fq_sparse_vec/sub.c create mode 100644 fq_sparse_vec/test/t-add.c create mode 100644 fq_sparse_vec/test/t-concat.c create mode 100644 fq_sparse_vec/test/t-construct.c create mode 100644 fq_sparse_vec/test/t-dense.c create mode 100644 fq_sparse_vec/test/t-dot.c create mode 100644 fq_sparse_vec/test/t-init_clear.c create mode 100644 fq_sparse_vec/test/t-neg.c create mode 100644 fq_sparse_vec/test/t-scalar_mul.c create mode 100644 fq_sparse_vec_templates.h create mode 100644 fq_sparse_vec_templates/add.c create mode 100644 fq_sparse_vec_templates/print_pretty.c create mode 100644 fq_sparse_vec_templates/randtest.c create mode 100644 fq_sparse_vec_templates/scalar_addmul.c create mode 100644 fq_sparse_vec_templates/sub.c create mode 100644 fq_sparse_vec_templates/test/t-add.c create mode 100644 fq_sparse_vec_templates/test/t-concat.c create mode 100644 fq_sparse_vec_templates/test/t-construct.c create mode 100644 fq_sparse_vec_templates/test/t-dense.c create mode 100644 fq_sparse_vec_templates/test/t-dot.c create mode 100644 fq_sparse_vec_templates/test/t-init_clear.c create mode 100644 fq_sparse_vec_templates/test/t-neg.c create mode 100644 fq_sparse_vec_templates/test/t-scalar_mul.c create mode 100644 fq_zech_mat/addmul.c create mode 100644 fq_zech_mat/mul_vec.c create mode 100644 fq_zech_mat/scalar_addmul.c create mode 100644 fq_zech_mat/scalar_mul.c create mode 100644 fq_zech_mat/scalar_submul.c create mode 100644 fq_zech_mat/transpose.c create mode 100644 fq_zech_sparse_mat.h create mode 100644 fq_zech_sparse_mat/from_entries.c create mode 100644 fq_zech_sparse_mat/inv.c create mode 100644 fq_zech_sparse_mat/lu.c create mode 100644 fq_zech_sparse_mat/nullspace_lanczos.c create mode 100644 fq_zech_sparse_mat/nullspace_lu.c create mode 100644 fq_zech_sparse_mat/nullspace_rref.c create mode 100644 fq_zech_sparse_mat/nullspace_wiedemann.c create mode 100644 fq_zech_sparse_mat/print_pretty.c create mode 100644 fq_zech_sparse_mat/randtest.c create mode 100644 fq_zech_sparse_mat/rref.c create mode 100644 fq_zech_sparse_mat/solve_block_lanczos.c create mode 100644 fq_zech_sparse_mat/solve_block_wiedemann.c create mode 100644 fq_zech_sparse_mat/solve_lanczos.c create mode 100644 fq_zech_sparse_mat/solve_lu.c create mode 100644 fq_zech_sparse_mat/solve_rref.c create mode 100644 fq_zech_sparse_mat/solve_wiedemann.c create mode 100644 fq_zech_sparse_mat/test/t-add.c create mode 100644 fq_zech_sparse_mat/test/t-concat_horizontal.c create mode 100644 fq_zech_sparse_mat/test/t-concat_vertical.c create mode 100644 fq_zech_sparse_mat/test/t-construct.c create mode 100644 fq_zech_sparse_mat/test/t-dense.c create mode 100644 fq_zech_sparse_mat/test/t-init_clear.c create mode 100644 fq_zech_sparse_mat/test/t-inv.c create mode 100644 fq_zech_sparse_mat/test/t-lu.c create mode 100644 fq_zech_sparse_mat/test/t-mul.c create mode 100644 fq_zech_sparse_mat/test/t-neg.c create mode 100644 fq_zech_sparse_mat/test/t-nullspace.c create mode 100644 fq_zech_sparse_mat/test/t-rref.c create mode 100644 fq_zech_sparse_mat/test/t-scalar_mul.c create mode 100644 fq_zech_sparse_mat/test/t-solve.c create mode 100644 fq_zech_sparse_mat/test/t-transpose.c create mode 100644 fq_zech_sparse_mat/transpose.c create mode 100644 fq_zech_sparse_mat/window_init.c create mode 100644 fq_zech_sparse_vec.h create mode 100644 fq_zech_sparse_vec/add.c create mode 100644 fq_zech_sparse_vec/print_pretty.c create mode 100644 fq_zech_sparse_vec/randtest.c create mode 100644 fq_zech_sparse_vec/scalar_addmul.c create mode 100644 fq_zech_sparse_vec/sub.c create mode 100644 fq_zech_sparse_vec/test/t-add.c create mode 100644 fq_zech_sparse_vec/test/t-concat.c create mode 100644 fq_zech_sparse_vec/test/t-construct.c create mode 100644 fq_zech_sparse_vec/test/t-dense.c create mode 100644 fq_zech_sparse_vec/test/t-dot.c create mode 100644 fq_zech_sparse_vec/test/t-init_clear.c create mode 100644 fq_zech_sparse_vec/test/t-neg.c create mode 100644 fq_zech_sparse_vec/test/t-scalar_mul.c create mode 100644 nmod_sparse_mat/solve_block_lanczos.c create mode 100644 nmod_sparse_mat/solve_block_wiedemann.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e7813cf80..7f0fd743c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,8 +60,8 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly - nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic + fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly + nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve double_extras d_vec d_mat padic_poly padic_mat qadic diff --git a/fq_mat/addmul.c b/fq_mat/addmul.c new file mode 100644 index 0000000000..f2c0cf8b8e --- /dev/null +++ b/fq_mat/addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/addmul.c" +#undef CAP_T +#undef T diff --git a/fq_mat/mul_vec.c b/fq_mat/mul_vec.c new file mode 100644 index 0000000000..5927e18dff --- /dev/null +++ b/fq_mat/mul_vec.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/mul_vec.c" +#undef CAP_T +#undef T diff --git a/fq_mat/scalar_addmul.c b/fq_mat/scalar_addmul.c new file mode 100644 index 0000000000..7375dbb9a9 --- /dev/null +++ b/fq_mat/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_mat/scalar_mul.c b/fq_mat/scalar_mul.c new file mode 100644 index 0000000000..ba7f8885d9 --- /dev/null +++ b/fq_mat/scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_mat/scalar_submul.c b/fq_mat/scalar_submul.c new file mode 100644 index 0000000000..6aad2e4767 --- /dev/null +++ b/fq_mat/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/fq_mat/transpose.c b/fq_mat/transpose.c new file mode 100644 index 0000000000..4c8f61aef0 --- /dev/null +++ b/fq_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_mat_templates.h b/fq_mat_templates.h index 4454e4966f..718f1be7de 100644 --- a/fq_mat_templates.h +++ b/fq_mat_templates.h @@ -274,6 +274,10 @@ FLINT_DLL void TEMPLATE(T, mat_randtriu)(TEMPLATE(T, mat_t) mat, flint_rand_t st /* Transpose */ +FLINT_DLL void TEMPLATE(T, mat_transpose)(TEMPLATE(T, mat_t) B, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, ctx_t) ctx); + /* Addition and subtraction */ FLINT_DLL void TEMPLATE(T, mat_add)(TEMPLATE(T, mat_t) C, @@ -290,6 +294,12 @@ FLINT_DLL void TEMPLATE(T, mat_neg)(TEMPLATE(T, mat_t) B, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, ctx_t) ctx); +FLINT_DLL void TEMPLATE(T, mat_addmul)(TEMPLATE(T, mat_t) D, + const TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, ctx_t) ctx); + FLINT_DLL void TEMPLATE(T, mat_submul)(TEMPLATE(T, mat_t) D, const TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, @@ -298,6 +308,24 @@ FLINT_DLL void TEMPLATE(T, mat_submul)(TEMPLATE(T, mat_t) D, /* Scalar operations */ +FLINT_DLL void TEMPLATE(T, mat_scalar_mul)(TEMPLATE(T, mat_t) B, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL void TEMPLATE(T, mat_scalar_addmul)(TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL void TEMPLATE(T, mat_scalar_submul)(TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx); + + /* Multiplication */ FLINT_DLL void TEMPLATE(T, mat_mul)(TEMPLATE(T, mat_t) C, @@ -305,6 +333,11 @@ FLINT_DLL void TEMPLATE(T, mat_mul)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx); +FLINT_DLL void TEMPLATE(T, mat_mul_vec)(TEMPLATE(T, struct) *y, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, struct) *x, + const TEMPLATE(T, ctx_t) ctx); + FLINT_DLL void TEMPLATE(T, mat_mul_classical)(TEMPLATE(T, mat_t) C, const TEMPLATE(T, mat_t) A, const TEMPLATE(T, mat_t) B, diff --git a/fq_mat_templates/addmul.c b/fq_mat_templates/addmul.c new file mode 100644 index 0000000000..509a15d34e --- /dev/null +++ b/fq_mat_templates/addmul.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_addmul) (TEMPLATE(T, mat_t) D, + const TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, ctx_t) ctx) +{ + TEMPLATE(T, mat_t) tmp; + TEMPLATE(T, mat_init) (tmp, A->r, B->c, ctx); + TEMPLATE(T, mat_mul) (tmp, A, B, ctx); + TEMPLATE(T, mat_add) (D, C, tmp, ctx); + TEMPLATE(T, mat_clear) (tmp, ctx); +} + + +#endif diff --git a/fq_mat_templates/mul_vec.c b/fq_mat_templates/mul_vec.c new file mode 100644 index 0000000000..bf67f08c7c --- /dev/null +++ b/fq_mat_templates/mul_vec.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_mul_vec) (TEMPLATE(T, struct) *y, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, struct) *x, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i = 0; i < A->r; ++i) + _TEMPLATE(T, vec_dot) (&y[i], A->rows[i], x, A->c, ctx); +} + + +#endif diff --git a/fq_mat_templates/scalar_addmul.c b/fq_mat_templates/scalar_addmul.c new file mode 100644 index 0000000000..f8502a9f9a --- /dev/null +++ b/fq_mat_templates/scalar_addmul.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_scalar_addmul) (TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i = 0; i < C->r; i++) + { + _TEMPLATE(T, vec_set) (C->rows[i], A->rows[i], A->c, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (C->rows[i], B->rows[i], A->c, c, ctx); + } +} + + +#endif diff --git a/fq_mat_templates/scalar_mul.c b/fq_mat_templates/scalar_mul.c new file mode 100644 index 0000000000..37f35cb14b --- /dev/null +++ b/fq_mat_templates/scalar_mul.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_scalar_mul) (TEMPLATE(T, mat_t) B, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i = 0; i < B->r; i++) + { + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (B->rows[i], A->rows[i], A->c, c, ctx); + } +} + + +#endif diff --git a/fq_mat_templates/scalar_submul.c b/fq_mat_templates/scalar_submul.c new file mode 100644 index 0000000000..ac8acd02dd --- /dev/null +++ b/fq_mat_templates/scalar_submul.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_scalar_submul) (TEMPLATE(T, mat_t) C, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, mat_t) B, + const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i = 0; i < C->r; i++) + { + _TEMPLATE(T, vec_set) (C->rows[i], A->rows[i], A->c, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_submul, T)) (C->rows[i], B->rows[i], A->c, c, ctx); + } +} + + +#endif diff --git a/fq_mat_templates/transpose.c b/fq_mat_templates/transpose.c new file mode 100644 index 0000000000..9949348e23 --- /dev/null +++ b/fq_mat_templates/transpose.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, mat_transpose) (TEMPLATE(T, mat_t) B, + const TEMPLATE(T, mat_t) A, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j; + TEMPLATE(T, t) tmp; + + if (A == B) + { + TEMPLATE(T, init) (tmp, ctx); + for (i = 0; i < A->r; ++i) + { + for (j = i+1; j < A->c; ++j) + { + TEMPLATE(T, set) (tmp, &A->rows[i][j], ctx); + TEMPLATE(T, set) (&B->rows[i][j], &A->rows[j][i], ctx); + TEMPLATE(T, set) (&B->rows[j][i], tmp, ctx); + } + } + TEMPLATE(T, clear) (tmp, ctx); + } + else + { + for (i = 0; i < A->r; ++i) + { + for (j = 0; j < A->c; ++j) + { + TEMPLATE(T, set) (&B->rows[j][i], &A->rows[i][j], ctx); + } + } + } + +} + + +#endif diff --git a/fq_nmod_mat/addmul.c b/fq_nmod_mat/addmul.c new file mode 100644 index 0000000000..73dccd5e1f --- /dev/null +++ b/fq_nmod_mat/addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/addmul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_mat/mul_vec.c b/fq_nmod_mat/mul_vec.c new file mode 100644 index 0000000000..4ab0ac9c23 --- /dev/null +++ b/fq_nmod_mat/mul_vec.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/mul_vec.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_mat/scalar_addmul.c b/fq_nmod_mat/scalar_addmul.c new file mode 100644 index 0000000000..3f5de0d064 --- /dev/null +++ b/fq_nmod_mat/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_mat/scalar_mul.c b/fq_nmod_mat/scalar_mul.c new file mode 100644 index 0000000000..e7c41730a7 --- /dev/null +++ b/fq_nmod_mat/scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_mat/scalar_submul.c b/fq_nmod_mat/scalar_submul.c new file mode 100644 index 0000000000..e98442c63e --- /dev/null +++ b/fq_nmod_mat/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_mat/transpose.c b/fq_nmod_mat/transpose.c new file mode 100644 index 0000000000..e50dc6f89a --- /dev/null +++ b/fq_nmod_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat.h b/fq_nmod_sparse_mat.h new file mode 100644 index 0000000000..47643c88e3 --- /dev/null +++ b/fq_nmod_sparse_mat.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_NMOD_SPARSE_MAT_H +#define FQ_NMOD_SPARSE_MAT_H + +#ifdef FQ_NMOD_SPARSE_MAT_INLINES_C +#define FQ_SPARSE_MAT_TEMPLATES_INLINE FLINT_DLL +#define FQ_NMOD_SPARSE_MAT_INLINE FLINT_DLL +#else +#define FQ_SPARSE_MAT_TEMPLATES_INLINE static __inline__ +#define FQ_NMOD_SPARSE_MAT_INLINE static __inline__ +#endif + + +#include "fq_nmod.h" +#include "fq_nmod_vec.h" +#include "fq_nmod_sparse_vec.h" +#include "fq_nmod_mat.h" + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_nmod_sparse_mat/from_entries.c b/fq_nmod_sparse_mat/from_entries.c new file mode 100644 index 0000000000..ca0181ed26 --- /dev/null +++ b/fq_nmod_sparse_mat/from_entries.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/from_entries.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/inv.c b/fq_nmod_sparse_mat/inv.c new file mode 100644 index 0000000000..eb17ddb966 --- /dev/null +++ b/fq_nmod_sparse_mat/inv.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/inv.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/lu.c b/fq_nmod_sparse_mat/lu.c new file mode 100644 index 0000000000..b1dc772bed --- /dev/null +++ b/fq_nmod_sparse_mat/lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/lu.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/nullspace_lanczos.c b/fq_nmod_sparse_mat/nullspace_lanczos.c new file mode 100644 index 0000000000..2d792bfb05 --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/nullspace_lu.c b/fq_nmod_sparse_mat/nullspace_lu.c new file mode 100644 index 0000000000..e2ebf8770c --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_lu.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/nullspace_rref.c b/fq_nmod_sparse_mat/nullspace_rref.c new file mode 100644 index 0000000000..1479456f60 --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_rref.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/nullspace_wiedemann.c b/fq_nmod_sparse_mat/nullspace_wiedemann.c new file mode 100644 index 0000000000..eb92c2dd6e --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/print_pretty.c b/fq_nmod_sparse_mat/print_pretty.c new file mode 100644 index 0000000000..1850340b4f --- /dev/null +++ b/fq_nmod_sparse_mat/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/randtest.c b/fq_nmod_sparse_mat/randtest.c new file mode 100644 index 0000000000..4faa708f4f --- /dev/null +++ b/fq_nmod_sparse_mat/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/rref.c b/fq_nmod_sparse_mat/rref.c new file mode 100644 index 0000000000..d2124c45bd --- /dev/null +++ b/fq_nmod_sparse_mat/rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/rref.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_block_lanczos.c b/fq_nmod_sparse_mat/solve_block_lanczos.c new file mode 100644 index 0000000000..57b0424fe9 --- /dev/null +++ b/fq_nmod_sparse_mat/solve_block_lanczos.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for + Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 + + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_block_wiedemann.c b/fq_nmod_sparse_mat/solve_block_wiedemann.c new file mode 100644 index 0000000000..fdf88b21dc --- /dev/null +++ b/fq_nmod_sparse_mat/solve_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_lanczos.c b/fq_nmod_sparse_mat/solve_lanczos.c new file mode 100644 index 0000000000..5f55f50b77 --- /dev/null +++ b/fq_nmod_sparse_mat/solve_lanczos.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_lu.c b/fq_nmod_sparse_mat/solve_lu.c new file mode 100644 index 0000000000..310d98b1c1 --- /dev/null +++ b/fq_nmod_sparse_mat/solve_lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_lu.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_rref.c b/fq_nmod_sparse_mat/solve_rref.c new file mode 100644 index 0000000000..fc7f6deb37 --- /dev/null +++ b/fq_nmod_sparse_mat/solve_rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_rref.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/solve_wiedemann.c b/fq_nmod_sparse_mat/solve_wiedemann.c new file mode 100644 index 0000000000..3b732c902f --- /dev/null +++ b/fq_nmod_sparse_mat/solve_wiedemann.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/solve_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-add.c b/fq_nmod_sparse_mat/test/t-add.c new file mode 100644 index 0000000000..3e96ab4964 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-concat_horizontal.c b/fq_nmod_sparse_mat/test/t-concat_horizontal.c new file mode 100644 index 0000000000..e4b7afdb3e --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-concat_horizontal.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-concat_horizontal.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-concat_vertical.c b/fq_nmod_sparse_mat/test/t-concat_vertical.c new file mode 100644 index 0000000000..ed52ddd2d1 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-concat_vertical.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-concat_vertical.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-construct.c b/fq_nmod_sparse_mat/test/t-construct.c new file mode 100644 index 0000000000..b8973155e9 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-dense.c b/fq_nmod_sparse_mat/test/t-dense.c new file mode 100644 index 0000000000..da27a9ab68 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-init_clear.c b/fq_nmod_sparse_mat/test/t-init_clear.c new file mode 100644 index 0000000000..b40e950776 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-inv.c b/fq_nmod_sparse_mat/test/t-inv.c new file mode 100644 index 0000000000..36d3648729 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-inv.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-inv.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-lu.c b/fq_nmod_sparse_mat/test/t-lu.c new file mode 100644 index 0000000000..7e4e75a6e8 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-lu.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-mul.c b/fq_nmod_sparse_mat/test/t-mul.c new file mode 100644 index 0000000000..654c1039fa --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-mul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-neg.c b/fq_nmod_sparse_mat/test/t-neg.c new file mode 100644 index 0000000000..45b024b361 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-neg.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-nullspace.c b/fq_nmod_sparse_mat/test/t-nullspace.c new file mode 100644 index 0000000000..d561349e5c --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-nullspace.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-nullspace.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-rref.c b/fq_nmod_sparse_mat/test/t-rref.c new file mode 100644 index 0000000000..ba4aa88694 --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-rref.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-scalar_mul.c b/fq_nmod_sparse_mat/test/t-scalar_mul.c new file mode 100644 index 0000000000..7c704d8f2e --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-solve.c b/fq_nmod_sparse_mat/test/t-solve.c new file mode 100644 index 0000000000..5e8763aaee --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-solve.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-solve.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/test/t-transpose.c b/fq_nmod_sparse_mat/test/t-transpose.c new file mode 100644 index 0000000000..1392eca38a --- /dev/null +++ b/fq_nmod_sparse_mat/test/t-transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/test/t-transpose.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/transpose.c b/fq_nmod_sparse_mat/transpose.c new file mode 100644 index 0000000000..7db5f5b7c9 --- /dev/null +++ b/fq_nmod_sparse_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/window_init.c b/fq_nmod_sparse_mat/window_init.c new file mode 100644 index 0000000000..bd8c3f34e7 --- /dev/null +++ b/fq_nmod_sparse_mat/window_init.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/window_init.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec.h b/fq_nmod_sparse_vec.h new file mode 100644 index 0000000000..f243bc7391 --- /dev/null +++ b/fq_nmod_sparse_vec.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_NMOD_SPARSE_VEC_H +#define FQ_NMOD_SPARSE_VEC_H + +#ifdef FQ_NMOD_SPARSE_VEC_INLINES_C +#define FQ_SPARSE_VEC_TEMPLATES_INLINE FLINT_DLL +#define FQ_NMOD_SPARSE_VEC_INLINE FLINT_DLL +#else +#define FQ_SPARSE_VEC_TEMPLATES_INLINE static __inline__ +#define FQ_NMOD_SPARSE_VEC_INLINE static __inline__ +#endif + +#include "fq_nmod.h" +#include "fq_nmod_vec.h" + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_nmod_sparse_vec/add.c b/fq_nmod_sparse_vec/add.c new file mode 100644 index 0000000000..0b2952f536 --- /dev/null +++ b/fq_nmod_sparse_vec/add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/add.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/print_pretty.c b/fq_nmod_sparse_vec/print_pretty.c new file mode 100644 index 0000000000..770eb351d5 --- /dev/null +++ b/fq_nmod_sparse_vec/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/randtest.c b/fq_nmod_sparse_vec/randtest.c new file mode 100644 index 0000000000..17b968995b --- /dev/null +++ b/fq_nmod_sparse_vec/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/scalar_addmul.c b/fq_nmod_sparse_vec/scalar_addmul.c new file mode 100644 index 0000000000..096833c1a8 --- /dev/null +++ b/fq_nmod_sparse_vec/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/sub.c b/fq_nmod_sparse_vec/sub.c new file mode 100644 index 0000000000..1ad014b2be --- /dev/null +++ b/fq_nmod_sparse_vec/sub.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/sub.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-add.c b/fq_nmod_sparse_vec/test/t-add.c new file mode 100644 index 0000000000..01a6e60300 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-add.c @@ -0,0 +1,21 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-concat.c b/fq_nmod_sparse_vec/test/t-concat.c new file mode 100644 index 0000000000..8253306aec --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-concat.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-concat.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-construct.c b/fq_nmod_sparse_vec/test/t-construct.c new file mode 100644 index 0000000000..40e309f7ef --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-dense.c b/fq_nmod_sparse_vec/test/t-dense.c new file mode 100644 index 0000000000..07fa2b09e5 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-dot.c b/fq_nmod_sparse_vec/test/t-dot.c new file mode 100644 index 0000000000..45d119f1f3 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-dot.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-dot.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-init_clear.c b/fq_nmod_sparse_vec/test/t-init_clear.c new file mode 100644 index 0000000000..607fa4e215 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-neg.c b/fq_nmod_sparse_vec/test/t-neg.c new file mode 100644 index 0000000000..b62369e249 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-neg.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_vec/test/t-scalar_mul.c b/fq_nmod_sparse_vec/test/t-scalar_mul.c new file mode 100644 index 0000000000..6a7ea91da8 --- /dev/null +++ b/fq_nmod_sparse_vec/test/t-scalar_mul.c @@ -0,0 +1,23 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat.h b/fq_sparse_mat.h new file mode 100644 index 0000000000..e9425c87ec --- /dev/null +++ b/fq_sparse_mat.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_SPARSE_MAT_H +#define FQ_SPARSE_MAT_H + +#ifdef FQ_SPARSE_MAT_INLINES_C +#define FQ_SPARSE_MAT_TEMPLATES_INLINE FLINT_DLL +#define FQ_SPARSE_MAT_INLINE FLINT_DLL +#else +#define FQ_SPARSE_MAT_TEMPLATES_INLINE static __inline__ +#define FQ_SPARSE_MAT_INLINE static __inline__ +#endif + + +#include "fq.h" +#include "fq_vec.h" +#include "fq_sparse_vec.h" +#include "fq_mat.h" + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_sparse_mat/from_entries.c b/fq_sparse_mat/from_entries.c new file mode 100644 index 0000000000..f3ff7e5490 --- /dev/null +++ b/fq_sparse_mat/from_entries.c @@ -0,0 +1,30 @@ +/* +<<<<<<< HEAD +<<<<<<< HEAD + Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters +======= + Copyright (C) 2011 Fredrik Johansson +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/from_entries.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/inv.c b/fq_sparse_mat/inv.c new file mode 100644 index 0000000000..1a510a64df --- /dev/null +++ b/fq_sparse_mat/inv.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/inv.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/lu.c b/fq_sparse_mat/lu.c new file mode 100644 index 0000000000..f34cf23b13 --- /dev/null +++ b/fq_sparse_mat/lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/lu.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_lanczos.c b/fq_sparse_mat/nullspace_lanczos.c new file mode 100644 index 0000000000..6cf17b90d1 --- /dev/null +++ b/fq_sparse_mat/nullspace_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_lu.c b/fq_sparse_mat/nullspace_lu.c new file mode 100644 index 0000000000..5c1d34e5f4 --- /dev/null +++ b/fq_sparse_mat/nullspace_lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_lu.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_rref.c b/fq_sparse_mat/nullspace_rref.c new file mode 100644 index 0000000000..c0d8646b3a --- /dev/null +++ b/fq_sparse_mat/nullspace_rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_rref.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_wiedemann.c b/fq_sparse_mat/nullspace_wiedemann.c new file mode 100644 index 0000000000..721fc4b9e1 --- /dev/null +++ b/fq_sparse_mat/nullspace_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/print_pretty.c b/fq_sparse_mat/print_pretty.c new file mode 100644 index 0000000000..83d2b583d3 --- /dev/null +++ b/fq_sparse_mat/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/randtest.c b/fq_sparse_mat/randtest.c new file mode 100644 index 0000000000..344d5ccdec --- /dev/null +++ b/fq_sparse_mat/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/rref.c b/fq_sparse_mat/rref.c new file mode 100644 index 0000000000..d8c2e69609 --- /dev/null +++ b/fq_sparse_mat/rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/rref.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_block_lanczos.c b/fq_sparse_mat/solve_block_lanczos.c new file mode 100644 index 0000000000..7b6e0ba4c1 --- /dev/null +++ b/fq_sparse_mat/solve_block_lanczos.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for + Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 + + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_block_wiedemann.c b/fq_sparse_mat/solve_block_wiedemann.c new file mode 100644 index 0000000000..08cee373a5 --- /dev/null +++ b/fq_sparse_mat/solve_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_lanczos.c b/fq_sparse_mat/solve_lanczos.c new file mode 100644 index 0000000000..2165bcfb7b --- /dev/null +++ b/fq_sparse_mat/solve_lanczos.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_lu.c b/fq_sparse_mat/solve_lu.c new file mode 100644 index 0000000000..c850b6b511 --- /dev/null +++ b/fq_sparse_mat/solve_lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_lu.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_rref.c b/fq_sparse_mat/solve_rref.c new file mode 100644 index 0000000000..f718908bd6 --- /dev/null +++ b/fq_sparse_mat/solve_rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_rref.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/solve_wiedemann.c b/fq_sparse_mat/solve_wiedemann.c new file mode 100644 index 0000000000..bb5886b871 --- /dev/null +++ b/fq_sparse_mat/solve_wiedemann.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/solve_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-add.c b/fq_sparse_mat/test/t-add.c new file mode 100644 index 0000000000..aba875a83e --- /dev/null +++ b/fq_sparse_mat/test/t-add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-concat_horizontal.c b/fq_sparse_mat/test/t-concat_horizontal.c new file mode 100644 index 0000000000..5ccf74698a --- /dev/null +++ b/fq_sparse_mat/test/t-concat_horizontal.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-concat_horizontal.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-concat_vertical.c b/fq_sparse_mat/test/t-concat_vertical.c new file mode 100644 index 0000000000..5c207ea5a0 --- /dev/null +++ b/fq_sparse_mat/test/t-concat_vertical.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-concat_vertical.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-construct.c b/fq_sparse_mat/test/t-construct.c new file mode 100644 index 0000000000..1f835d3797 --- /dev/null +++ b/fq_sparse_mat/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-dense.c b/fq_sparse_mat/test/t-dense.c new file mode 100644 index 0000000000..c9fcb894a7 --- /dev/null +++ b/fq_sparse_mat/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-init_clear.c b/fq_sparse_mat/test/t-init_clear.c new file mode 100644 index 0000000000..5fa52abb6c --- /dev/null +++ b/fq_sparse_mat/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-inv.c b/fq_sparse_mat/test/t-inv.c new file mode 100644 index 0000000000..f180442657 --- /dev/null +++ b/fq_sparse_mat/test/t-inv.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-inv.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-lu.c b/fq_sparse_mat/test/t-lu.c new file mode 100644 index 0000000000..327417bf86 --- /dev/null +++ b/fq_sparse_mat/test/t-lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-lu.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-mul.c b/fq_sparse_mat/test/t-mul.c new file mode 100644 index 0000000000..6225c09304 --- /dev/null +++ b/fq_sparse_mat/test/t-mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-mul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-neg.c b/fq_sparse_mat/test/t-neg.c new file mode 100644 index 0000000000..6bc923de5e --- /dev/null +++ b/fq_sparse_mat/test/t-neg.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-nullspace.c b/fq_sparse_mat/test/t-nullspace.c new file mode 100644 index 0000000000..039710f4f2 --- /dev/null +++ b/fq_sparse_mat/test/t-nullspace.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-nullspace.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-rref.c b/fq_sparse_mat/test/t-rref.c new file mode 100644 index 0000000000..d01a7ab372 --- /dev/null +++ b/fq_sparse_mat/test/t-rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-rref.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-scalar_mul.c b/fq_sparse_mat/test/t-scalar_mul.c new file mode 100644 index 0000000000..2aebfd1d45 --- /dev/null +++ b/fq_sparse_mat/test/t-scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-solve.c b/fq_sparse_mat/test/t-solve.c new file mode 100644 index 0000000000..d2bbcaa132 --- /dev/null +++ b/fq_sparse_mat/test/t-solve.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-solve.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/test/t-transpose.c b/fq_sparse_mat/test/t-transpose.c new file mode 100644 index 0000000000..b840457936 --- /dev/null +++ b/fq_sparse_mat/test/t-transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/test/t-transpose.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/transpose.c b/fq_sparse_mat/transpose.c new file mode 100644 index 0000000000..dcc14f275d --- /dev/null +++ b/fq_sparse_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/window_init.c b/fq_sparse_mat/window_init.c new file mode 100644 index 0000000000..ec6fa02e2a --- /dev/null +++ b/fq_sparse_mat/window_init.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/window_init.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat_templates.h b/fq_sparse_mat_templates.h new file mode 100644 index 0000000000..3ce9c803c6 --- /dev/null +++ b/fq_sparse_mat_templates.h @@ -0,0 +1,371 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include +#include "flint.h" +#include "longlong.h" +#include "templates.h" +#include "ulong_extras.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* A sparse matrix is a list of sparse vectors */ +typedef struct +{ + TEMPLATE(T, sparse_vec_struct) *rows; + slong r; + slong c; + slong c_off; +} +TEMPLATE(T, sparse_mat_struct); + +typedef TEMPLATE(T, sparse_mat_struct) TEMPLATE(T, sparse_mat_t)[1]; + +/* Memory management */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_init) (TEMPLATE(T, sparse_mat_t) M, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx) +{ + M->rows = flint_calloc(rows, sizeof(*M->rows)); + M->r = rows; + M->c = cols; + M->c_off = 0; +} +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_clear) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) TEMPLATE(T, sparse_vec_clear)(&M->rows[i], ctx); + flint_free(M->rows); + memset(M, 0, sizeof(*M)); +} +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_swap) (TEMPLATE(T, sparse_mat_t) M1, TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, ctx_t) ctx) +{ + TEMPLATE(T, sparse_mat_t) tmp; + *tmp = *M1; *M1 = *M2; *M2 = *tmp; +} + +/* One-time instantiation */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_zero) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) TEMPLATE(T, sparse_vec_zero)(&M->rows[i], ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_one) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) TEMPLATE(T, sparse_vec_one)(&M->rows[i], i, ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_set) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) src, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, rmax = FLINT_MIN(M->r, src->r); + if(M==src || M->r == 0) return; + for(i=0; irows[i], &src->rows[i], src->c_off, ctx); +} + +FLINT_DLL +void TEMPLATE(T, sparse_mat_from_entries)(TEMPLATE(T, sparse_mat_t) M, slong * rows, slong * cols, TEMPLATE(T, struct) * vals, slong nnz, const TEMPLATE(T, ctx_t) ctx); + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_append_col) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *v, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i=0; ir; ++i) TEMPLATE(T, sparse_vec_append_entry)(&M->rows[i], M->c, &v[i], ctx); + M->c += 1; +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_append_row) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, ctx_t) ctx) +{ + M->rows = realloc(M->rows, (M->r+1)*sizeof(*M->rows)); + memset(M->rows + M->r, 0, sizeof(*M->rows)); + TEMPLATE(T, sparse_vec_set)(&M->rows[M->r], v, 0, ctx); + M->r += 1; +} + +/* Convert from/to dense matrix */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_from_dense) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, mat_t) dM, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, rmax = FLINT_MIN(M->r, dM->r); + for (i = 0; i < rmax; ++i) TEMPLATE(T, sparse_vec_from_dense)(&M->rows[i], dM->rows[i], dM->c, ctx); +} +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_to_dense) (TEMPLATE(T, mat_t) dM, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, rmax = FLINT_MIN(M->r, dM->r); + for (i = 0; i < rmax; ++i) TEMPLATE(T, sparse_vec_to_dense)(dM->rows[i], &M->rows[i], dM->c, ctx); +} + +/* Windows, concatenation, and splitting */ +FLINT_DLL +void TEMPLATE(T, sparse_mat_window_init) (TEMPLATE(T, sparse_mat_t) W, const TEMPLATE(T, sparse_mat_t) M, slong r1, slong c1, slong r2, slong c2, const TEMPLATE(T, ctx_t) ctx); + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_window_clear) (TEMPLATE(T, sparse_mat_t) W, TEMPLATE(T, ctx_t) ctx) +{ + flint_free(W->rows); + memset(W, 0, sizeof(*W)); +} + + +/* Combine M1 and M2 into block matrix B = [M1 M2] */ +/* B->r must equal M1->r and M2->r */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_concat_horizontal)(TEMPLATE(T, sparse_mat_t) B, + const TEMPLATE(T, sparse_mat_t) M1, const TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + B->c = M1->c + M2->c; + for (i = 0; i < B->r; ++i) + TEMPLATE(T, sparse_vec_concat)(&B->rows[i], &M1->rows[i], &M2->rows[i], M1->c, ctx); +} +/* Combine M1 and M2 into block matrix B = [M1^t M1^t]^t */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_concat_vertical) (TEMPLATE(T, sparse_mat_t) B, const TEMPLATE(T, sparse_mat_t) M1, const TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + B->c = FLINT_MAX(M1->c, M2->c); + for (i = 0; i < M1->r; ++i) + TEMPLATE(T, sparse_vec_set)(&B->rows[i], &M1->rows[i], M1->c_off, ctx); + for (i = M1->r; i < B->r; ++i) + TEMPLATE(T, sparse_vec_set)(&B->rows[i], &M2->rows[i-M1->r], M2->c_off, ctx); +} + +/* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ +/* M1->r and M2->r must equal B->r */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_split_horizontal) (TEMPLATE(T, sparse_mat_t) M1, TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, sparse_mat_t) B, slong c, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i=0; ir; ++i) TEMPLATE(T, sparse_vec_split)(&M1->rows[i], &M2->rows[i], &B->rows[i], c, ctx); +} + +/* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_split_vertical) (TEMPLATE(T, sparse_mat_t) M1, TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, sparse_mat_t) B, slong r, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + r = FLINT_MIN(r, B->r); + for(i=0; irows[i], &B->rows[i], B->c_off, ctx); + for(i=r; ir; ++i) TEMPLATE(T, sparse_vec_set)(&M2->rows[i-r], &B->rows[i], B->c_off, ctx); +} + +/* Matrix permutation */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_permute_cols)(TEMPLATE(T, sparse_mat_t) M, slong *Q, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) { + if(!M->rows[i].nnz) continue; + TEMPLATE(T, sparse_vec_permute_inds)(&M->rows[i], Q, ctx); + qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), TEMPLATE(T, sparse_entry_cmp)); + } +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_permute_rows)(TEMPLATE(T, sparse_mat_t) M, slong *P, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + TEMPLATE(T, sparse_vec_struct) *prows; + prows = flint_calloc(M->r, sizeof(*prows)); + for (i = 0; i < M->r; ++i) prows[P[i]] = M->rows[i]; + memcpy(M->rows, prows, M->r*sizeof(*M->rows)); + flint_free(prows); +} + +/* Random matrix generation */ +FLINT_DLL void TEMPLATE(T, sparse_mat_randtest) (TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong min_nnz, slong max_nnz, const TEMPLATE(T, ctx_t) ctx); +/* +FLINT_DLL void TEMPLATE(T, sparse_mat_randfull) (TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, TEMPLATE(T, ctx_t) ctx); +FLINT_DLL int TEMPLATE(T, sparse_mat_randpermdiag)(TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, + const TEMPLATE(T, struct) *diag, slong n); +FLINT_DLL void TEMPLATE(T, sparse_mat_randrank) (TEMPLATE(T, sparse_mat_t), flint_rand_t state, slong rank, TEMPLATE(T, ctx_t) ctx); +FLINT_DLL void TEMPLATE(T, sparse_mat_randops) (TEMPLATE(T, sparse_mat_t) M, slong count, flint_rand_t state, TEMPLATE(T, ctx_t) ctx); +FLINT_DLL void TEMPLATE(T, sparse_mat_randtril) (TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, int unit, TEMPLATE(T, ctx_t) ctx); +FLINT_DLL void TEMPLATE(T, sparse_mat_randtriu) (TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, int unit, TEMPLATE(T, ctx_t) ctx); + */ + +FLINT_DLL void TEMPLATE(T, sparse_mat_print_pretty) (const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +FQ_SPARSE_MAT_TEMPLATES_INLINE +int TEMPLATE(T, sparse_mat_equal) (const TEMPLATE(T, sparse_mat_t) M1, const TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if (M1->r != M2->r) return 0; + for (i = 0; i < M1->r; ++i) + if (!TEMPLATE(T, sparse_vec_equal)(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off, ctx)) return 0; + return 1; +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +int TEMPLATE(T, sparse_mat_is_zero) (const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) + if (!TEMPLATE(T, sparse_vec_is_zero)(&M->rows[i], ctx)) return 0; + return 1; +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +int TEMPLATE(T, sparse_mat_is_square) (const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + return (M->r == M->c); +} + +/* Must have M->r == N->c and M->c == N->r */ +FLINT_DLL void TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +/* Arithmetic */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_neg) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < N->r; ++i) TEMPLATE(T, sparse_vec_neg)(&N->rows[i], &M->rows[i], ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_scalar_mul) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < N->r; ++i) TEMPLATE(T, sparse_vec_scalar_mul)(&N->rows[i], &M->rows[i], c, ctx); +} + + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_addmul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_scalar_addmul)(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_add) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_add)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_sub) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_sub)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); +} + +/* Matrix-vector and matrix-matrix multipliciation */ +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_mul_vec) (TEMPLATE(T, struct) *y, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *x, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < M->r; ++i) TEMPLATE(T, sparse_vec_dot_dense)(&y[i], &M->rows[i], x, ctx); +} +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_mul_mat) (TEMPLATE(T, mat_t) Y, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j; + for (i = 0; i < M->r; ++i) + { + for (j = 0; j < M->rows[i].nnz; ++j) + { + TEMPLATE(T, sparse_entry_struct) *e = &M->rows[i].entries[j]; + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T))(Y->rows[i], X->rows[e->ind], X->c, e->val, ctx); + } + } +} + +/* Permutations */ +/* FLINT_DLL void TEMPLATE(T, sparse_mat_swap_rows)(TEMPLATE(T, sparse_mat_t) M, slong * perm, slong r, slong s); +FLINT_DLL void TEMPLATE(T, sparse_mat_invert_rows)(TEMPLATE(T, sparse_mat_t) M, slong * perm); +FLINT_DLL void TEMPLATE(T, sparse_mat_swap_cols)(TEMPLATE(T, sparse_mat_t) M, slong * perm, slong r, slong s); +FLINT_DLL void TEMPLATE(T, sparse_mat_invert_cols)(TEMPLATE(T, sparse_mat_t) M, slong * perm); +FLINT_DLL void TEMPLATE(T, sparse_mat_apply_permutation)(TEMPLATE(T, sparse_mat_t) M, slong * P, slong n); + */ + +/* Decomposition/reduction */ +FLINT_DLL +slong TEMPLATE(T, sparse_mat_lu)(slong *P, slong *Q, TEMPLATE(T, sparse_mat_t) L, TEMPLATE(T, sparse_mat_t) U, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +/* Solve Ax=b */ +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_rref) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +/* Find single nullvector */ +FLINT_DLL +int TEMPLATE(T, sparse_mat_nullvector_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_nullvector_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx); + +/* Note: this should take in uninitialized matrix X */ +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_inv) (TEMPLATE(T, sparse_mat_t) Ai, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); + +/* Nullspace */ +/* NMOD_SPARSE_MAT_INLINE +slong TEMPLATE(T, sparse_mat_nullspace) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, ctx_t) ctx); + */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/fq_sparse_mat_templates/from_entries.c b/fq_sparse_mat_templates/from_entries.c new file mode 100644 index 0000000000..c3fc5e1dff --- /dev/null +++ b/fq_sparse_mat_templates/from_entries.c @@ -0,0 +1,36 @@ +/* +<<<<<<< HEAD +<<<<<<< HEAD + Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters +======= + Copyright (C) 2011 Fredrik Johansson +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, sparse_mat_from_entries) (TEMPLATE(T, sparse_mat_t) M, slong * rows, slong * cols, TEMPLATE(T, struct) * vals, slong nnz, const TEMPLATE(T, ctx_t) ctx) +{ + slong r, i, j; + for (r = i = 0; r < M->r; ++r, i = j) + { + M->rows[r].nnz = 0; + for (j = i; j < nnz && rows[j]==r; ++j); + TEMPLATE(T, sparse_vec_from_entries) (&M->rows[r], cols+i, vals+i, j-i, ctx); + } +} + +#endif diff --git a/fq_sparse_mat_templates/inv.c b/fq_sparse_mat_templates/inv.c new file mode 100644 index 0000000000..82b3f38b4c --- /dev/null +++ b/fq_sparse_mat_templates/inv.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_inv) (TEMPLATE(T, sparse_mat_t) Mi, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong rk; + TEMPLATE(T, sparse_mat_t) I, MI; + TEMPLATE(T, sparse_vec_struct) *row; + TEMPLATE(T, sparse_entry_struct) *le, *re; + + /* Create block matrix [M | I] */ + TEMPLATE(T, sparse_mat_init) (I, M->r, M->r, ctx); + TEMPLATE(T, sparse_mat_one) (I, ctx); + TEMPLATE(T, sparse_mat_init) (MI, M->r, M->r + M->c, ctx); + TEMPLATE(T, sparse_mat_concat_horizontal) (MI, M, I, ctx); + + /* Run Gaussian elimination on first half */ + MI->c = M->c; + rk = TEMPLATE(T, sparse_mat_rref) (MI, ctx); + MI->c = M->c+M->r; + TEMPLATE(T, sparse_mat_split_horizontal) (I, Mi, MI, M->c, ctx); + TEMPLATE(T, sparse_mat_clear) (I, ctx); + TEMPLATE(T, sparse_mat_clear) (MI, ctx); + return rk; +} + +#endif diff --git a/fq_sparse_mat_templates/lu.c b/fq_sparse_mat_templates/lu.c new file mode 100644 index 0000000000..4ddb675e48 --- /dev/null +++ b/fq_sparse_mat_templates/lu.c @@ -0,0 +1,179 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +static void heap_up(slong *heap, slong *heap_idx, slong *scores, slong pos) +{ + const slong c = heap[pos]; + slong nc, npos; + for (; pos > 0; pos = npos) + { + npos = (pos-1)/2; + nc = heap[npos]; + if (scores[c] >= scores[nc]) break; + + heap[pos] = nc; + heap_idx[nc] = pos; + } + heap[pos] = c; + heap_idx[c] = pos; +} + +static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, slong pos) +{ + const slong c = heap[pos]; + slong nc, npos; + for (; pos < (size-1)/2; pos = npos) + { + npos = 2*pos+1; + if (npos+1 < size && scores[heap[npos]] > scores[heap[npos+1]]) ++npos; + nc = heap[npos]; + if (scores[c] <= scores[nc]) break; + + heap[pos] = nc; + heap_idx[nc] = pos; + } + heap[pos] = c; + heap_idx[c] = pos; +} + +/* static void print_heap(slong *heap, slong *scores, slong size) { + slong level, i; + for(level=1; level<=size; level<<=1) { + for(i=level; i<=size && i<2*level; ++i) { + flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); + } + flint_printf("\n"); + } +} + */ +slong TEMPLATE(T, sparse_mat_lu)(slong *P, slong *Q, + TEMPLATE(T, sparse_mat_t) L, TEMPLATE(T, sparse_mat_t) U, + const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j, r, c, pr, pc, rank, remr, remc; + slong *heap, *heap_idx, *scores, heap_size; + TEMPLATE(T, t) cinv, cc; + TEMPLATE(T, sparse_mat_t) Lt; + TEMPLATE(T, sparse_vec_struct) *pcol, *prow, *row, *col; + + if (M->r == 0 || M->c == 0) + { + TEMPLATE(T, sparse_mat_zero) (L, ctx); + TEMPLATE(T, sparse_mat_zero) (U, ctx); + for (i = 0; i < M->r; ++i) P[i] = i; + for (i = 0; i < M->c; ++i) Q[i] = i; + return 0; + } + TEMPLATE(T, init) (cinv, ctx); + TEMPLATE(T, init) (cc, ctx); + TEMPLATE(T, sparse_mat_init) (Lt, L->c, L->r, ctx); + TEMPLATE(T, sparse_mat_transpose) (Lt, M, ctx); + TEMPLATE(T, sparse_mat_set) (U, M, ctx); + + /* Set up permutations */ + remr = M->r, remc = M->c; + for (r = 0; rr; ++r) + { + if (!U->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + for (c = 0; cc; ++c) + { + if (!Lt->rows[c].nnz) Q[c] = --remc; + else Q[c] = -1; + } + + /* Make heap of nonzero columns by size */ + heap_size = M->c; + heap = flint_malloc(M->c*sizeof(*heap)); + scores = flint_malloc(M->c*sizeof(*scores)); + heap_idx = flint_malloc(M->c*sizeof(*heap_idx)); + for (i = 0; i < M->c; ++i) + { + scores[i] = Lt->rows[i].nnz; /* TODO: randomized tiebreaker */ + heap[i] = i; + heap_up(heap, heap_idx, scores, i); + } + /* Run elimination */ + rank = 0; + for (heap_size=M->c; heap_size > 0; ) + { + /* Get lowest weight column (top of heap) */ + pc = heap[0]; + pcol = &Lt->rows[pc]; + heap[0] = heap[--heap_size]; + heap_down(heap, heap_idx, scores, heap_size, 0); + if (pcol->nnz == 0) continue; /* Empty columns already dealt with */ + Q[pc] = rank; /* Move pivot column to front */ + + /* Get lowest weight incident row */ + pr = pcol->entries[0].ind, prow = &U->rows[pr]; + for (j = 1; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &U->rows[r]; + if (row->nnz < prow->nnz) pr = r, prow = row; + } + P[pr] = rank; /* Move pivot row to front */ + + /* Invert pivot */ + TEMPLATE(T, inv) (cinv, *TEMPLATE(T, sparse_vec_at) (prow, pc, ctx), ctx); + + /* Gaussian eliminate rows */ + for (j = 0; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &U->rows[r]; + if (P[r] >= 0) continue; /* Skip previous pivot rows */ + TEMPLATE(T, mul) (cc, cinv, *TEMPLATE(T, sparse_vec_at) (row, pc, ctx), ctx); + TEMPLATE(T, neg) (cc, cc, ctx); + TEMPLATE(T, sparse_vec_scalar_addmul) (row, row, prow, cc, ctx); + if (row->nnz == 0) P[r] = --remr; + } + /* Gaussian eliminate cols */ + TEMPLATE(T, sparse_vec_scalar_mul) (pcol, pcol, cinv, ctx); + for (j = 0; j < prow->nnz; ++j) + { + c = prow->entries[j].ind, col = &Lt->rows[c]; + if (Q[c] >= 0) continue; /* Skip previous pivot columns */ + TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (col, pr, ctx), ctx); + TEMPLATE(T, sparse_vec_scalar_addmul) (col, col, pcol, cc, ctx); + if (col->nnz == 0) Q[c] = --remc; + scores[c] = col->nnz; + heap_up(heap, heap_idx, scores, heap_idx[c]); + heap_down(heap, heap_idx, scores, heap_size, heap_idx[c]); + + } + rank += 1; + } + flint_free(heap); + flint_free(scores); + flint_free(heap_idx); + + TEMPLATE(T, clear) (cinv, ctx); + TEMPLATE(T, clear) (cc, ctx); + + /* Transpose L^t */ + TEMPLATE(T, sparse_mat_transpose) (L, Lt, ctx); + TEMPLATE(T, sparse_mat_clear) (Lt, ctx); + + /* Reorder rows and cols in L and U */ + TEMPLATE(T, sparse_mat_permute_cols) (L, Q, ctx); + TEMPLATE(T, sparse_mat_permute_rows) (L, P, ctx); + TEMPLATE(T, sparse_mat_permute_cols) (U, Q, ctx); + TEMPLATE(T, sparse_mat_permute_rows) (U, P, ctx); + return rank; +} + +#endif diff --git a/fq_sparse_mat_templates/nullspace_lanczos.c b/fq_sparse_mat_templates/nullspace_lanczos.c new file mode 100644 index 0000000000..a5e3097d8a --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_lanczos.c @@ -0,0 +1,78 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) +{ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) *x, **xs; + + TEMPLATE(T, init) (cc, ctx); + x = _TEMPLATE(T, vec_init) (M->c, ctx); + nxs = 0; + xs = NULL; + xps = NULL; + for(iter = 0; iter < max_iters; ) + { + if(TEMPLATE(T, sparse_mat_nullvector_lanczos) (x, M, state, ctx) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && TEMPLATE(T, is_zero) (&x[i], ctx); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + TEMPLATE(T, inv) (cc, &x[i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + TEMPLATE(T, neg) (cc, &xs[j][i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _TEMPLATE(T, vec_init) (M->c, ctx); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + TEMPLATE(T, clear) (cc, ctx); + _TEMPLATE(T, vec_clear) (x, M->c, ctx); + TEMPLATE(T, mat_init) (X, M->c, nxs, ctx); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + TEMPLATE(T, set) (&X->rows[j][i], &xs[i][j], ctx); + _TEMPLATE(T, vec_clear) (xs[i], M->c, ctx); + } + flint_free(xs); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/nullspace_lu.c b/fq_sparse_mat_templates/nullspace_lu.c new file mode 100644 index 0000000000..efba6d6ee9 --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_lu.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + int good = 1; + slong rk, *P, *Q, *Qi, i, j; + TEMPLATE(T, t) cc; + TEMPLATE(T, sparse_mat_t) L, U; + TEMPLATE(T, sparse_entry_struct) *e; + TEMPLATE(T, sparse_vec_struct) *Urow; + TEMPLATE(T, struct) *Xrow; + + P = flint_malloc(M->r * sizeof(*P)); + Q = flint_malloc(M->c * sizeof(*Q)); + TEMPLATE(T, init) (cc, ctx); + TEMPLATE(T, sparse_mat_init) (L, M->r, M->c, ctx); + TEMPLATE(T, sparse_mat_init) (U, M->r, M->c, ctx); + rk = TEMPLATE(T, sparse_mat_lu) (P, Q, L, U, M, ctx); + flint_free(P); + TEMPLATE(T, sparse_mat_clear) (L, ctx); + for(i=0; irows[i].entries[0].val, ctx); + TEMPLATE(T, sparse_vec_scalar_mul) (&U->rows[i], &U->rows[i], cc, ctx); + } + TEMPLATE(T, mat_init) (X, M->c, M->c-rk, ctx); + if (rk != M->c) + { + /* Invert permutation */ + Qi = flint_malloc(M->c * sizeof(*Qi)); + for (i = 0; i < M->c; ++i) Qi[Q[i]] = i; + + /* Mssign unit vectors to non-pivot columns */ + for (i = M->c-1; i >= rk; --i) TEMPLATE(T, one) (&X->rows[Qi[i]][i-rk], ctx); + for (i = rk-1; i >= 0; --i) { + Urow = &U->rows[i]; + Xrow = X->rows[Qi[i]]; + for(j = 1; jnnz; ++j) { + e = &Urow->entries[j]; + /* Do in-place row elimination */ + TEMPLATE(T, neg) (cc, e->val, ctx); + if(e->ind < rk) _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (Xrow, X->rows[Qi[e->ind]], X->c, cc, ctx); + else TEMPLATE(T, sub) (&Xrow[e->ind-rk], &Xrow[e->ind-rk], e->val, ctx); + } + + } + flint_free(Qi); + } + flint_free(Q); + TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, sparse_mat_clear) (U, ctx); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/nullspace_rref.c b/fq_sparse_mat_templates/nullspace_rref.c new file mode 100644 index 0000000000..87306a306a --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_rref.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j, rk, numc, *Q; + TEMPLATE(T, struct) *Xrow; + TEMPLATE(T, sparse_mat_t) R; + TEMPLATE(T, sparse_vec_struct) *Rrow; + TEMPLATE(T, sparse_entry_struct) *le, *e; + TEMPLATE(T, sparse_mat_init) (R, M->r, M->c, ctx); + TEMPLATE(T, sparse_mat_set) (R, M, ctx); + rk = TEMPLATE(T, sparse_mat_rref) (R, ctx); + TEMPLATE(T, mat_init) (X, M->c, M->c-rk, ctx); + if(rk != M->c) + { + numc = 0; + /* Mark which cols are pivots and enumerate the nonpivots */ + Q = flint_calloc(M->c, sizeof(*Q)); + for (i = 0; i < rk; ++i) + Q[R->rows[i].entries->ind] = -1; + for (i = 0; i < M->c; ++i) + if(Q[i]==UWORD(0)) Q[i] = numc++, TEMPLATE(T, one) (&X->rows[i][Q[i]], ctx); + + /* For each pivot col, set the corresponding row in X as */ + /* the negative of the associated row in R (reordered by Q) */ + for (i = 0; i < rk; ++i) + { + Rrow = &R->rows[i]; + Xrow = X->rows[Rrow->entries[0].ind]; + for (j = 1; j < Rrow->nnz; ++j) + TEMPLATE(T, neg) (&Xrow[Q[Rrow->entries[j].ind]], Rrow->entries[j].val, ctx); + } + flint_free(Q); + } + TEMPLATE(T, sparse_mat_clear) (R, ctx); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/nullspace_wiedemann.c b/fq_sparse_mat_templates/nullspace_wiedemann.c new file mode 100644 index 0000000000..86930d3667 --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_wiedemann.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) +{ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) *x, **xs; + + TEMPLATE(T, init) (cc, ctx); + x = _TEMPLATE(T, vec_init) (M->c, ctx); + nxs = 0; + xs = NULL; + xps = NULL; + for(iter = 0; iter < max_iters; ) + { + if(TEMPLATE(T, sparse_mat_nullvector_wiedemann) (x, M, state, ctx) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && TEMPLATE(T, is_zero) (&x[i], ctx); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + TEMPLATE(T, inv) (cc, &x[i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + TEMPLATE(T, neg) (cc, &xs[j][i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _TEMPLATE(T, vec_init) (M->c, ctx); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + TEMPLATE(T, mat_init) (X, M->c, nxs, ctx); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + TEMPLATE(T, set) (&X->rows[j][i], &xs[i][j], ctx); + _TEMPLATE(T, vec_clear) (xs[i], M->c, ctx); + } + TEMPLATE(T, clear) (cc, ctx); + _TEMPLATE(T, vec_clear) (x, M->c, ctx); + + flint_free(xs); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/print_pretty.c b/fq_sparse_mat_templates/print_pretty.c new file mode 100644 index 0000000000..8d7917756d --- /dev/null +++ b/fq_sparse_mat_templates/print_pretty.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +void +TEMPLATE(T, sparse_mat_print_pretty) (const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + char row_fmt[FLINT_BITS + 5]; + flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(M->r, 10)); + + flint_printf("<%wd x %wd sparse integer matrix mod %w>\n", + M->r, M->c, ctx); + + for (i = 0; i < M->r; i++) + { + flint_printf(row_fmt, i); + TEMPLATE(T, sparse_vec_print_pretty) (&M->rows[i], M->c_off, M->c, ctx); + } +} + + +#endif diff --git a/fq_sparse_mat_templates/randtest.c b/fq_sparse_mat_templates/randtest.c new file mode 100644 index 0000000000..11bb98c367 --- /dev/null +++ b/fq_sparse_mat_templates/randtest.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +void +TEMPLATE(T, sparse_mat_randtest) (TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong min_nnz, slong max_nnz, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz; + + for (i = 0; i < M->r; ++i) + { + nnz = n_randint(state, max_nnz+1); + nnz = FLINT_MAX(nnz, min_nnz); + TEMPLATE(T, sparse_vec_randtest) (&M->rows[i], state, nnz, M->c, ctx); + } +} + +#endif diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c new file mode 100644 index 0000000000..8acc1551b1 --- /dev/null +++ b/fq_sparse_mat_templates/rref.c @@ -0,0 +1,94 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) +{ + if (M->r == 0 || M->c == 0) return 0; + slong *P; + slong i, j, r, c, pr, pc, rank, remr; + TEMPLATE(T, t) cinv, cc; + TEMPLATE(T, sparse_mat_t) Mt; + TEMPLATE(T, sparse_vec_struct) *pcol, *prow, *row, *col; + + P = flint_malloc(M->r*sizeof(*P)); + TEMPLATE(T, init) (cinv, ctx); + TEMPLATE(T, init) (cc, ctx); + TEMPLATE(T, sparse_mat_init) (Mt, M->c, M->r, ctx); + + /* Make transpose for doing column eliminations */ + TEMPLATE(T, sparse_mat_transpose) (Mt, M, ctx); + + /* Set up permutations */ + remr = M->r; + for (r = 0; rr; ++r) + { + if (!M->rows[r].nnz || M->rows[r].entries[0].ind >= M->c) P[r] = --remr; + else P[r] = -1; + } + + /* Run elimination */ + rank = 0; + for (pc=0; pcc; ++pc) + { + pcol = &Mt->rows[pc]; + + /* Get lowest weight incident row not used as previous pivot */ + pr = -1, prow = NULL; + for (j = 0; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &M->rows[r]; + if (P[r] >= 0) continue; + if (pr==-1 || (row->nnz < prow->nnz)) pr = r, prow = row; + } + if(pr == -1) continue; + P[pr] = rank; + + TEMPLATE(T, inv) (cinv, *TEMPLATE(T, sparse_vec_at) (prow, pc, ctx), ctx); + TEMPLATE(T, sparse_vec_scalar_mul) (prow, prow, cinv, ctx); + + /* Gaussian eliminate rows */ + for (j = 0; j < pcol->nnz; ++j) + { + r = pcol->entries[j].ind, row = &M->rows[r]; + if(r==pr) {TEMPLATE(T, zero) (pcol->entries[j].val, ctx); continue;} + + TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (row, pc, ctx), ctx); + TEMPLATE(T, sparse_vec_scalar_addmul) (row, row, prow, cc, ctx); + if (row->nnz == 0 || row->entries[0].ind >= M->c) P[r] = --remr; + } + /* Gaussian eliminate cols */ + TEMPLATE(T, sparse_vec_scalar_mul) (pcol, pcol, cinv, ctx); + for (j = 0; j < prow->nnz; ++j) + { + c = prow->entries[j].ind, col = &Mt->rows[c]; + if(c >= M->c || c==pc) continue; + TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (col, pr, ctx), ctx); + TEMPLATE(T, sparse_vec_scalar_addmul) (col, col, pcol, cc, ctx); + } + rank += 1; + } + /* Reorder rows */ + TEMPLATE(T, sparse_mat_permute_rows) (M, P, ctx); + + flint_free(P); + TEMPLATE(T, clear) (cinv, ctx); + TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, sparse_mat_clear) (Mt, ctx); + + return rank; +} + +#endif diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c new file mode 100644 index 0000000000..246cea4ca4 --- /dev/null +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -0,0 +1,246 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for + Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 + + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +/* Run row Gaussian elimination on first b block of [T I], save that, */ +/* if no pivot is found for a given column c, we Gaussian eliminate */ +/* the column c + b and zero out the row c. In addition, we reorder */ +/* columns so that ones corresponding to zero entries in S go first. */ +/* See Figure 1 in the above reference for details. */ +static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t) Torig, const TEMPLATE(T, ctx_t) ctx) { + + const slong b = Torig->r; + slong pc, i, j, rk = 0; + TEMPLATE(T, mat_t) T; + TEMPLATE(T, mat_struct) *X; + slong *P; + TEMPLATE(T, t) cc; + + P = flint_malloc(b * sizeof(*P)); + TEMPLATE(T, mat_init) (T, b, b, ctx); + TEMPLATE(T, mat_set) (T, Torig, ctx); + TEMPLATE(T, mat_one) (nWi, ctx); + + /* Set permutation to have previously dependent vectors at front */ + P = flint_malloc(b*sizeof(*P)); + for (i = j = 0; i < b; ++i) if(!S[i]) P[j++] = i; + for (i = j = 0; i < b; ++i) if(S[i]) P[j++] = i; + + for (j = 0; j < b; ++j) + { + pc = P[j]; /* Pivot col */ + + /* Find viable pivot row (from T if possible, then from W) */ + for (X = T, i = b; i == b; X = nWi) + for (i = j; i < b && TEMPLATE(T, is_zero)(&X->rows[P[i]][pc], ctx); ++i); + S[pc] = X == T; /* Viable column in V */ + TEMPLATE(T, mat_swap_rows) (T, NULL, pc, P[i], ctx); + TEMPLATE(T, mat_swap_rows) (nWi, NULL, pc, P[i], ctx); /* Now pivot row = pivot col */ + + /* Make pivot one */ + TEMPLATE(T, inv) (cc, &X->rows[pc][pc], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (T->rows[pc], T->rows[pc], b, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (nWi->rows[pc], nWi->rows[pc], b, cc, ctx); + + /* Kill all other entries in pivot column */ + for(i = 0; i < b; ++i) + { + TEMPLATE(T, neg) (cc, &X->rows[P[i]][pc], ctx); + if (i == j || TEMPLATE(T, is_zero) (cc, ctx)) continue; + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (T->rows[P[i]], T->rows[pc], T->c, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (nWi->rows[P[i]], nWi->rows[pc], nWi->c, cc, ctx); + } + if (S[pc]) rk++; /* Count viable columns */ + else + { + /* Kill row of both matrices */ + _TEMPLATE(T, vec_zero) (T->rows[pc], b, ctx); + _TEMPLATE(T, vec_zero) (nWi->rows[pc], b, ctx); + } + } + TEMPLATE(T, mat_neg) (nWi, nWi, ctx); + TEMPLATE(T, mat_clear) (T, ctx); + + return rk; +} + +static void kill_columns(TEMPLATE(T, mat_t) M, int *good, const TEMPLATE(T, ctx_t) ctx) +{ + slong r, c; + for (c = 0; c < M->c; ++c) + if(good[c] == 0) + for (r = 0; r < M->r; ++r) + TEMPLATE(T, zero) (&M->rows[r][c], ctx); +} + +int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { + int ret = 0; + slong i, j, prev_i, next_i, iter, cur_dim, total_dim = 0; + TEMPLATE(T, sparse_mat_t) Mt; /* Transpose of M, we work with A = MtM */ + TEMPLATE(T, mat_struct) V[3]; /* Keep track of current vector and two previous ones */ + TEMPLATE(T, mat_t) MV; /* Application of M to V */ + TEMPLATE(T, mat_t) AV; /* Application of Mt to MV */ + int *SSt; /* S is the maximal projection s.t. (VS)^tAVS is invertible, so SSt kills the dropped columns */ + TEMPLATE(T, mat_t) nWi[3]; /* -S((VS)^tAVS)^-1S^t */ + TEMPLATE(T, mat_t) VSSt; /* V with invalid vectors zeroed out */ + TEMPLATE(T, mat_t) T; /* Used to store transposes for inner products */ + TEMPLATE(T, mat_t) VtAV; /* Inner product _A */ + TEMPLATE(T, mat_t) AVtAVSSt_VtAV; /* Sum _A SS^t + _A, shared by two updates */ + TEMPLATE(T, mat_t) DEF; /* Used to store coefficient matrices D, E, and F */ + TEMPLATE(T, mat_t) I; /* I_{b x b} */ + TEMPLATE(T, struct) *SStVtb, *WiSStVtb, *VSStWiSStVtb; /* Intermediate elements in x update */ + if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + return 1; + } + + TEMPLATE(T, sparse_mat_init) (Mt, M->c, M->r, ctx); + for (i = 0; i < 3; ++i) TEMPLATE(T, mat_init) (&V[i], M->c, block_size, ctx); + TEMPLATE(T, mat_init) (MV, M->r, block_size, ctx); /* Intermediate product */ + TEMPLATE(T, mat_init) (AV, M->c, block_size, ctx); /* Symmetric product */ + SSt = flint_malloc(block_size*sizeof(*SSt)); + for (i = 0; i < 2; ++i) TEMPLATE(T, mat_init) (nWi[i], block_size, block_size, ctx); + TEMPLATE(T, mat_init) (T, block_size, M->c, ctx); /* Transpose for computing matrix dot products */ + TEMPLATE(T, mat_init) (VtAV, block_size, block_size, ctx); + TEMPLATE(T, mat_init) (AVtAVSSt_VtAV, block_size, block_size, ctx); // (AV)^T(AV) + VtAV + TEMPLATE(T, mat_init) (DEF, block_size, block_size, ctx); // Shared by D, E, and F + TEMPLATE(T, mat_init) (I, block_size, block_size, ctx); + SStVtb = _TEMPLATE(T, vec_init) (block_size, ctx); + WiSStVtb = _TEMPLATE(T, vec_init) (block_size, ctx); + VSStWiSStVtb = _TEMPLATE(T, vec_init) (M->c, ctx); + + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + TEMPLATE(T, sparse_mat_transpose) (Mt, M, ctx); + for (i = 0; i < block_size; ++i) SSt[i] = 1; + TEMPLATE(T, mat_one) (I, ctx); + + // Initialize V[0] randomly + for (i = 0; i < V[0].r*V[0].c; ++i) + TEMPLATE(T, randtest) (&V[0].entries[i], state, ctx); + + for(iter = 0; ; ++iter) + { + i = iter % 3; + next_i = (iter + 1) % 3; + prev_i = (iter + 2) % 3; + if(iter>=2) + { + /* Compute the F value for this round (minus the final term) */ + TEMPLATE(T, mat_addmul) (DEF, I, VtAV, nWi[prev_i], ctx); + TEMPLATE(T, mat_mul) (nWi[i], nWi[next_i], DEF, ctx); /* nWi[i] used for scratch */ + TEMPLATE(T, mat_mul) (DEF, nWi[i], AVtAVSSt_VtAV, ctx); + } + + /* Compute AV and V'AV */ + TEMPLATE(T, sparse_mat_mul_mat) (MV, M, &V[i], ctx); + TEMPLATE(T, sparse_mat_mul_mat) (AV, Mt, MV, ctx); + TEMPLATE(T, mat_transpose) (T, &V[i], ctx); + TEMPLATE(T, mat_mul) (VtAV, T, AV, ctx); + + /* Compute W^{-1} and indices of bad vectors */ + cur_dim = compute_nWi_S(nWi[i], SSt, VtAV, ctx); + total_dim += cur_dim; + if (cur_dim == 0 || total_dim > M->c) break; /* Ran out of vectors */ + + /* Update x_i = x_{i-1} - (VSS^t) W^{-1} (VSS^t)^tb */ + TEMPLATE(T, mat_set) (VSSt, &V[i], ctx); + kill_columns(VSSt, SSt, ctx); + TEMPLATE(T, mat_transpose) (T, VSSt, ctx); + TEMPLATE(T, mat_mul_vec) (SStVtb, T, b, ctx); + TEMPLATE(T, mat_mul_vec) (WiSStVtb, nWi[i], SStVtb, ctx); + TEMPLATE(T, mat_mul_vec) (VSStWiSStVtb, VSSt, WiSStVtb, ctx); + _TEMPLATE(T, vec_add) (x, x, VSStWiSStVtb, M->c, ctx); + + /** + * Per Equation (19), we compute the next vector + * V_{i+1} = AV_iS_iS_i^t + V_i D + V_{i-1} E + V_{i-2} F + * where + * D = I - W_i^-1((AV_i)^tAV_iS_iS_i^t + V_i^tAV_i) + * E = -W_{i-1}^-1V_i^tAV_iS_iS_i^t + * F = -W_{i-2}^-1(I - V_{i-1}^tAV_{i-1}W_{i-1}^-1) + * ((AV_{i-1})^tAV_{i-1}S_{i-1}S_{i-1}^t + V_{i-1}^tAV_{i-1})S_iS_i^t + **/ + if(iter >= 2) + { + /* V_{i+1} = V_{i-2} F */ + kill_columns(DEF, SSt, ctx); + TEMPLATE(T, mat_mul) (&V[next_i], &V[next_i], DEF, ctx); + } + if(iter >= 1) + { + /* V_{i+1} += V_{i-1} E */ + TEMPLATE(T, mat_mul) (DEF, nWi[prev_i], VtAV, ctx); + kill_columns(DEF, SSt, ctx); + TEMPLATE(T, mat_addmul) (&V[next_i], &V[next_i], &V[prev_i], DEF, ctx); + } + /* V_{i+1} += V_i D */ + TEMPLATE(T, mat_transpose) (T, AV, ctx); + TEMPLATE(T, mat_mul) (AVtAVSSt_VtAV, T, AV, ctx); + kill_columns(AVtAVSSt_VtAV, SSt, ctx); + TEMPLATE(T, mat_add) (AVtAVSSt_VtAV, AVtAVSSt_VtAV, VtAV, ctx); + TEMPLATE(T, mat_addmul) (DEF, I, nWi[i], AVtAVSSt_VtAV, ctx); + TEMPLATE(T, mat_addmul) (&V[next_i], &V[next_i], &V[i], DEF, ctx); + + /* V_{i+1} += AVSS^t */ + kill_columns(AV, SSt, ctx); + TEMPLATE(T, mat_add) (&V[next_i], &V[next_i], AV, ctx); + + if(TEMPLATE(T, mat_is_zero) (&V[i], ctx)) {ret = 1; break;} + } + TEMPLATE(T, sparse_mat_clear) (Mt, ctx); + for (i = 0; i < 3; ++i) TEMPLATE(T, mat_clear) (&V[i], ctx); + TEMPLATE(T, mat_clear) (MV, ctx); + TEMPLATE(T, mat_clear) (AV, ctx); + flint_free(SSt); + for (i = 0; i < 2; ++i) TEMPLATE(T, mat_clear) (nWi[i], ctx); + TEMPLATE(T, mat_clear) (T, ctx); + TEMPLATE(T, mat_clear) (VtAV, ctx); + TEMPLATE(T, mat_clear) (AVtAVSSt_VtAV, ctx); + TEMPLATE(T, mat_clear) (DEF, ctx); + TEMPLATE(T, mat_clear) (I, ctx); + _TEMPLATE(T, vec_clear) (SStVtb, block_size, ctx); + _TEMPLATE(T, vec_clear) (WiSStVtb, block_size, ctx); + _TEMPLATE(T, vec_clear) (VSStWiSStVtb, M->c, ctx); + return ret; +} + +int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { + int ret = 1; + TEMPLATE(T, struct) *x2, *b; + x2 = _TEMPLATE(T, vec_init) (M->c, ctx); + b = _TEMPLATE(T, vec_init) (M->r, ctx); + + _TEMPLATE(T, vec_randtest) (x, state, M->c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); + if(TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, M, b, block_size, state, ctx) == 0) ret = 0; /* Lanczos failed */ + if (ret) + { + _TEMPLATE(T, vec_sub) (x, x, x2, M->c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); + ret = _TEMPLATE(T, vec_is_zero) (x, M->c, ctx) || !_TEMPLATE(T, vec_is_zero) (b, M->r, ctx); + } + _TEMPLATE(T, vec_clear) (x2, M->c, ctx); + _TEMPLATE(T, vec_clear) (b, M->r, ctx); + return ret; +} + + +#endif diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c new file mode 100644 index 0000000000..e4c83b2211 --- /dev/null +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -0,0 +1,266 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +/* Compute S_i=(M^j Y)_{0...b-1}^T for i=0,...,ns-1 */ +static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Y[2], const TEMPLATE(T, ctx_t) ctx) +{ + slong iter, i, j, k, b = Y->c; + TEMPLATE(T, mat_struct) W[2]; + for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_init) (&W[i], Y, 0, 0, b, b, ctx); + for (i = iter = 0; iter < ns; ++iter, i = 1-i) + { + if (i > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Y[i], M, &Y[1-i], ctx); + TEMPLATE(T, mat_transpose) (&S[iter], &W[i], ctx); + } + for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_clear) (&W[i], ctx); +} + +/** + * Run Guassian elimination on the first b columns of the augmented + * matrix M = [ D | I], yielding a final matrix + * [ | ] [ Z | ] + * [ D | I ] -> [---| tau ] + * [ | ] [ L | ] + * where the the number of nonzero rows in Z is the ith rank. We choose + * the pivot row for a given column to be the one with minimal degree. +**/ +static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE(T, ctx_t) ctx) +{ + const slong b = M->r/2; + slong pr, pc, r, c, k, tmp; + slong num_pi; + slong *gamma; + TEMPLATE(T, t) cinv, cc; + TEMPLATE(T, mat_t) tau; + TEMPLATE(T, init) (cinv, ctx); + TEMPLATE(T, init) (cc, ctx); + /* Keep track of viable rows */ + gamma = flint_malloc(b*sizeof(*gamma)); + for (r = 0; r < b; ++r) gamma[r] = 1; + + for (pc = 0; pc < b; ++pc) + { + /* Set the pivot row to be the minimum degree row incident on column pc */ + pr = b + pc; + for (r = 0; r < b; r++) + if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; + + /* Try to move pivot row to appropriate position (if not already there) */ + if (pr != b + pc) + { + tmp = d[pr]; d[pr] = d[b+pc]; d[b+pc] = tmp; + + if (!TEMPLATE(T, is_zero) (&M->rows[b + pc][pr], ctx)) + TEMPLATE(T, mat_swap_rows)(M, NULL, pr, b + pc, ctx), pr = b + pc; + else /* Need to make new auxiliary vector and remove r from use */ + _TEMPLATE(T, vec_add) (M->rows[b + pc], M->rows[b + pc], M->rows[pr], 3*b, ctx), gamma[pr] = 0; + } + TEMPLATE(T, inv) (cinv, &M->rows[pr][pc], ctx); + + /* Do Gaussian elimination on first b rows */ + for (r = 0; r < b; ++k) + if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) + { + TEMPLATE(T, mul) (cc, &M->rows[r][pc], cinv, ctx); + TEMPLATE(T, neg) (cc, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T))(M->rows[r], M->rows[pr], M->c, cc, ctx); + } + } + TEMPLATE(T, clear) (cinv, ctx); + TEMPLATE(T, clear) (cc, ctx); + flint_free(gamma); +} + +/* Stop with failure if sum(d_0 ... d_{b-1}) < delta */ +/* Stop with success if sum(d_0 ... d_{b-1}) < delta + max(d_0 ... d_{b-1}) - min(d_b ... d_{2b-1}) */ +static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) +{ + slong tmp, r; + + /* Sum degrees of generating polynomials */ + tmp = d[0]; for (r = 1; r < b; ++r) tmp += d[r]; + delta -= tmp; + if (delta < 0) return 0; /* Insufficient degree */ + + /* Add maximum degree of first b polys and subtract minimum degree of last b */ + tmp = d[0]; for (r = 1; r < b; ++r) if (d[r] > tmp) tmp = d[r]; + delta += tmp; + tmp = d[b]; for (r = b + 1; r < 2*b; ++r) if (d[r] < tmp) tmp = d[r]; + delta -= tmp; + return delta < 0 ? 1 : -1; +} + +/** + * Generalization of Berlekamp-Massey due to Coppersmith. + * Iteratively computes a sequence F representing 2b polynomials: + * - the first b are the current (reversed) generating polynomials + * - the last b are certain auxiliary polynomials. +**/ +static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, const TEMPLATE(T, ctx_t) ctx) +{ + int ret; + slong t, sigma, beta, mu; + slong i, j, k, r, b = S->r; + slong f_len; + TEMPLATE(T, mat_struct) *F; + TEMPLATE(T, mat_t) M, D, tau; + + f_len = 1; + F = flint_malloc(n*sizeof(*F)); + TEMPLATE(T, mat_init) (&F[0], 2*b, b, ctx); + for (i = 0; i < b; ++i) d[i] = 0, d[b + i] = 1, TEMPLATE(T, one) (&F[0].rows[i][i], ctx); + + /* [ D | I ] -> [ ? | tau ]*/ + TEMPLATE(T, mat_init) (M, 2*b, 3*b, ctx); + + for (t = 0; (ret = coppersmith_stopping_criterion(d, n, b)) == -1; ++t) + { + /* Compute discrepancy matrix and tau */ + TEMPLATE(T, mat_window_init) (D, M, 0, 0, 2*b, b, ctx); + TEMPLATE(T, mat_window_init) (tau, M, 0, b, 2*b, 3*b, ctx); + TEMPLATE(T, mat_zero) (D, ctx); + for(k = 0; k <= t; ++k) TEMPLATE(T, mat_addmul) (D, D, &F[k], &S[t-k], ctx); + TEMPLATE(T, mat_one) (tau, ctx); + TEMPLATE(T, mat_window_clear) (D, ctx); + TEMPLATE(T, mat_window_clear) (tau, ctx); + coppersmith_aux_gauss(M, d, ctx); + + /* Multiply F by tau * diag(I xI) */ + TEMPLATE(T, mat_window_init) (tau, M, 0, b, 2*b, 3*b, ctx); /* Needed since gauss reorders rows */ + TEMPLATE(T, mat_init) (&F[f_len++], 2*b, b, ctx); + for (k = f_len-1; k > 0; --k) + TEMPLATE(T, mat_mul) (&F[k], tau, &F[k-1], ctx); /* Every row multiplied by x */ + for (k = 0; k < f_len; ++k) + for(r = 0; r < b; ++r) /* Divide first b rows by x */ + (k < f_len - 1) ? _TEMPLATE(T, vec_set) (F[k].rows[r], F[k+1].rows[r], b, ctx) : _TEMPLATE(T, vec_zero) (F[k].rows[r], b, ctx); + for (r = b; r < 2*b; ++r) d[r] += 1; + TEMPLATE(T, mat_window_clear) (tau, ctx); + } + + /* Copy C to S, with each row reversed according to its degree */ + for(r = 0; r < b; ++r) + for(k = 0; k <= d[r]; k++) + _TEMPLATE(T, vec_set) (S[d[r] - k].rows[r], F[k].rows[r], b, ctx); + + for(k = 0; k < f_len; ++k) TEMPLATE(T, mat_clear) (&F[i], ctx); + TEMPLATE(T, mat_clear) (M, ctx); + flint_free(F); + flint_free(d); + return ret; +} + +static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) *S, const slong *d, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Z[2], slong l, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, iter, k, nu, b = S->r; + slong *dd; + TEMPLATE(T, struct) *v, *xi; + + /* Compute differences between nominal and real degrees of each coordinate polynomial in row l */ + dd = flint_malloc(b*sizeof(*dd)); + for (nu = 0; nu < b; nu++); + for (dd[nu] = 0; dd[nu] <= d[l]; ++dd[nu]) + if(!TEMPLATE(T, is_zero) (&S[dd[nu]].rows[l][nu], ctx)) break; + + /* Simulaneously apply all polynomials in row l to iteration of M on Z */ + v = _TEMPLATE(T, vec_init) (b, ctx); + xi = _TEMPLATE(T, vec_init) (M->c, ctx); + _TEMPLATE(T, vec_zero) (x, M->r, ctx); + for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) + { + if(iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); + for(nu = 0; nu < b; nu++) + { + if (dd[nu] <= d[l]) TEMPLATE(T, set) (&v[nu], &S[dd[nu]++].rows[l][nu], ctx); + else TEMPLATE(T, zero) (&v[nu], ctx); + } + TEMPLATE(T, sparse_mat_mul_vec) (xi, M, v, ctx); + _TEMPLATE(T, vec_add) (x, x, xi, M->c, ctx); + } + _TEMPLATE(T, vec_clear) (v, b, ctx); + _TEMPLATE(T, vec_clear) (xi, M->c, ctx); + flint_free(dd); +} + +int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ + int good = 0; + slong i; + TEMPLATE(T, struct) *x1; + TEMPLATE(T, sparse_vec_t) z; + TEMPLATE(T, sparse_mat_t) Mb; + TEMPLATE(T, sparse_vec_struct) *row; + TEMPLATE(T, sparse_entry_struct) *le, *re; + if (M->r != M->c) return 0; /* TODO */ + if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + return 1; + } + + /* TODO: Precondition M */ + x1 = _TEMPLATE(T, vec_init) (M->c + 1, ctx); + TEMPLATE(T, sparse_vec_init) (z, ctx); + TEMPLATE(T, sparse_mat_init) (Mb, M->r, M->c, ctx); + TEMPLATE(T, sparse_mat_set) (Mb, M, ctx); + TEMPLATE(T, sparse_mat_append_col) (Mb, b, ctx); + TEMPLATE(T, sparse_mat_append_row) (Mb, z, ctx); + TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (x1, Mb, block_size, state, ctx); + TEMPLATE(T, sparse_vec_clear) (z, ctx); + TEMPLATE(T, sparse_mat_clear) (Mb, ctx); + + if(!TEMPLATE(T, is_zero) (&x1[M->c], ctx)) + { + TEMPLATE(T, inv) (&x1[M->c], &x1[M->c], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x1, M->c, &x1[M->c], ctx); + good = 1; + } + _TEMPLATE(T, vec_clear) (x1, M->c + 1, ctx); + return good; +} + +int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ + int ret = 0; + slong l, ns; + slong *d; + TEMPLATE(T, struct) *b; + TEMPLATE(T, mat_t) Z; + TEMPLATE(T, mat_struct) Y[3], *S; + if (M->r != M->c) return 0; /* TODO */ + + ns = 2*M->r/block_size + 3; /* Maybe 5? */ + d = flint_calloc(2*block_size, sizeof(*d)); + b = _TEMPLATE(T, vec_init) (M->r, ctx); + for (l = 0; l < 3; ++l) + TEMPLATE(T, mat_init) (&Y[l], M->c, block_size, ctx); + TEMPLATE(T, mat_randtest) (&Y[0], state, ctx); + TEMPLATE(T, sparse_mat_mul_mat) (&Y[1], M, &Y[0], ctx); + make_block_sequences(S, ns, M, &Y[1], ctx); + find_block_min_poly(S, d, ns, ctx); + + for (l = 0; l < block_size; ++l) + { + TEMPLATE(T, mat_set) (&Y[1], &Y[0], ctx); + make_block_sum(x, S, d, M, Y + 1, l, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) {ret = 1; break;}; + } + return ret; +} + + + +#endif diff --git a/fq_sparse_mat_templates/solve_lanczos.c b/fq_sparse_mat_templates/solve_lanczos.c new file mode 100644 index 0000000000..b9b48f8104 --- /dev/null +++ b/fq_sparse_mat_templates/solve_lanczos.c @@ -0,0 +1,125 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +int TEMPLATE(T, sparse_mat_solve_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ + slong j, ret; + + /* We assume that M is not symmetric, and work with A = M^t M */ + TEMPLATE(T, t) cinv, cc, AvtAv, vMtb, alpha, beta; + TEMPLATE(T, struct) *v[2], *Mv, *Av, *Mtb, vtAv[2]; + TEMPLATE(T, sparse_mat_t) Mt; + + if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + return 1; + } + + TEMPLATE(T, init) (cinv, ctx); + TEMPLATE(T, init) (cc, ctx); + TEMPLATE(T, init) (AvtAv, ctx); + TEMPLATE(T, init) (vMtb, ctx); + TEMPLATE(T, init) (alpha, ctx); + TEMPLATE(T, init) (beta, ctx); + TEMPLATE(T, init) (&vtAv[0], ctx); + TEMPLATE(T, init) (&vtAv[1], ctx); + v[0] = _TEMPLATE(T, vec_init) (M->c, ctx); + v[1] = _TEMPLATE(T, vec_init) (M->c, ctx); + Mv = _TEMPLATE(T, vec_init) (M->r, ctx); + Av = _TEMPLATE(T, vec_init) (M->c, ctx); + Mtb = _TEMPLATE(T, vec_init) (M->c, ctx); + TEMPLATE(T, sparse_mat_init) (Mt, M->c, M->r, ctx); + + /* Construct transpose */ + TEMPLATE(T, sparse_mat_transpose) (Mt, M, ctx); + + + /* Set starting data */ + _TEMPLATE(T, vec_randtest) (v[0], state, M->c, ctx); + _TEMPLATE(T, vec_zero) (v[1], M->c, ctx); + TEMPLATE(T, one) (&vtAv[1], ctx); + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Mtb, Mt, b, ctx); + for (j = 0; ; j = 1-j) + { + /* Compute M^T M v_j and check if it is orthogonal to v_j */ + TEMPLATE(T, sparse_mat_mul_vec) (Mv, M, v[j], ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Av, Mt, Mv, ctx); + _TEMPLATE(T, vec_dot) (&vtAv[j], v[j], Av, M->c, ctx); + if (TEMPLATE(T, is_zero) (&vtAv[j], ctx)) break; /* Can't make any more progress */ + + /* Update putative solution by /delta_j * v_j */ + _TEMPLATE(T, vec_dot) (cc, v[j], Mtb, M->c, ctx); + TEMPLATE(T, div) (cc, cc, &vtAv[j], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, v[j], M->c, cc, ctx); + + /* v_{j+1} = AtAv - alpha*v_j - beta*v_{j-1}, where */ + /* alpha = /delta_j, and */ + /* beta = delta_j/delta_{j-1} */ + TEMPLATE(T, div) (cc, &vtAv[j], &vtAv[1-j], ctx); + TEMPLATE(T, neg) (cc, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T))(v[1-j], v[1-j], M->c, cc, ctx); + _TEMPLATE(T, vec_dot) (cc, Av, Av, M->c, ctx); + TEMPLATE(T, div) (cc, cc, &vtAv[j], ctx); + TEMPLATE(T, neg) (cc, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (v[1-j], v[j], M->c, cc, ctx); + _TEMPLATE(T, vec_add) (v[1-j], v[1-j], Av, M->c, ctx); + } + /* Check result */ + TEMPLATE(T, sparse_mat_mul_vec) (Mv, M, x, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Av, Mt, Mv, ctx); + ret = _TEMPLATE(T, vec_equal) (Av, Mtb, M->c, ctx); + + /* Clear auxiliary vectors and transpose */ + TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, clear) (cinv, ctx); + TEMPLATE(T, clear) (AvtAv, ctx); + TEMPLATE(T, clear) (vMtb, ctx); + TEMPLATE(T, clear) (alpha, ctx); + TEMPLATE(T, clear) (beta, ctx); + TEMPLATE(T, clear) (&vtAv[0], ctx); + TEMPLATE(T, clear) (&vtAv[1], ctx); + _TEMPLATE(T, vec_clear) (v[0], M->c, ctx); + _TEMPLATE(T, vec_clear) (v[1], M->c, ctx); + _TEMPLATE(T, vec_clear) (Mv, M->r, ctx); + _TEMPLATE(T, vec_clear) (Av, M->c, ctx); + _TEMPLATE(T, vec_clear) (Mtb, M->c, ctx); + TEMPLATE(T, sparse_mat_clear) (Mt, ctx); + return ret; +} + +int TEMPLATE(T, sparse_mat_nullvector_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { + int ret = 1; + TEMPLATE(T, struct) *x2, *b; + x2 = _TEMPLATE(T, vec_init) (M->c, ctx); + b = _TEMPLATE(T, vec_init) (M->r, ctx); + + _TEMPLATE(T, vec_randtest) (x, state, M->c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); + if(TEMPLATE(T, sparse_mat_solve_lanczos) (x2, M, b, state, ctx) == 0) ret = 0; /* Lanczos failed */ + if (ret) + { + _TEMPLATE(T, vec_sub) (x, x, x2, M->c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); + ret = !_TEMPLATE(T, vec_is_zero) (x, M->c, ctx) && _TEMPLATE(T, vec_is_zero) (b, M->r, ctx); + } + _TEMPLATE(T, vec_clear) (x2, M->c, ctx); + _TEMPLATE(T, vec_clear) (b, M->r, ctx); + return ret; +} + +#endif diff --git a/fq_sparse_mat_templates/solve_lu.c b/fq_sparse_mat_templates/solve_lu.c new file mode 100644 index 0000000000..b2df8d78b0 --- /dev/null +++ b/fq_sparse_mat_templates/solve_lu.c @@ -0,0 +1,75 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x=Qx' */ +int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx) +{ + int good = 1; + slong rk, *P, *Q, i, j; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) *bp, *y, *xp; + TEMPLATE(T, sparse_mat_t) L, U; + if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + return 1; + } + + P = flint_malloc(M->r * sizeof(*P)); + Q = flint_malloc(M->c * sizeof(*Q)); + TEMPLATE(T, init) (cc, ctx); + bp = _TEMPLATE(T, vec_init) (M->r, ctx); + xp = _TEMPLATE(T, vec_init) (M->c, ctx); + TEMPLATE(T, sparse_mat_init) (L, M->r, M->c, ctx); + TEMPLATE(T, sparse_mat_init) (U, M->r, M->c, ctx); + + rk = TEMPLATE(T, sparse_mat_lu) (P, Q, L, U, M, ctx); + y = _TEMPLATE(T, vec_init) (rk, ctx); + + /* Solve Ly = b' = Pb */ + for (i = 0; i < M->r; ++i) TEMPLATE(T, set) (&bp[P[i]], &b[i], ctx); + + for (i = 0; i < rk; ++i) + { + TEMPLATE(T, sparse_vec_dot_dense) (cc, &L->rows[i], y, ctx); + TEMPLATE(T, sub) (&y[i], &bp[i], cc, ctx); + } + for (i = rk; i < M->r; ++i) + { + TEMPLATE(T, sparse_vec_dot_dense) (cc, &L->rows[i], y, ctx); + if (!TEMPLATE(T, equal) (&bp[i], cc, ctx)) {good = 0; break;} + } + + if (good) + { + /* Find a solution for Ux' = y */ + for (i = rk-1; i >= 0; --i) + { + TEMPLATE(T, sparse_vec_dot_dense) (&xp[i], &U->rows[i], xp, ctx); + TEMPLATE(T, sub) (&xp[i], &y[i], &xp[i], ctx); + TEMPLATE(T, div) (&xp[i], &xp[i], U->rows[i].entries[0].val, ctx); + } + for(i = 0; i < M->c; ++i) TEMPLATE(T, set) (&x[i], &xp[Q[i]], ctx); + } + TEMPLATE(T, sparse_mat_clear) (L, ctx); + TEMPLATE(T, sparse_mat_clear) (U, ctx); + _TEMPLATE(T, vec_clear) (xp, M->c, ctx); + _TEMPLATE(T, vec_clear) (y, rk, ctx); + _TEMPLATE(T, vec_clear) (bp, M->r, ctx); + return good; +} + +#endif diff --git a/fq_sparse_mat_templates/solve_rref.c b/fq_sparse_mat_templates/solve_rref.c new file mode 100644 index 0000000000..04ebc553bf --- /dev/null +++ b/fq_sparse_mat_templates/solve_rref.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +int TEMPLATE(T, sparse_mat_solve_rref) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx) +{ + int good = 1; + slong i; + TEMPLATE(T, sparse_mat_t) Mb; + TEMPLATE(T, sparse_vec_struct) *row; + TEMPLATE(T, sparse_entry_struct) *le, *re; + if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + return 1; + } + + TEMPLATE(T, sparse_mat_init) (Mb, M->r, M->c, ctx); + + TEMPLATE(T, sparse_mat_set) (Mb, M, ctx); + TEMPLATE(T, sparse_mat_append_col) (Mb, b, ctx); + Mb->c = M->c; + TEMPLATE(T, sparse_mat_rref) (Mb, ctx); + Mb->c = M->c+1; + + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + for (i = 0; i < M->r; ++i) + { + row = &Mb->rows[i]; + if (row->nnz == 0) continue; + le = &row->entries[0]; + re = &row->entries[row->nnz-1]; + /* If any row has leading col M->c, system is not solvable */ + if (le->ind==M->c) {good = 0; break;} + /* Otherwise, x[lc] = lagging value */ + if (re->ind==M->c) TEMPLATE(T, set) (&x[le->ind], re->val, ctx); + } + TEMPLATE(T, sparse_mat_clear) (Mb, ctx); +} + +#endif diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c new file mode 100644 index 0000000000..b1dc94ac2f --- /dev/null +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -0,0 +1,182 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +// Berlekamp - Massey algorithm +static slong find_min_poly(TEMPLATE(T, struct) *s, slong N, const TEMPLATE(T, ctx_t) ctx) +{ + slong L = 0, m, n, i; + slong deg_C = 0, deg_B = 0, deg_T = -1; + TEMPLATE(T, t) cinv, cc, d_C, d_B; + TEMPLATE(T, struct) *B, *C, *T; + + TEMPLATE(T, init) (cinv, ctx); + TEMPLATE(T, init) (cc, ctx); + TEMPLATE(T, init) (d_C, ctx); + TEMPLATE(T, init) (d_B, ctx); + B = _TEMPLATE(T, vec_init) (N, ctx); + C = _TEMPLATE(T, vec_init) (N, ctx); + T = _TEMPLATE(T, vec_init) (N, ctx); + TEMPLATE(T, one) (&B[0], ctx); + TEMPLATE(T, one) (&C[0], ctx); + TEMPLATE(T, one) (d_B, ctx); + + for (n = 0, m = 1; n < N; n++, m++) + { + /* d_C = sum_{i=0}^L C_i * s_{n-i} */ + TEMPLATE(T, set) (d_C, &s[n], ctx); + for (i = 1; i <= L; i++) + { + TEMPLATE(T, mul) (cc, &C[i], &s[n-i], ctx); + TEMPLATE(T, add) (d_C, d_C, cc, ctx); + } + if (TEMPLATE(T, is_zero)(d_C, ctx)) continue; /* C and L currently valid */ + + /* C(x) = C(x) - (d_C/d_B) x^m B(x); */ + if (L <= 2*n) deg_T = deg_C, _TEMPLATE(T, vec_set) (T, C, deg_C+1, ctx); /* T(X) = C(X) */ + TEMPLATE(T, div) (cinv, d_C, d_B, ctx); + TEMPLATE(T, neg) (cinv, cinv, ctx); + for (i = 0; i <= deg_B; ++i) + { + TEMPLATE(T, mul) (cc, &B[i], cinv, ctx); + TEMPLATE(T, add) (&C[m+i], &C[m+i], cc, ctx); + } + deg_C = FLINT_MAX(deg_C, deg_B + m); + while(TEMPLATE(T, is_zero) (&C[deg_C], ctx)) --deg_C; /* Probably unnecessary */ + + if (2*L <= n) /* Increase number of errors */ + { + L = n + 1 - L, m = 0; + TEMPLATE(T, set) (d_B, d_C, ctx), deg_B = deg_T; + _TEMPLATE(T, vec_set) (B, T, deg_T+1, ctx); + } + } + /* Reverse C into s */ + for (i = 0; i <= L; ++i) TEMPLATE(T, set) (&s[i], &C[L-i], ctx); + + TEMPLATE(T, clear) (cinv, ctx); + TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, clear) (d_C, ctx); + TEMPLATE(T, clear) (d_B, ctx); + _TEMPLATE(T, vec_clear) (B, N, ctx); + _TEMPLATE(T, vec_clear) (C, N, ctx); + _TEMPLATE(T, vec_clear) (T, N, ctx); + return L; +} + +/* Compute s_ij=(A^j y)_i for i=0,...,ns-1, j=0,...,num-1*/ +static void make_sequences(TEMPLATE(T, struct) **s, slong ns, slong len, const TEMPLATE(T, sparse_mat_t) A, TEMPLATE(T, struct) **y, const TEMPLATE(T, ctx_t) ctx) +{ + slong iter, i, j; + for (i = iter = 0; iter < len; ++iter, i = 1-i) + { + if(iter > 0) TEMPLATE(T, sparse_mat_mul_vec) (y[i], A, y[1-i], ctx); + for(j = 0; j < ns; ++j) TEMPLATE(T, set) (&s[j][iter], &y[i][j], ctx); + } +} + +/* Compute x = \Sigma_{i=0}^{L-1} s_i * A^i * b = 0 */ +static void make_sum(TEMPLATE(T, struct) *x, TEMPLATE(T, struct) *s, slong L, const TEMPLATE(T, sparse_mat_t) A, TEMPLATE(T, struct) **y, const TEMPLATE(T, ctx_t) ctx) +{ + slong iter, i; + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, y[0], A->r, &s[0], ctx); + for (i = iter = 1; iter < L; ++iter, i = 1-i) + { + TEMPLATE(T, sparse_mat_mul_vec) (y[i], A, y[1-i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, y[i], A->r, &s[iter], ctx); + } +} + +int TEMPLATE(T, sparse_mat_solve_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) A, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) **s, *y[2]; + if(A->r != A->c) return 0; /* TBD: reduce to square */ + if(_TEMPLATE(T, vec_is_zero) (b, A->r, ctx)) + { + _TEMPLATE(T, vec_zero) (x, A->c, ctx); + return 1; + } + TEMPLATE(T, init) (cc, ctx); + s = flint_malloc(ns * sizeof(*s)); + for (i = 0; i < ns; ++i) s[i] = _TEMPLATE(T, vec_init) (len, ctx); + for (i = 0; i < 2; ++i) y[i] = _TEMPLATE(T, vec_init) (A->r, ctx); + + _TEMPLATE(T, vec_set) (y[0], b, A->r, ctx); + + /* Make some number of sequences to be tried */ + make_sequences(s, ns, len, A, y, ctx); + + /* Try both sequences */ + for (i = 0; i < ns && ret == 0; ++i) + { + /* Get minimal polynomial */ + L = find_min_poly(s[i], len, ctx); + if(TEMPLATE(T, is_zero) (&s[i][0], ctx)) continue; + + /* If \sum_{j=0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j=0}^{L-1} s_i(j-1) A^jb solves Ax=b */ + _TEMPLATE(T, vec_set) (y[0], b, A->r, ctx); + make_sum(x, s[i]+1, L, A, y, ctx); + TEMPLATE(T, inv) (cc, &s[i][0], ctx); + TEMPLATE(T, neg) (cc, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, A->r, cc, ctx); + + /* Check if successful */ + TEMPLATE(T, sparse_mat_mul_vec) (y[0], A, x, ctx); + ret = _TEMPLATE(T, vec_equal) (y[0], b, A->r, ctx); + } + + TEMPLATE(T, clear) (cc, ctx); + for (i = 0; i < ns; ++i) _TEMPLATE(T, vec_clear) (s[i], len, ctx); + for (i = 0; i < 2; ++i) _TEMPLATE(T, vec_clear) (y[i], A->r, ctx); + flint_free(s); + return ret; +} + +int TEMPLATE(T, sparse_mat_nullvector_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) A, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + TEMPLATE(T, struct) **s, *y[3]; + + if(A->r != A->c) return 0; /* TBD: reduce to square */ + + s = flint_malloc(ns * sizeof(*s)); + for (i = 0; i < ns; ++i) s[i] = _TEMPLATE(T, vec_init) (len, ctx); + for (i = 0; i < 3; ++i) y[i] = _TEMPLATE(T, vec_init) (A->r, ctx); + + _TEMPLATE(T, vec_randtest) (y[0], state, A->r, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (y[1], A, y[0], ctx); + + make_sequences(s, ns, len, A, &y[1], ctx); + + for (i = 0; i < ns && ret == 0; ++i) + { + /* Get minimal polynomial */ + L = find_min_poly(s[i], len, ctx); + + /* \sum_{j=0}^L s_ijA^jb = 0 => x = \sum_{j=0}^L s_ijA^jx solves Ax=0 */ + _TEMPLATE(T, vec_set) (y[1], y[0], A->r, ctx); + make_sum(x, s[i], L+1, A, &y[1], ctx); + TEMPLATE(T, sparse_mat_mul_vec) (y[1], A, x, ctx); + ret = _TEMPLATE(T, vec_is_zero) (y[1], A->r, ctx); + } + for (i = 0; i < ns; ++i) _TEMPLATE(T, vec_clear) (s[i], len, ctx); + for (i = 0; i < 3; ++i) _TEMPLATE(T, vec_clear) (y[i], A->r, ctx); + flint_free(s); + return ret; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-add.c b/fq_sparse_mat_templates/test/t-add.c new file mode 100644 index 0000000000..9795b791a3 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-add.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 200); + c = n_randint(state, 200); + + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (C, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (D, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 0, c, ctx); + + TEMPLATE(T, sparse_mat_add) (C, A, B, ctx); + TEMPLATE(T, sparse_mat_sub) (D, C, B, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (D, A, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, sparse_mat_clear) (D, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-concat_horizontal.c b/fq_sparse_mat_templates/test/t-concat_horizontal.c new file mode 100644 index 0000000000..107b1ed22f --- /dev/null +++ b/fq_sparse_mat_templates/test/t-concat_horizontal.c @@ -0,0 +1,105 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int main(void) +{ + slong rep, r, c1, c2, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C; + TEMPLATE(T, sparse_mat_t) window1, window2; + FLINT_TEST_INIT(state); + + flint_printf("concat_horizontal...."); + fflush(stdout); + + + for (i = 0; i < 100; i++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 20); + c1 = n_randint(state, 20); + c2 = n_randint(state, 20); + TEMPLATE(T, sparse_mat_init) (A, r, c1, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c2, ctx); + TEMPLATE(T, sparse_mat_init) (C, r, c1+c2, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c1, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 0, c2, ctx); + TEMPLATE(T, sparse_mat_randtest) (C, state, 0, c1+c2, ctx); + + TEMPLATE(T, sparse_mat_concat_horizontal) (C, A, B, ctx); + + TEMPLATE(T, sparse_mat_window_init) (window1, C, 0, 0, r, c1, ctx); + TEMPLATE(T, sparse_mat_window_init) (window2, C, 0, c1, r, c1+c2, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (window1, A, ctx) || !TEMPLATE(T, sparse_mat_equal) (window2, B, ctx)) + { + flint_printf("A = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (B, ctx); + flint_printf("A | B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (C, ctx); + flint_printf("window1 = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (window1, ctx); + flint_printf("window2 = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (window2, ctx); + flint_printf("FAIL: window 2 not equal\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_window_clear) (window1, ctx); + TEMPLATE(T, sparse_mat_window_clear) (window2, ctx); + + TEMPLATE(T, sparse_mat_init) (window1, r, c1, ctx); + TEMPLATE(T, sparse_mat_init) (window2, r, c2, ctx); + TEMPLATE(T, sparse_mat_split_horizontal) (window1, window2, C, c1, ctx); + + if (!(TEMPLATE(T, sparse_mat_equal) (window1, A, ctx) && TEMPLATE(T, sparse_mat_equal) (window2, B, ctx))) + { + flint_printf("A = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (B, ctx); + flint_printf("A | B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (C, ctx); + flint_printf("window1 = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (window1, ctx); + flint_printf("window2 = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (window2, ctx); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_window_clear) (window1, ctx); + TEMPLATE(T, sparse_mat_window_clear) (window2, ctx); + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-concat_vertical.c b/fq_sparse_mat_templates/test/t-concat_vertical.c new file mode 100644 index 0000000000..c01461c30d --- /dev/null +++ b/fq_sparse_mat_templates/test/t-concat_vertical.c @@ -0,0 +1,98 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int main(void) +{ + slong rep, r1, r2, c, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C; + TEMPLATE(T, sparse_mat_t) window1, window2; + FLINT_TEST_INIT(state); + + + flint_printf("concat_vertical...."); + fflush(stdout); + + for (i = 0; i < 100; i++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r1 = n_randint(state, 100); + r2 = n_randint(state, 100); + c = n_randint(state, 100); + TEMPLATE(T, sparse_mat_init) (A, r1, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r2, c, ctx); + TEMPLATE(T, sparse_mat_init) (C, r1+r2, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (C, state, 0, c, ctx); + + TEMPLATE(T, sparse_mat_concat_vertical) (C, A, B, ctx); + + TEMPLATE(T, sparse_mat_window_init) (window1, C, 0, 0, r1, c, ctx); + TEMPLATE(T, sparse_mat_window_init) (window2, C, r1, 0, r1+r2, c, ctx); + + if (!(TEMPLATE(T, sparse_mat_equal) (window1, A, ctx) && TEMPLATE(T, sparse_mat_equal) (window2, B, ctx))) + { + flint_printf("A = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (B, ctx); + flint_printf("A concat_vertical B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (C, ctx); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_window_clear) (window1, ctx); + TEMPLATE(T, sparse_mat_window_clear) (window2, ctx); + + TEMPLATE(T, sparse_mat_init) (window1, r1, c, ctx); + TEMPLATE(T, sparse_mat_init) (window2, r2, c, ctx); + TEMPLATE(T, sparse_mat_split_vertical) (window1, window2, C, r1, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (window1, A, ctx) || !TEMPLATE(T, sparse_mat_equal) (window2, B, ctx)) + { + flint_printf("A = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (B, ctx); + flint_printf("A concat_vertical B = \n"); + TEMPLATE(T, sparse_mat_print_pretty) (C, ctx); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_window_clear) (window1, ctx); + TEMPLATE(T, sparse_mat_window_clear) (window2, ctx); + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-construct.c b/fq_sparse_mat_templates/test/t-construct.c new file mode 100644 index 0000000000..df38083a77 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-construct.c @@ -0,0 +1,98 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i, j, k, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C; + slong *rows; + slong *cols; + TEMPLATE(T, struct) *vals; + FLINT_TEST_INIT(state); + + flint_printf("construction from entries...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 10); + c = n_randint(state, 10); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (C, 0, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 2, 2, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 2, 2, ctx); + nnz = 0; + for (i = 0; i < r; ++i) nnz += A->rows[i].nnz; + + /* Construct B from entries of A */ + rows = flint_malloc(nnz * sizeof(*rows)); + cols = flint_malloc(nnz * sizeof(*cols)); + vals = _TEMPLATE(T, vec_init) (nnz, ctx); + for (i = k = 0; i < r; ++i) + { + for (j = 0; j < A->rows[i].nnz; ++j, ++k) + { + rows[k] = i; + cols[k] = A->rows[i].entries[j].ind; + TEMPLATE(T, set) (&vals[k], A->rows[i].entries[j].val, ctx); + } + } + TEMPLATE(T, sparse_mat_from_entries) (B, rows, cols, vals, nnz, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) + { + flint_printf("FAIL: A != B\n"); + flint_printf("A = "); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("B = "); + TEMPLATE(T, sparse_mat_print_pretty) (B, ctx); + abort(); + } + + for (i = 0; i < r; ++i) TEMPLATE(T, sparse_mat_append_row) (C, &A->rows[i], ctx); + if (!TEMPLATE(T, sparse_mat_equal) (A, C, ctx)) + { + flint_printf("FAIL: A != C\n"); + flint_printf("A = "); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("C = "); + TEMPLATE(T, sparse_mat_print_pretty) (C, ctx); + abort(); + } + flint_free(rows); + flint_free(cols); + _TEMPLATE(T, vec_clear) (vals, nnz, ctx); + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-dense.c b/fq_sparse_mat_templates/test/t-dense.c new file mode 100644 index 0000000000..a7c8b2bac0 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-dense.c @@ -0,0 +1,75 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i, j, k, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B; + TEMPLATE(T, mat_t) C, D; + FLINT_TEST_INIT(state); + + + flint_printf("conversion to/from dense matrix...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 10); + c = n_randint(state, 10); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, mat_init) (C, r, c, ctx); + TEMPLATE(T, mat_init) (D, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_to_dense) (C, A, ctx); + TEMPLATE(T, sparse_mat_from_dense) (B, C, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) + { + flint_printf("FAIL: A != B\n"); + abort(); + } + + TEMPLATE(T, mat_randtest) (C, state, ctx); + TEMPLATE(T, sparse_mat_from_dense) (A, C, ctx); + TEMPLATE(T, sparse_mat_to_dense) (D, A, ctx); + + if (!TEMPLATE(T, mat_equal) (C, D, ctx)) + { + flint_printf("FAIL: C != D\n"); + abort(); + } + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, mat_clear) (C, ctx); + TEMPLATE(T, mat_clear) (D, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-init_clear.c b/fq_sparse_mat_templates/test/t-init_clear.c new file mode 100644 index 0000000000..0890402a06 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-init_clear.c @@ -0,0 +1,63 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A; + FLINT_TEST_INIT(state); + + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 200); + c = n_randint(state, 200); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + + if (!TEMPLATE(T, sparse_mat_is_zero) (A, ctx)) + { + flint_printf("FAIL: A not zero!\n"); + abort(); + } + for (i = 0; i < r; i++) + { + if (!TEMPLATE(T, sparse_vec_is_zero) (&A->rows[i], ctx)) + { + flint_printf("FAIL: row %wd not zero!\n", i); + abort(); + } + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-inv.c b/fq_sparse_mat_templates/test/t-inv.c new file mode 100644 index 0000000000..f1c7906f3b --- /dev/null +++ b/fq_sparse_mat_templates/test/t-inv.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" +#include + +int +main(void) +{ + int ret; + slong rep, r, c, i, rk; + TEMPLATE(T, t) a; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, Ai; + TEMPLATE(T, mat_t) dA, dAiA; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("inverting A...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + TEMPLATE(T, ctx_randtest) (ctx, state); + do r = n_randint(state, 200), c = n_randint(state, 200); + while (r==UWORD(0) || c==UWORD(0)); + + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (Ai, r, r, ctx); + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, mat_init) (dA, r, c, ctx); + TEMPLATE(T, mat_init) (dAiA, r, c, ctx); + TEMPLATE(T, sparse_mat_to_dense) (dA, A, ctx); + + rk = TEMPLATE(T, sparse_mat_inv) (Ai, A, ctx); + TEMPLATE(T, sparse_mat_mul_mat) (dAiA, Ai, dA, ctx); + TEMPLATE(T, mat_rref) (dA, ctx); + if(!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) { + flint_printf("FAIL!\n"); + flint_printf("A^-1 x A = "); + TEMPLATE(T, mat_print_pretty) (dAiA, ctx); + flint_printf("rref(A) = "); + TEMPLATE(T, mat_print_pretty) (dA, ctx); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (Ai, ctx); + TEMPLATE(T, mat_clear) (dA, ctx); + TEMPLATE(T, mat_clear) (dAiA, ctx); + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-lu.c b/fq_sparse_mat_templates/test/t-lu.c new file mode 100644 index 0000000000..1672298d31 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-lu.c @@ -0,0 +1,126 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i, j, m, rk, *P, *Q; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, t) *val; + TEMPLATE(T, sparse_mat_t) A, LU, L, U; + TEMPLATE(T, mat_t) dL, dU, dLU; + FLINT_TEST_INIT(state); + + flint_printf("decomposing PAQ=LU...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + if (rep % 50 == 0) {flint_printf("."); fflush(stdout);} + r = n_randint(state, 200); + c = n_randint(state, 200); + + P = flint_malloc(r*sizeof(*P)); + Q = flint_malloc(c*sizeof(*P)); + m = FLINT_MIN(r, c); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (LU, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (L, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (U, r, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (A, state, 1, c, ctx); + rk = TEMPLATE(T, sparse_mat_lu) (P, Q, L, U, A, ctx); + TEMPLATE(T, mat_init) (dL, r, rk, ctx); + TEMPLATE(T, mat_init) (dU, rk, c, ctx); + TEMPLATE(T, mat_init) (dLU, r, c, ctx); + + /* Check that L is lower triangular (with ones on diagonal up to rank) */ + for(i=0; irows[i], i, ctx); + if(i < rk && (val == NULL || !TEMPLATE(T, is_one) (*val, ctx))) + { + flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); + } + for(j=0; jrows[i].nnz; ++j) { + TEMPLATE(T, sparse_entry_struct) *e = &L->rows[i].entries[j]; + if(e->ind > i) { + flint_printf("FAIL: L not lower triangular\n"); + abort(); + } + if(e->ind >= rk) { + flint_printf("FAIL: L not trivial past the rank\n"); + /*TEMPLATE(T, sparse_mat_print_pretty) (L, ctx);*/ + abort(); + } + } + } + /* Check that U is upper triangular (with nonzero diagonal up to rank) */ + for(i=0; irows[i], i, ctx); + if(i < rk && (val == NULL || TEMPLATE(T, is_zero) (*val, ctx))) + { + flint_printf("FAIL: U does not have nonzero diagonal\n"); + abort(); + } + if(i >= rk && U->rows[i].nnz != UWORD(0)) + { + flint_printf("FAIL: U not trivial past the rank\n"); + abort(); + } + for(j=0; jrows[i].nnz; ++j) { + TEMPLATE(T, sparse_entry_struct) *e = &U->rows[i].entries[j]; + if(e->ind < i) { + flint_printf("FAIL: U not upper triangular\n"); + abort(); + } + } + } + TEMPLATE(T, sparse_mat_to_dense) (dL, L, ctx); + TEMPLATE(T, sparse_mat_to_dense) (dU, U, ctx); + TEMPLATE(T, mat_mul) (dLU, dL, dU, ctx); + TEMPLATE(T, sparse_mat_from_dense) (LU, dLU, ctx); + TEMPLATE(T, sparse_mat_permute_rows) (A, P, ctx); + TEMPLATE(T, sparse_mat_permute_cols) (A, Q, ctx); + if(!TEMPLATE(T, sparse_mat_equal) (A, LU, ctx)) { + flint_printf("FAIL: PAQ != LU\n"); + flint_printf("PAQ="); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + flint_printf("LU="); + TEMPLATE(T, sparse_mat_print_pretty) (LU, ctx); + abort(); + } + + flint_free(P); + flint_free(Q); + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (U, ctx); + TEMPLATE(T, sparse_mat_clear) (L, ctx); + TEMPLATE(T, sparse_mat_clear) (LU, ctx); + TEMPLATE(T, mat_clear) (dL, ctx); + TEMPLATE(T, mat_clear) (dU, ctx); + TEMPLATE(T, mat_clear) (dLU, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-mul.c b/fq_sparse_mat_templates/test/t-mul.c new file mode 100644 index 0000000000..e8623df88f --- /dev/null +++ b/fq_sparse_mat_templates/test/t-mul.c @@ -0,0 +1,89 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i, k; + TEMPLATE(T, t) a; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A; + TEMPLATE(T, struct) *x, *y, *y2; + TEMPLATE(T, mat_t) B, X, Y, Y2; + FLINT_TEST_INIT(state); + + + flint_printf("multiplication by vec/mat...."); + fflush(stdout); + + for (rep = 0; rep < 10; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 200); + c = n_randint(state, 200); + k = n_randint(state, 200); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, mat_init) (B, r, c, ctx); + TEMPLATE(T, mat_init) (X, c, k, ctx); + TEMPLATE(T, mat_init) (Y, r, k, ctx); + TEMPLATE(T, mat_init) (Y2, r, k, ctx); + x = _TEMPLATE(T, vec_init) (c, ctx); + y = _TEMPLATE(T, vec_init) (r, ctx); + y2 = _TEMPLATE(T, vec_init) (r, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_to_dense) (B, A, ctx); + _TEMPLATE(T, vec_randtest) (x, state, c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (y, A, x, ctx); + TEMPLATE(T, mat_mul_vec) (y2, B, x, ctx); + + if (!_TEMPLATE(T, vec_equal) (y, y2, A->r, ctx)) + { + flint_printf("FAIL: y != y2\n"); + abort(); + } + + TEMPLATE(T, mat_randtest) (X, state, ctx); + TEMPLATE(T, sparse_mat_mul_mat) (Y, A, X, ctx); + TEMPLATE(T, mat_mul) (Y2, B, X, ctx); + + if (!TEMPLATE(T, mat_equal) (Y, Y2, ctx)) + { + flint_printf("Fail: Y != Y2\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, mat_clear) (B, ctx); + _TEMPLATE(T, vec_clear) (x, c, ctx); + _TEMPLATE(T, vec_clear) (y, r, ctx); + _TEMPLATE(T, vec_clear) (y2, r, ctx); + TEMPLATE(T, mat_clear) (X, ctx); + TEMPLATE(T, mat_clear) (Y, ctx); + TEMPLATE(T, mat_clear) (Y2, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-neg.c b/fq_sparse_mat_templates/test/t-neg.c new file mode 100644 index 0000000000..3026272623 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-neg.c @@ -0,0 +1,77 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 200); + c = n_randint(state, 200); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (C, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (D, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (C, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (D, state, 0, c, ctx); + + TEMPLATE(T, sparse_mat_sub) (C, A, B, ctx); + TEMPLATE(T, sparse_mat_neg) (B, B, ctx); + TEMPLATE(T, sparse_mat_add) (D, A, B, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (C, D, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_neg) (C, B, ctx); + TEMPLATE(T, sparse_mat_neg) (B, B, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (C, B, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, sparse_mat_clear) (D, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c new file mode 100644 index 0000000000..cbfa3f7ff8 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -0,0 +1,97 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + int iter, ret; + slong rep, nreps = 100, r, c, i; + TEMPLATE(T, t) a; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A; + TEMPLATE(T, mat_t) X, AX; + slong rk[4]; + slong discrep[4] = {0, 0, 0, 0}; + double elapsed[4] = {0, 0, 0, 0}; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("finding nullspace of A...."); + fflush(stdout); + + for (rep = 0; rep < nreps; ) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + TEMPLATE(T, ctx_randtest) (ctx, state); + r = c = n_randint(state, 200); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (A, state, c/5, c/2, ctx); + for (i = 0; i < 4; ++i) + { + gettimeofday(&start, NULL); + switch (i) + { + case 0: rk[0] = TEMPLATE(T, sparse_mat_nullspace_rref) (X, A, ctx); break; + case 1: rk[1] = TEMPLATE(T, sparse_mat_nullspace_lu) (X, A, ctx); break; + case 2: rk[2] = TEMPLATE(T, sparse_mat_nullspace_lanczos) (X, A, state, 5, ctx); break; + case 3: rk[3] = TEMPLATE(T, sparse_mat_nullspace_wiedemann) (X, A, state, 5, ctx); break; + } + if (i == 0 && rk[0] == UWORD(0) ) { TEMPLATE(T, mat_clear) (X, ctx); break;} + else ++rep; + gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if(rk[i]!=0) + { + TEMPLATE(T, mat_init) (AX, A->r, X->c, ctx); + TEMPLATE(T, sparse_mat_mul_mat) (AX, A, X, ctx); + if (!TEMPLATE(T, mat_is_zero) (AX, ctx)) + { + flint_printf("FAIL: %d!\n", i); + if (i != 0) + flint_printf("Nullity should be %wd\n", rk[0]); + TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); + TEMPLATE(T, mat_print_pretty) (X, ctx); + abort(); + } + TEMPLATE(T, mat_clear) (AX, ctx); + } + if (rk[i] != rk[0]) + { + discrep[i] += 1; + } + TEMPLATE(T, mat_clear) (X, ctx); + } + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + flint_printf("Average time for rref: %lf\n", elapsed[0]/nreps); + flint_printf("Average time for LU: %lf\n", elapsed[1]/nreps); + flint_printf("Average time for Lanzcos: %lf\n", elapsed[2]/nreps); + flint_printf("Average time for Wiedemann: %lf\n", elapsed[3]/nreps); + flint_printf("LU did not find full nullspace for %wd/%wd examples\n", discrep[1], nreps); + flint_printf("Lanczos did not find full nullspace for %wd/%wd examples\n", discrep[2], nreps); + flint_printf("Wiedemann did not find full nullspace for %wd/%wd examples\n", discrep[3], nreps); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-rref.c b/fq_sparse_mat_templates/test/t-rref.c new file mode 100644 index 0000000000..2aad0b8067 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-rref.c @@ -0,0 +1,64 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + TEMPLATE(T, t) n; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B; + TEMPLATE(T, mat_t) dA; + FLINT_TEST_INIT(state); + + flint_printf("converting A to reduced row echelon form...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + if (rep % 20 == 0) {flint_printf("."); fflush(stdout);} + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 100); + c = n_randint(state, 100); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, mat_init) (dA, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_to_dense) (dA, A, ctx); + TEMPLATE(T, sparse_mat_rref) (A, ctx); + TEMPLATE(T, mat_rref) (dA, ctx); + TEMPLATE(T, sparse_mat_from_dense) (B, dA, ctx); + if(!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) { + flint_printf("FAIL!\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, mat_clear) (dA, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c new file mode 100644 index 0000000000..6fc6de3f6e --- /dev/null +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + TEMPLATE(T, t) a, cc; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("scalar_mul...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + TEMPLATE(T, init) (a, ctx); + TEMPLATE(T, init) (cc, ctx); + r = n_randint(state, 200); + c = n_randint(state, 200); + TEMPLATE(T, randtest) (cc, state, ctx); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (C, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (D, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + + TEMPLATE(T, sparse_mat_scalar_mul) (B, A, a, ctx); + TEMPLATE(T, one) (cc, ctx); + TEMPLATE(T, sub) (cc, a, cc, ctx); + TEMPLATE(T, sparse_mat_scalar_mul) (C, A, cc, ctx); + + /* c*A - (c-1)*A == A */ + TEMPLATE(T, sparse_mat_sub) (D, B, C, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (A, D, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + + /* Aliasing */ + TEMPLATE(T, sparse_mat_scalar_mul) (C, A, a, ctx); + TEMPLATE(T, sparse_mat_scalar_mul) (A, A, a, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (A, C, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, sparse_mat_clear) (D, ctx); + TEMPLATE(T, clear) (a, ctx); + TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c new file mode 100644 index 0000000000..9fd64c2a8d --- /dev/null +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -0,0 +1,153 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" +#include + +int +main(void) +{ + int iter, ret; + int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + slong rep, r, c, i, nrep = 100; + TEMPLATE(T, t) a; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, At; + TEMPLATE(T, struct) *x, *x2, *b, *Atb, *Ax, *AtAx; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("solving Ax=b...."); + fflush(stdout); + + for (rep = 0; rep < nrep; rep++) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + TEMPLATE(T, ctx_randtest) (ctx, state); + + do c = r = n_randint(state, 200); + while(c == 0 || r == 0); + + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (At, c, r, ctx); + x = _TEMPLATE(T, vec_init) (c, ctx); + x2 = _TEMPLATE(T, vec_init) (c, ctx); + b = _TEMPLATE(T, vec_init) (r, ctx); + Ax = _TEMPLATE(T, vec_init) (r, ctx); + AtAx = _TEMPLATE(T, vec_init) (c, ctx); + Atb = _TEMPLATE(T, vec_init) (c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, c/20, c/10, ctx); + TEMPLATE(T, sparse_mat_transpose) (At, A, ctx); + + _TEMPLATE(T, vec_randtest) (x, state, c, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (b, A, x, ctx); + /* Solve via reduced row echelon form */ + gettimeofday(&start, NULL); + ret = TEMPLATE(T, sparse_mat_solve_rref) (x2, A, b, ctx); + gettimeofday(&end, NULL); + rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + if(!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve via lu decomposition */ + gettimeofday(&start, NULL); + ret = TEMPLATE(T, sparse_mat_solve_lu) (x2, A, b, ctx); + gettimeofday(&end, NULL); + lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + if(!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve iteratively */ +/**/ gettimeofday(&start, NULL); + ret=TEMPLATE(T, sparse_mat_solve_wiedemann) (x2, A, b, ctx); + gettimeofday(&end, NULL); + wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) + { + wied_nosol += 1; + } + else + { + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + flint_printf("FAIL: Ax != b\n"); + abort(); + } + } + + gettimeofday(&start, NULL); + iter = 0; + do ret=TEMPLATE(T, sparse_mat_solve_lanczos) (x2, A, b, state, ctx); + while(ret==0 && ++iter < 30); + gettimeofday(&end, NULL); + lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) + { + nosol += 1; + continue; + } + else + { + niters += iter; + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (AtAx, At, Ax, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Atb, At, b, ctx); + if (!_TEMPLATE(T, vec_equal) (AtAx, Atb, A->c, ctx)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + psolved += 1; + } + } + + _TEMPLATE(T, vec_clear) (x, c, ctx); + _TEMPLATE(T, vec_clear) (x2, c, ctx); + _TEMPLATE(T, vec_clear) (b, r, ctx); + _TEMPLATE(T, vec_clear) (Ax, r, ctx); + _TEMPLATE(T, vec_clear) (AtAx, c, ctx); + _TEMPLATE(T, vec_clear) (Atb, c, ctx); + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (At, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); + flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); + flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); + flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); + flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/test/t-transpose.c b/fq_sparse_mat_templates/test/t-transpose.c new file mode 100644 index 0000000000..4c3e49ec63 --- /dev/null +++ b/fq_sparse_mat_templates/test/t-transpose.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, r, c, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_mat_t) A, B, C; + FLINT_TEST_INIT(state); + + + flint_printf("transpose...."); + fflush(stdout); + + /* Rectangular transpose, same modulus */ + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + r = n_randint(state, 20); + c = n_randint(state, 20); + TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); + TEMPLATE(T, sparse_mat_init) (B, c, r, ctx); + TEMPLATE(T, sparse_mat_init) (C, r, c, ctx); + + TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); + TEMPLATE(T, sparse_mat_randtest) (B, state, 0, r, ctx); + TEMPLATE(T, sparse_mat_randtest) (C, state, 0, c, ctx); + + TEMPLATE(T, sparse_mat_transpose) (B, A, ctx); + TEMPLATE(T, sparse_mat_transpose) (C, B, ctx); + + if (!TEMPLATE(T, sparse_mat_equal) (C, A, ctx)) + { + flint_printf("FAIL: C != A\n"); + abort(); + } + + TEMPLATE(T, sparse_mat_clear) (A, ctx); + TEMPLATE(T, sparse_mat_clear) (B, ctx); + TEMPLATE(T, sparse_mat_clear) (C, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif diff --git a/fq_sparse_mat_templates/tmp b/fq_sparse_mat_templates/tmp new file mode 100644 index 0000000000..f16d89d6ca --- /dev/null +++ b/fq_sparse_mat_templates/tmp @@ -0,0 +1,31 @@ + int ret = 0; + slong l; + + std::vector combi(block_size,Vector(F,d[l]+1)); + for (size_t i=0;i 0;--i) { + lhs = lhs2 + combi[0][i]*y; + lhs2 = A^t*lhs; + } + Vector accu (lhs); + _TEMPLATE(T, vec_zero) (x, A->r, ctx); + for (size_t k=1;k= 0;--i) { + lhs = lhs2 + combi[k][i]*row; + lhs2 = A^t * lhs + } + _TEMPLATE(T, vec_add) (x, x, lhs, A->r, ctx); + } + TEMPLATE(T, neg) (cc, nmod_inv(S[0].rows[l][0], ctx), ctx); + _TEMPLATE(T, vec_scalar_mul) (x, x, A->r, cc, ctx); + return ret; diff --git a/fq_sparse_mat_templates/transpose.c b/fq_sparse_mat_templates/transpose.c new file mode 100644 index 0000000000..8cfff56f36 --- /dev/null +++ b/fq_sparse_mat_templates/transpose.c @@ -0,0 +1,61 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +void +TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) B, const TEMPLATE(T, sparse_mat_t) A, const TEMPLATE(T, ctx_t) ctx) +{ + slong r, c, i, j, *nnz; + TEMPLATE(T, sparse_entry_struct) *Ae, *Be; + nnz = flint_calloc(A->c, sizeof(*nnz)); + /* Get number of nnzs in each column of A (thus each row of B) */ + for (c = 0; c < A->c; ++c) + { + B->rows[c].nnz = 0; + } + for (r = 0; r < A->r; ++r) + { + for (i = 0; i < A->rows[r].nnz; ++i) + { + c = A->rows[r].entries[i].ind - A->c_off; + if(c >= A->c) break; + nnz[c]++; + } + } + /* Allocate space for nnz and reset counters */ + for (c = 0; c < A->c; ++c) + { + _TEMPLATE(T, sparse_vec_resize) (&B->rows[c], nnz[c], ctx); + nnz[c] = 0; + } + /* Put entries into transposed matrix */ + for (r = 0; r < A->r; ++r) + { + for (i = 0; i < A->rows[r].nnz; ++i) + { + Ae = &A->rows[r].entries[i]; + c = Ae->ind - A->c_off; + if(c >= A->c) break; + j = nnz[c]++; + Be = &B->rows[c].entries[j]; + Be->ind = r; + TEMPLATE(T, set) (Be->val, Ae->val, ctx); + } + } + flint_free(nnz); + B->c_off = 0; +} + +#endif diff --git a/fq_sparse_mat_templates/window_init.c b/fq_sparse_mat_templates/window_init.c new file mode 100644 index 0000000000..38df9f863c --- /dev/null +++ b/fq_sparse_mat_templates/window_init.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, sparse_mat_window_init)(TEMPLATE(T, sparse_mat_t) window, const TEMPLATE(T, sparse_mat_t) mat, slong r1, slong c1, slong r2, slong c2, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + r2 = FLINT_MIN(r2, mat->r), r1 = FLINT_MIN(r1, r2); + c2 = FLINT_MIN(c2, mat->c), c1 = FLINT_MIN(c1, c2); + window->r = r2-r1; + window->c = c2-c1; + window->c_off = c1; + window->rows = flint_malloc(window->r*sizeof(*window->rows)); + for (i = 0; i < window->r; ++i) + TEMPLATE(T, sparse_vec_window_init) (&window->rows[i], &mat->rows[i+r1], c1, c2, ctx); +} + +#endif diff --git a/fq_sparse_vec.h b/fq_sparse_vec.h new file mode 100644 index 0000000000..a1bad275b3 --- /dev/null +++ b/fq_sparse_vec.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_SPARSE_VEC_H +#define FQ_SPARSE_VEC_H + +#ifdef FQ_SPARSE_VEC_INLINES_C +#define FQ_SPARSE_VEC_TEMPLATES_INLINE FLINT_DLL +#define FQ_SPARSE_VEC_INLINE FLINT_DLL +#else +#define FQ_SPARSE_VEC_TEMPLATES_INLINE static __inline__ +#define FQ_SPARSE_VEC_INLINE static __inline__ +#endif + + +#include "fq.h" +#include "fq_vec.h" + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_sparse_vec/add.c b/fq_sparse_vec/add.c new file mode 100644 index 0000000000..7987451e2c --- /dev/null +++ b/fq_sparse_vec/add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/add.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/print_pretty.c b/fq_sparse_vec/print_pretty.c new file mode 100644 index 0000000000..97eb13f973 --- /dev/null +++ b/fq_sparse_vec/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/randtest.c b/fq_sparse_vec/randtest.c new file mode 100644 index 0000000000..6c07d2930d --- /dev/null +++ b/fq_sparse_vec/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/scalar_addmul.c b/fq_sparse_vec/scalar_addmul.c new file mode 100644 index 0000000000..56bdb15ba6 --- /dev/null +++ b/fq_sparse_vec/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/sub.c b/fq_sparse_vec/sub.c new file mode 100644 index 0000000000..2658de6cd3 --- /dev/null +++ b/fq_sparse_vec/sub.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/sub.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-add.c b/fq_sparse_vec/test/t-add.c new file mode 100644 index 0000000000..00dfacf628 --- /dev/null +++ b/fq_sparse_vec/test/t-add.c @@ -0,0 +1,21 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-concat.c b/fq_sparse_vec/test/t-concat.c new file mode 100644 index 0000000000..08fae5b5a4 --- /dev/null +++ b/fq_sparse_vec/test/t-concat.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-concat.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-construct.c b/fq_sparse_vec/test/t-construct.c new file mode 100644 index 0000000000..95c23a936e --- /dev/null +++ b/fq_sparse_vec/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-dense.c b/fq_sparse_vec/test/t-dense.c new file mode 100644 index 0000000000..a00caa371e --- /dev/null +++ b/fq_sparse_vec/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-dot.c b/fq_sparse_vec/test/t-dot.c new file mode 100644 index 0000000000..4af6321c57 --- /dev/null +++ b/fq_sparse_vec/test/t-dot.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-dot.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-init_clear.c b/fq_sparse_vec/test/t-init_clear.c new file mode 100644 index 0000000000..b2e4095cb7 --- /dev/null +++ b/fq_sparse_vec/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-neg.c b/fq_sparse_vec/test/t-neg.c new file mode 100644 index 0000000000..1fed5ea23a --- /dev/null +++ b/fq_sparse_vec/test/t-neg.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec/test/t-scalar_mul.c b/fq_sparse_vec/test/t-scalar_mul.c new file mode 100644 index 0000000000..1bda15e955 --- /dev/null +++ b/fq_sparse_vec/test/t-scalar_mul.c @@ -0,0 +1,23 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec_templates.h b/fq_sparse_vec_templates.h new file mode 100644 index 0000000000..77e61ccbd9 --- /dev/null +++ b/fq_sparse_vec_templates.h @@ -0,0 +1,371 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "flint.h" +#include "longlong.h" +#include "templates.h" +#include "ulong_extras.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + slong ind; + TEMPLATE(T, t) val; +} TEMPLATE(T, sparse_entry_struct); + +typedef TEMPLATE(T, sparse_entry_struct) TEMPLATE(T, sparse_entry_t)[1]; + +typedef struct { + TEMPLATE(T, sparse_entry_struct) *entries; + slong nnz; +} TEMPLATE(T, sparse_vec_struct); + +typedef TEMPLATE(T, sparse_vec_struct) TEMPLATE(T, sparse_vec_t)[1]; + +FQ_SPARSE_VEC_TEMPLATES_INLINE +int TEMPLATE(T, sparse_entry_cmp)(const void *va, const void *vb) +{ + const TEMPLATE(T, sparse_entry_struct) *a = va; + const TEMPLATE(T, sparse_entry_struct) *b = vb; + if (a->ind < b->ind) return -1; + if (b->ind < a->ind) return 1; + return 0; +} + +/* Memory management */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_init)(TEMPLATE(T, sparse_vec_t) vec, + const TEMPLATE(T, ctx_t) ctx) +{ + memset(vec, 0, sizeof(*vec)); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_clear)(TEMPLATE(T, sparse_vec_t) vec, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for(i = 0; i < vec->nnz; ++i) + TEMPLATE(T, clear) (vec->entries[i].val, ctx); + flint_free(vec->entries); + memset(vec, 0, sizeof(*vec)); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void _TEMPLATE(T, sparse_vec_resize)(TEMPLATE(T, sparse_vec_t) vec, slong nnz, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if(nnz == 0) TEMPLATE(T, sparse_vec_clear) (vec, ctx); + else if (nnz != vec->nnz) + { + for(i = nnz; i < vec->nnz; ++i) + TEMPLATE(T, clear) (vec->entries[i].val, ctx); + vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); + for(i = vec->nnz; i < nnz; ++i) + TEMPLATE(T, init) (vec->entries[i].val, ctx); + } + vec->nnz = nnz; +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_swap)(TEMPLATE(T, sparse_vec_t) vec1, TEMPLATE(T, sparse_vec_t) vec2, + const TEMPLATE(T, ctx_t) ctx) +{ + TEMPLATE(T, sparse_vec_t) tmp; + *tmp = *vec1, *vec1 = *vec2, *vec2 = *tmp; +} + +/* One-time instantiation */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_zero)(TEMPLATE(T, sparse_vec_t) vec, + const TEMPLATE(T, ctx_t) ctx) +{ + TEMPLATE(T, sparse_vec_clear)(vec, ctx); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_one)(TEMPLATE(T, sparse_vec_t) vec, slong ind, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + _TEMPLATE(T, sparse_vec_resize) (vec, 1, ctx); + vec->entries[0].ind = ind; + TEMPLATE(T, one) (vec->entries[0].val, ctx); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_set)(TEMPLATE(T, sparse_vec_t) dst, const TEMPLATE(T, sparse_vec_t) src, slong ioff, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if (dst == src) return; + _TEMPLATE(T, sparse_vec_resize) (dst, src->nnz, ctx); + for(i=0; innz; ++i) + { + dst->entries[i].ind = src->entries[i].ind - ioff; + TEMPLATE(T, set) (dst->entries[i].val, src->entries[i].val, ctx); + } +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_append_entry)(TEMPLATE(T, sparse_vec_t) v, slong ind, const TEMPLATE(T, t) val, + const TEMPLATE(T, ctx_t) ctx) +{ + if (TEMPLATE(T, is_zero) (val, ctx)) return; + _TEMPLATE(T, sparse_vec_resize) (v, v->nnz + 1, ctx); + TEMPLATE(T, set) (v->entries[v->nnz-1].val, val, ctx); + v->entries[v->nnz-1].ind = ind; + if(v->nnz >= 2 && ind < v->entries[v->nnz-2].ind) + qsort(v->entries, v->nnz, sizeof(*v->entries), TEMPLATE(T, sparse_entry_cmp)); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_from_entries)(TEMPLATE(T, sparse_vec_t) vec, slong * inds, TEMPLATE(T, struct) * vals, slong nnz, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + _TEMPLATE(T, sparse_vec_resize) (vec, nnz, ctx); + for (i = 0; i < nnz; ++i) + { + vec->entries[i].ind = inds[i]; + TEMPLATE(T, set) (vec->entries[i].val, &vals[i], ctx); + } +} + +/* Vector comparison */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +int TEMPLATE(T, sparse_vec_is_zero)(const TEMPLATE(T, sparse_vec_t) vec, + const TEMPLATE(T, ctx_t) ctx) +{ + return vec->nnz == 0; +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +int TEMPLATE(T, sparse_vec_equal)(const TEMPLATE(T, sparse_vec_t) vec1, const TEMPLATE(T, sparse_vec_t) vec2, slong ioff, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if (vec1->nnz != vec2->nnz) return 0; + for (i = 0; i < vec1->nnz; ++i) + { + if ((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || + !TEMPLATE(T, equal)(vec1->entries[i].val, vec2->entries[i].val, ctx)) return 0; + } + return 1; +} + +/* Vector indexing */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +TEMPLATE(T, t) *TEMPLATE(T, sparse_vec_at)(TEMPLATE(T, sparse_vec_t) vec, slong i, + const TEMPLATE(T, ctx_t) ctx) +{ + slong j; + for (j = 0; j < vec->nnz; ++j) + if (vec->entries[j].ind==i) + return &vec->entries[j].val; + return NULL; +} + +/* Convert from/to dense vector */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_from_dense)(TEMPLATE(T, sparse_vec_t) dst, TEMPLATE(T, struct) *src, slong len, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz = 0; + for (i = 0; i < len; ++i) + if (!TEMPLATE(T, is_zero) (&src[i], ctx)) ++nnz; + _TEMPLATE(T, sparse_vec_resize) (dst, nnz, ctx); + TEMPLATE(T, sparse_entry_struct) *e = dst->entries; + for (i = 0; i < len; ++i) + if (!TEMPLATE(T, is_zero) (&src[i], ctx)) + e->ind = i, TEMPLATE(T, set) (e->val, &src[i], ctx), ++e; +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_to_dense)(TEMPLATE(T, struct) *dst, const TEMPLATE(T, sparse_vec_t) src, slong len, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + _TEMPLATE(T, vec_zero)(dst, len, ctx); + for (i = 0; i < src->nnz; ++i) TEMPLATE(T, set)(&dst[src->entries[i].ind], src->entries[i].val, ctx); +} + +/* Windows and concatenation */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_window_init)(TEMPLATE(T, sparse_vec_t) window, const TEMPLATE(T, sparse_vec_t) vec, slong i1, slong i2, + const TEMPLATE(T, ctx_t) ctx) +{ + slong start, end; + for (start = 0; startnnz && vec->entries[start].ind < i1; ++start); + for (end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + window->entries = vec->entries + start; + window->nnz = end - start; +} + + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_window_clear)(TEMPLATE(T, sparse_vec_t) window, + const TEMPLATE(T, ctx_t) ctx) +{ + memset(window, 0, sizeof(*window)); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_concat)(TEMPLATE(T, sparse_vec_t) res, const TEMPLATE(T, sparse_vec_t) vec1, const TEMPLATE(T, sparse_vec_t) vec2, slong len1, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz = vec1->nnz+vec2->nnz; + _TEMPLATE(T, sparse_vec_resize) (res, nnz, ctx); + for (i = 0; i < nnz; ++i) + { + TEMPLATE(T, sparse_entry_struct) *e = (i < vec1->nnz) ? &vec1->entries[i] : &vec2->entries[i-vec1->nnz]; + res->entries[i].ind = e->ind + ((i < vec1->nnz) ? 0 : len1); + TEMPLATE(T, set) (res->entries[i].val, e->val, ctx); + } +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_split)(TEMPLATE(T, sparse_vec_t) res1, TEMPLATE(T, sparse_vec_t) res2, const TEMPLATE(T, sparse_vec_t) vec, slong ind, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz1; + TEMPLATE(T, sparse_entry_struct) *e1, *e2, *e; + for(nnz1=0; nnz1nnz; ++nnz1) if(vec->entries[nnz1].ind >= ind) break; + + _TEMPLATE(T, sparse_vec_resize) (res1, nnz1, ctx); + _TEMPLATE(T, sparse_vec_resize) (res2, vec->nnz - nnz1, ctx); + e1 = res1->entries, e2 = res2->entries; + for (i = 0; i < vec->nnz; ++i) + { + e = (i < nnz1) ? e1++ : e2++; + e->ind = vec->entries[i].ind - ((i < nnz1) ? 0 : ind); + TEMPLATE(T, set) (e->val, vec->entries[i].val, ctx); + } +} + +/* Vector permutation */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_permute_inds)(TEMPLATE(T, sparse_vec_t) vec, slong *P, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < vec->nnz; ++i) vec->entries[i].ind = P[vec->entries[i].ind]; + qsort(vec->entries, vec->nnz, sizeof(*vec->entries), TEMPLATE(T, sparse_entry_cmp)); +} + +/* Random vector generation */ +FLINT_DLL +void TEMPLATE(T, sparse_vec_randtest)(TEMPLATE(T, sparse_vec_t) vec, flint_rand_t state, slong nnz, slong len, + const TEMPLATE(T, ctx_t) ctx); + +/* Vector display */ +FLINT_DLL +void TEMPLATE(T, sparse_vec_print_pretty)(const TEMPLATE(T, sparse_vec_t) vec, slong ioff, slong maxi, + const TEMPLATE(T, ctx_t) ctx); + +/* Vector operations */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_neg)(TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, sparse_vec_t) u, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + TEMPLATE(T, sparse_vec_set)(v, u, 0, ctx); + for (i = 0; i < v->nnz; ++i) TEMPLATE(T, neg) (v->entries[i].val, v->entries[i].val, ctx); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_scalar_mul)(TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if (TEMPLATE(T, is_zero) (c, ctx)) {TEMPLATE(T, sparse_vec_zero)(v, ctx); return;} + TEMPLATE(T, sparse_vec_set)(v, u, 0, ctx); + if (!TEMPLATE(T, is_one)(c, ctx)) + for (i = 0; i < v->nnz; ++i) TEMPLATE(T, mul)(v->entries[i].val, v->entries[i].val, c, ctx); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +slong _TEMPLATE(T, sparse_vec_union_nnz)(const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j, nnz = 0; + for (i = j = 0; i < u->nnz && j < v->nnz; ++nnz) + { + if (u->entries[i].ind == v->entries[j].ind) ++i, ++j; + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } + nnz += u->nnz - i + v->nnz - j; + return nnz; +} +FLINT_DLL +void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx); + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_dot)(TEMPLATE(T, t) ret, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j; + TEMPLATE(T, t) tmp; + TEMPLATE(T, init) (tmp, ctx); + TEMPLATE(T, zero) (ret, ctx); + for (i = j = 0; i < u->nnz && j < v->nnz; ) + { + if (u->entries[i].ind == v->entries[j].ind) + { + TEMPLATE(T, mul) (tmp, u->entries[i].val, v->entries[j].val, ctx); + TEMPLATE(T, add) (ret, ret, tmp, ctx), ++i, ++j; + } + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } + TEMPLATE(T, clear) (tmp, ctx); +} + +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_dot_dense)(TEMPLATE(T, t) ret, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, struct) *v, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + TEMPLATE(T, t) tmp; + TEMPLATE(T, init) (tmp, ctx); + TEMPLATE(T, zero) (ret, ctx); + for(i=0; innz; ++i) + { + TEMPLATE(T, mul) (tmp, u->entries[i].val, &v[u->entries[i].ind], ctx); + TEMPLATE(T, add) (ret, ret, tmp, ctx); + } + TEMPLATE(T, clear) (tmp, ctx); +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/fq_sparse_vec_templates/add.c b/fq_sparse_vec_templates/add.c new file mode 100644 index 0000000000..407bd56abe --- /dev/null +++ b/fq_sparse_vec_templates/add.c @@ -0,0 +1,56 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz, unnz, vnnz; + TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; + if(u->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, v, 0, ctx); + else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); + else + { + nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ + _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); + ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; + while (ue >= u->entries && ve >= v->entries) + { + we->ind = FLINT_MAX(ue->ind, ve->ind); + if (ue->ind == ve->ind) + { + TEMPLATE(T, add) (we->val, (ue--)->val, (ve--)->val, ctx); + if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; + } + else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + else if (ve->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ve--)->val, ctx); + } + while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, set) ((we--)->val, (ve--)->val, ctx); + + nnz = w->nnz - (we + 1 - w->entries); + if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); + else if (nnz < w->nnz) + { + for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); + w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); + w->nnz = nnz; + } + } + +} +#endif + diff --git a/fq_sparse_vec_templates/print_pretty.c b/fq_sparse_vec_templates/print_pretty.c new file mode 100644 index 0000000000..453a5f0c14 --- /dev/null +++ b/fq_sparse_vec_templates/print_pretty.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#ifdef T + +#include "templates.h" + +void +TEMPLATE(T, sparse_vec_print_pretty)(const TEMPLATE(T, sparse_vec_t) vec, slong ioff, slong maxi, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + char ind_fmt[FLINT_BITS + 5]; + + flint_sprintf(ind_fmt, "%%%dwd:", n_sizeinbase(maxi, 10)); + + flint_printf("["); + for (i = 0; i < vec->nnz; i++) + { + flint_printf(ind_fmt, vec->entries[i].ind - ioff); + TEMPLATE(T, print_pretty) (vec->entries[i].val, ctx); + if (i + 1 < vec->nnz) flint_printf(" "); + } + flint_printf("]\n"); +} + + +#endif + diff --git a/fq_sparse_vec_templates/randtest.c b/fq_sparse_vec_templates/randtest.c new file mode 100644 index 0000000000..d4eaa37447 --- /dev/null +++ b/fq_sparse_vec_templates/randtest.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include "templates.h" + +void TEMPLATE(T, sparse_vec_randtest)(TEMPLATE(T, sparse_vec_t) vec, flint_rand_t state, slong nnz, slong len, const TEMPLATE(T, ctx_t) ctx) +{ + slong i, j; + nnz = FLINT_MIN(nnz, len); + _TEMPLATE(T, sparse_vec_resize) (vec, nnz, ctx); + for (i = 0; i < nnz; ++i) + { + vec->entries[i].ind = i; + do TEMPLATE(T, randtest) (vec->entries[i].val, state, ctx); + while (TEMPLATE(T, is_zero) (vec->entries[i].val, ctx)); + } + + /* Use resevoir sampling to randomize support */ + for (j = nnz; j < len; ++j) + if ((i = n_randint(state, j+1)) < nnz) vec->entries[i].ind = j; + qsort(vec->entries, nnz, sizeof(*vec->entries), TEMPLATE(T, sparse_entry_cmp)); +} + + +#endif + diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c new file mode 100644 index 0000000000..352c3bc722 --- /dev/null +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -0,0 +1,59 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz, unnz, vnnz; + TEMPLATE(T, t) tmp; + TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; + if(u->nnz == 0) TEMPLATE(T, sparse_vec_scalar_mul) (w, v, c, ctx); + else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); + else + { + TEMPLATE(T, init) (tmp, ctx); + unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ + nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); + ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; + while (ue >= u->entries && ve >= v->entries) + { + we->ind = FLINT_MAX(ue->ind, ve->ind); + if (ue->ind == ve->ind) + { + TEMPLATE(T, mul) (tmp, (ve--)->val, c, ctx); + TEMPLATE(T, add) (we->val, tmp, (ue--)->val, ctx); + if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; + } + else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + else if (ve->ind == we->ind) TEMPLATE(T, mul) ((we--)->val, (ve--)->val, c, ctx); + } + while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, mul) ((we--)->val, (ve--)->val, c, ctx); + + nnz = w->nnz - (we + 1 - w->entries); + if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); + else if (nnz < w->nnz) + { + for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); + w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); + w->nnz = nnz; + } + TEMPLATE(T, clear) (tmp, ctx); + } +} +#endif + diff --git a/fq_sparse_vec_templates/sub.c b/fq_sparse_vec_templates/sub.c new file mode 100644 index 0000000000..b85ce59d18 --- /dev/null +++ b/fq_sparse_vec_templates/sub.c @@ -0,0 +1,55 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz, unnz, vnnz; + TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; + if(u->nnz == 0) TEMPLATE(T, sparse_vec_neg) (w, v, ctx); + else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); + else + { + unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ + nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); + ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; + while (ue >= u->entries && ve >= v->entries) + { + we->ind = FLINT_MAX(ue->ind, ve->ind); + if (ue->ind == ve->ind) + { + TEMPLATE(T, sub) (we->val, (ue--)->val, (ve--)->val, ctx); + if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; + } + else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + else if (ve->ind == we->ind) TEMPLATE(T, neg) ((we--)->val, (ve--)->val, ctx); + } + while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, neg) ((we--)->val, (ve--)->val, ctx); + + nnz = w->nnz - (we + 1 - w->entries); + if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); + else if (nnz < w->nnz) + { + for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); + w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); + w->nnz = nnz; + } + } +} +#endif + diff --git a/fq_sparse_vec_templates/test/t-add.c b/fq_sparse_vec_templates/test/t-add.c new file mode 100644 index 0000000000..ecf9799ec7 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-add.c @@ -0,0 +1,81 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) u, v, w, x; + + FLINT_TEST_INIT(state); + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + len = n_randint(state, 40); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init)(u, ctx); + TEMPLATE(T, sparse_vec_init)(v, ctx); + TEMPLATE(T, sparse_vec_init)(w, ctx); + TEMPLATE(T, sparse_vec_init)(x, ctx); + + TEMPLATE(T, sparse_vec_randtest)(u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest)(v, state, nnz, len, ctx); + + TEMPLATE(T, sparse_vec_add)(w, u, v, ctx); + TEMPLATE(T, sparse_vec_sub)(x, w, v, ctx); + + if (!TEMPLATE(T, sparse_vec_equal)(u, x, 0, ctx)) + { + flint_printf("FAIL: u != u+v-v\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_add)(u, u, v, ctx); + if (!TEMPLATE(T, sparse_vec_equal)(u, w, 0, ctx)) + { + flint_printf("FAIL: (u += v) != u + v\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_sub)(u, u, v, ctx); + if (!TEMPLATE(T, sparse_vec_equal)(u, x, 0, ctx)) + { + flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); + abort(); + } + TEMPLATE(T, sparse_vec_clear)(u, ctx); + TEMPLATE(T, sparse_vec_clear)(v, ctx); + TEMPLATE(T, sparse_vec_clear)(w, ctx); + TEMPLATE(T, sparse_vec_clear)(x, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-concat.c b/fq_sparse_vec_templates/test/t-concat.c new file mode 100644 index 0000000000..fe29ba04cb --- /dev/null +++ b/fq_sparse_vec_templates/test/t-concat.c @@ -0,0 +1,102 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include "templates.h" + +#include +#include +#include +#include "ulong_extras.h" + +int main(void) +{ + slong rep, len, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) u, v, w; + TEMPLATE(T, sparse_vec_t) window1, window2; + FLINT_TEST_INIT(state); + + flint_printf("concat...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + TEMPLATE(T, sparse_vec_init) (w, ctx); + + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (w, state, nnz, len, ctx); + + TEMPLATE(T, sparse_vec_concat) (w, u, v, len, ctx); + + TEMPLATE(T, sparse_vec_window_init) (window1, w, 0, len, ctx); + TEMPLATE(T, sparse_vec_window_init)(window2, w, len, 2*len, ctx); + + if (!(TEMPLATE(T, sparse_vec_equal) (window1, u, 0, ctx) && TEMPLATE(T, sparse_vec_equal) (window2, v, len, ctx))) + { + flint_printf("u = "); + TEMPLATE(T, sparse_vec_print_pretty) (u, 0, len, ctx); + flint_printf("v = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (v, 0, len, ctx); + flint_printf("u | v = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (w, 0, len, ctx); + flint_printf("window1 = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (window1, 0, len, ctx); + flint_printf("window2 = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (window2, len, len, ctx); + flint_printf("FAIL: results not equal\n"); + abort(); + } + TEMPLATE(T, sparse_vec_window_clear) (window1, ctx); + TEMPLATE(T, sparse_vec_window_clear) (window2, ctx); + + TEMPLATE(T, sparse_vec_init) (window1, ctx); + TEMPLATE(T, sparse_vec_init) (window2, ctx); + TEMPLATE(T, sparse_vec_split) (window1, window2, w, len, ctx); + if (!(TEMPLATE(T, sparse_vec_equal) (window1, u, 0, ctx) && TEMPLATE(T, sparse_vec_equal) (window2, v, 0, ctx))) + { + flint_printf("u = "); + TEMPLATE(T, sparse_vec_print_pretty) (u, 0, len, ctx); + flint_printf("v = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (v, 0, len, ctx); + flint_printf("u | v = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (w, 0, len, ctx); + flint_printf("window1 = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (window1, 0, len, ctx); + flint_printf("window2 = \n"); + TEMPLATE(T, sparse_vec_print_pretty) (window2, 0, len, ctx); + flint_printf("FAIL: results not equal\n"); + abort(); + } + TEMPLATE(T, sparse_vec_window_clear) (window1, ctx); + TEMPLATE(T, sparse_vec_window_clear) (window2, ctx); + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + TEMPLATE(T, sparse_vec_clear) (w, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-construct.c b/fq_sparse_vec_templates/test/t-construct.c new file mode 100644 index 0000000000..d15adfebb2 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-construct.c @@ -0,0 +1,77 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz, i, j; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) u, v; + slong *inds; + TEMPLATE(T, struct) *vals; + FLINT_TEST_INIT(state); + + flint_printf("construction from elements...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + + /* Construct v from entries of u */ + inds = flint_malloc(nnz * sizeof(*inds)); + vals = flint_malloc(nnz * sizeof(*vals)); + for (i = 0; i < nnz; ++i) + { + inds[i] = u->entries[i].ind; + TEMPLATE(T, init) (&vals[i], ctx); + TEMPLATE(T, set) (&vals[i], u->entries[i].val, ctx); + } + TEMPLATE(T, sparse_vec_from_entries) (v, inds, vals, nnz, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (u, v, 0, ctx)) + { + flint_printf("FAIL: u != v\n"); + abort(); + } + flint_free(inds); + for (i = 0; i < nnz; ++i) + { + TEMPLATE(T, clear) (&vals[i], ctx); + } + flint_free(vals); + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-dense.c b/fq_sparse_vec_templates/test/t-dense.c new file mode 100644 index 0000000000..23f3f27a97 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-dense.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, t) *val; + TEMPLATE(T, sparse_vec_t) u, v; + TEMPLATE(T, struct) *w, *x; + FLINT_TEST_INIT(state); + + flint_printf("conversion to/from dense vector...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + w = _TEMPLATE(T, vec_init) (len, ctx); + x = _TEMPLATE(T, vec_init) (len, ctx); + + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + + TEMPLATE(T, sparse_vec_to_dense) (w, u, len, ctx); + TEMPLATE(T, sparse_vec_from_dense) (v, w, len, ctx); + + for (i = 0; i < len; ++i) + { + val = TEMPLATE(T, sparse_vec_at) (u, i, ctx); + if ((val == NULL && (!TEMPLATE(T, is_zero) (&w[i], ctx))) || (val != NULL && !(TEMPLATE(T, equal) (*val, &w[i], ctx)))) + { + flint_printf("FAIL: u[%wd] != v[%wd]\n", i, i); + abort(); + } + } + if (!TEMPLATE(T, sparse_vec_equal) (u, v, 0, ctx)) + { + flint_printf("FAIL: u != v\n"); + abort(); + } + + _TEMPLATE(T, vec_randtest) (w, state, len, ctx); + TEMPLATE(T, sparse_vec_from_dense) (u, w, len, ctx); + TEMPLATE(T, sparse_vec_to_dense) (x, u, len, ctx); + + if (!_TEMPLATE(T, vec_equal) (w, x, len, ctx)) + { + flint_printf("FAIL: w != x\n"); + abort(); + } + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + _TEMPLATE(T, vec_clear) (w, len, ctx); + _TEMPLATE(T, vec_clear) (x, len, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-dot.c b/fq_sparse_vec_templates/test/t-dot.c new file mode 100644 index 0000000000..d83ff86d19 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-dot.c @@ -0,0 +1,84 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, t) a, b; + TEMPLATE(T, sparse_vec_t) u, v; + TEMPLATE(T, struct) *w, *x; + FLINT_TEST_INIT(state); + + flint_printf("dot product...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + TEMPLATE(T, init) (a, ctx); + TEMPLATE(T, init) (b, ctx); + + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + w = _TEMPLATE(T, vec_init) (len, ctx); + x = _TEMPLATE(T, vec_init) (len, ctx); + + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_to_dense) (w, u, len, ctx); + TEMPLATE(T, sparse_vec_to_dense) (x, v, len, ctx); + + TEMPLATE(T, sparse_vec_dot) (a, u, v, ctx); + _TEMPLATE(T, vec_dot) (b, w, x, len, ctx); + + if (!TEMPLATE(T, equal) (a, b, ctx)) + { + flint_printf("Fail: sparse dot sparse\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_dot_dense) (a, u, x, ctx); + + if (!TEMPLATE(T, equal) (a, b, ctx)) + { + flint_printf("Fail: sparse dot dense\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + _TEMPLATE(T, vec_clear) (w, len, ctx); + _TEMPLATE(T, vec_clear) (x, len, ctx); + TEMPLATE(T, clear) (a, ctx); + TEMPLATE(T, clear) (b, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-init_clear.c b/fq_sparse_vec_templates/test/t-init_clear.c new file mode 100644 index 0000000000..39bb9008b5 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-init_clear.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +static void check_zero(TEMPLATE(T, sparse_vec_t) vec) +{ + if (vec->nnz != UWORD(0)) +{ + flint_printf("FAIL: nnz not zero!\n"); + abort(); + } + if (vec->entries != NULL) +{ + flint_printf("FAIL: entries not null!\n"); + abort(); + } +} + +int +main(void) +{ + slong rep, len, nnz, i; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) vec; + FLINT_TEST_INIT(state); + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + TEMPLATE(T, sparse_vec_init) (vec, ctx); + + check_zero(vec); + + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_randtest) (vec, state, nnz, len, ctx); + + if (nnz == 0) check_zero(vec); + else + { + for (i = 0; i < nnz; ++i) + { + TEMPLATE(T, sparse_entry_struct) *e = &vec->entries[i]; + if (e->ind >= len) + { + flint_printf("FAIL: found index %wd >= %wd!\n", e->ind, len); + abort(); + } + if (TEMPLATE(T, is_zero) (e->val, ctx)) + { + flint_printf("FAIL: found 0 value\n"); + abort(); + } + if (i>0 && e->ind <= e[-1].ind) + { + flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); + abort(); + } + } + } + + TEMPLATE(T, sparse_vec_clear) (vec, ctx); + check_zero(vec); + + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-neg.c b/fq_sparse_vec_templates/test/t-neg.c new file mode 100644 index 0000000000..f183c53612 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-neg.c @@ -0,0 +1,76 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) u, v, w, x; + FLINT_TEST_INIT(state); + + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + TEMPLATE(T, sparse_vec_init) (w, ctx); + TEMPLATE(T, sparse_vec_init) (x, ctx); + + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + + TEMPLATE(T, sparse_vec_sub) (w, u, v, ctx); + TEMPLATE(T, sparse_vec_neg) (v, v, ctx); + TEMPLATE(T, sparse_vec_add) (x, u, v, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (w, x, 0, ctx)) + { + flint_printf("FAIL: u - v != u + (-v)\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_neg) (w, u, ctx); + TEMPLATE(T, sparse_vec_neg) (u, u, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (w, w, 0, ctx)) + { + flint_printf("FAIL\n"); + abort(); + } + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + TEMPLATE(T, sparse_vec_clear) (w, ctx); + TEMPLATE(T, sparse_vec_clear) (x, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_sparse_vec_templates/test/t-scalar_mul.c b/fq_sparse_vec_templates/test/t-scalar_mul.c new file mode 100644 index 0000000000..cc68dad000 --- /dev/null +++ b/fq_sparse_vec_templates/test/t-scalar_mul.c @@ -0,0 +1,90 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include "templates.h" + +#include +#include +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, len, nnz; + TEMPLATE(T, t) c; + TEMPLATE(T, ctx_t) ctx; + TEMPLATE(T, sparse_vec_t) u, v, w, x; + FLINT_TEST_INIT(state); + + flint_printf("scalar_mul and muladd...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + TEMPLATE(T, ctx_randtest) (ctx, state); + TEMPLATE(T, init) (c, ctx); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + TEMPLATE(T, sparse_vec_init) (u, ctx); + TEMPLATE(T, sparse_vec_init) (v, ctx); + TEMPLATE(T, sparse_vec_init) (w, ctx); + TEMPLATE(T, sparse_vec_init) (x, ctx); + + TEMPLATE(T, sparse_vec_randtest) (u, state, nnz, len, ctx); + TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); + TEMPLATE(T, randtest) (c, state, ctx); + + TEMPLATE(T, sparse_vec_scalar_addmul) (w, u, v, c, ctx); + TEMPLATE(T, sparse_vec_scalar_mul) (x, v, c, ctx); + TEMPLATE(T, sparse_vec_add) (x, x, u, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (w, x, 0, ctx)) + { + flint_printf("FAIL: u + c*v != u + (c*v)\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_scalar_addmul) (w, u, v, c, ctx); + TEMPLATE(T, sparse_vec_scalar_addmul) (u, u, v, c, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (u, w, 0, ctx)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_scalar_mul) (x, v, c, ctx); + TEMPLATE(T, sparse_vec_scalar_mul) (v, v, c, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (v, x, 0, ctx)) + { + flint_printf("FAIL: c*v != (c *= v)\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_clear) (u, ctx); + TEMPLATE(T, sparse_vec_clear) (v, ctx); + TEMPLATE(T, sparse_vec_clear) (w, ctx); + TEMPLATE(T, sparse_vec_clear) (x, ctx); + TEMPLATE(T, clear) (c, ctx); + TEMPLATE(T, ctx_clear) (ctx); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + +#endif \ No newline at end of file diff --git a/fq_vec_templates.h b/fq_vec_templates.h index 9dbcd0601a..61f9a49dcc 100644 --- a/fq_vec_templates.h +++ b/fq_vec_templates.h @@ -47,6 +47,20 @@ int _TEMPLATE(T, vec_print)(const TEMPLATE(T, struct) * vec, slong len, return _TEMPLATE(T, vec_fprint)(stdout, vec, len, ctx); } +FQ_VEC_TEMPLATES_INLINE +void _TEMPLATE(T, vec_print_pretty)(const TEMPLATE(T, struct) * vec, slong len, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + flint_printf("["); + for (i = 0; i < len; ++i) + { + if (i > 0) flint_printf(" "); + TEMPLATE(T, print_pretty) (&vec[i], ctx); + } + flint_printf("]"); +} + /* Conversions *************************************************************/ /* Assignment and basic manipulation ***************************************/ diff --git a/fq_zech_mat/addmul.c b/fq_zech_mat/addmul.c new file mode 100644 index 0000000000..a84b964966 --- /dev/null +++ b/fq_zech_mat/addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/addmul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_mat/mul_vec.c b/fq_zech_mat/mul_vec.c new file mode 100644 index 0000000000..1aed5aabe3 --- /dev/null +++ b/fq_zech_mat/mul_vec.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/mul_vec.c" +#undef CAP_T +#undef T diff --git a/fq_zech_mat/scalar_addmul.c b/fq_zech_mat/scalar_addmul.c new file mode 100644 index 0000000000..8ef62b96e2 --- /dev/null +++ b/fq_zech_mat/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_mat/scalar_mul.c b/fq_zech_mat/scalar_mul.c new file mode 100644 index 0000000000..095427d95b --- /dev/null +++ b/fq_zech_mat/scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_mat/scalar_submul.c b/fq_zech_mat/scalar_submul.c new file mode 100644 index 0000000000..858564f147 --- /dev/null +++ b/fq_zech_mat/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_mat/transpose.c b/fq_zech_mat/transpose.c new file mode 100644 index 0000000000..8ffa3ea6e8 --- /dev/null +++ b/fq_zech_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat.h b/fq_zech_sparse_mat.h new file mode 100644 index 0000000000..50de22b788 --- /dev/null +++ b/fq_zech_sparse_mat.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_ZECH_SPARSE_MAT_H +#define FQ_ZECH_SPARSE_MAT_H + +#ifdef FQ_ZECH_SPARSE_MAT_INLINES_C +#define FQ_SPARSE_MAT_TEMPLATES_INLINE FLINT_DLL +#define FQ_ZECH_SPARSE_MAT_INLINE FLINT_DLL +#else +#define FQ_SPARSE_MAT_TEMPLATES_INLINE static __inline__ +#define FQ_ZECH_SPARSE_MAT_INLINE static __inline__ +#endif + + +#include "fq_zech.h" +#include "fq_zech_vec.h" +#include "fq_zech_sparse_vec.h" +#include "fq_zech_mat.h" + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_zech_sparse_mat/from_entries.c b/fq_zech_sparse_mat/from_entries.c new file mode 100644 index 0000000000..cf823fe825 --- /dev/null +++ b/fq_zech_sparse_mat/from_entries.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/from_entries.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/inv.c b/fq_zech_sparse_mat/inv.c new file mode 100644 index 0000000000..e2915a21d6 --- /dev/null +++ b/fq_zech_sparse_mat/inv.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/inv.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/lu.c b/fq_zech_sparse_mat/lu.c new file mode 100644 index 0000000000..ce3856921a --- /dev/null +++ b/fq_zech_sparse_mat/lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/lu.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/nullspace_lanczos.c b/fq_zech_sparse_mat/nullspace_lanczos.c new file mode 100644 index 0000000000..186d8efbad --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/nullspace_lu.c b/fq_zech_sparse_mat/nullspace_lu.c new file mode 100644 index 0000000000..9622c8ac02 --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_lu.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_lu.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/nullspace_rref.c b/fq_zech_sparse_mat/nullspace_rref.c new file mode 100644 index 0000000000..ef4a781520 --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_rref.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/nullspace_wiedemann.c b/fq_zech_sparse_mat/nullspace_wiedemann.c new file mode 100644 index 0000000000..cab43b28b2 --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/print_pretty.c b/fq_zech_sparse_mat/print_pretty.c new file mode 100644 index 0000000000..f4d091fc8a --- /dev/null +++ b/fq_zech_sparse_mat/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/randtest.c b/fq_zech_sparse_mat/randtest.c new file mode 100644 index 0000000000..6ce2a2f0be --- /dev/null +++ b/fq_zech_sparse_mat/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/rref.c b/fq_zech_sparse_mat/rref.c new file mode 100644 index 0000000000..cdbbeac30a --- /dev/null +++ b/fq_zech_sparse_mat/rref.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/rref.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_block_lanczos.c b/fq_zech_sparse_mat/solve_block_lanczos.c new file mode 100644 index 0000000000..0fe1013eff --- /dev/null +++ b/fq_zech_sparse_mat/solve_block_lanczos.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for + Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 + + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_block_wiedemann.c b/fq_zech_sparse_mat/solve_block_wiedemann.c new file mode 100644 index 0000000000..aa56921df6 --- /dev/null +++ b/fq_zech_sparse_mat/solve_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_lanczos.c b/fq_zech_sparse_mat/solve_lanczos.c new file mode 100644 index 0000000000..5a896d9309 --- /dev/null +++ b/fq_zech_sparse_mat/solve_lanczos.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_lu.c b/fq_zech_sparse_mat/solve_lu.c new file mode 100644 index 0000000000..15685f8902 --- /dev/null +++ b/fq_zech_sparse_mat/solve_lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_lu.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_rref.c b/fq_zech_sparse_mat/solve_rref.c new file mode 100644 index 0000000000..ddb496768b --- /dev/null +++ b/fq_zech_sparse_mat/solve_rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_rref.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/solve_wiedemann.c b/fq_zech_sparse_mat/solve_wiedemann.c new file mode 100644 index 0000000000..0fedb0e65a --- /dev/null +++ b/fq_zech_sparse_mat/solve_wiedemann.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/solve_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-add.c b/fq_zech_sparse_mat/test/t-add.c new file mode 100644 index 0000000000..7da2fdb588 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-concat_horizontal.c b/fq_zech_sparse_mat/test/t-concat_horizontal.c new file mode 100644 index 0000000000..1d53c5f725 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-concat_horizontal.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-concat_horizontal.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-concat_vertical.c b/fq_zech_sparse_mat/test/t-concat_vertical.c new file mode 100644 index 0000000000..8ef02c7014 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-concat_vertical.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-concat_vertical.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-construct.c b/fq_zech_sparse_mat/test/t-construct.c new file mode 100644 index 0000000000..04ce82c08b --- /dev/null +++ b/fq_zech_sparse_mat/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-dense.c b/fq_zech_sparse_mat/test/t-dense.c new file mode 100644 index 0000000000..f5397ecb4d --- /dev/null +++ b/fq_zech_sparse_mat/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-init_clear.c b/fq_zech_sparse_mat/test/t-init_clear.c new file mode 100644 index 0000000000..00e1aacd13 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-inv.c b/fq_zech_sparse_mat/test/t-inv.c new file mode 100644 index 0000000000..0866c19b0c --- /dev/null +++ b/fq_zech_sparse_mat/test/t-inv.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-inv.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-lu.c b/fq_zech_sparse_mat/test/t-lu.c new file mode 100644 index 0000000000..77a7087b1d --- /dev/null +++ b/fq_zech_sparse_mat/test/t-lu.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-lu.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-mul.c b/fq_zech_sparse_mat/test/t-mul.c new file mode 100644 index 0000000000..efb364c74b --- /dev/null +++ b/fq_zech_sparse_mat/test/t-mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-mul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-neg.c b/fq_zech_sparse_mat/test/t-neg.c new file mode 100644 index 0000000000..67a9750a55 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-neg.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-nullspace.c b/fq_zech_sparse_mat/test/t-nullspace.c new file mode 100644 index 0000000000..f0e78cd489 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-nullspace.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-nullspace.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-rref.c b/fq_zech_sparse_mat/test/t-rref.c new file mode 100644 index 0000000000..c8a9abc0fe --- /dev/null +++ b/fq_zech_sparse_mat/test/t-rref.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-rref.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-scalar_mul.c b/fq_zech_sparse_mat/test/t-scalar_mul.c new file mode 100644 index 0000000000..2223d641e9 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-scalar_mul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-solve.c b/fq_zech_sparse_mat/test/t-solve.c new file mode 100644 index 0000000000..8ba6081629 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-solve.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-solve.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/test/t-transpose.c b/fq_zech_sparse_mat/test/t-transpose.c new file mode 100644 index 0000000000..5ca1c4d587 --- /dev/null +++ b/fq_zech_sparse_mat/test/t-transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/test/t-transpose.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/transpose.c b/fq_zech_sparse_mat/transpose.c new file mode 100644 index 0000000000..9e1ce8d711 --- /dev/null +++ b/fq_zech_sparse_mat/transpose.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/transpose.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/window_init.c b/fq_zech_sparse_mat/window_init.c new file mode 100644 index 0000000000..0df7ccaf51 --- /dev/null +++ b/fq_zech_sparse_mat/window_init.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/window_init.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec.h b/fq_zech_sparse_vec.h new file mode 100644 index 0000000000..3e26cc940b --- /dev/null +++ b/fq_zech_sparse_vec.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2013 Mike Hansen + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FQ_ZECH_SPARSE_VEC_H +#define FQ_ZECH_SPARSE_VEC_H + +#ifdef FQ_ZECH_SPARSE_VEC_INLINES_C +#define FQ_SPARSE_VEC_TEMPLATES_INLINE FLINT_DLL +#define FQ_ZECH_SPARSE_VEC_INLINE FLINT_DLL +#else +#define FQ_SPARSE_VEC_TEMPLATES_INLINE static __inline__ +#define FQ_ZECH_SPARSE_VEC_INLINE static __inline__ +#endif + +#include "fq_zech.h" +#include "fq_zech_vec.h" + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates.h" +#undef CAP_T +#undef T + +#endif diff --git a/fq_zech_sparse_vec/add.c b/fq_zech_sparse_vec/add.c new file mode 100644 index 0000000000..628c65dcc2 --- /dev/null +++ b/fq_zech_sparse_vec/add.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/add.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/print_pretty.c b/fq_zech_sparse_vec/print_pretty.c new file mode 100644 index 0000000000..1f9451e311 --- /dev/null +++ b/fq_zech_sparse_vec/print_pretty.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/print_pretty.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/randtest.c b/fq_zech_sparse_vec/randtest.c new file mode 100644 index 0000000000..db642232b9 --- /dev/null +++ b/fq_zech_sparse_vec/randtest.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/randtest.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/scalar_addmul.c b/fq_zech_sparse_vec/scalar_addmul.c new file mode 100644 index 0000000000..1baaef6f9d --- /dev/null +++ b/fq_zech_sparse_vec/scalar_addmul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/scalar_addmul.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/sub.c b/fq_zech_sparse_vec/sub.c new file mode 100644 index 0000000000..2bf5a62707 --- /dev/null +++ b/fq_zech_sparse_vec/sub.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/sub.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-add.c b/fq_zech_sparse_vec/test/t-add.c new file mode 100644 index 0000000000..4f1d749ead --- /dev/null +++ b/fq_zech_sparse_vec/test/t-add.c @@ -0,0 +1,21 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-add.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-concat.c b/fq_zech_sparse_vec/test/t-concat.c new file mode 100644 index 0000000000..5d788bc0f6 --- /dev/null +++ b/fq_zech_sparse_vec/test/t-concat.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-concat.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-construct.c b/fq_zech_sparse_vec/test/t-construct.c new file mode 100644 index 0000000000..9b5a886c96 --- /dev/null +++ b/fq_zech_sparse_vec/test/t-construct.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-construct.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-dense.c b/fq_zech_sparse_vec/test/t-dense.c new file mode 100644 index 0000000000..16ed02a415 --- /dev/null +++ b/fq_zech_sparse_vec/test/t-dense.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-dense.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-dot.c b/fq_zech_sparse_vec/test/t-dot.c new file mode 100644 index 0000000000..57846654dd --- /dev/null +++ b/fq_zech_sparse_vec/test/t-dot.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-dot.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-init_clear.c b/fq_zech_sparse_vec/test/t-init_clear.c new file mode 100644 index 0000000000..3b0af13dd9 --- /dev/null +++ b/fq_zech_sparse_vec/test/t-init_clear.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-init_clear.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-neg.c b/fq_zech_sparse_vec/test/t-neg.c new file mode 100644 index 0000000000..a234501817 --- /dev/null +++ b/fq_zech_sparse_vec/test/t-neg.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-neg.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_vec/test/t-scalar_mul.c b/fq_zech_sparse_vec/test/t-scalar_mul.c new file mode 100644 index 0000000000..23aec9e2ad --- /dev/null +++ b/fq_zech_sparse_vec/test/t-scalar_mul.c @@ -0,0 +1,23 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/test/t-scalar_mul.c" +#undef CAP_T +#undef T diff --git a/nmod_mat.h b/nmod_mat.h index 1cae3a31bf..9ed0a797fb 100644 --- a/nmod_mat.h +++ b/nmod_mat.h @@ -193,7 +193,7 @@ void nmod_mat_scalar_mul_fmpz(nmod_mat_t res, const nmod_mat_t M, const fmpz_t c /* Matrix multiplication */ NMOD_MAT_INLINE -void nmod_mat_mul_vec(mp_ptr y, const nmod_mat_t A, const mp_ptr x) { +void nmod_mat_mul_vec(mp_ptr y, const nmod_mat_t A, mp_srcptr x) { slong i; slong limbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); for(i=0; ir; ++i) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 6407b38876..19f36fa52c 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -28,7 +28,6 @@ #define ulong mp_limb_t #include "flint.h" -#include "longlong.h" #include "ulong_extras.h" #include "nmod_vec.h" #include "nmod_sparse_vec.h" @@ -54,333 +53,351 @@ nmod_sparse_mat_struct; typedef nmod_sparse_mat_struct nmod_sparse_mat_t[1]; NMOD_SPARSE_MAT_INLINE -void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t mat, mp_limb_t n) +void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t M, mp_limb_t n) { - mat->mod.n = n; - count_leading_zeros(mat->mod.norm, n); - invert_limb(mat->mod.ninv, n << mat->mod.norm); + M->mod.n = n; + count_leading_zeros(M->mod.norm, n); + invert_limb(M->mod.ninv, n << M->mod.norm); } /* Memory management */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, slong cols, nmod_t mod) +void nmod_sparse_mat_init(nmod_sparse_mat_t M, slong rows, slong cols, nmod_t mod) { - mat->rows = flint_calloc(rows, sizeof(*mat->rows)); - mat->r = rows; - mat->c = cols; - mat->c_off = 0; - mat->mod = mod; + M->rows = flint_calloc(rows, sizeof(*M->rows)); + M->r = rows; + M->c = cols; + M->c_off = 0; + M->mod = mod; } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_clear(nmod_sparse_mat_t mat) +void nmod_sparse_mat_clear(nmod_sparse_mat_t M) { slong i; - for (i = 0; i < mat->r; ++i) nmod_sparse_vec_clear(&mat->rows[i]); - flint_free(mat->rows); - memset(mat, 0, sizeof(*mat)); + for (i = 0; i < M->r; ++i) nmod_sparse_vec_clear(&M->rows[i]); + flint_free(M->rows); + memset(M, 0, sizeof(*M)); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) +void nmod_sparse_mat_swap(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2) { nmod_sparse_mat_t tmp; - *tmp = *mat1; *mat1 = *mat2; *mat2 = *tmp; + *tmp = *M1; *M1 = *M2; *M2 = *tmp; } /* One-time instantiation */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_zero(nmod_sparse_mat_t mat) +void nmod_sparse_mat_zero(nmod_sparse_mat_t M) { slong i; - for (i = 0; i < mat->r; ++i) nmod_sparse_vec_zero(&mat->rows[i]); + for (i = 0; i < M->r; ++i) nmod_sparse_vec_zero(&M->rows[i]); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_one(nmod_sparse_mat_t mat) +void nmod_sparse_mat_one(nmod_sparse_mat_t M) { slong i; - for (i = 0; i < mat->r; ++i) nmod_sparse_vec_one(&mat->rows[i], i); + for (i = 0; i < M->r; ++i) nmod_sparse_vec_one(&M->rows[i], i); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) +void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { - slong i, rmax = FLINT_MIN(mat->r, src->r); - if(mat==src || mat->r == 0) return; - for(i=0; irows[i], &src->rows[i], src->c_off); + slong i, rmax = FLINT_MIN(M->r, src->r); + if(M==src || M->r == 0) return; + for(i=0; irows[i], &src->rows[i], src->c_off); } FLINT_DLL -void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); +void nmod_sparse_mat_from_entries(nmod_sparse_mat_t M, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_append_col(nmod_sparse_mat_t mat, const mp_ptr vec) +void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, const mp_ptr v) { slong i; - for(i=0; ir; ++i) _nmod_sparse_vec_append_entry(&mat->rows[i], mat->c, vec[i]); - mat->c += 1; + for(i=0; ir; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); + M->c += 1; } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, const nmod_sparse_vec_t vec) +void nmod_sparse_mat_append_row(nmod_sparse_mat_t M, const nmod_sparse_vec_t v) { - mat->rows = realloc(mat->rows, (mat->r+1)*sizeof(*mat->rows)); - memset(mat->rows + mat->r, 0, sizeof(*mat->rows)); - nmod_sparse_vec_set(&mat->rows[mat->r], vec, 0); - mat->r += 1; + M->rows = realloc(M->rows, (M->r+1)*sizeof(*M->rows)); + memset(M->rows + M->r, 0, sizeof(*M->rows)); + nmod_sparse_vec_set(&M->rows[M->r], v, 0); + M->r += 1; } /* Convert from/to dense matrix */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_from_dense(nmod_sparse_mat_t mat, const nmod_mat_t src) +void nmod_sparse_mat_from_dense(nmod_sparse_mat_t M, const nmod_mat_t dM) { - slong i, rmax = FLINT_MIN(mat->r, src->r); - for (i = 0; i < rmax; ++i) nmod_sparse_vec_from_dense(&mat->rows[i], src->rows[i], src->c); + slong i, rmax = FLINT_MIN(M->r, dM->r); + for (i = 0; i < rmax; ++i) nmod_sparse_vec_from_dense(&M->rows[i], dM->rows[i], dM->c); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) +void nmod_sparse_mat_to_dense(nmod_mat_t dM, const nmod_sparse_mat_t M) { - slong i, rmax = FLINT_MIN(mat->r, src->r); - for (i = 0; i < rmax; ++i) nmod_sparse_vec_to_dense(mat->rows[i], &src->rows[i], mat->c); + slong i, rmax = FLINT_MIN(M->r, dM->r); + for (i = 0; i < rmax; ++i) nmod_sparse_vec_to_dense(dM->rows[i], &M->rows[i], dM->c); } -/* Windows and concatenation */ +/* Windows, concatenation, and splitting */ FLINT_DLL -void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2); +void nmod_sparse_mat_window_init(nmod_sparse_mat_t W, const nmod_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2); NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) +void nmod_sparse_mat_window_clear(nmod_sparse_mat_t W) { - flint_free(window->rows); - memset(window, 0, sizeof(*window)); + flint_free(W->rows); + memset(W, 0, sizeof(*W)); } -/* res->r must equal mat1->r and mat2->r */ +/* Combine M1 and M2 into block matrix B = [M1 M2] */ +/* B->r must equal M1->r and M2->r */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, - const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, + const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; - res->c = mat1->c + mat2->c; - for (i = 0; i < res->r; ++i) - nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); + B->c = M1->c + M2->c; + for (i = 0; i < B->r; ++i) + nmod_sparse_vec_concat(&B->rows[i], &M1->rows[i], &M2->rows[i], M1->c); } -/* res->r must equal mat1->r + mat2->r */ +/* Combine M1 and M2 into block matrix B = [M1^t M1^t]^t */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; - res->c = FLINT_MAX(mat1->c, mat2->c); - for (i = 0; i < mat1->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i], mat1->c_off); - for (i = mat1->r; i < res->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r], mat2->c_off); + B->c = FLINT_MAX(M1->c, M2->c); + for (i = 0; i < M1->r; ++i) + nmod_sparse_vec_set(&B->rows[i], &M1->rows[i], M1->c_off); + for (i = M1->r; i < B->r; ++i) + nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); } +/* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ +/* M1->r and M2->r must equal B->r */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong c) +void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_split(&res1->rows[i], &res2->rows[i], &mat->rows[i], c); + for(i=0; ir; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); } +/* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong r) +void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong r) { slong i; - r = FLINT_MIN(r, mat->r); - for(i=0; irows[i], &mat->rows[i], mat->c_off); - for(i=r; ir; ++i) nmod_sparse_vec_set(&res2->rows[i-r], &mat->rows[i], mat->c_off); + r = FLINT_MIN(r, B->r); + for(i=0; irows[i], &B->rows[i], B->c_off); + for(i=r; ir; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE -void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t mat, slong *Q) +void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; - for (i = 0; i < mat->r; ++i) { - if(!mat->rows[i].nnz) continue; - nmod_sparse_vec_permute_inds(&mat->rows[i], Q); - qsort(mat->rows[i].entries, mat->rows[i].nnz, sizeof(*mat->rows[i].entries), nmod_sparse_entry_cmp); + for (i = 0; i < M->r; ++i) { + if(!M->rows[i].nnz) continue; + nmod_sparse_vec_permute_inds(&M->rows[i], Q); + qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), nmod_sparse_entry_cmp); } } NMOD_SPARSE_VEC_INLINE -void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t mat, slong *P) +void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t M, slong *P) { slong i; nmod_sparse_vec_struct *prows; - prows = flint_calloc(mat->r, sizeof(*prows)); - for (i = 0; i < mat->r; ++i) prows[P[i]] = mat->rows[i]; - memcpy(mat->rows, prows, mat->r*sizeof(*mat->rows)); + prows = flint_calloc(M->r, sizeof(*prows)); + for (i = 0; i < M->r; ++i) prows[P[i]] = M->rows[i]; + memcpy(M->rows, prows, M->r*sizeof(*M->rows)); flint_free(prows); } /* Random matrix generation */ -FLINT_DLL void nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state, slong min_nnz, slong max_nnz); +FLINT_DLL void nmod_sparse_mat_randtest(nmod_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz); /* -FLINT_DLL void nmod_sparse_mat_randfull(nmod_sparse_mat_t mat, flint_rand_t state); -FLINT_DLL int nmod_sparse_mat_randpermdiag(nmod_sparse_mat_t mat, flint_rand_t state, +FLINT_DLL void nmod_sparse_mat_randfull(nmod_sparse_mat_t M, flint_rand_t state); +FLINT_DLL int nmod_sparse_mat_randpermdiag(nmod_sparse_mat_t M, flint_rand_t state, mp_srcptr diag, slong n); FLINT_DLL void nmod_sparse_mat_randrank(nmod_sparse_mat_t, flint_rand_t state, slong rank); -FLINT_DLL void nmod_sparse_mat_randops(nmod_sparse_mat_t mat, slong count, flint_rand_t state); -FLINT_DLL void nmod_sparse_mat_randtril(nmod_sparse_mat_t mat, flint_rand_t state, int unit); -FLINT_DLL void nmod_sparse_mat_randtriu(nmod_sparse_mat_t mat, flint_rand_t state, int unit); +FLINT_DLL void nmod_sparse_mat_randops(nmod_sparse_mat_t M, slong count, flint_rand_t state); +FLINT_DLL void nmod_sparse_mat_randtril(nmod_sparse_mat_t M, flint_rand_t state, int unit); +FLINT_DLL void nmod_sparse_mat_randtriu(nmod_sparse_mat_t M, flint_rand_t state, int unit); */ -FLINT_DLL void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat); +FLINT_DLL void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t M); NMOD_SPARSE_MAT_INLINE -int nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +int nmod_sparse_mat_equal(const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; - if (mat1->r != mat2->r) return 0; - for (i = 0; i < mat1->r; ++i) - if (nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off) == 0) return 0; + if (M1->r != M2->r) return 0; + for (i = 0; i < M1->r; ++i) + if (nmod_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off) == 0) return 0; return 1; } NMOD_SPARSE_MAT_INLINE -int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t mat) +int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) { slong i; - for (i = 0; i < mat->r; ++i) - if (!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; + for (i = 0; i < M->r; ++i) + if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; return 1; } NMOD_SPARSE_MAT_INLINE -int nmod_sparse_mat_is_square(const nmod_sparse_mat_t mat) +int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) { - return (mat->r == mat->c); + return (M->r == M->c); } -/* Must have A->r == B->c and A->c == B->r */ -FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A); +/* Must have M->r == N->c and M->c == N->r */ +FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, const nmod_sparse_mat_t M); /* Arithmetic */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) { slong i; - nmod_sparse_mat_set(B, A); - for (i = 0; i < B->r; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); + nmod_sparse_mat_set(N, M); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) +void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { - if (c == UWORD(0)) nmod_sparse_mat_zero(B); + if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; - nmod_sparse_mat_set(B, A); - for (i = 0; i < B->r; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); + nmod_sparse_mat_set(N, M); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul(&N->rows[i], &N->rows[i], c, N->mod); } } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t res, const nmod_sparse_mat_t M, const fmpz_t c) +void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, const fmpz_t c) { fmpz_t d; fmpz_init(d); - fmpz_mod_ui(d, c, res->mod.n); - nmod_sparse_mat_scalar_mul(res, M, fmpz_get_ui(d)); + fmpz_mod_ui(d, c, N->mod.n); + nmod_sparse_mat_scalar_mul(N, M, fmpz_get_ui(d)); fmpz_clear(d); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) +void nmod_sparse_mat_addmul(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { slong i; - for (i = 0; i < C->r; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(C, A, B, UWORD(1)); + nmod_sparse_mat_addmul(O, M, N, UWORD(1)); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(C, A, B, C->mod.n-UWORD(1)); + nmod_sparse_mat_addmul(O, M, N, O->mod.n-UWORD(1)); } /* Matrix-vector and matrix-matrix multipliciation */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, const mp_ptr x) { slong i; - for (i = 0; i < A->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); + for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) +void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; - for (i = 0; i < A->r; ++i) + for (i = 0; i < M->r; ++i) { - for (j = 0; j < A->rows[i].nnz; ++j) + for (j = 0; j < M->rows[i].nnz; ++j) { - nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; + nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } } } /* Permutations */ -/* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t mat, slong * perm, slong r, slong s); -FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t mat, slong * perm); -FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t mat, slong * perm, slong r, slong s); -FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t mat, slong * perm); -FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t A, slong * P, slong n); +/* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t M, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t M, slong * perm); +FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t M, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t M, slong * perm); +FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t M, slong * P, slong n); */ /* Decomposition/reduction */ FLINT_DLL -slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t M); FLINT_DLL -slong nmod_sparse_mat_rref(nmod_sparse_mat_t A); +slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); /* Solve Ax=b */ FLINT_DLL -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state); +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); FLINT_DLL -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); FLINT_DLL -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); FLINT_DLL -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); + +FLINT_DLL +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); /* Find single nullvector */ -int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); +FLINT_DLL +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); +FLINT_DLL +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); /* Note: this should take in uninitialized matrix X */ FLINT_DLL -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); */ #ifdef __cplusplus } diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index f1e66b5bdd..9b78f0842f 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -23,13 +23,13 @@ #include "flint.h" #include "nmod_sparse_mat.h" -void nmod_sparse_mat_from_entries(nmod_sparse_mat_t mat, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) +void nmod_sparse_mat_from_entries(nmod_sparse_mat_t M, slong * rows, slong * cols, mp_limb_t * vals, slong nnz) { slong r, i, j; - for (r = i = 0; r < mat->r; ++r, i = j) + for (r = i = 0; r < M->r; ++r, i = j) { - mat->rows[r].nnz = 0; + M->rows[r].nnz = 0; for (j = i; j < nnz && rows[j]==r; ++j); - nmod_sparse_vec_from_entries(&mat->rows[r], cols+i, vals+i, j-i); + nmod_sparse_vec_from_entries(&M->rows[r], cols+i, vals+i, j-i); } } diff --git a/nmod_sparse_mat/inv.c b/nmod_sparse_mat/inv.c index 4396bcead9..d767b47e64 100644 --- a/nmod_sparse_mat/inv.c +++ b/nmod_sparse_mat/inv.c @@ -15,25 +15,25 @@ #include "flint.h" #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A) +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Mi, const nmod_sparse_mat_t M) { slong rk; - nmod_sparse_mat_t I, AI; + nmod_sparse_mat_t I, MI; nmod_sparse_vec_struct *row; nmod_sparse_entry_struct *le, *re; - /* Create block matrix [A | I] */ - nmod_sparse_mat_init(I, A->r, A->r, A->mod); + /* Create block matrix [M | I] */ + nmod_sparse_mat_init(I, M->r, M->r, M->mod); nmod_sparse_mat_one(I); - nmod_sparse_mat_init(AI, A->r, A->r + A->c, A->mod); - nmod_sparse_mat_concat_horizontal(AI, A, I); + nmod_sparse_mat_init(MI, M->r, M->r + M->c, M->mod); + nmod_sparse_mat_concat_horizontal(MI, M, I); /* Run Gaussian elimination on first half */ - AI->c = A->c; - rk = nmod_sparse_mat_rref(AI); - AI->c = A->c+A->r; - nmod_sparse_mat_split_horizontal(I, Ai, AI, A->c); + MI->c = M->c; + rk = nmod_sparse_mat_rref(MI); + MI->c = M->c+M->r; + nmod_sparse_mat_split_horizontal(I, Mi, MI, M->c); nmod_sparse_mat_clear(I); - nmod_sparse_mat_clear(AI); + nmod_sparse_mat_clear(MI); return rk; } diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 3df388caa2..8762f78494 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -51,7 +51,7 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s heap_idx[c] = pos; } -static void print_heap(slong *heap, slong *scores, slong size) { +/* static void print_heap(slong *heap, slong *scores, slong size) { slong level, i; for(level=1; level<=size; level<<=1) { for(i=level; i<=size && i<2*level; ++i) { @@ -60,50 +60,48 @@ static void print_heap(slong *heap, slong *scores, slong size) { flint_printf("\n"); } } - + */ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, - const nmod_sparse_mat_t A) + const nmod_sparse_mat_t M) { -/* flint_printf("Decomposing sparse matrix: "); - nmod_sparse_mat_print_pretty(A); */ slong i, j, r, c, pr, pc, rank, remr, remc; slong *heap, *heap_idx, *scores, heap_size; nmod_sparse_mat_t Lt; nmod_sparse_vec_struct *pcol, *prow, *row, *col; mp_limb_t cinv, cc; - if (A->r == 0 || A->c == 0) + if (M->r == 0 || M->c == 0) { nmod_sparse_mat_zero(L); nmod_sparse_mat_zero(U); - for (i = 0; i < A->r; ++i) P[i] = i; - for (i = 0; i < A->c; ++i) Q[i] = i; + for (i = 0; i < M->r; ++i) P[i] = i; + for (i = 0; i < M->c; ++i) Q[i] = i; return 0; } - nmod_sparse_mat_init(Lt, L->c, L->r, A->mod); - nmod_sparse_mat_transpose(Lt, A); - nmod_sparse_mat_set(U, A); + nmod_sparse_mat_init(Lt, L->c, L->r, M->mod); + nmod_sparse_mat_transpose(Lt, M); + nmod_sparse_mat_set(U, M); /* Set up permutations */ - remr = A->r, remc = A->c; - for (r = 0; rr; ++r) + remr = M->r, remc = M->c; + for (r = 0; rr; ++r) { if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for (c = 0; cc; ++c) + for (c = 0; cc; ++c) { if (!Lt->rows[c].nnz) Q[c] = --remc; else Q[c] = -1; } /* Make heap of nonzero columns by size */ - heap_size = A->c; - heap = flint_malloc(A->c*sizeof(*heap)); - scores = flint_malloc(A->c*sizeof(*scores)); - heap_idx = flint_malloc(A->c*sizeof(*heap_idx)); - for (i = 0; i < A->c; ++i) + heap_size = M->c; + heap = flint_malloc(M->c*sizeof(*heap)); + scores = flint_malloc(M->c*sizeof(*scores)); + heap_idx = flint_malloc(M->c*sizeof(*heap_idx)); + for (i = 0; i < M->c; ++i) { scores[i] = Lt->rows[i].nnz; /* TODO: randomized tiebreaker */ heap[i] = i; @@ -111,19 +109,15 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, } /* Run elimination */ rank = 0; - for (heap_size=A->c; heap_size > 0; ) + for (heap_size=M->c; heap_size > 0; ) { -/* print_heap(heap, scores, heap_size); */ /* Get lowest weight column (top of heap) */ pc = heap[0]; pcol = &Lt->rows[pc]; heap[0] = heap[--heap_size]; heap_down(heap, heap_idx, scores, heap_size, 0); -/* print_heap(heap, scores, heap_size); */ if (pcol->nnz == 0) continue; /* Empty columns already dealt with */ Q[pc] = rank; /* Move pivot column to front */ -/* flint_printf("Pivot col %wd: ", pc); - nmod_sparse_vec_print_pretty(pcol, 0, A->r, A->mod); */ /* Get lowest weight incident row */ pr = pcol->entries[0].ind, prow = &U->rows[pr]; @@ -133,43 +127,31 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, if (row->nnz < prow->nnz) pr = r, prow = row; } P[pr] = rank; /* Move pivot row to front */ -/* flint_printf("Pivot row %wd: ", pr); - nmod_sparse_vec_print_pretty(prow, 0, A->c, A->mod); */ /* Invert pivot */ -/* flint_printf("\tPivot: %wd\n", nmod_sparse_vec_at(prow, pc)); */ - cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), A->mod); + cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), M->mod); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) { r = pcol->entries[j].ind, row = &U->rows[r]; if (P[r] >= 0) continue; /* Skip previous pivot rows */ - cc = nmod_neg(nmod_mul(cinv, nmod_sparse_vec_at(row, pc), A->mod), A->mod); -/* flint_printf("\t\tRow %wd: ", r); - nmod_sparse_vec_print_pretty(row, 0, A->c, A->mod); */ - nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); -/* flint_printf("\t\t\t-> "); - nmod_sparse_vec_print_pretty(row, 0, A->c, A->mod); */ + cc = nmod_neg(nmod_mul(cinv, nmod_sparse_vec_at(row, pc), M->mod), M->mod); + nmod_sparse_vec_scalar_addmul(row, row, prow, cc, M->mod); if (row->nnz == 0) P[r] = --remr; } /* Gaussian eliminate cols */ - nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, A->mod); + nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, M->mod); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Lt->rows[c]; if (Q[c] >= 0) continue; /* Skip previous pivot columns */ - cc = nmod_neg(nmod_sparse_vec_at(col, pr), A->mod); -/* flint_printf("\t\t%Col wd: ", c); - nmod_sparse_vec_print_pretty(col, 0, A->r, A->mod); */ - nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); -/* flint_printf("\t\t\t-> "); - nmod_sparse_vec_print_pretty(col, 0, A->r, A->mod); */ + cc = nmod_neg(nmod_sparse_vec_at(col, pr), M->mod); + nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, M->mod); if (col->nnz == 0) Q[c] = --remc; scores[c] = col->nnz; heap_up(heap, heap_idx, scores, heap_idx[c]); heap_down(heap, heap_idx, scores, heap_size, heap_idx[c]); -/* print_heap(heap, scores, heap_size); */ } rank += 1; diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index 02a42e147f..19969e55cc 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -16,33 +16,33 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters) +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { - /* Generate random solutions to a random system Ax=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; - x = _nmod_vec_init(A->c); + x = _nmod_vec_init(M->c); nxs = 0; xs = NULL; xps = NULL; for(iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_lanczos(x, A, state) == 0) {++iter; continue;} + if(nmod_sparse_mat_nullvector_lanczos(x, M, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ for (j = nxs-1; j >= 0; --j) { - _nmod_vec_scalar_addmul_nmod(x, xs[j], A->c, nmod_neg(x[xps[j]], A->mod), A->mod); + _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } /* Normalize last nonzero entry to 1 */ - for (i = A->c-1; i >= 0 && x[i] == UWORD(0); --i); + for (i = M->c-1; i >= 0 && x[i] == UWORD(0); --i); if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ - _nmod_vec_scalar_mul_nmod(x, x, A->c, nmod_inv(x[i], A->mod), A->mod); + _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ for (j = 0; j < nxs; ++j) { - _nmod_vec_scalar_addmul_nmod(xs[j], x, A->c, nmod_neg(xs[j][i], A->mod), A->mod); + _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } /* Insert into list of vectors in nullspace (ordered by pivot) */ @@ -54,15 +54,15 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, xps[j] = i; xs[j] = x; nxs += 1; - x = _nmod_vec_init(A->c); /* New vector for next iteration */ + x = _nmod_vec_init(M->c); /* New vector for next iteration */ iter = 0; } flint_free(xps); flint_free(x); - nmod_mat_init(X, A->c, nxs, A->mod.n); + nmod_mat_init(X, M->c, nxs, M->mod.n); for (i = 0; i < nxs; ++i) { - for (j = 0; j < A->c; ++j) + for (j = 0; j < M->c; ++j) X->rows[j][i] = xs[i][j]; flint_free(xs[i]); } diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index 322dc33693..74f73b2d68 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -16,7 +16,7 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A) +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) { int good = 1; slong rk, *P, *Q, *Qi, i, j; @@ -24,32 +24,32 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A) nmod_sparse_entry_struct *e; nmod_sparse_vec_struct *Urow; mp_limb_t *Xrow; - P = flint_malloc(A->r * sizeof(*P)); - Q = flint_malloc(A->c * sizeof(*Q)); - nmod_sparse_mat_init(L, A->r, A->c, A->mod); - nmod_sparse_mat_init(U, A->r, A->c, A->mod); - rk = nmod_sparse_mat_lu(P, Q, L, U, A); + P = flint_malloc(M->r * sizeof(*P)); + Q = flint_malloc(M->c * sizeof(*Q)); + nmod_sparse_mat_init(L, M->r, M->c, M->mod); + nmod_sparse_mat_init(U, M->r, M->c, M->mod); + rk = nmod_sparse_mat_lu(P, Q, L, U, M); flint_free(P); nmod_sparse_mat_clear(L); for(i=0; irows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, A->mod), A->mod); - nmod_mat_init(X, A->c, A->c-rk, A->mod.n); - if (rk != A->c) + nmod_sparse_vec_scalar_mul(&U->rows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, M->mod), M->mod); + nmod_mat_init(X, M->c, M->c-rk, M->mod.n); + if (rk != M->c) { /* Invert permutation */ - Qi = flint_malloc(A->c * sizeof(*Qi)); - for (i = 0; i < A->c; ++i) Qi[Q[i]] = i; + Qi = flint_malloc(M->c * sizeof(*Qi)); + for (i = 0; i < M->c; ++i) Qi[Q[i]] = i; - /* Assign unit vectors to non-pivot columns */ - for (i = A->c-1; i >= rk; --i) X->rows[Qi[i]][i-rk] = 1; + /* Mssign unit vectors to non-pivot columns */ + for (i = M->c-1; i >= rk; --i) X->rows[Qi[i]][i-rk] = 1; for (i = rk-1; i >= 0; --i) { Urow = &U->rows[i]; Xrow = X->rows[Qi[i]]; for(j = 1; jnnz; ++j) { e = &Urow->entries[j]; /* Do in-place row elimination */ - if(e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, A->mod), A->mod); - else Xrow[e->ind-rk] = nmod_sub(Xrow[e->ind-rk], e->val, A->mod); + if(e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, M->mod), M->mod); + else Xrow[e->ind-rk] = nmod_sub(Xrow[e->ind-rk], e->val, M->mod); } } diff --git a/nmod_sparse_mat/nullspace_rref.c b/nmod_sparse_mat/nullspace_rref.c index 15bc97c3c8..c3d867e83f 100644 --- a/nmod_sparse_mat/nullspace_rref.c +++ b/nmod_sparse_mat/nullspace_rref.c @@ -16,25 +16,25 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A) +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M) { slong i, j, rk, numc, *Q; nmod_sparse_mat_t R; nmod_sparse_vec_struct *Rrow; mp_limb_t *Xrow; nmod_sparse_entry_struct *le, *e; - nmod_sparse_mat_init(R, A->r, A->c, A->mod); - nmod_sparse_mat_set(R, A); + nmod_sparse_mat_init(R, M->r, M->c, M->mod); + nmod_sparse_mat_set(R, M); rk = nmod_sparse_mat_rref(R); - nmod_mat_init(X, A->c, A->c-rk, A->mod.n); - if(rk != A->c) + nmod_mat_init(X, M->c, M->c-rk, M->mod.n); + if(rk != M->c) { numc = 0; /* Mark which cols are pivots and enumerate the nonpivots */ - Q = flint_calloc(A->c, sizeof(*Q)); + Q = flint_calloc(M->c, sizeof(*Q)); for (i = 0; i < rk; ++i) Q[R->rows[i].entries->ind] = -1; - for (i = 0; i < A->c; ++i) + for (i = 0; i < M->c; ++i) if(Q[i]==UWORD(0)) Q[i] = numc++, X->rows[i][Q[i]] = 1; /* For each pivot col, set the corresponding row in X as */ @@ -44,7 +44,7 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A) Rrow = &R->rows[i]; Xrow = X->rows[Rrow->entries[0].ind]; for (j = 1; j < Rrow->nnz; ++j) - Xrow[Q[Rrow->entries[j].ind]] = nmod_neg(Rrow->entries[j].val, A->mod); + Xrow[Q[Rrow->entries[j].ind]] = nmod_neg(Rrow->entries[j].val, M->mod); } flint_free(Q); } diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c index 33056affba..4f8497bfc7 100644 --- a/nmod_sparse_mat/nullspace_wiedemann.c +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -16,33 +16,33 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters) +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { - /* Generate random solutions to a random system Ax=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; - x = _nmod_vec_init(A->c); + x = _nmod_vec_init(M->c); nxs = 0; xs = NULL; xps = NULL; for(iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_wiedemann(x, A, state) == 0) {++iter; continue;} + if(nmod_sparse_mat_nullvector_wiedemann(x, M, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ for (j = nxs-1; j >= 0; --j) { - _nmod_vec_scalar_addmul_nmod(x, xs[j], A->c, nmod_neg(x[xps[j]], A->mod), A->mod); + _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } /* Normalize last nonzero entry to 1 */ - for (i = A->c-1; i >= 0 && x[i] == UWORD(0); --i); + for (i = M->c-1; i >= 0 && x[i] == UWORD(0); --i); if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ - _nmod_vec_scalar_mul_nmod(x, x, A->c, nmod_inv(x[i], A->mod), A->mod); + _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ for (j = 0; j < nxs; ++j) { - _nmod_vec_scalar_addmul_nmod(xs[j], x, A->c, nmod_neg(xs[j][i], A->mod), A->mod); + _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } /* Insert into list of vectors in nullspace (ordered by pivot) */ @@ -54,15 +54,15 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t xps[j] = i; xs[j] = x; nxs += 1; - x = _nmod_vec_init(A->c); /* New vector for next iteration */ + x = _nmod_vec_init(M->c); /* New vector for next iteration */ iter = 0; } flint_free(xps); flint_free(x); - nmod_mat_init(X, A->c, nxs, A->mod.n); + nmod_mat_init(X, M->c, nxs, M->mod.n); for (i = 0; i < nxs; ++i) { - for (j = 0; j < A->c; ++j) + for (j = 0; j < M->c; ++j) X->rows[j][i] = xs[i][j]; flint_free(xs[i]); } diff --git a/nmod_sparse_mat/print_pretty.c b/nmod_sparse_mat/print_pretty.c index 8cb51e9806..70cbb98ad6 100644 --- a/nmod_sparse_mat/print_pretty.c +++ b/nmod_sparse_mat/print_pretty.c @@ -17,19 +17,19 @@ #include "ulong_extras.h" void -nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t mat) +nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t M) { slong i;; char row_fmt[FLINT_BITS + 5]; - flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(mat->r, 10)); + flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(M->r, 10)); flint_printf("<%wd x %wd sparse integer matrix mod %w>\n", - mat->r, mat->c, mat->mod.n); + M->r, M->c, M->mod.n); - for (i = 0; i < mat->r; i++) + for (i = 0; i < M->r; i++) { flint_printf(row_fmt, i); - nmod_sparse_vec_print_pretty(&mat->rows[i], mat->c_off, mat->c, mat->mod); + nmod_sparse_vec_print_pretty(&M->rows[i], M->c_off, M->c, M->mod); } } diff --git a/nmod_sparse_mat/randtest.c b/nmod_sparse_mat/randtest.c index 69fe3190c0..afbbd2275a 100644 --- a/nmod_sparse_mat/randtest.c +++ b/nmod_sparse_mat/randtest.c @@ -15,14 +15,14 @@ #include "nmod_sparse_mat.h" void -nmod_sparse_mat_randtest(nmod_sparse_mat_t mat, flint_rand_t state, slong min_nnz, slong max_nnz) +nmod_sparse_mat_randtest(nmod_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz) { slong i, nnz; - for (i = 0; i < mat->r; ++i) + for (i = 0; i < M->r; ++i) { nnz = n_randint(state, max_nnz+1); nnz = FLINT_MAX(nnz, min_nnz); - nmod_sparse_vec_randtest(&mat->rows[i], state, nnz, mat->c, mat->mod); + nmod_sparse_vec_randtest(&M->rows[i], state, nnz, M->c, M->mod); } } diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index ec6a98923b..d30219554d 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -16,72 +16,72 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -slong nmod_sparse_mat_rref(nmod_sparse_mat_t A) +slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) { - if (A->r == 0 || A->c == 0) return 0; + if (M->r == 0 || M->c == 0) return 0; slong *P; slong i, j, r, c, pr, pc, rank, remr; - nmod_sparse_mat_t At; + nmod_sparse_mat_t Mt; nmod_sparse_vec_struct *pcol, *prow, *row, *col; mp_limb_t cinv, cc; - nmod_sparse_mat_init(At, A->c, A->r, A->mod); - nmod_sparse_mat_transpose(At, A); + nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); + nmod_sparse_mat_transpose(Mt, M); /* Set up permutations */ - P = flint_malloc(A->r*sizeof(*P)); - remr = A->r; - for (r = 0; rr; ++r) + P = flint_malloc(M->r*sizeof(*P)); + remr = M->r; + for (r = 0; rr; ++r) { - if (!A->rows[r].nnz || A->rows[r].entries[0].ind >= A->c) P[r] = --remr; + if (!M->rows[r].nnz || M->rows[r].entries[0].ind >= M->c) P[r] = --remr; else P[r] = -1; } /* Run elimination */ rank = 0; - for (pc=0; pcc; ++pc) + for (pc=0; pcc; ++pc) { - pcol = &At->rows[pc]; + pcol = &Mt->rows[pc]; /* Get lowest weight incident row not used as previous pivot */ pr = -1, prow = NULL; for (j = 0; j < pcol->nnz; ++j) { - r = pcol->entries[j].ind, row = &A->rows[r]; + r = pcol->entries[j].ind, row = &M->rows[r]; if (P[r] >= 0) continue; if (pr==-1 || (row->nnz < prow->nnz)) pr = r, prow = row; } if(pr == -1) continue; P[pr] = rank; - cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), A->mod); - nmod_sparse_vec_scalar_mul(prow, prow, cinv, A->mod); + cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), M->mod); + nmod_sparse_vec_scalar_mul(prow, prow, cinv, M->mod); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) { - r = pcol->entries[j].ind, row = &A->rows[r]; + r = pcol->entries[j].ind, row = &M->rows[r]; if(r==pr) {pcol->entries[j].val = UWORD(0); continue;} - cc = nmod_neg(nmod_sparse_vec_at(row, pc), A->mod); - nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); - if (row->nnz == 0 || row->entries[0].ind >= A->c) P[r] = --remr; + cc = nmod_neg(nmod_sparse_vec_at(row, pc), M->mod); + nmod_sparse_vec_scalar_addmul(row, row, prow, cc, M->mod); + if (row->nnz == 0 || row->entries[0].ind >= M->c) P[r] = --remr; } /* Gaussian eliminate cols */ - nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, A->mod); + nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, M->mod); for (j = 0; j < prow->nnz; ++j) { - c = prow->entries[j].ind, col = &At->rows[c]; - if(c >= A->c || c==pc) continue; - cc = nmod_neg(nmod_sparse_vec_at(col, pr), A->mod); - nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); + c = prow->entries[j].ind, col = &Mt->rows[c]; + if(c >= M->c || c==pc) continue; + cc = nmod_neg(nmod_sparse_vec_at(col, pr), M->mod); + nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, M->mod); } rank += 1; } - nmod_sparse_mat_clear(At); + nmod_sparse_mat_clear(Mt); /* Reorder rows */ - nmod_sparse_mat_permute_rows(A, P); + nmod_sparse_mat_permute_rows(M, P); flint_free(P); return rank; } diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c new file mode 100644 index 0000000000..40ac9ff0da --- /dev/null +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -0,0 +1,239 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for + Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 + + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Run row Gaussian elimination on first b block of [T I], save that, */ +/* if no pivot is found for a given column c, we Gaussian eliminate */ +/* the column c + b and zero out the row c. In addition, we reorder */ +/* columns so that ones corresponding to zero entries in S go first. */ +/* See Figure 1 in the above reference for details. */ +static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { + + const slong b = Torig->r; + slong pc, i, j, rk = 0; + nmod_mat_t T; + nmod_mat_struct *X; + slong *P; + mp_limb_t cc; + + P = flint_malloc(b * sizeof(*P)); + nmod_mat_init(T, b, b, Torig->mod.n); + nmod_mat_set(T, Torig); + nmod_mat_one(nWi); + + /* Set permutation to have previously dependent vectors at front */ + P = flint_malloc(b*sizeof(*P)); + for (i = j = 0; i < b; ++i) if(!S[i]) P[j++] = i; + for (i = j = 0; i < b; ++i) if(S[i]) P[j++] = i; + + for (j = 0; j < b; ++j) + { + pc = P[j]; /* Pivot col */ + + /* Find viable pivot row (from T if possible, then from W) */ + for (X = T, i = b; i == b; X = nWi) + for (i = j; i < b && X->rows[P[i]][pc] == 0; ++i); + S[pc] = X == T; /* Viable column in V */ + nmod_mat_swap_rows(T, NULL, pc, P[i]); + nmod_mat_swap_rows(nWi, NULL, pc, P[i]); /* Now pivot row = pivot col */ + + /* Make pivot one */ + cc = nmod_inv(X->rows[pc][pc], T->mod); + _nmod_vec_scalar_mul_nmod(T->rows[pc], T->rows[pc], b, cc, T->mod); + _nmod_vec_scalar_mul_nmod(nWi->rows[pc], nWi->rows[pc], b, cc, T->mod); + + /* Kill all other entries in pivot column */ + for(i = 0; i < b; ++i) + { + cc = nmod_neg(X->rows[P[i]][pc], T->mod); + if (i == j || cc == 0) continue; + _nmod_vec_scalar_addmul_nmod(T->rows[P[i]], T->rows[pc], T->c, cc, T->mod); + _nmod_vec_scalar_addmul_nmod(nWi->rows[P[i]], nWi->rows[pc], nWi->c, cc, T->mod); + } + if (S[pc]) rk++; /* Count viable columns */ + else + { + /* Kill row of both matrices */ + _nmod_vec_zero(T->rows[pc], b); + _nmod_vec_zero(nWi->rows[pc], b); + } + } + nmod_mat_neg(nWi, nWi); + nmod_mat_clear(T); + + return rk; +} + +static void kill_columns(nmod_mat_t M, int *good) +{ + slong r, c; + for (c = 0; c < M->c; ++c) + if(good[c] == 0) + for (r = 0; r < M->r; ++r) + M->rows[r][c] = UWORD(0); +} + +int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) { + int ret = 0; + slong i, j, prev_i, next_i, iter, cur_dim, total_dim = 0; + nmod_sparse_mat_t Mt; /* Transpose of M, we work with A = MtM */ + nmod_mat_struct V[3]; /* Keep track of current vector and two previous ones */ + nmod_mat_t MV; /* Application of M to V */ + nmod_mat_t AV; /* Application of Mt to MV */ + int *SSt; /* S is the maximal projection s.t. (VS)^tAVS is invertible, so SSt kills the dropped columns */ + nmod_mat_t nWi[3]; /* -S((VS)^tAVS)^-1S^t */ + nmod_mat_t VSSt; /* V with invalid vectors zeroed out */ + nmod_mat_t T; /* Used to store transposes for inner products */ + nmod_mat_t VtAV; /* Inner product _A */ + nmod_mat_t AVtAVSSt_VtAV; /* Sum _A SS^t + _A, shared by two updates */ + nmod_mat_t DEF; /* Used to store coefficient matrices D, E, and F */ + nmod_mat_t I; /* I_{b x b} */ + mp_ptr SStVtb, WiSStVtb, VSStWiSStVtb; /* Intermediate elements in x update */ + + nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); + for (i = 0; i < 3; ++i) nmod_mat_init(&V[i], M->c, block_size, M->mod.n); + nmod_mat_init(MV, M->r, block_size, M->mod.n); /* Intermediate product */ + nmod_mat_init(AV, M->c, block_size, M->mod.n); /* Symmetric product */ + SSt = flint_malloc(block_size*sizeof(*SSt)); + for (i = 0; i < 2; ++i) nmod_mat_init(nWi[i], block_size, block_size, M->mod.n); + nmod_mat_init(T, block_size, M->c, M->mod.n); /* Transpose for computing matrix dot products */ + nmod_mat_init(VtAV, block_size, block_size, M->mod.n); + nmod_mat_init(AVtAVSSt_VtAV, block_size, block_size, M->mod.n); // (AV)^T(AV) + VtAV + nmod_mat_init(DEF, block_size, block_size, M->mod.n); // Shared by D, E, and F + nmod_mat_init(I, block_size, block_size, M->mod.n); + SStVtb = _nmod_vec_init(block_size); + WiSStVtb = _nmod_vec_init(block_size); + VSStWiSStVtb = _nmod_vec_init(M->c); + + _nmod_vec_zero(x, M->c); + nmod_sparse_mat_transpose(Mt, M); + for (i = 0; i < block_size; ++i) SSt[i] = 1; + nmod_mat_one(I); + + // Initialize V[0] randomly + for (i = 0; i < V[0].r*V[0].c; ++i) + V[0].entries[i] = n_randint(state, V[0].mod.n); + + for(iter = 0; ; ++iter) + { + i = iter % 3; + next_i = (iter + 1) % 3; + prev_i = (iter + 2) % 3; + if(iter>=2) + { + /* Compute the F value for this round (minus the final term) */ + nmod_mat_addmul(DEF, I, VtAV, nWi[prev_i]); + nmod_mat_mul(nWi[i], nWi[next_i], DEF); /* nWi[i] used for scratch */ + nmod_mat_mul(DEF, nWi[i], AVtAVSSt_VtAV); + } + + /* Compute AV and V'AV */ + nmod_sparse_mat_mul_mat(MV, M, &V[i]); + nmod_sparse_mat_mul_mat(AV, Mt, MV); + nmod_mat_transpose(T, &V[i]); + nmod_mat_mul(VtAV, T, AV); + + /* Compute W^{-1} and indices of bad vectors */ + cur_dim = compute_nWi_S(nWi[i], SSt, VtAV); + total_dim += cur_dim; + if (cur_dim == 0 || total_dim > M->c) break; /* Ran out of vectors */ + + /* Update x_i = x_{i-1} - (VSS^t) W^{-1} (VSS^t)^tb */ + nmod_mat_set(VSSt, &V[i]); + kill_columns(VSSt, SSt); + nmod_mat_transpose(T, VSSt); + nmod_mat_mul_vec(SStVtb, T, b); + nmod_mat_mul_vec(WiSStVtb, nWi[i], SStVtb); + nmod_mat_mul_vec(VSStWiSStVtb, VSSt, WiSStVtb); + _nmod_vec_add(x, x, VSStWiSStVtb, M->c, M->mod); + + /** + * Per Equation (19), we compute the next vector + * V_{i+1} = AV_iS_iS_i^t + V_i D + V_{i-1} E + V_{i-2} F + * where + * D = I - W_i^-1((AV_i)^tAV_iS_iS_i^t + V_i^tAV_i) + * E = -W_{i-1}^-1V_i^tAV_iS_iS_i^t + * F = -W_{i-2}^-1(I - V_{i-1}^tAV_{i-1}W_{i-1}^-1) + * ((AV_{i-1})^tAV_{i-1}S_{i-1}S_{i-1}^t + V_{i-1}^tAV_{i-1})S_iS_i^t + **/ + if(iter >= 2) + { + /* V_{i+1} = V_{i-2} F */ + kill_columns(DEF, SSt); + nmod_mat_mul(&V[next_i], &V[next_i], DEF); + } + if(iter >= 1) + { + /* V_{i+1} += V_{i-1} E */ + nmod_mat_mul(DEF, nWi[prev_i], VtAV); + kill_columns(DEF, SSt); + nmod_mat_addmul(&V[next_i], &V[next_i], &V[prev_i], DEF); + } + /* V_{i+1} += V_i D */ + nmod_mat_transpose(T, AV); + nmod_mat_mul(AVtAVSSt_VtAV, T, AV); + kill_columns(AVtAVSSt_VtAV, SSt); + nmod_mat_add(AVtAVSSt_VtAV, AVtAVSSt_VtAV, VtAV); + nmod_mat_addmul(DEF, I, nWi[i], AVtAVSSt_VtAV); + nmod_mat_addmul(&V[next_i], &V[next_i], &V[i], DEF); + + /* V_{i+1} += AVSS^t */ + kill_columns(AV, SSt); + nmod_mat_add(&V[next_i], &V[next_i], AV); + + if(nmod_mat_is_zero(&V[i])) {ret = 1; break;} + } + nmod_sparse_mat_clear(Mt); + for (i = 0; i < 3; ++i) nmod_mat_clear(&V[i]); + nmod_mat_clear(MV); + nmod_mat_clear(AV); + flint_free(SSt); + for (i = 0; i < 2; ++i) nmod_mat_clear(nWi[i]); + nmod_mat_clear(T); + nmod_mat_clear(VtAV); + nmod_mat_clear(AVtAVSSt_VtAV); + nmod_mat_clear(DEF); + nmod_mat_clear(I); + _nmod_vec_clear(SStVtb); + _nmod_vec_clear(WiSStVtb); + _nmod_vec_clear(VSStWiSStVtb); + return ret; +} + +int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) { + int ret = 1; + mp_ptr x2, b; + x2 = _nmod_vec_init(M->c); + b = _nmod_vec_init(M->r); + + _nmod_vec_randtest(x, state, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + if(nmod_sparse_mat_solve_block_lanczos(x2, M, b, block_size, state) == 0) ret = 0; /* Lanczos failed */ + if (ret) + { + _nmod_vec_sub(x, x, x2, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + ret = _nmod_vec_is_zero(x, M->c) || !_nmod_vec_is_zero(b, M->r); + } + _nmod_vec_clear(x2); + _nmod_vec_clear(b); + return ret; +} \ No newline at end of file diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c new file mode 100644 index 0000000000..d2c6e8a331 --- /dev/null +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -0,0 +1,247 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Compute S_i=(M^j Y)_{0...b-1}^T for i=0,...,ns-1 */ +static void make_block_sequences(nmod_mat_struct *S, slong ns, const nmod_sparse_mat_t M, nmod_mat_struct Y[2]) +{ + slong iter, i, j, k, b = Y->c; + nmod_mat_struct W[2]; + for (i = 0; i < 2; ++i) nmod_mat_window_init(&W[i], Y, 0, 0, b, b); + for (i = iter = 0; iter < ns; ++iter, i = 1-i) + { + if (i > 0) nmod_sparse_mat_mul_mat(&Y[i], M, &Y[1-i]); + nmod_mat_transpose(&S[iter], &W[i]); + } + for (i = 0; i < 2; ++i) nmod_mat_window_clear(&W[i]); +} + +/** + * Run Guassian elimination on the first b columns of the augmented + * matrix M = [ D | I], yielding a final matrix + * [ | ] [ Z | ] + * [ D | I ] -> [---| tau ] + * [ | ] [ L | ] + * where the the number of nonzero rows in Z is the ith rank. We choose + * the pivot row for a given column to be the one with minimal degree. +**/ +static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) +{ + const slong b = M->r/2; + slong pr, pc, r, c, k, tmp; + slong num_pi; + slong *gamma; + mp_limb_t cinv, cc; + nmod_mat_t tau; + + /* Keep track of viable rows */ + gamma = flint_malloc(b*sizeof(*gamma)); + for (r = 0; r < b; ++r) gamma[r] = 1; + + for (pc = 0; pc < b; ++pc) + { + /* Set the pivot row to be the minimum degree row incident on column pc */ + pr = b + pc; + for (r = 0; r < b; r++) + if(gamma[r] && M->rows[r][pc] && d[r] < d[pr]) pr = r; + + /* Try to move pivot row to appropriate position (if not already there) */ + if (pr != b + pc) + { + tmp = d[pr]; d[pr] = d[b+pc]; d[b+pc] = tmp; + + if (M->rows[b + pc][pr]) + nmod_mat_swap_rows(M, NULL, pr, b + pc), pr = b + pc; + else /* Need to make new auxiliary vector and remove r from use */ + _nmod_vec_add(M->rows[b + pc], M->rows[b + pc], M->rows[pr], 3*b, M->mod), gamma[pr] = 0; + } + cinv = nmod_inv(M->rows[pr][pc], M->mod); + + /* Do Gaussian elimination on first b rows */ + for (r = 0; r < b; ++k) + if(gamma[r] && M->rows[r][pc]) + _nmod_vec_scalar_addmul_nmod(M->rows[r], M->rows[pr], M->c, + nmod_neg(nmod_mul(M->rows[r][pc], cinv, M->mod), M->mod), M->mod); + } + flint_free(gamma); +} + +/* Stop with failure if sum(d_0 ... d_{b-1}) < delta */ +/* Stop with success if sum(d_0 ... d_{b-1}) < delta + max(d_0 ... d_{b-1}) - min(d_b ... d_{2b-1}) */ +static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) +{ + slong tmp, r; + + /* Sum degrees of generating polynomials */ + tmp = d[0]; for (r = 1; r < b; ++r) tmp += d[r]; + delta -= tmp; + if (delta < 0) return 0; /* Insufficient degree */ + + /* Add maximum degree of first b polys and subtract minimum degree of last b */ + tmp = d[0]; for (r = 1; r < b; ++r) if (d[r] > tmp) tmp = d[r]; + delta += tmp; + tmp = d[b]; for (r = b + 1; r < 2*b; ++r) if (d[r] < tmp) tmp = d[r]; + delta -= tmp; + return delta < 0 ? 1 : -1; +} + +/** + * Generalization of Berlekamp-Massey due to Coppersmith. + * Iteratively computes a sequence F representing 2b polynomials: + * - the first b are the current (reversed) generating polynomials + * - the last b are certain auxiliary polynomials. +**/ +static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n) +{ + int ret; + slong t, sigma, beta, mu; + slong i, j, k, r, b = S->r; + slong f_len; + nmod_mat_struct *F; + nmod_mat_t M, D, tau; + + f_len = 1; + F = flint_malloc(n*sizeof(*F)); + nmod_mat_init(&F[0], 2*b, b, S->mod.n); + for (i = 0; i < b; ++i) d[i] = 0, d[b + i] = 1, F[0].rows[i][i] = 1; + + /* [ D | I ] -> [ ? | tau ]*/ + nmod_mat_init(M, 2*b, 3*b, S->mod.n); + + for (t = 0; (ret = coppersmith_stopping_criterion(d, n, b)) == -1; ++t) + { + /* Compute discrepancy matrix and tau */ + nmod_mat_window_init(D, M, 0, 0, 2*b, b); + nmod_mat_window_init(tau, M, 0, b, 2*b, 3*b); + nmod_mat_zero(D); + for(k = 0; k <= t; ++k) nmod_mat_addmul(D, D, &F[k], &S[t-k]); + nmod_mat_one(tau); + nmod_mat_window_clear(D); + nmod_mat_window_clear(tau); + coppersmith_aux_gauss(M, d); + + /* Multiply F by tau * diag(I xI) */ + nmod_mat_window_init(tau, M, 0, b, 2*b, 3*b); /* Needed since gauss reorders rows */ + nmod_mat_init(&F[f_len++], 2*b, b, S->mod.n); + for (k = f_len-1; k > 0; --k) + nmod_mat_mul(&F[k], tau, &F[k-1]); /* Every row multiplied by x */ + for (k = 0; k < f_len; ++k) + for(r = 0; r < b; ++r) /* Divide first b rows by x */ + (k < f_len - 1) ? _nmod_vec_set(F[k].rows[r], F[k+1].rows[r], b) : _nmod_vec_zero(F[k].rows[r], b); + for (r = b; r < 2*b; ++r) d[r] += 1; + nmod_mat_window_clear(tau); + } + + /* Copy C to S, with each row reversed according to its degree */ + for(r = 0; r < b; ++r) + for(k = 0; k <= d[r]; k++) + _nmod_vec_set(S[d[r] - k].rows[r], F[k].rows[r], b); + + for(k = 0; k < f_len; ++k) nmod_mat_clear(&F[i]); + nmod_mat_clear(M); + flint_free(F); + flint_free(d); + return ret; +} + +static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, const nmod_sparse_mat_t M, nmod_mat_struct Z[2], slong l) +{ + slong i, iter, k, nu, b = S->r; + slong *dd; + mp_ptr v, xi; + + /* Compute differences between nominal and real degrees of each coordinate polynomial in row l */ + dd = flint_malloc(b*sizeof(*dd)); + for (nu = 0; nu < b; nu++); + for (dd[nu] = 0; dd[nu] <= d[l]; ++dd[nu]) + if(S[dd[nu]].rows[l][nu]) break; + + /* Simulaneously apply all polynomials in row l to iteration of M on Z */ + v = _nmod_vec_init(b); + xi = _nmod_vec_init(M->c); + _nmod_vec_zero(x, M->r); + for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) + { + if(iter > 0) nmod_sparse_mat_mul_mat(&Z[i], M, &Z[1-i]); + for(nu = 0; nu < b; nu++) + v[nu] = (dd[nu] <= d[l]) ? S[dd[nu]++].rows[l][nu] : UWORD(0); + nmod_sparse_mat_mul_vec(xi, M, v); + _nmod_vec_add(x, x, xi, M->c, M->mod); + } + _nmod_vec_clear(v); + _nmod_vec_clear(xi); + flint_free(dd); +} + +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state) +{ + int good = 0; + slong i; + mp_ptr x1; + nmod_sparse_vec_t z; + nmod_sparse_mat_t Mb; + nmod_sparse_vec_struct *row; + nmod_sparse_entry_struct *le, *re; + if (M->r != M->c) return 0; /* TODO */ + + /* TODO: Precondition M */ + x1 = _nmod_vec_init(M->c + 1); + nmod_sparse_vec_init(z); + nmod_sparse_mat_init(Mb, M->r, M->c, M->mod); + nmod_sparse_mat_set(Mb, M); + nmod_sparse_mat_append_col(Mb, b); + nmod_sparse_mat_append_row(Mb, z); + nmod_sparse_mat_nullvector_block_wiedemann(x1, Mb, block_size, state); + nmod_sparse_vec_clear(z); + nmod_sparse_mat_clear(Mb); + + if(x1[M->c]) + memcpy(x, x1, M->c*sizeof(*x)), good = 1; + _nmod_vec_clear(x1); + return good; +} + +int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) +{ + int ret = 0; + slong l, ns; + slong *d; + mp_ptr b; + nmod_mat_t Z; + nmod_mat_struct Y[3], *S; + if (M->r != M->c) return 0; /* TODO */ + + ns = 2*M->r/block_size + 3; /* Maybe 5? */ + d = flint_calloc(2*block_size, sizeof(*d)); + b = _nmod_vec_init(M->r); + for (l = 0; l < 3; ++l) + nmod_mat_init(&Y[l], M->c, block_size, M->mod.n); + nmod_mat_randtest(&Y[0], state); + nmod_sparse_mat_mul_mat(&Y[1], M, &Y[0]); + make_block_sequences(S, ns, M, &Y[1]); + find_block_min_poly(S, d, ns); + + for (l = 0; l < block_size; ++l) + { + nmod_mat_set(&Y[1], &Y[0]); + make_block_sum(x, S, d, M, Y + 1, l); + nmod_sparse_mat_mul_vec(b, M, x); + if (_nmod_vec_is_zero(b, M->r)) {ret = 1; break;}; + } + return ret; +} + + diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 6f5df306a0..09205525e9 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -16,86 +16,87 @@ #include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b, flint_rand_t state) +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state) { slong j, ret; - const slong nlimbs = _nmod_vec_dot_bound_limbs(A->c, A->mod); - nmod_sparse_mat_t At; - mp_ptr w[2], Aw, AtAw, Atb; - mp_limb_t delta[2]; + const slong nlimbs = _nmod_vec_dot_bound_limbs(M->c, M->mod); - _nmod_vec_zero(x, A->c); + /* We assume that M is not symmetric, and work with A = M^t M */ + nmod_sparse_mat_t Mt; + mp_ptr v[2], Mv, Av, Mtb; + mp_limb_t vtAv[2], AvtAv, vMtb, alpha, beta; + + _nmod_vec_zero(x, M->c); /* Construct transpose */ - nmod_sparse_mat_init(At, A->c, A->r, A->mod); - nmod_sparse_mat_transpose(At, A); + nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); + nmod_sparse_mat_transpose(Mt, M); /* Construct auxiliary vectors */ - /* Rather than storing the whole sequence of values w_j, we alternate between two vectors */ - w[0] = _nmod_vec_init(A->c); - w[1] = _nmod_vec_init(A->c); - Aw = _nmod_vec_init(A->r); - AtAw = _nmod_vec_init(A->c); - Atb = _nmod_vec_init(A->c); - nmod_sparse_mat_mul_vec(Atb, At, b); + /* Rather than storing the whole sequence of values v_j, we alternate between two vectors */ + v[0] = _nmod_vec_init(M->c); + v[1] = _nmod_vec_init(M->c); + Mv = _nmod_vec_init(M->r); + Av = _nmod_vec_init(M->c); + Mtb = _nmod_vec_init(M->c); + nmod_sparse_mat_mul_vec(Mtb, Mt, b); /* Make 0th vector random (and -1st vector trivial) */ - //_nmod_vec_set(w[0], Atb, A->c); - //for(j = 0; j < A->c; ++j) w[0][j] = n_randint(state, A->mod.n); - _nmod_vec_randtest(w[0], state, A->c, A->mod); - _nmod_vec_zero(w[1], A->c); delta[1] = 1; + //_nmod_vec_set(v[0], Mtb, M->c); + //for(j = 0; j < M->c; ++j) v[0][j] = n_randint(state, M->mod.n); + _nmod_vec_randtest(v[0], state, M->c, M->mod); + _nmod_vec_zero(v[1], M->c); vtAv[1] = 1; for (j = 0; ; j = 1-j) { - /* Compute A^T A w_j and check if it is orthogonal to w_j */ - nmod_sparse_mat_mul_vec(Aw, A, w[j]); - nmod_sparse_mat_mul_vec(AtAw, At, Aw); - delta[j] = _nmod_vec_dot(w[j], AtAw, A->c, A->mod, nlimbs); - if (delta[j] == UWORD(0)) break; /* Can't make any more progress */ + /* Compute M^T M v_j and check if it is orthogonal to v_j */ + nmod_sparse_mat_mul_vec(Mv, M, v[j]); + nmod_sparse_mat_mul_vec(Av, Mt, Mv); + vtAv[j] = _nmod_vec_dot(v[j], Av, M->c, M->mod, nlimbs); + if (vtAv[j] == UWORD(0)) break; /* Can't make any more progress */ - /* Update putative solution by /delta_j * w_j */ - const mp_limb_t wAtb = nmod_div(_nmod_vec_dot(w[j], Atb, A->c, A->mod, nlimbs), delta[j], A->mod); - _nmod_vec_scalar_addmul_nmod(x, w[j], A->c, wAtb, A->mod); + /* Update putative solution by /delta_j * v_j */ + vMtb = nmod_div(_nmod_vec_dot(v[j], Mtb, M->c, M->mod, nlimbs), vtAv[j], M->mod); + _nmod_vec_scalar_addmul_nmod(x, v[j], M->c, vMtb, M->mod); - /* w_{j+1} = AtAw - alpha*w_j - beta*w_{j-1}, where */ - /* alpha = /delta_j, and */ + /* v_{j+1} = MtMv - alpha*v_j - beta*v_{j-1}, where */ + /* alpha = /delta_j, and */ /* beta = delta_j/delta_{j-1} */ - const mp_limb_t alpha = nmod_div(_nmod_vec_dot(AtAw, AtAw, A->c, A->mod, nlimbs), delta[j], A->mod); - const mp_limb_t beta = nmod_div(delta[j], delta[1-j], A->mod); - _nmod_vec_scalar_mul_nmod(w[1-j], w[1-j], A->c, nmod_neg(beta, A->mod), A->mod); - _nmod_vec_scalar_addmul_nmod(w[1-j], w[j], A->c, nmod_neg(alpha, A->mod), A->mod); - _nmod_vec_add(w[1-j], w[1-j], AtAw, A->c, A->mod); + AvtAv = _nmod_vec_dot(Av, Av, M->c, M->mod, nlimbs); + _nmod_vec_scalar_mul_nmod(v[1-j], v[1-j], M->c, nmod_neg(nmod_div(vtAv[j], vtAv[1-j], M->mod), M->mod), M->mod); + _nmod_vec_scalar_addmul_nmod(v[1-j], v[j], M->c, nmod_neg(nmod_div(AvtAv, vtAv[j], M->mod), M->mod), M->mod); + _nmod_vec_add(v[1-j], v[1-j], Av, M->c, M->mod); } /* Check result */ - nmod_sparse_mat_mul_vec(Aw, A, x); - nmod_sparse_mat_mul_vec(AtAw, At, Aw); - ret = _nmod_vec_equal(AtAw, Atb, A->c); + nmod_sparse_mat_mul_vec(Mv, M, x); + nmod_sparse_mat_mul_vec(Av, Mt, Mv); + ret = _nmod_vec_equal(Av, Mtb, M->c); /* Clear auxiliary vectors and transpose */ - _nmod_vec_clear(w[0]); - _nmod_vec_clear(w[1]); - _nmod_vec_clear(Aw); - _nmod_vec_clear(AtAw); - _nmod_vec_clear(Atb); - nmod_sparse_mat_clear(At); + _nmod_vec_clear(v[0]); + _nmod_vec_clear(v[1]); + _nmod_vec_clear(Mv); + _nmod_vec_clear(Av); + _nmod_vec_clear(Mtb); + nmod_sparse_mat_clear(Mt); return ret; } -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) { +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) { int ret = 1; mp_ptr x2, b; - x2 = _nmod_vec_init(A->c); - b = _nmod_vec_init(A->r); + x2 = _nmod_vec_init(M->c); + b = _nmod_vec_init(M->r); - _nmod_vec_randtest(x, state, A->c, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); - if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) ret = 0; /* Lanczos failed */ + _nmod_vec_randtest(x, state, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + if(nmod_sparse_mat_solve_lanczos(x2, M, b, state) == 0) ret = 0; /* Lanczos failed */ if (ret) { - _nmod_vec_sub(x, x, x2, A->c, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); - ret = _nmod_vec_is_zero(x, A->c) || !_nmod_vec_is_zero(b, A->r); + _nmod_vec_sub(x, x, x2, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + ret = !_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(b, M->r); } _nmod_vec_clear(x2); _nmod_vec_clear(b); return ret; -} \ No newline at end of file +} diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 50cf4ca8ce..14e2417267 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -17,29 +17,29 @@ #include "nmod_sparse_mat.h" /* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x=Qx' */ -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) { int good = 1; slong rk, *P, *Q, i, j; nmod_sparse_mat_t L, U; mp_ptr bp, y, xp; - P = flint_malloc(A->r * sizeof(*P)); - Q = flint_malloc(A->c * sizeof(*Q)); - nmod_sparse_mat_init(L, A->r, A->c, A->mod); - nmod_sparse_mat_init(U, A->r, A->c, A->mod); - rk = nmod_sparse_mat_lu(P, Q, L, U, A); + P = flint_malloc(M->r * sizeof(*P)); + Q = flint_malloc(M->c * sizeof(*Q)); + nmod_sparse_mat_init(L, M->r, M->c, M->mod); + nmod_sparse_mat_init(U, M->r, M->c, M->mod); + rk = nmod_sparse_mat_lu(P, Q, L, U, M); L->c = U->r = rk; /* Solve Ly = b' = Pb */ - bp = flint_malloc(A->r * sizeof(*bp)); + bp = flint_malloc(M->r * sizeof(*bp)); y = flint_calloc(rk, sizeof(*y)); - for (i = 0; i < A->r; ++i) bp[P[i]] = b[i]; + for (i = 0; i < M->r; ++i) bp[P[i]] = b[i]; flint_free(P); for (i = 0; i < rk; ++i) - y[i] = nmod_sub(bp[i], nmod_sparse_vec_dot_dense(&L->rows[i], y, A->mod), A->mod); - for (i = rk; i < A->r; ++i) - if (bp[i] != nmod_sparse_vec_dot_dense(&L->rows[i], y, A->mod)) {good = 0; break;} + y[i] = nmod_sub(bp[i], nmod_sparse_vec_dot_dense(&L->rows[i], y, M->mod), M->mod); + for (i = rk; i < M->r; ++i) + if (bp[i] != nmod_sparse_vec_dot_dense(&L->rows[i], y, M->mod)) {good = 0; break;} nmod_sparse_mat_mul_vec(bp, L, y); flint_free(bp); @@ -48,17 +48,17 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b if (good) { /* Find a solution for Ux' = y */ - xp = flint_calloc(A->c, sizeof(*xp)); + xp = flint_calloc(M->c, sizeof(*xp)); for (i = rk-1; i >= 0; --i) - xp[i] = nmod_div(nmod_sub(y[i], nmod_sparse_vec_dot_dense(&U->rows[i], xp, A->mod), A->mod), U->rows[i].entries[0].val, A->mod); + xp[i] = nmod_div(nmod_sub(y[i], nmod_sparse_vec_dot_dense(&U->rows[i], xp, M->mod), M->mod), U->rows[i].entries[0].val, M->mod); nmod_sparse_mat_mul_vec(y, U, xp); - for(i = 0; i < A->c; ++i) x[i] = xp[Q[i]]; + for(i = 0; i < M->c; ++i) x[i] = xp[Q[i]]; flint_free(xp); } flint_free(Q); flint_free(y); - U->r = A->r; + U->r = M->r; nmod_sparse_mat_clear(U); return good; } diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c index 856fe9dace..9075fba35c 100644 --- a/nmod_sparse_mat/solve_rref.c +++ b/nmod_sparse_mat/solve_rref.c @@ -16,31 +16,31 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) { int good = 1; slong i; - nmod_sparse_mat_t AB; + nmod_sparse_mat_t Mb; nmod_sparse_vec_struct *row; nmod_sparse_entry_struct *le, *re; - nmod_sparse_mat_init(AB, A->r, A->c, A->mod); - nmod_sparse_mat_set(AB, A); - nmod_sparse_mat_append_col(AB, b); - AB->c = A->c; - nmod_sparse_mat_rref(AB); - AB->c = A->c+1; + nmod_sparse_mat_init(Mb, M->r, M->c, M->mod); + nmod_sparse_mat_set(Mb, M); + nmod_sparse_mat_append_col(Mb, b); + Mb->c = M->c; + nmod_sparse_mat_rref(Mb); + Mb->c = M->c+1; - memset(x, 0, A->c*sizeof(*x)); - for (i = 0; i < A->r; ++i) + memset(x, 0, M->c*sizeof(*x)); + for (i = 0; i < M->r; ++i) { - row = &AB->rows[i]; + row = &Mb->rows[i]; if (row->nnz == 0) continue; le = &row->entries[0]; re = &row->entries[row->nnz-1]; - /* If any row has leading col A->c, system is not solvable */ - if (le->ind==A->c) {good = 0; break;} + /* If any row has leading col M->c, system is not solvable */ + if (le->ind==M->c) {good = 0; break;} /* Otherwise, x[lc] = lagging value */ - if (re->ind==A->c) {x[le->ind] = re->val;} + if (re->ind==M->c) {x[le->ind] = re->val;} } - nmod_sparse_mat_clear(AB); + nmod_sparse_mat_clear(Mb); } From 69a9be7ab9d983f3645e2cbbc8f1a768866cfe76 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 7 Apr 2020 22:25:15 -0700 Subject: [PATCH 16/42] Fixed spacing --- fq_mat_templates/mul_vec.c | 2 +- fq_mat_templates/scalar_addmul.c | 2 +- fq_mat_templates/scalar_mul.c | 2 +- fq_mat_templates/scalar_submul.c | 2 +- fq_sparse_mat_templates/lu.c | 4 +-- fq_sparse_mat_templates/nullspace_lanczos.c | 10 +++--- fq_sparse_mat_templates/nullspace_lu.c | 10 +++--- fq_sparse_mat_templates/nullspace_rref.c | 4 +-- fq_sparse_mat_templates/nullspace_wiedemann.c | 10 +++--- fq_sparse_mat_templates/rref.c | 8 ++--- fq_sparse_mat_templates/solve_block_lanczos.c | 31 ++++++++++--------- .../solve_block_wiedemann.c | 24 +++++++------- fq_sparse_mat_templates/solve_lanczos.c | 7 +++-- fq_sparse_mat_templates/solve_lu.c | 4 +-- fq_sparse_mat_templates/solve_rref.c | 2 +- fq_sparse_mat_templates/solve_wiedemann.c | 14 ++++----- fq_sparse_mat_templates/test/t-inv.c | 4 +-- fq_sparse_mat_templates/test/t-lu.c | 22 ++++++------- fq_sparse_mat_templates/test/t-nullspace.c | 4 +-- fq_sparse_mat_templates/test/t-rref.c | 2 +- fq_sparse_mat_templates/test/t-solve.c | 6 ++-- fq_sparse_mat_templates/transpose.c | 4 +-- fq_sparse_vec_templates/add.c | 4 +-- fq_sparse_vec_templates/scalar_addmul.c | 4 +-- fq_sparse_vec_templates/sub.c | 4 +-- fq_sparse_vec_templates/test/t-init_clear.c | 2 +- nmod_mat/one.c | 2 +- nmod_sparse_mat.h | 12 +++---- nmod_sparse_mat/lu.c | 10 +++--- nmod_sparse_mat/nullspace_lanczos.c | 4 +-- nmod_sparse_mat/nullspace_lu.c | 4 +-- nmod_sparse_mat/nullspace_wiedemann.c | 4 +-- nmod_sparse_mat/rref.c | 4 +-- nmod_sparse_mat/solve_block_lanczos.c | 4 +-- nmod_sparse_mat/solve_block_wiedemann.c | 14 ++++----- nmod_sparse_mat/solve_lanczos.c | 2 +- nmod_sparse_mat/solve_lu.c | 4 +-- nmod_sparse_mat/solve_wiedemann.c | 12 +++---- nmod_sparse_mat/test/t-lu.c | 10 +++--- nmod_sparse_mat/test/t-solve.c | 6 ++-- nmod_sparse_vec/dot_dense.c | 2 +- nmod_sparse_vec/set.c | 2 +- nmod_sparse_vec/split.c | 4 +-- nmod_sparse_vec/window_init.c | 4 +-- 44 files changed, 153 insertions(+), 143 deletions(-) diff --git a/fq_mat_templates/mul_vec.c b/fq_mat_templates/mul_vec.c index bf67f08c7c..1bc400f9e2 100644 --- a/fq_mat_templates/mul_vec.c +++ b/fq_mat_templates/mul_vec.c @@ -19,7 +19,7 @@ TEMPLATE(T, mat_mul_vec) (TEMPLATE(T, struct) *y, const TEMPLATE(T, struct) *x, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i = 0; i < A->r; ++i) + for (i = 0; i < A->r; ++i) _TEMPLATE(T, vec_dot) (&y[i], A->rows[i], x, A->c, ctx); } diff --git a/fq_mat_templates/scalar_addmul.c b/fq_mat_templates/scalar_addmul.c index f8502a9f9a..d4b1b03e7b 100644 --- a/fq_mat_templates/scalar_addmul.c +++ b/fq_mat_templates/scalar_addmul.c @@ -22,7 +22,7 @@ TEMPLATE(T, mat_scalar_addmul) (TEMPLATE(T, mat_t) C, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i = 0; i < C->r; i++) + for (i = 0; i < C->r; i++) { _TEMPLATE(T, vec_set) (C->rows[i], A->rows[i], A->c, ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (C->rows[i], B->rows[i], A->c, c, ctx); diff --git a/fq_mat_templates/scalar_mul.c b/fq_mat_templates/scalar_mul.c index 37f35cb14b..a82d79899f 100644 --- a/fq_mat_templates/scalar_mul.c +++ b/fq_mat_templates/scalar_mul.c @@ -21,7 +21,7 @@ TEMPLATE(T, mat_scalar_mul) (TEMPLATE(T, mat_t) B, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i = 0; i < B->r; i++) + for (i = 0; i < B->r; i++) { _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (B->rows[i], A->rows[i], A->c, c, ctx); } diff --git a/fq_mat_templates/scalar_submul.c b/fq_mat_templates/scalar_submul.c index ac8acd02dd..86765edb3b 100644 --- a/fq_mat_templates/scalar_submul.c +++ b/fq_mat_templates/scalar_submul.c @@ -22,7 +22,7 @@ TEMPLATE(T, mat_scalar_submul) (TEMPLATE(T, mat_t) C, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i = 0; i < C->r; i++) + for (i = 0; i < C->r; i++) { _TEMPLATE(T, vec_set) (C->rows[i], A->rows[i], A->c, ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_submul, T)) (C->rows[i], B->rows[i], A->c, c, ctx); diff --git a/fq_sparse_mat_templates/lu.c b/fq_sparse_mat_templates/lu.c index 4ddb675e48..831c0dd940 100644 --- a/fq_sparse_mat_templates/lu.c +++ b/fq_sparse_mat_templates/lu.c @@ -51,8 +51,8 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s /* static void print_heap(slong *heap, slong *scores, slong size) { slong level, i; - for(level=1; level<=size; level<<=1) { - for(i=level; i<=size && i<2*level; ++i) { + for (level = 1; level <= size; level<<=1) { + for (i = level; i <= size && i < 2*level; ++i) { flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); } flint_printf("\n"); diff --git a/fq_sparse_mat_templates/nullspace_lanczos.c b/fq_sparse_mat_templates/nullspace_lanczos.c index a5e3097d8a..b39bec7d2f 100644 --- a/fq_sparse_mat_templates/nullspace_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_lanczos.c @@ -27,12 +27,13 @@ slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEM nxs = 0; xs = NULL; xps = NULL; - for(iter = 0; iter < max_iters; ) + for (iter = 0; iter < max_iters; ) { - if(TEMPLATE(T, sparse_mat_nullvector_lanczos) (x, M, state, ctx) == 0) {++iter; continue;} + if (TEMPLATE(T, sparse_mat_nullvector_lanczos) (x, M, state, ctx) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); } @@ -44,7 +45,8 @@ slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEM _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { TEMPLATE(T, neg) (cc, &xs[j][i], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); } diff --git a/fq_sparse_mat_templates/nullspace_lu.c b/fq_sparse_mat_templates/nullspace_lu.c index efba6d6ee9..50c3f53fd7 100644 --- a/fq_sparse_mat_templates/nullspace_lu.c +++ b/fq_sparse_mat_templates/nullspace_lu.c @@ -32,7 +32,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE rk = TEMPLATE(T, sparse_mat_lu) (P, Q, L, U, M, ctx); flint_free(P); TEMPLATE(T, sparse_mat_clear) (L, ctx); - for(i=0; irows[i].entries[0].val, ctx); TEMPLATE(T, sparse_vec_scalar_mul) (&U->rows[i], &U->rows[i], cc, ctx); @@ -46,14 +46,16 @@ slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE /* Mssign unit vectors to non-pivot columns */ for (i = M->c-1; i >= rk; --i) TEMPLATE(T, one) (&X->rows[Qi[i]][i-rk], ctx); - for (i = rk-1; i >= 0; --i) { + for (i = rk-1; i >= 0; --i) + { Urow = &U->rows[i]; Xrow = X->rows[Qi[i]]; - for(j = 1; jnnz; ++j) { + for (j = 1; j < Urow->nnz; ++j) + { e = &Urow->entries[j]; /* Do in-place row elimination */ TEMPLATE(T, neg) (cc, e->val, ctx); - if(e->ind < rk) _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (Xrow, X->rows[Qi[e->ind]], X->c, cc, ctx); + if (e->ind < rk) _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (Xrow, X->rows[Qi[e->ind]], X->c, cc, ctx); else TEMPLATE(T, sub) (&Xrow[e->ind-rk], &Xrow[e->ind-rk], e->val, ctx); } diff --git a/fq_sparse_mat_templates/nullspace_rref.c b/fq_sparse_mat_templates/nullspace_rref.c index 87306a306a..e2b926ffc3 100644 --- a/fq_sparse_mat_templates/nullspace_rref.c +++ b/fq_sparse_mat_templates/nullspace_rref.c @@ -25,7 +25,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLA TEMPLATE(T, sparse_mat_set) (R, M, ctx); rk = TEMPLATE(T, sparse_mat_rref) (R, ctx); TEMPLATE(T, mat_init) (X, M->c, M->c-rk, ctx); - if(rk != M->c) + if (rk != M->c) { numc = 0; /* Mark which cols are pivots and enumerate the nonpivots */ @@ -33,7 +33,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLA for (i = 0; i < rk; ++i) Q[R->rows[i].entries->ind] = -1; for (i = 0; i < M->c; ++i) - if(Q[i]==UWORD(0)) Q[i] = numc++, TEMPLATE(T, one) (&X->rows[i][Q[i]], ctx); + if (Q[i]==UWORD(0)) Q[i] = numc++, TEMPLATE(T, one) (&X->rows[i][Q[i]], ctx); /* For each pivot col, set the corresponding row in X as */ /* the negative of the associated row in R (reordered by Q) */ diff --git a/fq_sparse_mat_templates/nullspace_wiedemann.c b/fq_sparse_mat_templates/nullspace_wiedemann.c index 86930d3667..7a1b07367e 100644 --- a/fq_sparse_mat_templates/nullspace_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_wiedemann.c @@ -27,12 +27,13 @@ slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const T nxs = 0; xs = NULL; xps = NULL; - for(iter = 0; iter < max_iters; ) + for (iter = 0; iter < max_iters; ) { - if(TEMPLATE(T, sparse_mat_nullvector_wiedemann) (x, M, state, ctx) == 0) {++iter; continue;} + if (TEMPLATE(T, sparse_mat_nullvector_wiedemann) (x, M, state, ctx) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); } @@ -44,7 +45,8 @@ slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const T _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { TEMPLATE(T, neg) (cc, &xs[j][i], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); } diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c index 8acc1551b1..b61dfc426f 100644 --- a/fq_sparse_mat_templates/rref.c +++ b/fq_sparse_mat_templates/rref.c @@ -41,7 +41,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( /* Run elimination */ rank = 0; - for (pc=0; pcc; ++pc) + for (pc = 0; pcc; ++pc) { pcol = &Mt->rows[pc]; @@ -53,7 +53,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( if (P[r] >= 0) continue; if (pr==-1 || (row->nnz < prow->nnz)) pr = r, prow = row; } - if(pr == -1) continue; + if (pr == -1) continue; P[pr] = rank; TEMPLATE(T, inv) (cinv, *TEMPLATE(T, sparse_vec_at) (prow, pc, ctx), ctx); @@ -63,7 +63,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( for (j = 0; j < pcol->nnz; ++j) { r = pcol->entries[j].ind, row = &M->rows[r]; - if(r==pr) {TEMPLATE(T, zero) (pcol->entries[j].val, ctx); continue;} + if (r == pr) {TEMPLATE(T, zero) (pcol->entries[j].val, ctx); continue;} TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (row, pc, ctx), ctx); TEMPLATE(T, sparse_vec_scalar_addmul) (row, row, prow, cc, ctx); @@ -74,7 +74,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Mt->rows[c]; - if(c >= M->c || c==pc) continue; + if (c >= M->c || c == pc) continue; TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (col, pr, ctx), ctx); TEMPLATE(T, sparse_vec_scalar_addmul) (col, col, pcol, cc, ctx); } diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c index 246cea4ca4..67731e41c9 100644 --- a/fq_sparse_mat_templates/solve_block_lanczos.c +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -24,7 +24,8 @@ /* the column c + b and zero out the row c. In addition, we reorder */ /* columns so that ones corresponding to zero entries in S go first. */ /* See Figure 1 in the above reference for details. */ -static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t) Torig, const TEMPLATE(T, ctx_t) ctx) { +static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t) Torig, const TEMPLATE(T, ctx_t) ctx) +{ const slong b = Torig->r; slong pc, i, j, rk = 0; @@ -40,8 +41,8 @@ static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t /* Set permutation to have previously dependent vectors at front */ P = flint_malloc(b*sizeof(*P)); - for (i = j = 0; i < b; ++i) if(!S[i]) P[j++] = i; - for (i = j = 0; i < b; ++i) if(S[i]) P[j++] = i; + for (i = j = 0; i < b; ++i) if (!S[i]) P[j++] = i; + for (i = j = 0; i < b; ++i) if (S[i]) P[j++] = i; for (j = 0; j < b; ++j) { @@ -60,7 +61,7 @@ static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (nWi->rows[pc], nWi->rows[pc], b, cc, ctx); /* Kill all other entries in pivot column */ - for(i = 0; i < b; ++i) + for (i = 0; i < b; ++i) { TEMPLATE(T, neg) (cc, &X->rows[P[i]][pc], ctx); if (i == j || TEMPLATE(T, is_zero) (cc, ctx)) continue; @@ -85,12 +86,13 @@ static void kill_columns(TEMPLATE(T, mat_t) M, int *good, const TEMPLATE(T, ctx_ { slong r, c; for (c = 0; c < M->c; ++c) - if(good[c] == 0) + if (good[c] == 0) for (r = 0; r < M->r; ++r) TEMPLATE(T, zero) (&M->rows[r][c], ctx); } -int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { +int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ int ret = 0; slong i, j, prev_i, next_i, iter, cur_dim, total_dim = 0; TEMPLATE(T, sparse_mat_t) Mt; /* Transpose of M, we work with A = MtM */ @@ -106,7 +108,7 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, mat_t) DEF; /* Used to store coefficient matrices D, E, and F */ TEMPLATE(T, mat_t) I; /* I_{b x b} */ TEMPLATE(T, struct) *SStVtb, *WiSStVtb, *VSStWiSStVtb; /* Intermediate elements in x update */ - if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; @@ -136,12 +138,12 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T for (i = 0; i < V[0].r*V[0].c; ++i) TEMPLATE(T, randtest) (&V[0].entries[i], state, ctx); - for(iter = 0; ; ++iter) + for (iter = 0; ; ++iter) { i = iter % 3; next_i = (iter + 1) % 3; prev_i = (iter + 2) % 3; - if(iter>=2) + if (iter >= 2) { /* Compute the F value for this round (minus the final term) */ TEMPLATE(T, mat_addmul) (DEF, I, VtAV, nWi[prev_i], ctx); @@ -178,13 +180,13 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T * F = -W_{i-2}^-1(I - V_{i-1}^tAV_{i-1}W_{i-1}^-1) * ((AV_{i-1})^tAV_{i-1}S_{i-1}S_{i-1}^t + V_{i-1}^tAV_{i-1})S_iS_i^t **/ - if(iter >= 2) + if (iter >= 2) { /* V_{i+1} = V_{i-2} F */ kill_columns(DEF, SSt, ctx); TEMPLATE(T, mat_mul) (&V[next_i], &V[next_i], DEF, ctx); } - if(iter >= 1) + if (iter >= 1) { /* V_{i+1} += V_{i-1} E */ TEMPLATE(T, mat_mul) (DEF, nWi[prev_i], VtAV, ctx); @@ -203,7 +205,7 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T kill_columns(AV, SSt, ctx); TEMPLATE(T, mat_add) (&V[next_i], &V[next_i], AV, ctx); - if(TEMPLATE(T, mat_is_zero) (&V[i], ctx)) {ret = 1; break;} + if (TEMPLATE(T, mat_is_zero) (&V[i], ctx)) {ret = 1; break;} } TEMPLATE(T, sparse_mat_clear) (Mt, ctx); for (i = 0; i < 3; ++i) TEMPLATE(T, mat_clear) (&V[i], ctx); @@ -222,7 +224,8 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T return ret; } -int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { +int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ int ret = 1; TEMPLATE(T, struct) *x2, *b; x2 = _TEMPLATE(T, vec_init) (M->c, ctx); @@ -230,7 +233,7 @@ int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, co _TEMPLATE(T, vec_randtest) (x, state, M->c, ctx); TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); - if(TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, M, b, block_size, state, ctx) == 0) ret = 0; /* Lanczos failed */ + if (TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, M, b, block_size, state, ctx) == 0) ret = 0; /* Lanczos failed */ if (ret) { _TEMPLATE(T, vec_sub) (x, x, x2, M->c, ctx); diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c index e4c83b2211..c54de9abe0 100644 --- a/fq_sparse_mat_templates/solve_block_wiedemann.c +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -56,7 +56,7 @@ static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE /* Set the pivot row to be the minimum degree row incident on column pc */ pr = b + pc; for (r = 0; r < b; r++) - if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; + if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; /* Try to move pivot row to appropriate position (if not already there) */ if (pr != b + pc) @@ -72,7 +72,7 @@ static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE /* Do Gaussian elimination on first b rows */ for (r = 0; r < b; ++k) - if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) + if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) { TEMPLATE(T, mul) (cc, &M->rows[r][pc], cinv, ctx); TEMPLATE(T, neg) (cc, cc, ctx); @@ -132,7 +132,7 @@ static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, co TEMPLATE(T, mat_window_init) (D, M, 0, 0, 2*b, b, ctx); TEMPLATE(T, mat_window_init) (tau, M, 0, b, 2*b, 3*b, ctx); TEMPLATE(T, mat_zero) (D, ctx); - for(k = 0; k <= t; ++k) TEMPLATE(T, mat_addmul) (D, D, &F[k], &S[t-k], ctx); + for (k = 0; k <= t; ++k) TEMPLATE(T, mat_addmul) (D, D, &F[k], &S[t-k], ctx); TEMPLATE(T, mat_one) (tau, ctx); TEMPLATE(T, mat_window_clear) (D, ctx); TEMPLATE(T, mat_window_clear) (tau, ctx); @@ -144,18 +144,18 @@ static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, co for (k = f_len-1; k > 0; --k) TEMPLATE(T, mat_mul) (&F[k], tau, &F[k-1], ctx); /* Every row multiplied by x */ for (k = 0; k < f_len; ++k) - for(r = 0; r < b; ++r) /* Divide first b rows by x */ + for (r = 0; r < b; ++r) /* Divide first b rows by x */ (k < f_len - 1) ? _TEMPLATE(T, vec_set) (F[k].rows[r], F[k+1].rows[r], b, ctx) : _TEMPLATE(T, vec_zero) (F[k].rows[r], b, ctx); for (r = b; r < 2*b; ++r) d[r] += 1; TEMPLATE(T, mat_window_clear) (tau, ctx); } /* Copy C to S, with each row reversed according to its degree */ - for(r = 0; r < b; ++r) - for(k = 0; k <= d[r]; k++) + for (r = 0; r < b; ++r) + for (k = 0; k <= d[r]; k++) _TEMPLATE(T, vec_set) (S[d[r] - k].rows[r], F[k].rows[r], b, ctx); - for(k = 0; k < f_len; ++k) TEMPLATE(T, mat_clear) (&F[i], ctx); + for (k = 0; k < f_len; ++k) TEMPLATE(T, mat_clear) (&F[i], ctx); TEMPLATE(T, mat_clear) (M, ctx); flint_free(F); flint_free(d); @@ -172,7 +172,7 @@ static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) dd = flint_malloc(b*sizeof(*dd)); for (nu = 0; nu < b; nu++); for (dd[nu] = 0; dd[nu] <= d[l]; ++dd[nu]) - if(!TEMPLATE(T, is_zero) (&S[dd[nu]].rows[l][nu], ctx)) break; + if (!TEMPLATE(T, is_zero) (&S[dd[nu]].rows[l][nu], ctx)) break; /* Simulaneously apply all polynomials in row l to iteration of M on Z */ v = _TEMPLATE(T, vec_init) (b, ctx); @@ -180,8 +180,8 @@ static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) _TEMPLATE(T, vec_zero) (x, M->r, ctx); for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) { - if(iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); - for(nu = 0; nu < b; nu++) + if (iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); + for (nu = 0; nu < b; nu++) { if (dd[nu] <= d[l]) TEMPLATE(T, set) (&v[nu], &S[dd[nu]++].rows[l][nu], ctx); else TEMPLATE(T, zero) (&v[nu], ctx); @@ -204,7 +204,7 @@ int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_vec_struct) *row; TEMPLATE(T, sparse_entry_struct) *le, *re; if (M->r != M->c) return 0; /* TODO */ - if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; @@ -221,7 +221,7 @@ int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_vec_clear) (z, ctx); TEMPLATE(T, sparse_mat_clear) (Mb, ctx); - if(!TEMPLATE(T, is_zero) (&x1[M->c], ctx)) + if (!TEMPLATE(T, is_zero) (&x1[M->c], ctx)) { TEMPLATE(T, inv) (&x1[M->c], &x1[M->c], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x1, M->c, &x1[M->c], ctx); diff --git a/fq_sparse_mat_templates/solve_lanczos.c b/fq_sparse_mat_templates/solve_lanczos.c index b9b48f8104..3b2216d5e3 100644 --- a/fq_sparse_mat_templates/solve_lanczos.c +++ b/fq_sparse_mat_templates/solve_lanczos.c @@ -23,7 +23,7 @@ int TEMPLATE(T, sparse_mat_solve_lanczos) (TEMPLATE(T, struct) *x, const TEMPLAT TEMPLATE(T, struct) *v[2], *Mv, *Av, *Mtb, vtAv[2]; TEMPLATE(T, sparse_mat_t) Mt; - if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; @@ -102,7 +102,8 @@ int TEMPLATE(T, sparse_mat_solve_lanczos) (TEMPLATE(T, struct) *x, const TEMPLAT return ret; } -int TEMPLATE(T, sparse_mat_nullvector_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { +int TEMPLATE(T, sparse_mat_nullvector_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +{ int ret = 1; TEMPLATE(T, struct) *x2, *b; x2 = _TEMPLATE(T, vec_init) (M->c, ctx); @@ -110,7 +111,7 @@ int TEMPLATE(T, sparse_mat_nullvector_lanczos) (TEMPLATE(T, struct) *x, const TE _TEMPLATE(T, vec_randtest) (x, state, M->c, ctx); TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); - if(TEMPLATE(T, sparse_mat_solve_lanczos) (x2, M, b, state, ctx) == 0) ret = 0; /* Lanczos failed */ + if (TEMPLATE(T, sparse_mat_solve_lanczos) (x2, M, b, state, ctx) == 0) ret = 0; /* Lanczos failed */ if (ret) { _TEMPLATE(T, vec_sub) (x, x, x2, M->c, ctx); diff --git a/fq_sparse_mat_templates/solve_lu.c b/fq_sparse_mat_templates/solve_lu.c index b2df8d78b0..9ba32954a2 100644 --- a/fq_sparse_mat_templates/solve_lu.c +++ b/fq_sparse_mat_templates/solve_lu.c @@ -22,7 +22,7 @@ int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, TEMPLATE(T, t) cc; TEMPLATE(T, struct) *bp, *y, *xp; TEMPLATE(T, sparse_mat_t) L, U; - if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; @@ -62,7 +62,7 @@ int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, TEMPLATE(T, sub) (&xp[i], &y[i], &xp[i], ctx); TEMPLATE(T, div) (&xp[i], &xp[i], U->rows[i].entries[0].val, ctx); } - for(i = 0; i < M->c; ++i) TEMPLATE(T, set) (&x[i], &xp[Q[i]], ctx); + for (i = 0; i < M->c; ++i) TEMPLATE(T, set) (&x[i], &xp[Q[i]], ctx); } TEMPLATE(T, sparse_mat_clear) (L, ctx); TEMPLATE(T, sparse_mat_clear) (U, ctx); diff --git a/fq_sparse_mat_templates/solve_rref.c b/fq_sparse_mat_templates/solve_rref.c index 04ebc553bf..a668c17df9 100644 --- a/fq_sparse_mat_templates/solve_rref.c +++ b/fq_sparse_mat_templates/solve_rref.c @@ -21,7 +21,7 @@ int TEMPLATE(T, sparse_mat_solve_rref) (TEMPLATE(T, struct) *x, const TEMPLATE(T TEMPLATE(T, sparse_mat_t) Mb; TEMPLATE(T, sparse_vec_struct) *row; TEMPLATE(T, sparse_entry_struct) *le, *re; - if(_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c index b1dc94ac2f..78b922484c 100644 --- a/fq_sparse_mat_templates/solve_wiedemann.c +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -54,7 +54,7 @@ static slong find_min_poly(TEMPLATE(T, struct) *s, slong N, const TEMPLATE(T, ct TEMPLATE(T, add) (&C[m+i], &C[m+i], cc, ctx); } deg_C = FLINT_MAX(deg_C, deg_B + m); - while(TEMPLATE(T, is_zero) (&C[deg_C], ctx)) --deg_C; /* Probably unnecessary */ + while (TEMPLATE(T, is_zero) (&C[deg_C], ctx)) --deg_C; /* Probably unnecessary */ if (2*L <= n) /* Increase number of errors */ { @@ -82,8 +82,8 @@ static void make_sequences(TEMPLATE(T, struct) **s, slong ns, slong len, const T slong iter, i, j; for (i = iter = 0; iter < len; ++iter, i = 1-i) { - if(iter > 0) TEMPLATE(T, sparse_mat_mul_vec) (y[i], A, y[1-i], ctx); - for(j = 0; j < ns; ++j) TEMPLATE(T, set) (&s[j][iter], &y[i][j], ctx); + if (iter > 0) TEMPLATE(T, sparse_mat_mul_vec) (y[i], A, y[1-i], ctx); + for (j = 0; j < ns; ++j) TEMPLATE(T, set) (&s[j][iter], &y[i][j], ctx); } } @@ -104,8 +104,8 @@ int TEMPLATE(T, sparse_mat_solve_wiedemann) (TEMPLATE(T, struct) *x, const TEMPL slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; TEMPLATE(T, t) cc; TEMPLATE(T, struct) **s, *y[2]; - if(A->r != A->c) return 0; /* TBD: reduce to square */ - if(_TEMPLATE(T, vec_is_zero) (b, A->r, ctx)) + if (A->r != A->c) return 0; /* TBD: reduce to square */ + if (_TEMPLATE(T, vec_is_zero) (b, A->r, ctx)) { _TEMPLATE(T, vec_zero) (x, A->c, ctx); return 1; @@ -125,7 +125,7 @@ int TEMPLATE(T, sparse_mat_solve_wiedemann) (TEMPLATE(T, struct) *x, const TEMPL { /* Get minimal polynomial */ L = find_min_poly(s[i], len, ctx); - if(TEMPLATE(T, is_zero) (&s[i][0], ctx)) continue; + if (TEMPLATE(T, is_zero) (&s[i][0], ctx)) continue; /* If \sum_{j=0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j=0}^{L-1} s_i(j-1) A^jb solves Ax=b */ _TEMPLATE(T, vec_set) (y[0], b, A->r, ctx); @@ -151,7 +151,7 @@ int TEMPLATE(T, sparse_mat_nullvector_wiedemann) (TEMPLATE(T, struct) *x, const slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; TEMPLATE(T, struct) **s, *y[3]; - if(A->r != A->c) return 0; /* TBD: reduce to square */ + if (A->r != A->c) return 0; /* TBD: reduce to square */ s = flint_malloc(ns * sizeof(*s)); for (i = 0; i < ns; ++i) s[i] = _TEMPLATE(T, vec_init) (len, ctx); diff --git a/fq_sparse_mat_templates/test/t-inv.c b/fq_sparse_mat_templates/test/t-inv.c index f1c7906f3b..f7e5cece7e 100644 --- a/fq_sparse_mat_templates/test/t-inv.c +++ b/fq_sparse_mat_templates/test/t-inv.c @@ -35,7 +35,7 @@ main(void) for (rep = 0; rep < 100; rep++) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); do r = n_randint(state, 200), c = n_randint(state, 200); while (r==UWORD(0) || c==UWORD(0)); @@ -50,7 +50,7 @@ main(void) rk = TEMPLATE(T, sparse_mat_inv) (Ai, A, ctx); TEMPLATE(T, sparse_mat_mul_mat) (dAiA, Ai, dA, ctx); TEMPLATE(T, mat_rref) (dA, ctx); - if(!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) { + if (!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) { flint_printf("FAIL!\n"); flint_printf("A^-1 x A = "); TEMPLATE(T, mat_print_pretty) (dAiA, ctx); diff --git a/fq_sparse_mat_templates/test/t-lu.c b/fq_sparse_mat_templates/test/t-lu.c index 1672298d31..03c74242c9 100644 --- a/fq_sparse_mat_templates/test/t-lu.c +++ b/fq_sparse_mat_templates/test/t-lu.c @@ -51,19 +51,19 @@ main(void) TEMPLATE(T, mat_init) (dLU, r, c, ctx); /* Check that L is lower triangular (with ones on diagonal up to rank) */ - for(i=0; irows[i], i, ctx); - if(i < rk && (val == NULL || !TEMPLATE(T, is_one) (*val, ctx))) + if (i < rk && (val == NULL || !TEMPLATE(T, is_one) (*val, ctx))) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } - for(j=0; jrows[i].nnz; ++j) { + for (j = 0; jrows[i].nnz; ++j) { TEMPLATE(T, sparse_entry_struct) *e = &L->rows[i].entries[j]; - if(e->ind > i) { + if (e->ind > i) { flint_printf("FAIL: L not lower triangular\n"); abort(); } - if(e->ind >= rk) { + if (e->ind >= rk) { flint_printf("FAIL: L not trivial past the rank\n"); /*TEMPLATE(T, sparse_mat_print_pretty) (L, ctx);*/ abort(); @@ -71,21 +71,21 @@ main(void) } } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ - for(i=0; irows[i], i, ctx); - if(i < rk && (val == NULL || TEMPLATE(T, is_zero) (*val, ctx))) + if (i < rk && (val == NULL || TEMPLATE(T, is_zero) (*val, ctx))) { flint_printf("FAIL: U does not have nonzero diagonal\n"); abort(); } - if(i >= rk && U->rows[i].nnz != UWORD(0)) + if (i >= rk && U->rows[i].nnz != UWORD(0)) { flint_printf("FAIL: U not trivial past the rank\n"); abort(); } - for(j=0; jrows[i].nnz; ++j) { + for (j = 0; j < U->rows[i].nnz; ++j) { TEMPLATE(T, sparse_entry_struct) *e = &U->rows[i].entries[j]; - if(e->ind < i) { + if (e->ind < i) { flint_printf("FAIL: U not upper triangular\n"); abort(); } @@ -97,7 +97,7 @@ main(void) TEMPLATE(T, sparse_mat_from_dense) (LU, dLU, ctx); TEMPLATE(T, sparse_mat_permute_rows) (A, P, ctx); TEMPLATE(T, sparse_mat_permute_cols) (A, Q, ctx); - if(!TEMPLATE(T, sparse_mat_equal) (A, LU, ctx)) { + if (!TEMPLATE(T, sparse_mat_equal) (A, LU, ctx)) { flint_printf("FAIL: PAQ != LU\n"); flint_printf("PAQ="); TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c index cbfa3f7ff8..4f78dd455e 100644 --- a/fq_sparse_mat_templates/test/t-nullspace.c +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -38,7 +38,7 @@ main(void) for (rep = 0; rep < nreps; ) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); r = c = n_randint(state, 200); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); @@ -57,7 +57,7 @@ main(void) else ++rep; gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if(rk[i]!=0) + if (rk[i]!=0) { TEMPLATE(T, mat_init) (AX, A->r, X->c, ctx); TEMPLATE(T, sparse_mat_mul_mat) (AX, A, X, ctx); diff --git a/fq_sparse_mat_templates/test/t-rref.c b/fq_sparse_mat_templates/test/t-rref.c index 2aad0b8067..35c2d8a977 100644 --- a/fq_sparse_mat_templates/test/t-rref.c +++ b/fq_sparse_mat_templates/test/t-rref.c @@ -45,7 +45,7 @@ main(void) TEMPLATE(T, sparse_mat_rref) (A, ctx); TEMPLATE(T, mat_rref) (dA, ctx); TEMPLATE(T, sparse_mat_from_dense) (B, dA, ctx); - if(!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) { + if (!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) { flint_printf("FAIL!\n"); abort(); } diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index 9fd64c2a8d..dad75aebdd 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -37,7 +37,7 @@ main(void) for (rep = 0; rep < nrep; rep++) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); do c = r = n_randint(state, 200); @@ -63,7 +63,7 @@ main(void) gettimeofday(&end, NULL); rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - if(!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) { flint_printf("FAIL: Ax != b, got ret %d\n", ret); abort(); @@ -75,7 +75,7 @@ main(void) gettimeofday(&end, NULL); lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - if(!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) { flint_printf("FAIL: Ax != b, got ret %d\n", ret); abort(); diff --git a/fq_sparse_mat_templates/transpose.c b/fq_sparse_mat_templates/transpose.c index 8cfff56f36..f227856165 100644 --- a/fq_sparse_mat_templates/transpose.c +++ b/fq_sparse_mat_templates/transpose.c @@ -30,7 +30,7 @@ TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) B, const TEMPLATE(T for (i = 0; i < A->rows[r].nnz; ++i) { c = A->rows[r].entries[i].ind - A->c_off; - if(c >= A->c) break; + if (c >= A->c) break; nnz[c]++; } } @@ -47,7 +47,7 @@ TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) B, const TEMPLATE(T { Ae = &A->rows[r].entries[i]; c = Ae->ind - A->c_off; - if(c >= A->c) break; + if (c >= A->c) break; j = nnz[c]++; Be = &B->rows[c].entries[j]; Be->ind = r; diff --git a/fq_sparse_vec_templates/add.c b/fq_sparse_vec_templates/add.c index 407bd56abe..d5dd9190a2 100644 --- a/fq_sparse_vec_templates/add.c +++ b/fq_sparse_vec_templates/add.c @@ -18,7 +18,7 @@ void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, { slong i, nnz, unnz, vnnz; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if(u->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, v, 0, ctx); + if (u->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, v, 0, ctx); else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); else { @@ -44,7 +44,7 @@ void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); else if (nnz < w->nnz) { - for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); w->nnz = nnz; diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c index 352c3bc722..90c62b163f 100644 --- a/fq_sparse_vec_templates/scalar_addmul.c +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -19,7 +19,7 @@ void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TE slong i, nnz, unnz, vnnz; TEMPLATE(T, t) tmp; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if(u->nnz == 0) TEMPLATE(T, sparse_vec_scalar_mul) (w, v, c, ctx); + if (u->nnz == 0) TEMPLATE(T, sparse_vec_scalar_mul) (w, v, c, ctx); else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); else { @@ -47,7 +47,7 @@ void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TE if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); else if (nnz < w->nnz) { - for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); w->nnz = nnz; diff --git a/fq_sparse_vec_templates/sub.c b/fq_sparse_vec_templates/sub.c index b85ce59d18..a0c1ade68b 100644 --- a/fq_sparse_vec_templates/sub.c +++ b/fq_sparse_vec_templates/sub.c @@ -18,7 +18,7 @@ void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, { slong i, nnz, unnz, vnnz; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if(u->nnz == 0) TEMPLATE(T, sparse_vec_neg) (w, v, ctx); + if (u->nnz == 0) TEMPLATE(T, sparse_vec_neg) (w, v, ctx); else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); else { @@ -44,7 +44,7 @@ void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); else if (nnz < w->nnz) { - for(i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); w->nnz = nnz; diff --git a/fq_sparse_vec_templates/test/t-init_clear.c b/fq_sparse_vec_templates/test/t-init_clear.c index 39bb9008b5..61a32ea3f8 100644 --- a/fq_sparse_vec_templates/test/t-init_clear.c +++ b/fq_sparse_vec_templates/test/t-init_clear.c @@ -70,7 +70,7 @@ main(void) flint_printf("FAIL: found 0 value\n"); abort(); } - if (i>0 && e->ind <= e[-1].ind) + if (i > 0 && e->ind <= e[-1].ind) { flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); abort(); diff --git a/nmod_mat/one.c b/nmod_mat/one.c index 700a54c21f..cb626b06dc 100644 --- a/nmod_mat/one.c +++ b/nmod_mat/one.c @@ -22,6 +22,6 @@ nmod_mat_one(nmod_mat_t mat) slong i,j; for(i = 0; i < mat->r; i++) for(j = 0; j < mat->c; j++) - if(i==j) nmod_mat_entry(mat, i, j) = 1; + if(i == j) nmod_mat_entry(mat, i, j) = 1; else nmod_mat_entry(mat, i, j) = 0; } diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 19f36fa52c..879e0341f7 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -105,7 +105,7 @@ void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { slong i, rmax = FLINT_MIN(M->r, src->r); if(M==src || M->r == 0) return; - for(i=0; irows[i], &src->rows[i], src->c_off); + for (i = 0; i < rmax; ++i) nmod_sparse_vec_set(&M->rows[i], &src->rows[i], src->c_off); } FLINT_DLL @@ -115,7 +115,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, const mp_ptr v) { slong i; - for(i=0; ir; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); + for (i = 0; i < M->r; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); M->c += 1; } @@ -183,7 +183,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); } /* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ @@ -192,8 +192,8 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, { slong i; r = FLINT_MIN(r, B->r); - for(i=0; irows[i], &B->rows[i], B->c_off); - for(i=r; ir; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); + for (i = 0; i < r; ++i) nmod_sparse_vec_set(&M1->rows[i], &B->rows[i], B->c_off); + for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } @@ -347,7 +347,7 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); -/* Solve Ax=b */ +/* Solve Ax = b */ FLINT_DLL int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 8762f78494..024486ab2e 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -53,8 +53,8 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s /* static void print_heap(slong *heap, slong *scores, slong size) { slong level, i; - for(level=1; level<=size; level<<=1) { - for(i=level; i<=size && i<2*level; ++i) { + for (level = 1; level<=size; level<<=1) { + for (i = level; i<=size && i < 2*level; ++i) { flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); } flint_printf("\n"); @@ -85,12 +85,12 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, /* Set up permutations */ remr = M->r, remc = M->c; - for (r = 0; rr; ++r) + for (r = 0; r < M->r; ++r) { if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for (c = 0; cc; ++c) + for (c = 0; c < M->c; ++c) { if (!Lt->rows[c].nnz) Q[c] = --remc; else Q[c] = -1; @@ -109,7 +109,7 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, } /* Run elimination */ rank = 0; - for (heap_size=M->c; heap_size > 0; ) + for (heap_size = M->c; heap_size > 0; ) { /* Get lowest weight column (top of heap) */ pc = heap[0]; diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index 19969e55cc..60497ecb57 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -18,7 +18,7 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; @@ -26,7 +26,7 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, nxs = 0; xs = NULL; xps = NULL; - for(iter = 0; iter < max_iters; ) + for (iter = 0; iter < max_iters; ) { if(nmod_sparse_mat_nullvector_lanczos(x, M, state) == 0) {++iter; continue;} diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index 74f73b2d68..eb5d68f1f1 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -31,7 +31,7 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) rk = nmod_sparse_mat_lu(P, Q, L, U, M); flint_free(P); nmod_sparse_mat_clear(L); - for(i=0; irows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, M->mod), M->mod); nmod_mat_init(X, M->c, M->c-rk, M->mod.n); if (rk != M->c) @@ -45,7 +45,7 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) for (i = rk-1; i >= 0; --i) { Urow = &U->rows[i]; Xrow = X->rows[Qi[i]]; - for(j = 1; jnnz; ++j) { + for (j = 1; j < Urow->nnz; ++j) { e = &Urow->entries[j]; /* Do in-place row elimination */ if(e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, M->mod), M->mod); diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c index 4f8497bfc7..84e9943d00 100644 --- a/nmod_sparse_mat/nullspace_wiedemann.c +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -18,7 +18,7 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; @@ -26,7 +26,7 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t nxs = 0; xs = NULL; xps = NULL; - for(iter = 0; iter < max_iters; ) + for (iter = 0; iter < max_iters; ) { if(nmod_sparse_mat_nullvector_wiedemann(x, M, state) == 0) {++iter; continue;} diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index d30219554d..6d071af025 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -31,7 +31,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) /* Set up permutations */ P = flint_malloc(M->r*sizeof(*P)); remr = M->r; - for (r = 0; rr; ++r) + for (r = 0; r < M->r; ++r) { if (!M->rows[r].nnz || M->rows[r].entries[0].ind >= M->c) P[r] = --remr; else P[r] = -1; @@ -39,7 +39,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) /* Run elimination */ rank = 0; - for (pc=0; pcc; ++pc) + for (pc = 0; pc < M->c; ++pc) { pcol = &Mt->rows[pc]; diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index 40ac9ff0da..3a91e4ff02 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -61,7 +61,7 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { _nmod_vec_scalar_mul_nmod(nWi->rows[pc], nWi->rows[pc], b, cc, T->mod); /* Kill all other entries in pivot column */ - for(i = 0; i < b; ++i) + for (i = 0; i < b; ++i) { cc = nmod_neg(X->rows[P[i]][pc], T->mod); if (i == j || cc == 0) continue; @@ -132,7 +132,7 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ for (i = 0; i < V[0].r*V[0].c; ++i) V[0].entries[i] = n_randint(state, V[0].mod.n); - for(iter = 0; ; ++iter) + for (iter = 0; ; ++iter) { i = iter % 3; next_i = (iter + 1) % 3; diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index d2c6e8a331..1de1b03ac0 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -15,7 +15,7 @@ #include "flint.h" #include "nmod_sparse_mat.h" -/* Compute S_i=(M^j Y)_{0...b-1}^T for i=0,...,ns-1 */ +/* Compute S_i=(M^j Y)_{0...b-1}^T for i = 0,...,ns-1 */ static void make_block_sequences(nmod_mat_struct *S, slong ns, const nmod_sparse_mat_t M, nmod_mat_struct Y[2]) { slong iter, i, j, k, b = Y->c; @@ -127,7 +127,7 @@ static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n) nmod_mat_window_init(D, M, 0, 0, 2*b, b); nmod_mat_window_init(tau, M, 0, b, 2*b, 3*b); nmod_mat_zero(D); - for(k = 0; k <= t; ++k) nmod_mat_addmul(D, D, &F[k], &S[t-k]); + for (k = 0; k <= t; ++k) nmod_mat_addmul(D, D, &F[k], &S[t-k]); nmod_mat_one(tau); nmod_mat_window_clear(D); nmod_mat_window_clear(tau); @@ -139,18 +139,18 @@ static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n) for (k = f_len-1; k > 0; --k) nmod_mat_mul(&F[k], tau, &F[k-1]); /* Every row multiplied by x */ for (k = 0; k < f_len; ++k) - for(r = 0; r < b; ++r) /* Divide first b rows by x */ + for (r = 0; r < b; ++r) /* Divide first b rows by x */ (k < f_len - 1) ? _nmod_vec_set(F[k].rows[r], F[k+1].rows[r], b) : _nmod_vec_zero(F[k].rows[r], b); for (r = b; r < 2*b; ++r) d[r] += 1; nmod_mat_window_clear(tau); } /* Copy C to S, with each row reversed according to its degree */ - for(r = 0; r < b; ++r) - for(k = 0; k <= d[r]; k++) + for (r = 0; r < b; ++r) + for (k = 0; k <= d[r]; k++) _nmod_vec_set(S[d[r] - k].rows[r], F[k].rows[r], b); - for(k = 0; k < f_len; ++k) nmod_mat_clear(&F[i]); + for (k = 0; k < f_len; ++k) nmod_mat_clear(&F[i]); nmod_mat_clear(M); flint_free(F); flint_free(d); @@ -176,7 +176,7 @@ static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, c for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) { if(iter > 0) nmod_sparse_mat_mul_mat(&Z[i], M, &Z[1-i]); - for(nu = 0; nu < b; nu++) + for (nu = 0; nu < b; nu++) v[nu] = (dd[nu] <= d[l]) ? S[dd[nu]++].rows[l][nu] : UWORD(0); nmod_sparse_mat_mul_vec(xi, M, v); _nmod_vec_add(x, x, xi, M->c, M->mod); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 09205525e9..bd53456b8b 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -43,7 +43,7 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ /* Make 0th vector random (and -1st vector trivial) */ //_nmod_vec_set(v[0], Mtb, M->c); - //for(j = 0; j < M->c; ++j) v[0][j] = n_randint(state, M->mod.n); + //for (j = 0; j < M->c; ++j) v[0][j] = n_randint(state, M->mod.n); _nmod_vec_randtest(v[0], state, M->c, M->mod); _nmod_vec_zero(v[1], M->c); vtAv[1] = 1; for (j = 0; ; j = 1-j) diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 14e2417267..63c22cff00 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -16,7 +16,7 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x=Qx' */ +/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x = Qx' */ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) { int good = 1; @@ -53,7 +53,7 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b xp[i] = nmod_div(nmod_sub(y[i], nmod_sparse_vec_dot_dense(&U->rows[i], xp, M->mod), M->mod), U->rows[i].entries[0].val, M->mod); nmod_sparse_mat_mul_vec(y, U, xp); - for(i = 0; i < M->c; ++i) x[i] = xp[Q[i]]; + for (i = 0; i < M->c; ++i) x[i] = xp[Q[i]]; flint_free(xp); } flint_free(Q); diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index c629ef1107..5d53d84ee4 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -30,7 +30,7 @@ static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) for (n = 0, m = 1; n < N; n++, m++) { - /* d_C = sum_{i=0}^L C_i * s_{n-i} */ + /* d_C = sum_{i = 0}^L C_i * s_{n-i} */ d_C = s[n]; for (i = 1; i <= L; i++) d_C = nmod_addmul(d_C, C[i], s[n-i], mod); @@ -59,7 +59,7 @@ static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) return L; } -/* Compute s_ij=(A^j y)_i for i=0,...,ns-1, j=0,...,num-1*/ +/* Compute s_ij=(A^j y)_i for i = 0,...,ns-1, j = 0,...,num-1*/ static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse_mat_t A, mp_srcptr b) { slong i, j; @@ -70,13 +70,13 @@ static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse for (j = 0; j < len; ++j) { if(j > 0) nmod_sparse_mat_mul_vec(Ay, A, y), memcpy(y, Ay, A->r*sizeof(*y)); - for(i = 0; i < ns; ++i) s[i][j] = y[i]; + for (i = 0; i < ns; ++i) s[i][j] = y[i]; } _nmod_vec_clear(y); _nmod_vec_clear(Ay); } -/* Compute x = \Sigma_{i=0}^{L-1} s_i * A^i * b = 0 */ +/* Compute x = \Sigma_{i = 0}^{L-1} s_i * A^i * b = 0 */ static void make_sum(mp_ptr x, mp_limb_t *s, slong L, const nmod_sparse_mat_t A, mp_srcptr b) { slong i; @@ -114,7 +114,7 @@ int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const m L = find_min_poly(s[i], len, A->mod); if(s[i][0]==0) continue; - /* If \sum_{j=0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j=0}^{L-1} s_i(j-1) A^jb solves Ax=b */ + /* If \sum_{j = 0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j = 0}^{L-1} s_i(j-1) A^jb solves Ax = b */ make_sum(x, s[i]+1, L, A, b); _nmod_vec_scalar_mul_nmod(x, x, A->r, nmod_neg(nmod_inv(s[i][0], A->mod), A->mod), A->mod); @@ -151,7 +151,7 @@ int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, fl /* Get minimal polynomial */ L = find_min_poly(s[i], len, A->mod); - /* \sum_{j=0}^L s_ijA^jb = 0 => x = \sum_{j=0}^L s_ijA^jx solves Ax=0 */ + /* \sum_{j = 0}^L s_ijA^jb = 0 => x = \sum_{j = 0}^L s_ijA^jx solves Ax = 0 */ make_sum(x, s[i], L+1, A, x); nmod_sparse_mat_mul_vec(Ax, A, x); ret = _nmod_vec_is_zero(Ax, A->r); diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c index 52cd5a215e..6fedc125b3 100644 --- a/nmod_sparse_mat/test/t-lu.c +++ b/nmod_sparse_mat/test/t-lu.c @@ -28,7 +28,7 @@ main(void) nmod_mat_t dL, dU, dLU; FLINT_TEST_INIT(state); - flint_printf("decomposing PAQ=LU...."); + flint_printf("decomposing PAQ = LU...."); fflush(stdout); for (rep = 0; rep < 1000; rep++) @@ -54,12 +54,12 @@ main(void) nmod_mat_init(dLU, r, c, n); /* Check that L is lower triangular (with ones on diagonal up to rank) */ - for(i=0; irows[i], i) != UWORD(1)) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } - for(j=0; jrows[i].nnz; ++j) { + for (j = 0; j < L->rows[i].nnz; ++j) { nmod_sparse_entry_struct *e = &L->rows[i].entries[j]; if(e->ind > i) { flint_printf("FAIL: L not lower triangular\n"); @@ -73,7 +73,7 @@ main(void) } } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ - for(i=0; irows[i], i) == UWORD(0)) { flint_printf("FAIL: U does not have nonzero diagonal\n"); @@ -84,7 +84,7 @@ main(void) flint_printf("FAIL: U not trivial pas the rank\n"); abort(); } - for(j=0; jrows[i].nnz; ++j) { + for (j = 0; j < U->rows[i].nnz; ++j) { nmod_sparse_entry_struct *e = &U->rows[i].entries[j]; if(e->ind < i) { flint_printf("FAIL: U not upper triangular\n"); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 3315828a40..30b3819fc3 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -32,7 +32,7 @@ main(void) struct timeval start, end; FLINT_TEST_INIT(state); - flint_printf("solving Ax=b...."); + flint_printf("solving Ax = b...."); fflush(stdout); for (rep = 0; rep < nrep; rep++) @@ -86,7 +86,7 @@ main(void) /* Solve iteratively */ gettimeofday(&start, NULL); - ret=nmod_sparse_mat_solve_wiedemann(x2, A, b); + ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); gettimeofday(&end, NULL); wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); if (ret == 0) @@ -105,7 +105,7 @@ main(void) gettimeofday(&start, NULL); iter = 0; - do ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state); + do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret==0 && ++iter < 30); gettimeofday(&end, NULL); lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c index e3a025fb7e..d634052964 100644 --- a/nmod_sparse_vec/dot_dense.c +++ b/nmod_sparse_vec/dot_dense.c @@ -18,6 +18,6 @@ mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) { slong i; mp_limb_t ret = UWORD(0); - for(i=0; innz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); + for (i = 0; i < u->nnz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); return ret; } diff --git a/nmod_sparse_vec/set.c b/nmod_sparse_vec/set.c index 9d7d105192..a78f588c6a 100644 --- a/nmod_sparse_vec/set.c +++ b/nmod_sparse_vec/set.c @@ -25,7 +25,7 @@ void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src, slo vec->entries = flint_realloc(vec->entries, src->nnz*sizeof(*vec->entries)); memcpy(vec->entries, src->entries, src->nnz*sizeof(*vec->entries)); vec->nnz = src->nnz; - for(i=0; innz; ++i) + for (i = 0; i < vec->nnz; ++i) { vec->entries[i].ind -= ioff; } diff --git a/nmod_sparse_vec/split.c b/nmod_sparse_vec/split.c index 83a8e11c25..3d8b2bc541 100644 --- a/nmod_sparse_vec/split.c +++ b/nmod_sparse_vec/split.c @@ -18,7 +18,7 @@ void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res2, const nmod_sparse_vec_t vec, slong ind) { slong i; - for(i=0; innz; ++i) if(vec->entries[i].ind >= ind) break; + for (i = 0; i < vec->nnz; ++i) if(vec->entries[i].ind >= ind) break; if(i==0) nmod_sparse_vec_clear(res1); else { res1->nnz = i; @@ -30,6 +30,6 @@ void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res2, const res2->nnz = vec->nnz - i; res2->entries = flint_realloc(res2->entries, res2->nnz*sizeof(*res2->entries)); memcpy(res2->entries, vec->entries+i, res2->nnz*sizeof(*res2->entries)); - for(i=0; innz; ++i) res2->entries[i].ind -= ind; + for (i = 0; i < res2->nnz; ++i) res2->entries[i].ind -= ind; } } diff --git a/nmod_sparse_vec/window_init.c b/nmod_sparse_vec/window_init.c index 40b50078a3..34ab51e428 100644 --- a/nmod_sparse_vec/window_init.c +++ b/nmod_sparse_vec/window_init.c @@ -18,8 +18,8 @@ void nmod_sparse_vec_window_init(nmod_sparse_vec_t window, const nmod_sparse_vec_t vec, slong i1, slong i2) { slong start, end; - for (start = 0; startnnz && vec->entries[start].ind < i1; ++start); - for (end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + for (start = 0; start < vec->nnz && vec->entries[start].ind < i1; ++start); + for (end = vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); window->entries = vec->entries + start; window->nnz = end - start; } From 23d2c4e9205b0deb7778a14ea1ad68e2c13c3f06 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 8 Apr 2020 18:42:28 -0700 Subject: [PATCH 17/42] Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) --- fq_nmod_sparse_mat/nullspace_block_lanczos.c | 23 +++++ .../nullspace_block_wiedemann.c | 23 +++++ fq_sparse_mat/nullspace_block_lanczos.c | 23 +++++ fq_sparse_mat/nullspace_block_wiedemann.c | 23 +++++ fq_sparse_mat_templates.h | 7 ++ .../nullspace_block_lanczos.c | 80 ++++++++++++++++++ .../nullspace_block_wiedemann.c | 81 ++++++++++++++++++ fq_sparse_mat_templates/solve_block_lanczos.c | 78 +++++++++-------- fq_sparse_mat_templates/test/t-solve.c | 35 +++++++- fq_zech_sparse_mat/nullspace_block_lanczos.c | 23 +++++ .../nullspace_block_wiedemann.c | 23 +++++ nmod_sparse_mat.h | 9 +- nmod_sparse_mat/nullspace_block_lanczos.c | 71 ++++++++++++++++ nmod_sparse_mat/nullspace_block_wiedemann.c | 71 ++++++++++++++++ nmod_sparse_mat/solve_block_lanczos.c | 84 ++++++++++++------- nmod_sparse_mat/test/t-solve.c | 44 ++++++++-- 16 files changed, 625 insertions(+), 73 deletions(-) create mode 100644 fq_nmod_sparse_mat/nullspace_block_lanczos.c create mode 100644 fq_nmod_sparse_mat/nullspace_block_wiedemann.c create mode 100644 fq_sparse_mat/nullspace_block_lanczos.c create mode 100644 fq_sparse_mat/nullspace_block_wiedemann.c create mode 100644 fq_sparse_mat_templates/nullspace_block_lanczos.c create mode 100644 fq_sparse_mat_templates/nullspace_block_wiedemann.c create mode 100644 fq_zech_sparse_mat/nullspace_block_lanczos.c create mode 100644 fq_zech_sparse_mat/nullspace_block_wiedemann.c create mode 100644 nmod_sparse_mat/nullspace_block_lanczos.c create mode 100644 nmod_sparse_mat/nullspace_block_wiedemann.c diff --git a/fq_nmod_sparse_mat/nullspace_block_lanczos.c b/fq_nmod_sparse_mat/nullspace_block_lanczos.c new file mode 100644 index 0000000000..5b4e5416f7 --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_block_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_nmod_sparse_mat/nullspace_block_wiedemann.c b/fq_nmod_sparse_mat/nullspace_block_wiedemann.c new file mode 100644 index 0000000000..a1a1e2d597 --- /dev/null +++ b/fq_nmod_sparse_mat/nullspace_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_nmod_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_mat_templates/nullspace_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_block_lanczos.c b/fq_sparse_mat/nullspace_block_lanczos.c new file mode 100644 index 0000000000..0da3550c03 --- /dev/null +++ b/fq_sparse_mat/nullspace_block_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat/nullspace_block_wiedemann.c b/fq_sparse_mat/nullspace_block_wiedemann.c new file mode 100644 index 0000000000..decfaf8ea1 --- /dev/null +++ b/fq_sparse_mat/nullspace_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_mat_templates/nullspace_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat_templates.h b/fq_sparse_mat_templates.h index 3ce9c803c6..d3d40ade96 100644 --- a/fq_sparse_mat_templates.h +++ b/fq_sparse_mat_templates.h @@ -286,6 +286,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_mul_mat) (TEMPLATE(T, mat_t) Y, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx) { slong i, j; + TEMPLATE(T, mat_zero) (Y, ctx); for (i = 0; i < M->r; ++i) { for (j = 0; j < M->rows[i].nnz; ++j) @@ -350,6 +351,12 @@ slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEM FLINT_DLL slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); + FLINT_DLL slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); diff --git a/fq_sparse_mat_templates/nullspace_block_lanczos.c b/fq_sparse_mat_templates/nullspace_block_lanczos.c new file mode 100644 index 0000000000..67de9dfab4 --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_block_lanczos.c @@ -0,0 +1,80 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) +{ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) *x, **xs; + + TEMPLATE(T, init) (cc, ctx); + x = _TEMPLATE(T, vec_init) (M->c, ctx); + nxs = 0; + xs = NULL; + xps = NULL; + for (iter = 0; iter < max_iters; ) + { + if (TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (x, M, block_size, state, ctx) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) + { + TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && TEMPLATE(T, is_zero) (&x[i], ctx); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + TEMPLATE(T, inv) (cc, &x[i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) + { + TEMPLATE(T, neg) (cc, &xs[j][i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _TEMPLATE(T, vec_init) (M->c, ctx); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + TEMPLATE(T, clear) (cc, ctx); + _TEMPLATE(T, vec_clear) (x, M->c, ctx); + TEMPLATE(T, mat_init) (X, M->c, nxs, ctx); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + TEMPLATE(T, set) (&X->rows[j][i], &xs[i][j], ctx); + _TEMPLATE(T, vec_clear) (xs[i], M->c, ctx); + } + flint_free(xs); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/nullspace_block_wiedemann.c b/fq_sparse_mat_templates/nullspace_block_wiedemann.c new file mode 100644 index 0000000000..0dfbbd25a2 --- /dev/null +++ b/fq_sparse_mat_templates/nullspace_block_wiedemann.c @@ -0,0 +1,81 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifdef T + +#include +#include "templates.h" + +slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) +{ + /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + TEMPLATE(T, t) cc; + TEMPLATE(T, struct) *x, **xs; + + TEMPLATE(T, init) (cc, ctx); + x = _TEMPLATE(T, vec_init) (M->c, ctx); + nxs = 0; + xs = NULL; + xps = NULL; + for (iter = 0; iter < max_iters; ) + { + if (TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (x, M, block_size, state, ctx) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) + { + TEMPLATE(T, neg) (cc, &x[xps[j]], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (x, xs[j], M->c, cc, ctx); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && TEMPLATE(T, is_zero) (&x[i], ctx); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + TEMPLATE(T, inv) (cc, &x[i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x, M->c, cc, ctx); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) + { + TEMPLATE(T, neg) (cc, &xs[j][i], ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (xs[j], x, M->c, cc, ctx); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _TEMPLATE(T, vec_init) (M->c, ctx); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + TEMPLATE(T, mat_init) (X, M->c, nxs, ctx); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + TEMPLATE(T, set) (&X->rows[j][i], &xs[i][j], ctx); + _TEMPLATE(T, vec_clear) (xs[i], M->c, ctx); + } + TEMPLATE(T, clear) (cc, ctx); + _TEMPLATE(T, vec_clear) (x, M->c, ctx); + + flint_free(xs); + return X->c; +} + +#endif diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c index 67731e41c9..572237a5ea 100644 --- a/fq_sparse_mat_templates/solve_block_lanczos.c +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -29,28 +29,31 @@ static int compute_nWi_S(TEMPLATE(T, mat_t) nWi, int *S, const TEMPLATE(T, mat_t const slong b = Torig->r; slong pc, i, j, rk = 0; - TEMPLATE(T, mat_t) T; - TEMPLATE(T, mat_struct) *X; slong *P; TEMPLATE(T, t) cc; + TEMPLATE(T, mat_t) T; + TEMPLATE(T, mat_struct) *X; P = flint_malloc(b * sizeof(*P)); + TEMPLATE(T, init) (cc, ctx); TEMPLATE(T, mat_init) (T, b, b, ctx); TEMPLATE(T, mat_set) (T, Torig, ctx); TEMPLATE(T, mat_one) (nWi, ctx); /* Set permutation to have previously dependent vectors at front */ P = flint_malloc(b*sizeof(*P)); - for (i = j = 0; i < b; ++i) if (!S[i]) P[j++] = i; - for (i = j = 0; i < b; ++i) if (S[i]) P[j++] = i; + j = 0; + for (i = 0; i < b; ++i) if (!S[i]) P[j++] = i; + for (i = 0; i < b; ++i) if (S[i]) P[j++] = i; for (j = 0; j < b; ++j) { pc = P[j]; /* Pivot col */ /* Find viable pivot row (from T if possible, then from W) */ - for (X = T, i = b; i == b; X = nWi) - for (i = j; i < b && TEMPLATE(T, is_zero)(&X->rows[P[i]][pc], ctx); ++i); + for (X = T, i = j; i < b && TEMPLATE(T, is_zero)(&X->rows[P[i]][pc], ctx); ++i); + if (i == b) + for (X = nWi, i = j; i < b && TEMPLATE(T, is_zero)(&X->rows[P[i]][pc], ctx); ++i); S[pc] = X == T; /* Viable column in V */ TEMPLATE(T, mat_swap_rows) (T, NULL, pc, P[i], ctx); TEMPLATE(T, mat_swap_rows) (nWi, NULL, pc, P[i], ctx); /* Now pivot row = pivot col */ @@ -100,39 +103,42 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, mat_t) MV; /* Application of M to V */ TEMPLATE(T, mat_t) AV; /* Application of Mt to MV */ int *SSt; /* S is the maximal projection s.t. (VS)^tAVS is invertible, so SSt kills the dropped columns */ - TEMPLATE(T, mat_t) nWi[3]; /* -S((VS)^tAVS)^-1S^t */ + TEMPLATE(T, mat_struct) nWi[3]; /* -S((VS)^tAVS)^-1S^t */ TEMPLATE(T, mat_t) VSSt; /* V with invalid vectors zeroed out */ TEMPLATE(T, mat_t) T; /* Used to store transposes for inner products */ TEMPLATE(T, mat_t) VtAV; /* Inner product _A */ TEMPLATE(T, mat_t) AVtAVSSt_VtAV; /* Sum _A SS^t + _A, shared by two updates */ TEMPLATE(T, mat_t) DEF; /* Used to store coefficient matrices D, E, and F */ - TEMPLATE(T, mat_t) I; /* I_{b x b} */ - TEMPLATE(T, struct) *SStVtb, *WiSStVtb, *VSStWiSStVtb; /* Intermediate elements in x update */ + TEMPLATE(T, mat_t) I, tmp; /* I_{b x b} */ + TEMPLATE(T, struct) *Mtb, *SStVtMtb, *WiSStVtMtb, *VSStWiSStVtMtb; /* Intermediate elements in x update */ if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; } - TEMPLATE(T, sparse_mat_init) (Mt, M->c, M->r, ctx); for (i = 0; i < 3; ++i) TEMPLATE(T, mat_init) (&V[i], M->c, block_size, ctx); TEMPLATE(T, mat_init) (MV, M->r, block_size, ctx); /* Intermediate product */ TEMPLATE(T, mat_init) (AV, M->c, block_size, ctx); /* Symmetric product */ SSt = flint_malloc(block_size*sizeof(*SSt)); - for (i = 0; i < 2; ++i) TEMPLATE(T, mat_init) (nWi[i], block_size, block_size, ctx); + for (i = 0; i < 3; ++i) TEMPLATE(T, mat_init) (&nWi[i], block_size, block_size, ctx); + TEMPLATE(T, mat_init) (VSSt, M->c, block_size, ctx); /* Transpose for computing matrix dot products */ TEMPLATE(T, mat_init) (T, block_size, M->c, ctx); /* Transpose for computing matrix dot products */ TEMPLATE(T, mat_init) (VtAV, block_size, block_size, ctx); TEMPLATE(T, mat_init) (AVtAVSSt_VtAV, block_size, block_size, ctx); // (AV)^T(AV) + VtAV TEMPLATE(T, mat_init) (DEF, block_size, block_size, ctx); // Shared by D, E, and F TEMPLATE(T, mat_init) (I, block_size, block_size, ctx); - SStVtb = _TEMPLATE(T, vec_init) (block_size, ctx); - WiSStVtb = _TEMPLATE(T, vec_init) (block_size, ctx); - VSStWiSStVtb = _TEMPLATE(T, vec_init) (M->c, ctx); + TEMPLATE(T, mat_init) (tmp, block_size, block_size, ctx); + Mtb = _TEMPLATE(T, vec_init) (M->c, ctx); + SStVtMtb = _TEMPLATE(T, vec_init) (block_size, ctx); + WiSStVtMtb = _TEMPLATE(T, vec_init) (block_size, ctx); + VSStWiSStVtMtb = _TEMPLATE(T, vec_init) (M->c, ctx); _TEMPLATE(T, vec_zero) (x, M->c, ctx); TEMPLATE(T, sparse_mat_transpose) (Mt, M, ctx); for (i = 0; i < block_size; ++i) SSt[i] = 1; TEMPLATE(T, mat_one) (I, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Mtb, Mt, b, ctx); // Initialize V[0] randomly for (i = 0; i < V[0].r*V[0].c; ++i) @@ -146,9 +152,9 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T if (iter >= 2) { /* Compute the F value for this round (minus the final term) */ - TEMPLATE(T, mat_addmul) (DEF, I, VtAV, nWi[prev_i], ctx); - TEMPLATE(T, mat_mul) (nWi[i], nWi[next_i], DEF, ctx); /* nWi[i] used for scratch */ - TEMPLATE(T, mat_mul) (DEF, nWi[i], AVtAVSSt_VtAV, ctx); + TEMPLATE(T, mat_addmul) (DEF, I, VtAV, &nWi[prev_i], ctx); + TEMPLATE(T, mat_mul) (tmp, &nWi[next_i], DEF, ctx); + TEMPLATE(T, mat_mul) (DEF, tmp, AVtAVSSt_VtAV, ctx); } /* Compute AV and V'AV */ @@ -156,9 +162,10 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, sparse_mat_mul_mat) (AV, Mt, MV, ctx); TEMPLATE(T, mat_transpose) (T, &V[i], ctx); TEMPLATE(T, mat_mul) (VtAV, T, AV, ctx); + if (TEMPLATE(T, mat_is_zero) (VtAV, ctx)) {ret = 1; break;} /* Compute W^{-1} and indices of bad vectors */ - cur_dim = compute_nWi_S(nWi[i], SSt, VtAV, ctx); + cur_dim = compute_nWi_S(&nWi[i], SSt, VtAV, ctx); total_dim += cur_dim; if (cur_dim == 0 || total_dim > M->c) break; /* Ran out of vectors */ @@ -166,10 +173,10 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, mat_set) (VSSt, &V[i], ctx); kill_columns(VSSt, SSt, ctx); TEMPLATE(T, mat_transpose) (T, VSSt, ctx); - TEMPLATE(T, mat_mul_vec) (SStVtb, T, b, ctx); - TEMPLATE(T, mat_mul_vec) (WiSStVtb, nWi[i], SStVtb, ctx); - TEMPLATE(T, mat_mul_vec) (VSStWiSStVtb, VSSt, WiSStVtb, ctx); - _TEMPLATE(T, vec_add) (x, x, VSStWiSStVtb, M->c, ctx); + TEMPLATE(T, mat_mul_vec) (SStVtMtb, T, Mtb, ctx); + TEMPLATE(T, mat_mul_vec) (WiSStVtMtb, &nWi[i], SStVtMtb, ctx); + TEMPLATE(T, mat_mul_vec) (VSStWiSStVtMtb, VSSt, WiSStVtMtb, ctx); + _TEMPLATE(T, vec_add) (x, x, VSStWiSStVtMtb, M->c, ctx); /** * Per Equation (19), we compute the next vector @@ -184,21 +191,22 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T { /* V_{i+1} = V_{i-2} F */ kill_columns(DEF, SSt, ctx); - TEMPLATE(T, mat_mul) (&V[next_i], &V[next_i], DEF, ctx); + TEMPLATE(T, mat_mul) (VSSt, &V[next_i], DEF, ctx); + TEMPLATE(T, mat_set) (&V[next_i], VSSt, ctx); } if (iter >= 1) { /* V_{i+1} += V_{i-1} E */ - TEMPLATE(T, mat_mul) (DEF, nWi[prev_i], VtAV, ctx); + TEMPLATE(T, mat_mul) (DEF, &nWi[prev_i], VtAV, ctx); kill_columns(DEF, SSt, ctx); TEMPLATE(T, mat_addmul) (&V[next_i], &V[next_i], &V[prev_i], DEF, ctx); } /* V_{i+1} += V_i D */ TEMPLATE(T, mat_transpose) (T, AV, ctx); - TEMPLATE(T, mat_mul) (AVtAVSSt_VtAV, T, AV, ctx); - kill_columns(AVtAVSSt_VtAV, SSt, ctx); - TEMPLATE(T, mat_add) (AVtAVSSt_VtAV, AVtAVSSt_VtAV, VtAV, ctx); - TEMPLATE(T, mat_addmul) (DEF, I, nWi[i], AVtAVSSt_VtAV, ctx); + TEMPLATE(T, mat_mul) (tmp, T, AV, ctx); + kill_columns(tmp, SSt, ctx); + TEMPLATE(T, mat_add) (AVtAVSSt_VtAV, tmp, VtAV, ctx); + TEMPLATE(T, mat_addmul) (DEF, I, &nWi[i], AVtAVSSt_VtAV, ctx); TEMPLATE(T, mat_addmul) (&V[next_i], &V[next_i], &V[i], DEF, ctx); /* V_{i+1} += AVSS^t */ @@ -207,20 +215,24 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T if (TEMPLATE(T, mat_is_zero) (&V[i], ctx)) {ret = 1; break;} } - TEMPLATE(T, sparse_mat_clear) (Mt, ctx); + _TEMPLATE(T, vec_neg) (x, x, M->c, ctx); + TEMPLATE(T, sparse_mat_clear) (Mt, ctx); for (i = 0; i < 3; ++i) TEMPLATE(T, mat_clear) (&V[i], ctx); TEMPLATE(T, mat_clear) (MV, ctx); TEMPLATE(T, mat_clear) (AV, ctx); flint_free(SSt); - for (i = 0; i < 2; ++i) TEMPLATE(T, mat_clear) (nWi[i], ctx); + for (i = 0; i < 3; ++i) TEMPLATE(T, mat_clear) (&nWi[i], ctx); TEMPLATE(T, mat_clear) (T, ctx); TEMPLATE(T, mat_clear) (VtAV, ctx); + TEMPLATE(T, mat_clear) (VSSt, ctx); TEMPLATE(T, mat_clear) (AVtAVSSt_VtAV, ctx); TEMPLATE(T, mat_clear) (DEF, ctx); TEMPLATE(T, mat_clear) (I, ctx); - _TEMPLATE(T, vec_clear) (SStVtb, block_size, ctx); - _TEMPLATE(T, vec_clear) (WiSStVtb, block_size, ctx); - _TEMPLATE(T, vec_clear) (VSStWiSStVtb, M->c, ctx); + TEMPLATE(T, mat_clear) (tmp, ctx); + _TEMPLATE(T, vec_clear) (Mtb, M->c, ctx); + _TEMPLATE(T, vec_clear) (SStVtMtb, block_size, ctx); + _TEMPLATE(T, vec_clear) (WiSStVtMtb, block_size, ctx); + _TEMPLATE(T, vec_clear) (VSStWiSStVtMtb, M->c, ctx); return ret; } diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index dad75aebdd..5af9c9d401 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -23,12 +23,13 @@ main(void) { int iter, ret; int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; slong rep, r, c, i, nrep = 100; TEMPLATE(T, t) a; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, At; TEMPLATE(T, struct) *x, *x2, *b, *Atb, *Ax, *AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + double block_lanczos_elapsed = 0, rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; struct timeval start, end; FLINT_TEST_INIT(state); @@ -40,7 +41,7 @@ main(void) if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); - do c = r = n_randint(state, 200); + do c = r = 100 + n_randint(state, 100); while(c == 0 || r == 0); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); @@ -127,6 +128,34 @@ main(void) psolved += 1; } } + + gettimeofday(&start, NULL); + iter = 0; + do ret=TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, A, b, 8, state, ctx); + while(ret==0 && ++iter < 30); + gettimeofday(&end, NULL); + block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) + { + block_lanczos_nosol += 1; + continue; + } + else + { + block_lanczos_niters += iter; + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (AtAx, At, Ax, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Atb, At, b, ctx); + if (!_TEMPLATE(T, vec_equal) (AtAx, Atb, A->c, ctx)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + psolved += 1; + } + } _TEMPLATE(T, vec_clear) (x, c, ctx); _TEMPLATE(T, vec_clear) (x2, c, ctx); @@ -143,10 +172,12 @@ main(void) flint_printf("PASS\n"); flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); + flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); return 0; } diff --git a/fq_zech_sparse_mat/nullspace_block_lanczos.c b/fq_zech_sparse_mat/nullspace_block_lanczos.c new file mode 100644 index 0000000000..dfe4bf1ccb --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_block_lanczos.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_block_lanczos.c" +#undef CAP_T +#undef T diff --git a/fq_zech_sparse_mat/nullspace_block_wiedemann.c b/fq_zech_sparse_mat/nullspace_block_wiedemann.c new file mode 100644 index 0000000000..873b0a4b9c --- /dev/null +++ b/fq_zech_sparse_mat/nullspace_block_wiedemann.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + + +#include "fq_zech_sparse_mat.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_mat_templates/nullspace_block_wiedemann.c" +#undef CAP_T +#undef T diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 879e0341f7..80f1220579 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -313,7 +313,7 @@ void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const n /* Matrix-vector and matrix-matrix multipliciation */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, const mp_ptr x) +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); @@ -322,6 +322,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; + nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) { for (j = 0; j < M->rows[i].nnz; ++j) @@ -383,9 +384,15 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M FLINT_DLL slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +FLINT_DLL +slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); + FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +FLINT_DLL +slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); + FLINT_DLL slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); diff --git a/nmod_sparse_mat/nullspace_block_lanczos.c b/nmod_sparse_mat/nullspace_block_lanczos.c new file mode 100644 index 0000000000..35f32db75d --- /dev/null +++ b/nmod_sparse_mat/nullspace_block_lanczos.c @@ -0,0 +1,71 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters) +{ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + mp_ptr x, *xs; + x = _nmod_vec_init(M->c); + nxs = 0; + xs = NULL; + xps = NULL; + for (iter = 0; iter < max_iters; ) + { + if(nmod_sparse_mat_nullvector_block_lanczos(x, M, block_size, state) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && x[i] == UWORD(0); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _nmod_vec_init(M->c); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + flint_free(x); + nmod_mat_init(X, M->c, nxs, M->mod.n); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + X->rows[j][i] = xs[i][j]; + flint_free(xs[i]); + } + flint_free(xs); + return X->c; +} diff --git a/nmod_sparse_mat/nullspace_block_wiedemann.c b/nmod_sparse_mat/nullspace_block_wiedemann.c new file mode 100644 index 0000000000..78ac95a105 --- /dev/null +++ b/nmod_sparse_mat/nullspace_block_wiedemann.c @@ -0,0 +1,71 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" + +slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters) +{ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ + int ret; + slong i, j, iter, nxs, *xps; + mp_ptr x, *xs; + x = _nmod_vec_init(M->c); + nxs = 0; + xs = NULL; + xps = NULL; + for (iter = 0; iter < max_iters; ) + { + if(nmod_sparse_mat_nullvector_block_wiedemann(x, M, block_size, state) == 0) {++iter; continue;} + + /* Reduce by existing kernel vectors */ + for (j = nxs-1; j >= 0; --j) { + _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); + } + + /* Normalize last nonzero entry to 1 */ + for (i = M->c-1; i >= 0 && x[i] == UWORD(0); --i); + if (i == -1) {++iter; continue;} /* x in span of xs, nullspace probably complete */ + _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); + + /* Reduce previous vectors by this one */ + for (j = 0; j < nxs; ++j) { + _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); + } + + /* Insert into list of vectors in nullspace (ordered by pivot) */ + xs = realloc(xs, (nxs+1)*sizeof(*xs)); + xps = realloc(xps, (nxs+1)*sizeof(*xps)); + for (j = 0; j < nxs && i > xps[j]; ++j); + memmove(xs + j + 1, xs + j, (nxs - j)*sizeof(*xs)); + memmove(xps + j + 1, xps + j, (nxs - j)*sizeof(*xps)); + xps[j] = i; + xs[j] = x; + nxs += 1; + x = _nmod_vec_init(M->c); /* New vector for next iteration */ + iter = 0; + } + flint_free(xps); + flint_free(x); + nmod_mat_init(X, M->c, nxs, M->mod.n); + for (i = 0; i < nxs; ++i) + { + for (j = 0; j < M->c; ++j) + X->rows[j][i] = xs[i][j]; + flint_free(xs[i]); + } + flint_free(xs); + return X->c; +} diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index 3a91e4ff02..afacbec6c3 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -41,16 +41,18 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { /* Set permutation to have previously dependent vectors at front */ P = flint_malloc(b*sizeof(*P)); - for (i = j = 0; i < b; ++i) if(!S[i]) P[j++] = i; - for (i = j = 0; i < b; ++i) if(S[i]) P[j++] = i; + j = 0; + for (i = 0; i < b; ++i) if(!S[i]) P[j++] = i; + for (i = 0; i < b; ++i) if(S[i]) P[j++] = i; for (j = 0; j < b; ++j) { pc = P[j]; /* Pivot col */ /* Find viable pivot row (from T if possible, then from W) */ - for (X = T, i = b; i == b; X = nWi) - for (i = j; i < b && X->rows[P[i]][pc] == 0; ++i); + for (X = T, i = j; i < b && X->rows[P[i]][pc] == 0; ++i); + if (i == b) + for (X = nWi, i = j; i < b && X->rows[P[i]][pc] == 0; ++i); S[pc] = X == T; /* Viable column in V */ nmod_mat_swap_rows(T, NULL, pc, P[i]); nmod_mat_swap_rows(nWi, NULL, pc, P[i]); /* Now pivot row = pivot col */ @@ -60,6 +62,7 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { _nmod_vec_scalar_mul_nmod(T->rows[pc], T->rows[pc], b, cc, T->mod); _nmod_vec_scalar_mul_nmod(nWi->rows[pc], nWi->rows[pc], b, cc, T->mod); + /* Kill all other entries in pivot column */ for (i = 0; i < b; ++i) { @@ -76,6 +79,7 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { _nmod_vec_zero(nWi->rows[pc], b); } } + nmod_mat_neg(nWi, nWi); nmod_mat_clear(T); @@ -99,34 +103,44 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ nmod_mat_t MV; /* Application of M to V */ nmod_mat_t AV; /* Application of Mt to MV */ int *SSt; /* S is the maximal projection s.t. (VS)^tAVS is invertible, so SSt kills the dropped columns */ - nmod_mat_t nWi[3]; /* -S((VS)^tAVS)^-1S^t */ + nmod_mat_struct nWi[3]; /* -S((VS)^tAVS)^-1S^t */ nmod_mat_t VSSt; /* V with invalid vectors zeroed out */ nmod_mat_t T; /* Used to store transposes for inner products */ nmod_mat_t VtAV; /* Inner product _A */ nmod_mat_t AVtAVSSt_VtAV; /* Sum _A SS^t + _A, shared by two updates */ nmod_mat_t DEF; /* Used to store coefficient matrices D, E, and F */ - nmod_mat_t I; /* I_{b x b} */ - mp_ptr SStVtb, WiSStVtb, VSStWiSStVtb; /* Intermediate elements in x update */ + nmod_mat_t I, tmp; /* I_{b x b}, tmp used as scratch */ + mp_ptr Mtb, SStVtMtb, WiSStVtMtb, VSStWiSStVtMtb; /* Intermediate elements in x update */ + + if (_nmod_vec_is_zero(b, M->r)) + { + _nmod_vec_zero(x, M->c); + return 1; + } nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); for (i = 0; i < 3; ++i) nmod_mat_init(&V[i], M->c, block_size, M->mod.n); nmod_mat_init(MV, M->r, block_size, M->mod.n); /* Intermediate product */ nmod_mat_init(AV, M->c, block_size, M->mod.n); /* Symmetric product */ SSt = flint_malloc(block_size*sizeof(*SSt)); - for (i = 0; i < 2; ++i) nmod_mat_init(nWi[i], block_size, block_size, M->mod.n); + for (i = 0; i < 3; ++i) nmod_mat_init(&nWi[i], block_size, block_size, M->mod.n); + nmod_mat_init(VSSt, M->c, block_size, M->mod.n); nmod_mat_init(T, block_size, M->c, M->mod.n); /* Transpose for computing matrix dot products */ nmod_mat_init(VtAV, block_size, block_size, M->mod.n); nmod_mat_init(AVtAVSSt_VtAV, block_size, block_size, M->mod.n); // (AV)^T(AV) + VtAV nmod_mat_init(DEF, block_size, block_size, M->mod.n); // Shared by D, E, and F nmod_mat_init(I, block_size, block_size, M->mod.n); - SStVtb = _nmod_vec_init(block_size); - WiSStVtb = _nmod_vec_init(block_size); - VSStWiSStVtb = _nmod_vec_init(M->c); + nmod_mat_init(tmp, block_size, block_size, M->mod.n); + Mtb = _nmod_vec_init(M->c); + SStVtMtb = _nmod_vec_init(block_size); + WiSStVtMtb = _nmod_vec_init(block_size); + VSStWiSStVtMtb = _nmod_vec_init(M->c); _nmod_vec_zero(x, M->c); nmod_sparse_mat_transpose(Mt, M); for (i = 0; i < block_size; ++i) SSt[i] = 1; nmod_mat_one(I); + nmod_sparse_mat_mul_vec(Mtb, Mt, b); // Initialize V[0] randomly for (i = 0; i < V[0].r*V[0].c; ++i) @@ -140,9 +154,9 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ if(iter>=2) { /* Compute the F value for this round (minus the final term) */ - nmod_mat_addmul(DEF, I, VtAV, nWi[prev_i]); - nmod_mat_mul(nWi[i], nWi[next_i], DEF); /* nWi[i] used for scratch */ - nmod_mat_mul(DEF, nWi[i], AVtAVSSt_VtAV); + nmod_mat_addmul(DEF, I, VtAV, &nWi[prev_i]); + nmod_mat_mul(tmp, &nWi[next_i], DEF); + nmod_mat_mul(DEF, tmp, AVtAVSSt_VtAV); } /* Compute AV and V'AV */ @@ -150,9 +164,10 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ nmod_sparse_mat_mul_mat(AV, Mt, MV); nmod_mat_transpose(T, &V[i]); nmod_mat_mul(VtAV, T, AV); - + if (nmod_mat_is_zero(VtAV)) {ret = 1; break;} + /* Compute W^{-1} and indices of bad vectors */ - cur_dim = compute_nWi_S(nWi[i], SSt, VtAV); + cur_dim = compute_nWi_S(&nWi[i], SSt, VtAV); total_dim += cur_dim; if (cur_dim == 0 || total_dim > M->c) break; /* Ran out of vectors */ @@ -160,10 +175,10 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ nmod_mat_set(VSSt, &V[i]); kill_columns(VSSt, SSt); nmod_mat_transpose(T, VSSt); - nmod_mat_mul_vec(SStVtb, T, b); - nmod_mat_mul_vec(WiSStVtb, nWi[i], SStVtb); - nmod_mat_mul_vec(VSStWiSStVtb, VSSt, WiSStVtb); - _nmod_vec_add(x, x, VSStWiSStVtb, M->c, M->mod); + nmod_mat_mul_vec(SStVtMtb, T, Mtb); + nmod_mat_mul_vec(WiSStVtMtb, &nWi[i], SStVtMtb); + nmod_mat_mul_vec(VSStWiSStVtMtb, VSSt, WiSStVtMtb); + _nmod_vec_add(x, x, VSStWiSStVtMtb, M->c, M->mod); /** * Per Equation (19), we compute the next vector @@ -178,43 +193,48 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ { /* V_{i+1} = V_{i-2} F */ kill_columns(DEF, SSt); - nmod_mat_mul(&V[next_i], &V[next_i], DEF); + nmod_mat_mul(VSSt, &V[next_i], DEF); + nmod_mat_set(&V[next_i], VSSt); } if(iter >= 1) { /* V_{i+1} += V_{i-1} E */ - nmod_mat_mul(DEF, nWi[prev_i], VtAV); + nmod_mat_mul(DEF, &nWi[prev_i], VtAV); kill_columns(DEF, SSt); nmod_mat_addmul(&V[next_i], &V[next_i], &V[prev_i], DEF); } /* V_{i+1} += V_i D */ nmod_mat_transpose(T, AV); - nmod_mat_mul(AVtAVSSt_VtAV, T, AV); - kill_columns(AVtAVSSt_VtAV, SSt); - nmod_mat_add(AVtAVSSt_VtAV, AVtAVSSt_VtAV, VtAV); - nmod_mat_addmul(DEF, I, nWi[i], AVtAVSSt_VtAV); + nmod_mat_mul(tmp, T, AV); + kill_columns(tmp, SSt); + nmod_mat_add(AVtAVSSt_VtAV, tmp, VtAV); + nmod_mat_addmul(DEF, I, &nWi[i], AVtAVSSt_VtAV); nmod_mat_addmul(&V[next_i], &V[next_i], &V[i], DEF); /* V_{i+1} += AVSS^t */ kill_columns(AV, SSt); nmod_mat_add(&V[next_i], &V[next_i], AV); - if(nmod_mat_is_zero(&V[i])) {ret = 1; break;} + if (nmod_mat_is_zero(&V[next_i])) {ret = 1; break;} } - nmod_sparse_mat_clear(Mt); + _nmod_vec_neg(x, x, M->c, M->mod); + nmod_sparse_mat_clear(Mt); for (i = 0; i < 3; ++i) nmod_mat_clear(&V[i]); nmod_mat_clear(MV); nmod_mat_clear(AV); flint_free(SSt); - for (i = 0; i < 2; ++i) nmod_mat_clear(nWi[i]); + for (i = 0; i < 3; ++i) nmod_mat_clear(&nWi[i]); nmod_mat_clear(T); nmod_mat_clear(VtAV); + nmod_mat_clear(VSSt); nmod_mat_clear(AVtAVSSt_VtAV); nmod_mat_clear(DEF); nmod_mat_clear(I); - _nmod_vec_clear(SStVtb); - _nmod_vec_clear(WiSStVtb); - _nmod_vec_clear(VSStWiSStVtb); + nmod_mat_clear(tmp); + _nmod_vec_clear(SStVtMtb); + _nmod_vec_clear(WiSStVtMtb); + _nmod_vec_clear(VSStWiSStVtMtb); + _nmod_vec_clear(Mtb); return ret; } diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 30b3819fc3..43d4697b06 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -23,12 +23,15 @@ main(void) { int iter, ret; int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; slong rep, r, c, i, nrep = 100; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, At; + nmod_mat_t dA; mp_ptr x, x2, b, Atb, Ax, AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; + double block_lanczos_elapsed = 0, block_wiedemann_elapsed = 0, wiedemann_elapsed = 0; struct timeval start, end; FLINT_TEST_INIT(state); @@ -39,16 +42,17 @@ main(void) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - do c = r = n_randint(state, 200); - while(c == 0 || r == 0); + c = r = 500 + n_randint(state, 100); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); + nmod_mat_init(dA, r, c, n); nmod_sparse_mat_init(At, c, r, mod); - nmod_sparse_mat_randtest(A, state, 30, 30); + nmod_sparse_mat_randtest(A, state, c/20, c/10); + nmod_sparse_mat_to_dense(dA, A); nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); @@ -122,7 +126,7 @@ main(void) nmod_sparse_mat_mul_vec(Atb, At, b); if (!_nmod_vec_equal(AtAx, Atb, A->c)) { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + flint_printf("FAIL: AtAx != Atb, got ret %d\n", 5, ret); abort(); } else if (!_nmod_vec_equal(b, Ax, A->r)) @@ -131,6 +135,34 @@ main(void) } } + gettimeofday(&start, NULL); + iter = 0; + do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); + while(ret==0 && ++iter < 10); + gettimeofday(&end, NULL); + block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) + { + block_lanczos_nosol += 1; + continue; + } + else + { + block_lanczos_niters += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_nmod_vec_equal(b, Ax, A->r)) + { + block_lanczos_psolved += 1; + } + } + flint_free(x); flint_free(x2); flint_free(b); @@ -145,9 +177,11 @@ main(void) flint_printf("PASS\n"); flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); + flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); return 0; } From 51b55849f4a6621ebc0db561ea4df6bf7212622a Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 9 Apr 2020 15:52:59 -0700 Subject: [PATCH 18/42] Now with working block Wiedemann (and nullspace for both block methods) --- fq_sparse_mat_templates/solve_block_lanczos.c | 2 +- .../solve_block_wiedemann.c | 140 +++++++------ fq_sparse_mat_templates/solve_rref.c | 1 + fq_sparse_mat_templates/solve_wiedemann.c | 2 +- fq_sparse_mat_templates/test/t-nullspace.c | 43 ++-- fq_sparse_mat_templates/test/t-solve.c | 177 ++++++---------- nmod_sparse_mat/solve_block_lanczos.c | 2 +- nmod_sparse_mat/solve_block_wiedemann.c | 94 +++++---- nmod_sparse_mat/solve_lanczos.c | 1 + nmod_sparse_mat/solve_lu.c | 6 + nmod_sparse_mat/solve_rref.c | 7 + nmod_sparse_mat/solve_wiedemann.c | 97 ++++----- nmod_sparse_mat/test/t-nullspace.c | 45 ++-- nmod_sparse_mat/test/t-solve.c | 193 +++++++----------- 14 files changed, 367 insertions(+), 443 deletions(-) diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c index 572237a5ea..7a2911882b 100644 --- a/fq_sparse_mat_templates/solve_block_lanczos.c +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -250,7 +250,7 @@ int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, co { _TEMPLATE(T, vec_sub) (x, x, x2, M->c, ctx); TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); - ret = _TEMPLATE(T, vec_is_zero) (x, M->c, ctx) || !_TEMPLATE(T, vec_is_zero) (b, M->r, ctx); + ret = !_TEMPLATE(T, vec_is_zero) (x, M->c, ctx) && _TEMPLATE(T, vec_is_zero) (b, M->r, ctx); } _TEMPLATE(T, vec_clear) (x2, M->c, ctx); _TEMPLATE(T, vec_clear) (b, M->r, ctx); diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c index c54de9abe0..08113620c9 100644 --- a/fq_sparse_mat_templates/solve_block_wiedemann.c +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -14,15 +14,15 @@ #include #include "templates.h" -/* Compute S_i=(M^j Y)_{0...b-1}^T for i=0,...,ns-1 */ -static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Y[2], const TEMPLATE(T, ctx_t) ctx) +/* Compute S_i=(M^j Y)_{0...b-1}^T for i = 0,...,ns-1 */ +static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Y[2], const TEMPLATE(T, ctx_t) ctx) { slong iter, i, j, k, b = Y->c; - TEMPLATE(T, mat_struct) W[2]; - for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_init) (&W[i], Y, 0, 0, b, b, ctx); + TEMPLATE(T, mat_struct) W[2]; + for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_init) (&W[i], &Y[i], 0, 0, b, b, ctx); for (i = iter = 0; iter < ns; ++iter, i = 1-i) { - if (i > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Y[i], M, &Y[1-i], ctx); + if (iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Y[i], M, &Y[1-i], ctx); TEMPLATE(T, mat_transpose) (&S[iter], &W[i], ctx); } for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_clear) (&W[i], ctx); @@ -37,16 +37,18 @@ static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TEM * where the the number of nonzero rows in Z is the ith rank. We choose * the pivot row for a given column to be the one with minimal degree. **/ -static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE(T, ctx_t) ctx) +static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE(T, ctx_t) ctx) { const slong b = M->r/2; slong pr, pc, r, c, k, tmp; slong num_pi; slong *gamma; TEMPLATE(T, t) cinv, cc; - TEMPLATE(T, mat_t) tau; + TEMPLATE(T, mat_t) tau; + TEMPLATE(T, init) (cinv, ctx); TEMPLATE(T, init) (cc, ctx); + /* Keep track of viable rows */ gamma = flint_malloc(b*sizeof(*gamma)); for (r = 0; r < b; ++r) gamma[r] = 1; @@ -56,31 +58,33 @@ static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE /* Set the pivot row to be the minimum degree row incident on column pc */ pr = b + pc; for (r = 0; r < b; r++) - if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; - + if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; + if(TEMPLATE(T, is_zero) (&M->rows[pr][pc], ctx)) continue; + + /* Try to move pivot row to appropriate position (if not already there) */ if (pr != b + pc) { tmp = d[pr]; d[pr] = d[b+pc]; d[b+pc] = tmp; - if (!TEMPLATE(T, is_zero) (&M->rows[b + pc][pr], ctx)) - TEMPLATE(T, mat_swap_rows)(M, NULL, pr, b + pc, ctx), pr = b + pc; + if (!TEMPLATE(T, is_zero) (&M->rows[b + pc][pr], ctx)) + TEMPLATE(T, mat_swap_rows) (M, NULL, pr, b + pc, ctx), pr = b + pc; else /* Need to make new auxiliary vector and remove r from use */ _TEMPLATE(T, vec_add) (M->rows[b + pc], M->rows[b + pc], M->rows[pr], 3*b, ctx), gamma[pr] = 0; } TEMPLATE(T, inv) (cinv, &M->rows[pr][pc], ctx); /* Do Gaussian elimination on first b rows */ - for (r = 0; r < b; ++k) - if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) + for (r = 0; r < b; ++r) + if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) { TEMPLATE(T, mul) (cc, &M->rows[r][pc], cinv, ctx); TEMPLATE(T, neg) (cc, cc, ctx); - _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T))(M->rows[r], M->rows[pr], M->c, cc, ctx); + _TEMPLATE(T, TEMPLATE(vec_scalar_addmul, T)) (M->rows[r], M->rows[pr], M->c, cc, ctx); } } - TEMPLATE(T, clear) (cinv, ctx); TEMPLATE(T, clear) (cc, ctx); + TEMPLATE(T, clear) (cinv, ctx); flint_free(gamma); } @@ -109,24 +113,25 @@ static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) * - the first b are the current (reversed) generating polynomials * - the last b are certain auxiliary polynomials. **/ -static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, const TEMPLATE(T, ctx_t) ctx) +static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, slong delta, const TEMPLATE(T, ctx_t) ctx) { int ret; slong t, sigma, beta, mu; slong i, j, k, r, b = S->r; slong f_len; - TEMPLATE(T, mat_struct) *F; - TEMPLATE(T, mat_t) M, D, tau; + TEMPLATE(T, mat_struct) *F; + TEMPLATE(T, mat_t) M, D, tau, tmp; f_len = 1; - F = flint_malloc(n*sizeof(*F)); + F = flint_malloc((n+1)*sizeof(*F)); TEMPLATE(T, mat_init) (&F[0], 2*b, b, ctx); + TEMPLATE(T, mat_init) (tmp, b, b, ctx); for (i = 0; i < b; ++i) d[i] = 0, d[b + i] = 1, TEMPLATE(T, one) (&F[0].rows[i][i], ctx); /* [ D | I ] -> [ ? | tau ]*/ TEMPLATE(T, mat_init) (M, 2*b, 3*b, ctx); - for (t = 0; (ret = coppersmith_stopping_criterion(d, n, b)) == -1; ++t) + for (t = 0, ret = -1; t < n && ret == -1; ++t) { /* Compute discrepancy matrix and tau */ TEMPLATE(T, mat_window_init) (D, M, 0, 0, 2*b, b, ctx); @@ -145,66 +150,57 @@ static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, co TEMPLATE(T, mat_mul) (&F[k], tau, &F[k-1], ctx); /* Every row multiplied by x */ for (k = 0; k < f_len; ++k) for (r = 0; r < b; ++r) /* Divide first b rows by x */ - (k < f_len - 1) ? _TEMPLATE(T, vec_set) (F[k].rows[r], F[k+1].rows[r], b, ctx) : _TEMPLATE(T, vec_zero) (F[k].rows[r], b, ctx); - for (r = b; r < 2*b; ++r) d[r] += 1; + { + if (k < f_len - 1) _TEMPLATE(T, vec_set) (F[k].rows[r], F[k+1].rows[r], b, ctx); + else _TEMPLATE(T, vec_zero) (F[k].rows[r], b, ctx); + } + for (r = b; r < 2*b; ++r) _TEMPLATE(T, vec_zero) (F[0].rows[r], b, ctx), d[r] += 1; TEMPLATE(T, mat_window_clear) (tau, ctx); + ret = coppersmith_stopping_criterion(d, delta, b); } /* Copy C to S, with each row reversed according to its degree */ for (r = 0; r < b; ++r) for (k = 0; k <= d[r]; k++) - _TEMPLATE(T, vec_set) (S[d[r] - k].rows[r], F[k].rows[r], b, ctx); - - for (k = 0; k < f_len; ++k) TEMPLATE(T, mat_clear) (&F[i], ctx); + _TEMPLATE(T, vec_set) (S[k].rows[r], F[d[r]-k].rows[r], b, ctx); + + for (k = 0; k < f_len; ++k) TEMPLATE(T, mat_clear) (&F[k], ctx); TEMPLATE(T, mat_clear) (M, ctx); flint_free(F); - flint_free(d); return ret; } -static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) *S, const slong *d, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Z[2], slong l, const TEMPLATE(T, ctx_t) ctx) +static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) *S, const slong *d, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Z[2], slong l, const TEMPLATE(T, ctx_t) ctx) { - slong i, iter, k, nu, b = S->r; - slong *dd; - TEMPLATE(T, struct) *v, *xi; + slong i, iter, b = S->r; + slong dd; + TEMPLATE(T, struct) *xi; - /* Compute differences between nominal and real degrees of each coordinate polynomial in row l */ - dd = flint_malloc(b*sizeof(*dd)); - for (nu = 0; nu < b; nu++); - for (dd[nu] = 0; dd[nu] <= d[l]; ++dd[nu]) - if (!TEMPLATE(T, is_zero) (&S[dd[nu]].rows[l][nu], ctx)) break; + /* Compute differences between nominal and real degree */ + dd = 0; + while (_TEMPLATE(T, vec_is_zero) (S[dd].rows[l], b, ctx)) ++dd; /* Simulaneously apply all polynomials in row l to iteration of M on Z */ - v = _TEMPLATE(T, vec_init) (b, ctx); xi = _TEMPLATE(T, vec_init) (M->c, ctx); - _TEMPLATE(T, vec_zero) (x, M->r, ctx); - for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) + _TEMPLATE(T, vec_zero) (x, M->c, ctx); + for (i = iter = 0; iter <= d[l]; ++iter, i = 1 - i) { - if (iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); - for (nu = 0; nu < b; nu++) - { - if (dd[nu] <= d[l]) TEMPLATE(T, set) (&v[nu], &S[dd[nu]++].rows[l][nu], ctx); - else TEMPLATE(T, zero) (&v[nu], ctx); - } - TEMPLATE(T, sparse_mat_mul_vec) (xi, M, v, ctx); + if(iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); + TEMPLATE(T, mat_mul_vec) (xi, &Z[i], S[dd + iter].rows[l], ctx); _TEMPLATE(T, vec_add) (x, x, xi, M->c, ctx); } - _TEMPLATE(T, vec_clear) (v, b, ctx); _TEMPLATE(T, vec_clear) (xi, M->c, ctx); - flint_free(dd); } -int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { - int good = 0; + int good = 0, ret; slong i; - TEMPLATE(T, struct) *x1; - TEMPLATE(T, sparse_vec_t) z; - TEMPLATE(T, sparse_mat_t) Mb; - TEMPLATE(T, sparse_vec_struct) *row; - TEMPLATE(T, sparse_entry_struct) *le, *re; + TEMPLATE (T, struct) *x1; + TEMPLATE(T, sparse_vec_t) z; + TEMPLATE(T, sparse_mat_t) Mb; if (M->r != M->c) return 0; /* TODO */ - if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) + if (_TEMPLATE(T, vec_is_zero) (b, M->c, ctx)) { _TEMPLATE(T, vec_zero) (x, M->c, ctx); return 1; @@ -217,50 +213,52 @@ int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_set) (Mb, M, ctx); TEMPLATE(T, sparse_mat_append_col) (Mb, b, ctx); TEMPLATE(T, sparse_mat_append_row) (Mb, z, ctx); - TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (x1, Mb, block_size, state, ctx); - TEMPLATE(T, sparse_vec_clear) (z, ctx); - TEMPLATE(T, sparse_mat_clear) (Mb, ctx); - if (!TEMPLATE(T, is_zero) (&x1[M->c], ctx)) + ret = TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (x1, Mb, block_size, state, ctx); + if(ret && !TEMPLATE(T, is_zero) (&x1[M->c], ctx)) { TEMPLATE(T, inv) (&x1[M->c], &x1[M->c], ctx); + TEMPLATE(T, neg) (&x1[M->c], &x1[M->c], ctx); _TEMPLATE(T, TEMPLATE(vec_scalar_mul, T)) (x, x1, M->c, &x1[M->c], ctx); good = 1; - } + } + TEMPLATE(T, sparse_vec_clear) (z, ctx); + TEMPLATE(T, sparse_mat_clear) (Mb, ctx); _TEMPLATE(T, vec_clear) (x1, M->c + 1, ctx); return good; } -int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) +int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { int ret = 0; - slong l, ns; + slong l, ns, k; slong *d; TEMPLATE(T, struct) *b; - TEMPLATE(T, mat_t) Z; - TEMPLATE(T, mat_struct) Y[3], *S; + TEMPLATE(T, mat_t) Z; + TEMPLATE(T, mat_struct) Y[3], *S; if (M->r != M->c) return 0; /* TODO */ ns = 2*M->r/block_size + 3; /* Maybe 5? */ + S = flint_malloc(ns*sizeof(*S)); d = flint_calloc(2*block_size, sizeof(*d)); b = _TEMPLATE(T, vec_init) (M->r, ctx); - for (l = 0; l < 3; ++l) - TEMPLATE(T, mat_init) (&Y[l], M->c, block_size, ctx); - TEMPLATE(T, mat_randtest) (&Y[0], state, ctx); + for (k = 0; k < ns; ++k) TEMPLATE(T, mat_init) (&S[k], block_size, block_size, ctx); + for (l = 0; l < 3; ++l) TEMPLATE(T, mat_init) (&Y[l], M->c, block_size, ctx); + do TEMPLATE(T, mat_randtest) (&Y[0], state, ctx); + while(TEMPLATE(T, mat_is_zero) (&Y[0], ctx)); + TEMPLATE(T, sparse_mat_mul_mat) (&Y[1], M, &Y[0], ctx); make_block_sequences(S, ns, M, &Y[1], ctx); - find_block_min_poly(S, d, ns, ctx); + find_block_min_poly(S, d, ns, M->r, ctx); for (l = 0; l < block_size; ++l) { TEMPLATE(T, mat_set) (&Y[1], &Y[0], ctx); make_block_sum(x, S, d, M, Y + 1, l, ctx); TEMPLATE(T, sparse_mat_mul_vec) (b, M, x, ctx); - if (_TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) {ret = 1; break;}; + if (!_TEMPLATE(T, vec_is_zero) (x, M->c, ctx) && _TEMPLATE(T, vec_is_zero) (b, M->r, ctx)) {ret = 1; break;}; } return ret; } - - #endif diff --git a/fq_sparse_mat_templates/solve_rref.c b/fq_sparse_mat_templates/solve_rref.c index a668c17df9..64286820b3 100644 --- a/fq_sparse_mat_templates/solve_rref.c +++ b/fq_sparse_mat_templates/solve_rref.c @@ -48,6 +48,7 @@ int TEMPLATE(T, sparse_mat_solve_rref) (TEMPLATE(T, struct) *x, const TEMPLATE(T if (re->ind==M->c) TEMPLATE(T, set) (&x[le->ind], re->val, ctx); } TEMPLATE(T, sparse_mat_clear) (Mb, ctx); + return good; } #endif diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c index 78b922484c..44d586bd06 100644 --- a/fq_sparse_mat_templates/solve_wiedemann.c +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -171,7 +171,7 @@ int TEMPLATE(T, sparse_mat_nullvector_wiedemann) (TEMPLATE(T, struct) *x, const _TEMPLATE(T, vec_set) (y[1], y[0], A->r, ctx); make_sum(x, s[i], L+1, A, &y[1], ctx); TEMPLATE(T, sparse_mat_mul_vec) (y[1], A, x, ctx); - ret = _TEMPLATE(T, vec_is_zero) (y[1], A->r, ctx); + ret = !_TEMPLATE(T, vec_is_zero) (x, A->c, ctx) && _TEMPLATE(T, vec_is_zero) (y[1], A->r, ctx); } for (i = 0; i < ns; ++i) _TEMPLATE(T, vec_clear) (s[i], len, ctx); for (i = 0; i < 3; ++i) _TEMPLATE(T, vec_clear) (y[i], A->r, ctx); diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c index 4f78dd455e..688505da41 100644 --- a/fq_sparse_mat_templates/test/t-nullspace.c +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -27,23 +27,24 @@ main(void) TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A; TEMPLATE(T, mat_t) X, AX; - slong rk[4]; - slong discrep[4] = {0, 0, 0, 0}; - double elapsed[4] = {0, 0, 0, 0}; + slong rk[6]; + slong discrep[6] = {0, 0, 0, 0}; + double elapsed[6] = {0, 0, 0, 0}; + char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("finding nullspace of A...."); fflush(stdout); - for (rep = 0; rep < nreps; ) + for (rep = 0; rep < nreps; ++rep) { if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); - r = c = n_randint(state, 200); + r = c = 100 + n_randint(state, 100); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); - TEMPLATE(T, sparse_mat_randtest) (A, state, c/5, c/2, ctx); - for (i = 0; i < 4; ++i) + TEMPLATE(T, sparse_mat_randtest) (A, state, c/20, c/10, ctx); + for (i = 0; i < 6; ++i) { gettimeofday(&start, NULL); switch (i) @@ -51,10 +52,12 @@ main(void) case 0: rk[0] = TEMPLATE(T, sparse_mat_nullspace_rref) (X, A, ctx); break; case 1: rk[1] = TEMPLATE(T, sparse_mat_nullspace_lu) (X, A, ctx); break; case 2: rk[2] = TEMPLATE(T, sparse_mat_nullspace_lanczos) (X, A, state, 5, ctx); break; - case 3: rk[3] = TEMPLATE(T, sparse_mat_nullspace_wiedemann) (X, A, state, 5, ctx); break; + case 3: rk[3] = TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (X, A, 8, state, 2, ctx); break; + case 4: rk[4] = TEMPLATE(T, sparse_mat_nullspace_wiedemann) (X, A, state, 5, ctx); break; + case 5: rk[5] = TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (X, A, 8, state, 2, ctx); break; } - if (i == 0 && rk[0] == UWORD(0) ) { TEMPLATE(T, mat_clear) (X, ctx); break;} - else ++rep; + //if (i == 0 && rk[0] == UWORD(0) ) { TEMPLATE(T, mat_clear) (X, ctx); break;} + //else ++rep; gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); if (rk[i]!=0) @@ -72,10 +75,7 @@ main(void) } TEMPLATE(T, mat_clear) (AX, ctx); } - if (rk[i] != rk[0]) - { - discrep[i] += 1; - } + if (rk[i] != rk[0]) discrep[i] += 1; TEMPLATE(T, mat_clear) (X, ctx); } TEMPLATE(T, sparse_mat_clear) (A, ctx); @@ -84,13 +84,14 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for rref: %lf\n", elapsed[0]/nreps); - flint_printf("Average time for LU: %lf\n", elapsed[1]/nreps); - flint_printf("Average time for Lanzcos: %lf\n", elapsed[2]/nreps); - flint_printf("Average time for Wiedemann: %lf\n", elapsed[3]/nreps); - flint_printf("LU did not find full nullspace for %wd/%wd examples\n", discrep[1], nreps); - flint_printf("Lanczos did not find full nullspace for %wd/%wd examples\n", discrep[2], nreps); - flint_printf("Wiedemann did not find full nullspace for %wd/%wd examples\n", discrep[3], nreps); + for(i = 0; i < 6; ++i) + { + flint_printf("Finding nullspace with %s took average time %lf\n", + names[i], elapsed[i]/nreps); + if(discrep[i] > 0) + flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", + discrep[i], nreps); + } return 0; } diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index 5af9c9d401..347e6c6b8e 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -22,162 +22,107 @@ int main(void) { int iter, ret; - int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; - int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; - slong rep, r, c, i, nrep = 100; + slong rep, nreps = 100, r, c, i; TEMPLATE(T, t) a; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, At; TEMPLATE(T, struct) *x, *x2, *b, *Atb, *Ax, *AtAx; - double block_lanczos_elapsed = 0, rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + slong niters[6] = {0, 0, 0, 0, 0, 0}; + slong psol[6] = {0, 0, 0, 0, 0, 0}; + slong nosol[6] = {0, 0, 0, 0, 0, 0}; + double elapsed[6] = {0, 0, 0, 0, 0}; + char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("solving Ax=b...."); fflush(stdout); - for (rep = 0; rep < nrep; rep++) + for (rep = 0; rep < nreps; rep++) { if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); - do c = r = 100 + n_randint(state, 100); - while(c == 0 || r == 0); + c = r = 50 + n_randint(state, 10); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); - TEMPLATE(T, sparse_mat_init) (At, c, r, ctx); x = _TEMPLATE(T, vec_init) (c, ctx); x2 = _TEMPLATE(T, vec_init) (c, ctx); b = _TEMPLATE(T, vec_init) (r, ctx); Ax = _TEMPLATE(T, vec_init) (r, ctx); - AtAx = _TEMPLATE(T, vec_init) (c, ctx); - Atb = _TEMPLATE(T, vec_init) (c, ctx); - - TEMPLATE(T, sparse_mat_randtest) (A, state, c/20, c/10, ctx); - TEMPLATE(T, sparse_mat_transpose) (At, A, ctx); + TEMPLATE(T, sparse_mat_randtest) (A, state, c/10, c/5, ctx); _TEMPLATE(T, vec_randtest) (x, state, c, ctx); TEMPLATE(T, sparse_mat_mul_vec) (b, A, x, ctx); - /* Solve via reduced row echelon form */ - gettimeofday(&start, NULL); - ret = TEMPLATE(T, sparse_mat_solve_rref) (x2, A, b, ctx); - gettimeofday(&end, NULL); - rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) - { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve via lu decomposition */ - gettimeofday(&start, NULL); - ret = TEMPLATE(T, sparse_mat_solve_lu) (x2, A, b, ctx); - gettimeofday(&end, NULL); - lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) - { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve iteratively */ -/**/ gettimeofday(&start, NULL); - ret=TEMPLATE(T, sparse_mat_solve_wiedemann) (x2, A, b, ctx); - gettimeofday(&end, NULL); - wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret == 0) - { - wied_nosol += 1; - } - else - { - TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) - { - flint_printf("FAIL: Ax != b\n"); - abort(); - } - } - gettimeofday(&start, NULL); - iter = 0; - do ret=TEMPLATE(T, sparse_mat_solve_lanczos) (x2, A, b, state, ctx); - while(ret==0 && ++iter < 30); - gettimeofday(&end, NULL); - lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) + for (i = 0; i < 6; ++i) { - nosol += 1; - continue; - } - else - { - niters += iter; - TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - TEMPLATE(T, sparse_mat_mul_vec) (AtAx, At, Ax, ctx); - TEMPLATE(T, sparse_mat_mul_vec) (Atb, At, b, ctx); - if (!_TEMPLATE(T, vec_equal) (AtAx, Atb, A->c, ctx)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); - abort(); - } - else if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + iter = 0; + gettimeofday(&start, NULL); + switch (i) { - psolved += 1; + case 0: ret = TEMPLATE(T, sparse_mat_solve_rref) (x2, A, b, ctx); break; + case 1: ret = TEMPLATE(T, sparse_mat_solve_lu) (x2, A, b, ctx); break; + case 2: do ret = TEMPLATE(T, sparse_mat_solve_lanczos) (x2, A, b, state, ctx); while(ret == 0 && ++iter < 3); break; + case 3: do ret = TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, A, b, 8, state, ctx); while(ret == 0 && ++iter < 3); break; + case 4: ret = TEMPLATE(T, sparse_mat_solve_wiedemann) (x2, A, b, ctx); break; + case 5: do ret = TEMPLATE(T, sparse_mat_solve_block_wiedemann) (x2, A, b, 8, state, ctx); while(ret == 0 && ++iter < 3); break; } - } - - gettimeofday(&start, NULL); - iter = 0; - do ret=TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, A, b, 8, state, ctx); - while(ret==0 && ++iter < 30); - gettimeofday(&end, NULL); - block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) - { - block_lanczos_nosol += 1; - continue; - } - else - { - block_lanczos_niters += iter; - TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); - TEMPLATE(T, sparse_mat_mul_vec) (AtAx, At, Ax, ctx); - TEMPLATE(T, sparse_mat_mul_vec) (Atb, At, b, ctx); - if (!_TEMPLATE(T, vec_equal) (AtAx, Atb, A->c, ctx)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); - abort(); - } - else if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) nosol[i] += 1; + else { - psolved += 1; + niters[i] += iter; + TEMPLATE(T, sparse_mat_mul_vec) (Ax, A, x2, ctx); + if (!_TEMPLATE(T, vec_equal) (b, Ax, A->r, ctx)) + { + if (i == 2 || i == 3) + { + TEMPLATE(T, sparse_mat_init) (At, c, r, ctx); + AtAx = _TEMPLATE(T, vec_init) (c, ctx); + Atb = _TEMPLATE(T, vec_init) (c, ctx); + TEMPLATE(T, sparse_mat_transpose) (At, A, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (AtAx, At, Ax, ctx); + TEMPLATE(T, sparse_mat_mul_vec) (Atb, At, b, ctx); + if (!_TEMPLATE(T, vec_equal) (AtAx, Atb, A->c, ctx)) + { + flint_printf("FAIL on %s: AtAx != Atb\n", names[i]); + abort(); + } + else psol[i] += 1; + _TEMPLATE(T, vec_clear) (AtAx, c, ctx); + _TEMPLATE(T, vec_clear) (Atb, c, ctx); + TEMPLATE(T, sparse_mat_clear) (At, ctx); + } + else + { + flint_printf("FAIL on %s: Ax != b\n", names[i]); + abort(); + } + } } } - _TEMPLATE(T, vec_clear) (x, c, ctx); _TEMPLATE(T, vec_clear) (x2, c, ctx); _TEMPLATE(T, vec_clear) (b, r, ctx); _TEMPLATE(T, vec_clear) (Ax, r, ctx); - _TEMPLATE(T, vec_clear) (AtAx, c, ctx); - _TEMPLATE(T, vec_clear) (Atb, c, ctx); TEMPLATE(T, sparse_mat_clear) (A, ctx); - TEMPLATE(T, sparse_mat_clear) (At, ctx); TEMPLATE(T, ctx_clear) (ctx); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); - flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); - flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); - flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); - flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); - flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); - flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); - flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); + for (i = 0; i < 6; ++i) + { + flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + if (nosol[i]) + flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); + if (psol[i]) + flint_printf("\tFound pseudo-solution for %wd/%wd examples\n", psol[i], nreps); + if (niters[i]) + flint_printf("\tRequired %f extra iters per solution (on average).\n", (double)niters[i]/nreps); + } return 0; } diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index afacbec6c3..bbc9c5af06 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -251,7 +251,7 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M { _nmod_vec_sub(x, x, x2, M->c, M->mod); nmod_sparse_mat_mul_vec(b, M, x); - ret = _nmod_vec_is_zero(x, M->c) || !_nmod_vec_is_zero(b, M->r); + ret = !_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(b, M->r); } _nmod_vec_clear(x2); _nmod_vec_clear(b); diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index 1de1b03ac0..135813588b 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -20,10 +20,10 @@ static void make_block_sequences(nmod_mat_struct *S, slong ns, const nmod_sparse { slong iter, i, j, k, b = Y->c; nmod_mat_struct W[2]; - for (i = 0; i < 2; ++i) nmod_mat_window_init(&W[i], Y, 0, 0, b, b); + for (i = 0; i < 2; ++i) nmod_mat_window_init(&W[i], &Y[i], 0, 0, b, b); for (i = iter = 0; iter < ns; ++iter, i = 1-i) { - if (i > 0) nmod_sparse_mat_mul_mat(&Y[i], M, &Y[1-i]); + if (iter > 0) nmod_sparse_mat_mul_mat(&Y[i], M, &Y[1-i]); nmod_mat_transpose(&S[iter], &W[i]); } for (i = 0; i < 2; ++i) nmod_mat_window_clear(&W[i]); @@ -57,7 +57,9 @@ static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) pr = b + pc; for (r = 0; r < b; r++) if(gamma[r] && M->rows[r][pc] && d[r] < d[pr]) pr = r; - + if(M->rows[pr][pc] == UWORD(0)) continue; + + /* Try to move pivot row to appropriate position (if not already there) */ if (pr != b + pc) { @@ -71,7 +73,7 @@ static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) cinv = nmod_inv(M->rows[pr][pc], M->mod); /* Do Gaussian elimination on first b rows */ - for (r = 0; r < b; ++k) + for (r = 0; r < b; ++r) if(gamma[r] && M->rows[r][pc]) _nmod_vec_scalar_addmul_nmod(M->rows[r], M->rows[pr], M->c, nmod_neg(nmod_mul(M->rows[r][pc], cinv, M->mod), M->mod), M->mod); @@ -104,24 +106,25 @@ static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) * - the first b are the current (reversed) generating polynomials * - the last b are certain auxiliary polynomials. **/ -static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n) +static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n, slong delta) { int ret; slong t, sigma, beta, mu; slong i, j, k, r, b = S->r; slong f_len; nmod_mat_struct *F; - nmod_mat_t M, D, tau; + nmod_mat_t M, D, tau, tmp; f_len = 1; - F = flint_malloc(n*sizeof(*F)); + F = flint_malloc((n+1)*sizeof(*F)); nmod_mat_init(&F[0], 2*b, b, S->mod.n); + nmod_mat_init(tmp, b, b, S->mod.n); for (i = 0; i < b; ++i) d[i] = 0, d[b + i] = 1, F[0].rows[i][i] = 1; /* [ D | I ] -> [ ? | tau ]*/ nmod_mat_init(M, 2*b, 3*b, S->mod.n); - for (t = 0; (ret = coppersmith_stopping_criterion(d, n, b)) == -1; ++t) + for (t = 0, ret = -1; t < n && ret == -1; ++t) { /* Compute discrepancy matrix and tau */ nmod_mat_window_init(D, M, 0, 0, 2*b, b); @@ -140,62 +143,61 @@ static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n) nmod_mat_mul(&F[k], tau, &F[k-1]); /* Every row multiplied by x */ for (k = 0; k < f_len; ++k) for (r = 0; r < b; ++r) /* Divide first b rows by x */ - (k < f_len - 1) ? _nmod_vec_set(F[k].rows[r], F[k+1].rows[r], b) : _nmod_vec_zero(F[k].rows[r], b); - for (r = b; r < 2*b; ++r) d[r] += 1; + { + if (k < f_len - 1) _nmod_vec_set(F[k].rows[r], F[k+1].rows[r], b); + else _nmod_vec_zero(F[k].rows[r], b); + } + for (r = b; r < 2*b; ++r) _nmod_vec_zero(F[0].rows[r], b), d[r] += 1; nmod_mat_window_clear(tau); + ret = coppersmith_stopping_criterion(d, delta, b); } /* Copy C to S, with each row reversed according to its degree */ for (r = 0; r < b; ++r) for (k = 0; k <= d[r]; k++) - _nmod_vec_set(S[d[r] - k].rows[r], F[k].rows[r], b); - - for (k = 0; k < f_len; ++k) nmod_mat_clear(&F[i]); + _nmod_vec_set(S[k].rows[r], F[d[r]-k].rows[r], b); + + for (k = 0; k < f_len; ++k) nmod_mat_clear(&F[k]); nmod_mat_clear(M); flint_free(F); - flint_free(d); return ret; } static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, const nmod_sparse_mat_t M, nmod_mat_struct Z[2], slong l) { - slong i, iter, k, nu, b = S->r; - slong *dd; - mp_ptr v, xi; + slong i, iter, b = S->r; + slong dd; + mp_ptr xi; - /* Compute differences between nominal and real degrees of each coordinate polynomial in row l */ - dd = flint_malloc(b*sizeof(*dd)); - for (nu = 0; nu < b; nu++); - for (dd[nu] = 0; dd[nu] <= d[l]; ++dd[nu]) - if(S[dd[nu]].rows[l][nu]) break; + /* Compute differences between nominal and real degree */ + dd = 0; + while (_nmod_vec_is_zero(S[dd].rows[l], b)) ++dd; /* Simulaneously apply all polynomials in row l to iteration of M on Z */ - v = _nmod_vec_init(b); xi = _nmod_vec_init(M->c); - _nmod_vec_zero(x, M->r); - for (i = iter = 0; iter < d[l]; ++iter, i = 1 - i) + _nmod_vec_zero(x, M->c); + for (i = iter = 0; iter <= d[l]; ++iter, i = 1 - i) { if(iter > 0) nmod_sparse_mat_mul_mat(&Z[i], M, &Z[1-i]); - for (nu = 0; nu < b; nu++) - v[nu] = (dd[nu] <= d[l]) ? S[dd[nu]++].rows[l][nu] : UWORD(0); - nmod_sparse_mat_mul_vec(xi, M, v); + nmod_mat_mul_vec(xi, &Z[i], S[dd + iter].rows[l]); _nmod_vec_add(x, x, xi, M->c, M->mod); } - _nmod_vec_clear(v); _nmod_vec_clear(xi); - flint_free(dd); } int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state) { - int good = 0; + int good = 0, ret; slong i; mp_ptr x1; nmod_sparse_vec_t z; nmod_sparse_mat_t Mb; - nmod_sparse_vec_struct *row; - nmod_sparse_entry_struct *le, *re; if (M->r != M->c) return 0; /* TODO */ + if (_nmod_vec_is_zero(b, M->c)) + { + _nmod_vec_zero(x, M->c); + return 1; + } /* TODO: Precondition M */ x1 = _nmod_vec_init(M->c + 1); @@ -204,12 +206,15 @@ int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, c nmod_sparse_mat_set(Mb, M); nmod_sparse_mat_append_col(Mb, b); nmod_sparse_mat_append_row(Mb, z); - nmod_sparse_mat_nullvector_block_wiedemann(x1, Mb, block_size, state); + + ret = nmod_sparse_mat_nullvector_block_wiedemann(x1, Mb, block_size, state); + if(ret && x1[M->c] != UWORD(0)) + { + _nmod_vec_scalar_mul_nmod(x, x1, M->c, nmod_neg(nmod_inv(x1[M->c], M->mod), M->mod), M->mod); + good = 1; + } nmod_sparse_vec_clear(z); nmod_sparse_mat_clear(Mb); - - if(x1[M->c]) - memcpy(x, x1, M->c*sizeof(*x)), good = 1; _nmod_vec_clear(x1); return good; } @@ -217,7 +222,7 @@ int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, c int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) { int ret = 0; - slong l, ns; + slong l, ns, k; slong *d; mp_ptr b; nmod_mat_t Z; @@ -225,21 +230,24 @@ int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t if (M->r != M->c) return 0; /* TODO */ ns = 2*M->r/block_size + 3; /* Maybe 5? */ + S = flint_malloc(ns*sizeof(*S)); d = flint_calloc(2*block_size, sizeof(*d)); b = _nmod_vec_init(M->r); - for (l = 0; l < 3; ++l) - nmod_mat_init(&Y[l], M->c, block_size, M->mod.n); - nmod_mat_randtest(&Y[0], state); + for (k = 0; k < ns; ++k) nmod_mat_init(&S[k], block_size, block_size, M->mod.n); + for (l = 0; l < 3; ++l) nmod_mat_init(&Y[l], M->c, block_size, M->mod.n); + do nmod_mat_randfull(&Y[0], state); + while(nmod_mat_is_zero(&Y[0])); + nmod_sparse_mat_mul_mat(&Y[1], M, &Y[0]); make_block_sequences(S, ns, M, &Y[1]); - find_block_min_poly(S, d, ns); + find_block_min_poly(S, d, ns, M->r); for (l = 0; l < block_size; ++l) { nmod_mat_set(&Y[1], &Y[0]); make_block_sum(x, S, d, M, Y + 1, l); nmod_sparse_mat_mul_vec(b, M, x); - if (_nmod_vec_is_zero(b, M->r)) {ret = 1; break;}; + if (!_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(b, M->r)) {ret = 1; break;}; } return ret; } diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index bd53456b8b..ae52186693 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -27,6 +27,7 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ mp_limb_t vtAv[2], AvtAv, vMtb, alpha, beta; _nmod_vec_zero(x, M->c); + if (_nmod_vec_is_zero(b, M->c)) return 1; /* Construct transpose */ nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 63c22cff00..ea7f4c2e25 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -23,6 +23,12 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b slong rk, *P, *Q, i, j; nmod_sparse_mat_t L, U; mp_ptr bp, y, xp; + if (_nmod_vec_is_zero(b, M->c)) + { + _nmod_vec_zero(x, M->c); + return 1; + } + P = flint_malloc(M->r * sizeof(*P)); Q = flint_malloc(M->c * sizeof(*Q)); nmod_sparse_mat_init(L, M->r, M->c, M->mod); diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c index 9075fba35c..63b3afb322 100644 --- a/nmod_sparse_mat/solve_rref.c +++ b/nmod_sparse_mat/solve_rref.c @@ -23,6 +23,12 @@ int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr nmod_sparse_mat_t Mb; nmod_sparse_vec_struct *row; nmod_sparse_entry_struct *le, *re; + if (_nmod_vec_is_zero(b, M->c)) + { + _nmod_vec_zero(x, M->c); + return 1; + } + nmod_sparse_mat_init(Mb, M->r, M->c, M->mod); nmod_sparse_mat_set(Mb, M); nmod_sparse_mat_append_col(Mb, b); @@ -43,4 +49,5 @@ int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr if (re->ind==M->c) {x[le->ind] = re->val;} } nmod_sparse_mat_clear(Mb); + return good; } diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index 5d53d84ee4..f359ca5170 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -59,105 +59,110 @@ static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) return L; } -/* Compute s_ij=(A^j y)_i for i = 0,...,ns-1, j = 0,...,num-1*/ -static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse_mat_t A, mp_srcptr b) +/* Compute s_ij=(M^j y)_i for i = 0,...,ns-1, j = 0,...,num-1*/ +static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse_mat_t M, mp_srcptr b) { slong i, j; - mp_ptr y, Ay; - y = _nmod_vec_init(A->r); - Ay = _nmod_vec_init(A->r); - memcpy(y, b, A->r*sizeof(*y)); + mp_ptr y, My; + y = _nmod_vec_init(M->r); + My = _nmod_vec_init(M->r); + memcpy(y, b, M->r*sizeof(*y)); for (j = 0; j < len; ++j) { - if(j > 0) nmod_sparse_mat_mul_vec(Ay, A, y), memcpy(y, Ay, A->r*sizeof(*y)); + if(j > 0) nmod_sparse_mat_mul_vec(My, M, y), memcpy(y, My, M->r*sizeof(*y)); for (i = 0; i < ns; ++i) s[i][j] = y[i]; } _nmod_vec_clear(y); - _nmod_vec_clear(Ay); + _nmod_vec_clear(My); } -/* Compute x = \Sigma_{i = 0}^{L-1} s_i * A^i * b = 0 */ -static void make_sum(mp_ptr x, mp_limb_t *s, slong L, const nmod_sparse_mat_t A, mp_srcptr b) +/* Compute x = \Sigma_{i = 0}^{L-1} s_i * M^i * b = 0 */ +static void make_sum(mp_ptr x, mp_limb_t *s, slong L, const nmod_sparse_mat_t M, mp_srcptr b) { slong i; - mp_ptr y, Ay; - y = _nmod_vec_init(A->r); - Ay = _nmod_vec_init(A->r); - memcpy(y, b, A->r*sizeof(*y)); - _nmod_vec_scalar_mul_nmod(x, b, A->r, s[0], A->mod); + mp_ptr y, My; + y = _nmod_vec_init(M->r); + My = _nmod_vec_init(M->r); + memcpy(y, b, M->r*sizeof(*y)); + _nmod_vec_scalar_mul_nmod(x, b, M->r, s[0], M->mod); for (i = 1; i < L; ++i) { - nmod_sparse_mat_mul_vec(Ay, A, y), memcpy(y, Ay, A->r*sizeof(*y)); - _nmod_vec_scalar_addmul_nmod(x, y, A->r, s[i], A->mod); + nmod_sparse_mat_mul_vec(My, M, y), memcpy(y, My, M->r*sizeof(*y)); + _nmod_vec_scalar_addmul_nmod(x, y, M->r, s[i], M->mod); } _nmod_vec_clear(y); - _nmod_vec_clear(Ay); + _nmod_vec_clear(My); } -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b) +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) { - slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + slong i, L, ret = 0, ns = FLINT_MIN(M->r, 2), len = 2*M->r + 1; mp_limb_t **s; - mp_ptr Ax; - if(A->r != A->c) return 0; /* TBD: reduce to square */ + mp_ptr Mx; + if(M->r != M->c) return 0; /* TBD: reduce to square */ + if (_nmod_vec_is_zero(b, M->c)) + { + _nmod_vec_zero(x, M->c); + return 1; + } - Ax = _nmod_vec_init(A->r); + Mx = _nmod_vec_init(M->r); s = flint_malloc(ns * sizeof(*s)); for (i = 0; i < ns; ++i) s[i] = flint_malloc(len*sizeof(*s[i])); - make_sequences(s, ns, len, A, b); + make_sequences(s, ns, len, M, b); /* Don't have block Berlekamp yet, just try each one */ for (i = 0; i < ns && ret == 0; ++i) { /* Get minimal polynomial */ - L = find_min_poly(s[i], len, A->mod); + L = find_min_poly(s[i], len, M->mod); if(s[i][0]==0) continue; - /* If \sum_{j = 0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j = 0}^{L-1} s_i(j-1) A^jb solves Ax = b */ - make_sum(x, s[i]+1, L, A, b); - _nmod_vec_scalar_mul_nmod(x, x, A->r, nmod_neg(nmod_inv(s[i][0], A->mod), A->mod), A->mod); + /* If \sum_{j = 0}^L s_ijM^jb = 0 => x = -1/s[0]\sum_{j = 0}^{L-1} s_i(j-1) M^jb solves Mx = b */ + make_sum(x, s[i]+1, L, M, b); + _nmod_vec_scalar_mul_nmod(x, x, M->r, nmod_neg(nmod_inv(s[i][0], M->mod), M->mod), M->mod); /* Check if successful */ - nmod_sparse_mat_mul_vec(Ax, A, x); - ret = _nmod_vec_equal(Ax, b, A->r); + nmod_sparse_mat_mul_vec(Mx, M, x); + ret = _nmod_vec_equal(Mx, b, M->r); } - _nmod_vec_clear(Ax); + _nmod_vec_clear(Mx); for (i = 0; i < ns; ++i) flint_free(s[i]); flint_free(s); return ret; } -int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) { - slong i, L, ret = 0, ns = FLINT_MIN(A->r, 2), len = 2*A->r + 1; + slong i, L, ret = 0, ns = FLINT_MIN(M->r, 2), len = 2*M->r + 1; mp_limb_t **s; - mp_ptr Ax, b; - Ax = _nmod_vec_init(A->r); - b = _nmod_vec_init(A->r); + mp_ptr Mx, b; + Mx = _nmod_vec_init(M->r); + b = _nmod_vec_init(M->r); s = flint_malloc(ns * sizeof(*s)); for (i = 0; i < ns; ++i) s[i] = flint_malloc(len*sizeof(*s[i])); - _nmod_vec_randtest(x, state, A->r, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); + _nmod_vec_randtest(x, state, M->r, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); - if(A->r != A->c) return 0; /* TBD: reduce to square */ - make_sequences(s, ns, len, A, b); + if(M->r != M->c) return 0; /* TBD: reduce to square */ + make_sequences(s, ns, len, M, b); for (i = 0; i < ns && ret == 0; ++i) { /* Get minimal polynomial */ - L = find_min_poly(s[i], len, A->mod); + L = find_min_poly(s[i], len, M->mod); - /* \sum_{j = 0}^L s_ijA^jb = 0 => x = \sum_{j = 0}^L s_ijA^jx solves Ax = 0 */ - make_sum(x, s[i], L+1, A, x); - nmod_sparse_mat_mul_vec(Ax, A, x); - ret = _nmod_vec_is_zero(Ax, A->r); + /* \sum_{j = 0}^L s_ijM^jb = 0 => x = \sum_{j = 0}^L s_ijM^jx solves Mx = 0 */ + make_sum(x, s[i], L+1, M, x); + nmod_sparse_mat_mul_vec(Mx, M, x); + ret = !_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(Mx, M->r); } - _nmod_vec_clear(Ax); + _nmod_vec_clear(Mx); _nmod_vec_clear(b); for (i = 0; i < ns; ++i) flint_free(s[i]); flint_free(s); diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c index 17ba11a8c8..0084dc0180 100644 --- a/nmod_sparse_mat/test/t-nullspace.c +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -22,30 +22,31 @@ int main(void) { int iter, ret; - slong rep, nreps = 100, r, c, i, lanczos_discrep = 0, wied_discrep = 0; + slong rep, nreps = 100, r, c, i; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A; nmod_mat_t X, AX; - slong rk[3]; - double elapsed[4] = {0, 0, 0, 0}; + slong rk[6]; + double elapsed[6] = {0, 0, 0, 0, 0, 0}; + slong discrep[6] = {0, 0, 0, 0, 0, 0}; + char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("finding nullspace of A...."); fflush(stdout); - for (rep = 0; rep < nreps; rep++) + for (rep = 0; rep < nreps; ++rep) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - r = n_randint(state, 500); - c = r + n_randint(state, 10); + c = r = 200 + n_randint(state, 100); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_randtest(A, state, c/20, c/10); - for (i = 0; i < 4; ++i) + for (i = 0; i < 6; ++i) { gettimeofday(&start, NULL); switch (i) @@ -53,8 +54,11 @@ main(void) case 0: rk[0] = nmod_sparse_mat_nullspace_rref(X, A); break; case 1: rk[1] = nmod_sparse_mat_nullspace_lu(X, A); break; case 2: rk[2] = nmod_sparse_mat_nullspace_lanczos(X, A, state, 2); break; - case 3: rk[3] = nmod_sparse_mat_nullspace_wiedemann(X, A, state, 2); break; + case 3: rk[3] = nmod_sparse_mat_nullspace_block_lanczos(X, A, 8, state, 2); break; + case 4: rk[4] = nmod_sparse_mat_nullspace_wiedemann(X, A, state, 2); break; + case 5: rk[5] = nmod_sparse_mat_nullspace_block_wiedemann(X, A, 8, state, 2); break; } + //if (i == 0 && rk[0] == UWORD(0) ) { nmod_mat_clear(X); break;} gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); if(X->c==0) continue; @@ -63,21 +67,14 @@ main(void) /*nmod_mat_print_pretty(AX); */ if (!nmod_mat_is_zero(AX)) { - flint_printf("FAIL: %d!\n", i); + flint_printf("FAIL: %s!\n", names[i]); if (i != 0) flint_printf("Nullity should be %wd\n", rk[i-1]); nmod_sparse_mat_print_pretty(A); nmod_mat_print_pretty(X); abort(); } - if (i == 2 && rk[i] != rk[0]) - { - lanczos_discrep += 1; - } - if (i == 3 && rk[i] != rk[0]) - { - wied_discrep += 1; - } + if(rk[i] != rk[0]) discrep[i] += 1; nmod_mat_clear(X); nmod_mat_clear(AX); @@ -87,11 +84,13 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for rref: %lf\n", elapsed[0]/nreps); - flint_printf("Average time for LU: %lf\n", elapsed[1]/nreps); - flint_printf("Average time for Lanzcos: %lf\n", elapsed[2]/nreps); - flint_printf("Average time for Wiedemann: %lf\n", elapsed[3]/nreps); - flint_printf("Lanczos did not find full nullspace for %wd/%wd examples\n", lanczos_discrep, nreps); - flint_printf("Wiedemann did not find full nullspace for %wd/%wd examples\n", lanczos_discrep, nreps); + for(i = 0; i < 6; ++i) + { + flint_printf("Finding nullspace with %s took average time %lf\n", + names[i], elapsed[i]/nreps); + if(discrep[i] > 0) + flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", + discrep[i], nreps); + } return 0; } diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 43d4697b06..9e29833e13 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -22,166 +22,119 @@ int main(void) { int iter, ret; - int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; - int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; - slong rep, r, c, i, nrep = 100; + slong rep, nreps = 100, r, c, i; mp_limb_t n, a; nmod_t mod; - nmod_sparse_mat_t A, At; nmod_mat_t dA; + nmod_sparse_mat_t A, At; mp_ptr x, x2, b, Atb, Ax, AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; - double block_lanczos_elapsed = 0, block_wiedemann_elapsed = 0, wiedemann_elapsed = 0; + slong niters[6] = {0, 0, 0, 0, 0, 0}; + slong psol[6] = {0, 0, 0, 0, 0, 0}; + slong nosol[6] = {0, 0, 0, 0, 0, 0}; + double elapsed[6] = {0, 0, 0, 0, 0}; + char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("solving Ax = b...."); fflush(stdout); - for (rep = 0; rep < nrep; rep++) + for (rep = 0; rep < nreps; rep++) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - c = r = 500 + n_randint(state, 100); - + c = r = 100 + n_randint(state, 50); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_mat_init(dA, r, c, n); - nmod_sparse_mat_init(At, c, r, mod); - - nmod_sparse_mat_randtest(A, state, c/20, c/10); - nmod_sparse_mat_to_dense(dA, A); - nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); b = _nmod_vec_init(r); Ax = _nmod_vec_init(r); - AtAx = _nmod_vec_init(c); - Atb = _nmod_vec_init(c); + nmod_sparse_mat_randtest(A, state, c/20, c/10); + nmod_sparse_mat_to_dense(dA, A); _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(b, A, x); - /* Solve via reduced row echelon form */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_rref(x2, A, b); - gettimeofday(&end, NULL); - rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - nmod_sparse_mat_mul_vec(Ax, A, x2); - if(!_nmod_vec_equal(b, Ax, A->r)) + for (i = 0; i < 6; ++i) { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve via lu decomposition */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_lu(x2, A, b); - gettimeofday(&end, NULL); - lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - nmod_sparse_mat_mul_vec(Ax, A, x2); - if(!_nmod_vec_equal(b, Ax, A->r)) - { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve iteratively */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); - gettimeofday(&end, NULL); - wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret == 0) - { - wied_nosol += 1; - } - else - { - nmod_sparse_mat_mul_vec(Ax, A, x2); - if (!_nmod_vec_equal(b, Ax, A->r)) + iter = 0; + gettimeofday(&start, NULL); + switch (i) { - flint_printf("FAIL: Ax != b\n"); - abort(); + case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; + case 1: ret = nmod_sparse_mat_solve_lu(x2, A, b); break; + case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret == 0 && ++iter < 30); break; + case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while(ret == 0 && ++iter < 30); break; + case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; + case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; } - } - - gettimeofday(&start, NULL); - iter = 0; - do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); - while(ret==0 && ++iter < 30); - gettimeofday(&end, NULL); - lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) - { - nosol += 1; - continue; - } - else - { - niters += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", 5, ret); - abort(); - } - else if (!_nmod_vec_equal(b, Ax, A->r)) + gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) nosol[i] += 1; + else { - psolved += 1; + niters[i] += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + if (!_nmod_vec_equal(b, Ax, A->r)) + { + if (i == 2 || i == 3) + { + nmod_sparse_mat_init(At, c, r, mod); + AtAx = _nmod_vec_init(c); + Atb = _nmod_vec_init(c); + nmod_sparse_mat_transpose(At, A); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL on %s: AtAx != Atb\n", names[i]); + abort(); + } + else psol[i] += 1; + flint_free(AtAx); + flint_free(Atb); + nmod_sparse_mat_clear(At); + } + else + { + flint_printf("FAIL on %s: Ax != b\n", names[i]); + flint_printf("A = "); + nmod_sparse_mat_print_pretty(A); + flint_printf("x = "); + _nmod_vec_print_pretty(x, c, mod); + flint_printf("x2 = "); + _nmod_vec_print_pretty(x2, c, mod); + flint_printf("Ax2 = "); + _nmod_vec_print_pretty(Ax, r, mod); + flint_printf("b = "); + _nmod_vec_print_pretty(b, r, mod); + abort(); + } + } } } - - gettimeofday(&start, NULL); - iter = 0; - do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); - while(ret==0 && ++iter < 10); - gettimeofday(&end, NULL); - block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) - { - block_lanczos_nosol += 1; - continue; - } - else - { - block_lanczos_niters += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); - abort(); - } - else if (!_nmod_vec_equal(b, Ax, A->r)) - { - block_lanczos_psolved += 1; - } - } - flint_free(x); flint_free(x2); flint_free(b); flint_free(Ax); - flint_free(AtAx); - flint_free(Atb); nmod_sparse_mat_clear(A); - nmod_sparse_mat_clear(At); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); - flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); - flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); - flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); - flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); - flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); - flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); - flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); + for (i = 0; i < 6; ++i) + { + flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + if (nosol[i]) + flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); + if (psol[i]) + flint_printf("\tFound pseudo-solution for %wd/%wd examples\n", psol[i], nreps); + if (niters[i]) + flint_printf("\tRequired %f extra iters per solution (on average).\n", (double)niters[i]/nreps); + } return 0; } From cd80b7a8140074e818650bbbdcd01ba83003e886 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 9 Apr 2020 22:28:24 -0700 Subject: [PATCH 19/42] Added rst documentation for sparse vectors and matrices --- doc/source/fq_nmod_sparse_mat.rst | 295 +++++++++++++++++++ doc/source/fq_nmod_sparse_vec.rst | 176 ++++++++++++ doc/source/fq_sparse_mat.rst | 295 +++++++++++++++++++ doc/source/fq_sparse_vec.rst | 176 ++++++++++++ doc/source/fq_zech_sparse_mat.rst | 295 +++++++++++++++++++ doc/source/fq_zech_sparse_vec.rst | 176 ++++++++++++ doc/source/nmod_sparse_mat.rst | 296 ++++++++++++++++++++ doc/source/nmod_sparse_vec.rst | 176 ++++++++++++ fq_sparse_mat_templates.h | 63 ++--- fq_sparse_mat_templates/lu.c | 6 +- fq_sparse_mat_templates/nullspace_lu.c | 2 +- fq_sparse_mat_templates/rref.c | 8 +- fq_sparse_mat_templates/test/t-scalar_mul.c | 8 +- fq_sparse_vec_templates.h | 49 ++-- fq_sparse_vec_templates/scalar_addmul.c | 4 +- fq_sparse_vec_templates/scalar_submul.c | 73 +++++ fq_sparse_vec_templates/test/t-scalar_mul.c | 12 +- nmod_sparse_mat.h | 60 ++-- nmod_sparse_mat/lu.c | 12 +- nmod_sparse_mat/nullspace_lu.c | 2 +- nmod_sparse_mat/rref.c | 14 +- nmod_sparse_mat/solve_block_wiedemann.c | 2 +- nmod_sparse_mat/solve_lanczos.c | 2 +- nmod_sparse_mat/solve_lu.c | 2 +- nmod_sparse_mat/solve_rref.c | 4 +- nmod_sparse_mat/solve_wiedemann.c | 2 +- nmod_sparse_mat/test/t-lu.c | 4 +- nmod_sparse_mat/test/t-scalar_mul.c | 8 +- nmod_sparse_vec.h | 43 +-- nmod_sparse_vec/at.c | 6 +- nmod_sparse_vec/scalar_addmul.c | 4 +- nmod_sparse_vec/scalar_mul.c | 2 +- nmod_sparse_vec/test/t-dense.c | 3 +- nmod_sparse_vec/test/t-dot.c | 2 +- nmod_sparse_vec/test/t-scalar_mul.c | 12 +- 35 files changed, 2125 insertions(+), 169 deletions(-) create mode 100644 doc/source/fq_nmod_sparse_mat.rst create mode 100644 doc/source/fq_nmod_sparse_vec.rst create mode 100644 doc/source/fq_sparse_mat.rst create mode 100644 doc/source/fq_sparse_vec.rst create mode 100644 doc/source/fq_zech_sparse_mat.rst create mode 100644 doc/source/fq_zech_sparse_vec.rst create mode 100644 doc/source/nmod_sparse_mat.rst create mode 100644 doc/source/nmod_sparse_vec.rst create mode 100644 fq_sparse_vec_templates/scalar_submul.c diff --git a/doc/source/fq_nmod_sparse_mat.rst b/doc/source/fq_nmod_sparse_mat.rst new file mode 100644 index 0000000000..ab7f04ac78 --- /dev/null +++ b/doc/source/fq_nmod_sparse_mat.rst @@ -0,0 +1,295 @@ +.. _fq-nmod-sparse-mat: + +**fq_nmod_sparse_mat.h** -- sparse matrixs over finite fields (word-size characteristic) +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_nmod_sparse_mat_t + + Holds an array of (possibly empty) sparse vectors corresponding to rows in + the matrix + +Memory management +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_init(fq_nmod_sparse_mat_t M, slong rows, slong cols, const fq_nmod_ctx_t ctx) + + Initializes an empty sparse matrix ``M`` with given number of rows and columns + +.. function:: void fq_nmod_sparse_mat_clear(fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Clears the entries of the matrix ``M`` and frees the space allocated for it + +.. function:: void fq_nmod_sparse_mat_swap(fq_nmod_sparse_mat_t M1, fq_nmod_sparse_mat_t M2, const fq_nmod_ctx_t ctx) + + Swaps two matrices ``M1`` and ``M2`` (no reallocaton) + + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_zero(fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Sets matrix ``M`` to zero (the empty sparse matrix) + +.. function:: void fq_nmod_sparse_mat_one(fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Sets matrix ``M`` to identity matrix (based on its number of rows) + +.. function:: void fq_nmod_sparse_mat_set(fq_nmod_sparse_mat_t N, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Makes ``N`` a (deep) copy of ``M`` + +.. function:: void fq_nmod_sparse_mat_from_entries(fq_nmod_sparse_mat_t M, slong *rows, slong *inds, fq_nmod_struct *vals, slong nnz, const fq_nmod_ctx_t ctx) + + Constructs matrix ``M`` from a given sequence of ``rows``, ``cols``, and + corresponding ``vals``, all of length ``nnz``, assumes sorted by rows + with no duplicate (row, col) indices + +.. function:: void fq_nmod_sparse_mat_append_col(fq_nmod_sparse_mat_t M, const fq_nmod_struct *v, const fq_nmod_ctx_t ctx) + + Add a dense column to the right of the matrix + +.. function:: void fq_nmod_sparse_mat_append_row(fq_nmod_sparse_mat_t M, const fq_nmod_sparse_vec_t v, const fq_nmod_ctx_t ctx) + + Add a sparse row to the bottom of the matrix + + +Conversion to/from dense matrix +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_from_dense(fq_nmod_sparse_mat_t M, const fq_nmod_mat_t dM, const fq_nmod_ctx_t ctx) + + Converts the dense matrix ``dM`` to a sparse matrix ``M`` + +.. function:: void fq_nmod_sparse_mat_to_dense(fq_nmod_mat_t dM, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Converts the sparse matrix ``M`` to a dense matrix ``dM`` + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_window_init(fq_nmod_sparse_mat_t window, const fq_nmod_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2, const fq_nmod_ctx_t ctx) + + Constructs a window on the sparse matrix ``M`` between rows ``r1`` and ``r2`` + and cols ``c1`` and ``c2`` (valid as long as original matrix remains unmodified) + +.. function:: void fq_nmod_sparse_mat_window_clear(fq_nmod_sparse_mat_t window, const fq_nmod_ctx_t ctx) + + Clears a window + +.. function:: void fq_nmod_sparse_mat_concat_horizontal(fq_nmod_sparse_mat_t B, const fq_nmod_sparse_mat_t M1, const fq_nmod_sparse_mat_t M2, const fq_nmod_ctx_t ctx) + + Horizontally concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_nmod_sparse_mat_concat_vertical(fq_nmod_sparse_mat_t B, const fq_nmod_sparse_mat_t M1, const fq_nmod_sparse_mat_t M2, const fq_nmod_ctx_t ctx) + + Vertically concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_nmod_sparse_mat_split_horizontal(fq_nmod_sparse_mat_t M1, fq_nmod_sparse_mat_t M2, const fq_nmod_sparse_mat_t B, slong c, const fq_nmod_ctx_t ctx) + + Splits ``B`` horizontally into two submatrices ``M1`` and ``M2``, dividing at column ``c`` + +.. function:: void fq_nmod_sparse_mat_split_vertical(fq_nmod_sparse_mat_t M1, fq_nmod_sparse_mat_t M2, const fq_nmod_sparse_mat_t B, slong r, const fq_nmod_ctx_t ctx) + + Splits ``B`` vertically into two submatrices ``M1`` and ``M2``, dividing at row ``r`` + + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_permute_cols(fq_nmod_sparse_mat_t M, slong *Q, const fq_nmod_ctx_t ctx) + + Permutes the columns indices of ``M`` according to ``Q``, and re-sorts each row + +.. function:: void fq_nmod_sparse_mat_permute_rows(fq_nmod_sparse_mat_t M, slong *P, const fq_nmod_ctx_t ctx) + + Permutes the rows of ``M`` according to ``P`` + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_nmod_sparse_mat_randtest(fq_nmod_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, const fq_nmod_ctx_t ctx) + + Makes ``M`` a sparse matrix with between ``min_nnz`` and ``max_nnz`` nonzero + entries per row, with individual entries generated by fq_nmod_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_print_pretty(const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Prints the matrix ``M`` to ``stdout`` in a human-readable format + + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_is_zero(fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Checks if the given matrix ``M`` is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_nmod_sparse_mat_equal(const fq_nmod_sparse_mat_t M1, const fq_nmod_sparse_mat_t M2, slong ioff, const fq_nmod_ctx_t ctx) + + Checks if ``M1`` equals ``M2``, returning `1` if so and `0` otherwise + + +Transpose +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_transpose(fq_nmod_sparse_mat_t N, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Transposes ``M`` into the matrix ``N`` (must have swapped rows and columns) + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_mat_neg(fq_nmod_sparse_mat_t N, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Sets ``N`` to the negation of ``M`` + +.. function:: void fq_nmod_sparse_mat_scalar_mul_fq_nmod(fq_nmod_sparse_mat_t N, const fq_nmod_sparse_mat_t M, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``N`` to the scalar multiple of ``M`` by ``c`` + +.. function:: void fq_nmod_sparse_mat_add(fq_nmod_sparse_mat_t O, const fq_nmod_sparse_mat_t M, const fq_nmod_sparse_mat_t N, const fq_nmod_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``N`` + +.. function:: void fq_nmod_sparse_mat_sub(fq_nmod_sparse_mat_t O, const fq_nmod_sparse_mat_t M, const fq_nmod_sparse_mat_t N, const fq_nmod_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N`` + +.. function:: void fq_nmod_sparse_mat_scalar_addmul_fq_nmod(fq_nmod_sparse_mat_t O, const fq_nmod_sparse_mat_t M, const fq_nmod_sparse_mat_t N, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``c` times ``N`` + +.. function:: void fq_nmod_sparse_mat_scalar_submul_fq_nmod(fq_nmod_sparse_mat_t O, const fq_nmod_sparse_mat_t M, const fq_nmod_sparse_mat_t N, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N` times ``v`` + +.. function:: void fq_nmod_sparse_mat_mul_vec(fq_nmod_struct *y, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *x, const fq_nmod_ctx_t ctx) + + Sets ``y`` to the product of ``M`` and ``x`` + +.. function:: void fq_nmod_sparse_mat_mul_mat(fq_nmod_mat_t Y, const fq_nmod_sparse_mat_t M, const fq_nmod_mat_t X, const fq_nmod_ctx_t ctx) + + Sets ``Y`` to the product of ``M`` and ``X`` + +.. function:: slong fq_nmod_sparse_mat_inv(fq_nmod_sparse_mat_t N, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Sets ``N`` to the "inverse" of ``M``, i.e., the matrix such that NM is + in reduced row-echelon form + + +Decomposition/reduction +-------------------------------------------------------------------------------- + +.. function:: slong fq_nmod_sparse_mat_lu(slong *P, slong *Q, fq_nmod_sparse_mat_t L, fq_nmod_sparse_mat_t U, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Computes the decomposition PMQ = LU for a given sparse matrix ``M``, where + ``P`` is a row permutation, ``Q`` is a column permutation, ``L``is a lower + triangular matrix, and ``U`` is an upper triangular matrix + +.. function:: void fq_nmod_sparse_mat_rref(fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Applies row reduction to put ``M`` in reduced row echelon form (in place) + +Solving +-------------------------------------------------------------------------------- + +.. function:: int fq_nmod_sparse_mat_solve_lu(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use LU decomposition to find + a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_solve_rref(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the reduced row-echelon + form to find a vector ``x`` such that Mx = b, returns `1` if successful and + `0` if not + +.. function:: int fq_nmod_sparse_mat_solve_lanczos(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Lanczos algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_solve_wiedemann(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Wiedemann algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_solve_block_lanczos(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Lanczos + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_solve_block_wiedemann(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, const fq_nmod_struct *b, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Wiedemann + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +Nullvector and nullspace computation +-------------------------------------------------------------------------------- + +.. function:: int fq_nmod_sparse_mat_nullvector_lanczos(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_nullvector_wiedemann(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_nullvector_block_lanczos(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_nullvector_block_wiedemann(fq_nmod_struct *x, const fq_nmod_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_nmod_sparse_mat_nullspace_rref(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the reduced row echelon form to construct the + nullspace ``X`` of M (initialized by this function), returns the nullity + +.. function:: int fq_nmod_sparse_mat_nullspace_lu(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the LU decomposition to construct the nullspace ``X`` + of M (initialized by this function), returns the nullity + +.. function:: int fq_nmod_sparse_mat_nullspace_lanczos(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_nmod_sparse_mat_nullspace_wiedemann(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_nmod_sparse_mat_nullspace_block_lanczos(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + +.. function:: int fq_nmod_sparse_mat_nullspace_block_wiedemann(fq_nmod_mat_t X, const fq_nmod_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_nmod_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + diff --git a/doc/source/fq_nmod_sparse_vec.rst b/doc/source/fq_nmod_sparse_vec.rst new file mode 100644 index 0000000000..3a96e1e780 --- /dev/null +++ b/doc/source/fq_nmod_sparse_vec.rst @@ -0,0 +1,176 @@ +.. _fq-nmod-sparse-vec: + +**fq_nmod_sparse_vec.h** -- sparse vectors over finite fields (word-size characteristic) +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_nmod_sparse_entry_t + + Holds a pair (ind, val), where ind (of type slong) is an index into the + vector and val (of type fq_nmod_t) is the value at that index + +.. type:: fq_nmod_sparse_vec_t + + Holds an array of nonzero entries (of type sparse_entry_struct *) of + specified length nnz, sorted by ind + +Memory management +-------------------------------------------------------------------------------- + + +.. function:: void fq_nmod_sparse_vec_init(fq_nmod_sparse_vec_t vec, const fq_nmod_ctx_t ctx) + + Initializes an empty sparse vector (no allocation) + +.. function:: void fq_nmod_sparse_vec_clear(fq_nmod_sparse_vec_t vec, slong len, const fq_nmod_ctx_t ctx) + + Clears the entries of vec and frees the space allocated for it + +.. function:: void fq_nmod_sparse_vec_swap(fq_nmod_sparse_vec_t vec1, fq_nmod_sparse_vec_t vec2, const fq_nmod_ctx_t ctx) + + Swaps two vectors (no reallocaton) + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_zero(fq_nmod_sparse_vec_t vec, const fq_nmod_ctx_t ctx) + + Sets vec to zero (the empty sparse vector) + +.. function:: void fq_nmod_sparse_vec_one(fq_nmod_sparse_vec_t vec, slong ind, const fq_nmod_ctx_t ctx) + + Sets vec to the ind-th basis vector (single one in position ind) + +.. function:: void fq_nmod_sparse_vec_set(fq_nmod_sparse_vec_t dst, fq_nmod_sparse_vec_t src, const fq_nmod_ctx_t ctx) + + Makes dst a (deep) copy of src + +.. function:: void fq_nmod_sparse_vec_set_entry(fq_nmod_sparse_vec_t vec, slong ind, const fq_nmod_t val, const fq_nmod_ctx_t ctx) + + Sets the value at index ind to val, either replacing an existing value or extending + the array of entries + +.. function:: void _fq_nmod_sparse_vec_from_entries(fq_nmod_sparse_vec_t vec, slong *inds, fq_nmod_struct *vals, slong nnz, const fq_nmod_ctx_t ctx) + + Constructs vec from a given sequence of indices and associated values, both of length nnz. + Assumes no duplicate indices + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_is_zero(fq_nmod_sparse_vec_t vec, const fq_nmod_ctx_t ctx) + + Checks if the given vector is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_nmod_sparse_vec_equal(const fq_nmod_sparse_vec_t vec1, const fq_nmod_sparse_vec_t vec2, slong ioff, const fq_nmod_ctx_t ctx) + + Checks if vec1 equals vec2 (with s specified column offset ioff), returning + `1` if so and `0` otherwise + +Indexing +-------------------------------------------------------------------------------- + +.. function:: fq_nmod_t * fq_nmod_sparse_vec_at(fq_nmod_sparse_vec_t vec, slong ind, const fq_nmod_ctx_t ctx) + + Returns a pointer to the value at the index ind (or NULL if index not found) + + +Conversion to/from dense vector +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_from_dense(fq_nmod_sparse_vec_t dst, const fq_nmod_struct *src, slong len, const fq_nmod_ctx_t ctx) + + Converts the dense vector src of length len to a sparse vector + +.. function:: void fq_nmod_sparse_vec_to_dense(fq_nmod_struct *dst, const fq_nmod_sparse_vec_t src, slong len, const fq_nmod_ctx_t ctx) + + Converts the sparse vector src to a dense vector of length len + + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_window_init(fq_nmod_sparse_vec_t window, const fq_nmod_sparse_vec_t vec, slong i1, slong i2, const fq_nmod_ctx_t ctx) + + Constructs a window on a the sparse vector vec between indices i1 and i2 + Note that window is only valid as long as original vector remains unmodified + +.. function:: void fq_nmod_sparse_vec_window_clear(fq_nmod_sparse_vec_t window, const fq_nmod_ctx_t ctx) + + Clears a window (for safety only) + +.. function:: void fq_nmod_sparse_vec_concat(fq_nmod_sparse_vec_t res, const fq_nmod_sparse_vec_t vec1, const fq_nmod_sparse_vec_t vec2, slong len1, const fq_nmod_ctx_t ctx) + + Concatenates two vectors vec1 and vec2 into res, with indices of vec2 + offset by len1 + +.. function:: void fq_nmod_sparse_vec_split(fq_nmod_sparse_vec_t res1, fq_nmod_sparse_vec_t res1, const fq_nmod_sparse_vec_t vec, slong ind, const fq_nmod_ctx_t ctx) + + Splits vec into two vectors res1 and res2, with res1 containing all entries + below index ind and res2 containing the rest + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_permute_inds(fq_nmod_sparse_vec_t vec, slong *P, const fq_nmod_ctx_t ctx) + + Permutes the indices of vec according to P, and resorts + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_nmod_sparse_vec_randtest(fq_nmod_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, const fq_nmod_ctx_t ctx) + + Makes vec a sparse vector with nnz nonzero entries uniformly distributed + between 0 and len - 1, with individual entries generated by fq_nmod_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_print_pretty(const fq_nmod_sparse_vec_t vec, slong ioff, slong maxi, const fq_nmod_ctx_t ctx) + + Prints the vector of given length to ``stdout`` in a human-readable format + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_nmod_sparse_vec_neg(fq_nmod_sparse_vec_t v, const fq_nmod_sparse_vec_t u, const fq_nmod_ctx_t ctx) + + Sets ``v`` to the negation of ``u`` + +.. function:: void fq_nmod_sparse_vec_scalar_mul_fq_nmod(fq_nmod_sparse_vec_t v, const fq_nmod_sparse_vec_t u, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``v`` to the scalar multiple of ``u`` by ``c`` + +.. function:: void fq_nmod_sparse_vec_add(fq_nmod_sparse_vec_t w, const fq_nmod_sparse_vec_t u, const fq_nmod_sparse_vec_t v, const fq_nmod_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``v`` + +.. function:: void fq_nmod_sparse_vec_sub(fq_nmod_sparse_vec_t w, const fq_nmod_sparse_vec_t u, const fq_nmod_sparse_vec_t v, const fq_nmod_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``v`` + +.. function:: void fq_nmod_sparse_vec_scalar_addmul_fq_nmod(fq_nmod_sparse_vec_t w, const fq_nmod_sparse_vec_t u, const fq_nmod_sparse_vec_t v, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``c` times ``v`` + +.. function:: void fq_nmod_sparse_vec_scalar_addmul_fq_nmod(fq_nmod_sparse_vec_t w, const fq_nmod_sparse_vec_t u, const fq_nmod_sparse_vec_t v, const fq_nmod_t c, const fq_nmod_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``c` times ``v`` + +.. function:: void fq_nmod_sparse_vec_dot(fq_nmod_t ret, const fq_nmod_sparse_vec_t u, const fq_nmod_sparse_vec_t v, const fq_nmod_ctx_t ctx) + + Sets ``ret`` to the dot product of ``u`` and ``v`` + +.. function:: void fq_nmod_sparse_vec_dot_dense(fq_nmod_t ret, const fq_nmod_sparse_vec_t u, const fq_nmod_struct * v, const fq_nmod_ctx_t ctx) + + Sets ``ret`` to the dot product of (``u``, ``v``) diff --git a/doc/source/fq_sparse_mat.rst b/doc/source/fq_sparse_mat.rst new file mode 100644 index 0000000000..45484a8bc9 --- /dev/null +++ b/doc/source/fq_sparse_mat.rst @@ -0,0 +1,295 @@ +.. _fq-sparse-mat: + +**fq_sparse_mat.h** -- sparse matrixs over finite fields +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_sparse_mat_t + + Holds an array of (possibly empty) sparse vectors corresponding to rows in + the matrix + +Memory management +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_init(fq_sparse_mat_t M, slong rows, slong cols, const fq_ctx_t ctx) + + Initializes an empty sparse matrix ``M`` with given number of rows and columns + +.. function:: void fq_sparse_mat_clear(fq_sparse_mat_t M, const fq_ctx_t ctx) + + Clears the entries of the matrix ``M`` and frees the space allocated for it + +.. function:: void fq_sparse_mat_swap(fq_sparse_mat_t M1, fq_sparse_mat_t M2, const fq_ctx_t ctx) + + Swaps two matrices ``M1`` and ``M2`` (no reallocaton) + + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_zero(fq_sparse_mat_t M, const fq_ctx_t ctx) + + Sets matrix ``M`` to zero (the empty sparse matrix) + +.. function:: void fq_sparse_mat_one(fq_sparse_mat_t M, const fq_ctx_t ctx) + + Sets matrix ``M`` to identity matrix (based on its number of rows) + +.. function:: void fq_sparse_mat_set(fq_sparse_mat_t N, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Makes ``N`` a (deep) copy of ``M`` + +.. function:: void fq_sparse_mat_from_entries(fq_sparse_mat_t M, slong *rows, slong *inds, fq_struct *vals, slong nnz, const fq_ctx_t ctx) + + Constructs matrix ``M`` from a given sequence of ``rows``, ``cols``, and + corresponding ``vals``, all of length ``nnz``, assumes sorted by rows + with no duplicate (row, col) indices + +.. function:: void fq_sparse_mat_append_col(fq_sparse_mat_t M, const fq_struct *v, const fq_ctx_t ctx) + + Add a dense column to the right of the matrix + +.. function:: void fq_sparse_mat_append_row(fq_sparse_mat_t M, const fq_sparse_vec_t v, const fq_ctx_t ctx) + + Add a sparse row to the bottom of the matrix + + +Conversion to/from dense matrix +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_from_dense(fq_sparse_mat_t M, const fq_mat_t dM, const fq_ctx_t ctx) + + Converts the dense matrix ``dM`` to a sparse matrix ``M`` + +.. function:: void fq_sparse_mat_to_dense(fq_mat_t dM, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Converts the sparse matrix ``M`` to a dense matrix ``dM`` + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_window_init(fq_sparse_mat_t window, const fq_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2, const fq_ctx_t ctx) + + Constructs a window on the sparse matrix ``M`` between rows ``r1`` and ``r2`` + and cols ``c1`` and ``c2`` (valid as long as original matrix remains uzechified) + +.. function:: void fq_sparse_mat_window_clear(fq_sparse_mat_t window, const fq_ctx_t ctx) + + Clears a window + +.. function:: void fq_sparse_mat_concat_horizontal(fq_sparse_mat_t B, const fq_sparse_mat_t M1, const fq_sparse_mat_t M2, const fq_ctx_t ctx) + + Horizontally concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_sparse_mat_concat_vertical(fq_sparse_mat_t B, const fq_sparse_mat_t M1, const fq_sparse_mat_t M2, const fq_ctx_t ctx) + + Vertically concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_sparse_mat_split_horizontal(fq_sparse_mat_t M1, fq_sparse_mat_t M2, const fq_sparse_mat_t B, slong c, const fq_ctx_t ctx) + + Splits ``B`` horizontally into two submatrices ``M1`` and ``M2``, dividing at column ``c`` + +.. function:: void fq_sparse_mat_split_vertical(fq_sparse_mat_t M1, fq_sparse_mat_t M2, const fq_sparse_mat_t B, slong r, const fq_ctx_t ctx) + + Splits ``B`` vertically into two submatrices ``M1`` and ``M2``, dividing at row ``r`` + + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_permute_cols(fq_sparse_mat_t M, slong *Q, const fq_ctx_t ctx) + + Permutes the columns indices of ``M`` according to ``Q``, and re-sorts each row + +.. function:: void fq_sparse_mat_permute_rows(fq_sparse_mat_t M, slong *P, const fq_ctx_t ctx) + + Permutes the rows of ``M`` according to ``P`` + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_sparse_mat_randtest(fq_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, const fq_ctx_t ctx) + + Makes ``M`` a sparse matrix with between ``min_nnz`` and ``max_nnz`` nonzero + entries per row, with individual entries generated by fq_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_print_pretty(const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Prints the matrix ``M`` to ``stdout`` in a human-readable format + + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_is_zero(fq_sparse_mat_t M, const fq_ctx_t ctx) + + Checks if the given matrix ``M`` is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_sparse_mat_equal(const fq_sparse_mat_t M1, const fq_sparse_mat_t M2, slong ioff, const fq_ctx_t ctx) + + Checks if ``M1`` equals ``M2``, returning `1` if so and `0` otherwise + + +Transpose +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_transpose(fq_sparse_mat_t N, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Transposes ``M`` into the matrix ``N`` (must have swapped rows and columns) + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_neg(fq_sparse_mat_t N, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Sets ``N`` to the negation of ``M`` + +.. function:: void fq_sparse_mat_scalar_mul_fq(fq_sparse_mat_t N, const fq_sparse_mat_t M, const fq_t c, const fq_ctx_t ctx) + + Sets ``N`` to the scalar multiple of ``M`` by ``c`` + +.. function:: void fq_sparse_mat_add(fq_sparse_mat_t O, const fq_sparse_mat_t M, const fq_sparse_mat_t N, const fq_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``N`` + +.. function:: void fq_sparse_mat_sub(fq_sparse_mat_t O, const fq_sparse_mat_t M, const fq_sparse_mat_t N, const fq_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N`` + +.. function:: void fq_sparse_mat_scalar_addmul_fq(fq_sparse_mat_t O, const fq_sparse_mat_t M, const fq_sparse_mat_t N, const fq_t c, const fq_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``c` times ``N`` + +.. function:: void fq_sparse_mat_scalar_submul_fq(fq_sparse_mat_t O, const fq_sparse_mat_t M, const fq_sparse_mat_t N, const fq_t c, const fq_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N` times ``v`` + +.. function:: void fq_sparse_mat_mul_vec(fq_struct *y, const fq_sparse_mat_t M, const fq_struct *x, const fq_ctx_t ctx) + + Sets ``y`` to the product of ``M`` and ``x`` + +.. function:: void fq_sparse_mat_mul_mat(fq_mat_t Y, const fq_sparse_mat_t M, const fq_mat_t X, const fq_ctx_t ctx) + + Sets ``Y`` to the product of ``M`` and ``X`` + +.. function:: slong fq_sparse_mat_inv(fq_sparse_mat_t N, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Sets ``N`` to the "inverse" of ``M``, i.e., the matrix such that NM is + in reduced row-echelon form + + +Decomposition/reduction +-------------------------------------------------------------------------------- + +.. function:: slong fq_sparse_mat_lu(slong *P, slong *Q, fq_sparse_mat_t L, fq_sparse_mat_t U, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Computes the decomposition PMQ = LU for a given sparse matrix ``M``, where + ``P`` is a row permutation, ``Q`` is a column permutation, ``L``is a lower + triangular matrix, and ``U`` is an upper triangular matrix + +.. function:: void fq_sparse_mat_rref(fq_sparse_mat_t M, const fq_ctx_t ctx) + + Applies row reduction to put ``M`` in reduced row echelon form (in place) + +Solving +-------------------------------------------------------------------------------- + +.. function:: int fq_sparse_mat_solve_lu(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use LU decomposition to find + a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_solve_rref(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the reduced row-echelon + form to find a vector ``x`` such that Mx = b, returns `1` if successful and + `0` if not + +.. function:: int fq_sparse_mat_solve_lanczos(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Lanczos algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_solve_wiedemann(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Wiedemann algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_solve_block_lanczos(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Lanczos + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_solve_block_wiedemann(fq_struct *x, const fq_sparse_mat_t M, const fq_struct *b, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Wiedemann + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +Nullvector and nullspace computation +-------------------------------------------------------------------------------- + +.. function:: int fq_sparse_mat_nullvector_lanczos(fq_struct *x, const fq_sparse_mat_t M, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_nullvector_wiedemann(fq_struct *x, const fq_sparse_mat_t M, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_nullvector_block_lanczos(fq_struct *x, const fq_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_nullvector_block_wiedemann(fq_struct *x, const fq_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_sparse_mat_nullspace_rref(fq_mat_t X, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Given a matrix ``M``, use the reduced row echelon form to construct the + nullspace ``X`` of M (initialized by this function), returns the nullity + +.. function:: int fq_sparse_mat_nullspace_lu(fq_mat_t X, const fq_sparse_mat_t M, const fq_ctx_t ctx) + + Given a matrix ``M``, use the LU decomposition to construct the nullspace ``X`` + of M (initialized by this function), returns the nullity + +.. function:: int fq_sparse_mat_nullspace_lanczos(fq_mat_t X, const fq_sparse_mat_t M, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_sparse_mat_nullspace_wiedemann(fq_mat_t X, const fq_sparse_mat_t M, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_sparse_mat_nullspace_block_lanczos(fq_mat_t X, const fq_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + +.. function:: int fq_sparse_mat_nullspace_block_wiedemann(fq_mat_t X, const fq_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + diff --git a/doc/source/fq_sparse_vec.rst b/doc/source/fq_sparse_vec.rst new file mode 100644 index 0000000000..3be0271f33 --- /dev/null +++ b/doc/source/fq_sparse_vec.rst @@ -0,0 +1,176 @@ +.. _fq-sparse-vec: + +**fq_sparse_vec.h** -- sparse vectors over finite fields +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_sparse_entry_t + + Holds a pair (ind, val), where ind (of type slong) is an index into the + vector and val (of type fq_t) is the value at that index + +.. type:: fq_sparse_vec_t + + Holds an array of nonzero entries (of type sparse_entry_struct *) of + specified length nnz, sorted by ind + +Memory management +-------------------------------------------------------------------------------- + + +.. function:: void fq_sparse_vec_init(fq_sparse_vec_t vec, const fq_ctx_t ctx) + + Initializes an empty sparse vector (no allocation) + +.. function:: void fq_sparse_vec_clear(fq_sparse_vec_t vec, slong len, const fq_ctx_t ctx) + + Clears the entries of vec and frees the space allocated for it + +.. function:: void fq_sparse_vec_swap(fq_sparse_vec_t vec1, fq_sparse_vec_t vec2, const fq_ctx_t ctx) + + Swaps two vectors (no reallocaton) + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_zero(fq_sparse_vec_t vec, const fq_ctx_t ctx) + + Sets vec to zero (the empty sparse vector) + +.. function:: void fq_sparse_vec_one(fq_sparse_vec_t vec, slong ind, const fq_ctx_t ctx) + + Sets vec to the ind-th basis vector (single one in position ind) + +.. function:: void fq_sparse_vec_set(fq_sparse_vec_t dst, fq_sparse_vec_t src, const fq_ctx_t ctx) + + Makes dst a (deep) copy of src + +.. function:: void fq_sparse_vec_set_entry(fq_sparse_vec_t vec, slong ind, const fq_t val, const fq_ctx_t ctx) + + Sets the value at index ind to val, either replacing an existing value or extending + the array of entries + +.. function:: void _fq_sparse_vec_from_entries(fq_sparse_vec_t vec, slong *inds, fq_struct *vals, slong nnz, const fq_ctx_t ctx) + + Constructs vec from a given sequence of indices and associated values, both of length nnz. + Assumes no duplicate indices + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_is_zero(fq_sparse_vec_t vec, const fq_ctx_t ctx) + + Checks if the given vector is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_sparse_vec_equal(const fq_sparse_vec_t vec1, const fq_sparse_vec_t vec2, slong ioff, const fq_ctx_t ctx) + + Checks if vec1 equals vec2 (with s specified column offset ioff), returning + `1` if so and `0` otherwise + +Indexing +-------------------------------------------------------------------------------- + +.. function:: fq_t * fq_sparse_vec_at(const fq_sparse_vec_t vec, slong ind, const fq_ctx_t ctx) + + Returns a pointer to the value at the index ind (or NULL if index not found) + + +Conversion to/from dense vector +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_from_dense(fq_sparse_vec_t dst, const fq_struct *src, slong len, const fq_ctx_t ctx) + + Converts the dense vector src of length len to a sparse vector + +.. function:: void fq_sparse_vec_to_dense(fq_struct *dst, const fq_sparse_vec_t src, slong len, const fq_ctx_t ctx) + + Converts the sparse vector src to a dense vector of length len + + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_window_init(fq_sparse_vec_t window, const fq_sparse_vec_t vec, slong i1, slong i2, const fq_ctx_t ctx) + + Constructs a window on a the sparse vector vec between indices i1 and i2 + Note that window is only valid as long as original vector remains unmodified + +.. function:: void fq_sparse_vec_window_clear(fq_sparse_vec_t window, const fq_ctx_t ctx) + + Clears a window (for safety only) + +.. function:: void fq_sparse_vec_concat(fq_sparse_vec_t res, const fq_sparse_vec_t vec1, const fq_sparse_vec_t vec2, slong len1, const fq_ctx_t ctx) + + Concatenates two vectors vec1 and vec2 into res, with indices of vec2 + offset by len1 + +.. function:: void fq_sparse_vec_split(fq_sparse_vec_t res1, fq_sparse_vec_t res1, const fq_sparse_vec_t vec, slong ind, const fq_ctx_t ctx) + + Splits vec into two vectors res1 and res2, with res1 containing all entries + below index ind and res2 containing the rest + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_permute_inds(fq_sparse_vec_t vec, slong *P, const fq_ctx_t ctx) + + Permutes the indices of vec according to P, and resorts + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_sparse_vec_randtest(fq_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, const fq_ctx_t ctx) + + Makes vec a sparse vector with nnz nonzero entries uniformly distributed + between 0 and len - 1, with individual entries generated by fq_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_print_pretty(const fq_sparse_vec_t vec, slong ioff, slong maxi, const fq_ctx_t ctx) + + Prints the vector of given length to ``stdout`` in a human-readable format + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_vec_neg(fq_sparse_vec_t v, const fq_sparse_vec_t u, const fq_ctx_t ctx) + + Sets ``v`` to the negation of ``u`` + +.. function:: void fq_sparse_vec_scalar_mul_fq(fq_sparse_vec_t v, const fq_sparse_vec_t u, const fq_t c, const fq_ctx_t ctx) + + Sets ``v`` to the scalar multiple of ``u`` by ``c`` + +.. function:: void fq_sparse_vec_add(fq_sparse_vec_t w, const fq_sparse_vec_t u, const fq_sparse_vec_t v, const fq_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``v`` + +.. function:: void fq_sparse_vec_sub(fq_sparse_vec_t w, const fq_sparse_vec_t u, const fq_sparse_vec_t v, const fq_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``v`` + +.. function:: void fq_sparse_vec_scalar_addmul_fq(fq_sparse_vec_t w, const fq_sparse_vec_t u, const fq_sparse_vec_t v, const fq_t c, const fq_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``c` times ``v`` + +.. function:: void fq_sparse_vec_scalar_addmul_fq(fq_sparse_vec_t w, const fq_sparse_vec_t u, const fq_sparse_vec_t v, const fq_t c, const fq_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``c` times ``v`` + +.. function:: void fq_sparse_vec_dot(fq_t ret, const fq_sparse_vec_t u, const fq_sparse_vec_t v, const fq_ctx_t ctx) + + Sets ``ret`` to the dot product of ``u`` and ``v`` + +.. function:: void fq_sparse_vec_dot_dense(fq_t ret, const fq_sparse_vec_t u, const fq_struct * v, const fq_ctx_t ctx) + + Sets ``ret`` to the dot product of (``u``, ``v``) diff --git a/doc/source/fq_zech_sparse_mat.rst b/doc/source/fq_zech_sparse_mat.rst new file mode 100644 index 0000000000..f7f5db6f4a --- /dev/null +++ b/doc/source/fq_zech_sparse_mat.rst @@ -0,0 +1,295 @@ +.. _fq-zech-sparse-mat: + +**fq_zech_sparse_mat.h** -- sparse matrixs over finite fields (Zech logarithm representation) +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_zech_sparse_mat_t + + Holds an array of (possibly empty) sparse vectors corresponding to rows in + the matrix + +Memory management +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_init(fq_zech_sparse_mat_t M, slong rows, slong cols, const fq_zech_ctx_t ctx) + + Initializes an empty sparse matrix ``M`` with given number of rows and columns + +.. function:: void fq_zech_sparse_mat_clear(fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Clears the entries of the matrix ``M`` and frees the space allocated for it + +.. function:: void fq_zech_sparse_mat_swap(fq_zech_sparse_mat_t M1, fq_zech_sparse_mat_t M2, const fq_zech_ctx_t ctx) + + Swaps two matrices ``M1`` and ``M2`` (no reallocaton) + + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_zero(fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Sets matrix ``M`` to zero (the empty sparse matrix) + +.. function:: void fq_zech_sparse_mat_one(fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Sets matrix ``M`` to identity matrix (based on its number of rows) + +.. function:: void fq_zech_sparse_mat_set(fq_zech_sparse_mat_t N, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Makes ``N`` a (deep) copy of ``M`` + +.. function:: void fq_zech_sparse_mat_from_entries(fq_zech_sparse_mat_t M, slong *rows, slong *inds, fq_zech_struct *vals, slong nnz, const fq_zech_ctx_t ctx) + + Constructs matrix ``M`` from a given sequence of ``rows``, ``cols``, and + corresponding ``vals``, all of length ``nnz``, assumes sorted by rows + with no duplicate (row, col) indices + +.. function:: void fq_zech_sparse_mat_append_col(fq_zech_sparse_mat_t M, const fq_zech_struct *v, const fq_zech_ctx_t ctx) + + Add a dense column to the right of the matrix + +.. function:: void fq_zech_sparse_mat_append_row(fq_zech_sparse_mat_t M, const fq_zech_sparse_vec_t v, const fq_zech_ctx_t ctx) + + Add a sparse row to the bottom of the matrix + + +Conversion to/from dense matrix +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_from_dense(fq_zech_sparse_mat_t M, const fq_zech_mat_t dM, const fq_zech_ctx_t ctx) + + Converts the dense matrix ``dM`` to a sparse matrix ``M`` + +.. function:: void fq_zech_sparse_mat_to_dense(fq_zech_mat_t dM, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Converts the sparse matrix ``M`` to a dense matrix ``dM`` + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_window_init(fq_zech_sparse_mat_t window, const fq_zech_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2, const fq_zech_ctx_t ctx) + + Constructs a window on the sparse matrix ``M`` between rows ``r1`` and ``r2`` + and cols ``c1`` and ``c2`` (valid as long as original matrix remains uzechified) + +.. function:: void fq_zech_sparse_mat_window_clear(fq_zech_sparse_mat_t window, const fq_zech_ctx_t ctx) + + Clears a window + +.. function:: void fq_zech_sparse_mat_concat_horizontal(fq_zech_sparse_mat_t B, const fq_zech_sparse_mat_t M1, const fq_zech_sparse_mat_t M2, const fq_zech_ctx_t ctx) + + Horizontally concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_zech_sparse_mat_concat_vertical(fq_zech_sparse_mat_t B, const fq_zech_sparse_mat_t M1, const fq_zech_sparse_mat_t M2, const fq_zech_ctx_t ctx) + + Vertically concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void fq_zech_sparse_mat_split_horizontal(fq_zech_sparse_mat_t M1, fq_zech_sparse_mat_t M2, const fq_zech_sparse_mat_t B, slong c, const fq_zech_ctx_t ctx) + + Splits ``B`` horizontally into two submatrices ``M1`` and ``M2``, dividing at column ``c`` + +.. function:: void fq_zech_sparse_mat_split_vertical(fq_zech_sparse_mat_t M1, fq_zech_sparse_mat_t M2, const fq_zech_sparse_mat_t B, slong r, const fq_zech_ctx_t ctx) + + Splits ``B`` vertically into two submatrices ``M1`` and ``M2``, dividing at row ``r`` + + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_permute_cols(fq_zech_sparse_mat_t M, slong *Q, const fq_zech_ctx_t ctx) + + Permutes the columns indices of ``M`` according to ``Q``, and re-sorts each row + +.. function:: void fq_zech_sparse_mat_permute_rows(fq_zech_sparse_mat_t M, slong *P, const fq_zech_ctx_t ctx) + + Permutes the rows of ``M`` according to ``P`` + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_zech_sparse_mat_randtest(fq_zech_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, const fq_zech_ctx_t ctx) + + Makes ``M`` a sparse matrix with between ``min_nnz`` and ``max_nnz`` nonzero + entries per row, with individual entries generated by fq_zech_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_print_pretty(const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Prints the matrix ``M`` to ``stdout`` in a human-readable format + + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_is_zero(fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Checks if the given matrix ``M`` is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_zech_sparse_mat_equal(const fq_zech_sparse_mat_t M1, const fq_zech_sparse_mat_t M2, slong ioff, const fq_zech_ctx_t ctx) + + Checks if ``M1`` equals ``M2``, returning `1` if so and `0` otherwise + + +Transpose +-------------------------------------------------------------------------------- + +.. function:: void fq_sparse_mat_transpose(fq_zech_sparse_mat_t N, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Transposes ``M`` into the matrix ``N`` (must have swapped rows and columns) + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_mat_neg(fq_zech_sparse_mat_t N, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Sets ``N`` to the negation of ``M`` + +.. function:: void fq_zech_sparse_mat_scalar_mul_fq_zech(fq_zech_sparse_mat_t N, const fq_zech_sparse_mat_t M, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``N`` to the scalar multiple of ``M`` by ``c`` + +.. function:: void fq_zech_sparse_mat_add(fq_zech_sparse_mat_t O, const fq_zech_sparse_mat_t M, const fq_zech_sparse_mat_t N, const fq_zech_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``N`` + +.. function:: void fq_zech_sparse_mat_sub(fq_zech_sparse_mat_t O, const fq_zech_sparse_mat_t M, const fq_zech_sparse_mat_t N, const fq_zech_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N`` + +.. function:: void fq_zech_sparse_mat_scalar_addmul_fq_zech(fq_zech_sparse_mat_t O, const fq_zech_sparse_mat_t M, const fq_zech_sparse_mat_t N, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``O`` to the sum of ``M`` and ``c` times ``N`` + +.. function:: void fq_zech_sparse_mat_scalar_submul_fq_zech(fq_zech_sparse_mat_t O, const fq_zech_sparse_mat_t M, const fq_zech_sparse_mat_t N, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``O`` to the difference of ``M`` and ``N` times ``v`` + +.. function:: void fq_zech_sparse_mat_mul_vec(fq_zech_struct *y, const fq_zech_sparse_mat_t M, const fq_zech_struct *x, const fq_zech_ctx_t ctx) + + Sets ``y`` to the product of ``M`` and ``x`` + +.. function:: void fq_zech_sparse_mat_mul_mat(fq_zech_mat_t Y, const fq_zech_sparse_mat_t M, const fq_zech_mat_t X, const fq_zech_ctx_t ctx) + + Sets ``Y`` to the product of ``M`` and ``X`` + +.. function:: slong fq_zech_sparse_mat_inv(fq_zech_sparse_mat_t N, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Sets ``N`` to the "inverse" of ``M``, i.e., the matrix such that NM is + in reduced row-echelon form + + +Decomposition/reduction +-------------------------------------------------------------------------------- + +.. function:: slong fq_zech_sparse_mat_lu(slong *P, slong *Q, fq_zech_sparse_mat_t L, fq_zech_sparse_mat_t U, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Computes the decomposition PMQ = LU for a given sparse matrix ``M``, where + ``P`` is a row permutation, ``Q`` is a column permutation, ``L``is a lower + triangular matrix, and ``U`` is an upper triangular matrix + +.. function:: void fq_zech_sparse_mat_rref(fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Applies row reduction to put ``M`` in reduced row echelon form (in place) + +Solving +-------------------------------------------------------------------------------- + +.. function:: int fq_zech_sparse_mat_solve_lu(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use LU decomposition to find + a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_solve_rref(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the reduced row-echelon + form to find a vector ``x`` such that Mx = b, returns `1` if successful and + `0` if not + +.. function:: int fq_zech_sparse_mat_solve_lanczos(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Lanczos algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_solve_wiedemann(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use the Wiedemann algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_solve_block_lanczos(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Lanczos + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_solve_block_wiedemann(fq_zech_struct *x, const fq_zech_sparse_mat_t M, const fq_zech_struct *b, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Wiedemann + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +Nullvector and nullspace computation +-------------------------------------------------------------------------------- + +.. function:: int fq_zech_sparse_mat_nullvector_lanczos(fq_zech_struct *x, const fq_zech_sparse_mat_t M, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_nullvector_wiedemann(fq_zech_struct *x, const fq_zech_sparse_mat_t M, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_nullvector_block_lanczos(fq_zech_struct *x, const fq_zech_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_nullvector_block_wiedemann(fq_zech_struct *x, const fq_zech_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int fq_zech_sparse_mat_nullspace_rref(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the reduced row echelon form to construct the + nullspace ``X`` of M (initialized by this function), returns the nullity + +.. function:: int fq_zech_sparse_mat_nullspace_lu(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the LU decomposition to construct the nullspace ``X`` + of M (initialized by this function), returns the nullity + +.. function:: int fq_zech_sparse_mat_nullspace_lanczos(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_zech_sparse_mat_nullspace_wiedemann(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int fq_zech_sparse_mat_nullspace_block_lanczos(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + +.. function:: int fq_zech_sparse_mat_nullspace_block_wiedemann(fq_zech_mat_t X, const fq_zech_sparse_mat_t M, slong block_size, flint_rand_t state, const fq_zech_ctx_t ctx) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + diff --git a/doc/source/fq_zech_sparse_vec.rst b/doc/source/fq_zech_sparse_vec.rst new file mode 100644 index 0000000000..d1b85b94fd --- /dev/null +++ b/doc/source/fq_zech_sparse_vec.rst @@ -0,0 +1,176 @@ +.. _fq-zech-sparse-vec: + +**fq_zech_sparse_vec.h** -- sparse vectors over finite fields (Zech logarithm representation) +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: fq_zech_sparse_entry_t + + Holds a pair (ind, val), where ind (of type slong) is an index into the + vector and val (of type fq_zech_t) is the value at that index + +.. type:: fq_zech_sparse_vec_t + + Holds an array of nonzero entries (of type sparse_entry_struct *) of + specified length nnz, sorted by ind + +Memory management +-------------------------------------------------------------------------------- + + +.. function:: void fq_zech_sparse_vec_init(fq_zech_sparse_vec_t vec, const fq_zech_ctx_t ctx) + + Initializes an empty sparse vector (no allocation) + +.. function:: void fq_zech_sparse_vec_clear(fq_zech_sparse_vec_t vec, slong len, const fq_zech_ctx_t ctx) + + Clears the entries of vec and frees the space allocated for it + +.. function:: void fq_zech_sparse_vec_swap(fq_zech_sparse_vec_t vec1, fq_zech_sparse_vec_t vec2, const fq_zech_ctx_t ctx) + + Swaps two vectors (no reallocaton) + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_zero(fq_zech_sparse_vec_t vec, const fq_zech_ctx_t ctx) + + Sets vec to zero (the empty sparse vector) + +.. function:: void fq_zech_sparse_vec_one(fq_zech_sparse_vec_t vec, slong ind, const fq_zech_ctx_t ctx) + + Sets vec to the ind-th basis vector (single one in position ind) + +.. function:: void fq_zech_sparse_vec_set(fq_zech_sparse_vec_t dst, fq_zech_sparse_vec_t src, const fq_zech_ctx_t ctx) + + Makes dst a (deep) copy of src + +.. function:: void fq_zech_sparse_vec_set_entry(fq_zech_sparse_vec_t vec, slong ind, const fq_zech_t val, const fq_zech_ctx_t ctx) + + Sets the value at index ind to val, either replacing an existing value or extending + the array of entries + +.. function:: void _fq_zech_sparse_vec_from_entries(fq_zech_sparse_vec_t vec, slong *inds, fq_zech_struct *vals, slong nnz, const fq_zech_ctx_t ctx) + + Constructs vec from a given sequence of indices and associated values, both of length nnz. + Assumes no duplicate indices + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_is_zero(fq_zech_sparse_vec_t vec, const fq_zech_ctx_t ctx) + + Checks if the given vector is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void fq_zech_sparse_vec_equal(const fq_zech_sparse_vec_t vec1, const fq_zech_sparse_vec_t vec2, slong ioff, const fq_zech_ctx_t ctx) + + Checks if vec1 equals vec2 (with s specified column offset ioff), returning + `1` if so and `0` otherwise + +Indexing +-------------------------------------------------------------------------------- + +.. function:: fq_zech_t * fq_zech_sparse_vec_at(fq_zech_sparse_vec_t vec, slong ind, const fq_zech_ctx_t ctx) + + Returns a pointer to the value at the index ind (or NULL if index not found) + + +Conversion to/from dense vector +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_from_dense(fq_zech_sparse_vec_t dst, const fq_zech_struct *src, slong len, const fq_zech_ctx_t ctx) + + Converts the dense vector src of length len to a sparse vector + +.. function:: void fq_zech_sparse_vec_to_dense(fq_zech_struct *dst, const fq_zech_sparse_vec_t src, slong len, const fq_zech_ctx_t ctx) + + Converts the sparse vector src to a dense vector of length len + + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_window_init(fq_zech_sparse_vec_t window, const fq_zech_sparse_vec_t vec, slong i1, slong i2, const fq_zech_ctx_t ctx) + + Constructs a window on a the sparse vector vec between indices i1 and i2 + Note that window is only valid as long as original vector remains uzechified + +.. function:: void fq_zech_sparse_vec_window_clear(fq_zech_sparse_vec_t window, const fq_zech_ctx_t ctx) + + Clears a window (for safety only) + +.. function:: void fq_zech_sparse_vec_concat(fq_zech_sparse_vec_t res, const fq_zech_sparse_vec_t vec1, const fq_zech_sparse_vec_t vec2, slong len1, const fq_zech_ctx_t ctx) + + Concatenates two vectors vec1 and vec2 into res, with indices of vec2 + offset by len1 + +.. function:: void fq_zech_sparse_vec_split(fq_zech_sparse_vec_t res1, fq_zech_sparse_vec_t res1, const fq_zech_sparse_vec_t vec, slong ind, const fq_zech_ctx_t ctx) + + Splits vec into two vectors res1 and res2, with res1 containing all entries + below index ind and res2 containing the rest + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_permute_inds(fq_zech_sparse_vec_t vec, slong *P, const fq_zech_ctx_t ctx) + + Permutes the indices of vec according to P, and resorts + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void fq_zech_sparse_vec_randtest(fq_zech_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, const fq_zech_ctx_t ctx) + + Makes vec a sparse vector with nnz nonzero entries uniformly distributed + between 0 and len - 1, with individual entries generated by fq_zech_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_print_pretty(const fq_zech_sparse_vec_t vec, slong ioff, slong maxi, const fq_zech_ctx_t ctx) + + Prints the vector of given length to ``stdout`` in a human-readable format + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void fq_zech_sparse_vec_neg(fq_zech_sparse_vec_t v, const fq_zech_sparse_vec_t u, const fq_zech_ctx_t ctx) + + Sets ``v`` to the negation of ``u`` + +.. function:: void fq_zech_sparse_vec_scalar_mul_fq_zech(fq_zech_sparse_vec_t v, const fq_zech_sparse_vec_t u, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``v`` to the scalar multiple of ``u`` by ``c`` + +.. function:: void fq_zech_sparse_vec_add(fq_zech_sparse_vec_t w, const fq_zech_sparse_vec_t u, const fq_zech_sparse_vec_t v, const fq_zech_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``v`` + +.. function:: void fq_zech_sparse_vec_sub(fq_zech_sparse_vec_t w, const fq_zech_sparse_vec_t u, const fq_zech_sparse_vec_t v, const fq_zech_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``v`` + +.. function:: void fq_zech_sparse_vec_scalar_addmul_fq_zech(fq_zech_sparse_vec_t w, const fq_zech_sparse_vec_t u, const fq_zech_sparse_vec_t v, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``w`` to the sum of ``u`` and ``c` times ``v`` + +.. function:: void fq_zech_sparse_vec_scalar_addmul_fq_zech(fq_zech_sparse_vec_t w, const fq_zech_sparse_vec_t u, const fq_zech_sparse_vec_t v, const fq_zech_t c, const fq_zech_ctx_t ctx) + + Sets ``w`` to the difference of ``u`` and ``c` times ``v`` + +.. function:: void fq_zech_sparse_vec_dot(fq_zech_t ret, const fq_zech_sparse_vec_t u, const fq_zech_sparse_vec_t v, const fq_zech_ctx_t ctx) + + Sets ``ret`` to the dot product of ``u`` and ``v`` + +.. function:: void fq_zech_sparse_vec_dot_dense(fq_zech_t ret, const fq_zech_sparse_vec_t u, const fq_zech_struct * v, const fq_zech_ctx_t ctx) + + Sets ``ret`` to the dot product of (``u``, ``v``) diff --git a/doc/source/nmod_sparse_mat.rst b/doc/source/nmod_sparse_mat.rst new file mode 100644 index 0000000000..52b74b7a18 --- /dev/null +++ b/doc/source/nmod_sparse_mat.rst @@ -0,0 +1,296 @@ +.. _nmod-sparse-mat: + +**nmod_sparse_mat.h** -- sparse matrices over integers mod n +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: nmod_sparse_mat_t + + Holds an array of (possibly empty) sparse vectors corresponding to rows in + the matrix + +Memory management +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_init(nmod_sparse_mat_t M, slong rows, slong cols, nmod_t mod) + + Initializes an empty sparse matrix ``M`` with given number of rows and columns + +.. function:: void nmod_sparse_mat_clear(nmod_sparse_mat_t M) + + Clears the entries of the matrix ``M`` and frees the space allocated for it + +.. function:: void nmod_sparse_mat_swap(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2) + + Swaps two matrices ``M1`` and ``M2`` (no reallocaton) + + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_zero(nmod_sparse_mat_t M) + + Sets matrix ``M`` to zero (the empty sparse matrix) + +.. function:: void nmod_sparse_mat_one(nmod_sparse_mat_t M) + + Sets matrix ``M`` to identity matrix (based on its number of rows) + +.. function:: void nmod_sparse_mat_set(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) + + Makes ``N`` a (deep) copy of ``M`` + +.. function:: void nmod_sparse_mat_from_entries(nmod_sparse_mat_t M, slong *rows, slong *inds, mp_ptr vals, slong nnz) + + Constructs matrix ``M`` from a given sequence of ``rows``, ``cols``, and + corresponding ``vals``, all of length ``nnz``, assumes sorted by rows + with no duplicate (row, col) indices + +.. function:: void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, mp_srcptr v) + + Add a dense column to the right of the matrix + +.. function:: void nmod_sparse_mat_append_row(nmod_sparse_mat_t M, const nmod_sparse_vec_t v) + + Add a sparse row to the bottom of the matrix + + +Conversion to/from dense matrix +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_from_dense(nmod_sparse_mat_t M, const nmod_mat_t dM) + + Converts the dense matrix ``dM`` to a sparse matrix ``M`` + +.. function:: void nmod_sparse_mat_to_dense(nmod_mat_t dM, const nmod_sparse_mat_t M) + + Converts the sparse matrix ``M`` to a dense matrix ``dM`` + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_window_init(nmod_sparse_mat_t window, const nmod_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2) + + Constructs a window on the sparse matrix ``M`` between rows ``r1`` and ``r2`` + and cols ``c1`` and ``c2`` (valid as long as original matrix remains uzechified) + +.. function:: void nmod_sparse_mat_window_clear(nmod_sparse_mat_t window) + + Clears a window + +.. function:: void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) + + Horizontally concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) + + Vertically concatenates two matrices ``M1`` and ``M2`` into block matrix ``B`` + +.. function:: void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) + + Splits ``B`` horizontally into two submatrices ``M1`` and ``M2``, dividing at column ``c`` + +.. function:: void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong r) + + Splits ``B`` vertically into two submatrices ``M1`` and ``M2``, dividing at row ``r`` + + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) + + Permutes the columns indices of ``M`` according to ``Q``, and re-sorts each row + +.. function:: void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t M, slong *P) + + Permutes the rows of ``M`` according to ``P`` + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void nmod_sparse_mat_randtest(nmod_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz) + + Makes ``M`` a sparse matrix with between ``min_nnz`` and ``max_nnz`` nonzero + entries per row, with individual entries generated by nmod_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t M) + + Prints the matrix ``M`` to ``stdout`` in a human-readable format + + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_is_zero(nmod_sparse_mat_t M) + + Checks if the given matrix ``M`` is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void nmod_sparse_mat_equal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, slong ioff) + + Checks if ``M1`` equals ``M2``, returning `1` if so and `0` otherwise + + +Transpose +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, nmod_sparse_mat_t M) + + Transposes ``M`` into the matrix ``N`` (must have swapped rows and columns) + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) + + Sets ``N`` to the negation of ``M`` + +.. function:: void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, const nmod_t c) + + Sets ``N`` to the scalar multiple of ``M`` by ``c`` + +.. function:: void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) + + Sets ``O`` to the sum of ``M`` and ``N`` + +.. function:: void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) + + Sets ``O`` to the difference of ``M`` and ``N`` + +.. function:: void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, const nmod_t c) + + Sets ``O`` to the sum of ``M`` and ``c` times ``N`` + +.. function:: void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, const nmod_t c) + + Sets ``O`` to the difference of ``M`` and ``N` times ``v`` + +.. function:: void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) + + Sets ``y`` to the product of ``M`` and ``x`` + +.. function:: void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) + + Sets ``Y`` to the product of ``M`` and ``X`` + +.. function:: slong nmod_sparse_mat_inv(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) + + Sets ``N`` to the "inverse" of ``M``, i.e., the matrix such that NM is + in reduced row-echelon form + + +Decomposition/reduction +-------------------------------------------------------------------------------- + +.. function:: slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t M) + + Computes the decomposition PMQ = LU for a given sparse matrix ``M``, where + ``P`` is a row permutation, ``Q`` is a column permutation, ``L``is a lower + triangular matrix, and ``U`` is an upper triangular matrix, returns the rank + +.. function:: slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) + + Applies row reduction to put ``M`` in reduced row echelon form (in place) + and returns the rank + +Solving +-------------------------------------------------------------------------------- + +.. function:: int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) + + Given a matrix ``M`` and target vector ``b``, use LU decomposition to find + a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) + + Given a matrix ``M`` and target vector ``b``, use the reduced row-echelon + form to find a vector ``x`` such that Mx = b, returns `1` if successful and + `0` if not + +.. function:: int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state) + + Given a matrix ``M`` and target vector ``b``, use the Lanczos algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) + + Given a matrix ``M`` and target vector ``b``, use the Wiedemann algorithm to + find a vector ``x`` such that Mx = b, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Lanczos + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) + + Given a matrix ``M`` and target vector ``b``, use Coppersmith's block Wiedemann + algorithm (with specified block size) to find a vector ``x`` such that Mx = b, + returns `1` if successful and `0` if not + +Nullvector and nullspace computation +-------------------------------------------------------------------------------- + +.. function:: int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullvector ``x`` + s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullvector ``x`` s.t. Mx = 0, returns `1` if successful and `0` if not + +.. function:: int nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M) + + Given a matrix ``M``, use the reduced row echelon form to construct the + nullspace ``X`` of M (initialized by this function), returns the nullity + +.. function:: int nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) + + Given a matrix ``M``, use the LU decomposition to construct the nullspace ``X`` + of M (initialized by this function), returns the nullity + +.. function:: int nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state) + + Given a matrix ``M``, use the Lanczos algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state) + + Given a matrix ``M``, use the Wiedemann algorithm to find a nullspace ``X`` + of M (initialized by this function), returns the found nullity + +.. function:: int nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) + + Given a matrix ``M``, use Coppersmith's block Lanczos algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + +.. function:: int nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) + + Given a matrix ``M``, use Coppersmith's block Wiedemann algorithm to find a + nullspace ``X`` of M (initialized by this function), returns the found nullity + diff --git a/doc/source/nmod_sparse_vec.rst b/doc/source/nmod_sparse_vec.rst new file mode 100644 index 0000000000..bfad8dce7b --- /dev/null +++ b/doc/source/nmod_sparse_vec.rst @@ -0,0 +1,176 @@ +.. _nmod-sparse-vec: + +**nmod_sparse_vec.h** -- sparse vectors over integers mod word-size integers +=============================================================================== + +Description. + +Types, macros and constants +------------------------------------------------------------------------------- + +.. type:: nmod_sparse_entry_t + + Holds a pair (ind, val), where ind (of type slong) is an index into the + vector and val (of type mp_limb_t) is the value at that index + +.. type:: nmod_sparse_vec_t + + Holds an array of nonzero entries (of type nmod_sparse_entry_struct *) of + specified length nnz, sorted by ind + +Memory management +-------------------------------------------------------------------------------- + + +.. function:: void nmod_sparse_vec_init(nmod_sparse_vec_t vec) + + Initializes an empty sparse vector (no allocation) + +.. function:: void nmod_sparse_vec_clear(nmod_sparse_vec_t vec, slong len) + + Clears the entries of vec and frees the space allocated for it + +.. function:: void nmod_sparse_vec_swap(nmod_sparse_vec_t vec1, nmod_sparse_vec_t vec2) + + Swaps two vectors (no reallocaton) + +Instantiation +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_zero(nmod_sparse_vec_t vec) + + Sets vec to zero (the empty sparse vector) + +.. function:: void nmod_sparse_vec_one(nmod_sparse_vec_t vec, slong ind) + + Sets vec to the ind-th basis vector (single one in position ind) + +.. function:: void nmod_sparse_vec_set(nmod_sparse_vec_t dst, nmod_sparse_vec_t src) + + Makes dst a (deep) copy of src + +.. function:: void nmod_sparse_vec_set_entry(nmod_sparse_vec_t vec, slong ind, const mp_limb_t val) + + Sets the value at index ``ind`` to nonzero ``val``, either replacing an existing value or + extending the array of entries + +.. function:: void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong *inds, mp_ptr vals, slong nnz) + + Constructs vec from a given sequence of indices and associated values, both of length nnz. + Assumes no duplicate indices + +Comparison +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_is_zero(nmod_sparse_vec_t vec) + + Checks if the given vector is trivial (empty), returning `1` if so and `0` + otherwise + +.. function:: void nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff) + + Checks if vec1 equals vec2 (with s specified column offset ioff), returning + `1` if so and `0` otherwise + +Indexing +-------------------------------------------------------------------------------- + +.. function:: mp_limb_t * nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong ind) + + Returns a pointer to the value at the index ind (or NULL if index not found) + + +Conversion to/from dense vector +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_from_dense(nmod_sparse_vec_t dst, mp_srcptr src, slong len) + + Converts the dense vector src of length len to a sparse vector + +.. function:: void nmod_sparse_vec_to_dense(mp_ptr dst, const nmod_sparse_vec_t src, slong len) + + Converts the sparse vector src to a dense vector of length len + + +Windows, concatenation, and splitting +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_window_init(nmod_sparse_vec_t window, const nmod_sparse_vec_t vec, slong i1, slong i2) + + Constructs a window on a the sparse vector vec between indices i1 and i2 + Note that window is only valid as long as original vector remains uzechified + +.. function:: void nmod_sparse_vec_window_clear(nmod_sparse_vec_t window) + + Clears a window (for safety only) + +.. function:: void nmod_sparse_vec_concat(nmod_sparse_vec_t res, const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong len1) + + Concatenates two vectors vec1 and vec2 into res, with indices of vec2 + offset by len1 + +.. function:: void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res1, const nmod_sparse_vec_t vec, slong ind) + + Splits vec into two vectors res1 and res2, with res1 containing all entries + below index ind and res2 containing the rest + +Permutation +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_permute_inds(nmod_sparse_vec_t vec, slong *P) + + Permutes the indices of vec according to P, and re-sorts + + +Randomization +-------------------------------------------------------------------------------- + + +.. function:: void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, nmod_t mod) + + Makes vec a sparse vector with nnz nonzero entries uniformly distributed + between 0 and len - 1, with individual entries generated by nmod_randtest + + +Output +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_print_pretty(const nmod_sparse_vec_t vec, slong ioff, slong maxi, nmod_t mod) + + Prints the vector of given length to ``stdout`` in a human-readable format + + +Arithmetic +-------------------------------------------------------------------------------- + +.. function:: void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t mod) + + Sets ``v`` to the negation of ``u`` + +.. function:: void nmod_sparse_vec_scalar_mul_nmod(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, const mp_limb_t c, nmod_t mod) + + Sets ``v`` to the scalar multiple of ``u`` by ``c`` + +.. function:: void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) + + Sets ``w`` to the sum of ``u`` and ``v`` + +.. function:: void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) + + Sets ``w`` to the difference of ``u`` and ``v`` + +.. function:: void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod) + + Sets ``w`` to the sum of ``u`` and ``c` times ``v`` + +.. function:: void nmod_sparse_vec_scalar_submul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod) + + Sets ``w`` to the difference of ``u`` and ``c` times ``v`` + +.. function:: mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) + + Sets ``ret`` to the dot product of ``u`` and ``v`` + +.. function:: mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) + + Sets ``ret`` to the dot product of ``u`` and ``v`` diff --git a/fq_sparse_mat_templates.h b/fq_sparse_mat_templates.h index d3d40ade96..e81e03fb21 100644 --- a/fq_sparse_mat_templates.h +++ b/fq_sparse_mat_templates.h @@ -78,11 +78,11 @@ void TEMPLATE(T, sparse_mat_one) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_set) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) src, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, sparse_mat_set) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) { - slong i, rmax = FLINT_MIN(M->r, src->r); - if(M==src || M->r == 0) return; - for(i=0; irows[i], &src->rows[i], src->c_off, ctx); + slong i, rmax = FLINT_MIN(M->r, M->r); + if(M==N) return; + for(i=0; irows[i], &M->rows[i], M->c_off, ctx); } FLINT_DLL @@ -92,7 +92,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_append_col) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *v, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i=0; ir; ++i) TEMPLATE(T, sparse_vec_append_entry)(&M->rows[i], M->c, &v[i], ctx); + for(i=0; ir; ++i) TEMPLATE(T, sparse_vec_set_entry)(&M->rows[i], M->c, &v[i], ctx); M->c += 1; } @@ -229,12 +229,6 @@ int TEMPLATE(T, sparse_mat_is_zero) (const TEMPLATE(T, sparse_mat_t) M, const TE return 1; } -FQ_SPARSE_MAT_TEMPLATES_INLINE -int TEMPLATE(T, sparse_mat_is_square) (const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) -{ - return (M->r == M->c); -} - /* Must have M->r == N->c and M->c == N->r */ FLINT_DLL void TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); @@ -247,32 +241,39 @@ void TEMPLATE(T, sparse_mat_neg) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_scalar_mul) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; - for (i = 0; i < N->r; ++i) TEMPLATE(T, sparse_vec_scalar_mul)(&N->rows[i], &M->rows[i], c, ctx); + for (i = 0; i < N->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T))(&N->rows[i], &M->rows[i], c, ctx); } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_addmul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, sparse_mat_add) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) { slong i; - for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_scalar_addmul)(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); + for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_add)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_add) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, sparse_mat_sub) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) { slong i; - for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_add)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); + for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_sub)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_sub) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, sparse_mat_addmul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; - for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_sub)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); + for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); +} + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_submul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); } /* Matrix-vector and matrix-matrix multipliciation */ @@ -297,13 +298,8 @@ void TEMPLATE(T, sparse_mat_mul_mat) (TEMPLATE(T, mat_t) Y, const TEMPLATE(T, sp } } -/* Permutations */ -/* FLINT_DLL void TEMPLATE(T, sparse_mat_swap_rows)(TEMPLATE(T, sparse_mat_t) M, slong * perm, slong r, slong s); -FLINT_DLL void TEMPLATE(T, sparse_mat_invert_rows)(TEMPLATE(T, sparse_mat_t) M, slong * perm); -FLINT_DLL void TEMPLATE(T, sparse_mat_swap_cols)(TEMPLATE(T, sparse_mat_t) M, slong * perm, slong r, slong s); -FLINT_DLL void TEMPLATE(T, sparse_mat_invert_cols)(TEMPLATE(T, sparse_mat_t) M, slong * perm); -FLINT_DLL void TEMPLATE(T, sparse_mat_apply_permutation)(TEMPLATE(T, sparse_mat_t) M, slong * P, slong n); - */ +FLINT_DLL +slong TEMPLATE(T, sparse_mat_inv) (TEMPLATE(T, sparse_mat_t) Mi, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); /* Decomposition/reduction */ FLINT_DLL @@ -346,25 +342,22 @@ int TEMPLATE(T, sparse_mat_nullvector_block_lanczos) (TEMPLATE(T, struct) *x, co /* Note: this should take in uninitialized matrix X */ FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); - -FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -slong TEMPLATE(T, sparse_mat_inv) (TEMPLATE(T, sparse_mat_t) Ai, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx); +slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx); /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE diff --git a/fq_sparse_mat_templates/lu.c b/fq_sparse_mat_templates/lu.c index 831c0dd940..0626c4c0dc 100644 --- a/fq_sparse_mat_templates/lu.c +++ b/fq_sparse_mat_templates/lu.c @@ -138,17 +138,17 @@ slong TEMPLATE(T, sparse_mat_lu)(slong *P, slong *Q, if (P[r] >= 0) continue; /* Skip previous pivot rows */ TEMPLATE(T, mul) (cc, cinv, *TEMPLATE(T, sparse_vec_at) (row, pc, ctx), ctx); TEMPLATE(T, neg) (cc, cc, ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (row, row, prow, cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (row, row, prow, cc, ctx); if (row->nnz == 0) P[r] = --remr; } /* Gaussian eliminate cols */ - TEMPLATE(T, sparse_vec_scalar_mul) (pcol, pcol, cinv, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (pcol, pcol, cinv, ctx); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Lt->rows[c]; if (Q[c] >= 0) continue; /* Skip previous pivot columns */ TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (col, pr, ctx), ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (col, col, pcol, cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (col, col, pcol, cc, ctx); if (col->nnz == 0) Q[c] = --remc; scores[c] = col->nnz; heap_up(heap, heap_idx, scores, heap_idx[c]); diff --git a/fq_sparse_mat_templates/nullspace_lu.c b/fq_sparse_mat_templates/nullspace_lu.c index 50c3f53fd7..5d68a9fd98 100644 --- a/fq_sparse_mat_templates/nullspace_lu.c +++ b/fq_sparse_mat_templates/nullspace_lu.c @@ -35,7 +35,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE for (i = 0; i < rk; ++i) { TEMPLATE(T, inv) (cc, U->rows[i].entries[0].val, ctx); - TEMPLATE(T, sparse_vec_scalar_mul) (&U->rows[i], &U->rows[i], cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (&U->rows[i], &U->rows[i], cc, ctx); } TEMPLATE(T, mat_init) (X, M->c, M->c-rk, ctx); if (rk != M->c) diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c index b61dfc426f..cb3dcbe990 100644 --- a/fq_sparse_mat_templates/rref.c +++ b/fq_sparse_mat_templates/rref.c @@ -57,7 +57,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( P[pr] = rank; TEMPLATE(T, inv) (cinv, *TEMPLATE(T, sparse_vec_at) (prow, pc, ctx), ctx); - TEMPLATE(T, sparse_vec_scalar_mul) (prow, prow, cinv, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (prow, prow, cinv, ctx); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) @@ -66,17 +66,17 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( if (r == pr) {TEMPLATE(T, zero) (pcol->entries[j].val, ctx); continue;} TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (row, pc, ctx), ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (row, row, prow, cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (row, row, prow, cc, ctx); if (row->nnz == 0 || row->entries[0].ind >= M->c) P[r] = --remr; } /* Gaussian eliminate cols */ - TEMPLATE(T, sparse_vec_scalar_mul) (pcol, pcol, cinv, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (pcol, pcol, cinv, ctx); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Mt->rows[c]; if (c >= M->c || c == pc) continue; TEMPLATE(T, neg) (cc, *TEMPLATE(T, sparse_vec_at) (col, pr, ctx), ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (col, col, pcol, cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (col, col, pcol, cc, ctx); } rank += 1; } diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c index 6fc6de3f6e..5dbc491a7e 100644 --- a/fq_sparse_mat_templates/test/t-scalar_mul.c +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -44,10 +44,10 @@ main(void) TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); - TEMPLATE(T, sparse_mat_scalar_mul) (B, A, a, ctx); + TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (B, A, a, ctx); TEMPLATE(T, one) (cc, ctx); TEMPLATE(T, sub) (cc, a, cc, ctx); - TEMPLATE(T, sparse_mat_scalar_mul) (C, A, cc, ctx); + TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, cc, ctx); /* c*A - (c-1)*A == A */ TEMPLATE(T, sparse_mat_sub) (D, B, C, ctx); @@ -59,8 +59,8 @@ main(void) } /* Aliasing */ - TEMPLATE(T, sparse_mat_scalar_mul) (C, A, a, ctx); - TEMPLATE(T, sparse_mat_scalar_mul) (A, A, a, ctx); + TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, a, ctx); + TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (A, A, a, ctx); if (!TEMPLATE(T, sparse_mat_equal) (A, C, ctx)) { diff --git a/fq_sparse_vec_templates.h b/fq_sparse_vec_templates.h index 77e61ccbd9..82b394132e 100644 --- a/fq_sparse_vec_templates.h +++ b/fq_sparse_vec_templates.h @@ -91,6 +91,18 @@ void TEMPLATE(T, sparse_vec_swap)(TEMPLATE(T, sparse_vec_t) vec1, TEMPLATE(T, sp *tmp = *vec1, *vec1 = *vec2, *vec2 = *tmp; } +/* Vector indexing */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +TEMPLATE(T, t) *TEMPLATE(T, sparse_vec_at)(TEMPLATE(T, sparse_vec_t) vec, slong i, + const TEMPLATE(T, ctx_t) ctx) +{ + slong j; + for (j = 0; j < vec->nnz; ++j) + if (vec->entries[j].ind==i) + return &vec->entries[j].val; + return NULL; +} + /* One-time instantiation */ FQ_SPARSE_VEC_TEMPLATES_INLINE void TEMPLATE(T, sparse_vec_zero)(TEMPLATE(T, sparse_vec_t) vec, @@ -124,15 +136,20 @@ void TEMPLATE(T, sparse_vec_set)(TEMPLATE(T, sparse_vec_t) dst, const TEMPLATE(T } FQ_SPARSE_VEC_TEMPLATES_INLINE -void TEMPLATE(T, sparse_vec_append_entry)(TEMPLATE(T, sparse_vec_t) v, slong ind, const TEMPLATE(T, t) val, +void TEMPLATE(T, sparse_vec_set_entry)(TEMPLATE(T, sparse_vec_t) v, slong ind, const TEMPLATE(T, t) val, const TEMPLATE(T, ctx_t) ctx) { if (TEMPLATE(T, is_zero) (val, ctx)) return; - _TEMPLATE(T, sparse_vec_resize) (v, v->nnz + 1, ctx); - TEMPLATE(T, set) (v->entries[v->nnz-1].val, val, ctx); - v->entries[v->nnz-1].ind = ind; - if(v->nnz >= 2 && ind < v->entries[v->nnz-2].ind) - qsort(v->entries, v->nnz, sizeof(*v->entries), TEMPLATE(T, sparse_entry_cmp)); + TEMPLATE(T, t) *oval = TEMPLATE(T, sparse_vec_at) (v, ind, ctx); + if (oval == NULL) + { + _TEMPLATE(T, sparse_vec_resize) (v, v->nnz + 1, ctx); + TEMPLATE(T, set) (v->entries[v->nnz-1].val, val, ctx); + v->entries[v->nnz-1].ind = ind; + if(v->nnz >= 2 && ind < v->entries[v->nnz-2].ind) + qsort(v->entries, v->nnz, sizeof(*v->entries), TEMPLATE(T, sparse_entry_cmp)); + } + else TEMPLATE(T, set) (*oval, val, ctx); } FQ_SPARSE_VEC_TEMPLATES_INLINE @@ -170,18 +187,6 @@ int TEMPLATE(T, sparse_vec_equal)(const TEMPLATE(T, sparse_vec_t) vec1, const TE return 1; } -/* Vector indexing */ -FQ_SPARSE_VEC_TEMPLATES_INLINE -TEMPLATE(T, t) *TEMPLATE(T, sparse_vec_at)(TEMPLATE(T, sparse_vec_t) vec, slong i, - const TEMPLATE(T, ctx_t) ctx) -{ - slong j; - for (j = 0; j < vec->nnz; ++j) - if (vec->entries[j].ind==i) - return &vec->entries[j].val; - return NULL; -} - /* Convert from/to dense vector */ FQ_SPARSE_VEC_TEMPLATES_INLINE void TEMPLATE(T, sparse_vec_from_dense)(TEMPLATE(T, sparse_vec_t) dst, TEMPLATE(T, struct) *src, slong len, @@ -290,7 +295,7 @@ void TEMPLATE(T, sparse_vec_neg)(TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, } FQ_SPARSE_VEC_TEMPLATES_INLINE -void TEMPLATE(T, sparse_vec_scalar_mul)(TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, t) c, +void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T))(TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; @@ -323,7 +328,11 @@ void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, const TEMPLATE(T, ctx_t) ctx); FLINT_DLL -void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, +void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx); + +FLINT_DLL +void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx); FQ_SPARSE_VEC_TEMPLATES_INLINE diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c index 90c62b163f..f19f8faa95 100644 --- a/fq_sparse_vec_templates/scalar_addmul.c +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -13,13 +13,13 @@ #include #include "templates.h" -void TEMPLATE(T, sparse_vec_scalar_addmul)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, +void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i, nnz, unnz, vnnz; TEMPLATE(T, t) tmp; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if (u->nnz == 0) TEMPLATE(T, sparse_vec_scalar_mul) (w, v, c, ctx); + if (u->nnz == 0) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); else { diff --git a/fq_sparse_vec_templates/scalar_submul.c b/fq_sparse_vec_templates/scalar_submul.c new file mode 100644 index 0000000000..45d6d4927d --- /dev/null +++ b/fq_sparse_vec_templates/scalar_submul.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifdef T + +#include +#include "templates.h" + +void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i, nnz, unnz, vnnz; + TEMPLATE(T, t) tmp; + TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; + if (u->nnz == 0) + { + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); + TEMPLATE(T, sparse_vec_neg) (w, w, ctx); + } + else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); + else + { + TEMPLATE(T, init) (tmp, ctx); + unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ + nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); + ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; + while (ue >= u->entries && ve >= v->entries) + { + we->ind = FLINT_MAX(ue->ind, ve->ind); + if (ue->ind == ve->ind) + { + TEMPLATE(T, mul) (tmp, (ve--)->val, c, ctx); + TEMPLATE(T, sub) (we->val, tmp, (ue--)->val, ctx); + if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; + } + else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + else if (ve->ind == we->ind) + { + TEMPLATE(T, mul) (we->val, (ve--)->val, c, ctx); + TEMPLATE(T, neg) (we->val, we->val, c, ctx); we--; + } + } + while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); + while (ve >= v->entries) + { + we->ind = ve->ind; + TEMPLATE(T, mul) (we->val, (ve--)->val, c, ctx); + TEMPLATE(T, neg) (we->val, we->val, c, ctx); + we--; + } + + nnz = w->nnz - (we + 1 - w->entries); + if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); + else if (nnz < w->nnz) + { + for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); + memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); + w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); + w->nnz = nnz; + } + TEMPLATE(T, clear) (tmp, ctx); + } +} +#endif + diff --git a/fq_sparse_vec_templates/test/t-scalar_mul.c b/fq_sparse_vec_templates/test/t-scalar_mul.c index cc68dad000..fa507f9c94 100644 --- a/fq_sparse_vec_templates/test/t-scalar_mul.c +++ b/fq_sparse_vec_templates/test/t-scalar_mul.c @@ -45,8 +45,8 @@ main(void) TEMPLATE(T, sparse_vec_randtest) (v, state, nnz, len, ctx); TEMPLATE(T, randtest) (c, state, ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (w, u, v, c, ctx); - TEMPLATE(T, sparse_vec_scalar_mul) (x, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (x, v, c, ctx); TEMPLATE(T, sparse_vec_add) (x, x, u, ctx); if (!TEMPLATE(T, sparse_vec_equal) (w, x, 0, ctx)) @@ -55,8 +55,8 @@ main(void) abort(); } - TEMPLATE(T, sparse_vec_scalar_addmul) (w, u, v, c, ctx); - TEMPLATE(T, sparse_vec_scalar_addmul) (u, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (u, u, v, c, ctx); if (!TEMPLATE(T, sparse_vec_equal) (u, w, 0, ctx)) { @@ -64,8 +64,8 @@ main(void) abort(); } - TEMPLATE(T, sparse_vec_scalar_mul) (x, v, c, ctx); - TEMPLATE(T, sparse_vec_scalar_mul) (v, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (x, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (v, v, c, ctx); if (!TEMPLATE(T, sparse_vec_equal) (v, x, 0, ctx)) { diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 80f1220579..b29af827a8 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -52,14 +52,6 @@ nmod_sparse_mat_struct; typedef nmod_sparse_mat_struct nmod_sparse_mat_t[1]; -NMOD_SPARSE_MAT_INLINE -void _nmod_sparse_mat_set_mod(nmod_sparse_mat_t M, mp_limb_t n) -{ - M->mod.n = n; - count_leading_zeros(M->mod.norm, n); - invert_limb(M->mod.ninv, n << M->mod.norm); -} - /* Memory management */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_init(nmod_sparse_mat_t M, slong rows, slong cols, nmod_t mod) @@ -112,10 +104,10 @@ FLINT_DLL void nmod_sparse_mat_from_entries(nmod_sparse_mat_t M, slong * rows, slong * cols, mp_limb_t * vals, slong nnz); NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, const mp_ptr v) +void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, mp_srcptr v) { slong i; - for (i = 0; i < M->r; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); + for (i = 0; i < M->r; ++i) nmod_sparse_vec_set_entry(&M->rows[i], M->c, v[i]); M->c += 1; } @@ -253,12 +245,6 @@ int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) return 1; } -NMOD_SPARSE_MAT_INLINE -int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) -{ - return (M->r == M->c); -} - /* Must have M->r == N->c and M->c == N->r */ FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, const nmod_sparse_mat_t M); @@ -272,13 +258,13 @@ void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) +void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; nmod_sparse_mat_set(N, M); - for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul(&N->rows[i], &N->rows[i], c, N->mod); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); } } @@ -288,27 +274,33 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, N->mod.n); - nmod_sparse_mat_scalar_mul(N, M, fmpz_get_ui(d)); + nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); fmpz_clear(d); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_addmul(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +{ + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, nmod_neg(c, O->mod)); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(O, M, N, UWORD(1)); + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, UWORD(1)); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(O, M, N, O->mod.n-UWORD(1)); + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, O->mod.n-UWORD(1)); } /* Matrix-vector and matrix-matrix multipliciation */ @@ -333,13 +325,8 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod } } -/* Permutations */ -/* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t M, slong * perm, slong r, slong s); -FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t M, slong * perm); -FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t M, slong * perm, slong r, slong s); -FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t M, slong * perm); -FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t M, slong * P, slong n); - */ +FLINT_DLL +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); /* Decomposition/reduction */ FLINT_DLL @@ -350,19 +337,19 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); /* Solve Ax = b */ FLINT_DLL -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state); FLINT_DLL -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state); +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); FLINT_DLL int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); @@ -399,9 +386,6 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); -FLINT_DLL -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); - /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 024486ab2e..dc07510e23 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -129,25 +129,25 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, P[pr] = rank; /* Move pivot row to front */ /* Invert pivot */ - cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), M->mod); + cinv = nmod_inv(*nmod_sparse_vec_at(prow, pc), M->mod); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) { r = pcol->entries[j].ind, row = &U->rows[r]; if (P[r] >= 0) continue; /* Skip previous pivot rows */ - cc = nmod_neg(nmod_mul(cinv, nmod_sparse_vec_at(row, pc), M->mod), M->mod); - nmod_sparse_vec_scalar_addmul(row, row, prow, cc, M->mod); + cc = nmod_neg(nmod_mul(cinv, *nmod_sparse_vec_at(row, pc), M->mod), M->mod); + nmod_sparse_vec_scalar_addmul_nmod(row, row, prow, cc, M->mod); if (row->nnz == 0) P[r] = --remr; } /* Gaussian eliminate cols */ - nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, M->mod); + nmod_sparse_vec_scalar_mul_nmod(pcol, pcol, cinv, M->mod); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Lt->rows[c]; if (Q[c] >= 0) continue; /* Skip previous pivot columns */ - cc = nmod_neg(nmod_sparse_vec_at(col, pr), M->mod); - nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, M->mod); + cc = nmod_neg(*nmod_sparse_vec_at(col, pr), M->mod); + nmod_sparse_vec_scalar_addmul_nmod(col, col, pcol, cc, M->mod); if (col->nnz == 0) Q[c] = --remc; scores[c] = col->nnz; heap_up(heap, heap_idx, scores, heap_idx[c]); diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index eb5d68f1f1..154198e690 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -32,7 +32,7 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) flint_free(P); nmod_sparse_mat_clear(L); for (i = 0; i < rk; ++i) - nmod_sparse_vec_scalar_mul(&U->rows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, M->mod), M->mod); + nmod_sparse_vec_scalar_mul_nmod(&U->rows[i], &U->rows[i], nmod_inv(U->rows[i].entries[0].val, M->mod), M->mod); nmod_mat_init(X, M->c, M->c-rk, M->mod.n); if (rk != M->c) { diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index 6d071af025..155f25cdde 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -54,8 +54,8 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) if(pr == -1) continue; P[pr] = rank; - cinv = nmod_inv(nmod_sparse_vec_at(prow, pc), M->mod); - nmod_sparse_vec_scalar_mul(prow, prow, cinv, M->mod); + cinv = nmod_inv(*nmod_sparse_vec_at(prow, pc), M->mod); + nmod_sparse_vec_scalar_mul_nmod(prow, prow, cinv, M->mod); /* Gaussian eliminate rows */ for (j = 0; j < pcol->nnz; ++j) @@ -63,18 +63,18 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) r = pcol->entries[j].ind, row = &M->rows[r]; if(r==pr) {pcol->entries[j].val = UWORD(0); continue;} - cc = nmod_neg(nmod_sparse_vec_at(row, pc), M->mod); - nmod_sparse_vec_scalar_addmul(row, row, prow, cc, M->mod); + cc = nmod_neg(*nmod_sparse_vec_at(row, pc), M->mod); + nmod_sparse_vec_scalar_addmul_nmod(row, row, prow, cc, M->mod); if (row->nnz == 0 || row->entries[0].ind >= M->c) P[r] = --remr; } /* Gaussian eliminate cols */ - nmod_sparse_vec_scalar_mul(pcol, pcol, cinv, M->mod); + nmod_sparse_vec_scalar_mul_nmod(pcol, pcol, cinv, M->mod); for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Mt->rows[c]; if(c >= M->c || c==pc) continue; - cc = nmod_neg(nmod_sparse_vec_at(col, pr), M->mod); - nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, M->mod); + cc = nmod_neg(*nmod_sparse_vec_at(col, pr), M->mod); + nmod_sparse_vec_scalar_addmul_nmod(col, col, pcol, cc, M->mod); } rank += 1; } diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index 135813588b..d26e25b8e6 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -185,7 +185,7 @@ static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, c _nmod_vec_clear(xi); } -int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state) +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) { int good = 0, ret; slong i; diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index ae52186693..9f56dfdefa 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -16,7 +16,7 @@ #include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state) +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state) { slong j, ret; const slong nlimbs = _nmod_vec_dot_bound_limbs(M->c, M->mod); diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index ea7f4c2e25..64bae7ddb4 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -17,7 +17,7 @@ #include "nmod_sparse_mat.h" /* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x = Qx' */ -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) { int good = 1; slong rk, *P, *Q, i, j; diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c index 63b3afb322..a2a8fccb9b 100644 --- a/nmod_sparse_mat/solve_rref.c +++ b/nmod_sparse_mat/solve_rref.c @@ -16,7 +16,7 @@ #include "nmod_sparse_vec.h" #include "nmod_sparse_mat.h" -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) { int good = 1; slong i; @@ -28,7 +28,7 @@ int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr _nmod_vec_zero(x, M->c); return 1; } - + nmod_sparse_mat_init(Mb, M->r, M->c, M->mod); nmod_sparse_mat_set(Mb, M); nmod_sparse_mat_append_col(Mb, b); diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index f359ca5170..86763e4406 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -94,7 +94,7 @@ static void make_sum(mp_ptr x, mp_limb_t *s, slong L, const nmod_sparse_mat_t M, _nmod_vec_clear(My); } -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b) +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) { slong i, L, ret = 0, ns = FLINT_MIN(M->r, 2), len = 2*M->r + 1; mp_limb_t **s; diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c index 6fedc125b3..3184bb46af 100644 --- a/nmod_sparse_mat/test/t-lu.c +++ b/nmod_sparse_mat/test/t-lu.c @@ -55,7 +55,7 @@ main(void) /* Check that L is lower triangular (with ones on diagonal up to rank) */ for (i = 0; i < r; ++i) { - if(i < rk && nmod_sparse_vec_at(&L->rows[i], i) != UWORD(1)) + if(i < rk && *nmod_sparse_vec_at(&L->rows[i], i) != UWORD(1)) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } @@ -74,7 +74,7 @@ main(void) } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ for (i = 0; i < r; ++i) { - if(i < rk && nmod_sparse_vec_at(&U->rows[i], i) == UWORD(0)) + if(i < rk && *nmod_sparse_vec_at(&U->rows[i], i) == UWORD(0)) { flint_printf("FAIL: U does not have nonzero diagonal\n"); abort(); diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c index 93ae5e7385..d83850d960 100644 --- a/nmod_sparse_mat/test/t-scalar_mul.c +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -45,8 +45,8 @@ main(void) nmod_sparse_mat_randtest(A, state, 0, c); - nmod_sparse_mat_scalar_mul(B, A, c); - nmod_sparse_mat_scalar_mul(C, A, nmod_sub(c, UWORD(1), A->mod)); + nmod_sparse_mat_scalar_mul_nmod(B, A, c); + nmod_sparse_mat_scalar_mul_nmod(C, A, nmod_sub(c, UWORD(1), A->mod)); /* c*A - (c-1)*A == A */ nmod_sparse_mat_sub(D, B, C); @@ -58,8 +58,8 @@ main(void) } /* Aliasing */ - nmod_sparse_mat_scalar_mul(C, A, c); - nmod_sparse_mat_scalar_mul(A, A, c); + nmod_sparse_mat_scalar_mul_nmod(C, A, c); + nmod_sparse_mat_scalar_mul_nmod(A, A, c); if (!nmod_sparse_mat_equal(A, C)) { diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 4c6ba410d4..1fc01aa24c 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -83,6 +83,10 @@ void nmod_sparse_vec_swap(nmod_sparse_vec_t vec1, nmod_sparse_vec_t vec2) *tmp = *vec1, *vec1 = *vec2, *vec2 = *tmp; } +/* Vector indexing */ +FLINT_DLL +mp_limb_t * nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i); + /* One-time instantiation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_zero(nmod_sparse_vec_t vec) @@ -103,19 +107,24 @@ FLINT_DLL void nmod_sparse_vec_set(nmod_sparse_vec_t vec, const nmod_sparse_vec_t src, slong ioff); NMOD_SPARSE_VEC_INLINE -void _nmod_sparse_vec_append_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) +void nmod_sparse_vec_set_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) { - if (val == UWORD(0)) return; - v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); - v->entries[v->nnz].ind = ind; - v->entries[v->nnz].val = val; - v->nnz += 1; + mp_limb_t *oval = nmod_sparse_vec_at(v, ind); + if(oval == NULL) + { + v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); + v->entries[v->nnz].ind = ind; + v->entries[v->nnz].val = val; + v->nnz += 1; + if (v->nnz >= 2 && v->entries[v->nnz-2].ind > ind) + qsort(v->entries, v->nnz, sizeof(*v->entries), nmod_sparse_entry_cmp); + } + else *oval = val; } FLINT_DLL void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz); - /* Vector comparison */ NMOD_SPARSE_VEC_INLINE int nmod_sparse_vec_is_zero(const nmod_sparse_vec_t vec) @@ -126,10 +135,6 @@ int nmod_sparse_vec_is_zero(const nmod_sparse_vec_t vec) FLINT_DLL int nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff); -/* Vector indexing */ -FLINT_DLL -mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i); - /* Convert from/to dense vector */ FLINT_DLL void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len); @@ -185,7 +190,7 @@ void nmod_sparse_vec_neg(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, nmod_t } FLINT_DLL -void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod); +void nmod_sparse_vec_scalar_mul_nmod(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod); NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, const fmpz_t c, nmod_t mod) @@ -193,23 +198,29 @@ void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, mod.n); - nmod_sparse_vec_scalar_mul(v, u, fmpz_get_ui(d), mod); + nmod_sparse_vec_scalar_mul_nmod(v, u, fmpz_get_ui(d), mod); fmpz_clear(d); } FLINT_DLL -void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod); +void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod); + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_scalar_submul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod) +{ + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, nmod_neg(c, mod), mod); +} NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { - nmod_sparse_vec_scalar_addmul(w, u, v, UWORD(1), mod); + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, UWORD(1), mod); } NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) { - nmod_sparse_vec_scalar_addmul(w, u, v, mod.n-1, mod); + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, mod.n-1, mod); } FLINT_DLL diff --git a/nmod_sparse_vec/at.c b/nmod_sparse_vec/at.c index 67f8979528..00080f92c8 100644 --- a/nmod_sparse_vec/at.c +++ b/nmod_sparse_vec/at.c @@ -15,7 +15,7 @@ #include "flint.h" #include "nmod_sparse_vec.h" -mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) +mp_limb_t *nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) { slong pc, pr; slong numr = 0, numc = 0; @@ -24,7 +24,7 @@ mp_limb_t nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) /* TODO: binary search */ slong j; for (j = 0; j < vec->nnz; ++j) - if (vec->entries[j].ind==i) return vec->entries[j].val; - return 0; + if (vec->entries[j].ind==i) return &vec->entries[j].val; + return NULL; } diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c index 0cee0b1a53..37d7b5f890 100644 --- a/nmod_sparse_vec/scalar_addmul.c +++ b/nmod_sparse_vec/scalar_addmul.c @@ -15,11 +15,11 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_scalar_addmul(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) +void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) { if (c == UWORD(0) || (u->nnz == 0 && v->nnz == 0)) {nmod_sparse_vec_zero(w); return;} if (v->nnz == 0) {nmod_sparse_vec_set(w, u, 0); return;} - if (u->nnz == 0) {nmod_sparse_vec_scalar_mul(w, v, c, mod); return;} + if (u->nnz == 0) {nmod_sparse_vec_scalar_mul_nmod(w, v, c, mod); return;} nmod_sparse_vec_t u2; u2->nnz = u->nnz; if (u==w) diff --git a/nmod_sparse_vec/scalar_mul.c b/nmod_sparse_vec/scalar_mul.c index 3a86fac860..03324ab09b 100644 --- a/nmod_sparse_vec/scalar_mul.c +++ b/nmod_sparse_vec/scalar_mul.c @@ -15,7 +15,7 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_scalar_mul(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) +void nmod_sparse_vec_scalar_mul_nmod(nmod_sparse_vec_t v, const nmod_sparse_vec_t u, mp_limb_t c, nmod_t mod) { if (c == UWORD(0)) nmod_sparse_vec_zero(v); else if (c == UWORD(1)) nmod_sparse_vec_set(v, u, 0); diff --git a/nmod_sparse_vec/test/t-dense.c b/nmod_sparse_vec/test/t-dense.c index da97f6617d..49f218f52f 100644 --- a/nmod_sparse_vec/test/t-dense.c +++ b/nmod_sparse_vec/test/t-dense.c @@ -51,7 +51,8 @@ main(void) for (i = 0; i < len; ++i) { - if (nmod_sparse_vec_at(u, i) != w[i]) + mp_limb_t *val = nmod_sparse_vec_at(u, i); + if ((w[i] == 0 && val != NULL) || (w[i] != 0 && (val == NULL || *val != w[i]))) { flint_printf("FAIL: u[%wd] != v[%wd]\n", i, i); abort(); diff --git a/nmod_sparse_vec/test/t-dot.c b/nmod_sparse_vec/test/t-dot.c index d88c521c95..7f5ad3aaea 100644 --- a/nmod_sparse_vec/test/t-dot.c +++ b/nmod_sparse_vec/test/t-dot.c @@ -29,7 +29,7 @@ main(void) FLINT_TEST_INIT(state); - flint_printf("dot product....\n"); + flint_printf("dot product...."); fflush(stdout); for (rep = 0; rep < 1000; rep++) diff --git a/nmod_sparse_vec/test/t-scalar_mul.c b/nmod_sparse_vec/test/t-scalar_mul.c index 4ba2d3df3e..a79ecf0b8b 100644 --- a/nmod_sparse_vec/test/t-scalar_mul.c +++ b/nmod_sparse_vec/test/t-scalar_mul.c @@ -47,8 +47,8 @@ main(void) nmod_sparse_vec_randtest(u, state, nnz, len, mod); nmod_sparse_vec_randtest(v, state, nnz, len, mod); - nmod_sparse_vec_scalar_addmul(w, u, v, c, mod); - nmod_sparse_vec_scalar_mul(x, v, c, mod); + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_mul_nmod(x, v, c, mod); nmod_sparse_vec_add(x, x, u, mod); if (!nmod_sparse_vec_equal(w, x, 0)) @@ -57,8 +57,8 @@ main(void) abort(); } - nmod_sparse_vec_scalar_addmul(w, u, v, c, mod); - nmod_sparse_vec_scalar_addmul(u, u, v, c, mod); + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_addmul_nmod(u, u, v, c, mod); if (!nmod_sparse_vec_equal(u, w, 0)) { @@ -66,8 +66,8 @@ main(void) abort(); } - nmod_sparse_vec_scalar_mul(x, v, c, mod); - nmod_sparse_vec_scalar_mul(v, v, c, mod); + nmod_sparse_vec_scalar_mul_nmod(x, v, c, mod); + nmod_sparse_vec_scalar_mul_nmod(v, v, c, mod); if (!nmod_sparse_vec_equal(v, x, 0)) { From 2e35dec9b8e5ce407a613c9a21f9dfe4b9bbb3a0 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 28 Apr 2020 22:08:32 -0700 Subject: [PATCH 20/42] Most of the desired code for sparse integer linear algebra, except for smith normal form --- CMakeLists.txt | 2 +- Makefile.in | 6 +- fmpz_mat.h | 8 + fmpz_mpoly/divides_array.c | 1 - fmpz_sparse_mat.h | 639 ++++++++++++++++++ fmpz_sparse_mat/CRT_ui.c | 30 + fmpz_sparse_mat/content.c | 28 + fmpz_sparse_mat/det.c | 40 ++ fmpz_sparse_mat/det_bareiss.c | 47 ++ fmpz_sparse_mat/det_bound.c | 40 ++ fmpz_sparse_mat/det_cofactor.c | 27 + fmpz_sparse_mat/det_divisor.c | 61 ++ fmpz_sparse_mat/det_modular.c | 22 + fmpz_sparse_mat/det_modular_accelerated.c | 22 + fmpz_sparse_mat/det_modular_given_divisor.c | 100 +++ fmpz_sparse_mat/fflu.c | 135 ++++ fmpz_sparse_mat/from_entries.c | 25 + fmpz_sparse_mat/gram.c | 23 + fmpz_sparse_mat/hnf_classical.c | 97 +++ fmpz_sparse_mat/hnf_minors.c | 125 ++++ fmpz_sparse_mat/hnf_modular.c | 111 +++ fmpz_sparse_mat/hnf_modular_eldiv.c | 40 ++ fmpz_sparse_mat/hnf_xgcd.c | 92 +++ fmpz_sparse_mat/howell_form_mod.c | 33 + fmpz_sparse_mat/is_in_hnf.c | 42 ++ fmpz_sparse_mat/max_bits.c | 38 ++ fmpz_sparse_mat/multi_CRT_ui.c | 50 ++ fmpz_sparse_mat/multi_mod_ui.c | 58 ++ fmpz_sparse_mat/print_pretty.c | 32 + fmpz_sparse_mat/randtest.c | 29 + fmpz_sparse_mat/randtest_unsigned.c | 29 + fmpz_sparse_mat/solve_bound.c | 46 ++ fmpz_sparse_mat/solve_dixon.c | 235 +++++++ fmpz_sparse_mat/strong_echelon_form_mod.c | 189 ++++++ fmpz_sparse_mat/test/t-CRT_ui.c | 86 +++ fmpz_sparse_mat/test/t-CRT_ui_unsigned.c | 87 +++ fmpz_sparse_mat/test/t-add.c | 61 ++ fmpz_sparse_mat/test/t-concat_horizontal.c | 101 +++ fmpz_sparse_mat/test/t-concat_vertical.c | 93 +++ fmpz_sparse_mat/test/t-construct.c | 93 +++ fmpz_sparse_mat/test/t-content.c | 87 +++ fmpz_sparse_mat/test/t-dense.c | 70 ++ fmpz_sparse_mat/test/t-det.c | 85 +++ fmpz_sparse_mat/test/t-det_bareiss.c | 70 ++ fmpz_sparse_mat/test/t-det_bound.c | 67 ++ fmpz_sparse_mat/test/t-det_divisor.c | 72 ++ fmpz_sparse_mat/test/t-det_modular.c | 69 ++ .../test/t-det_modular_accelerated.c | 69 ++ fmpz_sparse_mat/test/t-fflu.c | 136 ++++ fmpz_sparse_mat/test/t-hnf_classical.c | 74 ++ fmpz_sparse_mat/test/t-hnf_minors.c | 73 ++ fmpz_sparse_mat/test/t-hnf_modular.c | 87 +++ fmpz_sparse_mat/test/t-hnf_modular_eldiv.c | 89 +++ fmpz_sparse_mat/test/t-hnf_xgcd.c | 74 ++ fmpz_sparse_mat/test/t-howell_form_mod.c | 79 +++ fmpz_sparse_mat/test/t-init_clear.c | 58 ++ fmpz_sparse_mat/test/t-mul.c | 83 +++ fmpz_sparse_mat/test/t-multi_CRT_ui.c | 86 +++ .../test/t-multi_CRT_ui_unsigned.c | 86 +++ fmpz_sparse_mat/test/t-neg.c | 72 ++ fmpz_sparse_mat/test/t-scalar_mul.c | 81 +++ fmpz_sparse_mat/test/t-solve_dixon.c | 98 +++ fmpz_sparse_mat/test/t-solve_dixon_den.c | 91 +++ fmpz_sparse_mat/test/t-transpose.c | 62 ++ fmpz_sparse_mat/transpose.c | 59 ++ fmpz_sparse_mat/window_init.c | 29 + fmpz_sparse_mat/with_transpose_fix_support.c | 34 + fmpz_sparse_mat/with_transpose_init.c | 33 + fmpz_sparse_vec.h | 428 ++++++++++++ fmpz_sparse_vec/CRT_ui.c | 38 ++ fmpz_sparse_vec/add.c | 42 ++ fmpz_sparse_vec/at.c | 26 + fmpz_sparse_vec/concat.c | 28 + fmpz_sparse_vec/dot.c | 32 + fmpz_sparse_vec/dot_dense.c | 23 + fmpz_sparse_vec/equal.c | 28 + fmpz_sparse_vec/from_dense.c | 29 + fmpz_sparse_vec/from_entries.c | 30 + fmpz_sparse_vec/gauss_elim.c | 122 ++++ fmpz_sparse_vec/gauss_elim_debugging | 146 ++++ fmpz_sparse_vec/max_bits.c | 78 +++ fmpz_sparse_vec/multi_CRT_ui.c | 72 ++ fmpz_sparse_vec/multi_mod_ui.c | 62 ++ fmpz_sparse_vec/print_pretty.c | 36 + fmpz_sparse_vec/randtest.c | 37 + fmpz_sparse_vec/randtest_unsigned.c | 37 + fmpz_sparse_vec/scalar_addmul.c | 49 ++ fmpz_sparse_vec/scalar_divexact.c | 28 + fmpz_sparse_vec/scalar_mod.c | 33 + fmpz_sparse_vec/scalar_mods.c | 33 + fmpz_sparse_vec/scalar_mul.c | 29 + fmpz_sparse_vec/scalar_submul.c | 73 ++ fmpz_sparse_vec/set.c | 28 + fmpz_sparse_vec/split.c | 33 + fmpz_sparse_vec/sub.c | 43 ++ fmpz_sparse_vec/test/t-add.c | 82 +++ fmpz_sparse_vec/test/t-concat.c | 97 +++ fmpz_sparse_vec/test/t-construct.c | 75 ++ fmpz_sparse_vec/test/t-dense.c | 83 +++ fmpz_sparse_vec/test/t-dot.c | 80 +++ fmpz_sparse_vec/test/t-gauss_elim.c | 132 ++++ fmpz_sparse_vec/test/t-init_clear.c | 87 +++ fmpz_sparse_vec/test/t-max_bits.c | 67 ++ fmpz_sparse_vec/test/t-neg.c | 74 ++ fmpz_sparse_vec/test/t-nmod.c | 117 ++++ fmpz_sparse_vec/test/t-scalar_divexact.c | 93 +++ fmpz_sparse_vec/test/t-scalar_mod.c | 160 +++++ fmpz_sparse_vec/test/t-scalar_mul.c | 114 ++++ fmpz_sparse_vec/window_init.c | 25 + fq_nmod_sparse_vec/scalar_submul.c | 22 + fq_sparse_mat_templates.h | 4 +- fq_sparse_mat_templates/inv.c | 2 - .../nullspace_block_lanczos.c | 1 - .../nullspace_block_wiedemann.c | 1 - fq_sparse_mat_templates/nullspace_lanczos.c | 1 - fq_sparse_mat_templates/nullspace_lu.c | 1 - fq_sparse_mat_templates/nullspace_rref.c | 1 - fq_sparse_mat_templates/nullspace_wiedemann.c | 1 - fq_sparse_mat_templates/rref.c | 4 +- fq_sparse_mat_templates/solve_block_lanczos.c | 8 +- .../solve_block_wiedemann.c | 12 +- fq_sparse_mat_templates/solve_lu.c | 2 +- fq_sparse_mat_templates/solve_wiedemann.c | 2 +- fq_sparse_mat_templates/test/t-add.c | 1 - .../test/t-concat_horizontal.c | 4 +- .../test/t-concat_vertical.c | 4 +- fq_sparse_mat_templates/test/t-dense.c | 2 +- fq_sparse_mat_templates/test/t-inv.c | 11 +- fq_sparse_mat_templates/test/t-lu.c | 11 +- fq_sparse_mat_templates/test/t-mul.c | 3 +- fq_sparse_mat_templates/test/t-neg.c | 2 +- fq_sparse_mat_templates/test/t-nullspace.c | 25 +- fq_sparse_mat_templates/test/t-rref.c | 5 +- fq_sparse_mat_templates/test/t-scalar_mul.c | 2 +- fq_sparse_mat_templates/test/t-solve.c | 16 +- fq_sparse_mat_templates/test/t-transpose.c | 4 +- fq_sparse_vec/scalar_submul.c | 22 + fq_sparse_vec_templates.h | 45 +- fq_sparse_vec_templates/add.c | 44 +- fq_sparse_vec_templates/scalar_addmul.c | 55 +- fq_sparse_vec_templates/scalar_submul.c | 67 +- fq_sparse_vec_templates/sub.c | 43 +- fq_sparse_vec_templates/test/t-add.c | 13 + fq_sparse_vec_templates/test/t-construct.c | 2 +- fq_sparse_vec_templates/test/t-scalar_mul.c | 39 +- fq_zech_sparse_vec/scalar_submul.c | 22 + hashmap.c | 183 ++--- hashmap.h | 114 +--- heap.c | 104 +++ heap.h | 48 ++ mpoly/compose_mat.c | 11 - nmod_sparse_mat.h | 30 +- nmod_sparse_mat/det.c | 60 ++ nmod_sparse_mat/howell_form.c | 37 + nmod_sparse_mat/inv.c | 2 - nmod_sparse_mat/nullspace_block_lanczos.c | 1 - nmod_sparse_mat/nullspace_block_wiedemann.c | 1 - nmod_sparse_mat/nullspace_lanczos.c | 1 - nmod_sparse_mat/nullspace_lu.c | 1 - nmod_sparse_mat/nullspace_rref.c | 1 - nmod_sparse_mat/nullspace_wiedemann.c | 1 - nmod_sparse_mat/print_pretty.c | 2 +- nmod_sparse_mat/rref.c | 4 +- nmod_sparse_mat/solve_block_lanczos.c | 8 +- nmod_sparse_mat/solve_block_wiedemann.c | 14 +- nmod_sparse_mat/solve_lanczos.c | 6 +- nmod_sparse_mat/solve_lu.c | 2 +- nmod_sparse_mat/solve_wiedemann.c | 2 +- nmod_sparse_mat/strong_echelon_form.c | 185 +++++ nmod_sparse_mat/test/t-concat_horizontal.c | 4 +- nmod_sparse_mat/test/t-concat_vertical.c | 4 +- nmod_sparse_mat/test/t-dense.c | 2 +- nmod_sparse_mat/test/t-inv.c | 9 +- nmod_sparse_mat/test/t-lu.c | 5 +- nmod_sparse_mat/test/t-mul.c | 4 +- nmod_sparse_mat/test/t-neg.c | 2 +- nmod_sparse_mat/test/t-nullspace.c | 23 +- nmod_sparse_mat/test/t-rref.c | 2 +- nmod_sparse_mat/test/t-scalar_mul.c | 5 +- nmod_sparse_mat/test/t-solve.c | 17 +- nmod_sparse_mat/test/t-transpose.c | 4 +- nmod_sparse_mat/transpose.c | 9 +- nmod_sparse_vec.h | 59 +- nmod_sparse_vec/add.c | 44 ++ nmod_sparse_vec/at.c | 4 - nmod_sparse_vec/equal.c | 2 +- nmod_sparse_vec/from_dense.c | 5 +- nmod_sparse_vec/randtest.c | 6 +- nmod_sparse_vec/scalar_addmul.c | 55 +- nmod_sparse_vec/scalar_submul.c | 46 ++ nmod_sparse_vec/sub.c | 44 ++ nmod_sparse_vec/test/t-add.c | 14 + nmod_sparse_vec/test/t-construct.c | 2 +- nmod_sparse_vec/test/t-scalar_mul.c | 41 +- test/t-hashmap.c | 78 +++ test/t-heap.c | 97 +++ 196 files changed, 9355 insertions(+), 579 deletions(-) create mode 100644 fmpz_sparse_mat.h create mode 100644 fmpz_sparse_mat/CRT_ui.c create mode 100644 fmpz_sparse_mat/content.c create mode 100644 fmpz_sparse_mat/det.c create mode 100644 fmpz_sparse_mat/det_bareiss.c create mode 100644 fmpz_sparse_mat/det_bound.c create mode 100644 fmpz_sparse_mat/det_cofactor.c create mode 100644 fmpz_sparse_mat/det_divisor.c create mode 100644 fmpz_sparse_mat/det_modular.c create mode 100644 fmpz_sparse_mat/det_modular_accelerated.c create mode 100644 fmpz_sparse_mat/det_modular_given_divisor.c create mode 100644 fmpz_sparse_mat/fflu.c create mode 100644 fmpz_sparse_mat/from_entries.c create mode 100644 fmpz_sparse_mat/gram.c create mode 100644 fmpz_sparse_mat/hnf_classical.c create mode 100644 fmpz_sparse_mat/hnf_minors.c create mode 100644 fmpz_sparse_mat/hnf_modular.c create mode 100644 fmpz_sparse_mat/hnf_modular_eldiv.c create mode 100644 fmpz_sparse_mat/hnf_xgcd.c create mode 100644 fmpz_sparse_mat/howell_form_mod.c create mode 100644 fmpz_sparse_mat/is_in_hnf.c create mode 100644 fmpz_sparse_mat/max_bits.c create mode 100644 fmpz_sparse_mat/multi_CRT_ui.c create mode 100644 fmpz_sparse_mat/multi_mod_ui.c create mode 100644 fmpz_sparse_mat/print_pretty.c create mode 100644 fmpz_sparse_mat/randtest.c create mode 100644 fmpz_sparse_mat/randtest_unsigned.c create mode 100644 fmpz_sparse_mat/solve_bound.c create mode 100644 fmpz_sparse_mat/solve_dixon.c create mode 100644 fmpz_sparse_mat/strong_echelon_form_mod.c create mode 100644 fmpz_sparse_mat/test/t-CRT_ui.c create mode 100644 fmpz_sparse_mat/test/t-CRT_ui_unsigned.c create mode 100644 fmpz_sparse_mat/test/t-add.c create mode 100644 fmpz_sparse_mat/test/t-concat_horizontal.c create mode 100644 fmpz_sparse_mat/test/t-concat_vertical.c create mode 100644 fmpz_sparse_mat/test/t-construct.c create mode 100644 fmpz_sparse_mat/test/t-content.c create mode 100644 fmpz_sparse_mat/test/t-dense.c create mode 100644 fmpz_sparse_mat/test/t-det.c create mode 100644 fmpz_sparse_mat/test/t-det_bareiss.c create mode 100644 fmpz_sparse_mat/test/t-det_bound.c create mode 100644 fmpz_sparse_mat/test/t-det_divisor.c create mode 100644 fmpz_sparse_mat/test/t-det_modular.c create mode 100644 fmpz_sparse_mat/test/t-det_modular_accelerated.c create mode 100644 fmpz_sparse_mat/test/t-fflu.c create mode 100644 fmpz_sparse_mat/test/t-hnf_classical.c create mode 100644 fmpz_sparse_mat/test/t-hnf_minors.c create mode 100644 fmpz_sparse_mat/test/t-hnf_modular.c create mode 100644 fmpz_sparse_mat/test/t-hnf_modular_eldiv.c create mode 100644 fmpz_sparse_mat/test/t-hnf_xgcd.c create mode 100644 fmpz_sparse_mat/test/t-howell_form_mod.c create mode 100644 fmpz_sparse_mat/test/t-init_clear.c create mode 100644 fmpz_sparse_mat/test/t-mul.c create mode 100644 fmpz_sparse_mat/test/t-multi_CRT_ui.c create mode 100644 fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c create mode 100644 fmpz_sparse_mat/test/t-neg.c create mode 100644 fmpz_sparse_mat/test/t-scalar_mul.c create mode 100644 fmpz_sparse_mat/test/t-solve_dixon.c create mode 100644 fmpz_sparse_mat/test/t-solve_dixon_den.c create mode 100644 fmpz_sparse_mat/test/t-transpose.c create mode 100644 fmpz_sparse_mat/transpose.c create mode 100644 fmpz_sparse_mat/window_init.c create mode 100644 fmpz_sparse_mat/with_transpose_fix_support.c create mode 100644 fmpz_sparse_mat/with_transpose_init.c create mode 100644 fmpz_sparse_vec.h create mode 100644 fmpz_sparse_vec/CRT_ui.c create mode 100644 fmpz_sparse_vec/add.c create mode 100644 fmpz_sparse_vec/at.c create mode 100644 fmpz_sparse_vec/concat.c create mode 100644 fmpz_sparse_vec/dot.c create mode 100644 fmpz_sparse_vec/dot_dense.c create mode 100644 fmpz_sparse_vec/equal.c create mode 100644 fmpz_sparse_vec/from_dense.c create mode 100644 fmpz_sparse_vec/from_entries.c create mode 100644 fmpz_sparse_vec/gauss_elim.c create mode 100644 fmpz_sparse_vec/gauss_elim_debugging create mode 100644 fmpz_sparse_vec/max_bits.c create mode 100644 fmpz_sparse_vec/multi_CRT_ui.c create mode 100644 fmpz_sparse_vec/multi_mod_ui.c create mode 100644 fmpz_sparse_vec/print_pretty.c create mode 100644 fmpz_sparse_vec/randtest.c create mode 100644 fmpz_sparse_vec/randtest_unsigned.c create mode 100644 fmpz_sparse_vec/scalar_addmul.c create mode 100644 fmpz_sparse_vec/scalar_divexact.c create mode 100644 fmpz_sparse_vec/scalar_mod.c create mode 100644 fmpz_sparse_vec/scalar_mods.c create mode 100644 fmpz_sparse_vec/scalar_mul.c create mode 100644 fmpz_sparse_vec/scalar_submul.c create mode 100644 fmpz_sparse_vec/set.c create mode 100644 fmpz_sparse_vec/split.c create mode 100644 fmpz_sparse_vec/sub.c create mode 100644 fmpz_sparse_vec/test/t-add.c create mode 100644 fmpz_sparse_vec/test/t-concat.c create mode 100644 fmpz_sparse_vec/test/t-construct.c create mode 100644 fmpz_sparse_vec/test/t-dense.c create mode 100644 fmpz_sparse_vec/test/t-dot.c create mode 100644 fmpz_sparse_vec/test/t-gauss_elim.c create mode 100644 fmpz_sparse_vec/test/t-init_clear.c create mode 100644 fmpz_sparse_vec/test/t-max_bits.c create mode 100644 fmpz_sparse_vec/test/t-neg.c create mode 100644 fmpz_sparse_vec/test/t-nmod.c create mode 100644 fmpz_sparse_vec/test/t-scalar_divexact.c create mode 100644 fmpz_sparse_vec/test/t-scalar_mod.c create mode 100644 fmpz_sparse_vec/test/t-scalar_mul.c create mode 100644 fmpz_sparse_vec/window_init.c create mode 100644 fq_nmod_sparse_vec/scalar_submul.c create mode 100644 fq_sparse_vec/scalar_submul.c create mode 100644 fq_zech_sparse_vec/scalar_submul.c create mode 100644 heap.c create mode 100644 heap.h create mode 100644 nmod_sparse_mat/det.c create mode 100644 nmod_sparse_mat/howell_form.c create mode 100644 nmod_sparse_mat/strong_echelon_form.c create mode 100644 nmod_sparse_vec/add.c create mode 100644 nmod_sparse_vec/scalar_submul.c create mode 100644 nmod_sparse_vec/sub.c create mode 100644 test/t-hashmap.c create mode 100644 test/t-heap.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f0fd743c1..a74acbd3de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ set(TEMPLATE_DIRS set(SOURCES printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c - hashmap.c inlines.c fmpz/fmpz.c + heap.c hashmap.c inlines.c fmpz/fmpz.c ) if (MSVC) diff --git a/Makefile.in b/Makefile.in index 6489b7c241..630ca529dc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -6,8 +6,8 @@ QUIET_AR = @echo ' ' AR ' ' $@; AT=@ -BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly \ - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly \ +BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_sparse_vec fmpz_poly \ + fmpq_poly fmpz_mat fmpz_sparse_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly \ nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic \ fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly \ fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve \ @@ -27,7 +27,7 @@ TEMPLATE_DIRS = fq_vec_templates fq_mat_templates fq_poly_templates \ export -SOURCES = printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c hashmap.c inlines.c +SOURCES = printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c heap.c hashmap.c inlines.c LIB_SOURCES = $(wildcard $(patsubst %, %/*.c, $(BUILD_DIRS))) $(patsubst %, %/*.c, $(TEMPLATE_DIRS)) HEADERS = $(patsubst %, %.h, $(BUILD_DIRS)) NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h fmpz-conversions.h profiler.h templates.h exception.h hashmap.h thread_support.h $(patsubst %, %.h, $(TEMPLATE_DIRS)) diff --git a/fmpz_mat.h b/fmpz_mat.h index faffd10523..56aa923dd3 100644 --- a/fmpz_mat.h +++ b/fmpz_mat.h @@ -244,6 +244,14 @@ FLINT_DLL void fmpz_mat_scalar_mod_fmpz(fmpz_mat_t B, const fmpz_mat_t A, const /* Multiplication */ +FMPZ_MAT_INLINE +void fmpz_mat_mul_vec(fmpz *y, const fmpz_mat_t A, fmpz *x) +{ + slong i; + for (i = 0; i < A->r; ++i) + _fmpz_vec_dot(&y[i], A->rows[i], x, A->c); +} + FLINT_DLL void fmpz_mat_mul(fmpz_mat_t C, const fmpz_mat_t A, const fmpz_mat_t B); FLINT_DLL void fmpz_mat_mul_classical(fmpz_mat_t C, const fmpz_mat_t A, diff --git a/fmpz_mpoly/divides_array.c b/fmpz_mpoly/divides_array.c index 0b233afe73..d218f76f06 100644 --- a/fmpz_mpoly/divides_array.c +++ b/fmpz_mpoly/divides_array.c @@ -14,7 +14,6 @@ #include "flint.h" #include "fmpz.h" #include "fmpz_mpoly.h" -#include "hashmap.h" /* improve locality */ #define BLOCK 128 diff --git a/fmpz_sparse_mat.h b/fmpz_sparse_mat.h new file mode 100644 index 0000000000..7c3d2c27a6 --- /dev/null +++ b/fmpz_sparse_mat.h @@ -0,0 +1,639 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#ifndef FMPZ_SPARSE_MAT_H +#define FMPZ_SPARSE_MAT_H + +#ifdef FMPZ_SPARSE_MAT_INLINES_C +#define FMPZ_SPARSE_MAT_INLINE FLINT_DLL +#else +#define FMPZ_SPARSE_MAT_INLINE static __inline__ +#endif + +#undef ulong +#define ulong ulongxx /* interferes with system includes */ +#include +#undef ulong + +#include +#define ulong mp_limb_t +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "hashmap.h" +#include "heap.h" +#include "nmod_sparse_mat.h" +#include "fmpz_sparse_vec.h" +#include "fmpz_mat.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* A sparse matrix is a list of sparse row vectors */ +typedef struct +{ + fmpz_sparse_vec_struct *rows; + slong r; + slong c; + slong c_off; +} +fmpz_sparse_mat_struct; + +typedef fmpz_sparse_mat_struct fmpz_sparse_mat_t[1]; + +#define LT(M, r) M->rows[r].entries[0] + +/* Can package matrix with its column support, to enable various operations */ +typedef struct +{ + fmpz_sparse_mat_struct *M; + hashmap_struct *cols; +} +fmpz_sparse_mat_with_transpose_struct; + +typedef fmpz_sparse_mat_with_transpose_struct fmpz_sparse_mat_with_transpose_t[1]; + +/* Memory management */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_init (fmpz_sparse_mat_t M, slong rows, slong cols) +{ + M->rows = flint_calloc(rows, sizeof(*M->rows)); + M->r = rows; + M->c = cols; + M->c_off = 0; +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_clear (fmpz_sparse_mat_t M) +{ + slong i; + for (i = 0; i < M->r; ++i) fmpz_sparse_vec_clear(&M->rows[i]); + flint_free(M->rows); + memset(M, 0, sizeof(*M)); +} +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_swap (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2) +{ + fmpz_sparse_mat_t tmp; + *tmp = *M1; *M1 = *M2; *M2 = *tmp; +} + +FLINT_DLL +slong fmpz_sparse_mat_max_bits(const fmpz_sparse_mat_t v); + +/* One-time instantiation */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_zero (fmpz_sparse_mat_t M) +{ + slong i; + for (i = 0; i < M->r; ++i) fmpz_sparse_vec_zero(&M->rows[i]); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_one (fmpz_sparse_mat_t M) +{ + slong i; + for (i = 0; i < M->r; ++i) fmpz_sparse_vec_one(&M->rows[i], i); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_set (fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M) +{ + slong i, rmax = FLINT_MIN(M->r, M->r); + if(M==N) return; + for(i=0; irows[i], &M->rows[i], M->c_off); +} + +FLINT_DLL +void fmpz_sparse_mat_from_entries(fmpz_sparse_mat_t M, slong * rows, slong * cols, fmpz * vals, slong nnz); + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_append_col (fmpz_sparse_mat_t M, const fmpz *v) +{ + slong i; + for(i=0; ir; ++i) fmpz_sparse_vec_set_entry(&M->rows[i], M->c, &v[i]); + M->c += 1; +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_append_row (fmpz_sparse_mat_t M, const fmpz_sparse_vec_t v) +{ + M->rows = realloc(M->rows, (M->r+1)*sizeof(*M->rows)); + memset(M->rows + M->r, 0, sizeof(*M->rows)); + fmpz_sparse_vec_set(&M->rows[M->r], v, 0); + M->r += 1; +} + +/* Convert from/to dense matrix */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_from_dense (fmpz_sparse_mat_t M, const fmpz_mat_t dM) +{ + slong i, rmax = FLINT_MIN(M->r, dM->r); + if (M->c == 0 || dM->c == 0) {fmpz_sparse_mat_zero(M); return;} + for (i = 0; i < rmax; ++i) fmpz_sparse_vec_from_dense(&M->rows[i], dM->rows[i], dM->c); +} +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_to_dense (fmpz_mat_t dM, const fmpz_sparse_mat_t M) +{ + slong i, rmax = FLINT_MIN(M->r, dM->r); + if (M->c == 0 || dM->c == 0) {fmpz_mat_zero(dM); return;} + for (i = 0; i < rmax; ++i) + fmpz_sparse_vec_to_dense(dM->rows[i], &M->rows[i], dM->c); +} + +/* Convert to/from modular matrix */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_get_nmod_sparse_mat(nmod_sparse_mat_t Amod, const fmpz_sparse_mat_t A) +{ + slong i; + for (i = 0; i < A->r; i++) + fmpz_sparse_vec_get_nmod_sparse_vec(&Amod->rows[i], &A->rows[i], Amod->mod); +} + +void fmpz_sparse_mat_multi_mod_ui_precomp(nmod_sparse_mat_struct * residues, slong nres, const fmpz_sparse_mat_t M, + const fmpz_comb_t comb, fmpz_comb_temp_t temp); + +void fmpz_sparse_mat_multi_mod_ui(nmod_sparse_mat_struct * residues, slong nres, const fmpz_sparse_mat_t M); + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_set_nmod_sparse_mat_unsigned(fmpz_sparse_mat_t A, const nmod_sparse_mat_t Amod) +{ + slong i; + for (i = 0; i < A->r; i++) + fmpz_sparse_vec_set_nmod_sparse_vec_unsigned(&A->rows[i], &Amod->rows[i]); +} + + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_set_nmod_sparse_mat(fmpz_sparse_mat_t A, const nmod_sparse_mat_t Amod) +{ + slong i; + for (i = 0; i < A->r; i++) + fmpz_sparse_vec_set_nmod_sparse_vec(&A->rows[i], &Amod->rows[i], Amod->mod); +} + +FLINT_DLL +void fmpz_sparse_mat_CRT_ui(fmpz_sparse_mat_t res, const fmpz_sparse_mat_t mat1, + const fmpz_t m1, const nmod_sparse_mat_t mat2, int sign); + + +FLINT_DLL +void fmpz_sparse_mat_multi_CRT_ui_precomp(fmpz_sparse_mat_t M, nmod_sparse_mat_struct * residues, slong nres, + const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign); + +FLINT_DLL +void fmpz_sparse_mat_multi_CRT_ui(fmpz_sparse_mat_t mat, nmod_sparse_mat_struct * residues, slong nres, int sign); + +/* Windows, concatenation, and splitting */ +FLINT_DLL +void fmpz_sparse_mat_window_init (fmpz_sparse_mat_t W, const fmpz_sparse_mat_t M, slong r1, slong c1, slong r2, slong c2); + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_window_clear (fmpz_sparse_mat_t W) +{ + flint_free(W->rows); + memset(W, 0, sizeof(*W)); +} + + +/* Combine M1 and M2 into block matrix B = [M1 M2] */ +/* B->r must equal M1->r and M2->r */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_concat_horizontal(fmpz_sparse_mat_t B, + const fmpz_sparse_mat_t M1, const fmpz_sparse_mat_t M2) +{ + slong i; + B->c = M1->c + M2->c; + for (i = 0; i < B->r; ++i) + fmpz_sparse_vec_concat(&B->rows[i], &M1->rows[i], &M2->rows[i], M1->c); +} +/* Combine M1 and M2 into block matrix B = [M1^t M1^t]^t */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_concat_vertical (fmpz_sparse_mat_t B, const fmpz_sparse_mat_t M1, const fmpz_sparse_mat_t M2) +{ + slong i; + B->c = FLINT_MAX(M1->c, M2->c); + for (i = 0; i < M1->r; ++i) + fmpz_sparse_vec_set(&B->rows[i], &M1->rows[i], M1->c_off); + for (i = M1->r; i < B->r; ++i) + fmpz_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); +} + +/* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ +/* M1->r and M2->r must equal B->r */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_split_horizontal (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2, const fmpz_sparse_mat_t B, slong c) +{ + slong i; + for(i=0; ir; ++i) fmpz_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); +} + +/* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_split_vertical (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2, const fmpz_sparse_mat_t B, slong r) +{ + slong i; + r = FLINT_MIN(r, B->r); + for(i=0; irows[i], &B->rows[i], B->c_off); + for(i=r; ir; ++i) fmpz_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); +} + +/* Matrix permutation */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_permute_cols(fmpz_sparse_mat_t M, slong *Q) +{ + slong i; + for (i = 0; i < M->r; ++i) { + if(!M->rows[i].nnz) continue; + fmpz_sparse_vec_permute_inds(&M->rows[i], Q); + qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), fmpz_sparse_entry_cmp); + } +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_permute_rows(fmpz_sparse_mat_t M, slong *P) +{ + slong i; + fmpz_sparse_vec_struct *prows; + prows = flint_calloc(M->r, sizeof(*prows)); + for (i = 0; i < M->r; ++i) prows[P[i]] = M->rows[i]; + memcpy(M->rows, prows, M->r*sizeof(*M->rows)); + flint_free(prows); +} + +/* Random matrix generation */ +FLINT_DLL void fmpz_sparse_mat_randtest (fmpz_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, flint_bitcnt_t bits); +FLINT_DLL void fmpz_sparse_mat_randtest_unsigned (fmpz_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, flint_bitcnt_t bits); +/* +FLINT_DLL void fmpz_sparse_mat_randfull (fmpz_sparse_mat_t M, flint_rand_t state, fmpz_ctx_t ctx); +FLINT_DLL int fmpz_sparse_mat_randpermdiag(fmpz_sparse_mat_t M, flint_rand_t state, + const fmpz *diag, slong n); +FLINT_DLL void fmpz_sparse_mat_randrank (fmpz_sparse_mat_t, flint_rand_t state, slong rank, fmpz_ctx_t ctx); +FLINT_DLL void fmpz_sparse_mat_randops (fmpz_sparse_mat_t M, slong count, flint_rand_t state, fmpz_ctx_t ctx); +FLINT_DLL void fmpz_sparse_mat_randtril (fmpz_sparse_mat_t M, flint_rand_t state, int unit, fmpz_ctx_t ctx); +FLINT_DLL void fmpz_sparse_mat_randtriu (fmpz_sparse_mat_t M, flint_rand_t state, int unit, fmpz_ctx_t ctx); + */ + +FLINT_DLL void fmpz_sparse_mat_print_pretty (const fmpz_sparse_mat_t M); + +FMPZ_SPARSE_MAT_INLINE +int fmpz_sparse_mat_equal (const fmpz_sparse_mat_t M1, const fmpz_sparse_mat_t M2) +{ + slong i; + if (M1->r != M2->r) return 0; + for (i = 0; i < M1->r; ++i) + if (!fmpz_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off)) return 0; + return 1; +} + +FMPZ_SPARSE_MAT_INLINE +int fmpz_sparse_mat_is_zero (const fmpz_sparse_mat_t M) +{ + slong i; + for (i = 0; i < M->r; ++i) + if (!fmpz_sparse_vec_is_zero(&M->rows[i])) return 0; + return 1; +} + +/* Must have M->r == N->c and M->c == N->r */ +FLINT_DLL +void fmpz_sparse_mat_transpose (fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M); + +/* Arithmetic */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_neg (fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_neg(&N->rows[i], &M->rows[i]); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_mul_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t c) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mul_fmpz(&N->rows[i], &M->rows[i], c); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_mul_diag_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, fmpz * D) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mul_fmpz(&N->rows[i], &M->rows[i], &D[i]); +} + + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_divexact_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t c) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_divexact_fmpz(&N->rows[i], &M->rows[i], c); +} + + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_mod_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t mod) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mod_fmpz(&N->rows[i], &M->rows[i], mod); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_mods_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t mod) +{ + slong i; + for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mods_fmpz(&N->rows[i], &M->rows[i], mod); +} + + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_add (fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N) +{ + slong i; + for (i = 0; i < O->r; ++i) fmpz_sparse_vec_add(&O->rows[i], &M->rows[i], &N->rows[i]); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_sub (fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N) +{ + slong i; + for (i = 0; i < O->r; ++i) fmpz_sparse_vec_sub(&O->rows[i], &M->rows[i], &N->rows[i]); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_addmul_fmpz(fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N, const fmpz_t c) +{ + slong i; + for (i = 0; i < O->r; ++i) fmpz_sparse_vec_scalar_addmul_fmpz(&O->rows[i], &M->rows[i], &N->rows[i], c); +} + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_scalar_submul_fmpz(fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N, const fmpz_t c) +{ + slong i; + for (i = 0; i < O->r; ++i) fmpz_sparse_vec_scalar_submul_fmpz(&O->rows[i], &M->rows[i], &N->rows[i], c); +} + +/* Matrix-vector and matrix-matrix multipliciation */ +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_mul_vec (fmpz *y, const fmpz_sparse_mat_t M, const fmpz *x) +{ + slong i; + if (M->c == 0) _fmpz_vec_zero(y, M->r); + else for (i = 0; i < M->r; ++i) fmpz_sparse_vec_dot_dense(&y[i], &M->rows[i], x); +} +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_mul_mat (fmpz_mat_t Y, const fmpz_sparse_mat_t M, const fmpz_mat_t X) +{ + slong i, j; + fmpz_mat_zero (Y); + for (i = 0; i < M->r; ++i) + { + for (j = 0; j < M->rows[i].nnz; ++j) + { + fmpz_sparse_entry_struct *e = &M->rows[i].entries[j]; + _fmpz_vec_scalar_addmul_fmpz(Y->rows[i], X->rows[e->ind], X->c, e->val); + } + } +} + +/* Memory management for matrix with transpose */ +FLINT_DLL +void _fmpz_sparse_mat_with_transpose_init(fmpz_sparse_mat_with_transpose_t MT, fmpz_sparse_mat_t M); + +FMPZ_SPARSE_MAT_INLINE +void _fmpz_sparse_mat_with_transpose_clear(fmpz_sparse_mat_with_transpose_t MT) +{ + slong c; + for(c = 0; c < MT->M->c; ++c) + hashmap_clear(&MT->cols[c]); + flint_free(MT->cols); + memset(MT, 0, sizeof(*MT)); +} + +FMPZ_SPARSE_MAT_INLINE +void _fmpz_sparse_mat_with_transpose_print_pretty(fmpz_sparse_mat_with_transpose_t MT) +{ + slong i, j; + fmpz_sparse_mat_print_pretty(MT->M); + flint_printf("Transpose: \nSupport: "); + for (i = 0; i < MT->M->c; ++i) + { + flint_printf("%wd ", MT->cols[i].num); + } + flint_printf("\n"); + for (i = 0; i < MT->M->c; ++i) + { + flint_printf("%wd: [", i); fflush(stdout); + for (j = 0; j < MT->cols[i].num; ++j) + { + if (j > 0) flint_printf(" "); + flint_printf("%wd: ", MT->cols[i].keys[j]); fflush(stdout); + fmpz_print(*((fmpz_t *) (MT->cols[i].vals[j]))); + } + flint_printf("]\n"); + } +} + +FLINT_DLL +void _fmpz_sparse_mat_with_transpose_fix_support(fmpz_sparse_mat_with_transpose_t MT, slong r, slong *osupp, slong onnz); + +#define MT_FIX(MT, r, ...) \ +{\ + slong *supp, nnz; \ + nnz = _fmpz_sparse_vec_support(&supp, &MT->M->rows[r]); \ + __VA_ARGS__; \ + _fmpz_sparse_mat_with_transpose_fix_support(MT, r, supp, nnz);\ + flint_free(supp);\ +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_col(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r, slong col) +{ + MT_FIX(MT, r, fmpz_sparse_vec_gauss_elim_col(&MT->M->rows[r], &MT->M->rows[pr], col)); + return fmpz_sparse_vec_at(&MT->M->rows[r], col) == NULL; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r) +{ + MT_FIX(MT, r, fmpz_sparse_vec_gauss_elim(&MT->M->rows[r], &MT->M->rows[pr])); + return fmpz_sparse_vec_at(&MT->M->rows[r], MT->M->rows[pr].entries[0].ind) == NULL; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_mod(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r, const fmpz_t mod) +{ + MT_FIX(MT, r, + fmpz_sparse_vec_gauss_elim(&MT->M->rows[r], &MT->M->rows[pr]); + fmpz_sparse_vec_scalar_mod_fmpz(&MT->M->rows[r], &MT->M->rows[r], mod)); + return fmpz_sparse_vec_at(&MT->M->rows[r], MT->M->rows[pr].entries[0].ind) == NULL; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_mods(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r, const fmpz_t mod) +{ + MT_FIX(MT, r, + fmpz_sparse_vec_gauss_elim(&MT->M->rows[r], &MT->M->rows[pr]); + fmpz_sparse_vec_scalar_mods_fmpz(&MT->M->rows[r], &MT->M->rows[r], mod)); + return fmpz_sparse_vec_at(&MT->M->rows[r], MT->M->rows[pr].entries[0].ind) == NULL; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_ext(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r) +{ + /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ + fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; + if(pe->ind != e->ind) + return _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r); + + MT_FIX(MT, pr, MT_FIX(MT, r, + fmpz_sparse_vec_gauss_elim_ext(&MT->M->rows[r], &MT->M->rows[pr]) + )); + return 1; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mod(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r, const fmpz_t mod) +{ + /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ + fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; + if(pe->ind != e->ind) + return _fmpz_sparse_mat_with_transpose_gauss_elim_mod(MT, pr, r, mod); + + MT_FIX(MT, pr, MT_FIX(MT, r, + fmpz_sparse_vec_gauss_elim_ext(&MT->M->rows[r], &MT->M->rows[pr]); + fmpz_sparse_vec_scalar_mod_fmpz(&MT->M->rows[pr], &MT->M->rows[pr], mod); + fmpz_sparse_vec_scalar_mod_fmpz(&MT->M->rows[r], &MT->M->rows[r], mod); + )); + return 1; +} + +FMPZ_SPARSE_MAT_INLINE +int _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mods(fmpz_sparse_mat_with_transpose_t MT, slong pr, slong r, const fmpz_t mod) +{ + /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ + fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; + if(pe->ind != e->ind) + return _fmpz_sparse_mat_with_transpose_gauss_elim_mods(MT, pr, r, mod); + + MT_FIX(MT, pr, MT_FIX(MT, r, + fmpz_sparse_vec_gauss_elim_ext(&MT->M->rows[r], &MT->M->rows[pr]); + fmpz_sparse_vec_scalar_mods_fmpz(&MT->M->rows[pr], &MT->M->rows[pr], mod); + fmpz_sparse_vec_scalar_mods_fmpz(&MT->M->rows[r], &MT->M->rows[r], mod); + )); + return 1; +} + +/* Utility computations */ +FLINT_DLL +void fmpz_sparse_mat_content(fmpz_t mat_gcd, const fmpz_sparse_mat_t M); + +FLINT_DLL +void fmpz_sparse_mat_gram(fmpz_mat_t B, const fmpz_sparse_mat_t A); + +/* Solving */ +FLINT_DLL +void fmpz_sparse_mat_solve_bound(fmpz_t N, fmpz_t D, const fmpz_sparse_mat_t A, const fmpz_mat_t B); + +FLINT_DLL +int fmpz_sparse_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_sparse_mat_t A, const fmpz_mat_t B); + +FMPZ_SPARSE_MAT_INLINE +int fmpz_sparse_mat_solve_vec_dixon(fmpz * x, fmpz_t mod, const fmpz_sparse_mat_t A, fmpz *b) +{ + int ret; + slong i; + fmpz_mat_t X, B; + fmpz_mat_init(X, A->c, 1); + fmpz_mat_init(B, A->r, 1); + for (i = 0; i < A->r; ++i) fmpz_set(fmpz_mat_entry(B, i, 0), &b[i]); + ret = fmpz_sparse_mat_solve_dixon(X, mod, A, B); + for (i = 0; i < A->c; ++i) fmpz_set(&x[i], fmpz_mat_entry(X, i, 0)); + fmpz_mat_clear(X); + fmpz_mat_clear(B); + return ret; +} + +FLINT_DLL +int fmpz_sparse_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_sparse_mat_t A, const fmpz_mat_t B); + +FMPZ_SPARSE_MAT_INLINE +int fmpz_sparse_mat_solve_vec_dixon_den(fmpz * x, fmpz_t den, const fmpz_sparse_mat_t A, fmpz *b) +{ + int ret; + slong i; + fmpz_mat_t X, B; + fmpz_mat_init(X, A->c, 1); + fmpz_mat_init(B, A->r, 1); + for (i = 0; i < A->r; ++i) fmpz_set(fmpz_mat_entry(B, i, 0), &b[i]); + ret = fmpz_sparse_mat_solve_dixon_den(X, den, A, B); + for (i = 0; i < A->c; ++i) fmpz_set(&x[i], fmpz_mat_entry(X, i, 0)); + fmpz_mat_clear(X); + fmpz_mat_clear(B); + return ret; +} + +/* Determinant computation */ +FLINT_DLL +void fmpz_sparse_mat_det_bound(fmpz_t bound, const fmpz_sparse_mat_t A); +FLINT_DLL +void fmpz_sparse_mat_det_cofactor(fmpz_t det, const fmpz_sparse_mat_t M); +FLINT_DLL +void fmpz_sparse_mat_det_bareiss(fmpz_t det, const fmpz_sparse_mat_t M); +FLINT_DLL +void fmpz_sparse_mat_det_divisor(fmpz_t d, const fmpz_sparse_mat_t M); +FLINT_DLL +void fmpz_sparse_mat_det_modular_accelerated(fmpz_t det, const fmpz_sparse_mat_t A, int proved); +FLINT_DLL +void fmpz_sparse_mat_det_modular_given_divisor(fmpz_t det, const fmpz_sparse_mat_t A, const fmpz_t d, int proved); +FLINT_DLL +void fmpz_sparse_mat_det_modular(fmpz_t det, const fmpz_sparse_mat_t A, int proved); +FLINT_DLL +void fmpz_sparse_mat_det(fmpz_t det, const fmpz_sparse_mat_t A); + +/* Fraction-free LU factorization */ +FLINT_DLL +slong fmpz_sparse_mat_fflu(fmpz *D, slong *P, slong *Q, fmpz_sparse_mat_t L, fmpz_sparse_mat_t U, + const fmpz_sparse_mat_t M); + +/* Hermite normal form */ +FLINT_DLL +int fmpz_sparse_mat_is_in_hnf(const fmpz_sparse_mat_t A); + +FLINT_DLL +slong fmpz_sparse_mat_hnf_classical(fmpz_sparse_mat_t M); + +FLINT_DLL +slong fmpz_sparse_mat_hnf_xgcd(fmpz_sparse_mat_t M); + +FLINT_DLL +slong fmpz_sparse_mat_hnf_minors(fmpz_sparse_mat_t M); + +FLINT_DLL +slong fmpz_sparse_mat_hnf_modular(fmpz_sparse_mat_t M, const fmpz_t det); + +FLINT_DLL +slong fmpz_sparse_mat_hnf_modular_eldiv(fmpz_sparse_mat_t M, const fmpz_t n); + +/* Modular forms */ +slong fmpz_sparse_mat_howell_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod); + +FLINT_DLL +slong fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/fmpz_sparse_mat/CRT_ui.c b/fmpz_sparse_mat/CRT_ui.c new file mode 100644 index 0000000000..7e215b13b1 --- /dev/null +++ b/fmpz_sparse_mat/CRT_ui.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "nmod_sparse_mat.h" +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_CRT_ui(fmpz_sparse_mat_t res, const fmpz_sparse_mat_t mat1, + const fmpz_t m1, const nmod_sparse_mat_t mat2, int sign) +{ + slong i; + mp_limb_t m1i_m2 = n_invmod(fmpz_fdiv_ui(m1, mat2->mod.n), mat2->mod.n); + + if (m1i_m2 == 0) + { + flint_printf("Exception (fmpz_mat_CRT_ui). m1 not invertible modulo m2.\n"); + flint_abort(); + } + for (i = 0; i < mat1->r; i++) + fmpz_sparse_vec_CRT_ui(&res->rows[i], &mat1->rows[i], m1, &mat2->rows[i], mat2->mod, m1i_m2, sign); +} + diff --git a/fmpz_sparse_mat/content.c b/fmpz_sparse_mat/content.c new file mode 100644 index 0000000000..9fc8b73c12 --- /dev/null +++ b/fmpz_sparse_mat/content.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2015 Dharak Kharod + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "fmpz.h" + +void fmpz_sparse_mat_content(fmpz_t mat_gcd, const fmpz_sparse_mat_t M) +{ + slong i, j; + fmpz_set_si(mat_gcd,0); + for (i = 0; i < M->r; i++ ) + { + for (j = 0; j < M->rows[i].nnz; j++) + { + fmpz_gcd(mat_gcd, mat_gcd, M->rows[i].entries[j].val); + if (fmpz_is_one(mat_gcd)) return; + } + } +} + diff --git a/fmpz_sparse_mat/det.c b/fmpz_sparse_mat/det.c new file mode 100644 index 0000000000..9859cd7d4d --- /dev/null +++ b/fmpz_sparse_mat/det.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 2010,2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_det(fmpz_t det, const fmpz_sparse_mat_t A) +{ + slong dim = A->r; + + if (dim != A->c) + { + flint_printf("Exception (fmpz_mat_det). Non-square matrix.\n"); + flint_abort(); + } + + if (dim < 5) + fmpz_sparse_mat_det_cofactor(det, A); + else if (dim < 25) + fmpz_sparse_mat_det_bareiss(det, A); + else if (dim < 60) + fmpz_sparse_mat_det_modular(det, A, 1); + else + { + slong bits = fmpz_sparse_mat_max_bits(A); + + if (dim < FLINT_ABS(bits)) + fmpz_sparse_mat_det_modular(det, A, 1); + else + fmpz_sparse_mat_det_modular_accelerated(det, A, 1); + } +} diff --git a/fmpz_sparse_mat/det_bareiss.c b/fmpz_sparse_mat/det_bareiss.c new file mode 100644 index 0000000000..e74d7f4db1 --- /dev/null +++ b/fmpz_sparse_mat/det_bareiss.c @@ -0,0 +1,47 @@ +/* + Copyright (C) 2010,2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "perm.h" + +void +fmpz_sparse_mat_det_bareiss(fmpz_t det, const fmpz_sparse_mat_t M) +{ + slong i, rk, *P, *Q; + fmpz *D; + fmpz_sparse_mat_t L, U; + if(M->r != M->c) {fmpz_zero(det); return;} + fmpz_one(det); + if (M->r == UWORD(0)) return; + + P = flint_malloc(M->r*sizeof(*P)); + Q = flint_malloc(M->c*sizeof(*P)); + D = _fmpz_vec_init(M->r); + fmpz_sparse_mat_init(L, M->r, M->c); + fmpz_sparse_mat_init(U, M->r, M->c); + rk = fmpz_sparse_mat_fflu(D, P, Q, L, U, M); + if (rk != M->r) fmpz_zero(det); + else + { + for (i = 0; i < M->r; ++i) + fmpz_mul(det, det, U->rows[i].entries[0].val); + for (i = 0; i < M->r; ++i) + fmpz_divexact(det, det, &D[i]); + if (_perm_parity(P, M->r) ^ _perm_parity(Q, M->c)) + fmpz_neg(det, det); + } + + flint_free(P); + flint_free(Q); + _fmpz_vec_clear(D, M->r); + fmpz_sparse_mat_clear(L); + fmpz_sparse_mat_clear(U); +} diff --git a/fmpz_sparse_mat/det_bound.c b/fmpz_sparse_mat/det_bound.c new file mode 100644 index 0000000000..fc1e25f858 --- /dev/null +++ b/fmpz_sparse_mat/det_bound.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_det_bound(fmpz_t bound, const fmpz_sparse_mat_t A) +{ + fmpz_t s, t; + slong i, j; + + fmpz_init(s); + fmpz_init(t); + + /* bound = II_i ceil(||A[i]||_2) */ + fmpz_one(bound); + for (i = 0; i < A->r; i++) + { + fmpz_zero(s); + for (j = 0; j < A->rows[i].nnz; j++) + fmpz_addmul(s, A->rows[i].entries[j].val, A->rows[i].entries[j].val); + fmpz_sqrtrem(s, t, s); + + if (!fmpz_is_zero(t)) + fmpz_add_ui(s, s, UWORD(1)); + + fmpz_mul(bound, bound, s); + } + + fmpz_clear(s); + fmpz_clear(t); +} diff --git a/fmpz_sparse_mat/det_cofactor.c b/fmpz_sparse_mat/det_cofactor.c new file mode 100644 index 0000000000..e0a8297c1e --- /dev/null +++ b/fmpz_sparse_mat/det_cofactor.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2010,2011,2018 Fredrik Johansson + + This file is part of FLINT. + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_det_cofactor(fmpz_t det, const fmpz_sparse_mat_t M) +{ + fmpz_mat_t dM; + if(M->r != M->c) {fmpz_zero(det); return;} + if (M->r > 4) + { + flint_printf("Exception (fmpz_sparse_mat_det_cofactor). dim > 4 not implemented."); + flint_abort(); + } + fmpz_mat_init(dM, M->r, M->c); + fmpz_sparse_mat_to_dense(dM, M); + fmpz_mat_det_cofactor(det, dM); + fmpz_mat_clear(dM); +} diff --git a/fmpz_sparse_mat/det_divisor.c b/fmpz_sparse_mat/det_divisor.c new file mode 100644 index 0000000000..007e81c027 --- /dev/null +++ b/fmpz_sparse_mat/det_divisor.c @@ -0,0 +1,61 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "fmpq.h" + +void +fmpz_sparse_mat_det_divisor(fmpz_t d, const fmpz_sparse_mat_t M) +{ + int success; + slong i; + fmpz_mat_t X, B; + fmpz_t t, u, v, mod; + if(M->r != M->c) {fmpz_zero(d); return;} + + fmpz_mat_init(X, M->c, 1); + fmpz_mat_init(B, M->r, 1); + fmpz_init(t); + fmpz_init(u); + fmpz_init(v); + fmpz_init(mod); + + /* Create a "random" vector */ + for (i = 0; i < M->r; i++) + fmpz_set_si(fmpz_mat_entry(B, i, 0), 2*(i % 2) - 1); + + success = fmpz_sparse_mat_solve_dixon(X, mod, M, B); + if (success) + { + fmpz_one(d); + for (i = 0; i < M->r; i++) + { + fmpz_mul(t, d, fmpz_mat_entry(X, i, 0)); + fmpz_fdiv_qr(u, t, t, mod); + if (!_fmpq_reconstruct_fmpz(u, v, t, mod)) + { + flint_printf("Exception (fmpz_mat_det_divisor): " + "Rational reconstruction failed.\n"); + flint_abort(); + } + + fmpz_mul(d, v, d); + } + } + else fmpz_zero(d); + + fmpz_mat_clear(X); + fmpz_mat_clear(B); + fmpz_clear(t); + fmpz_clear(u); + fmpz_clear(v); + fmpz_clear(mod); +} diff --git a/fmpz_sparse_mat/det_modular.c b/fmpz_sparse_mat/det_modular.c new file mode 100644 index 0000000000..33ef2234f1 --- /dev/null +++ b/fmpz_sparse_mat/det_modular.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_det_modular(fmpz_t det, const fmpz_sparse_mat_t A, int proved) +{ + fmpz_t d; + fmpz_init(d); + fmpz_one(d); + fmpz_sparse_mat_det_modular_given_divisor(det, A, d, proved); + fmpz_clear(d); +} diff --git a/fmpz_sparse_mat/det_modular_accelerated.c b/fmpz_sparse_mat/det_modular_accelerated.c new file mode 100644 index 0000000000..2a6f5b469b --- /dev/null +++ b/fmpz_sparse_mat/det_modular_accelerated.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_det_modular_accelerated(fmpz_t det, const fmpz_sparse_mat_t A, int proved) +{ + fmpz_t d; + fmpz_init(d); + fmpz_sparse_mat_det_divisor(d, A); + fmpz_sparse_mat_det_modular_given_divisor(det, A, d, proved); + fmpz_clear(d); +} diff --git a/fmpz_sparse_mat/det_modular_given_divisor.c b/fmpz_sparse_mat/det_modular_given_divisor.c new file mode 100644 index 0000000000..ad51245795 --- /dev/null +++ b/fmpz_sparse_mat/det_modular_given_divisor.c @@ -0,0 +1,100 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "nmod_sparse_mat.h" +#include "fmpz_sparse_mat.h" + +/* Enable to exercise corner cases */ +#define DEBUG_USE_SMALL_PRIMES 0 + + +static mp_limb_t +next_good_prime(const fmpz_t d, mp_limb_t p) +{ + mp_limb_t r = 0; + + while (r == 0) + { + p = n_nextprime(p, 0); + r = fmpz_fdiv_ui(d, p); + } + + return p; +} + + +void +fmpz_sparse_mat_det_modular_given_divisor(fmpz_t det, const fmpz_sparse_mat_t A, + const fmpz_t d, int proved) +{ + fmpz_t bound, prod, stable_prod, x, xnew; + mp_limb_t p, xmod; + nmod_t mod; + nmod_sparse_mat_t Amod; + slong n = A->r; + + if (A->r == 0) {fmpz_one(det); return;} + if (fmpz_is_zero(d)) {fmpz_zero(det); return;} + + fmpz_init(bound); + fmpz_init(prod); + fmpz_init(stable_prod); + fmpz_init(x); + fmpz_init(xnew); + + /* Bound x = det(A) / d */ + fmpz_sparse_mat_det_bound(bound, A); + fmpz_mul_ui(bound, bound, UWORD(2)); /* accomodate sign */ + fmpz_cdiv_q(bound, bound, d); + + nmod_init(&mod, 2); + nmod_sparse_mat_init(Amod, n, n, mod); + fmpz_zero(x); + fmpz_one(prod); + + p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; + + /* Compute x = det(A) / d */ + while (fmpz_cmp(prod, bound) <= 0) + { + p = next_good_prime(d, p); + nmod_init(&mod, p); + Amod->mod = mod; + fmpz_sparse_mat_get_nmod_sparse_mat(Amod, A); + + /* Compute x = det(A) / d mod p */ + xmod = nmod_sparse_mat_det(Amod); + xmod = n_mulmod2_preinv(xmod, + n_invmod(fmpz_fdiv_ui(d, p), p), Amod->mod.n, Amod->mod.ninv); + + fmpz_CRT_ui(xnew, x, prod, xmod, p, 1); + + if (fmpz_equal(xnew, x)) + { + fmpz_mul_ui(stable_prod, stable_prod, p); + if (!proved && fmpz_bits(stable_prod) > 100) break; + } + else fmpz_set_ui(stable_prod, p); + + fmpz_mul_ui(prod, prod, p); + fmpz_set(x, xnew); + } + + /* det(A) = x * d */ + fmpz_mul(det, x, d); + + nmod_sparse_mat_clear(Amod); + fmpz_clear(bound); + fmpz_clear(prod); + fmpz_clear(stable_prod); + fmpz_clear(x); + fmpz_clear(xnew); +} diff --git a/fmpz_sparse_mat/fflu.c b/fmpz_sparse_mat/fflu.c new file mode 100644 index 0000000000..b246b5e4da --- /dev/null +++ b/fmpz_sparse_mat/fflu.c @@ -0,0 +1,135 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "hashmap.h" +#include "heap.h" +#include "perm.h" +#include "longlong.h" + +static void update_heap(heap_t h, const fmpz_sparse_mat_with_transpose_t MT, slong r, slong *osupp, slong onnz) +{ + slong i = 0, j = 0, oc, nc, c; + fmpz_sparse_vec_struct *row = &MT->M->rows[r]; + while (1) + { + oc = (i==onnz) ? MT->M->c : osupp[i]; + nc = (j==row->nnz) ? MT->M->c : row->entries[j].ind; + c = FLINT_MIN(oc, nc); + if (c >= MT->M->c) break; + if (oc != nc) heap_adjust(h, c, MT->cols[c].num); + if (c==oc) ++i; + if (c==nc) ++j; + } +} + +slong +fmpz_sparse_mat_fflu(fmpz *D, slong *P, slong *Q, fmpz_sparse_mat_t L, fmpz_sparse_mat_t U, + const fmpz_sparse_mat_t M) +{ + slong i, j, r, c, pr, pc, rank, remr, remc, *supp, nnz; + heap_t h; + fmpz_t pivot, one, tmp; + fmpz_sparse_vec_struct *prow, *row; + hashmap_struct *hcol; + fmpz_t *hval; + fmpz_sparse_mat_with_transpose_t UT; + + for (i = 0; i < M->r; ++i) fmpz_one(&D[i]); + if (M->r == 0 || M->c == 0) + { + fmpz_sparse_mat_zero (L); + fmpz_sparse_mat_zero (U); + for (i = 0; i < M->r; ++i) P[i] = i; + for (i = 0; i < M->c; ++i) Q[i] = i; + return 0; + } + fmpz_init(pivot); + fmpz_init(tmp); + fmpz_init_set_ui(one, UWORD(1)); + fmpz_sparse_mat_zero(L); + fmpz_sparse_mat_set (U, M); + _fmpz_sparse_mat_with_transpose_init(UT, U); + + /* Initialize permutations */ + remr = M->r, remc = M->c; + for (r = 0; rr; ++r) + { + if (!U->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + for (c = 0; cc; ++c) + { + if (!UT->cols[c].num) Q[c] = --remc; + else Q[c] = -1; + } + + /* Make heap of nonzero columns by size */ + heap_init(h, M->c); + for (c = 0; c < M->c; ++c) + heap_push(h, UT->cols[c].num); + + /* Run elimination */ + rank = 0; + + while (h->num > 0) + { + /* Get lowest weight column (top of heap) */ + pc = heap_pop(h, NULL); + hcol = &UT->cols[pc]; + + /* Get lowest weight incident row */ + prow = NULL, pr = -1; + for (i = 0; i < hcol->num; ++i) + { + r = hcol->keys[i]; + row = &U->rows[r]; + if (prow == NULL || row->nnz < prow->nnz) + pr = r, prow = row; + } + if (pr == -1) {if (Q[pc] == -1) Q[pc] = --remc; continue;} + P[pr] = Q[pc] = rank++; /* Move pivot row and col to front */ + + /* Get pivot */ + fmpz_set(pivot, *fmpz_sparse_vec_at(prow, pc)); + fmpz_sparse_vec_set_entry(&L->rows[pr], pc, one); + + /* Remove pivot row from transpose */ + for (j = 0; j < prow->nnz; ++j) + hashmap_rem(&UT->cols[prow->entries[j].ind], pr); + + /* Use pivot row to fraction-free Gaussian eliminate other incident rows */ + while (hcol->num > 0) + { + r = hcol->keys[0]; + nnz = _fmpz_sparse_vec_support(&supp, &U->rows[r]); + fmpz_mul(&D[r], &D[r], pivot); + hval = hcol->vals[0], fmpz_set(tmp, *hval); + fmpz_sparse_vec_scalar_mul_fmpz(&U->rows[r], &U->rows[r], pivot); + fmpz_sparse_vec_scalar_mul_fmpz(&L->rows[r], &L->rows[r], pivot); + fmpz_sparse_vec_set_entry(&L->rows[r], pc, tmp); + _fmpz_sparse_mat_with_transpose_gauss_elim_col(UT, pr, r, pc); + update_heap(h, UT, r, supp, nnz); + if (U->rows[r].nnz == 0) P[r] = --remr; + } + } + heap_clear(h); + _fmpz_sparse_mat_with_transpose_clear(UT); + + /* Reorder rows and cols in L and U */ + fmpz_sparse_mat_permute_cols (L, Q); + fmpz_sparse_mat_permute_rows (L, P); + fmpz_sparse_mat_permute_cols (U, Q); + fmpz_sparse_mat_permute_rows (U, P); + fmpz_clear(pivot); + fmpz_clear(tmp); + return rank; +} diff --git a/fmpz_sparse_mat/from_entries.c b/fmpz_sparse_mat/from_entries.c new file mode 100644 index 0000000000..b1c3f3cb99 --- /dev/null +++ b/fmpz_sparse_mat/from_entries.c @@ -0,0 +1,25 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void fmpz_sparse_mat_from_entries(fmpz_sparse_mat_t M, slong * rows, slong * cols, fmpz * vals, slong nnz) +{ + slong r, i, j; + for (r = i = 0; r < M->r; ++r, i = j) + { + for (j = i; j < nnz && rows[j]==r; ++j); + fmpz_sparse_vec_from_entries(&M->rows[r], cols+i, vals+i, j-i); + } +} diff --git a/fmpz_sparse_mat/gram.c b/fmpz_sparse_mat/gram.c new file mode 100644 index 0000000000..dd76433a1a --- /dev/null +++ b/fmpz_sparse_mat/gram.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2014 Abhinav Baid + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void fmpz_sparse_mat_gram(fmpz_mat_t B, const fmpz_sparse_mat_t M) +{ + slong i, j; + + if(M->r == 0) fmpz_mat_zero(B); + else + for(i = 0; i < M->r; i++) + for(j = 0; j < M->r; j++) + fmpz_sparse_vec_dot(&B->rows[i][j], &M->rows[i], &M->rows[j]); +} diff --git a/fmpz_sparse_mat/hnf_classical.c b/fmpz_sparse_mat/hnf_classical.c new file mode 100644 index 0000000000..dc0d9c00e8 --- /dev/null +++ b/fmpz_sparse_mat/hnf_classical.c @@ -0,0 +1,97 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "hashmap.h" +#include "fmpz_sparse_mat.h" + +slong +fmpz_sparse_mat_hnf_classical(fmpz_sparse_mat_t M) +{ + slong i, r, pr, pc, rank, remr, next_pr, nnz; + slong *P; /* Row permutation */ + slong *irows; /* Set of row incident on a given column */ + slong nnp, next_nnp; /* Number of such rows which are not previous pivots */ + slong npp; /* Number of such rows which are previous pivots */ + fmpz_sparse_mat_with_transpose_t MT; + hashmap_struct *hcol; + + if (M->r == 0 || M->c == 0) return 0; + + /* Construct virtual transpose */ + _fmpz_sparse_mat_with_transpose_init(MT, M); + + /* Set up permutation */ + P = flint_malloc(M->r*sizeof(*P)); + remr = M->r; + for (r = 0; r < M->r; ++r) + { + if (!M->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + irows = flint_malloc(M->r * sizeof(*irows)); + + for (rank = pc = 0; pc < M->c; ++pc) + { + hcol = &MT->cols[pc]; nnz = hcol->num; + if(!nnz) continue; + pr = next_pr = -1, next_nnp = nnz, npp = 0; + + do + { + pr = next_pr, next_pr = -1; + nnp = next_nnp, next_nnp = 0; + for (i = 0; i < nnp; ++i) + { + r = (pr == -1) ? hcol->keys[i] : irows[i]; + if (pr >= 0) /* Reduce row r by row pr */ + { + if(_fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r)) + { + if(M->rows[r].nnz == 0) P[r] = --remr; + continue; + } + } + else if (P[r] >= 0) /* Record incident previous pivot rows at end of irows */ + { + irows[hcol->num - (++npp)] = r; + continue; + } + + /* Either add r (back) to irows or make it the next pivot row */ + + if (next_pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, next_pr).val) >= 0) { + irows[next_nnp++] = r; + continue; + } + if (next_pr >= 0) irows[next_nnp++] = next_pr; + next_pr = r; + } + if (pr != -1) irows[next_nnp++] = pr; + } while (next_pr != -1); /* Stop when no more reduction to be done */ + if (pr == -1) continue; /* No incident rows which are not previous pivots */ + + if (fmpz_sgn(LT(M, pr).val) < 0) + fmpz_sparse_vec_neg(&M->rows[pr], &M->rows[pr]); + + /* Now use row pr to reduce the previous pivot rows */ + for (i = nnz - npp; i < nnz; ++i) + _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, irows[i]); + P[pr] = rank++; + } + + /* Apply row permutation */ + fmpz_sparse_mat_permute_rows (M, P); + + flint_free(P); + flint_free(irows); + _fmpz_sparse_mat_with_transpose_clear(MT); + return rank; +} diff --git a/fmpz_sparse_mat/hnf_minors.c b/fmpz_sparse_mat/hnf_minors.c new file mode 100644 index 0000000000..22c81bfb36 --- /dev/null +++ b/fmpz_sparse_mat/hnf_minors.c @@ -0,0 +1,125 @@ +/* + Copyright (C) 2014 Alex J. Best + Copyright (C) 2017 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +/* + This is the algorithm of Kannan, Bachem, "Polynomial algorithms for computing + the Smith and Hermite normal forms of an integer matrix", Siam J. Comput., + Vol. 8, No. 4, pp. 499-507. +*/ +slong +fmpz_sparse_mat_hnf_minors(fmpz_sparse_mat_t M) +{ + + slong i, r, c, pr, pc, rank, remr, nnz; + slong *P; /* Row permutation */ + slong *Pr; /* Assignment of pivot row to each column */ + fmpz_sparse_mat_with_transpose_t MT; + hashmap_struct *hcol; /* Virtual L^t and one of its rows */ + fmpz_t g, a, b, one; + + if (M->r == 0 || M->c == 0) return 0; + fmpz_init(g); + fmpz_init(a); + fmpz_init(b); + fmpz_init_set_ui(one, UWORD(1)); + + /* Construct virtual transpose */ + _fmpz_sparse_mat_with_transpose_init(MT, M); + + /* Set up permutation and its "inverse" */ + P = flint_malloc(M->r*sizeof(*P)); + Pr = flint_malloc(M->c*sizeof(*Pr)); + remr = M->r; + for (r = 0; r < M->r; ++r) + { + if (!M->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + + for (rank = pc = 0; pc < M->c; ++pc) + { + Pr[pc] = -1; + + /* Find first non-empty row which is not a previous pivot and eliminate cols up to pc */ + for (r = 0; r < M->r; ++r) + { + if (P[r] >= 0) continue; + + /* Reduce r by previous pivot rows */ + while ((c = M->rows[r].entries[0].ind) < pc) + { + _fmpz_sparse_mat_with_transpose_gauss_elim_ext(MT, Pr[c], r); + if (M->rows[r].nnz == 0) {P[r] = --remr; break;} + } + if (M->rows[r].nnz > 0 && M->rows[r].entries[0].ind == pc) break; + } + if (r == M->r) continue; /* No viable pivot for column */ + pr = r; + + if (fmpz_sgn(LT(M, r).val) < 0) + fmpz_sparse_vec_neg(&M->rows[r], &M->rows[r]); + + /* Use this row to reduce previous pivot rows */ + hcol = &MT->cols[pc]; nnz = hcol->num; + for (i = 0; i < nnz; ++i) + { + r = hcol->keys[i]; + if (r != pr && P[r] >= 0) + _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r); + } + Pr[pc] = pr; + P[pr] = rank++; + } + + /* Deal with any remaining rows */ + for(r = 0; r < M->r; ++r) + { + if (P[r] >= 0) continue; + + /* Reduce r by previous pivot rows */ + while ((c = M->rows[r].entries[0].ind) < M->c) + { + _fmpz_sparse_mat_with_transpose_gauss_elim_ext(MT, Pr[c], r); + if (M->rows[r].nnz == 0) {P[r] = --remr; break;} + } + } + + /* Since pivot rows were modified, need to re-reduce previous pivot rows */ + for (pc = 0; pc < M->c; ++pc) + { + if (Pr[pc] == -1) continue; /* No pivot for this column */ + pr = Pr[pc]; + hcol = &MT->cols[pc]; nnz = hcol->num; + for (i = 0; i < nnz; ++i) + { + r = hcol->keys[i]; + if (r == pr) continue; + + /* All other incident rows must be previous pivots */ + _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r); + } + } + + /* Apply row permutation */ + fmpz_sparse_mat_permute_rows (M, P); + + flint_free(P); + flint_free(Pr); + _fmpz_sparse_mat_with_transpose_clear(MT); + fmpz_clear(g); + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(one); + return rank; +} diff --git a/fmpz_sparse_mat/hnf_modular.c b/fmpz_sparse_mat/hnf_modular.c new file mode 100644 index 0000000000..36fdc1cc97 --- /dev/null +++ b/fmpz_sparse_mat/hnf_modular.c @@ -0,0 +1,111 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +slong +fmpz_sparse_mat_hnf_modular(fmpz_sparse_mat_t M, const fmpz_t det) +{ + slong i, r, pr, pc, rank, remr, nnz; + slong *P; /* Row permutation */ + slong *irows; /* Set of rows incident on a given column */ + slong nnp; /* Number of such rows which are not previous pivots */ + slong npp; /* Number of such rows which are previous pivots */ + fmpz_sparse_mat_with_transpose_t MT; + hashmap_struct *hcol; /* Virtual L^t and one of its rows */ + fmpz_t g, a, b, one, rem_det; + + if (M->r == 0 || M->c == 0 || M->r != M->c || fmpz_is_zero(det)) return 0; + fmpz_init(g); + fmpz_init(a); + fmpz_init(b); + fmpz_init_set_ui(one, UWORD(1)); + fmpz_init_set(rem_det, det); + + /* Construct virtual transpose */ + _fmpz_sparse_mat_with_transpose_init(MT, M); + + /* Set up permutation */ + P = flint_malloc(M->r*sizeof(*P)); + remr = M->r; + for (r = 0; r < M->r; ++r) + { + if (!M->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + + irows = NULL; + for (rank = pc = 0; pc < M->c; ++pc) + { + hcol = &MT->cols[pc]; nnz = hcol->num; + if(!nnz) continue; + irows = flint_realloc(irows, nnz*sizeof(*irows)); + pr = -1, nnp = 0, npp = 0; + + /* Find incident row pr which is not a previous pivot and has minimal leading term */ + /* Make pi_0 ... pi_{nnp-1} the other incident rows which are not previous pivots */ + /* and pi_{nnz-npp} ... pi_{nnz - 1} the incident rows which are previous pivots */ + for (i = 0; i < nnz; ++i) + { + r = hcol->keys[i]; + if (P[r] >= 0) + irows[hcol->num - (++npp)] = r; + else if (pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, pr).val) >= 0) + irows[nnp++] = r; + else + { + if (pr >= 0) irows[nnp++] = pr; + pr = r; + } + } + if(pr == -1) + { + /* Set pivot col in some non-pivot row to rem_det */ + for (pr = 0; pr < M->r; ++pr) + if (P[pr] == -1) break; + fmpz_sparse_vec_set_entry(&M->rows[pr], pc, rem_det); + fmpz_one(rem_det); + } + else + { + /* Eliminate non-pivot rows */ + for (i = 0; i < nnp; ++i) + _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mods(MT, pr, irows[i], rem_det); + + /* Minimize row modulo rem_det */ + fmpz_xgcd(g, a, b, LT(M, pr).val, rem_det); + + MT_FIX(MT, pr, + fmpz_sparse_vec_scalar_mul_fmpz(&M->rows[pr], &M->rows[pr], a); + fmpz_sparse_vec_scalar_mods_fmpz(&M->rows[pr], &M->rows[pr], rem_det); + if (M->rows[pr].nnz == 0 || LT(M, pr).ind != pc) + fmpz_sparse_vec_set_entry(&M->rows[pr], pc, rem_det); + ); + + fmpz_divexact(rem_det, rem_det, g); + } + /* Reduce previous pivot rows */ + for (i = nnz - npp; i < nnz; ++i) + _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, irows[i]); + P[pr] = rank++; + } + /* Apply row permutation */ + fmpz_sparse_mat_permute_rows (M, P); + + flint_free(P); + flint_free(irows); + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(one); + fmpz_clear(rem_det); + _fmpz_sparse_mat_with_transpose_clear(MT); + return M->r; +} diff --git a/fmpz_sparse_mat/hnf_modular_eldiv.c b/fmpz_sparse_mat/hnf_modular_eldiv.c new file mode 100644 index 0000000000..94b03bf2c0 --- /dev/null +++ b/fmpz_sparse_mat/hnf_modular_eldiv.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "nmod_sparse_mat.h" + +slong +fmpz_sparse_mat_hnf_modular_eldiv(fmpz_sparse_mat_t M, const fmpz_t n) +{ + slong i; + + if (fmpz_sparse_mat_is_zero(M)) return 0; + + if (fmpz_abs_fits_ui(n)) + { + /* TODO: have nmod version */ +/* nmod_init(&mod, fmpz_get_ui(n)); + nmod_sparse_mat_init(Mmod, M->r, M->c, mod); + fmpz_sparse_mat_get_nmod_sparse_mat(Mmod, M); + rank = nmod_sparse_mat_strong_echelon_form(Mmod); + fmpz_sparse_mat_set_nmod_sparse_mat_unsigned(M, Mmod); + nmod_sparse_mat_clear(Mmod); + */ } + + fmpz_sparse_mat_strong_echelon_form_mod(M, n); + + for (i = 0; i < M->r; ++i) + if (fmpz_sparse_vec_is_zero(&M->rows[i])) + fmpz_sparse_vec_set_entry(&M->rows[i], i, n); + return M->r; +} + diff --git a/fmpz_sparse_mat/hnf_xgcd.c b/fmpz_sparse_mat/hnf_xgcd.c new file mode 100644 index 0000000000..a1af9b4eb8 --- /dev/null +++ b/fmpz_sparse_mat/hnf_xgcd.c @@ -0,0 +1,92 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +slong fmpz_sparse_mat_hnf_xgcd(fmpz_sparse_mat_t M) +{ + slong i, r, pr, pc, rank, remr, nnz; + slong *P; /* Row permutation */ + slong *irows; /* Set of rows incident on a given column */ + slong nnp; /* Number of rows which are not pivots */ + slong npp; /* Number of rows which are previous pivots */ + fmpz_sparse_mat_with_transpose_t MT; + hashmap_struct *hcol; /* Virtual L^t and one of its rows */ + fmpz_t g, a, b, one; + + if (M->r == 0 || M->c == 0) return 0; + fmpz_init(g); + fmpz_init(a); + fmpz_init(b); + fmpz_init_set_ui(one, UWORD(1)); + + /* Construct virtual transpose */ + _fmpz_sparse_mat_with_transpose_init(MT, M); + + /* Set up permutation */ + P = flint_malloc(M->r*sizeof(*P)); + remr = M->r; + for (r = 0; r < M->r; ++r) + { + if (!M->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + irows = flint_malloc(M->r * sizeof(*irows)); + + for (rank = pc = 0; pc < M->c; ++pc) + { + hcol = &MT->cols[pc]; nnz = hcol->num; + if(!nnz) continue; + pr = -1, nnp = 0, npp = 0; + + for (i = 0; i < nnz; ++i) + { + r = hcol->keys[i]; + if (P[r] >= 0) /* Put previous pivot rows at end of irows */ + irows[hcol->num - (++npp)] = r; + else if (pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, pr).val) >= 0) + irows[nnp++] = r; /* Put non-pivot rows with larger entries at beginning of irows */ + else /* Replace the pivot row with the current row */ + { + if (pr >= 0) irows[nnp++] = pr; + pr = r; + } + } + if(pr == -1) continue; + + /* Eliminate larger, non-pivot rows */ + for (i = 0; i < nnp; ++i) + { + r = irows[i]; + _fmpz_sparse_mat_with_transpose_gauss_elim_ext(MT, pr, r); + if(M->rows[r].nnz == 0) P[r] = --remr; + } + + if (fmpz_sgn(LT(M, pr).val) < 0) + fmpz_sparse_vec_neg(&M->rows[pr], &M->rows[pr]); + + /* Reduce previous pivot rows incident to pivot column */ + for (i = nnz - npp; i < nnz; ++i) + _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, irows[i]); + P[pr] = rank++; + } + + /* Apply row permutation */ + fmpz_sparse_mat_permute_rows (M, P); + + flint_free(P); + flint_free(irows); + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(one); + _fmpz_sparse_mat_with_transpose_clear(MT); + return rank; +} diff --git a/fmpz_sparse_mat/howell_form_mod.c b/fmpz_sparse_mat/howell_form_mod.c new file mode 100644 index 0000000000..5839ef8fec --- /dev/null +++ b/fmpz_sparse_mat/howell_form_mod.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +slong +fmpz_sparse_mat_howell_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) +{ + slong i, *P, rank = 0, remr = M->r; + + if (fmpz_sparse_mat_is_zero(M)) return 0; + + fmpz_sparse_mat_strong_echelon_form_mod(M, mod); + P = flint_malloc(M->r*sizeof(*P)); + for (i = 0; i < M->r; ++i) + { + if (M->rows[i].nnz > 0) P[i] = rank++; + else P[i] = --remr; + } + /* Apply row permutation */ + fmpz_sparse_mat_permute_rows (M, P); + flint_free(P); + return rank; +} + diff --git a/fmpz_sparse_mat/is_in_hnf.c b/fmpz_sparse_mat/is_in_hnf.c new file mode 100644 index 0000000000..8a3be06c8e --- /dev/null +++ b/fmpz_sparse_mat/is_in_hnf.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +int fmpz_sparse_mat_is_in_hnf(const fmpz_sparse_mat_t A) +{ + slong pr, rk, pc, prev_pc, r; + fmpz_t *ptr; + + /* Compute the rank (assuming HNF form) */ + for (rk = A->r; rk != 0; rk--) + { + if (!fmpz_sparse_vec_is_zero(&A->rows[rk - 1]) && LT(A, rk - 1).ind < A->c) break; + } + + /* Check that first rk rows are in HNF */ + prev_pc = -1; + for (pr = 0; pr < rk; pr++) + { + if (fmpz_sparse_vec_is_zero(&A->rows[pr])) return 0; + pc = LT(A, pr).ind; + if (pc >= A->c || pc <= prev_pc || fmpz_sgn(LT(A, pr).val) < 0) return 0; + + for (r = 0; r < pr; r++) + { + ptr = fmpz_sparse_vec_at(&A->rows[r], pc); + if (ptr && ((fmpz_sgn(*ptr) < 0) || (fmpz_cmp(*ptr, LT(A, pr).val) >= 0))) return 0; + } + prev_pc = pc; + } + + return 1; +} diff --git a/fmpz_sparse_mat/max_bits.c b/fmpz_sparse_mat/max_bits.c new file mode 100644 index 0000000000..2a9f46888a --- /dev/null +++ b/fmpz_sparse_mat/max_bits.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "hashmap.h" +#include "longlong.h" + +slong fmpz_sparse_mat_max_bits(const fmpz_sparse_mat_t M) +{ + slong i; + slong bits, row_bits, sign; + + sign = 1; + bits = 0; + + if (M->r == 0 || M->c == 0) + return 0; + + for (i = 0; i < M->r; i++) + { + row_bits = fmpz_sparse_vec_max_bits(&M->rows[i]); + if (row_bits < 0) + { + row_bits = -row_bits; + sign = -1; + } + bits = FLINT_MAX(bits, row_bits); + } + return bits * sign; +} \ No newline at end of file diff --git a/fmpz_sparse_mat/multi_CRT_ui.c b/fmpz_sparse_mat/multi_CRT_ui.c new file mode 100644 index 0000000000..77946c9bb0 --- /dev/null +++ b/fmpz_sparse_mat/multi_CRT_ui.c @@ -0,0 +1,50 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_multi_CRT_ui_precomp(fmpz_sparse_mat_t M, + nmod_sparse_mat_struct * residues, slong nres, + const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) +{ + slong i, j; + nmod_sparse_vec_struct *vres; + + vres = flint_malloc(nres * sizeof(*vres)); + + for (i = 0; i < M->r; i++) + { + for (j = 0; j < nres; ++j) vres[j] = residues[j].rows[i]; + fmpz_sparse_vec_multi_CRT_ui_precomp(&M->rows[i], vres, nres, comb, temp, sign); + } + flint_free(vres); +} + +void +fmpz_sparse_mat_multi_CRT_ui(fmpz_sparse_mat_t mat, nmod_sparse_mat_struct * residues, slong nres, int sign) +{ + slong i; + mp_limb_t *primes; + fmpz_comb_t comb; + fmpz_comb_temp_t temp; + + primes = flint_malloc(nres * sizeof(*primes)); + for (i = 0; i < nres; i++) primes[i] = residues[i].mod.n; + fmpz_comb_init(comb, primes, nres); + fmpz_comb_temp_init(temp, comb); + + fmpz_sparse_mat_multi_CRT_ui_precomp(mat, residues, nres, comb, temp, sign); + + fmpz_comb_clear(comb); + fmpz_comb_temp_clear(temp); + flint_free(primes); +} diff --git a/fmpz_sparse_mat/multi_mod_ui.c b/fmpz_sparse_mat/multi_mod_ui.c new file mode 100644 index 0000000000..a9b0c4773e --- /dev/null +++ b/fmpz_sparse_mat/multi_mod_ui.c @@ -0,0 +1,58 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +/* for (j = 0; j < fmpz_mat_ncols(mat); j++) + { + fmpz_multi_mod_ui(r, fmpz_mat_entry(mat, i, j), comb, temp); + for (k = 0; k < nres; k++) + nmod_mat_entry(residues[k], i, j) = r[k]; + } + */ +void +fmpz_sparse_mat_multi_mod_ui_precomp(nmod_sparse_mat_struct * residues, slong nres, const fmpz_sparse_mat_t M, + const fmpz_comb_t comb, fmpz_comb_temp_t temp) +{ + slong i, j; + nmod_sparse_vec_struct *vres; + + vres = flint_malloc(nres * sizeof(*vres)); + + for (i = 0; i < M->r; i++) + { + for (j = 0; j < nres; ++j) vres[j] = residues[j].rows[i]; + fmpz_sparse_vec_multi_mod_ui_precomp(vres, nres, &M->rows[i], comb, temp); + for (j = 0; j < nres; ++j) residues[j].rows[i] = vres[j]; + + } + flint_free(vres); +} + +void +fmpz_sparse_mat_multi_mod_ui(nmod_sparse_mat_struct * residues, slong nres, const fmpz_sparse_mat_t M) +{ + slong i; + mp_limb_t *primes; + fmpz_comb_t comb; + fmpz_comb_temp_t temp; + + primes = flint_malloc(nres * sizeof(*primes)); + for (i = 0; i < nres; i++) primes[i] = residues[i].mod.n; + fmpz_comb_init(comb, primes, nres); + fmpz_comb_temp_init(temp, comb); + + fmpz_sparse_mat_multi_mod_ui_precomp(residues, nres, M, comb, temp); + + fmpz_comb_clear(comb); + fmpz_comb_temp_clear(temp); + flint_free(primes); +} diff --git a/fmpz_sparse_mat/print_pretty.c b/fmpz_sparse_mat/print_pretty.c new file mode 100644 index 0000000000..f000cf9509 --- /dev/null +++ b/fmpz_sparse_mat/print_pretty.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_print_pretty(const fmpz_sparse_mat_t M) +{ + slong i; + char row_fmt[FLINT_BITS + 5]; + flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(M->r, 10)); + + flint_printf("<%wd x %wd sparse integer matrix>\n", + M->r, M->c); + + for (i = 0; i < M->r; i++) + { + flint_printf(row_fmt, i); + fmpz_sparse_vec_print_pretty(&M->rows[i], M->c_off, M->c); + } +} diff --git a/fmpz_sparse_mat/randtest.c b/fmpz_sparse_mat/randtest.c new file mode 100644 index 0000000000..c0d260028b --- /dev/null +++ b/fmpz_sparse_mat/randtest.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_randtest(fmpz_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, flint_bitcnt_t bits) +{ + slong i, nnz; + + for (i = 0; i < M->r; ++i) + { + nnz = n_randint(state, max_nnz+1); + nnz = FLINT_MAX(nnz, min_nnz); + fmpz_sparse_vec_randtest(&M->rows[i], state, nnz, M->c, bits); + } +} + diff --git a/fmpz_sparse_mat/randtest_unsigned.c b/fmpz_sparse_mat/randtest_unsigned.c new file mode 100644 index 0000000000..e637dd377c --- /dev/null +++ b/fmpz_sparse_mat/randtest_unsigned.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_randtest_unsigned(fmpz_sparse_mat_t M, flint_rand_t state, slong min_nnz, slong max_nnz, flint_bitcnt_t bits) +{ + slong i, nnz; + + for (i = 0; i < M->r; ++i) + { + nnz = n_randint(state, max_nnz+1); + nnz = FLINT_MAX(nnz, min_nnz); + fmpz_sparse_vec_randtest_unsigned(&M->rows[i], state, nnz, M->c, bits); + } +} + diff --git a/fmpz_sparse_mat/solve_bound.c b/fmpz_sparse_mat/solve_bound.c new file mode 100644 index 0000000000..efe70349b0 --- /dev/null +++ b/fmpz_sparse_mat/solve_bound.c @@ -0,0 +1,46 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_solve_bound(fmpz_t N, fmpz_t D, + const fmpz_sparse_mat_t A, const fmpz_mat_t B) +{ + slong i, j; + fmpz_t t, u; + + /* Get product of row norms of A */ + fmpz_sparse_mat_det_bound(D, A); + + fmpz_init(t); + fmpz_init(u); + + fmpz_zero(t); + + /* Get largest column norm of B */ + for (j = 0; j < B->c; j++) + { + fmpz_zero(u); + for (i = 0; i < A->r; i++) + fmpz_addmul(u, fmpz_mat_entry(B, i, j), fmpz_mat_entry(B, i, j)); + if (fmpz_cmp(t, u) < 0) + fmpz_set(t, u); + } + fmpz_sqrtrem(t, u, t); + if (!fmpz_is_zero(u)) + fmpz_add_ui(t, t, UWORD(1)); + + fmpz_mul(N, D, t); + + fmpz_clear(t); + fmpz_clear(u); +} diff --git a/fmpz_sparse_mat/solve_dixon.c b/fmpz_sparse_mat/solve_dixon.c new file mode 100644 index 0000000000..3dec84fedc --- /dev/null +++ b/fmpz_sparse_mat/solve_dixon.c @@ -0,0 +1,235 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpq_mat.h" +#include "fmpz_sparse_mat.h" + +static mp_limb_t find_good_prime_and_invert(nmod_sparse_mat_t Ainv, const fmpz_sparse_mat_t A, const fmpz_t D) +{ + nmod_t nmod; + slong rk = 0; + mp_limb_t p; + fmpz_t prod; + fmpz_init(prod); + + /* Find a prime to use for Hensel lifting, i.e., one modulo which A is invertible */ + p = n_nextprime(UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS, 0); + for (fmpz_one(prod); fmpz_cmp(prod, D) <= 0; fmpz_mul_ui(prod, prod, p), p = n_nextprime(p, 0)) + { + nmod_init(&nmod, p); + nmod_sparse_mat_init(Ainv, A->r, A->r, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(Ainv, A); + rk = nmod_sparse_mat_inv(Ainv, Ainv); + if (rk == A->r) break; + nmod_sparse_mat_clear(Ainv); + } + if (rk != A->r) p = 0; /* Failed to invert matrix modulo prime == probably not invertible */ + fmpz_clear(prod); + return p; +} + +static nmod_sparse_mat_struct * get_mod_mats(slong *num_primes, const fmpz_sparse_mat_t A, mp_limb_t p) +{ + slong np; + nmod_t nmod; + fmpz_t prod, bound; + nmod_sparse_mat_struct *A_mod; + fmpz_init(prod); + + /* Get bound on product of primes needed to recover Ay via CRT */ + fmpz_init_set_ui(bound, p); /* size of y */ + fmpz_mul_2exp(bound, bound, FLINT_ABS(fmpz_sparse_mat_max_bits(A))+1); /* Size of A + sign */ + fmpz_mul_ui(bound, bound, A->r); /* Entries in dot product */ + + np = fmpz_bits(bound) / (FLINT_BIT_COUNT(p) - 1) + 2; /* Overestimate */ + A_mod = flint_malloc(np * sizeof(*A_mod)); + np = 0; + for (fmpz_one(prod); fmpz_cmp(prod, bound) < 0; fmpz_mul_ui(prod, prod, p), p = n_nextprime(p, 0)) + { + nmod_init(&nmod, p); + nmod_sparse_mat_init(&A_mod[np], A->r, A->r, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(&A_mod[np++], A); + } + fmpz_clear(prod); + fmpz_clear(bound); + *num_primes = np; + return flint_realloc(A_mod, np*sizeof(*A_mod)); +} + +int +_fmpq_mat_check_solution_fmpz_sparse_mat(const fmpq_mat_t X, const fmpz_sparse_mat_t A, const fmpz_mat_t B) +{ + slong i, j; + fmpz_mat_t Xclear, AXclear; + fmpz_t t; + fmpz * Xden; + int ok; + + Xden = _fmpz_vec_init(X->c); + fmpz_mat_init(Xclear, X->r, X->c); + fmpz_mat_init(AXclear, X->r, X->c); + fmpz_init(t); + + fmpq_mat_get_fmpz_mat_colwise(Xclear, Xden, X); + fmpz_sparse_mat_mul_mat(AXclear, A, Xclear); + + ok = 1; + for (i = 0; i < B->r && ok; i++) + { + for (j = 0; j < B->c && ok; j++) + { + /* AXclear[i,j] / Xden[j] = B[i,j] */ + fmpz_mul(t, fmpz_mat_entry(B, i, j), Xden + j); + + if (!fmpz_equal(t, fmpz_mat_entry(AXclear, i, j))) + ok = 0; + } + } + + _fmpz_vec_clear(Xden, X->c); + fmpz_mat_clear(Xclear); + fmpz_mat_clear(AXclear); + fmpz_clear(t); + + return ok; +} + +int _fmpz_sparse_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_sparse_mat_t A, const fmpz_mat_t B, int rat_sol) +{ + slong i, j, jcheck, num_primes; + mp_limb_t p; + fmpz_t N, D, bound, prod; + nmod_sparse_mat_struct *A_mod; + nmod_sparse_mat_t Ainv; + nmod_mat_t d_mod, y_mod, Ay_mod; + fmpz_mat_t d, y, Ay; + fmpq_mat_t Q; + + if (A->r != A->c) + { + flint_printf("Exception (fmpz_sparse_mat_solve_dixon). Non-square system matrix.\n"); + flint_abort(); + } + + if (A->r == 0 || A->c == 0 || B->c == 0) return 1; + if (fmpz_sparse_mat_is_zero(A)) return 0; + + fmpz_init(N); + fmpz_init(D); + fmpz_sparse_mat_solve_bound(N, D, A, B); + p = find_good_prime_and_invert(Ainv, A, D); + if(p == 0) + { + fmpz_clear(N); + fmpz_clear(D); + return 0; + } + + /* Get collection of primes ~ p and construct A mod each */ + A_mod = get_mod_mats(&num_primes, A, p); + + /* Get bound on modulus for Hensel lift */ + fmpz_init(bound); + if (fmpz_cmpabs(N, D) < 0) + fmpz_mul(bound, D, D); + else + fmpz_mul(bound, N, N); + fmpz_mul_ui(bound, bound, UWORD(2)); /* signs */ + + fmpz_mat_init(d, A->r, B->c); + fmpz_mat_init(y, A->r, B->c); + fmpz_mat_init(Ay, A->r, B->c); + nmod_mat_init(d_mod, A->r, B->c, p); + nmod_mat_init(y_mod, A->r, B->c, p); + nmod_mat_init(Ay_mod, A->r, B->c, p); + if (rat_sol) fmpq_mat_init(Q, A->r, B->c); + + /* Initialize X to y = A^-1 b mod p */ + fmpz_init(prod); + fmpz_mat_set(d, B); + fmpz_mat_get_nmod_mat(d_mod, d); + nmod_sparse_mat_mul_mat(y_mod, Ainv, d_mod); + fmpz_mat_set_nmod_mat_unsigned(X, y_mod); + j = jcheck = 1; + for (fmpz_set_ui(mod, p); fmpz_cmp(mod, bound) <= 0; fmpz_mul_ui(mod, mod, p)) + { + if (rat_sol && j == jcheck) + { + if (fmpq_mat_set_fmpz_mat_mod_fmpz(Q, X, mod) && _fmpq_mat_check_solution_fmpz_sparse_mat(Q, A, B)) + break; + jcheck = (slong)(j*1.4) + 1; /* Set when to check next */ + + } + /* Construct Ay via CRT */ + for (i = 0; i < num_primes; i++) + { + _nmod_mat_set_mod(y_mod, A_mod[i].mod.n); + _nmod_mat_set_mod(Ay_mod, A_mod[i].mod.n); + nmod_sparse_mat_mul_mat(Ay_mod, &A_mod[i], y_mod); + if (i == 0) + { + fmpz_mat_set_nmod_mat(Ay, Ay_mod); + fmpz_set_ui(prod, p); + } + else + { + fmpz_mat_CRT_ui(Ay, Ay, prod, Ay_mod, 1); + fmpz_mul_ui(prod, prod, A_mod[i].mod.n); + } + } + /* fmpz_mat_set_nmod_mat_unsigned(y, y_mod); + fmpz_mat_mul(Ay, A, y); */ + + /* Update d = (d - Ay) / p */ + fmpz_mat_sub(d, d, Ay); + fmpz_mat_scalar_divexact_ui(d, d, p); + fmpz_mat_get_nmod_mat(d_mod, d); + + /* Update x = x + (A^(-1) * d mod p) * p^i [= A^(-1) * b mod p^(i+1)] */ + _nmod_mat_set_mod(y_mod, p); + nmod_sparse_mat_mul_mat(y_mod, Ainv, d_mod); + fmpz_mat_scalar_addmul_nmod_mat_fmpz(X, y_mod, mod); + } + if (rat_sol) + { + if (fmpz_cmp(mod, bound) > 0) fmpq_mat_set_fmpz_mat_mod_fmpz(Q, X, mod); + fmpq_mat_get_fmpz_mat_matwise(X, mod, Q); + fmpq_mat_clear(Q); + } + + nmod_mat_clear(d_mod); + nmod_mat_clear(y_mod); + nmod_mat_clear(Ay_mod); + fmpz_mat_clear(d); + fmpz_mat_clear(y); + fmpz_mat_clear(Ay); + + for (i = 0; i < num_primes; i++) nmod_sparse_mat_clear(&A_mod[i]); + flint_free(A_mod); + + fmpz_clear(bound); + fmpz_clear(prod); + + nmod_sparse_mat_clear(Ainv); + fmpz_clear(N); + fmpz_clear(D); + return 1; +} + +int fmpz_sparse_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_sparse_mat_t A, const fmpz_mat_t B) +{ + return _fmpz_sparse_mat_solve_dixon(X, mod, A, B, 0); +} + +int fmpz_sparse_mat_solve_dixon_den(fmpz_mat_t X, fmpz_t den, const fmpz_sparse_mat_t A, const fmpz_mat_t B) +{ + return _fmpz_sparse_mat_solve_dixon(X, den, A, B, 1); +} diff --git a/fmpz_sparse_mat/strong_echelon_form_mod.c b/fmpz_sparse_mat/strong_echelon_form_mod.c new file mode 100644 index 0000000000..6b1af06f42 --- /dev/null +++ b/fmpz_sparse_mat/strong_echelon_form_mod.c @@ -0,0 +1,189 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" + + + + +/* Multiply by unit to minimize leading term (to a factor of N) */ +static void scale_row(fmpz_sparse_mat_with_transpose_t MT, slong r, const fmpz_t mod) +{ + fmpz_t g, a, b, n; + if(!fmpz_is_one(LT(MT->M, r).val)) + { + fmpz_init(g); + fmpz_init(a); + fmpz_init(b); + fmpz_xgcd(g, a, b, LT(MT->M, r).val, mod); + if(!fmpz_is_one(g)) /* Need to lift a = (M[pr][pc]/g)^-1 mod N/g to a unit modulo N */ + { + fmpz_divexact(b, mod, g); + fmpz_init_set(n, mod); + while (!fmpz_is_one(g)) + { + fmpz_gcd(g, a, n); + fmpz_divexact(n, n, g); + } + fmpz_addmul(a, n, b); + fmpz_mod(a, a, mod); + fmpz_clear(n); + } + MT_FIX(MT, r, + fmpz_sparse_vec_scalar_mul_fmpz(&MT->M->rows[r], &MT->M->rows[r], a); + fmpz_sparse_vec_scalar_mod_fmpz(&MT->M->rows[r], &MT->M->rows[r], mod); + ); + fmpz_clear(g); + fmpz_clear(a); + fmpz_clear(b); + } +} + +slong +fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) +{ + slong i, r, c, pr, pc, rank, remr, nzrows; + slong *P; /* Row permutation */ + slong *Pr; /* Map from column to associated pivot row */ + slong *irows; /* Set of rows incident on a given column */ + slong *zrows; /* Set of empty rows */ + slong nnp; /* Number of such rows which are not pivots */ + slong npp; /* Number of such rows which are not pivots */ + fmpz_sparse_mat_with_transpose_t MT; + hashmap_struct *hcol; /* Virtual L^t and one of its rows */ + fmpz_t q, zero; + fmpz_sparse_vec_t zero_vec; + + if (fmpz_sparse_mat_is_zero(M)) return 0; + fmpz_init(zero); + fmpz_init(q); + + /* Final object must have at least as many rows as columns */ + fmpz_sparse_vec_init(zero_vec); + while(M->r < M->c) fmpz_sparse_mat_append_row(M, zero_vec); + + /* Need extra row to deal with final elimination */ + fmpz_sparse_mat_append_row(M, zero_vec); + + /* Initialize data structure to hold copy of incident rows of a given column */ + irows = flint_malloc(M->r*sizeof(*irows)); + zrows = flint_malloc(M->r*sizeof(*zrows)); + + fmpz_sparse_mat_scalar_mod_fmpz(M, M, mod); + + /* Set up permutation */ + P = flint_malloc(M->r*sizeof(*P)); + remr = M->r, nzrows = 0; + for (r = 0; r < M->r; ++r) + { + if (!M->rows[r].nnz) P[r] = --remr, zrows[nzrows++] = r; + else P[r] = -1; + } + + /* Set up pivot row mapping */ + Pr = flint_malloc(M->c*sizeof(*Pr)); + for (c = 0; c < M->c; ++c) + Pr[c] = -1; + + /* Construct virtual transpose */ + _fmpz_sparse_mat_with_transpose_init(MT, M); + + for (pc = 0; pc < M->c; ++pc) + { + hcol = &MT->cols[pc]; + if(!hcol->num) continue; + pr = -1, nnp = 0; + + /* Find incident row pr which is not a previous pivot and has minimal leading term */ + /* Make pi_0 ... pi_{nnp-1} the other incident rows which are not previous pivots */ + for (i = 0; i < hcol->num; ++i) + { + r = hcol->keys[i]; + if (P[r] >= 0) continue; + else if (pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, pr).val) >= 0) + irows[nnp++] = r; + else + { + if (pr >= 0) irows[nnp++] = pr; + pr = r; + } + } + if(pr == -1) continue; /* Cannot perform elimination on this column (yet) */ + scale_row(MT, pr, mod); + Pr[pc] = pr, P[pr] = pc; + + /* Eliminate non-pivot rows */ + for (i = 0; i < nnp; ++i) + { + r = irows[i]; + _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mod(MT, pr, r, mod); + if (M->rows[r].nnz == 0) P[r] = --remr, zrows[nzrows++] = r; + } + } + + /* Reduce upwards, and deal with non-unit leading terms */ + for (pc = 0; pc < M->c; pc++) + { + if (Pr[pc] == -1) {P[zrows[--nzrows]] = pc; continue;} /* No pivot for this column */ + hcol = &MT->cols[pc]; + pr = Pr[pc]; + + /* Reduce previous pivot rows */ + for (i = npp = 0; i < hcol->num; ++i) + if (hcol->keys[i] != pr) + irows[npp++] = hcol->keys[i]; + for (i = 0; i < npp; ++i) + { + _fmpz_sparse_mat_with_transpose_gauss_elim_mod(MT, pr, irows[i], mod); + } + if (fmpz_is_one(LT(M, pr).val)) continue; + + /* Obtain (possibly) new basis element by scalar multiplicition */ + r = zrows[--nzrows]; + fmpz_divexact(q, mod, LT(M, pr).val); + MT_FIX(MT, r, + fmpz_sparse_vec_scalar_mul_fmpz(&M->rows[r], &M->rows[pr], q); + fmpz_sparse_vec_scalar_mod_fmpz(&M->rows[r], &M->rows[r], mod); + ); + + while(!fmpz_sparse_vec_is_zero(&M->rows[r])) + { + c = M->rows[r].entries[0].ind; + /* If no previous pivot row exists, use this row */ + if (Pr[c] == -1) { + scale_row(MT, r, mod); + Pr[c] = r; P[r] = c; + break; + } + + /* Otherwise, eliminate c using existing pivot */ + _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mod(MT, Pr[c], r, mod); + if(!fmpz_sparse_vec_is_zero(&M->rows[r]) && LT(M, r).ind == c) flint_abort(); + } + /* If row fully eliminated, add back to empty stock */ + + if (fmpz_sparse_vec_is_zero(&M->rows[r])) nzrows++; + + } + fmpz_sparse_mat_permute_rows(M, P); + fmpz_clear(zero); + fmpz_clear(q); + flint_free(irows); + flint_free(zrows); + fmpz_sparse_vec_clear(zero_vec); + M->r -= 1; + M->rows = realloc(M->rows, M->r*sizeof(*M->rows)); + _fmpz_sparse_mat_with_transpose_clear(MT); + flint_free(P); + flint_free(Pr); + return rank; +} + diff --git a/fmpz_sparse_mat/test/t-CRT_ui.c b/fmpz_sparse_mat/test/t-CRT_ui.c new file mode 100644 index 0000000000..4248181b86 --- /dev/null +++ b/fmpz_sparse_mat/test/t-CRT_ui.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2007 William Hart and David Harvey + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" +#include "nmod_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, prime_bits, num_primes, j, nreps = 1000; + mp_limb_t primes[1000]; + nmod_t nmod; + fmpz_t mod; + nmod_sparse_mat_t Amod; + fmpz_sparse_mat_t A, B; + FLINT_TEST_INIT(state); + + flint_printf("CRT_ui...."); + fflush(stdout); + + + for (rep = 0; rep < nreps; rep++) + { + bits = n_randint(state, 500) + 2; + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + prime_bits = 1 + n_randint(state, FLINT_BITS - 1); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + + fmpz_init_set_ui(mod, UWORD(1)); + for (num_primes = 0; fmpz_bits(mod) <= bits + 1; num_primes++) + { + primes[num_primes] = n_nextprime((num_primes == 0) ? (UWORD(1) << prime_bits) : primes[num_primes - 1], 0); + nmod_init(&nmod, primes[num_primes]); + nmod_sparse_mat_init(Amod, r, c, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(Amod, A); + if (num_primes == 0) + fmpz_sparse_mat_set_nmod_sparse_mat(B, Amod); + else + fmpz_sparse_mat_CRT_ui(B, B, mod, Amod, 1); + fmpz_mul_ui(mod, mod, primes[num_primes]); + nmod_sparse_mat_clear(Amod); + } + if (!fmpz_sparse_mat_equal(B, A)) + { + flint_printf("FAIL!\n"); + flint_printf("primes: "); + for (j = 0; j < num_primes; j++) + flint_printf("%wu ", primes[j]); + flint_printf("\nA: \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("\nB: \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c b/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c new file mode 100644 index 0000000000..4507517234 --- /dev/null +++ b/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2007 William Hart and David Harvey + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" +#include "nmod_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, prime_bits, num_primes, j, nreps = 1000; + mp_limb_t primes[1000]; + nmod_t nmod; + fmpz_t mod; + nmod_sparse_mat_t Amod; + fmpz_sparse_mat_t A, B; + FLINT_TEST_INIT(state); + + flint_printf("CRT_ui_unsigned...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = n_randint(state, 500) + 1; + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + prime_bits = 1 + n_randint(state, FLINT_BITS - 1); + + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + + fmpz_sparse_mat_randtest_unsigned(A, state, min_nnz, max_nnz, bits); + + fmpz_init_set_ui(mod, UWORD(1)); + for (num_primes = 0; fmpz_bits(mod) <= bits; num_primes++) + { + primes[num_primes] = n_nextprime((num_primes == 0) ? (UWORD(1) << prime_bits) : primes[num_primes - 1], 0); + nmod_init(&nmod, primes[num_primes]); + nmod_sparse_mat_init(Amod, r, c, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(Amod, A); + if (num_primes == 0) + fmpz_sparse_mat_set_nmod_sparse_mat_unsigned(B, Amod); + else + fmpz_sparse_mat_CRT_ui(B, B, mod, Amod, 0); + fmpz_mul_ui(mod, mod, primes[num_primes]); + nmod_sparse_mat_clear(Amod); + } + + if (!fmpz_sparse_mat_equal(B, A)) + { + flint_printf("FAIL!\n"); + flint_printf("primes: "); + for (j = 0; j < num_primes; j++) + flint_printf("%wu ", primes[j]); + flint_printf("\nA: \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("\nB: \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-add.c b/fmpz_sparse_mat/test/t-add.c new file mode 100644 index 0000000000..f7ea70b5f7 --- /dev/null +++ b/fmpz_sparse_mat/test/t-add.c @@ -0,0 +1,61 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c; + fmpz_sparse_mat_t A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 200); + c = n_randint(state, 200); + + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + fmpz_sparse_mat_init(C, r, c); + fmpz_sparse_mat_init(D, r, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_randtest(B, state, 0, c, bits); + + fmpz_sparse_mat_add(C, A, B); + fmpz_sparse_mat_sub(D, C, B); + + if (!fmpz_sparse_mat_equal(D, A)) + { + flint_printf("FAIL\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + fmpz_sparse_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-concat_horizontal.c b/fmpz_sparse_mat/test/t-concat_horizontal.c new file mode 100644 index 0000000000..98281de443 --- /dev/null +++ b/fmpz_sparse_mat/test/t-concat_horizontal.c @@ -0,0 +1,101 @@ +/* + + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int main(void) +{ + slong rep, bits, r, c1, c2, nreps = 100; + fmpz_sparse_mat_t A, B, C; + fmpz_sparse_mat_t window1, window2; + FLINT_TEST_INIT(state); + + flint_printf("concat_horizontal...."); + fflush(stdout); + + + for (rep = 0; rep < nreps; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 20); + c1 = n_randint(state, 20); + c2 = n_randint(state, 20); + fmpz_sparse_mat_init(A, r, c1); + fmpz_sparse_mat_init(B, r, c2); + fmpz_sparse_mat_init(C, r, c1+c2); + + fmpz_sparse_mat_randtest(A, state, 0, c1, bits); + fmpz_sparse_mat_randtest(B, state, 0, c2, bits); + fmpz_sparse_mat_randtest(C, state, 0, c1+c2, bits); + + fmpz_sparse_mat_concat_horizontal(C, A, B); + + fmpz_sparse_mat_window_init(window1, C, 0, 0, r, c1); + fmpz_sparse_mat_window_init(window2, C, 0, c1, r, c1+c2); + + if (!fmpz_sparse_mat_equal(window1, A) || !fmpz_sparse_mat_equal(window2, B)) + { + flint_printf("A = \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("A | B = \n"); + fmpz_sparse_mat_print_pretty(C); + flint_printf("window1 = \n"); + fmpz_sparse_mat_print_pretty(window1); + flint_printf("window2 = \n"); + fmpz_sparse_mat_print_pretty(window2); + flint_printf("FAIL: window 2 not equal\n"); + abort(); + } + + fmpz_sparse_mat_window_clear(window1); + fmpz_sparse_mat_window_clear(window2); + + fmpz_sparse_mat_init(window1, r, c1); + fmpz_sparse_mat_init(window2, r, c2); + fmpz_sparse_mat_split_horizontal(window1, window2, C, c1); + + if (!(fmpz_sparse_mat_equal(window1, A) && fmpz_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("A | B = \n"); + fmpz_sparse_mat_print_pretty(C); + flint_printf("window1 = \n"); + fmpz_sparse_mat_print_pretty(window1); + flint_printf("window2 = \n"); + fmpz_sparse_mat_print_pretty(window2); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + fmpz_sparse_mat_clear(window1); + fmpz_sparse_mat_clear(window2); + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-concat_vertical.c b/fmpz_sparse_mat/test/t-concat_vertical.c new file mode 100644 index 0000000000..a42c8b20e0 --- /dev/null +++ b/fmpz_sparse_mat/test/t-concat_vertical.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int main(void) +{ + slong rep, bits, r1, r2, c, nreps = 100; + fmpz_sparse_mat_t A, B, C; + fmpz_sparse_mat_t window1, window2; + FLINT_TEST_INIT(state); + + + flint_printf("concat_vertical...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r1 = n_randint(state, 100); + r2 = n_randint(state, 100); + c = n_randint(state, 100); + fmpz_sparse_mat_init(A, r1, c); + fmpz_sparse_mat_init(B, r2, c); + fmpz_sparse_mat_init(C, r1+r2, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_randtest(B, state, 0, c, bits); + fmpz_sparse_mat_randtest(C, state, 0, c, bits); + + fmpz_sparse_mat_concat_vertical(C, A, B); + + fmpz_sparse_mat_window_init(window1, C, 0, 0, r1, c); + fmpz_sparse_mat_window_init(window2, C, r1, 0, r1+r2, c); + + if (!(fmpz_sparse_mat_equal(window1, A) && fmpz_sparse_mat_equal(window2, B))) + { + flint_printf("A = \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("A concat_vertical B = \n"); + fmpz_sparse_mat_print_pretty(C); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + fmpz_sparse_mat_window_clear(window1); + fmpz_sparse_mat_window_clear(window2); + + fmpz_sparse_mat_init(window1, r1, c); + fmpz_sparse_mat_init(window2, r2, c); + fmpz_sparse_mat_split_vertical(window1, window2, C, r1); + + if (!fmpz_sparse_mat_equal(window1, A) || !fmpz_sparse_mat_equal(window2, B)) + { + flint_printf("A = \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("B = \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("A concat_vertical B = \n"); + fmpz_sparse_mat_print_pretty(C); + flint_printf("FAIL: results not equal\n"); + abort(); + } + + fmpz_sparse_mat_clear(window1); + fmpz_sparse_mat_clear(window2); + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-construct.c b/fmpz_sparse_mat/test/t-construct.c new file mode 100644 index 0000000000..eb101e62b2 --- /dev/null +++ b/fmpz_sparse_mat/test/t-construct.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c, i, j, k, nnz; + fmpz_sparse_mat_t A, B, C; + slong *rows; + slong *cols; + fmpz *vals; + FLINT_TEST_INIT(state); + + flint_printf("construction from entries...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + r = 1; /*n_randint(state, 10);*/ + c = n_randint(state, 10); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + fmpz_sparse_mat_init(C, 0, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_randtest(B, state, 0, c, bits); + nnz = 0; + for (i = 0; i < r; ++i) nnz += A->rows[i].nnz; + + /* Construct B from entries of A */ + rows = flint_malloc(nnz * sizeof(*rows)); + cols = flint_malloc(nnz * sizeof(*cols)); + vals = _fmpz_vec_init(nnz); + for (i = k = 0; i < r; ++i) + { + for (j = 0; j < A->rows[i].nnz; ++j, ++k) + { + rows[k] = i; + cols[k] = A->rows[i].entries[j].ind; + fmpz_set(&vals[k], A->rows[i].entries[j].val); + } + } + fmpz_sparse_mat_from_entries(B, rows, cols, vals, nnz); + + if (!fmpz_sparse_mat_equal(A, B)) + { + flint_printf("FAIL: A != B\n"); + flint_printf("A = "); + fmpz_sparse_mat_print_pretty(A); + flint_printf("B = "); + fmpz_sparse_mat_print_pretty(B); + abort(); + } + + for (i = 0; i < r; ++i) fmpz_sparse_mat_append_row(C, &A->rows[i]); + if (!fmpz_sparse_mat_equal(A, C)) + { + flint_printf("FAIL: A != C\n"); + flint_printf("A = "); + fmpz_sparse_mat_print_pretty(A); + flint_printf("C = "); + fmpz_sparse_mat_print_pretty(C); + abort(); + } + flint_free(rows); + flint_free(cols); + _fmpz_vec_clear(vals, nnz); + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-content.c b/fmpz_sparse_mat/test/t-content.c new file mode 100644 index 0000000000..b1911742a9 --- /dev/null +++ b/fmpz_sparse_mat/test/t-content.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2015 Dharak Kharod + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" +#include "long_extras.h" + + +int main() +{ + slong rep, r, c, min_nnz, max_nnz, bits, nreps = 100; + fmpz_sparse_mat_t A,B; + fmpz_t scalar, gcd_mat, temp; + FLINT_TEST_INIT(state); + + flint_printf("fmpz_sparse_mat_content...."); + fflush(stdout); + + for (rep = 0; rep < nreps; ++rep) + { + r = n_randint(state, 50); + c = n_randint(state, 50); + min_nnz = 0; + max_nnz = c; + do bits = n_randint(state, 256); + while (bits <= UWORD(1)); + + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + + fmpz_init(scalar); + fmpz_init(gcd_mat); + fmpz_init(temp); + + fmpz_sparse_mat_randtest(B, state, min_nnz, max_nnz, bits); + + fmpz_sparse_mat_content(gcd_mat, B); + + if (r == 0 || c == 0) + { + if (!fmpz_is_zero(gcd_mat)) + { + flint_printf("FAIL!\n"); + abort(); + } + } else { + fmpz_randtest_not_zero(scalar, state, 50); + + fmpz_sparse_mat_scalar_mul_fmpz(A, B, scalar); + + fmpz_sparse_mat_content(temp, A); + + fmpz_mul(gcd_mat, gcd_mat, scalar); + + if (fmpz_cmpabs(gcd_mat, temp) != 0) + { + flint_printf("FAIL!\n"); + abort(); + } + } + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + + fmpz_clear(scalar); + fmpz_clear(temp); + fmpz_clear(gcd_mat); + } + + + FLINT_TEST_CLEANUP(state); + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-dense.c b/fmpz_sparse_mat/test/t-dense.c new file mode 100644 index 0000000000..7d686d14c3 --- /dev/null +++ b/fmpz_sparse_mat/test/t-dense.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c; + fmpz_sparse_mat_t A, B; + fmpz_mat_t C, D; + FLINT_TEST_INIT(state); + + + flint_printf("conversion to/from dense matrix...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + r = n_randint(state, 100); + c = n_randint(state, 100); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + fmpz_mat_init(C, r, c); + fmpz_mat_init(D, r, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_to_dense(C, A); + fmpz_sparse_mat_from_dense(B, C); + + if (!fmpz_sparse_mat_equal(A, B)) + { + flint_printf("FAIL: A != B\n"); + abort(); + } + + fmpz_mat_randtest(C, state, bits); + fmpz_sparse_mat_from_dense(A, C); + fmpz_sparse_mat_to_dense(D, A); + + if (!fmpz_mat_equal(C, D)) + { + flint_printf("FAIL: C != D\n"); + abort(); + } + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_mat_clear(C); + fmpz_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det.c b/fmpz_sparse_mat/test/t-det.c new file mode 100644 index 0000000000..dbebace188 --- /dev/null +++ b/fmpz_sparse_mat/test/t-det.c @@ -0,0 +1,85 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, bits, r, nreps = 100, nzero = 0; + fmpz_t det, d; + fmpz_mat_t dA; + fmpz_sparse_mat_t A; + + FLINT_TEST_INIT(state); + + flint_printf("det...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + r = n_randint(state, 75); + bits = 1 + n_randint(state, 100); + + fmpz_sparse_mat_init(A, r, r); + + fmpz_init(det); + fmpz_init(d); + + if (r == 0) + fmpz_one(d); + else + { + fmpz_mat_init(dA, r, r); + if (r > 1 && n_randint(state, 2) == 0) + { + fmpz_zero(d); nzero++; + fmpz_mat_randrank(dA, state, 1+n_randint(state, r - 1), bits); + } + else + { + fmpz_randtest(d, state, 30); + fmpz_mat_randdet(dA, state, d); + } + fmpz_mat_randops(dA, state, n_randint(state, FLINT_MAX(r/4, 1)*r + 1)); + fmpz_sparse_mat_from_dense(A, dA); + fmpz_mat_clear(dA); + } + + fmpz_sparse_mat_det(det, A); + + if (!fmpz_equal(det, d)) + { + flint_printf("FAIL:\n"); + flint_printf("wrong determinant!\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("expected: "), fmpz_print(d), flint_printf("\n"); + flint_printf("ncomputed: "), fmpz_print(det), flint_printf("\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_clear(det); + fmpz_clear(d); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det_bareiss.c b/fmpz_sparse_mat/test/t-det_bareiss.c new file mode 100644 index 0000000000..fbd894c1e1 --- /dev/null +++ b/fmpz_sparse_mat/test/t-det_bareiss.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, bits, r, nreps = 1000; + fmpz_t det, ddet; + fmpz_mat_t dA; + fmpz_sparse_mat_t A; + + FLINT_TEST_INIT(state); + + flint_printf("det_bareiss...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 1+n_randint(state,200); + r = n_randint(state, 10); + + fmpz_mat_init(dA, r, r); + fmpz_sparse_mat_init(A, r, r); + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + + fmpz_init(det); + fmpz_init(ddet); + + fmpz_sparse_mat_det(det, A); + fmpz_sparse_mat_to_dense(dA, A); + fmpz_mat_det(ddet, dA); + if (!fmpz_equal(det, ddet)) + { + flint_printf("FAIL:\n"); + flint_printf("Incorrect determinant!\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("found det: "), fmpz_print(det), flint_printf("\n"); + flint_printf("right det: "), fmpz_print(ddet), flint_printf("\n"); + abort(); + } + + fmpz_clear(det); + fmpz_clear(ddet); + fmpz_mat_clear(dA); + fmpz_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det_bound.c b/fmpz_sparse_mat/test/t-det_bound.c new file mode 100644 index 0000000000..2dd2e4074b --- /dev/null +++ b/fmpz_sparse_mat/test/t-det_bound.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + fmpz_sparse_mat_t A; + slong i, m; + fmpz_t det, bound; + + FLINT_TEST_INIT(state); + + flint_printf("det_bound...."); + fflush(stdout); + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + m = n_randint(state, 10); + + fmpz_sparse_mat_init(A, m, m); + + fmpz_init(det); + fmpz_init(bound); + + fmpz_sparse_mat_randtest(A, state, 0, m, 1+n_randint(state,200)); + + fmpz_sparse_mat_det(det, A); + fmpz_sparse_mat_det_bound(bound, A); + + if (fmpz_cmp(det, bound) > 0) + { + flint_printf("FAIL:\n"); + flint_printf("bound too small!\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("det: "), fmpz_print(det), flint_printf("\n"); + flint_printf("bound: "), fmpz_print(bound), flint_printf("\n"); + abort(); + } + + fmpz_clear(det); + fmpz_clear(bound); + fmpz_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det_divisor.c b/fmpz_sparse_mat/test/t-det_divisor.c new file mode 100644 index 0000000000..3217ace8fd --- /dev/null +++ b/fmpz_sparse_mat/test/t-det_divisor.c @@ -0,0 +1,72 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, bits, r, nreps = 1000; + fmpz_t det, d; + fmpz_sparse_mat_t A; + + FLINT_TEST_INIT(state); + + flint_printf("det_divisor...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + r = n_randint(state, 15); + bits = 1 + n_randint(state, 100); + + fmpz_init(det); + fmpz_init(d); + fmpz_sparse_mat_init(A, r, r); + + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + + fmpz_sparse_mat_det_divisor(d, A); + fmpz_sparse_mat_det_bareiss(det, A); + + if ((fmpz_is_zero(det) || fmpz_is_zero(d)) && !fmpz_equal(det, d)) + { + flint_printf("FAIL: found divisor of matrix with det 0\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + abort(); + } + else if (!fmpz_divisible(det, d)) + { + flint_printf("FAIL:\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("det: "); fmpz_print(det); flint_printf("\n"); + flint_printf("d: "); fmpz_print(d); flint_printf("\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_clear(det); + fmpz_clear(d); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det_modular.c b/fmpz_sparse_mat/test/t-det_modular.c new file mode 100644 index 0000000000..bf3c2d459f --- /dev/null +++ b/fmpz_sparse_mat/test/t-det_modular.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, bits, r, nreps = 1000; + fmpz_t det, d; + fmpz_sparse_mat_t A; + + FLINT_TEST_INIT(state); + + flint_printf("det_modular...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + int proved = n_randlimb(state) % 2; + bits = 1+n_randint(state,200); + r = n_randint(state, 20); + + fmpz_sparse_mat_init(A, r, r); + + fmpz_init(det); + fmpz_init(d); + + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + + fmpz_sparse_mat_det_bareiss(d, A); + fmpz_sparse_mat_det_modular(det, A, proved); + + if (!fmpz_equal(d, det)) + { + flint_printf("FAIL:\n"); + flint_printf("different determinants!\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("det_bareiss: "), fmpz_print(d), flint_printf("\n"); + flint_printf("det_modular: "), fmpz_print(det), flint_printf("\n"); + abort(); + } + + fmpz_clear(d); + fmpz_clear(det); + fmpz_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-det_modular_accelerated.c b/fmpz_sparse_mat/test/t-det_modular_accelerated.c new file mode 100644 index 0000000000..d317e979ea --- /dev/null +++ b/fmpz_sparse_mat/test/t-det_modular_accelerated.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + + +int +main(void) +{ + slong rep, bits, r, nreps = 1000; + fmpz_t det, d; + fmpz_sparse_mat_t A; + + FLINT_TEST_INIT(state); + + flint_printf("det_modular_accelerated...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + int proved = n_randlimb(state) % 2; + bits = 1+n_randint(state,200); + r = n_randint(state, 20); + + fmpz_sparse_mat_init(A, r, r); + + fmpz_init(det); + fmpz_init(d); + + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + + fmpz_sparse_mat_det_bareiss(d, A); + fmpz_sparse_mat_det_modular_accelerated(det, A, proved); + + if (!fmpz_equal(d, det)) + { + flint_printf("FAIL:\n"); + flint_printf("different determinants!\n"); + fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("det_bareiss: "), fmpz_print(d), flint_printf("\n"); + flint_printf("det_modular: "), fmpz_print(det), flint_printf("\n"); + abort(); + } + + fmpz_clear(d); + fmpz_clear(det); + fmpz_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-fflu.c b/fmpz_sparse_mat/test/t-fflu.c new file mode 100644 index 0000000000..8925c83c24 --- /dev/null +++ b/fmpz_sparse_mat/test/t-fflu.c @@ -0,0 +1,136 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "perm.h" +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, rk, nreps = 1000, i, j; + slong *P, *Q; + fmpz_t *val; + fmpz *D; + fmpz_mat_t dL, dU, dLU; + fmpz_sparse_mat_t L, U, M, LU; + FLINT_TEST_INIT(state); + + flint_printf("fflu...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 100; /*2 + n_randint(state, 10);*/ + r = c = n_randint(state, 10); + /*c = n_randint(state, 20);*/ + min_nnz = 0; + max_nnz = c; + + D = _fmpz_vec_init(r); + P = flint_malloc(r*sizeof(*P)); + Q = flint_malloc(c*sizeof(*Q)); + fmpz_sparse_mat_init(M, r, c); + fmpz_sparse_mat_init(L, r, c); + fmpz_sparse_mat_init(U, r, c); + fmpz_sparse_mat_init(LU, r, c); + fmpz_sparse_mat_randtest(M, state, min_nnz, max_nnz, bits); + rk = fmpz_sparse_mat_fflu(D, P, Q, L, U, M); + + /* Check that L is lower triangular (with ones on diagonal up to rank) */ + for (i = 0; i < r; ++i) { + val = fmpz_sparse_vec_at(&L->rows[i], i); + if (i < rk && (val == NULL || !fmpz_is_one(*val))) + { + flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); + } + for (j = 0; jrows[i].nnz; ++j) { + if (L->rows[i].entries[j].ind > i) { + flint_printf("FAIL: L not lower triangular\n"); + abort(); + } + if (L->rows[i].entries[j].ind >= rk) { + flint_printf("FAIL: L not trivial past the rank\n"); + flint_printf("rank = %wd\n", rk); + flint_printf("L = "); + fmpz_sparse_mat_print_pretty(L); + abort(); + } + } + } + /* Check that U is upper triangular (with nonzero diagonal up to rank) */ + for (i = 0; i < r; ++i) { + val = fmpz_sparse_vec_at(&U->rows[i], i); + if (i < rk && (val == NULL || fmpz_is_zero(*val))) + { + flint_printf("FAIL: U does not have nonzero diagonal\n"); + abort(); + } + if (i >= rk && U->rows[i].nnz != UWORD(0)) + { + flint_printf("FAIL: U not trivial past the rank\n"); + abort(); + } + for (j = 0; j < U->rows[i].nnz; ++j) { + if (U->rows[i].entries[j].ind < i) { + flint_printf("FAIL: U not upper triangular\n"); + abort(); + } + } + } + + + fmpz_mat_init(dL, r, rk); + fmpz_mat_init(dU, rk, c); + fmpz_mat_init(dLU, r, c); + + /* Verify that PDMQ = LU */ + fmpz_sparse_mat_mul_diag_fmpz(M, M, D); + fmpz_sparse_mat_permute_rows(M, P); + fmpz_sparse_mat_permute_cols(M, Q); + fmpz_sparse_mat_to_dense(dL, L); + fmpz_sparse_mat_to_dense(dU, U); + fmpz_mat_mul(dLU, dL, dU); + fmpz_sparse_mat_from_dense(LU, dLU); + if(!fmpz_sparse_mat_equal(M, LU)) { + flint_printf("FAIL: PDMQ != LU\n"); + flint_printf("PDMQ="); + fmpz_sparse_mat_print_pretty(M); + flint_printf("LU="); + fmpz_sparse_mat_print_pretty(LU); + flint_printf("diff = "); + fmpz_sparse_mat_sub(LU, LU, M); + fmpz_sparse_mat_print_pretty(LU); + abort(); + } + + _fmpz_vec_clear(D, r); + flint_free(P); + flint_free(Q); + fmpz_sparse_mat_clear(M); + fmpz_sparse_mat_clear(U); + fmpz_sparse_mat_clear(L); + fmpz_sparse_mat_clear(LU); + fmpz_mat_clear(dL); + fmpz_mat_clear(dU); + fmpz_mat_clear(dLU); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-hnf_classical.c b/fmpz_sparse_mat/test/t-hnf_classical.c new file mode 100644 index 0000000000..6dce52af0d --- /dev/null +++ b/fmpz_sparse_mat/test/t-hnf_classical.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, rk, nreps = 1000; + fmpz_mat_t dA, dH; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("hnf_classical...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 2 + n_randint(state, 100); + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + + fmpz_mat_init(dA, r, c); + fmpz_mat_init(dH, r, c); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(H, r, c); + fmpz_sparse_mat_init(H2, r, c); + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + fmpz_sparse_mat_set(H, A); + rk = fmpz_sparse_mat_hnf_classical(H); + fmpz_sparse_mat_to_dense(dA, A); + fmpz_mat_hnf_classical(dH, dA); + fmpz_sparse_mat_from_dense(H2, dH); + + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL: matrix not in hnf!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + flint_printf("Obtained: \n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + flint_printf("Should be: \n"); + fmpz_sparse_mat_print_pretty(H2); flint_printf("\n\n"); + flint_printf("Found rank %wd\n", rk); + abort(); + } + + fmpz_sparse_mat_clear(H2); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(dA); + fmpz_mat_clear(dH); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-hnf_minors.c b/fmpz_sparse_mat/test/t-hnf_minors.c new file mode 100644 index 0000000000..57983a8c9c --- /dev/null +++ b/fmpz_sparse_mat/test/t-hnf_minors.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" + + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, rk, nreps = 1000; + fmpz_mat_t dA, dH; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("hnf_minors...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + if (rep % 20 == 0) {flint_printf("."); fflush(stdout);} + bits = 2 + n_randint(state, 100); + r = n_randint(state, 20); + c = n_randint(state, 20); + min_nnz = 0; + max_nnz = c; + + fmpz_mat_init(dA, r, c); + fmpz_mat_init(dH, r, c); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(H, r, c); + fmpz_sparse_mat_init(H2, r, c); + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + fmpz_sparse_mat_set(H, A); + rk = fmpz_sparse_mat_hnf_minors(H); + fmpz_sparse_mat_to_dense(dA, A); + fmpz_mat_hnf(dH, dA); + fmpz_sparse_mat_from_dense(H2, dH); + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL: matrix not in hnf!\n"); + flint_printf("Starting: \n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + flint_printf("Obtained: \n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + flint_printf("Found rank %wd\n", rk); + abort(); + } + + fmpz_sparse_mat_clear(H2); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(dA); + fmpz_mat_clear(dH); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-hnf_modular.c b/fmpz_sparse_mat/test/t-hnf_modular.c new file mode 100644 index 0000000000..9077dc15c0 --- /dev/null +++ b/fmpz_sparse_mat/test/t-hnf_modular.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, r, min_nnz, max_nnz, bits, nreps = 1000; + fmpz_t det; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("hnf_modular...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 1 + n_randint(state, 200); + r = n_randint(state, 20); + min_nnz = 0; + max_nnz = r; + + fmpz_init(det); + + fmpz_sparse_mat_init(A, r, r); + fmpz_sparse_mat_init(H, r, r); + fmpz_sparse_mat_init(H2, r, r); + + do + { + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + fmpz_sparse_mat_det(det, A); + } while (fmpz_is_zero(det)); + fmpz_abs(det, det); + fmpz_mul_ui(det, det, 1 + n_randint(state, 10)); + + fmpz_sparse_mat_set(H, A); + fmpz_sparse_mat_hnf_modular(H, det); + + fmpz_sparse_mat_set(H2, A); + fmpz_sparse_mat_hnf_classical(H2); + + if (!fmpz_sparse_mat_is_in_hnf(H)) + { + flint_printf("FAIL:\n"); + flint_printf("matrix not in hnf!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + abort(); + } + + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL:\n"); + flint_printf("hnfs produced by different methods should be the same!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H2); flint_printf("\n\n"); + fmpz_print(det); flint_printf("\n\n"); + abort(); + } + + fmpz_sparse_mat_clear(H2); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(A); + fmpz_clear(det); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c b/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c new file mode 100644 index 0000000000..85eac68768 --- /dev/null +++ b/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c @@ -0,0 +1,89 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" + +/* FIX ME */ +int +main(void) +{ + slong rep, r, min_nnz, max_nnz, bits, nreps = 100; + fmpz_t det; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("hnf_modular_eldiv...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 1 + n_randint(state, 100); + r = n_randint(state, 20); + min_nnz = 0; + max_nnz = r; + + fmpz_init(det); + + fmpz_sparse_mat_init(A, r, r); + fmpz_sparse_mat_init(H, r, r); + fmpz_sparse_mat_init(H2, r, r); + + do + { + fmpz_sparse_mat_randtest_unsigned(A, state, min_nnz, max_nnz, bits); + fmpz_sparse_mat_det(det, A); + } while (fmpz_is_zero(det)); + fmpz_abs(det, det); + /*fmpz_mul_ui(det, det, 1 + n_randint(state, 10));*/ + + fmpz_sparse_mat_set(H, A); + fmpz_sparse_mat_hnf_modular_eldiv(H, det); + fmpz_sparse_mat_set(H2, A); + fmpz_sparse_mat_hnf_minors(H2); + + if (!fmpz_sparse_mat_is_in_hnf(H)) + { + flint_printf("FAIL:\n"); + flint_printf("matrix not in hnf!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + flint_printf("determinant:"); fmpz_print(det); + flint_printf("\n\n"); + abort(); + } + + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL:\n"); + flint_printf("hnfs produced by different methods should be the same!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H2); flint_printf("\n\n"); + fmpz_print(det); flint_printf("\n\n"); + abort(); + } + + fmpz_sparse_mat_clear(H2); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(A); + fmpz_clear(det); + } + + FLINT_TEST_CLEANUP(state); + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-hnf_xgcd.c b/fmpz_sparse_mat/test/t-hnf_xgcd.c new file mode 100644 index 0000000000..d7ac5698ec --- /dev/null +++ b/fmpz_sparse_mat/test/t-hnf_xgcd.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, rk, nreps = 1000; + fmpz_mat_t dA, dH; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("hnf_xgcd...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 2 + n_randint(state, 100); + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + + fmpz_mat_init(dA, r, c); + fmpz_mat_init(dH, r, c); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(H, r, c); + fmpz_sparse_mat_init(H2, r, c); + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + + fmpz_sparse_mat_set(H, A); + rk = fmpz_sparse_mat_hnf_xgcd(H); + fmpz_sparse_mat_to_dense(dA, A); + fmpz_mat_hnf_xgcd(dH, dA); + fmpz_sparse_mat_from_dense(H2, dH); + + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL: matrix not in hnf!\n"); + fmpz_sparse_mat_print_pretty(A); flint_printf("\n\n"); + flint_printf("Obtained: \n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + flint_printf("Should be: \n"); + fmpz_sparse_mat_print_pretty(H2); flint_printf("\n\n"); + flint_printf("Found rank %wd\n", rk); + abort(); + } + + fmpz_sparse_mat_clear(H2); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(dA); + fmpz_mat_clear(dH); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-howell_form_mod.c b/fmpz_sparse_mat/test/t-howell_form_mod.c new file mode 100644 index 0000000000..26f5aa1196 --- /dev/null +++ b/fmpz_sparse_mat/test/t-howell_form_mod.c @@ -0,0 +1,79 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, rk, rk2, nreps = 10; + fmpz_t mod; + slong *P; + fmpz_mat_t dH; + fmpz_sparse_mat_t A, H, H2; + FLINT_TEST_INIT(state); + + flint_printf("howell_form...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + bits = 64 + n_randint(state, 10); + c = n_randint(state, 10); + r = c + n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + + fmpz_mat_init(dH, r, c); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(H, r, c); + fmpz_sparse_mat_init(H2, r, c); + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + + fmpz_init(mod); + do fmpz_randtest_not_zero(mod, state, bits); + while (fmpz_fits_si(mod)); + fmpz_sparse_mat_set(H, A); + fmpz_sparse_mat_to_dense(dH, A); + rk = fmpz_sparse_mat_howell_form_mod(H, mod); + rk2 = fmpz_mat_howell_form_mod(dH, mod); + fmpz_sparse_mat_from_dense(H2, dH); + if (!fmpz_sparse_mat_equal(H, H2)) + { + flint_printf("FAIL: Howell form not equal\n"); + fmpz_sparse_mat_print_pretty(H); flint_printf("\n\n"); + fmpz_sparse_mat_print_pretty(H2); flint_printf("\n\n"); + flint_printf("Ranks: %wd, %wd\nModulus: ", rk, rk2); + fmpz_print(mod); + flint_printf("\n\n"); + abort(); + } + + do fmpz_randtest_unsigned(mod, state, 10); + while (fmpz_is_zero(mod)); + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(H); + fmpz_sparse_mat_clear(H2); + fmpz_mat_clear(dH); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} + diff --git a/fmpz_sparse_mat/test/t-init_clear.c b/fmpz_sparse_mat/test/t-init_clear.c new file mode 100644 index 0000000000..ee1b568a9e --- /dev/null +++ b/fmpz_sparse_mat/test/t-init_clear.c @@ -0,0 +1,58 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c, i; + fmpz_sparse_mat_t A; + FLINT_TEST_INIT(state); + + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 200); + c = n_randint(state, 200); + fmpz_sparse_mat_init(A, r, c); + + if (!fmpz_sparse_mat_is_zero(A)) + { + flint_printf("FAIL: A not zero!\n"); + abort(); + } + for (i = 0; i < r; i++) + { + if (!fmpz_sparse_vec_is_zero(&A->rows[i])) + { + flint_printf("FAIL: row %wd not zero!\n", i); + abort(); + } + } + + fmpz_sparse_mat_clear(A); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-mul.c b/fmpz_sparse_mat/test/t-mul.c new file mode 100644 index 0000000000..3b0e40bdaa --- /dev/null +++ b/fmpz_sparse_mat/test/t-mul.c @@ -0,0 +1,83 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c, k; + fmpz_sparse_mat_t A; + fmpz *x, *y, *y2; + fmpz_mat_t B, X, Y, Y2; + FLINT_TEST_INIT(state); + + + flint_printf("multiplication by vec/mat...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 70); + while(bits < UWORD(2)); + r = 1 + n_randint(state, 20); + c = 1 + n_randint(state, 20); + k = 1 + n_randint(state, 20); + fmpz_sparse_mat_init(A, r, c); + fmpz_mat_init(B, r, c); + fmpz_mat_init(X, c, k); + fmpz_mat_init(Y, r, k); + fmpz_mat_init(Y2, r, k); + x = _fmpz_vec_init(c); + y = _fmpz_vec_init(r); + y2 = _fmpz_vec_init(r); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_to_dense(B, A); + _fmpz_vec_randtest(x, state, c, bits); + fmpz_sparse_mat_mul_vec(y, A, x); + fmpz_mat_mul_vec(y2, B, x); + + if (!_fmpz_vec_equal(y, y2, A->r)) + { + flint_printf("FAIL: y != y2\n"); + abort(); + } + + fmpz_mat_randtest(X, state, bits); + fmpz_sparse_mat_mul_mat(Y, A, X); + fmpz_mat_mul(Y2, B, X); + + if (!fmpz_mat_equal(Y, Y2)) + { + flint_printf("Fail: Y != Y2\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(B); + _fmpz_vec_clear(x, c); + _fmpz_vec_clear(y, r); + _fmpz_vec_clear(y2, r); + fmpz_mat_clear(X); + fmpz_mat_clear(Y); + fmpz_mat_clear(Y2); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-multi_CRT_ui.c b/fmpz_sparse_mat/test/t-multi_CRT_ui.c new file mode 100644 index 0000000000..9456791a60 --- /dev/null +++ b/fmpz_sparse_mat/test/t-multi_CRT_ui.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2007 William Hart and David Harvey + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" +#include "nmod_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, prime_bits, num_primes, j, nreps = 1000; + mp_limb_t primes[1000]; + nmod_t nmod; + fmpz_t mod; + nmod_sparse_mat_struct Amod[1000]; + fmpz_sparse_mat_t A, B; + FLINT_TEST_INIT(state); + + flint_printf("multi_CRT_ui...."); + fflush(stdout); + + + for (rep = 0; rep < nreps; rep++) + { + bits = n_randint(state, 500) + 2; + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + prime_bits = 1 + n_randint(state, FLINT_BITS - 1); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + + fmpz_sparse_mat_randtest(A, state, min_nnz, max_nnz, bits); + + fmpz_init_set_ui(mod, UWORD(1)); + for (num_primes = 0; fmpz_bits(mod) <= bits + 1; num_primes++) + { + primes[num_primes] = n_nextprime((num_primes == 0) ? (UWORD(1) << prime_bits) : primes[num_primes - 1], 0); + nmod_init(&nmod, primes[num_primes]); + nmod_sparse_mat_init(&Amod[num_primes], r, c, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(&Amod[num_primes], A); + fmpz_mul_ui(mod, mod, primes[num_primes]); + } + fmpz_sparse_mat_multi_mod_ui(Amod, num_primes, A); + fmpz_sparse_mat_multi_CRT_ui(B, Amod, num_primes, 1); + + if (!fmpz_sparse_mat_equal(B, A)) + { + flint_printf("FAIL!\n"); + flint_printf("primes: "); + for (j = 0; j < num_primes; j++) + flint_printf("%wu ", primes[j]); + flint_printf("\nA: \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("\nB: \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("\n"); + abort(); + } + + for (j = 0; j < num_primes; j++) + nmod_sparse_mat_clear(&Amod[j]); + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c b/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c new file mode 100644 index 0000000000..30cab7c705 --- /dev/null +++ b/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2007 William Hart and David Harvey + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_sparse_mat.h" +#include "nmod_sparse_mat.h" + +int +main(void) +{ + slong rep, r, c, min_nnz, max_nnz, bits, prime_bits, num_primes, j, nreps = 1000; + mp_limb_t primes[1000]; + nmod_t nmod; + fmpz_t mod; + nmod_sparse_mat_struct Amod[1000]; + fmpz_sparse_mat_t A, B; + FLINT_TEST_INIT(state); + + flint_printf("multi_CRT_ui_unsigned...."); + fflush(stdout); + + + for (rep = 0; rep < nreps; rep++) + { + bits = n_randint(state, 500) + 2; + r = n_randint(state, 10); + c = n_randint(state, 10); + min_nnz = 0; + max_nnz = c; + prime_bits = 1 + n_randint(state, FLINT_BITS - 1); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + + fmpz_sparse_mat_randtest_unsigned(A, state, min_nnz, max_nnz, bits); + + fmpz_init_set_ui(mod, UWORD(1)); + for (num_primes = 0; fmpz_bits(mod) <= bits; num_primes++) + { + primes[num_primes] = n_nextprime((num_primes == 0) ? (UWORD(1) << prime_bits) : primes[num_primes - 1], 0); + nmod_init(&nmod, primes[num_primes]); + nmod_sparse_mat_init(&Amod[num_primes], r, c, nmod); + fmpz_sparse_mat_get_nmod_sparse_mat(&Amod[num_primes], A); + fmpz_mul_ui(mod, mod, primes[num_primes]); + } + fmpz_sparse_mat_multi_mod_ui(Amod, num_primes, A); + fmpz_sparse_mat_multi_CRT_ui(B, Amod, num_primes, 0); + + if (!fmpz_sparse_mat_equal(B, A)) + { + flint_printf("FAIL!\n"); + flint_printf("primes: "); + for (j = 0; j < num_primes; j++) + flint_printf("%wu ", primes[j]); + flint_printf("\nA: \n"); + fmpz_sparse_mat_print_pretty(A); + flint_printf("\nB: \n"); + fmpz_sparse_mat_print_pretty(B); + flint_printf("\n"); + abort(); + } + + for (j = 0; j < num_primes; j++) + nmod_sparse_mat_clear(&Amod[j]); + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-neg.c b/fmpz_sparse_mat/test/t-neg.c new file mode 100644 index 0000000000..ef33d82ff5 --- /dev/null +++ b/fmpz_sparse_mat/test/t-neg.c @@ -0,0 +1,72 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c; + fmpz_sparse_mat_t A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 200); + c = n_randint(state, 200); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + fmpz_sparse_mat_init(C, r, c); + fmpz_sparse_mat_init(D, r, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_randtest(B, state, 0, c, bits); + fmpz_sparse_mat_randtest(C, state, 0, c, bits); + fmpz_sparse_mat_randtest(D, state, 0, c, bits); + + fmpz_sparse_mat_sub(C, A, B); + fmpz_sparse_mat_neg(B, B); + fmpz_sparse_mat_add(D, A, B); + + if (!fmpz_sparse_mat_equal(C, D)) + { + flint_printf("FAIL\n"); + abort(); + } + + fmpz_sparse_mat_neg(C, B); + fmpz_sparse_mat_neg(B, B); + + if (!fmpz_sparse_mat_equal(C, B)) + { + flint_printf("FAIL\n"); + abort(); + } + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + fmpz_sparse_mat_clear(D); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-scalar_mul.c b/fmpz_sparse_mat/test/t-scalar_mul.c new file mode 100644 index 0000000000..c4eaaea3b0 --- /dev/null +++ b/fmpz_sparse_mat/test/t-scalar_mul.c @@ -0,0 +1,81 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c, nreps = 1000; + fmpz_t a, cc; + fmpz_sparse_mat_t A, B, C, D; + FLINT_TEST_INIT(state); + + flint_printf("scalar_mul...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 200); + c = n_randint(state, 200); + fmpz_init(a); + fmpz_init(cc); + fmpz_randtest(cc, state, bits); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, r, c); + fmpz_sparse_mat_init(C, r, c); + fmpz_sparse_mat_init(D, r, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + + fmpz_sparse_mat_scalar_mul_fmpz(B, A, a); + fmpz_one(cc); + fmpz_sub(cc, a, cc); + fmpz_sparse_mat_scalar_mul_fmpz(C, A, cc); + + /* c*A - (c-1)*A == A */ + fmpz_sparse_mat_sub(D, B, C); + + if (!fmpz_sparse_mat_equal(A, D)) + { + flint_printf("FAIL\n"); + abort(); + } + + /* Aliasing */ + fmpz_sparse_mat_scalar_mul_fmpz(C, A, a); + fmpz_sparse_mat_scalar_mul_fmpz(A, A, a); + + if (!fmpz_sparse_mat_equal(A, C)) + { + flint_printf("FAIL\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + fmpz_sparse_mat_clear(D); + fmpz_clear(a); + fmpz_clear(cc); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-solve_dixon.c b/fmpz_sparse_mat/test/t-solve_dixon.c new file mode 100644 index 0000000000..ada103771c --- /dev/null +++ b/fmpz_sparse_mat/test/t-solve_dixon.c @@ -0,0 +1,98 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, r, c, nreps = 1000, num_bad_fail = 0; + fmpz_sparse_mat_t A; + fmpz_mat_t X, B, AX, AXm, Bm; + fmpz_t mod, det; + int success; + + FLINT_TEST_INIT(state); + + flint_printf("solve_dixon...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + r = n_randint(state, 20); + c = n_randint(state, 20); + + fmpz_sparse_mat_init(A, r, r); + fmpz_mat_init(B, r, c); + fmpz_mat_init(X, r, c); + fmpz_init(mod); + + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*bits); + + success = fmpz_sparse_mat_solve_dixon(X, mod, A, B); + if (!success) + { + fmpz_init(det); + fmpz_sparse_mat_det(det, A); + if (!fmpz_is_zero(det)) { + num_bad_fail++; + } + fmpz_clear(det); + } + else + { + fmpz_mat_init(AX, r, c); + fmpz_mat_init(AXm, r, c); + fmpz_mat_init(Bm, r, c); + + fmpz_sparse_mat_mul_mat(AX, A, X); + fmpz_mat_scalar_mod_fmpz(AXm, AX, mod); + fmpz_mat_scalar_mod_fmpz(Bm, B, mod); + + if (!fmpz_mat_equal(AXm, Bm) || !success) + { + flint_printf("FAIL:\n"); + flint_printf("AX != B!\n"); + flint_printf("A:\n"), fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); + flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); + flint_printf("mod = "), fmpz_print(mod), flint_printf("\n"); + flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); + abort(); + } + fmpz_mat_clear(Bm); + fmpz_mat_clear(AX); + fmpz_mat_clear(AXm); + } + + + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(B); + fmpz_mat_clear(X); + fmpz_clear(mod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + if (num_bad_fail != 0) flint_printf("Number of unexpected failures: %wd\n", num_bad_fail); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-solve_dixon_den.c b/fmpz_sparse_mat/test/t-solve_dixon_den.c new file mode 100644 index 0000000000..fa07dc65b1 --- /dev/null +++ b/fmpz_sparse_mat/test/t-solve_dixon_den.c @@ -0,0 +1,91 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz.h" +#include "fmpz_vec.h" +#include "fmpz_sparse_mat.h" +#include "ulong_extras.h" + +/* TODO */ +int +main(void) +{ + slong rep, bits, r, c, nreps = 1000, num_bad_fail = 0; + fmpz_sparse_mat_t A; + fmpz_mat_t X, B, AX; + fmpz_t den, det; + int success; + + FLINT_TEST_INIT(state); + + flint_printf("solve_dixon_den...."); + fflush(stdout); + + for (rep = 0; rep < nreps; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + r = n_randint(state, 20); + c = n_randint(state, 20); + + fmpz_sparse_mat_init(A, r, r); + fmpz_mat_init(B, r, c); + fmpz_mat_init(X, r, c); + fmpz_init(den); + + fmpz_sparse_mat_randtest(A, state, 0, r, bits); + fmpz_mat_randtest(B, state, 1+n_randint(state, 2)*bits); + + success = fmpz_sparse_mat_solve_dixon_den(X, den, A, B); + if (!success) + { + fmpz_init(det); + fmpz_sparse_mat_det(det, A); + if (!fmpz_is_zero(det)) { + num_bad_fail++; + } + fmpz_clear(det); + } + else + { + fmpz_mat_init(AX, r, c); + fmpz_sparse_mat_mul_mat(AX, A, X); + fmpz_mat_scalar_divexact_fmpz(AX, AX, den); + + if (!fmpz_mat_equal(AX, B)) + { + flint_printf("FAIL:\n"); + flint_printf("AX != B!\n"); + flint_printf("A:\n"), fmpz_sparse_mat_print_pretty(A), flint_printf("\n"); + flint_printf("B:\n"), fmpz_mat_print_pretty(B), flint_printf("\n"); + flint_printf("X:\n"), fmpz_mat_print_pretty(X), flint_printf("\n"); + flint_printf("den = "), fmpz_print(den), flint_printf("\n"); + flint_printf("AX:\n"), fmpz_mat_print_pretty(AX), flint_printf("\n"); + abort(); + } + fmpz_mat_clear(AX); + } + + fmpz_sparse_mat_clear(A); + fmpz_mat_clear(B); + fmpz_mat_clear(X); + fmpz_clear(den); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\nNum bad fail: %wd\n", num_bad_fail); + return 0; +} diff --git a/fmpz_sparse_mat/test/t-transpose.c b/fmpz_sparse_mat/test/t-transpose.c new file mode 100644 index 0000000000..9a70e01c93 --- /dev/null +++ b/fmpz_sparse_mat/test/t-transpose.c @@ -0,0 +1,62 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +int +main(void) +{ + slong rep, bits, r, c; + fmpz_sparse_mat_t A, B, C; + FLINT_TEST_INIT(state); + + + flint_printf("transpose...."); + fflush(stdout); + + /* Rectangular transpose, same modulus */ + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + r = n_randint(state, 20); + c = n_randint(state, 20); + fmpz_sparse_mat_init(A, r, c); + fmpz_sparse_mat_init(B, c, r); + fmpz_sparse_mat_init(C, r, c); + + fmpz_sparse_mat_randtest(A, state, 0, c, bits); + fmpz_sparse_mat_randtest(B, state, 0, r, bits); + fmpz_sparse_mat_randtest(C, state, 0, c, bits); + + fmpz_sparse_mat_transpose(B, A); + fmpz_sparse_mat_transpose(C, B); + + if (!fmpz_sparse_mat_equal(C, A)) + { + flint_printf("FAIL: C != A\n"); + abort(); + } + + fmpz_sparse_mat_clear(A); + fmpz_sparse_mat_clear(B); + fmpz_sparse_mat_clear(C); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_mat/transpose.c b/fmpz_sparse_mat/transpose.c new file mode 100644 index 0000000000..c6eab43ee1 --- /dev/null +++ b/fmpz_sparse_mat/transpose.c @@ -0,0 +1,59 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void +fmpz_sparse_mat_transpose(fmpz_sparse_mat_t B, const fmpz_sparse_mat_t A) +{ + slong r, c, i, j, *nnz; + fmpz_sparse_entry_struct *Ae, *Be; + nnz = flint_calloc(A->c, sizeof(*nnz)); + /* Get number of nnzs in each column of A (thus each row of B) */ + for (c = 0; c < A->c; ++c) + { + nnz[c] = 0; + } + for (r = 0; r < A->r; ++r) + { + for (i = 0; i < A->rows[r].nnz; ++i) + { + c = A->rows[r].entries[i].ind - A->c_off; + if (c >= A->c) break; + nnz[c]++; + } + } + /* Allocate space for nnz and reset counters */ + for (c = 0; c < A->c; ++c) + { + _fmpz_sparse_vec_resize(&B->rows[c], nnz[c]); + nnz[c] = 0; + } + /* Put entries into transposed matrix */ + for (r = 0; r < A->r; ++r) + { + for (i = 0; i < A->rows[r].nnz; ++i) + { + Ae = &A->rows[r].entries[i]; + c = Ae->ind - A->c_off; + if (c >= A->c) break; + j = nnz[c]++; + Be = &B->rows[c].entries[j]; + Be->ind = r; + fmpz_set(Be->val, Ae->val); + } + } + flint_free(nnz); + B->c_off = 0; +} diff --git a/fmpz_sparse_mat/window_init.c b/fmpz_sparse_mat/window_init.c new file mode 100644 index 0000000000..9d1a50834d --- /dev/null +++ b/fmpz_sparse_mat/window_init.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_mat.h" + +void fmpz_sparse_mat_window_init(fmpz_sparse_mat_t window, const fmpz_sparse_mat_t mat, slong r1, slong c1, slong r2, slong c2) +{ + slong i; + r2 = FLINT_MIN(r2, mat->r), r1 = FLINT_MIN(r1, r2); + c2 = FLINT_MIN(c2, mat->c), c1 = FLINT_MIN(c1, c2); + window->r = r2-r1; + window->c = c2-c1; + window->c_off = c1; + window->rows = flint_malloc(window->r*sizeof(*window->rows)); + for (i = 0; i < window->r; ++i) + fmpz_sparse_vec_window_init(&window->rows[i], &mat->rows[i+r1], c1, c2); +} diff --git a/fmpz_sparse_mat/with_transpose_fix_support.c b/fmpz_sparse_mat/with_transpose_fix_support.c new file mode 100644 index 0000000000..fe8d8371f2 --- /dev/null +++ b/fmpz_sparse_mat/with_transpose_fix_support.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "hashmap.h" +#include "longlong.h" + +void _fmpz_sparse_mat_with_transpose_fix_support(fmpz_sparse_mat_with_transpose_t MT, slong r, slong *osupp, slong onnz) +{ + slong i = 0, j = 0, oc, nc, c; + fmpz_sparse_vec_struct *row = &MT->M->rows[r]; + + i = 0; + while (1) + { + oc = (i==onnz) ? MT->M->c : osupp[i]; + nc = (j==row->nnz) ? MT->M->c : row->entries[j].ind; + c = FLINT_MIN(oc, nc); + if (c >= MT->M->c) break; + if (oc < nc) hashmap_rem(&MT->cols[c], r); + else hashmap_put(&MT->cols[c], r, &MT->M->rows[r].entries[j].val); + if (oc <= nc) ++i; + if (oc >= nc) ++j; + } +} + diff --git a/fmpz_sparse_mat/with_transpose_init.c b/fmpz_sparse_mat/with_transpose_init.c new file mode 100644 index 0000000000..a1666e48e7 --- /dev/null +++ b/fmpz_sparse_mat/with_transpose_init.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_mat.h" +#include "hashmap.h" +#include "longlong.h" + +void _fmpz_sparse_mat_with_transpose_init(fmpz_sparse_mat_with_transpose_t MT, fmpz_sparse_mat_t M) +{ + slong r, c, j; + MT->M = M; + + /* Construct virtual transpose */ + MT->cols = flint_calloc(M->c, sizeof(*MT->cols)); + for (r = 0; r < M->r; ++r) + for (j = 0; j < M->rows[r].nnz; ++j) + if (M->rows[r].entries[j].ind < M->c) + MT->cols[M->rows[r].entries[j].ind].num++; + for (c = 0; c < M->c; ++c) + hashmap_init(&MT->cols[c], MT->cols[c].num); + for (r = 0; r < M->r; ++r) + for (j = 0; j < M->rows[r].nnz; ++j) + if (M->rows[r].entries[j].ind < M->c) + hashmap_put(&MT->cols[M->rows[r].entries[j].ind], r, &M->rows[r].entries[j].val); +} diff --git a/fmpz_sparse_vec.h b/fmpz_sparse_vec.h new file mode 100644 index 0000000000..57cae848e6 --- /dev/null +++ b/fmpz_sparse_vec.h @@ -0,0 +1,428 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef FMPZ_SPARSE_VEC_H +#define FMPZ_SPARSE_VEC_H + +#ifdef FMPZ_SPARSE_VEC_INLINES_C +#define FMPZ_SPARSE_VEC_INLINE FLINT_DLL +#else +#define FMPZ_SPARSE_VEC_INLINE static __inline__ +#endif + +#undef ulong +#define ulong ulongxx /* interferes with system includes */ +#include +#include +#undef ulong +#include +#define ulong mp_limb_t + +#include "flint.h" +#include "longlong.h" +#include "ulong_extras.h" +#include "nmod_sparse_vec.h" +#include "fmpz_vec.h" +#include "fmpz.h" +#include "thread_support.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + slong ind; + fmpz_t val; +} fmpz_sparse_entry_struct; + +typedef fmpz_sparse_entry_struct fmpz_sparse_entry_t[1]; + +typedef struct { + fmpz_sparse_entry_struct *entries; + slong nnz; +} fmpz_sparse_vec_struct; + +typedef fmpz_sparse_vec_struct fmpz_sparse_vec_t[1]; + +FMPZ_SPARSE_VEC_INLINE +int fmpz_sparse_entry_cmp(const void *va, const void *vb) +{ + const fmpz_sparse_entry_struct *a = va; + const fmpz_sparse_entry_struct *b = vb; + if (a->ind < b->ind) return -1; + if (b->ind < a->ind) return 1; + return 0; +} + +/* Memory management */ +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_init(fmpz_sparse_vec_t vec) +{ + memset(vec, 0, sizeof(*vec)); +} +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_clear(fmpz_sparse_vec_t vec) +{ + slong i; + for (i = 0; i < vec->nnz; ++i) + fmpz_clear(vec->entries[i].val); + flint_free(vec->entries); + memset(vec, 0, sizeof(*vec)); +} + +FMPZ_SPARSE_VEC_INLINE +void _fmpz_sparse_vec_resize(fmpz_sparse_vec_t vec, slong nnz) +{ + slong i; + if(nnz == 0) fmpz_sparse_vec_clear(vec); + else if (nnz != vec->nnz) + { + for(i = nnz; i < vec->nnz; ++i) + fmpz_clear (vec->entries[i].val); + vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); + for(i = vec->nnz; i < nnz; ++i) + fmpz_init (vec->entries[i].val); + } + vec->nnz = nnz; +} + +FMPZ_SPARSE_VEC_INLINE +slong _fmpz_sparse_vec_support(slong **supp, fmpz_sparse_vec_t vec) +{ + slong i; + *supp = flint_malloc(vec->nnz*sizeof(**supp)); + for (i = 0; i < vec->nnz; ++i) (*supp)[i] = vec->entries[i].ind; + return vec->nnz; +} +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_swap(fmpz_sparse_vec_t vec1, fmpz_sparse_vec_t vec2) +{ + fmpz_sparse_vec_t tmp; + *tmp = *vec1, *vec1 = *vec2, *vec2 = *tmp; +} + +FLINT_DLL +slong fmpz_sparse_vec_max_bits(const fmpz_sparse_vec_t v); + +/* Vector indexing */ +FLINT_DLL +fmpz_t * fmpz_sparse_vec_at(const fmpz_sparse_vec_t vec, slong i); + +/* One-time instantiation */ +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_zero(fmpz_sparse_vec_t vec) +{ + fmpz_sparse_vec_clear(vec); +} + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_one(fmpz_sparse_vec_t vec, slong ind) +{ + _fmpz_sparse_vec_resize(vec, 1); + vec->entries[0].ind = ind; + fmpz_one(vec->entries[0].val); +} + +FLINT_DLL +void fmpz_sparse_vec_set(fmpz_sparse_vec_t vec, const fmpz_sparse_vec_t src, slong ioff); + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_set_entry(fmpz_sparse_vec_t v, slong ind, const fmpz_t val) +{ + fmpz_t * oval = fmpz_sparse_vec_at(v, ind); + if(oval == NULL) + { + _fmpz_sparse_vec_resize(v, v->nnz+1); + v->entries[v->nnz-1].ind = ind; + fmpz_set(v->entries[v->nnz-1].val, val); + if (v->nnz >= 2 && v->entries[v->nnz-2].ind > ind) + qsort(v->entries, v->nnz, sizeof(*v->entries), fmpz_sparse_entry_cmp); + } + else fmpz_set(*oval, val); +} + +FLINT_DLL +void fmpz_sparse_vec_from_entries(fmpz_sparse_vec_t vec, slong * inds, fmpz * vals, slong nnz); + +/* Vector comparison */ +FMPZ_SPARSE_VEC_INLINE +int fmpz_sparse_vec_is_zero(const fmpz_sparse_vec_t vec) +{ + return vec->nnz == 0; +} + +FLINT_DLL +int fmpz_sparse_vec_equal(const fmpz_sparse_vec_t vec1, const fmpz_sparse_vec_t vec2, slong ioff); + +/* Convert from/to dense vector */ +FLINT_DLL +void fmpz_sparse_vec_from_dense(fmpz_sparse_vec_t vec, const fmpz *src, slong len); + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_to_dense(fmpz *vec, const fmpz_sparse_vec_t src, slong len) +{ + slong i; + _fmpz_vec_zero(vec, len); + for (i = 0; i < src->nnz; ++i) + if(src->entries[i].ind < len) + fmpz_set(&vec[src->entries[i].ind], src->entries[i].val); +} + +/* To/from modular vector(s) */ +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_get_nmod_sparse_vec(nmod_sparse_vec_t dst, const fmpz_sparse_vec_t src, const nmod_t mod) +{ + slong i, ind; + if (src->nnz == 0) + nmod_sparse_vec_zero(dst); + else + { + dst->entries = flint_realloc(dst->entries, src->nnz*sizeof(*dst->entries)); + for (i = ind = 0; i < src->nnz; ++i) + { + dst->entries[ind].ind = src->entries[i].ind; + dst->entries[ind].val = fmpz_fdiv_ui(src->entries[i].val, mod.n); + if(dst->entries[ind].val != UWORD(0)) ++ind; + } + if (ind == 0) + { + flint_free(dst->entries); + dst->entries = NULL; + } + else dst->entries = flint_realloc(dst->entries, ind*sizeof(*dst->entries)); + dst->nnz = ind; + } +} + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_set_nmod_sparse_vec_unsigned(fmpz_sparse_vec_t dst, const nmod_sparse_vec_t src) +{ + slong i; + _fmpz_sparse_vec_resize(dst, src->nnz); + for (i = 0; i < src->nnz; ++i) + { + dst->entries[i].ind = src->entries[i].ind; + fmpz_set_ui(dst->entries[i].val, src->entries[i].val); + } +} + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_set_nmod_sparse_vec(fmpz_sparse_vec_t dst, const nmod_sparse_vec_t src, const nmod_t mod) +{ + slong i; + _fmpz_sparse_vec_resize(dst, src->nnz); + for (i = 0; i < src->nnz; ++i) + { + dst->entries[i].ind = src->entries[i].ind; + fmpz_set_ui_smod(dst->entries[i].val, src->entries[i].val, mod.n); + } +} + +FLINT_DLL +void fmpz_sparse_vec_multi_mod_ui_precomp(nmod_sparse_vec_struct * residues, slong nres, const fmpz_sparse_vec_t v, + const fmpz_comb_t comb, fmpz_comb_temp_t temp); + +FLINT_DLL +void fmpz_sparse_vec_multi_mod_ui(nmod_sparse_vec_struct * residues, mp_srcptr primes, slong nres, const fmpz_sparse_vec_t v); + +FLINT_DLL +void fmpz_sparse_vec_CRT_ui(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_t m1, + const nmod_sparse_vec_t v, nmod_t m2, mp_limb_t m1i_m2, int sign); + +FLINT_DLL +void fmpz_sparse_vec_multi_CRT_ui_precomp(fmpz_sparse_vec_t v, nmod_sparse_vec_struct const * residues, slong nres, + const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign); + +FLINT_DLL +void fmpz_sparse_vec_multi_CRT_ui(fmpz_sparse_vec_t v, nmod_sparse_vec_struct * const residues, mp_srcptr primes, slong nres, int sign); + +/* Windows and concatenation */ +FLINT_DLL +void fmpz_sparse_vec_window_init(fmpz_sparse_vec_t window, const fmpz_sparse_vec_t vec, slong i1, slong i2); + + +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_window_clear(fmpz_sparse_vec_t window) +{ + memset(window, 0, sizeof(*window)); +} + +FLINT_DLL +void fmpz_sparse_vec_concat(fmpz_sparse_vec_t res, const fmpz_sparse_vec_t vec1, const fmpz_sparse_vec_t vec2, slong len1); + +FLINT_DLL +void fmpz_sparse_vec_split(fmpz_sparse_vec_t res1, fmpz_sparse_vec_t res2, const fmpz_sparse_vec_t vec, slong ind); + +/* Vector permutation */ +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_permute_inds(fmpz_sparse_vec_t vec, slong *P) +{ + slong i; + for (i = 0; i < vec->nnz; ++i) vec->entries[i].ind = P[vec->entries[i].ind]; +} + +/* Random vector generation */ +FLINT_DLL +void fmpz_sparse_vec_randtest(fmpz_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, flint_bitcnt_t bits); + +FLINT_DLL +void fmpz_sparse_vec_randtest_unsigned(fmpz_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, flint_bitcnt_t bits); + +/* Vector display */ +FLINT_DLL +void fmpz_sparse_vec_print_pretty(const fmpz_sparse_vec_t vec, slong ioff, slong maxi); + +/* Vector operations */ +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_neg(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u) +{ + slong i; + fmpz_sparse_vec_set(v, u, 0); + for (i = 0; i < v->nnz; ++i) fmpz_neg(v->entries[i].val, v->entries[i].val); +} + +FLINT_DLL +void fmpz_sparse_vec_scalar_mul_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t c); + +FLINT_DLL +void fmpz_sparse_vec_scalar_divexact_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t c); + +FLINT_DLL +void fmpz_sparse_vec_scalar_mod_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t mod); + +FLINT_DLL +void fmpz_sparse_vec_scalar_mods_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t mod); + +/* Utility macros used by binary vector operations */ +/* Compute total number of indices between two sparse vectors */ +FMPZ_SPARSE_VEC_INLINE +slong _fmpz_sparse_vec_union_nnz(const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + slong i, j, nnz = 0; + for (i = j = 0; i < u->nnz && j < v->nnz; ++nnz) + { + if (u->entries[i].ind == v->entries[j].ind) ++i, ++j; + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } + nnz += u->nnz - i + v->nnz - j; + return nnz; +} + +/* Utility macros used by binary vector operations */ +/* Compute total number of indices between two sparse vectors */ +FMPZ_SPARSE_VEC_INLINE +slong _fmpz_sparse_vec_union_nnz_nmod(const fmpz_sparse_vec_t u, const nmod_sparse_vec_t v) +{ + slong i, j, nnz = 0; + for (i = j = 0; i < u->nnz && j < v->nnz; ++nnz) + { + if (u->entries[i].ind == v->entries[j].ind) ++i, ++j; + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } + nnz += u->nnz - i + v->nnz - j; + return nnz; +} + +/* Iterate through u and v in descending order, assigning sorted indices to w */ +/* Returns -1 if u and v are both exhausted, + 2 if we->ind = ue->ind == ve->ind + 1 if we->ind = ve->ind > ue->ind (or u exhausted), + 0 if we->ind = ue->ind > ve->ind (or v exhausted). */ +FMPZ_SPARSE_VEC_INLINE +slong _fmpz_sparse_vector_merge_descend(fmpz_sparse_entry_struct **we, + fmpz_sparse_entry_struct **ue, + fmpz_sparse_entry_struct **ve, + const fmpz_sparse_vec_t u, + const fmpz_sparse_vec_t v) +{ + slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; + slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; + if(uind == -1 && vind == -1) return -1; + if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + --*ue, --*we; (*we)->ind = uind; return 0; +} + +/* Iterate through u and v in descending order, assigning sorted indices to w */ +/* Returns -1 if u and v are both exhausted, + 2 if we->ind = ue->ind == ve->ind + 1 if we->ind = ve->ind > ue->ind (or u exhausted), + 0 if we->ind = ue->ind > ve->ind (or v exhausted). */ +FMPZ_SPARSE_VEC_INLINE +slong _fmpz_sparse_vector_merge_descend_nmod(fmpz_sparse_entry_struct **we, + fmpz_sparse_entry_struct **ue, + nmod_sparse_entry_struct **ve, + const fmpz_sparse_vec_t u, + const nmod_sparse_vec_t v) +{ + slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; + slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; + if(uind == -1 && vind == -1) return -1; + if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + --*ue, --*we; (*we)->ind = uind; return 0; +} + +/* Like resize, but removes entries from the front of the vector */ +FMPZ_SPARSE_VEC_INLINE +void _fmpz_sparse_vector_shift_left (fmpz_sparse_vec_t v, slong amt) +{ + slong i; + if (amt == v->nnz) fmpz_sparse_vec_clear(v); + else if(amt > 0) + { + for (i = amt; i < v->nnz; ++i) + { + v->entries[i-amt].ind = v->entries[i].ind; + fmpz_set(v->entries[i - amt].val, v->entries[i].val); + } + _fmpz_sparse_vec_resize(v, v->nnz - amt); + } +} + +FLINT_DLL +void fmpz_sparse_vec_add(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v); + +FLINT_DLL +void fmpz_sparse_vec_sub(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v); + +FLINT_DLL +void fmpz_sparse_vec_scalar_addmul_fmpz(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, const fmpz_t c); + +FLINT_DLL +void fmpz_sparse_vec_scalar_submul_fmpz(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, const fmpz_t c); + +FLINT_DLL +void fmpz_sparse_vec_dot(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v); + +FLINT_DLL +void fmpz_sparse_vec_dot_dense(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz *v); + +/* Gaussian elimination operations */ +FLINT_DLL +void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col); + +FLINT_DLL +void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v); + +FLINT_DLL +void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/fmpz_sparse_vec/CRT_ui.c b/fmpz_sparse_vec/CRT_ui.c new file mode 100644 index 0000000000..3472717fe8 --- /dev/null +++ b/fmpz_sparse_vec/CRT_ui.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "nmod_sparse_vec.h" +#include "fmpz_sparse_vec.h" + +void +fmpz_sparse_vec_CRT_ui(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_t m1, + const nmod_sparse_vec_t v, nmod_t m2, mp_limb_t m1i_m2, int sign) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + fmpz_sparse_entry_struct *ue, *we; + nmod_sparse_entry_struct *ve; + fmpz_t m1m2, zero; + fmpz_init(m1m2); + fmpz_init_set_ui(zero, UWORD(0)); + fmpz_mul_ui(m1m2, m1, m2.n); + + wnnz = _fmpz_sparse_vec_union_nnz_nmod (u, v); + _fmpz_sparse_vec_resize(w, wnnz); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _fmpz_sparse_vector_merge_descend_nmod (&we, &ue, &ve, u, v)) >= 0) + { + _fmpz_CRT_ui_precomp(we->val, (k==1)?zero:ue->val, m1, (k==0)?UWORD(0):ve->val, + m2.n, m2.ninv, m1m2, m1i_m2, sign); + } + fmpz_clear(zero); + fmpz_clear(m1m2); +} + diff --git a/fmpz_sparse_vec/add.c b/fmpz_sparse_vec/add.c new file mode 100644 index 0000000000..92282452c6 --- /dev/null +++ b/fmpz_sparse_vec/add.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_add(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + fmpz_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (vnnz == 0) fmpz_sparse_vec_set(w, u, 0); + else if (unnz == 0) fmpz_sparse_vec_set(w, v, 0); + else + { + wnnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(w, wnnz); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _fmpz_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: fmpz_set(we->val, ue->val); break; + case 1: fmpz_set(we->val, ve->val); break; + default: fmpz_add(we->val, ue->val, ve->val); + if (fmpz_is_zero(we->val)) we++; + } + } + _fmpz_sparse_vector_shift_left (w, we - w->entries); + } +} diff --git a/fmpz_sparse_vec/at.c b/fmpz_sparse_vec/at.c new file mode 100644 index 0000000000..f89a71fec4 --- /dev/null +++ b/fmpz_sparse_vec/at.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +fmpz_t *fmpz_sparse_vec_at(const fmpz_sparse_vec_t vec, slong i) +{ + /* TODO: binary search */ + slong j; + for (j = 0; j < vec->nnz; ++j) + if (vec->entries[j].ind==i) return &vec->entries[j].val; + return NULL; +} + diff --git a/fmpz_sparse_vec/concat.c b/fmpz_sparse_vec/concat.c new file mode 100644 index 0000000000..37b7caefd6 --- /dev/null +++ b/fmpz_sparse_vec/concat.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_concat(fmpz_sparse_vec_t res, const fmpz_sparse_vec_t vec1, const fmpz_sparse_vec_t vec2, slong len1) +{ + slong i, nnz = vec1->nnz + vec2->nnz; + _fmpz_sparse_vec_resize (res, nnz); + for (i = 0; i < nnz; ++i) + { + fmpz_sparse_entry_struct *e = (i < vec1->nnz) ? &vec1->entries[i] : &vec2->entries[i-vec1->nnz]; + res->entries[i].ind = e->ind + ((i < vec1->nnz) ? 0 : len1); + fmpz_set (res->entries[i].val, e->val); + } +} diff --git a/fmpz_sparse_vec/dot.c b/fmpz_sparse_vec/dot.c new file mode 100644 index 0000000000..d7fb1f8774 --- /dev/null +++ b/fmpz_sparse_vec/dot.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_dot(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + slong i, j; + fmpz_zero(ret); + for (i = j = 0; i < u->nnz && j < v->nnz; ) + { + if (u->entries[i].ind == v->entries[j].ind) + { + fmpz_addmul(ret, u->entries[i].val, v->entries[j].val); + ++i; ++j; + } + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } +} diff --git a/fmpz_sparse_vec/dot_dense.c b/fmpz_sparse_vec/dot_dense.c new file mode 100644 index 0000000000..b7baec33f4 --- /dev/null +++ b/fmpz_sparse_vec/dot_dense.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_dot_dense(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz *v) { + slong i; + fmpz_zero(ret); + for (i = 0; i < u->nnz; ++i) fmpz_addmul(ret, u->entries[i].val, &v[u->entries[i].ind]); + +} diff --git a/fmpz_sparse_vec/equal.c b/fmpz_sparse_vec/equal.c new file mode 100644 index 0000000000..ef5ce60a1e --- /dev/null +++ b/fmpz_sparse_vec/equal.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +int fmpz_sparse_vec_equal(const fmpz_sparse_vec_t vec1, const fmpz_sparse_vec_t vec2, slong ioff) +{ + slong i; + if (vec1->nnz != vec2->nnz) return 0; + for (i = 0; i < vec1->nnz; ++i) + { + if ((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || + (!fmpz_equal(vec1->entries[i].val, vec2->entries[i].val))) return 0; + } + return 1; +} diff --git a/fmpz_sparse_vec/from_dense.c b/fmpz_sparse_vec/from_dense.c new file mode 100644 index 0000000000..1eba2e3943 --- /dev/null +++ b/fmpz_sparse_vec/from_dense.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_from_dense(fmpz_sparse_vec_t dst, const fmpz *src, slong len) +{ + slong i, nnz = 0; + fmpz_sparse_entry_struct *e; + for (i = 0; i < len; ++i) + if (!fmpz_is_zero(&src[i])) ++nnz; + _fmpz_sparse_vec_resize(dst, nnz); + e = dst->entries; + for (i = 0; i < len; ++i) + if (!fmpz_is_zero(&src[i])) + e->ind = i, fmpz_set(e->val, &src[i]), ++e; +} \ No newline at end of file diff --git a/fmpz_sparse_vec/from_entries.c b/fmpz_sparse_vec/from_entries.c new file mode 100644 index 0000000000..1b5d0bdc72 --- /dev/null +++ b/fmpz_sparse_vec/from_entries.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_from_entries(fmpz_sparse_vec_t vec, slong * inds, fmpz * vals, slong nnz) +{ + if (nnz == 0) fmpz_sparse_vec_clear(vec); + else { + slong i; + _fmpz_sparse_vec_resize(vec, nnz); + for (i = 0; i < nnz; ++i) + { + vec->entries[i].ind = inds[i]; + fmpz_set(vec->entries[i].val, &vals[i]); + } + } +} diff --git a/fmpz_sparse_vec/gauss_elim.c b/fmpz_sparse_vec/gauss_elim.c new file mode 100644 index 0000000000..06fb9555d8 --- /dev/null +++ b/fmpz_sparse_vec/gauss_elim.c @@ -0,0 +1,122 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col) +{ + fmpz_t q; + fmpz_t *uc = fmpz_sparse_vec_at(u, col); + fmpz_t *vc = fmpz_sparse_vec_at(v, col); + if (uc == NULL || vc == NULL) return; + + fmpz_init(q); + fmpz_fdiv_q(q, *uc, *vc); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + fmpz_t q, *uc; + fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; + if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; + fmpz_init(q); + if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); + else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ +void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) +{ + slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; + fmpz_sparse_entry_struct *lu = u->entries; + fmpz_sparse_entry_struct *lv = v->entries; + fmpz_t g, vv, vu, uv, uu, a, b; + fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; + if(u->nnz == 0 || v->nnz == 0) return; + if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} + pc = lu->ind; + if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ + { + fmpz_sparse_vec_swap(u, v); + fmpz_sparse_vec_neg(u, u); + lu = u->entries, lv = v->entries; + vnnz = v->nnz, unnz = u->nnz; + } + if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ + { + fmpz_sparse_vec_neg(v, v); + fmpz_sparse_vec_neg(u, u); + } + + /* Check for trivial cases */ + if (fmpz_divisible(lu->val, lv->val)) {fmpz_sparse_vec_gauss_elim(u, v); return;} + + fmpz_init(g); + fmpz_init(vv); + fmpz_init(vu); + fmpz_init(uv); + fmpz_init(uu); + fmpz_init(a); + fmpz_init(b); + + /* Construct transformation */ + fmpz_xgcd(g, vv, vu, lv->val, lu->val); + if (fmpz_sgn(g) < 0) + { + fmpz_neg(vv, vv); + fmpz_neg(vu, vu); + } + fmpz_divexact(uu, lv->val, g); + fmpz_divexact(uv, lu->val, g); + fmpz_neg(uv, uv); /* [[uu uv] [vu vv]] is unimodular */ + + /* Reallocate vectors */ + nnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(u, nnz); + _fmpz_sparse_vec_resize(v, nnz); + ue = u->entries + unnz, ve = v->entries + vnnz; /* Old locations */ + nue = u->entries + nnz, nve = v->entries + nnz; /* New locations */ + while ((k = _fmpz_sparse_vector_merge_descend (&nue, &ue, &ve, u, v)) >= 0) + { + nve--; + switch(k) + { + case 0: nve->ind = ue->ind; fmpz_mul(nve->val, ue->val, vu); fmpz_mul(nue->val, ue->val, uu); break; + case 1: nve->ind = ve->ind; fmpz_mul(nue->val, ve->val, uv); fmpz_mul(nve->val, ve->val, vv); break; + default: nve->ind = ve->ind; + fmpz_set(a, ve->val); + fmpz_set(b, ue->val); + fmpz_mul(nve->val, a, vv); fmpz_addmul(nve->val, b, vu); + fmpz_mul(nue->val, b, uu); fmpz_addmul(nue->val, a, uv); + } + if (fmpz_is_zero(nue->val)) nue++; + if (fmpz_is_zero(nve->val)) nve++; + } + _fmpz_sparse_vector_shift_left (u, nue - u->entries); + _fmpz_sparse_vector_shift_left (v, nve - v->entries); + fmpz_clear(g); + fmpz_clear(vv); + fmpz_clear(vu); + fmpz_clear(uv); + fmpz_clear(uu); + fmpz_clear(a); + fmpz_clear(b); +} diff --git a/fmpz_sparse_vec/gauss_elim_debugging b/fmpz_sparse_vec/gauss_elim_debugging new file mode 100644 index 0000000000..48040a0972 --- /dev/null +++ b/fmpz_sparse_vec/gauss_elim_debugging @@ -0,0 +1,146 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col) +{ + fmpz_t q; + fmpz_t *uc = fmpz_sparse_vec_at(u, col); + fmpz_t *vc = fmpz_sparse_vec_at(v, col); + if (uc == NULL || vc == NULL) return; + + fmpz_init(q); + fmpz_fdiv_q(q, *uc, *vc); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + fmpz_t q, *uc; + fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; + if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; + fmpz_init(q); + flint_printf("Doing ordinary gaussian elimination, found coefficient "); + if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); + else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); + fmpz_print(q); flint_printf(": %wd\n", q[0]); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ +void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) +{ + slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; + fmpz_sparse_entry_struct *lu = u->entries; + fmpz_sparse_entry_struct *lv = v->entries; + fmpz_t g, vv, vu, uv, uu, a, b; + fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; + if(u->nnz == 0 || v->nnz == 0) return; + flint_printf("\t\t\t%wd, %wd\n", lu->ind, lv->ind); + if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} + pc = lu->ind; + if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ + { + flint_printf("Swapping\n"); + fmpz_sparse_vec_swap(u, v); + fmpz_sparse_vec_neg(u, u); + lu = u->entries, lv = v->entries; + vnnz = v->nnz, unnz = u->nnz; + } + if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ + { + fmpz_sparse_vec_neg(v, v); + fmpz_sparse_vec_neg(u, u); + } + flint_printf("pr[pc] = "), fmpz_print(lv->val), flint_printf("\n"); + flint_printf("r[pc] = "), fmpz_print(lu->val), flint_printf("\n"); + + /* Check for trivial cases */ + if (fmpz_divisible(lu->val, lv->val)) {fmpz_sparse_vec_gauss_elim(u, v); return;} + + fmpz_init(g); + fmpz_init(vv); + fmpz_init(vu); + fmpz_init(uv); + fmpz_init(uu); + fmpz_init(a); + fmpz_init(b); + + /* Construct transformation */ + fmpz_xgcd(g, vv, vu, lv->val, lu->val); + if (fmpz_sgn(g) < 0) + { + fmpz_neg(vv, vv); + fmpz_neg(vu, vu); + } + fmpz_divexact(uu, lv->val, g); + fmpz_divexact(uv, lu->val, g); + fmpz_neg(uv, uv); /* [[uu uv] [vu vv]] is unimodular */ + fmpz_set(g, uv); + flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); + flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); + flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); + + /* Reallocate vectors */ + nnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(u, nnz); + _fmpz_sparse_vec_resize(v, nnz); + ue = u->entries + unnz, ve = v->entries + vnnz; /* Old locations */ + nue = u->entries + nnz, nve = v->entries + nnz; /* New locations */ + while ((k = _fmpz_sparse_vector_merge_descend (&nue, &ue, &ve, u, v)) >= 0) + { + nve--; + flint_printf("%wd, %wd, %wd\n", nnz, nue - u->entries, nve-v->entries); + flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); + flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); + flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); + flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); + flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); + switch(k) + { + case 0: nve->ind = ue->ind; fmpz_mul(nve->val, ue->val, vu); fmpz_mul(nue->val, ue->val, uu); break; + case 1: nve->ind = ve->ind; fmpz_mul(nue->val, ve->val, g); fmpz_mul(nve->val, ve->val, vv); break; + default: nve->ind = ve->ind; + flint_printf("\t\tcur: [[%wd, %wd], [%wd, %wd]]\n", nue->val[0], nve->val[0], ue->val[0], ve->val[0]); + flint_printf("\t\tcur: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); + flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); + + fmpz_set(a, ve->val); + fmpz_set(b, ue->val); + fmpz_mul(nve->val, a, vv); fmpz_addmul(nve->val, b, vu); + fmpz_mul(nue->val, b, uu); fmpz_addmul(nue->val, a, uv); + flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(vu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(vv); flint_printf("\n"); + flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(uu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); flint_printf("\n"); + flint_printf("\t\tafter: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); + flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); + } + if (fmpz_is_zero(nue->val)) nue++; + if (fmpz_is_zero(nve->val)) nve++; + } + _fmpz_sparse_vector_shift_left (u, nue - u->entries); + _fmpz_sparse_vector_shift_left (v, nve - v->entries); + fmpz_clear(g); + fmpz_clear(vv); + fmpz_clear(vu); + fmpz_clear(uv); + fmpz_clear(uu); + fmpz_clear(a); + fmpz_clear(b); +} diff --git a/fmpz_sparse_vec/max_bits.c b/fmpz_sparse_vec/max_bits.c new file mode 100644 index 0000000000..94e83083c4 --- /dev/null +++ b/fmpz_sparse_vec/max_bits.c @@ -0,0 +1,78 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + + +slong fmpz_sparse_vec_max_bits(const fmpz_sparse_vec_t v) +{ + slong i, sign, max_limbs; + mp_limb_t max_limb; + mp_size_t limbs; + + sign = 1; + max_limb = 0; + + for (i = 0; i < v->nnz; i++) + { + fmpz c = *(v->entries[i].val); + + if (c >= 0) + { + if (c > COEFF_MAX) + goto bignum; + max_limb |= c; + } + else + { + if (c < COEFF_MIN) + goto bignum; + max_limb |= -c; + sign = -1; + } + } + return sign * FLINT_BIT_COUNT(max_limb); + +bignum: + max_limbs = 1; + + for ( ; i < v->nnz; i++) + { + fmpz c = *(v->entries[i].val); + + if (COEFF_IS_MPZ(c)) + { + __mpz_struct * z = COEFF_TO_PTR(c); + limbs = z->_mp_size; + + if (limbs < 0) + { + sign = -1; + limbs = -limbs; + } + + if (limbs == max_limbs) + max_limb |= z->_mp_d[limbs - 1]; + else if (limbs > max_limbs) + { + max_limb = z->_mp_d[limbs - 1]; + max_limbs = limbs; + } + } + else if (c < 0) + sign = -1; + } + return sign * ((max_limbs - 1) * FLINT_BITS + FLINT_BIT_COUNT(max_limb)); +} \ No newline at end of file diff --git a/fmpz_sparse_vec/multi_CRT_ui.c b/fmpz_sparse_vec/multi_CRT_ui.c new file mode 100644 index 0000000000..ad13f836e7 --- /dev/null +++ b/fmpz_sparse_vec/multi_CRT_ui.c @@ -0,0 +1,72 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_vec.h" + +void +fmpz_sparse_vec_multi_CRT_ui_precomp(fmpz_sparse_vec_t v, nmod_sparse_vec_struct const * residues, slong nres, + const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) +{ + slong i, j, pos, *rpos, max_nnz, max_ind; + mp_limb_t *r; + nmod_sparse_vec_struct *vm; + fmpz_sparse_entry_struct *e; + + for (j = max_nnz = max_ind = 0; j < nres; ++j) + { + vm = &residues[j]; + max_nnz = FLINT_MAX(max_nnz, vm->nnz); + if (vm->nnz != 0) max_ind = FLINT_MAX(max_ind, vm->entries[vm->nnz - 1].ind); + } + _fmpz_sparse_vec_resize(v, max_nnz); /* May change later */ + if (max_nnz == 0) return; + + rpos = flint_calloc(nres, sizeof(*rpos)); + r = flint_malloc(nres * sizeof (*r)); + for(pos = 0; ; ++pos) + { + if (pos == max_nnz) max_nnz *= 2, _fmpz_sparse_vec_resize(v, max_nnz); + e = &v->entries[pos]; + + /* Get next minimal index */ + e->ind = max_ind + 1; + for (j = 0; j < nres; ++j) + { + vm = &residues[j]; + e->ind = (rpos[j] != vm->nnz && vm->entries[rpos[j]].ind < e->ind) ? vm->entries[rpos[j]].ind : e->ind; + } + if (e->ind == max_ind + 1) break; + for (j = 0; j < nres; ++j) + { + vm = &residues[j]; + r[j] = (rpos[j] != vm->nnz && vm->entries[rpos[j]].ind == e->ind) ? vm->entries[rpos[j]++].val : 0; + } + fmpz_multi_CRT_ui(e->val, r, comb, temp, sign); + } + _fmpz_sparse_vec_resize(v, pos); + flint_free(rpos); + flint_free(r); +} + +void +fmpz_sparse_vec_multi_CRT_ui(fmpz_sparse_vec_t v, nmod_sparse_vec_struct * const residues, mp_srcptr primes, slong nres, int sign) +{ + fmpz_comb_t comb; + fmpz_comb_temp_t temp; + + fmpz_comb_init(comb, primes, nres); + fmpz_comb_temp_init(temp, comb); + + fmpz_sparse_vec_multi_CRT_ui_precomp(v, residues, nres, comb, temp, sign); + + fmpz_comb_clear(comb); + fmpz_comb_temp_clear(temp); +} diff --git a/fmpz_sparse_vec/multi_mod_ui.c b/fmpz_sparse_vec/multi_mod_ui.c new file mode 100644 index 0000000000..05c752981a --- /dev/null +++ b/fmpz_sparse_vec/multi_mod_ui.c @@ -0,0 +1,62 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_sparse_vec.h" + +/* for (j = 0; j < fmpz_vec_ncols(vec); j++) + { + + for (k = 0; k < nres; k++) + nmod_vec_entry(residues[k], i, j) = r[k]; + } + */ +void +fmpz_sparse_vec_multi_mod_ui_precomp(nmod_sparse_vec_struct * residues, slong nres, const fmpz_sparse_vec_t v, + const fmpz_comb_t comb, fmpz_comb_temp_t temp) +{ + slong i, j; + nmod_sparse_entry_struct *e; + nmod_sparse_vec_struct *vm; + mp_limb_t *r; + + r = flint_malloc(nres * sizeof(*r)); + + for (j = 0; j < nres; ++j) + vm = &residues[j], vm->entries = realloc(vm->entries, v->nnz * sizeof(*vm->entries)), vm->nnz = 0; + + for (i = 0; i < v->nnz; i++) + { + fmpz_multi_mod_ui(r, v->entries[i].val, comb, temp); + for (j = 0; j < nres; ++j) + if (r[j] != UWORD(0)) + e = &residues[j].entries[residues[j].nnz++], e->ind = v->entries[i].ind, e->val = r[j]; + } + + for (j = 0; j < nres; ++j) + vm = &residues[j], vm->entries = realloc(vm->entries, vm->nnz * sizeof(*vm->entries)); + + flint_free(r); +} + +void +fmpz_sparse_vec_multi_mod_ui(nmod_sparse_vec_struct * residues, mp_srcptr primes, slong nres, const fmpz_sparse_vec_t v) +{ + fmpz_comb_t comb; + fmpz_comb_temp_t temp; + + fmpz_comb_init(comb, primes, nres); + fmpz_comb_temp_init(temp, comb); + + fmpz_sparse_vec_multi_mod_ui_precomp(residues, nres, v, comb, temp); + + fmpz_comb_clear(comb); + fmpz_comb_temp_clear(temp); +} diff --git a/fmpz_sparse_vec/print_pretty.c b/fmpz_sparse_vec/print_pretty.c new file mode 100644 index 0000000000..c385a71951 --- /dev/null +++ b/fmpz_sparse_vec/print_pretty.c @@ -0,0 +1,36 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +void +fmpz_sparse_vec_print_pretty(const fmpz_sparse_vec_t vec, slong ioff, slong maxi) +{ + slong i; + char ind_fmt[FLINT_BITS + 5]; + + flint_sprintf(ind_fmt, "%%%dwd:", n_sizeinbase(maxi, 10)); + + flint_printf("["); + for (i = 0; i < vec->nnz; i++) + { + flint_printf(ind_fmt, vec->entries[i].ind - ioff); + fmpz_print(vec->entries[i].val); + if (i + 1 < vec->nnz) flint_printf(" "); + } + flint_printf("]\n"); +} + diff --git a/fmpz_sparse_vec/randtest.c b/fmpz_sparse_vec/randtest.c new file mode 100644 index 0000000000..818c48b4cb --- /dev/null +++ b/fmpz_sparse_vec/randtest.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_randtest(fmpz_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, flint_bitcnt_t bits) +{ + slong i, j; + nnz = FLINT_MIN(nnz, len); + _fmpz_sparse_vec_resize(vec, nnz); + for (i = 0; i < nnz; ++i) + { + vec->entries[i].ind = i; + do fmpz_randtest(vec->entries[i].val, state, bits); + while (fmpz_is_zero(vec->entries[i].val)); + } + + /* Use resevoir sampling to get random support */ + for (j = nnz; j < len; ++j) + { + i = n_randint(state, j+1); + if (i < nnz) vec->entries[i].ind = j; + } + qsort(vec->entries, nnz, sizeof(*vec->entries), fmpz_sparse_entry_cmp); +} diff --git a/fmpz_sparse_vec/randtest_unsigned.c b/fmpz_sparse_vec/randtest_unsigned.c new file mode 100644 index 0000000000..8c66e30271 --- /dev/null +++ b/fmpz_sparse_vec/randtest_unsigned.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_randtest_unsigned(fmpz_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, flint_bitcnt_t bits) +{ + slong i, j; + nnz = FLINT_MIN(nnz, len); + _fmpz_sparse_vec_resize(vec, nnz); + for (i = 0; i < nnz; ++i) + { + vec->entries[i].ind = i; + do fmpz_randtest_unsigned(vec->entries[i].val, state, bits); + while (fmpz_is_zero(vec->entries[i].val)); + } + + /* Use resevoir sampling to get random support */ + for (j = nnz; j < len; ++j) + { + i = n_randint(state, j+1); + if (i < nnz) vec->entries[i].ind = j; + } + qsort(vec->entries, nnz, sizeof(*vec->entries), fmpz_sparse_entry_cmp); +} diff --git a/fmpz_sparse_vec/scalar_addmul.c b/fmpz_sparse_vec/scalar_addmul.c new file mode 100644 index 0000000000..4dab59b4f7 --- /dev/null +++ b/fmpz_sparse_vec/scalar_addmul.c @@ -0,0 +1,49 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_addmul_fmpz(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, const fmpz_t c) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + fmpz_t tmp; + fmpz_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (fmpz_is_zero(c) || vnnz == 0) fmpz_sparse_vec_set(w, u, 0); + else if (fmpz_is_one(c)) fmpz_sparse_vec_add(w, u, v); + else if (fmpz_equal_si(c, WORD(-1))) fmpz_sparse_vec_sub(w, u, v); + else if (unnz == 0) fmpz_sparse_vec_scalar_mul_fmpz(w, v, c); + else + { + fmpz_init(tmp); + wnnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(w, wnnz); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _fmpz_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: fmpz_set(we->val, ue->val); break; + case 1: fmpz_mul(we->val, ve->val, c); break; + default: fmpz_mul(tmp, ve->val, c); + fmpz_add(we->val, ue->val, tmp); + if (fmpz_is_zero(we->val)) we++; + } + } + _fmpz_sparse_vector_shift_left (w, we - w->entries); + fmpz_clear(tmp); + } +} diff --git a/fmpz_sparse_vec/scalar_divexact.c b/fmpz_sparse_vec/scalar_divexact.c new file mode 100644 index 0000000000..f45f27f2ea --- /dev/null +++ b/fmpz_sparse_vec/scalar_divexact.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_divexact_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t c) +{ + if (fmpz_is_one(c)) fmpz_sparse_vec_set(v, u, 0); + else if (fmpz_equal_si(c, WORD(-1))) fmpz_sparse_vec_neg(v, u); + else + { + slong i; + fmpz_sparse_vec_set(v, u, 0); + for (i = 0; i < v->nnz; ++i) fmpz_divexact(v->entries[i].val, v->entries[i].val, c); + } +} \ No newline at end of file diff --git a/fmpz_sparse_vec/scalar_mod.c b/fmpz_sparse_vec/scalar_mod.c new file mode 100644 index 0000000000..1273ba4bab --- /dev/null +++ b/fmpz_sparse_vec/scalar_mod.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_mod_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t mod) +{ + if (fmpz_is_one(mod)) fmpz_sparse_vec_zero(v); + else + { + slong i, ind; + fmpz_sparse_vec_set(v, u, 0); + for (i = ind = 0; i < v->nnz; ++i) + { + v->entries[ind].ind = v->entries[i].ind; + fmpz_mod(v->entries[ind].val, v->entries[i].val, mod); + if (!fmpz_is_zero(v->entries[ind].val)) ++ind; + } + _fmpz_sparse_vec_resize(v, ind); + } +} \ No newline at end of file diff --git a/fmpz_sparse_vec/scalar_mods.c b/fmpz_sparse_vec/scalar_mods.c new file mode 100644 index 0000000000..16db4c12d1 --- /dev/null +++ b/fmpz_sparse_vec/scalar_mods.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_mods_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t mod) +{ + if (fmpz_is_one(mod)) fmpz_sparse_vec_zero(v); + else + { + slong i, ind; + fmpz_sparse_vec_set(v, u, 0); + for (i = ind = 0; i < v->nnz; ++i) + { + v->entries[ind].ind = v->entries[i].ind; + fmpz_mods(v->entries[ind].val, v->entries[i].val, mod); + if (!fmpz_is_zero(v->entries[ind].val)) ++ind; + } + _fmpz_sparse_vec_resize(v, ind); + } +} \ No newline at end of file diff --git a/fmpz_sparse_vec/scalar_mul.c b/fmpz_sparse_vec/scalar_mul.c new file mode 100644 index 0000000000..50522125f0 --- /dev/null +++ b/fmpz_sparse_vec/scalar_mul.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_mul_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec_t u, const fmpz_t c) +{ + if (fmpz_is_zero(c)) fmpz_sparse_vec_zero(v); + else if (fmpz_is_one(c)) fmpz_sparse_vec_set(v, u, 0); + else if (fmpz_equal_si(c, WORD(-1))) fmpz_sparse_vec_neg(v, u); + else + { + slong i; + fmpz_sparse_vec_set(v, u, 0); + for (i = 0; i < v->nnz; ++i) fmpz_mul(v->entries[i].val, v->entries[i].val, c); + } +} \ No newline at end of file diff --git a/fmpz_sparse_vec/scalar_submul.c b/fmpz_sparse_vec/scalar_submul.c new file mode 100644 index 0000000000..8ada9678f6 --- /dev/null +++ b/fmpz_sparse_vec/scalar_submul.c @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_scalar_submul_fmpz(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, const fmpz_t c) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + fmpz_t tmp, tmp2; + fmpz_sparse_entry_struct *ue, *ve, *we; + +/* flint_printf("c = "), fmpz_print(c); flint_printf("\n"); */ + /* Check for simpler operations first */ + if (fmpz_is_zero(c) || vnnz == 0) fmpz_sparse_vec_set(w, u, 0); + else if (fmpz_is_one(c)) fmpz_sparse_vec_sub(w, u, v); + else if (fmpz_equal_si(c, WORD(-1))) fmpz_sparse_vec_add(w, u, v); + else if (unnz == 0) + { + fmpz_sparse_vec_scalar_mul_fmpz(w, v, c); + fmpz_sparse_vec_neg(w, w); + } + else + { + fmpz_init(tmp); + fmpz_init_set(tmp2, c); + wnnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(w, wnnz); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + /* flint_printf("c = "), fmpz_print(c); flint_printf(": %wd\n", c[0]); */ + while ((k = _fmpz_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { +/* flint_printf("\t\t\tc = "), fmpz_print(c); flint_printf("\n"); + flint_printf("\t\t\ttmp = %wd, tmp2 = %wd\n", tmp[0], tmp2[0]); */ + switch(k) + { + case 0: fmpz_set(we->val, ue->val); break; + case 1: fmpz_mul(we->val, ve->val, tmp2); fmpz_neg(we->val, we->val); break; + default: +/* flint_printf("\t\tSubtracting: "); + fmpz_print(we->val); flint_printf(" <- "); + fmpz_print(ue->val); flint_printf("-"); + fmpz_print(ve->val); flint_printf("*"); fmpz_print(c); flint_printf("\n"); + flint_printf("%wd <- %wd - %wd * %wd\n", we->val[0], ue->val[0], ve->val[0], c[0]); + flint_printf("c1: "); fmpz_print(c); flint_printf("\n"); */ + fmpz_mul(tmp, ve->val, tmp2); +/* flint_printf("%wd = %wd * %wd\n", tmp[0], ve->val[0], c[0]); + flint_printf("c2: "); fmpz_print(c); flint_printf("\n"); */ + fmpz_sub(we->val, ue->val, tmp); +/* flint_printf("%wd = %wd - %wd, %wd\n", we->val[0], ue->val[0], tmp[0], c[0]); + flint_printf("c3: "); fmpz_print(c); flint_printf("\n"); */ + if (fmpz_is_zero(we->val)) we++; +/* flint_printf("c4: "); fmpz_print(c); flint_printf("\n"); */ + } +/* flint_printf("\t\tAfter subtraction: %wd, %wd\n", k, we->ind); + flint_printf("\t\t\tr: "); fmpz_sparse_vec_print_pretty(w, 0, 0); flint_printf("\n"); */ + } + _fmpz_sparse_vector_shift_left (w, we - w->entries); + fmpz_clear(tmp); + fmpz_clear(tmp2); + } +} diff --git a/fmpz_sparse_vec/set.c b/fmpz_sparse_vec/set.c new file mode 100644 index 0000000000..d8322b365e --- /dev/null +++ b/fmpz_sparse_vec/set.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_set(fmpz_sparse_vec_t dst, const fmpz_sparse_vec_t src, slong ioff) +{ + slong i; + if (dst == src) return; + _fmpz_sparse_vec_resize(dst, src->nnz); + for(i=0; innz; ++i) + { + dst->entries[i].ind = src->entries[i].ind - ioff; + fmpz_set(dst->entries[i].val, src->entries[i].val); + } +} \ No newline at end of file diff --git a/fmpz_sparse_vec/split.c b/fmpz_sparse_vec/split.c new file mode 100644 index 0000000000..c03d777181 --- /dev/null +++ b/fmpz_sparse_vec/split.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_split(fmpz_sparse_vec_t res1, fmpz_sparse_vec_t res2, const fmpz_sparse_vec_t vec, slong ind) +{ + slong i, nnz1; + fmpz_sparse_entry_struct *e1, *e2, *e; + for(nnz1=0; nnz1nnz; ++nnz1) if(vec->entries[nnz1].ind >= ind) break; + + _fmpz_sparse_vec_resize(res1, nnz1); + _fmpz_sparse_vec_resize(res2, vec->nnz - nnz1); + e1 = res1->entries, e2 = res2->entries; + for (i = 0; i < vec->nnz; ++i) + { + e = (i < nnz1) ? e1++ : e2++; + e->ind = vec->entries[i].ind - ((i < nnz1) ? 0 : ind); + fmpz_set(e->val, vec->entries[i].val); + } +} diff --git a/fmpz_sparse_vec/sub.c b/fmpz_sparse_vec/sub.c new file mode 100644 index 0000000000..927e9909b3 --- /dev/null +++ b/fmpz_sparse_vec/sub.c @@ -0,0 +1,43 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_sub(fmpz_sparse_vec_t w, const fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + fmpz_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (vnnz == 0) fmpz_sparse_vec_set(w, u, 0); + else if (unnz == 0) fmpz_sparse_vec_neg(w, v); + else + { + wnnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(w, wnnz); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _fmpz_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: fmpz_set(we->val, ue->val); break; + case 1: fmpz_neg(we->val, ve->val); break; + default: fmpz_sub(we->val, ue->val, ve->val); + if (fmpz_is_zero(we->val)) we++; + } + } + _fmpz_sparse_vector_shift_left (w, we - w->entries); + } +} diff --git a/fmpz_sparse_vec/test/t-add.c b/fmpz_sparse_vec/test/t-add.c new file mode 100644 index 0000000000..c0c21b7efd --- /dev/null +++ b/fmpz_sparse_vec/test/t-add.c @@ -0,0 +1,82 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_sparse_vec_t u, v, w, x; + + FLINT_TEST_INIT(state); + + flint_printf("add/sub...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 256); + while(bits < UWORD(2)); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + fmpz_sparse_vec_init(x); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + + fmpz_sparse_vec_add(w, u, v); + fmpz_sparse_vec_sub(x, w, v); + + if (!fmpz_sparse_vec_equal(u, x, 0)) + { + flint_printf("FAIL: u != u+v-v\n"); + flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); + flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); + flint_printf("w = "), fmpz_sparse_vec_print_pretty(w, 0, 0); + flint_printf("x = "), fmpz_sparse_vec_print_pretty(x, 0, 0); + abort(); + } + + fmpz_sparse_vec_add(u, u, v); + if (!fmpz_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: (u += v) != u + v\n"); + abort(); + } + + fmpz_sparse_vec_sub(u, u, v); + if (!fmpz_sparse_vec_equal(u, x, 0)) + { + flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); + abort(); + } + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + fmpz_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-concat.c b/fmpz_sparse_vec/test/t-concat.c new file mode 100644 index 0000000000..5a59135963 --- /dev/null +++ b/fmpz_sparse_vec/test/t-concat.c @@ -0,0 +1,97 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int main(void) +{ + slong rep, bits, len, nnz; + fmpz_sparse_vec_t u, v, w; + fmpz_sparse_vec_t window1, window2; + FLINT_TEST_INIT(state); + + flint_printf("concat...."); + fflush(stdout); + + for (rep = 0; rep < 100; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + fmpz_sparse_vec_randtest(w, state, nnz, len, bits); + + fmpz_sparse_vec_concat(w, u, v, len); + + fmpz_sparse_vec_window_init(window1, w, 0, len); + fmpz_sparse_vec_window_init(window2, w, len, 2*len); + + if (!(fmpz_sparse_vec_equal(window1, u, 0) && fmpz_sparse_vec_equal(window2, v, len))) + { + flint_printf("u = "); + fmpz_sparse_vec_print_pretty(u, 0, len); + flint_printf("v = \n"); + fmpz_sparse_vec_print_pretty(v, 0, len); + flint_printf("u | v = \n"); + fmpz_sparse_vec_print_pretty(w, 0, len); + flint_printf("window1 = \n"); + fmpz_sparse_vec_print_pretty(window1, 0, len); + flint_printf("window2 = \n"); + fmpz_sparse_vec_print_pretty(window2, len, len); + flint_printf("FAIL: results not equal\n"); + abort(); + } + fmpz_sparse_vec_window_clear(window1); + fmpz_sparse_vec_window_clear(window2); + + fmpz_sparse_vec_init(window1); + fmpz_sparse_vec_init(window2); + fmpz_sparse_vec_split(window1, window2, w, len); + if (!(fmpz_sparse_vec_equal(window1, u, 0) && fmpz_sparse_vec_equal(window2, v, 0))) + { + flint_printf("u = "); + fmpz_sparse_vec_print_pretty(u, 0, len); + flint_printf("v = \n"); + fmpz_sparse_vec_print_pretty(v, 0, len); + flint_printf("u | v = \n"); + fmpz_sparse_vec_print_pretty(w, 0, len); + flint_printf("window1 = \n"); + fmpz_sparse_vec_print_pretty(window1, 0, len); + flint_printf("window2 = \n"); + fmpz_sparse_vec_print_pretty(window2, 0, len); + flint_printf("FAIL: results not equal\n"); + abort(); + } + fmpz_sparse_vec_clear(window1); + fmpz_sparse_vec_clear(window2); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + } + + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-construct.c b/fmpz_sparse_vec/test/t-construct.c new file mode 100644 index 0000000000..319790bec9 --- /dev/null +++ b/fmpz_sparse_vec/test/t-construct.c @@ -0,0 +1,75 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz, i; + fmpz_sparse_vec_t u, v; + slong *inds; + fmpz *vals; + FLINT_TEST_INIT(state); + + flint_printf("construction from elements...."); + fflush(stdout); + + for (rep = 0; rep < 1; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + len = n_randint(state, 10); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + + /* Construct v from entries of u */ + inds = flint_malloc(nnz * sizeof(*inds)); + vals = flint_malloc(nnz * sizeof(*vals)); + for (i = 0; i < nnz; ++i) + { + fmpz_init(&vals[i]); + inds[i] = u->entries[i].ind; + fmpz_set(&vals[i], u->entries[i].val); + } + fmpz_sparse_vec_from_entries(v, inds, vals, nnz); + + if (!fmpz_sparse_vec_equal(u, v, 0)) + { + fmpz_sparse_vec_print_pretty(u, 0, 0); + fmpz_sparse_vec_print_pretty(v, 0, 0); + abort(); + } + flint_free(inds); + for (i = 0; i < nnz; ++i) + { + fmpz_clear(&vals[i]); + } + flint_free(vals); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-dense.c b/fmpz_sparse_vec/test/t-dense.c new file mode 100644 index 0000000000..097c0addba --- /dev/null +++ b/fmpz_sparse_vec/test/t-dense.c @@ -0,0 +1,83 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz, i; + fmpz_sparse_vec_t u, v; + fmpz *w, *x; + FLINT_TEST_INIT(state); + + flint_printf("conversion to/from dense vector...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + w = _fmpz_vec_init(len); + x = _fmpz_vec_init(len); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + + fmpz_sparse_vec_to_dense(w, u, len); + fmpz_sparse_vec_from_dense(v, w, len); + + for (i = 0; i < len; ++i) + { + fmpz_t *val = fmpz_sparse_vec_at(u, i); + if ((fmpz_is_zero(&w[i]) && val != NULL) || (!fmpz_is_zero(&w[i]) && (val == NULL || !fmpz_equal(*val, &w[i])))) + { + flint_printf("FAIL: u[%wd] != v[%wd]\n", i, i); + abort(); + } + } + if (!fmpz_sparse_vec_equal(u, v, 0)) + { + flint_printf("FAIL: u != v\n"); + abort(); + } + + _fmpz_vec_randtest(w, state, len, bits); + fmpz_sparse_vec_from_dense(u, w, len); + fmpz_sparse_vec_to_dense(x, u, len); + + if (!_fmpz_vec_equal(w, x, len)) + { + flint_printf("FAIL: w != x\n"); + abort(); + } + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + _fmpz_vec_clear(w, len); + _fmpz_vec_clear(x, len); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-dot.c b/fmpz_sparse_vec/test/t-dot.c new file mode 100644 index 0000000000..b48479d25d --- /dev/null +++ b/fmpz_sparse_vec/test/t-dot.c @@ -0,0 +1,80 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_t a, b; + fmpz_sparse_vec_t u, v; + fmpz *w, *x; + FLINT_TEST_INIT(state); + + + flint_printf("dot product...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + fmpz_init(a); + fmpz_init(b); + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + w = _fmpz_vec_init(len); + x = _fmpz_vec_init(len); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + fmpz_sparse_vec_to_dense(w, u, len); + fmpz_sparse_vec_to_dense(x, v, len); + + fmpz_sparse_vec_dot(a, u, v); + _fmpz_vec_dot(b, w, x, len); + + if (!fmpz_equal(a, b)) + { + flint_printf("Fail: sparse dot sparse\n"); + abort(); + } + + fmpz_sparse_vec_dot_dense(a, u, x); + + if (!fmpz_equal(a, b)) + { + flint_printf("Fail: sparse dot dense\n"); + abort(); + } + fmpz_clear(a); + fmpz_clear(b); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + _fmpz_vec_clear(w, len); + _fmpz_vec_clear(x, len); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-gauss_elim.c b/fmpz_sparse_vec/test/t-gauss_elim.c new file mode 100644 index 0000000000..1996d62e9c --- /dev/null +++ b/fmpz_sparse_vec/test/t-gauss_elim.c @@ -0,0 +1,132 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "fmpz_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_t a, b, c, d, g; + fmpz_sparse_vec_t u, v, w, x, y; + FLINT_TEST_INIT(state); + + flint_printf("Gaussian elimination...."); + fflush(stdout); + + for (rep = 0; rep < 10; rep++) + { + do bits = n_randint(state, 10); + while(bits < UWORD(2)); + len = n_randint(state, 20); + nnz = n_randint(state, len+1); + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + fmpz_init(d); + fmpz_init(g); + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + fmpz_sparse_vec_init(x); + fmpz_sparse_vec_init(y); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + fmpz_sparse_vec_set(w, u, 0); + fmpz_sparse_vec_set(x, v, 0); + fmpz_sparse_vec_gauss_elim(x, w); + if (!fmpz_sparse_vec_equal(w, u, 0)) + { + flint_printf("FAIL: pivot row modified\n"); + abort(); + } + if (nnz != 0 && fmpz_sparse_vec_at(v, u->entries[0].ind) != NULL) + { + /* Undo elimination and check if matches original */ + fmpz_fdiv_q(c, *fmpz_sparse_vec_at(v, u->entries[0].ind), u->entries[0].val); + fmpz_sparse_vec_scalar_addmul_fmpz(w, x, u, c); + if (!fmpz_sparse_vec_equal(w, v, 0)) + { + flint_printf("FAIL: Incorrect Gaussian elimination\n"); + fmpz_sparse_vec_print_pretty(u, 0, len); + fmpz_sparse_vec_print_pretty(v, 0, len); + fmpz_sparse_vec_print_pretty(x, 0, len); + fmpz_sparse_vec_print_pretty(w, 0, len); + abort(); + } + } + else if (!fmpz_sparse_vec_equal(x, v, 0)) + { + flint_printf("FAIL: Incorrect Gaussian elimination on trivial vectors\n"); + fmpz_sparse_vec_print_pretty(x, 0, len); + abort(); + } + + if (nnz != 0 && u->entries[0].ind == v->entries[0].ind) + { + fmpz_sparse_vec_set(w, u, 0); + fmpz_sparse_vec_set(x, v, 0); + fmpz_sparse_vec_gauss_elim_ext(x, w); + + fmpz_xgcd(g, a, b, u->entries[0].val, v->entries[0].val); + fmpz_divexact(d, u->entries[0].val, g); + fmpz_divexact(c, v->entries[0].val, g); + fmpz_sparse_vec_scalar_mul_fmpz(y, w, d); + fmpz_sparse_vec_scalar_submul_fmpz(y, y, x, b); + if (!fmpz_sparse_vec_equal(y, u, 0)) + { + flint_printf("FAIL: did not recover u when inverting extended Gaussian elimination\n"); + fmpz_sparse_vec_print_pretty(u, 0, len); + fmpz_sparse_vec_print_pretty(v, 0, len); + fmpz_sparse_vec_print_pretty(w, 0, len); + fmpz_sparse_vec_print_pretty(x, 0, len); + fmpz_sparse_vec_print_pretty(y, 0, len); + abort(); + } + fmpz_sparse_vec_scalar_mul_fmpz(y, w, c); + fmpz_sparse_vec_scalar_addmul_fmpz(y, y, x, a); + if (!fmpz_sparse_vec_equal(y, v, 0)) + { + flint_printf("FAIL: did not recover v when inverting extended Gaussian elimination\n"); + fmpz_sparse_vec_print_pretty(u, 0, len); + fmpz_sparse_vec_print_pretty(v, 0, len); + fmpz_sparse_vec_print_pretty(w, 0, len); + fmpz_sparse_vec_print_pretty(x, 0, len); + fmpz_sparse_vec_print_pretty(y, 0, len); + abort(); + } + } + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + fmpz_clear(d); + fmpz_clear(g); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + fmpz_sparse_vec_clear(x); + fmpz_sparse_vec_clear(y); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-init_clear.c b/fmpz_sparse_vec/test/t-init_clear.c new file mode 100644 index 0000000000..5d6145aabc --- /dev/null +++ b/fmpz_sparse_vec/test/t-init_clear.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +static void check_zero(fmpz_sparse_vec_t vec) +{ + if (vec->nnz != UWORD(0)) +{ + flint_printf("FAIL: nnz not zero!\n"); + abort(); + } + if (vec->entries != NULL) +{ + flint_printf("FAIL: entries not null!\n"); + abort(); + } +} + +int +main(void) +{ + slong rep, len, nnz, bits, i; + fmpz_sparse_vec_t vec; + FLINT_TEST_INIT(state); + + flint_printf("init/clear...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + fmpz_sparse_vec_init(vec); + check_zero(vec); + + fmpz_sparse_vec_randtest(vec, state, nnz, len, bits); + + if (nnz == 0) check_zero(vec); + else + { + for (i = 0; i < nnz; ++i) + { + fmpz_sparse_entry_struct *e = &vec->entries[i]; + if (e->ind >= len) + { + flint_printf("FAIL: found index %wd >= %wd!\n", e->ind, len); + abort(); + } + if (fmpz_is_zero(e->val)) + { + flint_printf("FAIL: found zero value\n"); + abort(); + } + if (i>0 && e->ind <= e[-1].ind) + { + flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); + abort(); + } + } + } + + fmpz_sparse_vec_clear(vec); + check_zero(vec); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-max_bits.c b/fmpz_sparse_vec/test/t-max_bits.c new file mode 100644 index 0000000000..2db9284fc0 --- /dev/null +++ b/fmpz_sparse_vec/test/t-max_bits.c @@ -0,0 +1,67 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, mbits, max_bits, len, nnz, i; + fmpz_sparse_vec_t u; + FLINT_TEST_INIT(state); + + flint_printf("max bits...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + mbits = fmpz_sparse_vec_max_bits(u); + mbits = FLINT_ABS(mbits); + + max_bits = 0; + for (i = 0; i < nnz; ++i) + { + bits = fmpz_bits(u->entries[i].val); + if (bits > mbits) + { + flint_printf("FAIL: entry %wd has bitcnt %wd, max was %wd\n", i, bits, mbits); + fmpz_sparse_vec_print_pretty(u, 0, len); + abort(); + } + if (bits > max_bits) max_bits = bits; + } + if (mbits != max_bits) + { + flint_printf("FAIL: no entry has bitcnt %wd\n", mbits); + fmpz_sparse_vec_print_pretty(u, 0, len); + abort(); + } + fmpz_sparse_vec_clear(u); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-neg.c b/fmpz_sparse_vec/test/t-neg.c new file mode 100644 index 0000000000..7d303f0d99 --- /dev/null +++ b/fmpz_sparse_vec/test/t-neg.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_sparse_vec_t u, v, w, x; + FLINT_TEST_INIT(state); + + + flint_printf("neg...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 200); + nnz = n_randint(state, len+1); + + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + fmpz_sparse_vec_init(x); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + + fmpz_sparse_vec_sub(w, u, v); + fmpz_sparse_vec_neg(v, v); + fmpz_sparse_vec_add(x, u, v); + + if (!fmpz_sparse_vec_equal(w, x, 0)) + { + flint_printf("FAIL: u - v != u + (-v)\n"); + abort(); + } + + fmpz_sparse_vec_neg(w, u); + fmpz_sparse_vec_neg(u, u); + + if (!fmpz_sparse_vec_equal(w, w, 0)) + { + flint_printf("FAIL\n"); + abort(); + } + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + fmpz_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-nmod.c b/fmpz_sparse_vec/test/t-nmod.c new file mode 100644 index 0000000000..bc53819cd9 --- /dev/null +++ b/fmpz_sparse_vec/test/t-nmod.c @@ -0,0 +1,117 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz, i, j; + slong n, c; + nmod_t mod; + nmod_sparse_vec_t umod; + fmpz_sparse_vec_t u; + FLINT_TEST_INIT(state); + + + flint_printf("nmod...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 256); + while(bits < UWORD(2)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + do n = n_randlimb(state); + while (n < UWORD(2)); + nmod_init(&mod, n); + + nmod_sparse_vec_init(umod); + fmpz_sparse_vec_init(u); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_get_nmod_sparse_vec(umod, u, mod); + + for (i = j = 0; i < u->nnz; ++i) + { + c = fmpz_fdiv_ui(u->entries[i].val, n); + if (c == UWORD(0)) continue; + if (u->entries[i].ind != umod->entries[j].ind) + { + flint_printf("Fail: v %% c has extra/missing entry\n"); + abort(); + } + if (c != umod->entries[j].val) + { + flint_printf("Fail: v %% c has incorrect entry\n"); + abort(); + } + ++j; + } + if (j != umod->nnz) + { + flint_printf("Fail: v %% c has incorrect number of nonzeroes\n"); + abort(); + } + + nmod_sparse_vec_randtest(umod, state, nnz, len, mod); + fmpz_sparse_vec_set_nmod_sparse_vec_unsigned(u, umod); + + for (i = 0; i < u->nnz; ++i) + { + if (u->entries[i].ind != umod->entries[i].ind || + fmpz_cmp_ui(u->entries[i].val, umod->entries[i].val)) + { + flint_printf("FAIL: u = umod has bad entry\n"); + abort(); + } + } + if (u->nnz != umod->nnz) + { + flint_printf("Fail: u = umod has bad length\n"); + abort(); + } + + fmpz_sparse_vec_set_nmod_sparse_vec(u, umod, mod); + + for (i = 0; i < u->nnz; ++i) + { + if (u->entries[i].ind != umod->entries[i].ind || + (fmpz_sgn(u->entries[i].val) > 0 && fmpz_cmp_ui(u->entries[i].val, umod->entries[i].val)) || + (fmpz_sgn(u->entries[i].val) < 0 && fmpz_cmp_si(u->entries[i].val, umod->entries[i].val - n))) + { + flint_printf("FAIL: su = umod has bad entry\n"); + abort(); + } + } + if (u->nnz != umod->nnz) + { + flint_printf("Fail: su = umod has bad length\n"); + abort(); + } + + fmpz_sparse_vec_clear(u); + nmod_sparse_vec_clear(umod); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-scalar_divexact.c b/fmpz_sparse_vec/test/t-scalar_divexact.c new file mode 100644 index 0000000000..162538d1db --- /dev/null +++ b/fmpz_sparse_vec/test/t-scalar_divexact.c @@ -0,0 +1,93 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "fmpz_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_t c; + fmpz_sparse_vec_t u, v, w; + FLINT_TEST_INIT(state); + + flint_printf("divexact...."); + fflush(stdout); + + for (rep = 0; rep < 1; rep++) + { + do bits = n_randint(state, 100); + while(bits < UWORD(2)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + fmpz_init(c); + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + + do fmpz_randtest(c, state, bits); + while (fmpz_is_zero(c)); + + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); + flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); + + fmpz_sparse_vec_scalar_mul_fmpz(v, u, c); + flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); + fmpz_sparse_vec_scalar_divexact_fmpz(w, v, c); + + if (!fmpz_sparse_vec_equal(w, u, 0)) + { + flint_printf("FAIL: out of place c*v/c != v\n"); + flint_printf("rep = %wd, c = ", rep), fmpz_print(c), flint_printf("\n"); + fmpz_sparse_vec_print_pretty(u, 0, 0); + fmpz_sparse_vec_print_pretty(v, 0, 0); + fmpz_sparse_vec_print_pretty(w, 0, 0); + fmpz_clear(c); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + abort(); + } + fmpz_sparse_vec_scalar_divexact_fmpz(v, v, c); + + if (!fmpz_sparse_vec_equal(v, u, 0)) + { + flint_printf("FAIL: in place c*v/c != v\n"); + flint_printf("c = "), fmpz_print(c), flint_printf("\n"); + fmpz_sparse_vec_print_pretty(u, 0, 0); + fmpz_sparse_vec_print_pretty(v, 0, 0); + fmpz_clear(c); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + abort(); + } + fmpz_clear(c); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-scalar_mod.c b/fmpz_sparse_vec/test/t-scalar_mod.c new file mode 100644 index 0000000000..a579a9612a --- /dev/null +++ b/fmpz_sparse_vec/test/t-scalar_mod.c @@ -0,0 +1,160 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz, i, j; + fmpz_t mod, c; + fmpz_sparse_vec_t u, v; + FLINT_TEST_INIT(state); + + + flint_printf("mod...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 10); + while(bits < UWORD(3)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + fmpz_init(mod); + fmpz_init(c); + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + + fmpz_randbits(mod, state, bits-1); + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + + fmpz_sparse_vec_scalar_mod_fmpz(v, u, mod); + + for (i = j = 0; i < u->nnz; ++i) + { + fmpz_mod(c, u->entries[i].val, mod); + if (fmpz_is_zero(c)) continue; + if (u->entries[i].ind != v->entries[j].ind) + { + flint_printf("Fail: v %% c has extra/missing entry\n"); + fmpz_sparse_vec_print_pretty(u, 0, len); + fmpz_print(mod); flint_printf("\n"); + fmpz_sparse_vec_print_pretty(v, 0, len); + abort(); + } + if (fmpz_cmp(c, v->entries[j].val) != 0) + { + flint_printf("Fail: v %% c has incorrect entry\n"); + abort(); + } + ++j; + } + if (j != v->nnz) + { + flint_printf("Fail: v %% c has incorrect number of nonzeroes\n"); + abort(); + } + + fmpz_sparse_vec_scalar_mods_fmpz(v, u, mod); + for (i = j = 0; i < u->nnz; ++i) + { + fmpz_mods(c, u->entries[i].val, mod); + if (fmpz_is_zero(c)) continue; + if (u->entries[i].ind != v->entries[j].ind) + { + flint_printf("Fail: v %%s c has extra/missing entry\n"); + fmpz_sparse_vec_print_pretty(u, 0, len); + fmpz_print(mod); flint_printf("\n"); + fmpz_sparse_vec_print_pretty(v, 0, len); + abort(); + } + if (fmpz_cmp(c, v->entries[j].val) != 0) + { + flint_printf("Fail: v %%s c has incorrect entry\n"); + abort(); + } + ++j; + } + if (j != v->nnz) + { + flint_printf("Fail: v %%s c has incorrect number of nonzeroes\n"); + abort(); + } + + fmpz_sparse_vec_set(v, u, 0); + fmpz_sparse_vec_scalar_mod_fmpz(v, v, mod); + + for (i = j = 0; i < u->nnz; ++i) + { + fmpz_mod(c, u->entries[i].val, mod); + if (fmpz_is_zero(c)) continue; + if (u->entries[i].ind != v->entries[j].ind) + { + flint_printf("Fail: v %%= c has extra/missing entry\n"); + abort(); + } + if (fmpz_cmp(c, v->entries[j].val) != 0) + { + flint_printf("Fail: v %%= c has incorrect entry\n"); + abort(); + } + ++j; + } + if (j != v->nnz) + { + flint_printf("Fail: v %%= c has incorrect number of nonzeroes\n"); + abort(); + } + + fmpz_sparse_vec_set(v, u, 0); + fmpz_sparse_vec_scalar_mods_fmpz(v, v, mod); + + for (i = j = 0; i < u->nnz; ++i) + { + fmpz_mods(c, u->entries[i].val, mod); + if (fmpz_is_zero(c)) continue; + if (u->entries[i].ind != v->entries[j].ind) + { + flint_printf("Fail: v %%s= c has extra/missing entry\n"); + abort(); + } + if (fmpz_cmp(c, v->entries[j].val) != 0) + { + flint_printf("Fail: v %%s= c has incorrect entry\n"); + abort(); + } + ++j; + } + if (j != v->nnz) + { + flint_printf("Fail: v %%s= c has incorrect number of nonzeroes\n"); + abort(); + } + + fmpz_clear(mod); + fmpz_clear(c); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/test/t-scalar_mul.c b/fmpz_sparse_vec/test/t-scalar_mul.c new file mode 100644 index 0000000000..664bb6914d --- /dev/null +++ b/fmpz_sparse_vec/test/t-scalar_mul.c @@ -0,0 +1,114 @@ +/* + wopyright (w) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" +#include "fmpz_vec.h" +#include "ulong_extras.h" + +int +main(void) +{ + slong rep, bits, len, nnz; + fmpz_t c; + fmpz_sparse_vec_t u, v, w, x; + FLINT_TEST_INIT(state); + + flint_printf("scalar_mul and muladd...."); + fflush(stdout); + + for (rep = 0; rep < 1000; rep++) + { + do bits = n_randint(state, 200); + while(bits < UWORD(2)); + len = n_randint(state, 50); + nnz = n_randint(state, len+1); + + fmpz_init(c); + fmpz_sparse_vec_init(u); + fmpz_sparse_vec_init(v); + fmpz_sparse_vec_init(w); + fmpz_sparse_vec_init(x); + + fmpz_randtest(c, state, bits); + fmpz_sparse_vec_randtest(u, state, nnz, len, bits); + fmpz_sparse_vec_randtest(v, state, nnz, len, bits); + + fmpz_sparse_vec_scalar_addmul_fmpz(w, u, v, c); + fmpz_sparse_vec_scalar_mul_fmpz(x, v, c); + fmpz_sparse_vec_add(x, x, u); + + if (!fmpz_sparse_vec_equal(w, x, 0)) + { + flint_printf("FAIL: u + c*v != u + (c*v)\n"); + abort(); + } + + fmpz_sparse_vec_scalar_addmul_fmpz(w, u, v, c); + fmpz_sparse_vec_scalar_addmul_fmpz(u, u, v, c); + + if (!fmpz_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + fmpz_sparse_vec_scalar_addmul_fmpz(w, u, v, c); + fmpz_sparse_vec_scalar_addmul_fmpz(v, u, v, c); + + if (!fmpz_sparse_vec_equal(v, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + fmpz_sparse_vec_scalar_submul_fmpz(w, u, v, c); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, c); + + if (!fmpz_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + fmpz_sparse_vec_scalar_submul_fmpz(w, u, v, c); + fmpz_sparse_vec_scalar_submul_fmpz(v, u, v, c); + + if (!fmpz_sparse_vec_equal(v, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + fmpz_sparse_vec_scalar_mul_fmpz(x, v, c); + fmpz_sparse_vec_scalar_mul_fmpz(v, v, c); + + if (!fmpz_sparse_vec_equal(v, x, 0)) + { + flint_printf("FAIL: c*v != (c *= v)\n"); + abort(); + } + fmpz_clear(c); + fmpz_sparse_vec_clear(u); + fmpz_sparse_vec_clear(v); + fmpz_sparse_vec_clear(w); + fmpz_sparse_vec_clear(x); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +} diff --git a/fmpz_sparse_vec/window_init.c b/fmpz_sparse_vec/window_init.c new file mode 100644 index 0000000000..e85950d813 --- /dev/null +++ b/fmpz_sparse_vec/window_init.c @@ -0,0 +1,25 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +void fmpz_sparse_vec_window_init(fmpz_sparse_vec_t window, const fmpz_sparse_vec_t vec, slong i1, slong i2) +{ + slong start, end; + for (start = 0; start < vec->nnz && vec->entries[start].ind < i1; ++start); + for (end = vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + window->entries = vec->entries + start; + window->nnz = end - start; +} diff --git a/fq_nmod_sparse_vec/scalar_submul.c b/fq_nmod_sparse_vec/scalar_submul.c new file mode 100644 index 0000000000..1a2f5dc482 --- /dev/null +++ b/fq_nmod_sparse_vec/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_nmod_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_nmod +#define CAP_T FQ_NMOD +#include "fq_sparse_vec_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_mat_templates.h b/fq_sparse_mat_templates.h index e81e03fb21..5dab0a3961 100644 --- a/fq_sparse_mat_templates.h +++ b/fq_sparse_mat_templates.h @@ -263,14 +263,14 @@ void TEMPLATE(T, sparse_mat_sub) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_addmul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_addmul, T)) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); } FQ_SPARSE_MAT_TEMPLATES_INLINE -void TEMPLATE(T, sparse_mat_submul) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) +void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_submul, T)) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); diff --git a/fq_sparse_mat_templates/inv.c b/fq_sparse_mat_templates/inv.c index 82b3f38b4c..22249dc340 100644 --- a/fq_sparse_mat_templates/inv.c +++ b/fq_sparse_mat_templates/inv.c @@ -18,8 +18,6 @@ slong TEMPLATE(T, sparse_mat_inv) (TEMPLATE(T, sparse_mat_t) Mi, const TEMPLATE( { slong rk; TEMPLATE(T, sparse_mat_t) I, MI; - TEMPLATE(T, sparse_vec_struct) *row; - TEMPLATE(T, sparse_entry_struct) *le, *re; /* Create block matrix [M | I] */ TEMPLATE(T, sparse_mat_init) (I, M->r, M->r, ctx); diff --git a/fq_sparse_mat_templates/nullspace_block_lanczos.c b/fq_sparse_mat_templates/nullspace_block_lanczos.c index 67de9dfab4..f535e3efbd 100644 --- a/fq_sparse_mat_templates/nullspace_block_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_block_lanczos.c @@ -17,7 +17,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_block_wiedemann.c b/fq_sparse_mat_templates/nullspace_block_wiedemann.c index 0dfbbd25a2..f4e759918c 100644 --- a/fq_sparse_mat_templates/nullspace_block_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_block_wiedemann.c @@ -17,7 +17,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_lanczos.c b/fq_sparse_mat_templates/nullspace_lanczos.c index b39bec7d2f..6ebf652b25 100644 --- a/fq_sparse_mat_templates/nullspace_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_lanczos.c @@ -17,7 +17,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_lu.c b/fq_sparse_mat_templates/nullspace_lu.c index 5d68a9fd98..64ecd0df4a 100644 --- a/fq_sparse_mat_templates/nullspace_lu.c +++ b/fq_sparse_mat_templates/nullspace_lu.c @@ -16,7 +16,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_lu) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) { - int good = 1; slong rk, *P, *Q, *Qi, i, j; TEMPLATE(T, t) cc; TEMPLATE(T, sparse_mat_t) L, U; diff --git a/fq_sparse_mat_templates/nullspace_rref.c b/fq_sparse_mat_templates/nullspace_rref.c index e2b926ffc3..e2cacf60bd 100644 --- a/fq_sparse_mat_templates/nullspace_rref.c +++ b/fq_sparse_mat_templates/nullspace_rref.c @@ -20,7 +20,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_rref) (TEMPLATE(T, mat_t) X, const TEMPLA TEMPLATE(T, struct) *Xrow; TEMPLATE(T, sparse_mat_t) R; TEMPLATE(T, sparse_vec_struct) *Rrow; - TEMPLATE(T, sparse_entry_struct) *le, *e; TEMPLATE(T, sparse_mat_init) (R, M->r, M->c, ctx); TEMPLATE(T, sparse_mat_set) (R, M, ctx); rk = TEMPLATE(T, sparse_mat_rref) (R, ctx); diff --git a/fq_sparse_mat_templates/nullspace_wiedemann.c b/fq_sparse_mat_templates/nullspace_wiedemann.c index 7a1b07367e..9dd7254709 100644 --- a/fq_sparse_mat_templates/nullspace_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_wiedemann.c @@ -17,7 +17,6 @@ slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c index cb3dcbe990..89acbc60a6 100644 --- a/fq_sparse_mat_templates/rref.c +++ b/fq_sparse_mat_templates/rref.c @@ -16,13 +16,13 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) { - if (M->r == 0 || M->c == 0) return 0; slong *P; - slong i, j, r, c, pr, pc, rank, remr; + slong j, r, c, pr, pc, rank, remr; TEMPLATE(T, t) cinv, cc; TEMPLATE(T, sparse_mat_t) Mt; TEMPLATE(T, sparse_vec_struct) *pcol, *prow, *row, *col; + if (M->r == 0 || M->c == 0) return 0; P = flint_malloc(M->r*sizeof(*P)); TEMPLATE(T, init) (cinv, ctx); TEMPLATE(T, init) (cc, ctx); diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c index 7a2911882b..6b30543288 100644 --- a/fq_sparse_mat_templates/solve_block_lanczos.c +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -97,7 +97,7 @@ static void kill_columns(TEMPLATE(T, mat_t) M, int *good, const TEMPLATE(T, ctx_ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { int ret = 0; - slong i, j, prev_i, next_i, iter, cur_dim, total_dim = 0; + slong i, prev_i, next_i, iter, cur_dim, total_dim = 0; TEMPLATE(T, sparse_mat_t) Mt; /* Transpose of M, we work with A = MtM */ TEMPLATE(T, mat_struct) V[3]; /* Keep track of current vector and two previous ones */ TEMPLATE(T, mat_t) MV; /* Application of M to V */ @@ -125,8 +125,8 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, mat_init) (VSSt, M->c, block_size, ctx); /* Transpose for computing matrix dot products */ TEMPLATE(T, mat_init) (T, block_size, M->c, ctx); /* Transpose for computing matrix dot products */ TEMPLATE(T, mat_init) (VtAV, block_size, block_size, ctx); - TEMPLATE(T, mat_init) (AVtAVSSt_VtAV, block_size, block_size, ctx); // (AV)^T(AV) + VtAV - TEMPLATE(T, mat_init) (DEF, block_size, block_size, ctx); // Shared by D, E, and F + TEMPLATE(T, mat_init) (AVtAVSSt_VtAV, block_size, block_size, ctx); /* (AV)^T(AV) + VtAV */ + TEMPLATE(T, mat_init) (DEF, block_size, block_size, ctx); /* Shared by D, E, and F */ TEMPLATE(T, mat_init) (I, block_size, block_size, ctx); TEMPLATE(T, mat_init) (tmp, block_size, block_size, ctx); Mtb = _TEMPLATE(T, vec_init) (M->c, ctx); @@ -140,7 +140,7 @@ int TEMPLATE(T, sparse_mat_solve_block_lanczos) (TEMPLATE(T, struct) *x, const T TEMPLATE(T, mat_one) (I, ctx); TEMPLATE(T, sparse_mat_mul_vec) (Mtb, Mt, b, ctx); - // Initialize V[0] randomly + /* Initialize V[0] randomly */ for (i = 0; i < V[0].r*V[0].c; ++i) TEMPLATE(T, randtest) (&V[0].entries[i], state, ctx); diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c index 08113620c9..4f178c30c9 100644 --- a/fq_sparse_mat_templates/solve_block_wiedemann.c +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -17,7 +17,7 @@ /* Compute S_i=(M^j Y)_{0...b-1}^T for i = 0,...,ns-1 */ static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TEMPLATE(T, sparse_mat_t) M, TEMPLATE(T, mat_struct) Y[2], const TEMPLATE(T, ctx_t) ctx) { - slong iter, i, j, k, b = Y->c; + slong iter, i, b = Y->c; TEMPLATE(T, mat_struct) W[2]; for (i = 0; i < 2; ++i) TEMPLATE(T, mat_window_init) (&W[i], &Y[i], 0, 0, b, b, ctx); for (i = iter = 0; iter < ns; ++iter, i = 1-i) @@ -40,11 +40,9 @@ static void make_block_sequences(TEMPLATE(T, mat_struct) *S, slong ns, const TE static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLATE(T, ctx_t) ctx) { const slong b = M->r/2; - slong pr, pc, r, c, k, tmp; - slong num_pi; + slong pr, pc, r, tmp; slong *gamma; TEMPLATE(T, t) cinv, cc; - TEMPLATE(T, mat_t) tau; TEMPLATE(T, init) (cinv, ctx); TEMPLATE(T, init) (cc, ctx); @@ -116,8 +114,8 @@ static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) static int find_block_min_poly(TEMPLATE(T, mat_struct) *S, slong *d, slong n, slong delta, const TEMPLATE(T, ctx_t) ctx) { int ret; - slong t, sigma, beta, mu; - slong i, j, k, r, b = S->r; + slong t; + slong i, k, r, b = S->r; slong f_len; TEMPLATE(T, mat_struct) *F; TEMPLATE(T, mat_t) M, D, tau, tmp; @@ -195,7 +193,6 @@ static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, slong block_size, flint_rand_t state, const TEMPLATE(T, ctx_t) ctx) { int good = 0, ret; - slong i; TEMPLATE (T, struct) *x1; TEMPLATE(T, sparse_vec_t) z; TEMPLATE(T, sparse_mat_t) Mb; @@ -234,7 +231,6 @@ int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, slong l, ns, k; slong *d; TEMPLATE(T, struct) *b; - TEMPLATE(T, mat_t) Z; TEMPLATE(T, mat_struct) Y[3], *S; if (M->r != M->c) return 0; /* TODO */ diff --git a/fq_sparse_mat_templates/solve_lu.c b/fq_sparse_mat_templates/solve_lu.c index 9ba32954a2..372a9fd91c 100644 --- a/fq_sparse_mat_templates/solve_lu.c +++ b/fq_sparse_mat_templates/solve_lu.c @@ -18,7 +18,7 @@ int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx) { int good = 1; - slong rk, *P, *Q, i, j; + slong rk, *P, *Q, i; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *bp, *y, *xp; TEMPLATE(T, sparse_mat_t) L, U; diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c index 44d586bd06..a6d49cecdf 100644 --- a/fq_sparse_mat_templates/solve_wiedemann.c +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -14,7 +14,7 @@ #include #include "templates.h" -// Berlekamp - Massey algorithm +/* Berlekamp - Massey algorithm */ static slong find_min_poly(TEMPLATE(T, struct) *s, slong N, const TEMPLATE(T, ctx_t) ctx) { slong L = 0, m, n, i; diff --git a/fq_sparse_mat_templates/test/t-add.c b/fq_sparse_mat_templates/test/t-add.c index 9795b791a3..a4e773a3e1 100644 --- a/fq_sparse_mat_templates/test/t-add.c +++ b/fq_sparse_mat_templates/test/t-add.c @@ -29,7 +29,6 @@ main(void) for (rep = 0; rep < 1000; rep++) { - TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, ctx_randtest) (ctx, state); r = n_randint(state, 200); c = n_randint(state, 200); diff --git a/fq_sparse_mat_templates/test/t-concat_horizontal.c b/fq_sparse_mat_templates/test/t-concat_horizontal.c index 107b1ed22f..65edca0e73 100644 --- a/fq_sparse_mat_templates/test/t-concat_horizontal.c +++ b/fq_sparse_mat_templates/test/t-concat_horizontal.c @@ -18,7 +18,7 @@ int main(void) { - slong rep, r, c1, c2, i; + slong rep, r, c1, c2, nreps = 100; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C; TEMPLATE(T, sparse_mat_t) window1, window2; @@ -28,7 +28,7 @@ int main(void) fflush(stdout); - for (i = 0; i < 100; i++) + for (rep = 0; rep < nreps; rep++) { TEMPLATE(T, ctx_randtest) (ctx, state); r = n_randint(state, 20); diff --git a/fq_sparse_mat_templates/test/t-concat_vertical.c b/fq_sparse_mat_templates/test/t-concat_vertical.c index c01461c30d..71cbcee37e 100644 --- a/fq_sparse_mat_templates/test/t-concat_vertical.c +++ b/fq_sparse_mat_templates/test/t-concat_vertical.c @@ -19,7 +19,7 @@ int main(void) { - slong rep, r1, r2, c, i; + slong rep, r1, r2, c, nreps = 100; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C; TEMPLATE(T, sparse_mat_t) window1, window2; @@ -29,7 +29,7 @@ int main(void) flint_printf("concat_vertical...."); fflush(stdout); - for (i = 0; i < 100; i++) + for (rep = 0; rep < nreps; rep++) { TEMPLATE(T, ctx_randtest) (ctx, state); r1 = n_randint(state, 100); diff --git a/fq_sparse_mat_templates/test/t-dense.c b/fq_sparse_mat_templates/test/t-dense.c index a7c8b2bac0..b689d697d2 100644 --- a/fq_sparse_mat_templates/test/t-dense.c +++ b/fq_sparse_mat_templates/test/t-dense.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i, j, k, nnz; + slong rep, r, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B; TEMPLATE(T, mat_t) C, D; diff --git a/fq_sparse_mat_templates/test/t-inv.c b/fq_sparse_mat_templates/test/t-inv.c index f7e5cece7e..9f5ff66f72 100644 --- a/fq_sparse_mat_templates/test/t-inv.c +++ b/fq_sparse_mat_templates/test/t-inv.c @@ -21,23 +21,20 @@ int main(void) { - int ret; - slong rep, r, c, i, rk; - TEMPLATE(T, t) a; + slong rep, r, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, Ai; TEMPLATE(T, mat_t) dA, dAiA; - struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("inverting A...."); fflush(stdout); - for (rep = 0; rep < 100; rep++) + for (rep = 0; rep < 200; rep++) { if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); - do r = n_randint(state, 200), c = n_randint(state, 200); + do r = n_randint(state, 100), c = n_randint(state, 100); while (r==UWORD(0) || c==UWORD(0)); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); @@ -47,7 +44,7 @@ main(void) TEMPLATE(T, mat_init) (dAiA, r, c, ctx); TEMPLATE(T, sparse_mat_to_dense) (dA, A, ctx); - rk = TEMPLATE(T, sparse_mat_inv) (Ai, A, ctx); + TEMPLATE(T, sparse_mat_inv) (Ai, A, ctx); TEMPLATE(T, sparse_mat_mul_mat) (dAiA, Ai, dA, ctx); TEMPLATE(T, mat_rref) (dA, ctx); if (!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) { diff --git a/fq_sparse_mat_templates/test/t-lu.c b/fq_sparse_mat_templates/test/t-lu.c index 03c74242c9..a9b93f5afa 100644 --- a/fq_sparse_mat_templates/test/t-lu.c +++ b/fq_sparse_mat_templates/test/t-lu.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i, j, m, rk, *P, *Q; + slong rep, r, c, i, j, rk, *P, *Q; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, t) *val; TEMPLATE(T, sparse_mat_t) A, LU, L, U; @@ -30,16 +30,15 @@ main(void) flint_printf("decomposing PAQ=LU...."); fflush(stdout); - for (rep = 0; rep < 1000; rep++) + for (rep = 0; rep < 200; rep++) { TEMPLATE(T, ctx_randtest) (ctx, state); - if (rep % 50 == 0) {flint_printf("."); fflush(stdout);} - r = n_randint(state, 200); - c = n_randint(state, 200); + if (rep % 20 == 0) {flint_printf("."); fflush(stdout);} + r = n_randint(state, 100); + c = n_randint(state, 100); P = flint_malloc(r*sizeof(*P)); Q = flint_malloc(c*sizeof(*P)); - m = FLINT_MIN(r, c); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); TEMPLATE(T, sparse_mat_init) (LU, r, c, ctx); TEMPLATE(T, sparse_mat_init) (L, r, c, ctx); diff --git a/fq_sparse_mat_templates/test/t-mul.c b/fq_sparse_mat_templates/test/t-mul.c index e8623df88f..73145de7dd 100644 --- a/fq_sparse_mat_templates/test/t-mul.c +++ b/fq_sparse_mat_templates/test/t-mul.c @@ -20,8 +20,7 @@ int main(void) { - slong rep, r, c, i, k; - TEMPLATE(T, t) a; + slong rep, r, c, k; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A; TEMPLATE(T, struct) *x, *y, *y2; diff --git a/fq_sparse_mat_templates/test/t-neg.c b/fq_sparse_mat_templates/test/t-neg.c index 3026272623..f7b7562be7 100644 --- a/fq_sparse_mat_templates/test/t-neg.c +++ b/fq_sparse_mat_templates/test/t-neg.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C, D; FLINT_TEST_INIT(state); diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c index 688505da41..bfded6b73b 100644 --- a/fq_sparse_mat_templates/test/t-nullspace.c +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -15,23 +15,21 @@ #include #include -#include +/* #include */ #include "ulong_extras.h" int main(void) { - int iter, ret; - slong rep, nreps = 100, r, c, i; - TEMPLATE(T, t) a; + slong rep, nreps = 50, r, c, i; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A; TEMPLATE(T, mat_t) X, AX; slong rk[6]; slong discrep[6] = {0, 0, 0, 0}; - double elapsed[6] = {0, 0, 0, 0}; + /* double elapsed[6] = {0, 0, 0, 0}; */ char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - struct timeval start, end; + /* struct timeval start, end; */ FLINT_TEST_INIT(state); flint_printf("finding nullspace of A...."); @@ -41,12 +39,12 @@ main(void) { if (rep % 5==0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); - r = c = 100 + n_randint(state, 100); + r = c = 50 + n_randint(state, 50); TEMPLATE(T, sparse_mat_init) (A, r, c, ctx); TEMPLATE(T, sparse_mat_randtest) (A, state, c/20, c/10, ctx); for (i = 0; i < 6; ++i) { - gettimeofday(&start, NULL); + /* gettimeofday(&start, NULL); */ switch (i) { case 0: rk[0] = TEMPLATE(T, sparse_mat_nullspace_rref) (X, A, ctx); break; @@ -56,10 +54,9 @@ main(void) case 4: rk[4] = TEMPLATE(T, sparse_mat_nullspace_wiedemann) (X, A, state, 5, ctx); break; case 5: rk[5] = TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (X, A, 8, state, 2, ctx); break; } - //if (i == 0 && rk[0] == UWORD(0) ) { TEMPLATE(T, mat_clear) (X, ctx); break;} - //else ++rep; - gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + /*if (i == 0 && rk[0] == UWORD(0) ) { TEMPLATE(T, mat_clear) (X, ctx); break;} else ++rep;*/ + /* gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); */ if (rk[i]!=0) { TEMPLATE(T, mat_init) (AX, A->r, X->c, ctx); @@ -86,8 +83,8 @@ main(void) flint_printf("PASS\n"); for(i = 0; i < 6; ++i) { - flint_printf("Finding nullspace with %s took average time %lf\n", - names[i], elapsed[i]/nreps); + flint_printf("Finding nullspace with %s\n", names[i]); + /* flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps); */ if(discrep[i] > 0) flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", discrep[i], nreps); diff --git a/fq_sparse_mat_templates/test/t-rref.c b/fq_sparse_mat_templates/test/t-rref.c index 35c2d8a977..230972ae54 100644 --- a/fq_sparse_mat_templates/test/t-rref.c +++ b/fq_sparse_mat_templates/test/t-rref.c @@ -20,8 +20,7 @@ int main(void) { - slong rep, r, c, i; - TEMPLATE(T, t) n; + slong rep, r, c; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B; TEMPLATE(T, mat_t) dA; @@ -30,7 +29,7 @@ main(void) flint_printf("converting A to reduced row echelon form...."); fflush(stdout); - for (rep = 0; rep < 1000; rep++) + for (rep = 0; rep < 200; rep++) { if (rep % 20 == 0) {flint_printf("."); fflush(stdout);} TEMPLATE(T, ctx_randtest) (ctx, state); diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c index 5dbc491a7e..0c1b8a5513 100644 --- a/fq_sparse_mat_templates/test/t-scalar_mul.c +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, c; TEMPLATE(T, t) a, cc; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C, D; diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index 347e6c6b8e..408200f195 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -16,23 +16,22 @@ #include #include #include "ulong_extras.h" -#include +/* #include */ int main(void) { int iter, ret; slong rep, nreps = 100, r, c, i; - TEMPLATE(T, t) a; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, At; TEMPLATE(T, struct) *x, *x2, *b, *Atb, *Ax, *AtAx; slong niters[6] = {0, 0, 0, 0, 0, 0}; slong psol[6] = {0, 0, 0, 0, 0, 0}; slong nosol[6] = {0, 0, 0, 0, 0, 0}; - double elapsed[6] = {0, 0, 0, 0, 0}; + /* double elapsed[6] = {0, 0, 0, 0, 0}; */ char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - struct timeval start, end; + /* struct timeval start, end; */ FLINT_TEST_INIT(state); flint_printf("solving Ax=b...."); @@ -58,7 +57,7 @@ main(void) for (i = 0; i < 6; ++i) { iter = 0; - gettimeofday(&start, NULL); + /* gettimeofday(&start, NULL); */ switch (i) { case 0: ret = TEMPLATE(T, sparse_mat_solve_rref) (x2, A, b, ctx); break; @@ -68,8 +67,8 @@ main(void) case 4: ret = TEMPLATE(T, sparse_mat_solve_wiedemann) (x2, A, b, ctx); break; case 5: do ret = TEMPLATE(T, sparse_mat_solve_block_wiedemann) (x2, A, b, 8, state, ctx); while(ret == 0 && ++iter < 3); break; } - gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + /* gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); */ if (ret == 0) nosol[i] += 1; else { @@ -115,7 +114,8 @@ main(void) flint_printf("PASS\n"); for (i = 0; i < 6; ++i) { - flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + flint_printf("Solved with %s\n", names[i]); + /* flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps); */ if (nosol[i]) flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); if (psol[i]) diff --git a/fq_sparse_mat_templates/test/t-transpose.c b/fq_sparse_mat_templates/test/t-transpose.c index 4c3e49ec63..b24edf3ffb 100644 --- a/fq_sparse_mat_templates/test/t-transpose.c +++ b/fq_sparse_mat_templates/test/t-transpose.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, c, nreps = 1000; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C; FLINT_TEST_INIT(state); @@ -30,7 +30,7 @@ main(void) fflush(stdout); /* Rectangular transpose, same modulus */ - for (rep = 0; rep < 1000; rep++) + for (rep = 0; rep < nreps; rep++) { TEMPLATE(T, ctx_randtest) (ctx, state); r = n_randint(state, 20); diff --git a/fq_sparse_vec/scalar_submul.c b/fq_sparse_vec/scalar_submul.c new file mode 100644 index 0000000000..72924b1f11 --- /dev/null +++ b/fq_sparse_vec/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq +#define CAP_T FQ +#include "fq_sparse_vec_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/fq_sparse_vec_templates.h b/fq_sparse_vec_templates.h index 82b394132e..ce66c41317 100644 --- a/fq_sparse_vec_templates.h +++ b/fq_sparse_vec_templates.h @@ -115,7 +115,6 @@ FQ_SPARSE_VEC_TEMPLATES_INLINE void TEMPLATE(T, sparse_vec_one)(TEMPLATE(T, sparse_vec_t) vec, slong ind, const TEMPLATE(T, ctx_t) ctx) { - slong i; _TEMPLATE(T, sparse_vec_resize) (vec, 1, ctx); vec->entries[0].ind = ind; TEMPLATE(T, one) (vec->entries[0].val, ctx); @@ -139,8 +138,9 @@ FQ_SPARSE_VEC_TEMPLATES_INLINE void TEMPLATE(T, sparse_vec_set_entry)(TEMPLATE(T, sparse_vec_t) v, slong ind, const TEMPLATE(T, t) val, const TEMPLATE(T, ctx_t) ctx) { + TEMPLATE(T, t) *oval; if (TEMPLATE(T, is_zero) (val, ctx)) return; - TEMPLATE(T, t) *oval = TEMPLATE(T, sparse_vec_at) (v, ind, ctx); + oval = TEMPLATE(T, sparse_vec_at) (v, ind, ctx); if (oval == NULL) { _TEMPLATE(T, sparse_vec_resize) (v, v->nnz + 1, ctx); @@ -193,10 +193,11 @@ void TEMPLATE(T, sparse_vec_from_dense)(TEMPLATE(T, sparse_vec_t) dst, TEMPLATE( const TEMPLATE(T, ctx_t) ctx) { slong i, nnz = 0; + TEMPLATE(T, sparse_entry_struct) *e; for (i = 0; i < len; ++i) if (!TEMPLATE(T, is_zero) (&src[i], ctx)) ++nnz; _TEMPLATE(T, sparse_vec_resize) (dst, nnz, ctx); - TEMPLATE(T, sparse_entry_struct) *e = dst->entries; + e = dst->entries; for (i = 0; i < len; ++i) if (!TEMPLATE(T, is_zero) (&src[i], ctx)) e->ind = i, TEMPLATE(T, set) (e->val, &src[i], ctx), ++e; @@ -305,6 +306,8 @@ void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T))(TEMPLATE(T, sparse_vec_t) v for (i = 0; i < v->nnz; ++i) TEMPLATE(T, mul)(v->entries[i].val, v->entries[i].val, c, ctx); } +/* Utility macros used by binary vector operations */ +/* Compute total number of indices between two sparse vectors */ FQ_SPARSE_VEC_TEMPLATES_INLINE slong _TEMPLATE(T, sparse_vec_union_nnz)(const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, ctx_t) ctx) @@ -319,6 +322,42 @@ slong _TEMPLATE(T, sparse_vec_union_nnz)(const TEMPLATE(T, sparse_vec_t) u, cons nnz += u->nnz - i + v->nnz - j; return nnz; } + +/* Iterate through u and v in descending order, assigning sorted indices to w */ +/* Returns -1 if u and v are both exhausted, + 2 if we->ind = ue->ind == ve->ind + 1 if we->ind = ve->ind > ue->ind (or u exhausted), + 0 if we->ind = ue->ind > ve->ind (or v exhausted). */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +slong _TEMPLATE(T, sparse_vector_merge_descend) (TEMPLATE(T, sparse_entry_struct) **we, + TEMPLATE(T, sparse_entry_struct) **ue, + TEMPLATE(T, sparse_entry_struct) **ve, + const TEMPLATE(T, sparse_vec_t) u, + const TEMPLATE(T, sparse_vec_t) v) +{ + slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; + slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; + if(uind == -1 && vind == -1) return -1; + if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + --*ue, --*we; (*we)->ind = uind; return 0; +} + +/* Like resize, but removes entries from the front of the vector */ +FQ_SPARSE_VEC_TEMPLATES_INLINE +void _TEMPLATE(T, sparse_vector_shift_left) (TEMPLATE(T, sparse_vec_t) v, slong amt, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + if (amt == v->nnz) TEMPLATE(T, sparse_vec_clear) (v, ctx); + else if(amt > 0) + { + v->nnz -= amt; + for (i = 0; i < amt; ++i) TEMPLATE(T, clear) (v->entries[i].val, ctx); + memmove(v->entries, v->entries + amt, v->nnz*sizeof(*v->entries)); + v->entries = flint_realloc(v->entries, v->nnz*sizeof(*v->entries)); + } +} + FLINT_DLL void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, ctx_t) ctx); diff --git a/fq_sparse_vec_templates/add.c b/fq_sparse_vec_templates/add.c index d5dd9190a2..ad6d992b06 100644 --- a/fq_sparse_vec_templates/add.c +++ b/fq_sparse_vec_templates/add.c @@ -16,41 +16,25 @@ void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, ctx_t) ctx) { - slong i, nnz, unnz, vnnz; + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if (u->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, v, 0, ctx); - else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); - else - { - nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); - unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ - _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); - ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; - while (ue >= u->entries && ve >= v->entries) - { - we->ind = FLINT_MAX(ue->ind, ve->ind); - if (ue->ind == ve->ind) - { - TEMPLATE(T, add) (we->val, (ue--)->val, (ve--)->val, ctx); - if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; - } - else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - else if (ve->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ve--)->val, ctx); - } - while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, set) ((we--)->val, (ve--)->val, ctx); - nnz = w->nnz - (we + 1 - w->entries); - if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); - else if (nnz < w->nnz) + if (vnnz == 0) {TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); return;} + if (unnz == 0) {TEMPLATE(T, sparse_vec_set) (w, v, 0, ctx); return;} + wnnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, wnnz, ctx); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _TEMPLATE(T, sparse_vector_merge_descend) (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) { - for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); - memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); - w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); - w->nnz = nnz; + case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; + case 1: TEMPLATE(T, set)(we->val, ve->val, ctx); break; + default: TEMPLATE(T, add)(we->val, ue->val, ve->val, ctx); + if(TEMPLATE(T, is_zero) (we->val, ctx)) we++; } } - + _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); } #endif diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c index f19f8faa95..c75a7375d4 100644 --- a/fq_sparse_vec_templates/scalar_addmul.c +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -16,44 +16,37 @@ void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { - slong i, nnz, unnz, vnnz; - TEMPLATE(T, t) tmp; + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if (u->nnz == 0) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); - else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); - else + TEMPLATE(T, t) tmp; + + /* Check for simpler operations first */ + if (vnnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) {TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); return;} + if (TEMPLATE(T, is_one) (c, ctx)) {TEMPLATE(T, sparse_vec_add) (w, u, v, ctx); return;} + if (unnz == 0) {TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); return;} + TEMPLATE(T, init) (tmp, ctx); + TEMPLATE(T, neg) (tmp, c, ctx); + if(TEMPLATE(T, is_one) (tmp, ctx)) TEMPLATE(T, sparse_vec_sub) (w, u, v, ctx); + else /* Now just do standard addmul */ { - TEMPLATE(T, init) (tmp, ctx); - unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ - nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); - _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); - ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; - while (ue >= u->entries && ve >= v->entries) + wnnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, wnnz, ctx); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _TEMPLATE(T, sparse_vector_merge_descend) (&we, &ue, &ve, u, v)) >= 0) { - we->ind = FLINT_MAX(ue->ind, ve->ind); - if (ue->ind == ve->ind) + switch(k) { - TEMPLATE(T, mul) (tmp, (ve--)->val, c, ctx); - TEMPLATE(T, add) (we->val, tmp, (ue--)->val, ctx); - if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; + case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; + case 1: TEMPLATE(T, mul)(we->val, ve->val, c, ctx); break; + default: TEMPLATE(T, mul) (tmp, ve->val, c, ctx); + TEMPLATE(T, add) (we->val, ue->val, tmp, ctx); + if (TEMPLATE(T, is_zero) (we->val, ctx)) we++; } - else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - else if (ve->ind == we->ind) TEMPLATE(T, mul) ((we--)->val, (ve--)->val, c, ctx); - } - while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, mul) ((we--)->val, (ve--)->val, c, ctx); - - nnz = w->nnz - (we + 1 - w->entries); - if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); - else if (nnz < w->nnz) - { - for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); - memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); - w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); - w->nnz = nnz; } - TEMPLATE(T, clear) (tmp, ctx); + _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); } + + TEMPLATE(T, clear) (tmp, ctx); } #endif diff --git a/fq_sparse_vec_templates/scalar_submul.c b/fq_sparse_vec_templates/scalar_submul.c index 45d6d4927d..181cbff605 100644 --- a/fq_sparse_vec_templates/scalar_submul.c +++ b/fq_sparse_vec_templates/scalar_submul.c @@ -16,58 +16,37 @@ void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { - slong i, nnz, unnz, vnnz; - TEMPLATE(T, t) tmp; + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if (u->nnz == 0) - { - TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); - TEMPLATE(T, sparse_vec_neg) (w, w, ctx); - } - else if (v->nnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); + TEMPLATE(T, t) tmp; + + /* Check for simpler operations first */ + if (vnnz == 0 || TEMPLATE(T, is_zero) (c, ctx)) {TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); return;} + if (TEMPLATE(T, is_one) (c, ctx)) {TEMPLATE(T, sparse_vec_sub) (w, u, v, ctx); return;} + TEMPLATE(T, init) (tmp, ctx); + TEMPLATE(T, neg) (tmp, c, ctx); + if (unnz == 0) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, tmp, ctx); + else if (TEMPLATE(T, is_one) (tmp, ctx)) TEMPLATE(T, sparse_vec_add) (w, u, v, ctx); else { - TEMPLATE(T, init) (tmp, ctx); - unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ - nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); - _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); - ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; - while (ue >= u->entries && ve >= v->entries) + wnnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, wnnz, ctx); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _TEMPLATE(T, sparse_vector_merge_descend) (&we, &ue, &ve, u, v)) >= 0) { - we->ind = FLINT_MAX(ue->ind, ve->ind); - if (ue->ind == ve->ind) - { - TEMPLATE(T, mul) (tmp, (ve--)->val, c, ctx); - TEMPLATE(T, sub) (we->val, tmp, (ue--)->val, ctx); - if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; - } - else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - else if (ve->ind == we->ind) + switch(k) { - TEMPLATE(T, mul) (we->val, (ve--)->val, c, ctx); - TEMPLATE(T, neg) (we->val, we->val, c, ctx); we--; + case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; + case 1: TEMPLATE(T, mul)(we->val, ve->val, c, ctx); + TEMPLATE(T, neg)(we->val, we->val, ctx); break; + default: TEMPLATE(T, mul) (tmp, ve->val, c, ctx); + TEMPLATE(T, sub) (we->val, ue->val, tmp, ctx); + if (TEMPLATE(T, is_zero) (we->val, ctx)) we++; } } - while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - while (ve >= v->entries) - { - we->ind = ve->ind; - TEMPLATE(T, mul) (we->val, (ve--)->val, c, ctx); - TEMPLATE(T, neg) (we->val, we->val, c, ctx); - we--; - } - - nnz = w->nnz - (we + 1 - w->entries); - if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); - else if (nnz < w->nnz) - { - for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); - memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); - w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); - w->nnz = nnz; - } - TEMPLATE(T, clear) (tmp, ctx); + _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); } + TEMPLATE(T, clear) (tmp, ctx); } #endif diff --git a/fq_sparse_vec_templates/sub.c b/fq_sparse_vec_templates/sub.c index a0c1ade68b..21289fac98 100644 --- a/fq_sparse_vec_templates/sub.c +++ b/fq_sparse_vec_templates/sub.c @@ -16,40 +16,25 @@ void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, sparse_vec_t) u, const TEMPLATE(T, sparse_vec_t) v, const TEMPLATE(T, ctx_t) ctx) { - slong i, nnz, unnz, vnnz; + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; TEMPLATE(T, sparse_entry_struct) *ue, *ve, *we; - if (u->nnz == 0) TEMPLATE(T, sparse_vec_neg) (w, v, ctx); - else if (v->nnz == 0) TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); - else - { - unnz = u->nnz; vnnz = v->nnz; /* Store in case either equals w (gets resized) */ - nnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); - _TEMPLATE(T, sparse_vec_resize) (w, nnz, ctx); - ue = u->entries + unnz - 1, ve = v->entries + vnnz - 1, we = w->entries + w->nnz - 1; - while (ue >= u->entries && ve >= v->entries) - { - we->ind = FLINT_MAX(ue->ind, ve->ind); - if (ue->ind == ve->ind) - { - TEMPLATE(T, sub) (we->val, (ue--)->val, (ve--)->val, ctx); - if (!TEMPLATE(T, is_zero) (we->val, ctx)) we--; - } - else if (ue->ind == we->ind) TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - else if (ve->ind == we->ind) TEMPLATE(T, neg) ((we--)->val, (ve--)->val, ctx); - } - while (ue >= u->entries) we->ind = ue->ind, TEMPLATE(T, set) ((we--)->val, (ue--)->val, ctx); - while (ve >= v->entries) we->ind = ve->ind, TEMPLATE(T, neg) ((we--)->val, (ve--)->val, ctx); - nnz = w->nnz - (we + 1 - w->entries); - if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (w, ctx); - else if (nnz < w->nnz) + if (vnnz == 0) {TEMPLATE(T, sparse_vec_set) (w, u, 0, ctx); return;} + if (unnz == 0) {TEMPLATE(T, sparse_vec_neg) (w, v, ctx); return;} + wnnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); + _TEMPLATE(T, sparse_vec_resize) (w, wnnz, ctx); + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _TEMPLATE(T, sparse_vector_merge_descend) (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) { - for (i = 0; i < w->nnz - nnz; ++i) TEMPLATE(T, clear) (w->entries[i].val, ctx); - memmove(w->entries, we + 1, nnz*sizeof(*w->entries)); - w->entries = flint_realloc(w->entries, nnz*sizeof(*w->entries)); - w->nnz = nnz; + case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; + case 1: TEMPLATE(T, neg)(we->val, ve->val, ctx); break; + default: TEMPLATE(T, sub)(we->val, ue->val, ve->val, ctx); + if(TEMPLATE(T, is_zero) (we->val, ctx)) we++; } } + _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); } #endif diff --git a/fq_sparse_vec_templates/test/t-add.c b/fq_sparse_vec_templates/test/t-add.c index ecf9799ec7..067d6a35a1 100644 --- a/fq_sparse_vec_templates/test/t-add.c +++ b/fq_sparse_vec_templates/test/t-add.c @@ -65,6 +65,19 @@ main(void) flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); abort(); } + TEMPLATE(T, sparse_vec_add)(u, v, u, ctx); + if (!TEMPLATE(T, sparse_vec_equal)(u, w, 0, ctx)) + { + flint_printf("FAIL: (u += v) != u + v\n"); + abort(); + } + + TEMPLATE(T, sparse_vec_sub)(v, w, v, ctx); + if (!TEMPLATE(T, sparse_vec_equal)(v, x, 0, ctx)) + { + flint_printf("FAIL: (v = u+v - v) != u+v-v\n"); + abort(); + } TEMPLATE(T, sparse_vec_clear)(u, ctx); TEMPLATE(T, sparse_vec_clear)(v, ctx); TEMPLATE(T, sparse_vec_clear)(w, ctx); diff --git a/fq_sparse_vec_templates/test/t-construct.c b/fq_sparse_vec_templates/test/t-construct.c index d15adfebb2..f7f983b3c2 100644 --- a/fq_sparse_vec_templates/test/t-construct.c +++ b/fq_sparse_vec_templates/test/t-construct.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, len, nnz, i, j; + slong rep, len, nnz, i; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_vec_t) u, v; slong *inds; diff --git a/fq_sparse_vec_templates/test/t-scalar_mul.c b/fq_sparse_vec_templates/test/t-scalar_mul.c index fa507f9c94..d12d47d922 100644 --- a/fq_sparse_vec_templates/test/t-scalar_mul.c +++ b/fq_sparse_vec_templates/test/t-scalar_mul.c @@ -47,7 +47,17 @@ main(void) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (w, u, v, c, ctx); TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (x, v, c, ctx); - TEMPLATE(T, sparse_vec_add) (x, x, u, ctx); + TEMPLATE(T, sparse_vec_add) (x, u, x, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (w, x, 0, ctx)) + { + flint_printf("FAIL: u + c*v != u + (c*v)\n"); + abort(); + } + + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (x, v, c, ctx); + TEMPLATE(T, sparse_vec_sub) (x, u, x, ctx); if (!TEMPLATE(T, sparse_vec_equal) (w, x, 0, ctx)) { @@ -64,6 +74,33 @@ main(void) abort(); } + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T)) (v, u, v, c, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (v, w, 0, ctx)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T)) (u, u, v, c, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (u, w, 0, ctx)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T)) (w, u, v, c, ctx); + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T)) (v, u, v, c, ctx); + + if (!TEMPLATE(T, sparse_vec_equal) (v, w, 0, ctx)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (x, v, c, ctx); TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (v, v, c, ctx); diff --git a/fq_zech_sparse_vec/scalar_submul.c b/fq_zech_sparse_vec/scalar_submul.c new file mode 100644 index 0000000000..f5bc3d54f6 --- /dev/null +++ b/fq_zech_sparse_vec/scalar_submul.c @@ -0,0 +1,22 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fq_zech_sparse_vec.h" + +#ifdef T +#undef T +#endif + +#define T fq_zech +#define CAP_T FQ_ZECH +#include "fq_sparse_vec_templates/scalar_submul.c" +#undef CAP_T +#undef T diff --git a/hashmap.c b/hashmap.c index c4dde1c12f..103b0954c5 100644 --- a/hashmap.c +++ b/hashmap.c @@ -9,141 +9,92 @@ (at your option) any later version. See . */ +#include #include "flint.h" #include "hashmap.h" -void hashmap1_init(hashmap1_t h) +void hashmap_init(hashmap_t h, slong size) { - h->data = (hashmap1_elem_s *) flint_calloc(HASHMAP_START_SIZE, - sizeof(hashmap1_elem_s)); - h->alloc = HASHMAP_START_SIZE; - h->mask = HASHMAP_START_MASK; - h->num_used = 0; + memset(h, 0, sizeof(*h)); + h->size = (UWORD(1)) << MIN_HASHMAP_BITS; + while (h->size < size) h->size <<= UWORD(1); + + h->mask = 2*h->size - 1; + h->num = 0; + h->table = flint_calloc(2*h->size, sizeof(*h->table)); + h->keys = flint_malloc(h->size*sizeof(*h->keys)); + h->vals = flint_malloc(h->size*sizeof(*h->vals)); } -void hashmap1_init2(hashmap1_t h, slong size) +void hashmap_clear(hashmap_t h) { - slong bits = 10; - - if (2*size >= 0) - size *= 2; - - while ((WORD(1) << bits) < size) - bits++; - - h->alloc = (WORD(1) << bits); - h->mask = h->alloc - 1; - h->num_used = 0; - - h->data = (hashmap1_elem_s *) flint_calloc(h->alloc, - sizeof(hashmap1_elem_s)); + flint_free(h->table); + flint_free(h->keys); + flint_free(h->vals); + memset(h, 0, sizeof(*h)); } -void hashmap1_clear(hashmap1_t h) +static void _hashmap_rehash(hashmap_t h) { - flint_free(h->data); + slong i, num = h->num; + h->size <<= 1; + h->mask = 2*h->size - 1; + h->table = realloc(h->table, 2*h->size*sizeof(*h->table)); + h->keys = realloc(h->keys, h->size*sizeof(*h->keys)); + h->vals = realloc(h->vals, h->size*sizeof(*h->vals)); + memset(h->table, 0, 2*h->size*sizeof(*h->table)); + h->num = 0; + for (i = 0; i < num; ++i) + hashmap_put(h, h->keys[i], h->vals[i]); } -/* find location in data to store value with 1 word key */ -slong hashmap1_hash(ulong key, hashmap1_t h) +static slong _hashmap_pos(hashmap_t h, slong key, int skip_deleted) { - slong loc, i; - - if (h->num_used == h->alloc/2) - return -WORD(1); /* hashmap is full */ - - loc = (slong) hashmap1_hash_key(key, h); - - for (i = 0; i < h->alloc; i++) - { - if (h->data[loc].in_use == 0 || h->data[loc].key == key) - return loc; - - loc++; - if (loc == h->alloc) - loc = 0; - } - - return -WORD(1); /* map needs rehashing */ + slong ind, pos = key*UWORD(13282407956253574709) + UWORD(286824421); + for(; (ind = h->table[pos & h->mask]); pos++) + { + if (!skip_deleted && ind == -1) break; + if (ind != -1 && h->keys[ind - 1] == key) break; + } + return pos & h->mask; } -/* rehash a full hashmap to twice current size */ -void hashmap1_rehash(hashmap1_t h) +void * hashmap_get(hashmap_t h, slong key) { - slong i; - hashmap1_elem_s * tmp; - - tmp = h->data; - h->data = (hashmap1_elem_s *) flint_calloc(2*h->alloc, sizeof(hashmap1_elem_s)); - - h->alloc = 2*h->alloc; - h->mask = h->alloc - 1; - h->num_used = 0; - - for (i = 0; i < h->alloc/2; i++) - { - if (tmp[i].in_use == 1) - hashmap1_insert(tmp[i].key, tmp[i].value, h); - } - - flint_free(tmp); + slong pos = _hashmap_pos(h, key, 1), ind = h->table[pos]; + return (ind = h->table[pos]) ? h->vals[ind - 1] : NULL; } -/* insert key, value pair into hashmap */ -void hashmap1_insert(ulong key, void * value, hashmap1_t h) +void hashmap_put(hashmap_t h, slong key, void *val) { - slong loc; - - loc = hashmap1_hash(key, h); - if (loc == -WORD(1)) - { - hashmap1_rehash(h); - loc = hashmap1_hash(key, h); - - if (loc == -WORD(1)) - { - /* should never be reached */ - flint_printf("Rehashing unsuccessful\n"); - flint_abort(); - } - } - - h->data[loc].value = value; - h->data[loc].key = key; - h->data[loc].in_use = 1; - h->num_used += 1; + slong pos = _hashmap_pos(h, key, 1), ind = h->table[pos]; + if(ind > 0) h->vals[ind - 1] = val; + else if(h->num < h->size) + { + pos = _hashmap_pos(h, key, 0); + h->keys[h->num] = key; + h->vals[h->num] = val; + h->table[pos] = ++h->num; + } + else + { + _hashmap_rehash(h); + hashmap_put(h, key, val); + } } -/* - set *ptr to location of value corresponding to key in hashmap - return 1 if found, otherwise return 0 (in which case *ptr = NULL) -*/ -int hashmap1_find(void ** ptr, ulong key, hashmap1_t h) +void hashmap_rem(hashmap_t h, slong key) { - slong i, loc; - - loc = hashmap1_hash_key(key, h); - - for (i = 0; i < h->alloc; i++) - { - if (h->data[loc].in_use == 0) - { - (*ptr) = NULL; - return 0; - } - - if (h->data[loc].key == key) - { - (*ptr) = h->data[loc].value; - return 1; - } - - loc++; - if (loc == h->alloc) - loc = 0; - } - - (*ptr) = NULL; - - return 0; -} + slong pos = _hashmap_pos(h, key, 1), ind = h->table[pos]; + if(ind > 0) + { + h->table[pos] = -1; /* Mark as deleted, new entries can be put here */ + if (ind < h->num) + { + h->keys[ind - 1] = h->keys[h->num - 1]; + h->vals[ind - 1] = h->vals[h->num - 1]; + h->table[_hashmap_pos(h, h->keys[ind - 1], 1)] = ind; + } + h->num--; + } +} \ No newline at end of file diff --git a/hashmap.h b/hashmap.h index 7cda979172..cc131767f0 100644 --- a/hashmap.h +++ b/hashmap.h @@ -14,109 +14,33 @@ #include "flint.h" -#define HASHMAP_START_SIZE 1024 -#define HASHMAP_START_MASK (HASHMAP_START_SIZE - 1) +#define MIN_HASHMAP_BITS 5 -/****************************************************************************** - - Hashmap types with one word key - -******************************************************************************/ - -typedef struct hashmap1_elem_s -{ - ulong key; - void * value; - int in_use; -} hashmap1_elem_s; - -typedef struct hashmap1_s +typedef struct { - slong alloc; - slong num_used; + ulong size; ulong mask; - hashmap1_elem_s * data; -} hashmap1_s; - -typedef hashmap1_s hashmap1_t[1]; - -/****************************************************************************** - - Hash functions - -******************************************************************************/ - -/* from lookup3.c, by Bob Jenkins, May 2006, Public Domain. */ - -#define hash_rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) - -#define hash_mix(a,b,c) \ -{ \ - c ^= b; c -= hash_rot(b, 14); \ - a ^= c; a -= hash_rot(c, 11); \ - b ^= a; b -= hash_rot(a, 25); \ - c ^= b; c -= hash_rot(b, 16); \ - a ^= c; a -= hash_rot(c, 4); \ - b ^= a; b -= hash_rot(a, 14); \ - c ^= b; c -= hash_rot(b, 24); \ -} - -/* End of Public Domain code. */ - -#if FLINT64 - -static __inline__ -ulong hash_word(ulong val) -{ - int * ptr = (int * ) &val; - int a = ptr[0], b = ptr[1], c = 0; - - hash_mix(a, b, c); - - ptr[0] = b; - ptr[1] = c; - - return val; -} - -#else + ulong num; + ulong *table; + slong *keys; + void **vals; +} hashmap_struct; -static __inline__ -ulong hash_word(ulong a) -{ - int b = 0, c = 0; - - hash_mix(a, b, c); - - return c; -} - -#endif +typedef hashmap_struct hashmap_t[1]; -/****************************************************************************** - - Hashmap functions with one word key - -******************************************************************************/ - -FLINT_DLL void hashmap1_init(hashmap1_t h); - -FLINT_DLL void hashmap1_init2(hashmap1_t h, slong size); - -FLINT_DLL void hashmap1_clear(hashmap1_t h); - -static __inline__ -ulong hashmap1_hash_key(ulong key, hashmap1_t h) -{ - return hash_word(key) & h->mask; -} +/* Initialize hash table to accomodate size elements */ +void hashmap_init(hashmap_t h, slong size); -FLINT_DLL slong hashmap1_hash(ulong key, hashmap1_t h); +/* Clear hash table */ +void hashmap_clear(hashmap_t h); -FLINT_DLL void hashmap1_rehash(hashmap1_t h); +/* Get value associated with given key */ +void * hashmap_get(hashmap_t h, slong key); -FLINT_DLL void hashmap1_insert(ulong key, void * value, hashmap1_t h); +/* Assign value to a given key */ +void hashmap_put(hashmap_t h, slong key, void *val); -FLINT_DLL int hashmap1_find(void ** ptr, ulong key, hashmap1_t h); +/* Remove value with a given key */ +void hashmap_rem(hashmap_t h, slong key); #endif diff --git a/heap.c b/heap.c new file mode 100644 index 0000000000..d5417a1fba --- /dev/null +++ b/heap.c @@ -0,0 +1,104 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "flint.h" +#include "heap.h" + +static void _heap_up(heap_t h, slong pos) +{ + const slong idx = h->idx[pos]; + slong nidx, npos; + for (; pos > 0; pos = npos) + { + npos = (pos-1)/2; + nidx = h->idx[npos]; + if (h->val[idx] >= h->val[nidx]) break; + + h->idx[pos] = nidx; + h->pos[nidx] = pos; + } + h->idx[pos] = idx; + h->pos[idx] = pos; +} + +void _heap_down(heap_t h, slong pos) +{ + const slong idx = h->idx[pos]; + slong nidx, npos; + for (; (npos = 2*pos+1) < h->num; pos = npos) + { + if (npos+1 < h->num && h->val[h->idx[npos]] > h->val[h->idx[npos+1]]) ++npos; + nidx = h->idx[npos]; + if (h->val[idx] <= h->val[nidx]) break; + + h->idx[pos] = nidx; + h->pos[nidx] = pos; + } + h->idx[pos] = idx; + h->pos[idx] = pos; +} + +void heap_init(heap_t h, slong cap) +{ + h->cap = FLINT_MAX(cap, MIN_HEAP_CAP); + h->idx = flint_malloc(h->cap*sizeof(h->idx)); + h->pos = flint_malloc(h->cap*sizeof(h->pos)); + h->val = flint_malloc(h->cap*sizeof(h->val)); + h->num = h->max = 0; + h->cap = cap; +} + +void heap_clear(heap_t h) +{ + flint_free(h->idx); + flint_free(h->pos); + flint_free(h->val); + memset(h, 0, sizeof(*h)); +} + +slong heap_push(heap_t h, slong val) +{ + if(h->max == h->cap) + { + h->cap *= 2; + h->idx = flint_realloc(h->idx, h->cap*sizeof(h->idx)); + h->pos = flint_realloc(h->pos, h->cap*sizeof(h->pos)); + h->val = flint_realloc(h->val, h->cap*sizeof(h->val)); + } + h->idx[h->max] = h->max; + h->val[h->max] = val; + ++h->num; + _heap_up(h, h->max); + return h->max++; +} + +slong heap_pop(heap_t h, slong *val) +{ + slong idx = h->idx[0]; + if(val) *val = h->val[idx]; + h->pos[idx] = -1; + h->idx[0] = h->idx[--h->num]; + _heap_down(h, 0); + return idx; +} + +slong heap_adjust(heap_t h, slong idx, slong val) +{ + slong oval = h->val[idx], pos = h->pos[idx]; + h->val[idx] = val; + if (pos != -1) + { + if (oval < val) _heap_down(h, pos); + if (oval > val) _heap_up(h, pos); + } + return oval; +} diff --git a/heap.h b/heap.h new file mode 100644 index 0000000000..b98fb5e74d --- /dev/null +++ b/heap.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2020 Kartik Venkatram + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#ifndef HEAP_H +#define HEAP_H + +#include "flint.h" + +#define MIN_HEAP_CAP 32 + +typedef struct +{ + slong *idx; /* Heap of indices */ + slong *pos; /* Inverse of idx (map from index to heap position) */ + slong *val; /* Map from index to values */ + slong num; /* Number of elements in heap */ + slong max; /* Largest index in heap */ + slong cap; /* Capacity of heap */ +} heap_struct; + +typedef heap_struct heap_t[1]; + +/* Initialize heap with initial capacity cap */ +void heap_init(heap_t h, slong cap); + +/* Free heap contents */ +void heap_clear(heap_t h); + +/* Push new score onto heap, returning assigned index */ +/* Note: if want to re-insert a current element with */ +/* new score, use heap_adjust instead */ +slong heap_push(heap_t h, slong val); + +/* Pop element with minimal score from heap */ +slong heap_pop(heap_t h, slong *val); + +/* Modify score of existing element in heap */ +slong heap_adjust(heap_t h, slong idx, slong val); + +#endif \ No newline at end of file diff --git a/mpoly/compose_mat.c b/mpoly/compose_mat.c index a90b9b1c1f..fa335700f9 100644 --- a/mpoly/compose_mat.c +++ b/mpoly/compose_mat.c @@ -11,17 +11,6 @@ #include "mpoly.h" -/* unfortunate function missing from fmpz_mat */ -void fmpz_mat_mul_vec(fmpz * v, const fmpz_mat_t M, fmpz * u) -{ - slong i; - slong r = fmpz_mat_nrows(M); - slong c = fmpz_mat_ncols(M); - - for (i = 0; i < r; i++) - _fmpz_vec_dot(v + i, M->rows[i], u, c); -} - /* Fill the compose matrix for the T_mpoly_compose_T_mpoly_gen functions */ void mpoly_compose_mat_gen(fmpz_mat_t M, const slong * c, const mpoly_ctx_t mctxB, const mpoly_ctx_t mctxAC) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index b29af827a8..bd46d76962 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -279,28 +279,31 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_add(&O->rows[i], &M->rows[i], &N->rows[i], O->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, nmod_neg(c, O->mod)); + slong i; + for (i = 0; i < O->r; ++i) nmod_sparse_vec_sub(&O->rows[i], &M->rows[i], &N->rows[i], O->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) +void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, UWORD(1)); + slong i; + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) +void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, O->mod.n-UWORD(1)); + slong i; + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } /* Matrix-vector and matrix-matrix multipliciation */ @@ -335,6 +338,13 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_strong_echelon_form(nmod_sparse_mat_t M) +{ + /* TODO */ + return 0; +} + /* Solve Ax = b */ FLINT_DLL int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state); @@ -386,6 +396,10 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); +/* Determinant */ +FLINT_DLL +mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); + /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); diff --git a/nmod_sparse_mat/det.c b/nmod_sparse_mat/det.c new file mode 100644 index 0000000000..8021e371bf --- /dev/null +++ b/nmod_sparse_mat/det.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "ulong_extras.h" +#include "nmod_sparse_mat.h" +#include "perm.h" + +mp_limb_t +nmod_sparse_mat_det(const nmod_sparse_mat_t M) +{ + slong rank, i; + slong *P, *Q; + mp_limb_t det; + nmod_sparse_mat_t L, U; + if (M->r != M->c) + { + flint_printf("Exception (nmod_mat_det). Non-square matrix.\n"); + flint_abort(); + } + + if (M->r == 0) return UWORD(1); + if (nmod_sparse_mat_is_zero(M)) return UWORD(0); + if (M->r == 1) return M->rows[0].entries[0].val; + + + P = flint_malloc(M->r*sizeof(*P)); + Q = flint_malloc(M->c*sizeof(*P)); + nmod_sparse_mat_init(L, M->r, M->c, M->mod); + nmod_sparse_mat_init(U, M->r, M->c, M->mod); + rank = nmod_sparse_mat_lu(P, Q, L, U, M); + + det = UWORD(0); + + if (rank == M->r) + { + det = UWORD(1); + for (i = 0; i < M->r; i++) + det = n_mulmod2_preinv(det, U->rows[i].entries[0].val, M->mod.n, M->mod.ninv); + if ((_perm_parity(P, M->r) == 1) ^ (_perm_parity(Q, M->c) == 1)) + det = nmod_neg(det, M->mod); + } + + flint_free(P); + flint_free(Q); + nmod_sparse_mat_clear(L); + nmod_sparse_mat_clear(U); + + return det; +} diff --git a/nmod_sparse_mat/howell_form.c b/nmod_sparse_mat/howell_form.c new file mode 100644 index 0000000000..2bafcb8dc9 --- /dev/null +++ b/nmod_sparse_mat/howell_form.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +slong +nmod_sparse_mat_howell_form(nmod_sparse_mat_t M) +{ +slong i, *P, rank = 0, remr = M->r; + + if (nmod_sparse_mat_is_zero(M)) return 0; + + nmod_sparse_mat_strong_echelon_form(M); + P = flint_malloc(M->r*sizeof(*P)); + for (i = 0; i < M->r; ++i) + { + if (M->rows[i].nnz > 0) P[i] = rank++; + else P[i] = --remr; + } + /* Apply row permutation */ + nmod_sparse_mat_permute_rows (M, P); + flint_free(P); + return rank; +} + diff --git a/nmod_sparse_mat/inv.c b/nmod_sparse_mat/inv.c index d767b47e64..faf4438621 100644 --- a/nmod_sparse_mat/inv.c +++ b/nmod_sparse_mat/inv.c @@ -19,8 +19,6 @@ slong nmod_sparse_mat_inv(nmod_sparse_mat_t Mi, const nmod_sparse_mat_t M) { slong rk; nmod_sparse_mat_t I, MI; - nmod_sparse_vec_struct *row; - nmod_sparse_entry_struct *le, *re; /* Create block matrix [M | I] */ nmod_sparse_mat_init(I, M->r, M->r, M->mod); diff --git a/nmod_sparse_mat/nullspace_block_lanczos.c b/nmod_sparse_mat/nullspace_block_lanczos.c index 35f32db75d..588429530e 100644 --- a/nmod_sparse_mat/nullspace_block_lanczos.c +++ b/nmod_sparse_mat/nullspace_block_lanczos.c @@ -19,7 +19,6 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters) { /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; x = _nmod_vec_init(M->c); diff --git a/nmod_sparse_mat/nullspace_block_wiedemann.c b/nmod_sparse_mat/nullspace_block_wiedemann.c index 78ac95a105..bea2ac88d9 100644 --- a/nmod_sparse_mat/nullspace_block_wiedemann.c +++ b/nmod_sparse_mat/nullspace_block_wiedemann.c @@ -19,7 +19,6 @@ slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters) { /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; x = _nmod_vec_init(M->c); diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index 60497ecb57..f35cc78e6f 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -19,7 +19,6 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; x = _nmod_vec_init(M->c); diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index 154198e690..f8b0ef9447 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -18,7 +18,6 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) { - int good = 1; slong rk, *P, *Q, *Qi, i, j; nmod_sparse_mat_t L, U; nmod_sparse_entry_struct *e; diff --git a/nmod_sparse_mat/nullspace_rref.c b/nmod_sparse_mat/nullspace_rref.c index c3d867e83f..68595e2074 100644 --- a/nmod_sparse_mat/nullspace_rref.c +++ b/nmod_sparse_mat/nullspace_rref.c @@ -22,7 +22,6 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M) nmod_sparse_mat_t R; nmod_sparse_vec_struct *Rrow; mp_limb_t *Xrow; - nmod_sparse_entry_struct *le, *e; nmod_sparse_mat_init(R, M->r, M->c, M->mod); nmod_sparse_mat_set(R, M); rk = nmod_sparse_mat_rref(R); diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c index 84e9943d00..895d8e939b 100644 --- a/nmod_sparse_mat/nullspace_wiedemann.c +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -19,7 +19,6 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters) { /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ - int ret; slong i, j, iter, nxs, *xps; mp_ptr x, *xs; x = _nmod_vec_init(M->c); diff --git a/nmod_sparse_mat/print_pretty.c b/nmod_sparse_mat/print_pretty.c index 70cbb98ad6..00ba167283 100644 --- a/nmod_sparse_mat/print_pretty.c +++ b/nmod_sparse_mat/print_pretty.c @@ -19,7 +19,7 @@ void nmod_sparse_mat_print_pretty(const nmod_sparse_mat_t M) { - slong i;; + slong i; char row_fmt[FLINT_BITS + 5]; flint_sprintf(row_fmt, "%%%dwd: ", n_sizeinbase(M->r, 10)); diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index 155f25cdde..fa1326c52a 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -18,13 +18,13 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) { - if (M->r == 0 || M->c == 0) return 0; slong *P; - slong i, j, r, c, pr, pc, rank, remr; + slong j, r, c, pr, pc, rank, remr; nmod_sparse_mat_t Mt; nmod_sparse_vec_struct *pcol, *prow, *row, *col; mp_limb_t cinv, cc; + if (M->r == 0 || M->c == 0) return 0; nmod_sparse_mat_init(Mt, M->c, M->r, M->mod); nmod_sparse_mat_transpose(Mt, M); diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index bbc9c5af06..68aae02594 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -97,7 +97,7 @@ static void kill_columns(nmod_mat_t M, int *good) int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) { int ret = 0; - slong i, j, prev_i, next_i, iter, cur_dim, total_dim = 0; + slong i, prev_i, next_i, iter, cur_dim, total_dim = 0; nmod_sparse_mat_t Mt; /* Transpose of M, we work with A = MtM */ nmod_mat_struct V[3]; /* Keep track of current vector and two previous ones */ nmod_mat_t MV; /* Application of M to V */ @@ -127,8 +127,8 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ nmod_mat_init(VSSt, M->c, block_size, M->mod.n); nmod_mat_init(T, block_size, M->c, M->mod.n); /* Transpose for computing matrix dot products */ nmod_mat_init(VtAV, block_size, block_size, M->mod.n); - nmod_mat_init(AVtAVSSt_VtAV, block_size, block_size, M->mod.n); // (AV)^T(AV) + VtAV - nmod_mat_init(DEF, block_size, block_size, M->mod.n); // Shared by D, E, and F + nmod_mat_init(AVtAVSSt_VtAV, block_size, block_size, M->mod.n); /* (AV)^T(AV) + VtAV */ + nmod_mat_init(DEF, block_size, block_size, M->mod.n); /* Shared by D, E, and F */ nmod_mat_init(I, block_size, block_size, M->mod.n); nmod_mat_init(tmp, block_size, block_size, M->mod.n); Mtb = _nmod_vec_init(M->c); @@ -142,7 +142,7 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ nmod_mat_one(I); nmod_sparse_mat_mul_vec(Mtb, Mt, b); - // Initialize V[0] randomly + /* Initialize V[0] randomly */ for (i = 0; i < V[0].r*V[0].c; ++i) V[0].entries[i] = n_randint(state, V[0].mod.n); diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index d26e25b8e6..7d0ec45756 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -18,7 +18,7 @@ /* Compute S_i=(M^j Y)_{0...b-1}^T for i = 0,...,ns-1 */ static void make_block_sequences(nmod_mat_struct *S, slong ns, const nmod_sparse_mat_t M, nmod_mat_struct Y[2]) { - slong iter, i, j, k, b = Y->c; + slong iter, i, b = Y->c; nmod_mat_struct W[2]; for (i = 0; i < 2; ++i) nmod_mat_window_init(&W[i], &Y[i], 0, 0, b, b); for (i = iter = 0; iter < ns; ++iter, i = 1-i) @@ -41,11 +41,9 @@ static void make_block_sequences(nmod_mat_struct *S, slong ns, const nmod_sparse static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) { const slong b = M->r/2; - slong pr, pc, r, c, k, tmp; - slong num_pi; + slong pr, pc, r, tmp; slong *gamma; - mp_limb_t cinv, cc; - nmod_mat_t tau; + mp_limb_t cinv; /* Keep track of viable rows */ gamma = flint_malloc(b*sizeof(*gamma)); @@ -109,8 +107,8 @@ static int coppersmith_stopping_criterion(slong *d, slong delta, slong b) static int find_block_min_poly(nmod_mat_struct *S, slong *d, slong n, slong delta) { int ret; - slong t, sigma, beta, mu; - slong i, j, k, r, b = S->r; + slong t; + slong i, k, r, b = S->r; slong f_len; nmod_mat_struct *F; nmod_mat_t M, D, tau, tmp; @@ -188,7 +186,6 @@ static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, c int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) { int good = 0, ret; - slong i; mp_ptr x1; nmod_sparse_vec_t z; nmod_sparse_mat_t Mb; @@ -225,7 +222,6 @@ int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t slong l, ns, k; slong *d; mp_ptr b; - nmod_mat_t Z; nmod_mat_struct Y[3], *S; if (M->r != M->c) return 0; /* TODO */ diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 9f56dfdefa..0e1e908398 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -24,7 +24,7 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr /* We assume that M is not symmetric, and work with A = M^t M */ nmod_sparse_mat_t Mt; mp_ptr v[2], Mv, Av, Mtb; - mp_limb_t vtAv[2], AvtAv, vMtb, alpha, beta; + mp_limb_t vtAv[2], AvtAv, vMtb; _nmod_vec_zero(x, M->c); if (_nmod_vec_is_zero(b, M->c)) return 1; @@ -43,8 +43,8 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr nmod_sparse_mat_mul_vec(Mtb, Mt, b); /* Make 0th vector random (and -1st vector trivial) */ - //_nmod_vec_set(v[0], Mtb, M->c); - //for (j = 0; j < M->c; ++j) v[0][j] = n_randint(state, M->mod.n); + /*_nmod_vec_set(v[0], Mtb, M->c); + for (j = 0; j < M->c; ++j) v[0][j] = n_randint(state, M->mod.n); */ _nmod_vec_randtest(v[0], state, M->c, M->mod); _nmod_vec_zero(v[1], M->c); vtAv[1] = 1; for (j = 0; ; j = 1-j) diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 64bae7ddb4..438e86acf8 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -20,7 +20,7 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) { int good = 1; - slong rk, *P, *Q, i, j; + slong rk, *P, *Q, i; nmod_sparse_mat_t L, U; mp_ptr bp, y, xp; if (_nmod_vec_is_zero(b, M->c)) diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index 86763e4406..fdd9bd2c57 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -15,7 +15,7 @@ #include "flint.h" #include "nmod_sparse_mat.h" -// Berlekamp - Massey algorithm +/* Berlekamp - Massey algorithm */ static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) { slong L = 0, m, n, i; diff --git a/nmod_sparse_mat/strong_echelon_form.c b/nmod_sparse_mat/strong_echelon_form.c new file mode 100644 index 0000000000..22965ff882 --- /dev/null +++ b/nmod_sparse_mat/strong_echelon_form.c @@ -0,0 +1,185 @@ +/* + Copyright (C) 2015 Tommy Hofmann + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "flint.h" +#include "nmod_sparse_vec.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" +#if 0 +static __inline__ int +_nmod_mat_pivot(nmod_mat_t M, slong start_row, slong pc) +{ + slong j; + mp_ptr u; + + if (nmod_mat_entry(M, start_row, pc) != 0) + return 1; + + for (j = start_row + 1; j < M->r; j++) + { + if (M->rows[j][pc] != 0) + { + u = M->rows[j]; + M->rows[j] = M->rows[start_row]; + M->rows[start_row] = u; + + return -1; + } + } + return 0; +} + +static void +_n_ppio(mp_ptr ppi, mp_ptr ppo, mp_limb_t a, mp_limb_t b) +{ + mp_limb_t c, M->r, g; + + c = n_gcd(a, b); + M->r = a/c; + g = n_gcd(c, M->r); + while( g != 1 ) + { + c = c * g; + M->r = M->r/g; + g = n_gcd(c, M->r); + } + *ppi = c; + *ppo = M->r; +} + +static mp_limb_t +_n_stab(mp_limb_t a, mp_limb_t b, nmod_t N) +{ + mp_limb_t g, a, b; + g = n_gcd(a, b); + b = n_gcd(g, N.M->r); + _n_ppio(&a, &b, N.M->r/b, a/b); + return b; +} + +static mp_limb_t +_n_unit(mp_limb_t a, nmod_t N) +{ + mp_limb_t g, a, l, d; + + g = n_gcdinv(&a, a, N.M->r); + + if (g == 1) + { + return a; + } + else + { + l = N.M->r/g; + d = _n_stab(a, l, N); + return nmod_add(a, nmod_mul(d, l, N), N); + } +} + +/* test wether q*a = b M->mod N has a solution */ +static int +_n_is_divisible(mp_ptr q, mp_limb_t b, mp_limb_t a, nmod_t N) +{ + mp_limb_t e, g; + g = n_gcdinv(&e, a, N.M->r); + + if (( b % g ) == 0) + { + *q = nmod_mul(e, b/g, N); + return 1; + } + + return 0; +} + +void +nmod_sparse_mat_strong_echelon_form(nmod_sparse_mat_t M) +{ + mp_limb_t a, b, u, v, q, t1, t2, g; + slong pr, pc, r, k, l; + mp_limb_t **r; + mp_ptr extra_row; + + if (nmod_mat_is_empty(M)) + return; + + + extra_row = _nmod_vec_init(M->c); + + pr = pc = 0; + + while (pr < M->r && pc < M->c) + { + if (_nmod_mat_pivot(M, pr, pc) == 0) {pc++; continue;} + for (r = pr + 1; r < M->r; r++) + { + if (M->rows[r][pc] == 0) continue; + + if (M->rows[pr][pc] >= M->rows[r][pc]) + g = n_xgcd(&a, &b, M->rows[pr][pc], M->rows[r][pc]); + else + g = n_xgcd(&b, &a, M->rows[r][pc], M->rows[pr][pc]); + + if (b != UWORD(0)) + _nmod_sparse_mat_rowop(M, pr, a, r, nmod_neg(b, M->mod)); + _nmod_sparse_mat_rowop(M, r, UWORD(1), pr, M->rows[r][pc]/g); + nmod_sparse_mat_scalar_div_nmod(M->rows[r], M->rows[r], a); + } + pr++; + pc++; + } + + for (pc = 0; pc < M->c; pc++) + { + if (M->rows[pc][pc] != 0) + { + u = _n_unit(M->rows[pc][pc], M->mod); + _nmod_sparse_vec_scalar_mul_nmod(M->rows[pc], M->rows[pc], u, M->mod); + + for (pr = 0; pr < pc ; pr++) + { + + q = M->rows[pr][pc]/M->rows[pc][pc]; + + for (l = pr; l< M->c; l++) + { + M->rows[pr][l] = nmod_sub(M->rows[pr][l], nmod_mul(q, M->rows[pc][l], M->mod), M->mod); + } + } + + g = n_gcd(M->mod.n, M->rows[pc][pc]); + if (g == 1) continue; + _nmod_vec_scalar_mul_nmod(extra_row, M->rows[pc], M->c, M->mod.n/g, M->mod); + } + else + { + _nmod_vec_set(extra_row, M->rows[pc], M->c); + } + + for (pr = pc + 1; pr < M->c; pr++) + { + if (extra_row[pr] == 0) continue; + + if (M->rows[pr][pr] >= extra_row[pr]) + g = n_xgcd(&a, &b, M->rows[pr][pr], extra_row[pr]); + else + g = n_xgcd(&b, &a, extra_row[pr], M->rows[pr][pr]); + + if (b != UWORD(0)) + _nmod_sparse_mat_rowop(M, pr, a, r, nmod_neg(b, M->mod)); + _nmod_sparse_mat_rowop(M, r, UWORD(1), pr, extra_row[pr]/g); + nmod_sparse_mat_scalar_div_nmod(extra_row, extra_row, a); + } + } + _nmod_vec_clear(extra_row); +} +#endif \ No newline at end of file diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index dcb8b7b081..a2b26bd4af 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -18,7 +18,7 @@ int main(void) { - slong rep, r, c1, c2, i; + slong rep, r, c1, c2, nreps = 100; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B, C; @@ -29,7 +29,7 @@ int main(void) fflush(stdout); - for (i = 0; i < 100; i++) + for (rep = 0; rep < nreps; rep++) { r = n_randint(state, 200); c1 = n_randint(state, 200); diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index 12a992efa8..5f61d34c6e 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -19,7 +19,7 @@ int main(void) { - slong rep, r1, r2, c, i; + slong rep, r1, r2, c, nreps = 100; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B, C; @@ -30,7 +30,7 @@ int main(void) flint_printf("concat_vertical...."); fflush(stdout); - for (i = 0; i < 100; i++) + for (rep = 0; rep < nreps; rep++) { r1 = n_randint(state, 100); r2 = n_randint(state, 100); diff --git a/nmod_sparse_mat/test/t-dense.c b/nmod_sparse_mat/test/t-dense.c index 4a0ab379f8..ba167bc754 100644 --- a/nmod_sparse_mat/test/t-dense.c +++ b/nmod_sparse_mat/test/t-dense.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i, j, k, nnz; + slong rep, r, c; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B; diff --git a/nmod_sparse_mat/test/t-inv.c b/nmod_sparse_mat/test/t-inv.c index 99eccb4a07..1131f50b78 100644 --- a/nmod_sparse_mat/test/t-inv.c +++ b/nmod_sparse_mat/test/t-inv.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "flint.h" #include "nmod_sparse_mat.h" #include "ulong_extras.h" @@ -21,13 +20,11 @@ int main(void) { - int ret, badct = 0; - slong rep, r, c, i, rk; - mp_limb_t n, a; + slong rep, r, c; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, Ai; nmod_mat_t dA, dAiA; - struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("inverting A...."); @@ -49,7 +46,7 @@ main(void) nmod_mat_init(dAiA, r, c, n); nmod_sparse_mat_to_dense(dA, A); - rk = nmod_sparse_mat_inv(Ai, A); + nmod_sparse_mat_inv(Ai, A); nmod_sparse_mat_mul_mat(dAiA, Ai, dA); nmod_mat_rref(dA); if(!nmod_mat_equal(dAiA, dA)) { diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c index 3184bb46af..842ea29a68 100644 --- a/nmod_sparse_mat/test/t-lu.c +++ b/nmod_sparse_mat/test/t-lu.c @@ -21,8 +21,8 @@ int main(void) { - slong rep, r, c, i, j, m, rk; - mp_limb_t n, *P, *Q; + slong rep, r, c, i, j, rk, *P, *Q; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, LU, L, U; nmod_mat_t dL, dU, dLU; @@ -42,7 +42,6 @@ main(void) nmod_init(&mod, n); P = flint_malloc(r*sizeof(*P)); Q = flint_malloc(c*sizeof(*P)); - m = FLINT_MIN(r, c); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(LU, r, c, mod); nmod_sparse_mat_init(L, r, c, mod); diff --git a/nmod_sparse_mat/test/t-mul.c b/nmod_sparse_mat/test/t-mul.c index df34d1f56b..550cd18dd3 100644 --- a/nmod_sparse_mat/test/t-mul.c +++ b/nmod_sparse_mat/test/t-mul.c @@ -20,8 +20,8 @@ int main(void) { - slong rep, r, c, i, k; - mp_limb_t n, a; + slong rep, r, c, k; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A; mp_ptr x, y, y2; diff --git a/nmod_sparse_mat/test/t-neg.c b/nmod_sparse_mat/test/t-neg.c index 03d8a3a159..8961c42dec 100644 --- a/nmod_sparse_mat/test/t-neg.c +++ b/nmod_sparse_mat/test/t-neg.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, c; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B, C, D; diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c index 0084dc0180..9792da5527 100644 --- a/nmod_sparse_mat/test/t-nullspace.c +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -13,7 +13,7 @@ #include #include #include -#include +/* #include */ #include "flint.h" #include "nmod_sparse_mat.h" #include "ulong_extras.h" @@ -21,17 +21,16 @@ int main(void) { - int iter, ret; slong rep, nreps = 100, r, c, i; - mp_limb_t n, a; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A; nmod_mat_t X, AX; slong rk[6]; - double elapsed[6] = {0, 0, 0, 0, 0, 0}; +/* double elapsed[6] = {0, 0, 0, 0, 0, 0}; */ slong discrep[6] = {0, 0, 0, 0, 0, 0}; char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - struct timeval start, end; +/* struct timeval start, end; */ FLINT_TEST_INIT(state); flint_printf("finding nullspace of A...."); @@ -48,7 +47,7 @@ main(void) nmod_sparse_mat_randtest(A, state, c/20, c/10); for (i = 0; i < 6; ++i) { - gettimeofday(&start, NULL); +/* gettimeofday(&start, NULL); */ switch (i) { case 0: rk[0] = nmod_sparse_mat_nullspace_rref(X, A); break; @@ -58,9 +57,9 @@ main(void) case 4: rk[4] = nmod_sparse_mat_nullspace_wiedemann(X, A, state, 2); break; case 5: rk[5] = nmod_sparse_mat_nullspace_block_wiedemann(X, A, 8, state, 2); break; } - //if (i == 0 && rk[0] == UWORD(0) ) { nmod_mat_clear(X); break;} - gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + /* if (i == 0 && rk[0] == UWORD(0) ) { nmod_mat_clear(X); break;} */ +/* gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); */ if(X->c==0) continue; nmod_mat_init(AX, A->r, X->c, n); nmod_sparse_mat_mul_mat(AX, A, X); @@ -86,11 +85,11 @@ main(void) flint_printf("PASS\n"); for(i = 0; i < 6; ++i) { - flint_printf("Finding nullspace with %s took average time %lf\n", - names[i], elapsed[i]/nreps); + flint_printf("Found nullspace with %s\n", names[i]); +/* flint_printf("\tAverage time %lf:\n", elapsed[i]/nreps); */ if(discrep[i] > 0) flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", - discrep[i], nreps); + discrep[i], nreps); } return 0; } diff --git a/nmod_sparse_mat/test/t-rref.c b/nmod_sparse_mat/test/t-rref.c index 5c678219e5..aa5c1345c0 100644 --- a/nmod_sparse_mat/test/t-rref.c +++ b/nmod_sparse_mat/test/t-rref.c @@ -21,7 +21,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, c; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B; diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c index d83850d960..a38f634d2e 100644 --- a/nmod_sparse_mat/test/t-scalar_mul.c +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -21,8 +21,8 @@ int main(void) { - slong rep, r, c, i; - mp_limb_t n, a; + slong rep, r, c; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B, C, D; FLINT_TEST_INIT(state); @@ -36,7 +36,6 @@ main(void) c = n_randint(state, 200); do n = n_randtest_not_zero(state); while (n == UWORD(1)); - a = n_randint(state, n); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_sparse_mat_init(B, r, c, mod); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 9e29833e13..c63b739ad6 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -13,7 +13,7 @@ #include #include #include -#include +/*#include */ #include "flint.h" #include "nmod_sparse_mat.h" #include "ulong_extras.h" @@ -23,7 +23,7 @@ main(void) { int iter, ret; slong rep, nreps = 100, r, c, i; - mp_limb_t n, a; + mp_limb_t n; nmod_t mod; nmod_mat_t dA; nmod_sparse_mat_t A, At; @@ -31,9 +31,9 @@ main(void) slong niters[6] = {0, 0, 0, 0, 0, 0}; slong psol[6] = {0, 0, 0, 0, 0, 0}; slong nosol[6] = {0, 0, 0, 0, 0, 0}; - double elapsed[6] = {0, 0, 0, 0, 0}; + /*double elapsed[6] = {0, 0, 0, 0, 0};*/ char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - struct timeval start, end; + /*struct timeval start, end;*/ FLINT_TEST_INIT(state); flint_printf("solving Ax = b...."); @@ -62,7 +62,7 @@ main(void) for (i = 0; i < 6; ++i) { iter = 0; - gettimeofday(&start, NULL); + /*gettimeofday(&start, NULL);*/ switch (i) { case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; @@ -72,8 +72,8 @@ main(void) case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; } - gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + /*gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec);*/ if (ret == 0) nosol[i] += 1; else { @@ -128,7 +128,8 @@ main(void) flint_printf("PASS\n"); for (i = 0; i < 6; ++i) { - flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + flint_printf("Solved with %s\n", names[i]); + /*flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps);*/ if (nosol[i]) flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); if (psol[i]) diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index 7062b8565c..f87c3fb53b 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,8 +20,8 @@ int main(void) { - slong rep, r, c, i; - mp_limb_t n, a; + slong rep, r, c; + mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A, B, C; FLINT_TEST_INIT(state); diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index 318f7a0e15..ea937c93cf 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -19,6 +19,9 @@ void nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { slong r, c, i, j; + nmod_sparse_entry_struct *Ae, *Be; + nmod_sparse_vec_struct *row; + /* Get number of nnzs in each column of A (thus each row of B) */ for (c = 0; c < A->c; ++c) { @@ -36,7 +39,7 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) /* Allocate space for nnz and reset counters */ for (c = 0; c < A->c; ++c) { - nmod_sparse_vec_struct *row = &B->rows[c]; + row = &B->rows[c]; if (row->nnz == 0) nmod_sparse_vec_clear(row); else row->entries = flint_realloc(row->entries, row->nnz*sizeof(*row->entries)); row->nnz = 0; @@ -46,11 +49,11 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { for (i = 0; i < A->rows[r].nnz; ++i) { - nmod_sparse_entry_struct *Ae = &A->rows[r].entries[i]; + Ae = &A->rows[r].entries[i]; c = Ae->ind; if(c >= A->c) break; j = B->rows[c].nnz++; - nmod_sparse_entry_struct *Be = &B->rows[c].entries[j]; + Be = &B->rows[c].entries[j]; Be->ind = r, Be->val = Ae->val; } } diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 1fc01aa24c..f5226bef96 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -202,27 +202,68 @@ void nmod_sparse_vec_scalar_mul_fmpz(nmod_sparse_vec_t v, const nmod_sparse_vec_ fmpz_clear(d); } -FLINT_DLL -void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod); - +/* Utility macros used by binary vector operations */ +/* Compute total number of indices between two sparse vectors */ NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_scalar_submul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod) +slong _nmod_sparse_vec_union_nnz(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v) { - nmod_sparse_vec_scalar_addmul_nmod(w, u, v, nmod_neg(c, mod), mod); + slong i, j, nnz = 0; + for (i = j = 0; i < u->nnz && j < v->nnz; ++nnz) + { + if (u->entries[i].ind == v->entries[j].ind) ++i, ++j; + else if (u->entries[i].ind < v->entries[j].ind) ++i; + else if (u->entries[i].ind > v->entries[j].ind) ++j; + } + nnz += u->nnz - i + v->nnz - j; + return nnz; } +/* Iterate through u and v in descending order, assigning sorted indices to w */ +/* Returns -1 if u and v are both exhausted, + 2 if we->ind = ue->ind == ve->ind + 1 if we->ind = ve->ind > ue->ind (or u exhausted), + 0 if we->ind = ue->ind > ve->ind (or v exhausted). */ NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +slong _nmod_sparse_vector_merge_descend(nmod_sparse_entry_struct **we, + nmod_sparse_entry_struct **ue, + nmod_sparse_entry_struct **ve, + const nmod_sparse_vec_t u, + const nmod_sparse_vec_t v) { - nmod_sparse_vec_scalar_addmul_nmod(w, u, v, UWORD(1), mod); + slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; + slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; + if(uind == -1 && vind == -1) return -1; + if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + --*ue, --*we; (*we)->ind = uind; return 0; } +/* Like resize, but removes entries from the front of the vector */ NMOD_SPARSE_VEC_INLINE -void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +void _nmod_sparse_vector_shift_left (nmod_sparse_vec_t v, slong amt) { - nmod_sparse_vec_scalar_addmul_nmod(w, u, v, mod.n-1, mod); + if (amt == v->nnz) nmod_sparse_vec_clear(v); + else if(amt > 0) + { + v->nnz -= amt; + memmove(v->entries, v->entries + amt, v->nnz*sizeof(*v->entries)); + v->entries = flint_realloc(v->entries, v->nnz*sizeof(*v->entries)); + } } +FLINT_DLL +void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod); + +FLINT_DLL +void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod); + +FLINT_DLL +void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod); + +FLINT_DLL +void nmod_sparse_vec_scalar_submul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, const mp_limb_t c, nmod_t mod); + + FLINT_DLL mp_limb_t nmod_sparse_vec_dot(const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod); diff --git a/nmod_sparse_vec/add.c b/nmod_sparse_vec/add.c new file mode 100644 index 0000000000..af85da0198 --- /dev/null +++ b/nmod_sparse_vec/add.c @@ -0,0 +1,44 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_add(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + nmod_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (vnnz == 0) nmod_sparse_vec_set(w, u, 0); + else if (unnz == 0) nmod_sparse_vec_set(w, v, 0); + else + { + wnnz = _nmod_sparse_vec_union_nnz (u, v); + w->entries = flint_realloc(w->entries, wnnz*sizeof(*w->entries)); + w->nnz = wnnz; + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _nmod_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: we->val = ue->val; break; + case 1: we->val = ve->val; break; + default: we->val = nmod_add(ue->val, ve->val, mod); + if (we->val == UWORD(0)) we++; + } + } + _nmod_sparse_vector_shift_left (w, we - w->entries); + } +} diff --git a/nmod_sparse_vec/at.c b/nmod_sparse_vec/at.c index 00080f92c8..e2e145294b 100644 --- a/nmod_sparse_vec/at.c +++ b/nmod_sparse_vec/at.c @@ -17,10 +17,6 @@ mp_limb_t *nmod_sparse_vec_at(nmod_sparse_vec_t vec, slong i) { - slong pc, pr; - slong numr = 0, numc = 0; - nmod_sparse_vec_struct *pcol, *prow, *row, *col; - /* TODO: binary search */ slong j; for (j = 0; j < vec->nnz; ++j) diff --git a/nmod_sparse_vec/equal.c b/nmod_sparse_vec/equal.c index 10e7726848..7d4cc036a7 100644 --- a/nmod_sparse_vec/equal.c +++ b/nmod_sparse_vec/equal.c @@ -17,8 +17,8 @@ int nmod_sparse_vec_equal(const nmod_sparse_vec_t vec1, const nmod_sparse_vec_t vec2, slong ioff) { - if (vec1->nnz != vec2->nnz) return 0; slong i; + if (vec1->nnz != vec2->nnz) return 0; for (i = 0; i < vec1->nnz; ++i) { if ((vec1->entries[i].ind != vec2->entries[i].ind + ioff) || diff --git a/nmod_sparse_vec/from_dense.c b/nmod_sparse_vec/from_dense.c index 82d51ff13c..00c0be2798 100644 --- a/nmod_sparse_vec/from_dense.c +++ b/nmod_sparse_vec/from_dense.c @@ -17,15 +17,16 @@ void nmod_sparse_vec_from_dense(nmod_sparse_vec_t vec, mp_srcptr src, slong len) { + slong i; + nmod_sparse_entry_struct *e; if (len == 0) nmod_sparse_vec_clear(vec); else { - slong i; vec->entries = flint_realloc(vec->entries, len*sizeof(*vec->entries)); vec->nnz = 0; for (i = 0; i < len; ++i) { if (src[i] == UWORD(0)) continue; - nmod_sparse_entry_struct *e = &vec->entries[vec->nnz++]; + e = &vec->entries[vec->nnz++]; e->ind = i, e->val = src[i]; } if (vec->nnz == 0) nmod_sparse_vec_clear(vec); diff --git a/nmod_sparse_vec/randtest.c b/nmod_sparse_vec/randtest.c index 8c1ce08282..9176b3baa4 100644 --- a/nmod_sparse_vec/randtest.c +++ b/nmod_sparse_vec/randtest.c @@ -15,15 +15,15 @@ #include "flint.h" #include "nmod_sparse_vec.h" -void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, mp_limb_signed_t nnz, mp_limb_signed_t len, nmod_t mod) +void nmod_sparse_vec_randtest(nmod_sparse_vec_t vec, flint_rand_t state, slong nnz, slong len, nmod_t mod) { + slong i, j; + mp_limb_t v; nnz = FLINT_MIN(nnz, len); vec->nnz = nnz; if (nnz == 0) {vec->entries = NULL; return;} vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); - slong i, j; - mp_limb_t v; for (i = 0; i < nnz; ++i) { do v = n_randtest(state) % mod.n; diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c index 37d7b5f890..8c107973a6 100644 --- a/nmod_sparse_vec/scalar_addmul.c +++ b/nmod_sparse_vec/scalar_addmul.c @@ -17,39 +17,30 @@ void nmod_sparse_vec_scalar_addmul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) { - if (c == UWORD(0) || (u->nnz == 0 && v->nnz == 0)) {nmod_sparse_vec_zero(w); return;} - if (v->nnz == 0) {nmod_sparse_vec_set(w, u, 0); return;} - if (u->nnz == 0) {nmod_sparse_vec_scalar_mul_nmod(w, v, c, mod); return;} + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + nmod_sparse_entry_struct *ue, *ve, *we; - nmod_sparse_vec_t u2; u2->nnz = u->nnz; - if (u==w) + /* Check for simpler operations first */ + if (c == UWORD(0) || vnnz == 0) nmod_sparse_vec_set(w, u, 0); + else if (c == UWORD(1)) nmod_sparse_vec_add(w, u, v, mod); + else if (c + UWORD(1) == mod.n) nmod_sparse_vec_sub(w, u, v, mod); + else if (unnz == 0) nmod_sparse_vec_scalar_mul_nmod(w, v, c, mod); + else { - /* Handle inplace operations */ - u2->entries = flint_malloc(u->nnz*sizeof(*u2->entries)); - memcpy(u2->entries, u->entries, u->nnz*sizeof(*u2->entries)); - } - else u2->entries = u->entries; - - w->entries = flint_realloc(w->entries, (u->nnz+v->nnz)*sizeof(*w->entries)); - memset(w->entries, 0, (u->nnz+v->nnz)*sizeof(*w->entries)); - slong i = 0, j = 0, k = 0; - nmod_sparse_entry_struct *ue = u2->entries; - nmod_sparse_entry_struct *ve = v->entries; - nmod_sparse_entry_struct *we = w->entries; - - /* Interleave u and v */ - while (i < u->nnz && j < v->nnz) - { - we[k].ind = FLINT_MIN(ue[i].ind, ve[j].ind); - if (ue[i].ind == we[k].ind) we[k].val = ue[i].val, ++i; - if (ve[j].ind == we[k].ind) we[k].val = nmod_addmul(we[k].val, ve[j].val, c, mod), ++j; - if (we[k].val != UWORD(0)) ++k; + wnnz = _nmod_sparse_vec_union_nnz (u, v); + w->entries = flint_realloc(w->entries, wnnz*sizeof(*w->entries)); + w->nnz = wnnz; + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _nmod_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: we->val = ue->val; break; + case 1: we->val = nmod_mul(ve->val, c, mod); break; + default: we->val = nmod_add (ue->val, nmod_mul(ve->val, c, mod), mod); + if (we->val == UWORD(0)) we++; + } + } + _nmod_sparse_vector_shift_left (w, we - w->entries); } - while (i < u->nnz) we[k].ind = ue[i].ind, we[k].val = ue[i].val, ++i, ++k; - while (j < v->nnz) we[k].ind = ve[j].ind, we[k].val = nmod_mul(ve[j].val, c, mod), ++j, ++k; - - if (u==w) flint_free(u2->entries); - if (k == 0) nmod_sparse_vec_clear(w); - else w->entries = realloc(w->entries, k*sizeof(*w->entries)); - w->nnz = k; } diff --git a/nmod_sparse_vec/scalar_submul.c b/nmod_sparse_vec/scalar_submul.c new file mode 100644 index 0000000000..2e1c6d396b --- /dev/null +++ b/nmod_sparse_vec/scalar_submul.c @@ -0,0 +1,46 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_scalar_submul_nmod(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, mp_limb_t c, nmod_t mod) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + nmod_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (c == UWORD(0) || vnnz == 0) nmod_sparse_vec_set(w, u, 0); + else if (c == UWORD(1)) nmod_sparse_vec_sub(w, u, v, mod); + else if (c + UWORD(1) == mod.n) nmod_sparse_vec_add(w, u, v, mod); + else if (unnz == 0) nmod_sparse_vec_scalar_mul_nmod(w, v, nmod_neg(c, mod), mod); + else + { + wnnz = _nmod_sparse_vec_union_nnz (u, v); + w->entries = flint_realloc(w->entries, wnnz*sizeof(*w->entries)); + w->nnz = wnnz; + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _nmod_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: we->val = ue->val; break; + case 1: we->val = nmod_mul(ve->val, nmod_neg(c, mod), mod); break; + default: we->val = nmod_sub(ue->val, nmod_mul(ve->val, c, mod), mod); + if (we->val == UWORD(0)) we++; + } + } + _nmod_sparse_vector_shift_left (w, we - w->entries); + } +} diff --git a/nmod_sparse_vec/sub.c b/nmod_sparse_vec/sub.c new file mode 100644 index 0000000000..675a034b7d --- /dev/null +++ b/nmod_sparse_vec/sub.c @@ -0,0 +1,44 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_vec.h" + +void nmod_sparse_vec_sub(nmod_sparse_vec_t w, const nmod_sparse_vec_t u, const nmod_sparse_vec_t v, nmod_t mod) +{ + slong unnz = u->nnz, vnnz = v->nnz, wnnz, k; + nmod_sparse_entry_struct *ue, *ve, *we; + + /* Check for simpler operations first */ + if (vnnz == 0) nmod_sparse_vec_set(w, u, 0); + else if (unnz == 0) nmod_sparse_vec_neg(w, v, mod); + else + { + wnnz = _nmod_sparse_vec_union_nnz (u, v); + w->entries = flint_realloc(w->entries, wnnz*sizeof(*w->entries)); + w->nnz = wnnz; + ue = u->entries + unnz, ve = v->entries + vnnz, we = w->entries + wnnz; + while ((k = _nmod_sparse_vector_merge_descend (&we, &ue, &ve, u, v)) >= 0) + { + switch(k) + { + case 0: we->val = ue->val; break; + case 1: we->val = nmod_neg(ve->val, mod); break; + default: we->val = nmod_sub(ue->val, ve->val, mod); + if (we->val == UWORD(0)) we++; + } + } + _nmod_sparse_vector_shift_left (w, we - w->entries); + } +} diff --git a/nmod_sparse_vec/test/t-add.c b/nmod_sparse_vec/test/t-add.c index 5c9116eb22..86c0dc094f 100644 --- a/nmod_sparse_vec/test/t-add.c +++ b/nmod_sparse_vec/test/t-add.c @@ -68,6 +68,20 @@ main(void) flint_printf("FAIL: ((u += v) -= v) != u+v-v\n"); abort(); } + + nmod_sparse_vec_add(u, v, u, mod); + if (!nmod_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: (u = v + u) != u+v\n"); + abort(); + } + + nmod_sparse_vec_sub(v, u, v, mod); + if (!nmod_sparse_vec_equal(v, x, 0)) + { + flint_printf("FAIL: (u = v + u) != u+v\n"); + abort(); + } nmod_sparse_vec_clear(u); nmod_sparse_vec_clear(v); nmod_sparse_vec_clear(w); diff --git a/nmod_sparse_vec/test/t-construct.c b/nmod_sparse_vec/test/t-construct.c index 418a4b8b18..1345568e47 100644 --- a/nmod_sparse_vec/test/t-construct.c +++ b/nmod_sparse_vec/test/t-construct.c @@ -20,7 +20,7 @@ int main(void) { - slong rep, len, nnz, i, j; + slong rep, len, nnz, i; mp_limb_t n; nmod_t mod; nmod_sparse_vec_t u, v; diff --git a/nmod_sparse_vec/test/t-scalar_mul.c b/nmod_sparse_vec/test/t-scalar_mul.c index a79ecf0b8b..82c51d334c 100644 --- a/nmod_sparse_vec/test/t-scalar_mul.c +++ b/nmod_sparse_vec/test/t-scalar_mul.c @@ -33,10 +33,10 @@ main(void) for (rep = 0; rep < 1000; rep++) { len = n_randint(state, 50); - nnz = 2; //n_randint(state, len+1); + nnz = n_randint(state, len+1); do n = n_randtest_not_zero(state); while (n == UWORD(1)); - c = 2; //n_randint(state, n); + c = n_randint(state, n); nmod_init(&mod, n); nmod_sparse_vec_init(u); @@ -57,6 +57,16 @@ main(void) abort(); } + nmod_sparse_vec_scalar_submul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_mul_nmod(x, v, c, mod); + nmod_sparse_vec_sub(x, u, x, mod); + + if (!nmod_sparse_vec_equal(w, x, 0)) + { + flint_printf("FAIL: u - c*v != u - (c*v)\n"); + abort(); + } + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, c, mod); nmod_sparse_vec_scalar_addmul_nmod(u, u, v, c, mod); @@ -66,6 +76,33 @@ main(void) abort(); } + nmod_sparse_vec_scalar_addmul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_addmul_nmod(v, u, v, c, mod); + + if (!nmod_sparse_vec_equal(v, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + nmod_sparse_vec_scalar_submul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_submul_nmod(u, u, v, c, mod); + + if (!nmod_sparse_vec_equal(u, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + + nmod_sparse_vec_scalar_submul_nmod(w, u, v, c, mod); + nmod_sparse_vec_scalar_submul_nmod(v, u, v, c, mod); + + if (!nmod_sparse_vec_equal(v, w, 0)) + { + flint_printf("FAIL: u + c*v != (u += c*v)\n"); + abort(); + } + nmod_sparse_vec_scalar_mul_nmod(x, v, c, mod); nmod_sparse_vec_scalar_mul_nmod(v, v, c, mod); diff --git a/test/t-hashmap.c b/test/t-hashmap.c new file mode 100644 index 0000000000..9db70162cc --- /dev/null +++ b/test/t-hashmap.c @@ -0,0 +1,78 @@ +/* + Copyright (C) 2009 William Hart + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "hashmap.h" +#include "ulong_extras.h" + +int main(void) +{ + slong rep, num, *keys, *vals, nreps = 1000, i, *ptr; + hashmap_t h; + FLINT_TEST_INIT(state); + + flint_printf("hashmap...."); + fflush(stdout); + for (rep = 0; rep < nreps; rep++) + { + num = n_randint(state, 1000); + keys = flint_malloc(num*sizeof(*keys)); + vals = flint_malloc(num*sizeof(*vals)); + + hashmap_init(h, num); + for (i = 0; i < num; ++i) + { + do keys[i] = n_randtest(state); + while (hashmap_get(h, keys[i]) != NULL); + vals[i] = n_randtest(state); + hashmap_put(h, keys[i], &vals[i]); + } + if (h->num != num) + { + flint_printf("FAIL: Added %wd keys, hashmap only has %wd\n", num, h->num); + abort(); + } + + for (i = 0; i < num; ++i) + { + if (h->keys[i] != keys[i]) + { + flint_printf("FAIL: Mismatch key at %wd:%wd\n", i, keys[i]); + abort(); + } + ptr = hashmap_get(h, keys[i]); + if (ptr != &vals[i]) + { + flint_printf("FAIL: Mismatch value at %wd:%wd\n", i, keys[i]); + abort(); + } + } + for (i = 0; i < num; ++i) + { + hashmap_rem(h, keys[i]); + ptr = hashmap_get(h, keys[i]); + if (ptr != NULL) + { + flint_printf("FAIL: removed key %wd, still exists in hashtable\n"); + abort(); + } + } + flint_free(keys); + flint_free(vals); + hashmap_clear(h); + } + FLINT_TEST_CLEANUP(state); + flint_printf("PASS\n"); + return 0; +} diff --git a/test/t-heap.c b/test/t-heap.c new file mode 100644 index 0000000000..2f6b90212c --- /dev/null +++ b/test/t-heap.c @@ -0,0 +1,97 @@ +/* + Copyright (C) 2009 William Hart + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "heap.h" +#include "ulong_extras.h" + +void check_heap(heap_t h, slong *vals) +{ + slong i, j; + for (i = h->num - 1; i >= 0; --i) + { + if (h->pos[h->idx[i]] != i) + { + flint_printf("Mismatch between idx and pos\n"); + abort(); + } + if (h->val[h->idx[i]] != vals[h->idx[i]]) + { + flint_printf("Mismatch between inside and outside scores\n"); + abort(); + } + if (i==0) break; + j = (i - 1)/2; + if (h->val[h->idx[i]] < h->val[h->idx[j]]) + { + flint_printf("Not a heap: %2wd:%2wd:%2wd < %2wd:%2wd:%2wd\n", + i, h->idx[i], h->val[h->idx[i]], j, h->idx[j], h->val[h->idx[j]]); + abort(); + } + } +} + +int main(void) +{ + slong rep, num, *vals, nreps = 1000, i, j, val, oval; + heap_t h; + FLINT_TEST_INIT(state); + + flint_printf("heap...."); + fflush(stdout); + for (rep = 0; rep < nreps; rep++) + { + num = n_randint(state, 1000); + vals = flint_malloc(num*sizeof(*vals)); + + heap_init(h, num); + for (i = 0; i < num; ++i) + { + vals[i] = n_randtest(state); + heap_push(h, vals[i]); + } + if (h->num != num) + { + flint_printf("FAIL: Added %wd values, heap only has %wd\n", num, h->num); + abort(); + } + check_heap(h, vals); + + /* Modify each value and check if heap maintained */ + for (i = 0; i < num; ++i) + { + vals[i] = n_randtest(state); + heap_adjust(h, i, vals[i]); + check_heap(h, vals); + } + + /* Pop items from heap and check that in sorted order */ + for (i = 0; i < num; ++i) + { + heap_pop(h, &val); + if (i > 0 && val < oval) + { + flint_printf("FAIL: popping from heap out of order\n"); + abort(); + } + check_heap(h, vals); + oval = val; + } + flint_free(vals); + heap_clear(h); + } + FLINT_TEST_CLEANUP(state); + flint_printf("PASS\n"); + return 0; +} From 7323a4bca5496a95cd6de09c66566b07d5cb2d38 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 28 Apr 2020 22:31:09 -0700 Subject: [PATCH 21/42] Fixed spacing issues --- fmpz_sparse_mat.h | 25 +- fmpz_sparse_mat/det_bareiss.c | 2 +- fmpz_sparse_mat/det_cofactor.c | 2 +- fmpz_sparse_mat/det_divisor.c | 2 +- fmpz_sparse_mat/fflu.c | 4 +- fmpz_sparse_mat/gram.c | 6 +- fmpz_sparse_mat/hnf_classical.c | 9 +- fmpz_sparse_mat/hnf_minors.c | 2 +- fmpz_sparse_mat/hnf_modular.c | 4 +- fmpz_sparse_mat/hnf_pernet_stein.c | 637 ++++++++++++++++++ fmpz_sparse_mat/hnf_xgcd.c | 6 +- fmpz_sparse_mat/snf.c | 50 ++ fmpz_sparse_mat/snf_diagonal.c | 42 ++ fmpz_sparse_mat/snf_iliopoulos.c | 237 +++++++ fmpz_sparse_mat/snf_kannan_bachem.c | 137 ++++ fmpz_sparse_mat/solve_dixon.c | 2 +- fmpz_sparse_mat/strong_echelon_form_mod.c | 17 +- fmpz_sparse_mat/test/t-add.c | 2 +- fmpz_sparse_mat/test/t-concat_horizontal.c | 2 +- fmpz_sparse_mat/test/t-concat_vertical.c | 2 +- fmpz_sparse_mat/test/t-construct.c | 2 +- fmpz_sparse_mat/test/t-dense.c | 2 +- fmpz_sparse_mat/test/t-fflu.c | 24 +- fmpz_sparse_mat/test/t-init_clear.c | 2 +- fmpz_sparse_mat/test/t-mul.c | 2 +- fmpz_sparse_mat/test/t-neg.c | 2 +- fmpz_sparse_mat/test/t-scalar_mul.c | 2 +- fmpz_sparse_mat/test/t-solve_dixon.c | 5 +- fmpz_sparse_mat/test/t-solve_dixon_den.c | 5 +- fmpz_sparse_mat/test/t-transpose.c | 2 +- fmpz_sparse_vec.h | 26 +- fmpz_sparse_vec/dot_dense.c | 3 +- fmpz_sparse_vec/gauss_elim.c | 12 +- fmpz_sparse_vec/gauss_elim_debugging | 146 ---- fmpz_sparse_vec/multi_CRT_ui.c | 2 +- fmpz_sparse_vec/set.c | 2 +- fmpz_sparse_vec/split.c | 2 +- fmpz_sparse_vec/test/t-add.c | 2 +- fmpz_sparse_vec/test/t-concat.c | 2 +- fmpz_sparse_vec/test/t-construct.c | 2 +- fmpz_sparse_vec/test/t-dense.c | 2 +- fmpz_sparse_vec/test/t-dot.c | 2 +- fmpz_sparse_vec/test/t-gauss_elim.c | 2 +- fmpz_sparse_vec/test/t-init_clear.c | 4 +- fmpz_sparse_vec/test/t-max_bits.c | 2 +- fmpz_sparse_vec/test/t-neg.c | 2 +- fmpz_sparse_vec/test/t-nmod.c | 2 +- fmpz_sparse_vec/test/t-scalar_divexact.c | 2 +- fmpz_sparse_vec/test/t-scalar_mod.c | 2 +- fmpz_sparse_vec/test/t-scalar_mul.c | 2 +- fq_sparse_mat_templates/lu.c | 15 +- .../nullspace_block_lanczos.c | 2 +- .../nullspace_block_wiedemann.c | 2 +- fq_sparse_mat_templates/nullspace_lanczos.c | 2 +- fq_sparse_mat_templates/nullspace_wiedemann.c | 2 +- fq_sparse_mat_templates/rref.c | 4 +- .../solve_block_wiedemann.c | 12 +- fq_sparse_mat_templates/solve_lu.c | 2 +- fq_sparse_mat_templates/solve_wiedemann.c | 10 +- fq_sparse_mat_templates/test/t-inv.c | 3 +- fq_sparse_mat_templates/test/t-lu.c | 26 +- fq_sparse_mat_templates/test/t-nullspace.c | 4 +- fq_sparse_mat_templates/test/t-rref.c | 3 +- fq_sparse_mat_templates/test/t-solve.c | 8 +- fq_sparse_mat_templates/tmp | 31 - fq_sparse_vec_templates.h | 28 +- fq_sparse_vec_templates/add.c | 2 +- fq_sparse_vec_templates/scalar_addmul.c | 2 +- fq_sparse_vec_templates/sub.c | 2 +- nmod_sparse_mat.h | 7 +- nmod_sparse_mat/lu.c | 9 +- nmod_sparse_mat/nullspace_block_lanczos.c | 8 +- nmod_sparse_mat/nullspace_block_wiedemann.c | 8 +- nmod_sparse_mat/nullspace_lanczos.c | 8 +- nmod_sparse_mat/nullspace_lu.c | 8 +- nmod_sparse_mat/nullspace_rref.c | 4 +- nmod_sparse_mat/nullspace_wiedemann.c | 8 +- nmod_sparse_mat/rref.c | 6 +- nmod_sparse_mat/solve_block_lanczos.c | 23 +- nmod_sparse_mat/solve_block_wiedemann.c | 12 +- nmod_sparse_mat/solve_lanczos.c | 5 +- nmod_sparse_mat/solve_wiedemann.c | 10 +- nmod_sparse_mat/strong_echelon_form.c | 2 +- nmod_sparse_mat/test/t-inv.c | 5 +- nmod_sparse_mat/test/t-lu.c | 30 +- nmod_sparse_mat/test/t-nullspace.c | 10 +- nmod_sparse_mat/test/t-rref.c | 3 +- nmod_sparse_mat/test/t-solve.c | 8 +- nmod_sparse_mat/transpose.c | 4 +- nmod_sparse_vec.h | 10 +- nmod_sparse_vec/dot_dense.c | 3 +- nmod_sparse_vec/split.c | 6 +- nmod_sparse_vec/test/t-init_clear.c | 2 +- 93 files changed, 1400 insertions(+), 418 deletions(-) create mode 100644 fmpz_sparse_mat/hnf_pernet_stein.c create mode 100644 fmpz_sparse_mat/snf.c create mode 100644 fmpz_sparse_mat/snf_diagonal.c create mode 100644 fmpz_sparse_mat/snf_iliopoulos.c create mode 100644 fmpz_sparse_mat/snf_kannan_bachem.c delete mode 100644 fmpz_sparse_vec/gauss_elim_debugging delete mode 100644 fq_sparse_mat_templates/tmp diff --git a/fmpz_sparse_mat.h b/fmpz_sparse_mat.h index 7c3d2c27a6..f7393d4bb5 100644 --- a/fmpz_sparse_mat.h +++ b/fmpz_sparse_mat.h @@ -110,8 +110,8 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_set (fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M) { slong i, rmax = FLINT_MIN(M->r, M->r); - if(M==N) return; - for(i=0; irows[i], &M->rows[i], M->c_off); + if (M==N) return; + for (i = 0; i < rmax; ++i) fmpz_sparse_vec_set(&N->rows[i], &M->rows[i], M->c_off); } FLINT_DLL @@ -121,7 +121,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_append_col (fmpz_sparse_mat_t M, const fmpz *v) { slong i; - for(i=0; ir; ++i) fmpz_sparse_vec_set_entry(&M->rows[i], M->c, &v[i]); + for (i = 0; i < M->r; ++i) fmpz_sparse_vec_set_entry(&M->rows[i], M->c, &v[i]); M->c += 1; } @@ -235,7 +235,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_split_horizontal (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2, const fmpz_sparse_mat_t B, slong c) { slong i; - for(i=0; ir; ++i) fmpz_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); + for (i = 0; i < B->r; ++i) fmpz_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); } /* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ @@ -244,8 +244,8 @@ void fmpz_sparse_mat_split_vertical (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2, { slong i; r = FLINT_MIN(r, B->r); - for(i=0; irows[i], &B->rows[i], B->c_off); - for(i=r; ir; ++i) fmpz_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); + for (i = 0; i < r; ++i) fmpz_sparse_vec_set(&M1->rows[i], &B->rows[i], B->c_off); + for (i = r; i < B->r; ++i) fmpz_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } /* Matrix permutation */ @@ -253,8 +253,9 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_permute_cols(fmpz_sparse_mat_t M, slong *Q) { slong i; - for (i = 0; i < M->r; ++i) { - if(!M->rows[i].nnz) continue; + for (i = 0; i < M->r; ++i) + { + if (!M->rows[i].nnz) continue; fmpz_sparse_vec_permute_inds(&M->rows[i], Q); qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), fmpz_sparse_entry_cmp); } @@ -414,7 +415,7 @@ FMPZ_SPARSE_MAT_INLINE void _fmpz_sparse_mat_with_transpose_clear(fmpz_sparse_mat_with_transpose_t MT) { slong c; - for(c = 0; c < MT->M->c; ++c) + for (c = 0; c < MT->M->c; ++c) hashmap_clear(&MT->cols[c]); flint_free(MT->cols); memset(MT, 0, sizeof(*MT)); @@ -493,7 +494,7 @@ int _fmpz_sparse_mat_with_transpose_gauss_elim_ext(fmpz_sparse_mat_with_transpos { /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; - if(pe->ind != e->ind) + if (pe->ind != e->ind) return _fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r); MT_FIX(MT, pr, MT_FIX(MT, r, @@ -507,7 +508,7 @@ int _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mod(fmpz_sparse_mat_with_tran { /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; - if(pe->ind != e->ind) + if (pe->ind != e->ind) return _fmpz_sparse_mat_with_transpose_gauss_elim_mod(MT, pr, r, mod); MT_FIX(MT, pr, MT_FIX(MT, r, @@ -523,7 +524,7 @@ int _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mods(fmpz_sparse_mat_with_tra { /* If leading entries do not match, or leading entry of pr divides that of r, just a normal elimination */ fmpz_sparse_entry_struct *pe = &MT->M->rows[pr].entries[0], *e = &MT->M->rows[r].entries[0]; - if(pe->ind != e->ind) + if (pe->ind != e->ind) return _fmpz_sparse_mat_with_transpose_gauss_elim_mods(MT, pr, r, mod); MT_FIX(MT, pr, MT_FIX(MT, r, diff --git a/fmpz_sparse_mat/det_bareiss.c b/fmpz_sparse_mat/det_bareiss.c index e74d7f4db1..4414747a62 100644 --- a/fmpz_sparse_mat/det_bareiss.c +++ b/fmpz_sparse_mat/det_bareiss.c @@ -18,7 +18,7 @@ fmpz_sparse_mat_det_bareiss(fmpz_t det, const fmpz_sparse_mat_t M) slong i, rk, *P, *Q; fmpz *D; fmpz_sparse_mat_t L, U; - if(M->r != M->c) {fmpz_zero(det); return;} + if (M->r != M->c) {fmpz_zero(det); return;} fmpz_one(det); if (M->r == UWORD(0)) return; diff --git a/fmpz_sparse_mat/det_cofactor.c b/fmpz_sparse_mat/det_cofactor.c index e0a8297c1e..ed13e145bd 100644 --- a/fmpz_sparse_mat/det_cofactor.c +++ b/fmpz_sparse_mat/det_cofactor.c @@ -14,7 +14,7 @@ void fmpz_sparse_mat_det_cofactor(fmpz_t det, const fmpz_sparse_mat_t M) { fmpz_mat_t dM; - if(M->r != M->c) {fmpz_zero(det); return;} + if (M->r != M->c) {fmpz_zero(det); return;} if (M->r > 4) { flint_printf("Exception (fmpz_sparse_mat_det_cofactor). dim > 4 not implemented."); diff --git a/fmpz_sparse_mat/det_divisor.c b/fmpz_sparse_mat/det_divisor.c index 007e81c027..fcb69daef7 100644 --- a/fmpz_sparse_mat/det_divisor.c +++ b/fmpz_sparse_mat/det_divisor.c @@ -19,7 +19,7 @@ fmpz_sparse_mat_det_divisor(fmpz_t d, const fmpz_sparse_mat_t M) slong i; fmpz_mat_t X, B; fmpz_t t, u, v, mod; - if(M->r != M->c) {fmpz_zero(d); return;} + if (M->r != M->c) {fmpz_zero(d); return;} fmpz_mat_init(X, M->c, 1); fmpz_mat_init(B, M->r, 1); diff --git a/fmpz_sparse_mat/fflu.c b/fmpz_sparse_mat/fflu.c index b246b5e4da..fe7ed77d71 100644 --- a/fmpz_sparse_mat/fflu.c +++ b/fmpz_sparse_mat/fflu.c @@ -61,12 +61,12 @@ fmpz_sparse_mat_fflu(fmpz *D, slong *P, slong *Q, fmpz_sparse_mat_t L, fmpz_spar /* Initialize permutations */ remr = M->r, remc = M->c; - for (r = 0; rr; ++r) + for (r = 0; r < M->r; ++r) { if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for (c = 0; cc; ++c) + for (c = 0; c < M->c; ++c) { if (!UT->cols[c].num) Q[c] = --remc; else Q[c] = -1; diff --git a/fmpz_sparse_mat/gram.c b/fmpz_sparse_mat/gram.c index dd76433a1a..374f70b2fc 100644 --- a/fmpz_sparse_mat/gram.c +++ b/fmpz_sparse_mat/gram.c @@ -15,9 +15,9 @@ void fmpz_sparse_mat_gram(fmpz_mat_t B, const fmpz_sparse_mat_t M) { slong i, j; - if(M->r == 0) fmpz_mat_zero(B); + if (M->r == 0) fmpz_mat_zero(B); else - for(i = 0; i < M->r; i++) - for(j = 0; j < M->r; j++) + for (i = 0; i < M->r; i++) + for (j = 0; j < M->r; j++) fmpz_sparse_vec_dot(&B->rows[i][j], &M->rows[i], &M->rows[j]); } diff --git a/fmpz_sparse_mat/hnf_classical.c b/fmpz_sparse_mat/hnf_classical.c index dc0d9c00e8..cc4fecf08b 100644 --- a/fmpz_sparse_mat/hnf_classical.c +++ b/fmpz_sparse_mat/hnf_classical.c @@ -41,7 +41,7 @@ fmpz_sparse_mat_hnf_classical(fmpz_sparse_mat_t M) for (rank = pc = 0; pc < M->c; ++pc) { hcol = &MT->cols[pc]; nnz = hcol->num; - if(!nnz) continue; + if (!nnz) continue; pr = next_pr = -1, next_nnp = nnz, npp = 0; do @@ -53,9 +53,9 @@ fmpz_sparse_mat_hnf_classical(fmpz_sparse_mat_t M) r = (pr == -1) ? hcol->keys[i] : irows[i]; if (pr >= 0) /* Reduce row r by row pr */ { - if(_fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r)) + if (_fmpz_sparse_mat_with_transpose_gauss_elim(MT, pr, r)) { - if(M->rows[r].nnz == 0) P[r] = --remr; + if (M->rows[r].nnz == 0) P[r] = --remr; continue; } } @@ -67,7 +67,8 @@ fmpz_sparse_mat_hnf_classical(fmpz_sparse_mat_t M) /* Either add r (back) to irows or make it the next pivot row */ - if (next_pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, next_pr).val) >= 0) { + if (next_pr >= 0 && fmpz_cmpabs(LT(M, r).val, LT(M, next_pr).val) >= 0) + { irows[next_nnp++] = r; continue; } diff --git a/fmpz_sparse_mat/hnf_minors.c b/fmpz_sparse_mat/hnf_minors.c index 22c81bfb36..b12c25f686 100644 --- a/fmpz_sparse_mat/hnf_minors.c +++ b/fmpz_sparse_mat/hnf_minors.c @@ -83,7 +83,7 @@ fmpz_sparse_mat_hnf_minors(fmpz_sparse_mat_t M) } /* Deal with any remaining rows */ - for(r = 0; r < M->r; ++r) + for (r = 0; r < M->r; ++r) { if (P[r] >= 0) continue; diff --git a/fmpz_sparse_mat/hnf_modular.c b/fmpz_sparse_mat/hnf_modular.c index 36fdc1cc97..bb10c1f580 100644 --- a/fmpz_sparse_mat/hnf_modular.c +++ b/fmpz_sparse_mat/hnf_modular.c @@ -46,7 +46,7 @@ fmpz_sparse_mat_hnf_modular(fmpz_sparse_mat_t M, const fmpz_t det) for (rank = pc = 0; pc < M->c; ++pc) { hcol = &MT->cols[pc]; nnz = hcol->num; - if(!nnz) continue; + if (!nnz) continue; irows = flint_realloc(irows, nnz*sizeof(*irows)); pr = -1, nnp = 0, npp = 0; @@ -66,7 +66,7 @@ fmpz_sparse_mat_hnf_modular(fmpz_sparse_mat_t M, const fmpz_t det) pr = r; } } - if(pr == -1) + if (pr == -1) { /* Set pivot col in some non-pivot row to rem_det */ for (pr = 0; pr < M->r; ++pr) diff --git a/fmpz_sparse_mat/hnf_pernet_stein.c b/fmpz_sparse_mat/hnf_pernet_stein.c new file mode 100644 index 0000000000..c97eb6d522 --- /dev/null +++ b/fmpz_sparse_mat/hnf_pernet_stein.c @@ -0,0 +1,637 @@ +/* + Copyright (C) 2014, 2015 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_mat.h" +#include "fmpq_mat.h" +#include "perm.h" + +#if 0 + +static void +add_columns(fmpz_mat_t H, const fmpz_mat_t B, const fmpz_mat_t H1, flint_rand_t state) +{ + int neg; + slong i, j, n, bits; + fmpz_t den, tmp, one; + fmpq_t num, alpha; + fmpz_mat_t Bu, B1, cols, k; + fmpq_mat_t H1_q, cols_q, x; + + n = B->r; + + fmpz_mat_init(Bu, n, n); + fmpz_mat_init(B1, n - 1, n); + fmpz_mat_init(cols, n, B->c - n); + fmpz_mat_init(k, n, 1); + fmpq_mat_init(x, n, B->c - n); + fmpq_mat_init(cols_q, n, B->c - n); + fmpq_mat_init(H1_q, n, n); + + for (i = 0; i < n; i++) + for (j = 0; j < cols->c; j++) + fmpz_set(fmpz_mat_entry(cols, i, j), fmpz_mat_entry(B, i, n + j)); + for (i = 0; i < n - 1; i++) + { + for (j = 0; j < n; j++) + { + fmpz_set(fmpz_mat_entry(Bu, i, j), fmpz_mat_entry(B, i, j)); + fmpz_set(fmpz_mat_entry(B1, i, j), fmpz_mat_entry(B, i, j)); + } + } + + /* find kernel basis vector */ + if (fmpz_mat_nullspace(k, B1) != 1) + { + flint_printf("Exception (fmpz_mat_hnf_pernet_stein). " + "Nullspace was not dimension one.\n"); + flint_abort(); + } + + bits = fmpz_mat_max_bits(B1); + if (bits < 0) + bits = -bits; + + fmpz_mat_clear(B1); + + fmpz_init(tmp); + + /* set the last row of Bu to be random, such that Bu is nonsingular */ + while (fmpz_is_zero(tmp)) + { + _fmpz_vec_randtest(Bu->rows[n - 1], state, n, bits); + + fmpz_zero(tmp); + for (j = 0; j < n; j++) + fmpz_addmul(tmp, fmpz_mat_entry(Bu, n - 1, j), + fmpz_mat_entry(k, j, 0)); + } + fmpz_clear(tmp); + + /* solve Bu*x = cols */ + if (!fmpq_mat_solve_fmpz_mat(x, Bu, cols)) + { + flint_printf("Exception (fmpz_mat_hnf_pernet_stein). " + "Singular input matrix for solve."); + flint_abort(); + } + + /* fix final row */ + fmpq_init(num); + fmpz_init(den); + fmpq_init(alpha); + fmpz_init(one); + fmpz_one(one); + + /* compute denominator */ + for (i = 0; i < n; i++) + fmpz_addmul(den, fmpz_mat_entry(B, n - 1, i), fmpz_mat_entry(k, i, 0)); + neg = (fmpz_sgn(den) < 0); + if (neg) + fmpz_neg(den, den); + + for (j = 0; j < B->c - H1->c; j++) + { + fmpq_zero(num); + for (i = 0; i < n; i++) + { + _fmpq_addmul(fmpq_numref(num), fmpq_denref(num), + fmpz_mat_entry(B, n - 1, i), one, + fmpq_mat_entry_num(x, i, j), + fmpq_mat_entry_den(x, i, j)); + } + _fmpq_sub(fmpq_numref(alpha), fmpq_denref(alpha), + fmpz_mat_entry(B, n - 1, n + j), one, + fmpq_numref(num), fmpq_denref(num)); + + _fmpq_mul(fmpq_numref(alpha), fmpq_denref(alpha), + fmpq_numref(alpha), fmpq_denref(alpha), one, den); + if (neg) + fmpq_neg(alpha, alpha); + + /* x_i += alpha*k */ + for (i = 0; i < n; i++) + { + _fmpq_addmul(fmpq_mat_entry_num(x, i, j), + fmpq_mat_entry_den(x, i, j), fmpq_numref(alpha), + fmpq_denref(alpha), fmpz_mat_entry(k, i, 0), one); + } + } + + fmpq_clear(num); + fmpz_clear(den); + fmpz_clear(one); + fmpq_clear(alpha); + + /* set cols = H1*x and place in position in H */ + fmpq_mat_set_fmpz_mat(H1_q, H1); + fmpq_mat_mul(cols_q, H1_q, x); + fmpq_mat_get_fmpz_mat(cols, cols_q); + for (i = 0; i < n; i++) + { + for (j = 0; j < n; j++) + fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H1, i, j)); + for (j = n; j < H->c; j++) + fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(cols, i, j - n)); + } + + fmpq_mat_clear(H1_q); + fmpq_mat_clear(x); + fmpq_mat_clear(cols_q); + fmpz_mat_clear(k); + fmpz_mat_clear(cols); + fmpz_mat_clear(Bu); +} + +/* takes input matrix H with rows 0 to start_row - 1 in HNF to a HNF matrix */ +static void +add_rows(fmpz_mat_t H, slong start_row, slong *pivots, slong num_pivots) +{ + slong i, i2, j, j2, new_row, row; + fmpz_t b, d, u, v, r1d, r2d, q; + + fmpz_init(b); + fmpz_init(d); + fmpz_init(u); + fmpz_init(v); + fmpz_init(r1d); + fmpz_init(r2d); + fmpz_init(q); + + for (row = start_row; row < H->r; row++) + { + /* reduce row to be added with existing */ + for (i = j = 0; i < num_pivots; i++) + { + /* check if added row can still be reduced */ + for (; j < pivots[i]; j++) + if (!fmpz_is_zero(fmpz_mat_entry(H, row, j))) + break; + if (j < pivots[i]) + break; + if (fmpz_is_zero(fmpz_mat_entry(H, row, j))) + continue; + fmpz_xgcd(d, u, v, fmpz_mat_entry(H, i, j), + fmpz_mat_entry(H, row, j)); + fmpz_divexact(r1d, fmpz_mat_entry(H, i, j), d); + fmpz_divexact(r2d, fmpz_mat_entry(H, row, j), d); + for (j2 = j; j2 < H->c; j2++) + { + fmpz_mul(b, u, fmpz_mat_entry(H, i, j2)); + fmpz_addmul(b, v, fmpz_mat_entry(H, row, j2)); + fmpz_mul(fmpz_mat_entry(H, row, j2), r1d, + fmpz_mat_entry(H, row, j2)); + fmpz_submul(fmpz_mat_entry(H, row, j2), r2d, + fmpz_mat_entry(H, i, j2)); + fmpz_set(fmpz_mat_entry(H, i, j2), b); + } + } + + /* find first non-zero entry of the added row */ + for (j = 0; j < H->c && fmpz_is_zero(fmpz_mat_entry(H, row, j)); j++) ; + new_row = row; + if (j != H->c) /* last row non-zero, move to correct position */ + { + if (fmpz_sgn(fmpz_mat_entry(H, row, j)) < 0) + { + for (j2 = j; j2 < H->c; j2++) + { + fmpz_neg(fmpz_mat_entry(H, row, j2), + fmpz_mat_entry(H, row, j2)); + } + } + do + { + if (new_row < row) + fmpz_mat_swap_rows(H, NULL, new_row, new_row + 1); + if (new_row == 0) + break; + new_row--; + for (j2 = 0; j2 < H->c && + fmpz_is_zero(fmpz_mat_entry(H, new_row, j2)); j2++) ; + } + while (j2 > j); + } + + /* recompute pivots */ + for (i = new_row, j = 0; i <= row && i < H->c; i++, j++) + { + for (; j < H->c && fmpz_is_zero(fmpz_mat_entry(H, i, j)); j++) ; + if (j == H->c) + break; + pivots[i] = j; + num_pivots = i + 1; + } + + /* reduce above pivot entries */ + for (i = 0; i < num_pivots; i++) + { + for (i2 = 0; i2 < i; i2++) + { + fmpz_fdiv_q(q, fmpz_mat_entry(H, i2, pivots[i]), + fmpz_mat_entry(H, i, pivots[i])); + for (j2 = pivots[i]; j2 < H->c; j2++) + { + fmpz_submul(fmpz_mat_entry(H, i2, j2), q, + fmpz_mat_entry(H, i, j2)); + } + } + } + } + + fmpz_clear(q); + fmpz_clear(r2d); + fmpz_clear(r1d); + fmpz_clear(v); + fmpz_clear(u); + fmpz_clear(d); + fmpz_clear(b); +} + +static void +double_det(fmpz_t d1, fmpz_t d2, const fmpz_mat_t B, const fmpz_mat_t c, + const fmpz_mat_t d) +{ + slong i, j, n; + slong *P; + mp_limb_t p, u1mod, u2mod, v1mod, v2mod; + fmpz_t bound, prod, s1, s2, t, u1, u2, v1, v2; + fmpz_mat_t dt, Bt; + fmpq_t tmpq; + fmpq_mat_t x; + nmod_mat_t Btmod; + + n = B->c; + + fmpz_mat_init(dt, n, 1); + fmpz_mat_init(Bt, n, n); + fmpq_mat_init(x, n, 1); + + for (i = 0; i < n; i++) + { + for (j = 0; j < n - 1; j++) + fmpz_set(fmpz_mat_entry(Bt, i, j), fmpz_mat_entry(B, j, i)); + fmpz_set(fmpz_mat_entry(Bt, i, n - 1), fmpz_mat_entry(c, 0, i)); + } + + /* solve B^Tx = d^T */ + fmpz_mat_transpose(dt, d); + fmpq_mat_solve_fmpz_mat(x, Bt, dt); + + if (!fmpq_is_zero(fmpq_mat_entry(x, n - 1, 0))) + { + fmpz_init(bound); + fmpz_init(prod); + fmpz_init(t); + fmpz_init(s1); + fmpz_init(s2); + fmpz_init(u1); + fmpz_init(u2); + fmpz_init(v1); + fmpz_init(v2); + + /* compute lcm of denominators of vectors x and y */ + fmpq_init(tmpq); + fmpz_one(u1); + fmpz_one(u2); + for (i = 0; i < n - 1; i++) + { + fmpz_lcm(u1, u1, fmpq_mat_entry_den(x, i, 0)); + fmpq_div(tmpq, fmpq_mat_entry(x, i, 0), + fmpq_mat_entry(x, n - 1, 0)); + fmpz_lcm(u2, u2, fmpq_denref(tmpq)); + } + fmpz_lcm(u1, u1, fmpq_mat_entry_den(x, n - 1, 0)); + fmpq_inv(tmpq, fmpq_mat_entry(x, n - 1, 0)); + fmpz_lcm(u2, u2, fmpq_denref(tmpq)); + fmpq_clear(tmpq); + + /* compute Hadamard bounds */ + fmpz_one(bound); + for (j = 0; j < n - 1; j++) + { + fmpz_zero(s1); + for (i = 0; i < n; i++) + fmpz_addmul(s1, fmpz_mat_entry(Bt, i, j), + fmpz_mat_entry(Bt, i, j)); + fmpz_sqrtrem(s1, t, s1); + if (!fmpz_is_zero(t)) + fmpz_add_ui(s1, s1, UWORD(1)); + fmpz_mul(bound, bound, s1); + } + fmpz_zero(s1); + fmpz_zero(s2); + for (j = 0; j < n; j++) + { + fmpz_addmul(s1, fmpz_mat_entry(c, 0, j), fmpz_mat_entry(c, 0, j)); + fmpz_addmul(s2, fmpz_mat_entry(d, 0, j), fmpz_mat_entry(d, 0, j)); + } + fmpz_sqrtrem(s1, t, s1); + if (!fmpz_is_zero(t)) + fmpz_add_ui(s1, s1, UWORD(1)); + fmpz_sqrtrem(s2, t, s2); + if (!fmpz_is_zero(t)) + fmpz_add_ui(s2, s2, UWORD(1)); + fmpz_mul(s1, s1, bound); + fmpz_mul(s2, s2, bound); + fmpz_cdiv_q(s1, s1, u1); + fmpz_cdiv_q(s2, s2, u2); + if (fmpz_cmp(s1, s2) > 0) + fmpz_set(bound, s1); + else + fmpz_set(bound, s2); + fmpz_mul_ui(bound, bound, UWORD(2)); + + fmpz_one(prod); + P = _perm_init(n); + nmod_mat_init(Btmod, n, n, 2); + p = UWORD(1) << NMOD_MAT_OPTIMAL_MODULUS_BITS; + /* compute determinants divided by u1 and u2 */ + while (fmpz_cmp(prod, bound) <= 0) + { + p = n_nextprime(p, 0); + u1mod = fmpz_fdiv_ui(u1, p); + u2mod = fmpz_fdiv_ui(u2, p); + if (!(u1mod || u2mod)) + continue; + _nmod_mat_set_mod(Btmod, p); + for (i = 0; i < n; i++) + { + for (j = 0; j < n - 1; j++) + nmod_mat_entry(Btmod, i, j) = + fmpz_fdiv_ui(fmpz_mat_entry(B, j, i), p); + nmod_mat_entry(Btmod, i, n - 1) = + fmpz_fdiv_ui(fmpz_mat_entry(c, 0, i), p); + } + nmod_mat_lu(P, Btmod, 0); + v1mod = UWORD(1); + for (i = 0; i < n; i++) + v1mod = n_mulmod2_preinv(v1mod, nmod_mat_entry(Btmod, i, i), p, + Btmod->mod.ninv); + if (_perm_parity(P, n) == 1) + v1mod = nmod_neg(v1mod, Btmod->mod); + + for (i = 0; i < n; i++) + { + for (j = 0; j < n - 1; j++) + nmod_mat_entry(Btmod, i, j) = + fmpz_fdiv_ui(fmpz_mat_entry(B, j, i), p); + nmod_mat_entry(Btmod, i, n - 1) = + fmpz_fdiv_ui(fmpz_mat_entry(d, 0, i), p); + } + nmod_mat_lu(P, Btmod, 0); + v2mod = UWORD(1); + for (i = 0; i < n; i++) + v2mod = n_mulmod2_preinv(v2mod, nmod_mat_entry(Btmod, i, i), p, + Btmod->mod.ninv); + if (_perm_parity(P, n) == 1) + v2mod = nmod_neg(v2mod, Btmod->mod); + + v1mod = n_mulmod2_preinv(v1mod, n_invmod(u1mod, p), p, + Btmod->mod.ninv); + v2mod = n_mulmod2_preinv(v2mod, n_invmod(u2mod, p), p, + Btmod->mod.ninv); + fmpz_CRT_ui(v1, v1, prod, v1mod, p, 1); + fmpz_CRT_ui(v2, v2, prod, v2mod, p, 1); + fmpz_mul_ui(prod, prod, p); + } + + fmpz_mul(d1, u1, v1); + fmpz_mul(d2, u2, v2); + + fmpz_clear(bound); + fmpz_clear(prod); + fmpz_clear(s1); + fmpz_clear(s2); + fmpz_clear(u1); + fmpz_clear(u2); + fmpz_clear(v1); + fmpz_clear(v2); + fmpz_clear(t); + _perm_clear(P); + nmod_mat_clear(Btmod); + } + else /* can't use the clever method above so naively compute both dets */ + { + fmpz_mat_det(d1, Bt); + for (j = 0; j < n; j++) + fmpz_set(fmpz_mat_entry(Bt, j, n - 1), fmpz_mat_entry(d, 0, j)); + fmpz_mat_det(d2, Bt); + } + + fmpz_mat_clear(dt); + fmpz_mat_clear(Bt); + fmpq_mat_clear(x); +} + +void +fmpz_mat_hnf_pernet_stein(fmpz_mat_t H, const fmpz_mat_t A, flint_rand_t state) +{ + slong i, j, m, n, p, r, *P, *pivots, finished; + fmpz_t d1, d2, g, s, t; + fmpz_mat_t c, d, B, C, H1, H2, H3; + nmod_mat_t Amod; + + m = fmpz_mat_nrows(A); + n = fmpz_mat_ncols(A); + + if (m == 0 || n == 0) + return; + + /* find permutation so we can ensure first rows of H are nonsingular */ + P = _perm_init(m); + pivots = _perm_init(n); + + finished = 0; + + while (!finished) + { + p = n_randprime(state, NMOD_MAT_OPTIMAL_MODULUS_BITS, 1); + nmod_mat_init(Amod, m, n, p); + + fmpz_mat_get_nmod_mat(Amod, A); + r = _nmod_mat_rref(Amod, pivots, P); + + nmod_mat_clear(Amod); + + /* rank is zero so matrix is possibly zero too */ + if (r == 0) + { + if (fmpz_mat_is_zero(A)) + { + fmpz_mat_zero(H); + _perm_clear(P); + _perm_clear(pivots); + return; + } + continue; + } + + /* if A has full column rank we might wish to use minors based hnf */ + if (r == n && n < 52) + { + slong b = fmpz_mat_max_bits(A), cutoff = 52; + if (b < 0) + b = -b; + + if (b <= 8) + cutoff = 35; + else if (b <= 32) + cutoff = 44; + else if (b <= 256) + cutoff = 48; + + if (n < cutoff) + { + fmpz_mat_hnf_minors(H, A); + _perm_clear(P); + _perm_clear(pivots); + return; + } + } + + fmpz_mat_init(c, 1, r - 1); + fmpz_mat_init(d, 1, r - 1); + fmpz_mat_init(B, r - 2, r - 1); + fmpz_mat_init(C, r - 1, r - 1); + + for (i = 0; i < r - 2; i++) + { + for (j = 0; j < r - 1; j++) + { + fmpz_set(fmpz_mat_entry(B, i, j), + fmpz_mat_entry(A, P[i], pivots[j])); + fmpz_set(fmpz_mat_entry(C, i, j), + fmpz_mat_entry(A, P[i], pivots[j])); + } + fmpz_set(fmpz_mat_entry(C, i, r - 1), + fmpz_mat_entry(A, P[i], pivots[r - 1])); + } + for (j = 0; j < r - 1; j++) + { + fmpz_set(fmpz_mat_entry(c, 0, j), + fmpz_mat_entry(A, P[r - 2], pivots[j])); + fmpz_set(fmpz_mat_entry(d, 0, j), + fmpz_mat_entry(A, P[r - 1], pivots[j])); + } + + fmpz_init(g); + fmpz_init(s); + fmpz_init(t); + + /* if rank is too low leave g = 0 so we don't try to decompose later */ + if (r > 2) + { + fmpz_init(d1); + fmpz_init(d2); + + double_det(d1, d2, B, c, d); + fmpz_xgcd(g, s, t, d1, d2); + + for (j = 0; j < r - 1; j++) + { + fmpz_mul(fmpz_mat_entry(C, r - 2, j), s, + fmpz_mat_entry(A, P[r - 2], pivots[j])); + fmpz_addmul(fmpz_mat_entry(C, r - 2, j), t, + fmpz_mat_entry(A, P[r - 1], pivots[j])); + } + + fmpz_clear(d2); + fmpz_clear(d1); + } + + if (!fmpz_is_zero(g)) /* chosen matrix invertible */ + { + fmpz_mat_init(H1, r - 1, r - 1); + + if (COEFF_IS_MPZ(*g) && C->r > 3) /* if g is too big, recurse */ + fmpz_mat_hnf_pernet_stein(H1, C, state); + else /* use modulo determinant algorithm to compute HNF of C */ + fmpz_mat_hnf_modular(H1, C, g); + + fmpz_mat_clear(B); + fmpz_mat_init(B, r - 1, n); + + for (j = 0; j < n; j++) + { + for (i = 0; i < r - 2; i++) + fmpz_set(fmpz_mat_entry(B, i, j), + fmpz_mat_entry(A, P[i], pivots[j])); + fmpz_mul(fmpz_mat_entry(B, r - 2, j), s, + fmpz_mat_entry(A, P[r - 2], pivots[j])); + fmpz_addmul(fmpz_mat_entry(B, r - 2, j), t, + fmpz_mat_entry(A, P[r - 1], pivots[j])); + } + + fmpz_mat_init(H2, r - 1, n); + fmpz_mat_init(H3, m + 1, n); + + add_columns(H2, B, H1, state); + + for (i = 0; i < r - 1; i++) + for (j = 0; j < n; j++) + fmpz_set(fmpz_mat_entry(H3, i, pivots[j]), + fmpz_mat_entry(H2, i, j)); + + for (i = 1; i <= m - r + 2; i++) + for (j = 0; j < n; j++) + fmpz_set(fmpz_mat_entry(H3, H3->r - i, j), + fmpz_mat_entry(A, P[m - i], j)); + + /* check the pivots of H3 are as expected */ + for (i = 0; i < r - 1; i++) + { + for (j = 0; j < H3->c && fmpz_is_zero(fmpz_mat_entry(H3, i, j)); j++); + if (pivots[i] != j) + break; + } + + /* the pivots were as expected so our choice of prime was ok */ + if (i == r - 1) + { + /* add final rows in */ + add_rows(H3, r - 1, pivots, r - 1); + + /* fill H with HNF */ + for (i = 0; i < m; i++) + for (j = 0; j < n; j++) + fmpz_set(fmpz_mat_entry(H, i, j), fmpz_mat_entry(H3, i, j)); + + finished = 1; + } + /* otherwise we must restart as our random prime gave us incorrect pivots */ + + fmpz_mat_clear(H1); + fmpz_mat_clear(H2); + fmpz_mat_clear(H3); + } + else + { + if (r == n) /* if A has full column rank we can use minors based hnf */ + fmpz_mat_hnf_minors(H, A); + else + fmpz_mat_hnf_classical(H, A); + finished = 1; + } + + fmpz_clear(t); + fmpz_clear(s); + fmpz_clear(g); + fmpz_mat_clear(C); + fmpz_mat_clear(B); + fmpz_mat_clear(c); + fmpz_mat_clear(d); + } + + _perm_clear(P); + _perm_clear(pivots); +} + +#endif \ No newline at end of file diff --git a/fmpz_sparse_mat/hnf_xgcd.c b/fmpz_sparse_mat/hnf_xgcd.c index a1af9b4eb8..eb045eecf8 100644 --- a/fmpz_sparse_mat/hnf_xgcd.c +++ b/fmpz_sparse_mat/hnf_xgcd.c @@ -44,7 +44,7 @@ slong fmpz_sparse_mat_hnf_xgcd(fmpz_sparse_mat_t M) for (rank = pc = 0; pc < M->c; ++pc) { hcol = &MT->cols[pc]; nnz = hcol->num; - if(!nnz) continue; + if (!nnz) continue; pr = -1, nnp = 0, npp = 0; for (i = 0; i < nnz; ++i) @@ -60,14 +60,14 @@ slong fmpz_sparse_mat_hnf_xgcd(fmpz_sparse_mat_t M) pr = r; } } - if(pr == -1) continue; + if (pr == -1) continue; /* Eliminate larger, non-pivot rows */ for (i = 0; i < nnp; ++i) { r = irows[i]; _fmpz_sparse_mat_with_transpose_gauss_elim_ext(MT, pr, r); - if(M->rows[r].nnz == 0) P[r] = --remr; + if (M->rows[r].nnz == 0) P[r] = --remr; } if (fmpz_sgn(LT(M, pr).val) < 0) diff --git a/fmpz_sparse_mat/snf.c b/fmpz_sparse_mat/snf.c new file mode 100644 index 0000000000..e733132b4e --- /dev/null +++ b/fmpz_sparse_mat/snf.c @@ -0,0 +1,50 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_mat.h" + +void +fmpz_sparse_mat_snf(fmpz_mat_t S, const fmpz_mat_t A) +{ + fmpz_t det; + slong m = A->r, n = A->c, b = fmpz_mat_max_bits(A), cutoff = 9; + + if (b <= 2) + cutoff = 15; + else if (b <= 4) + cutoff = 13; + else if (b <= 8) + cutoff = 13; + else if (b <= 16) + cutoff = 11; + else if (b <= 32) + cutoff = 11; + else if (b <= 64) + cutoff = 10; + + if (FLINT_MAX(m, n) < cutoff || m != n) + fmpz_mat_snf_kannan_bachem(S, A); + else + { + fmpz_init(det); + fmpz_mat_det(det, A); + if (!fmpz_is_zero(det)) + { + fmpz_abs(det, det); + fmpz_mat_snf_iliopoulos(S, A, det); + } + else + { + fmpz_mat_snf_kannan_bachem(S, A); + } + fmpz_clear(det); + } +} diff --git a/fmpz_sparse_mat/snf_diagonal.c b/fmpz_sparse_mat/snf_diagonal.c new file mode 100644 index 0000000000..21808d358b --- /dev/null +++ b/fmpz_sparse_mat/snf_diagonal.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_mat.h" + +/* sets a to gcd(a,b) and b to lcm(a,b) using temporary fmpz_t t */ +static void _gcdlcm(fmpz_t t, fmpz_t a, fmpz_t b) +{ + if (fmpz_equal(a, b)) return; + fmpz_gcd(t, a, b); + fmpz_divexact(b, b, t); + fmpz_mul(b, b, a); + fmpz_set(a, t); +} + +void fmpz_sparse_mat_snf_diagonal(fmpz_mat_t S, const fmpz_mat_t A) +{ + fmpz_t t; + slong i, j, n = FLINT_MIN(A->r, A->c); + + fmpz_init(t); + fmpz_mat_set(S, A); + for (i = 0; i < n; i++) + fmpz_abs(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i)); + for (j = n - 1; j >= 0; j--) + { + for (i = 0; i < j; i++) + { + _gcdlcm(t, fmpz_mat_entry(S, i, i), + fmpz_mat_entry(S, i + 1, i + 1)); + } + } + fmpz_clear(t); +} diff --git a/fmpz_sparse_mat/snf_iliopoulos.c b/fmpz_sparse_mat/snf_iliopoulos.c new file mode 100644 index 0000000000..889f08a7f1 --- /dev/null +++ b/fmpz_sparse_mat/snf_iliopoulos.c @@ -0,0 +1,237 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_mat.h" + +static void _eliminate_col(fmpz_mat_t S, slong i, const fmpz_t mod) +{ + slong j, k, m, n; + fmpz * t; + fmpz_t b, g, u, v, r1g, r2g; + + m = S->r; + n = S->c; + + if (i == m - 1) + { + fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); + return; + } + + fmpz_init(g); + fmpz_init(u); + fmpz_init(b); + fmpz_init(r1g); + fmpz_init(r2g); + + if (!fmpz_is_zero(fmpz_mat_entry(S, i, i))) + { + fmpz_init(v); + + fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i + 1, i), + fmpz_mat_entry(S, i, i)); + fmpz_divexact(r1g, fmpz_mat_entry(S, i + 1, i), g); + fmpz_divexact(r2g, fmpz_mat_entry(S, i, i), g); + for (j = i; j < n; j++) + { + fmpz_mul(b, u, fmpz_mat_entry(S, i + 1, j)); + fmpz_addmul(b, v, fmpz_mat_entry(S, i, j)); + fmpz_mul(fmpz_mat_entry(S, i, j), r1g, + fmpz_mat_entry(S, i, j)); + fmpz_submul(fmpz_mat_entry(S, i, j), r2g, + fmpz_mat_entry(S, i + 1, j)); + fmpz_set(fmpz_mat_entry(S, i + 1, j), b); + } + + fmpz_clear(v); + } + + /* compute extended gcd of entries in column i */ + t = _fmpz_vec_init(m - i - 1); + + fmpz_set(g, fmpz_mat_entry(S, i + 1, i)); + fmpz_one(t); + for (j = 2; j < m - i; j++) + { + fmpz_xgcd(g, u, t + j - 1, g, fmpz_mat_entry(S, i + j, i)); + for (k = 0; k < j - 1; k++) + fmpz_mul(t + k, t + k, u); + } + + /* set row i to have gcd in col i */ + for (k = i + 1; k < m; k++) + { + fmpz_mod(t + k - i - 1, t + k - i - 1, mod); + for (j = i; j < n; j++) + fmpz_addmul(fmpz_mat_entry(S, i, j), t + k - i - 1, + fmpz_mat_entry(S, k, j)); + } + + _fmpz_vec_clear(t, m - i - 1); + + /* reduce each row k with row i */ + if (!fmpz_is_zero(g)) /* if g = 0 then don't need to reduce */ + { + for (k = i + 1; k < m; k++) + { + fmpz_divexact(r1g, fmpz_mat_entry(S, k, i), g); + fmpz_neg(r1g, r1g); + for (j = i; j < n; j++) + fmpz_addmul(fmpz_mat_entry(S, k, j), r1g, + fmpz_mat_entry(S, i, j)); + } + for (k = i + 1; k < m; k++) + fmpz_mod(fmpz_mat_entry(S, k, i), fmpz_mat_entry(S, k, i), mod); + } + for (j = i; j < m; j++) + for (k = i + 1; k < n; k++) + fmpz_fdiv_r(fmpz_mat_entry(S, j, k), fmpz_mat_entry(S, j, k), mod); + fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); + + fmpz_clear(b); + fmpz_clear(g); + fmpz_clear(u); + fmpz_clear(r1g); + fmpz_clear(r2g); +} + +static void _eliminate_row(fmpz_mat_t S, slong i, const fmpz_t mod) +{ + slong j, k, m, n; + fmpz * t; + fmpz_t b, g, u, v, r1g, r2g, halfmod; + + m = S->r; + n = S->c; + + if (i == n - 1) + { + fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); + return; + } + + fmpz_init(g); + fmpz_init(u); + fmpz_init(b); + fmpz_init(r1g); + fmpz_init(r2g); + fmpz_init(halfmod); + fmpz_fdiv_q_2exp(halfmod, mod, 1); + + if (!fmpz_is_zero(fmpz_mat_entry(S, i, i))) + { + fmpz_init(v); + + fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i, i + 1), + fmpz_mat_entry(S, i, i)); + fmpz_divexact(r1g, fmpz_mat_entry(S, i, i + 1), g); + fmpz_divexact(r2g, fmpz_mat_entry(S, i, i), g); + for (j = i; j < m; j++) + { + fmpz_mul(b, u, fmpz_mat_entry(S, j, i + 1)); + fmpz_addmul(b, v, fmpz_mat_entry(S, j, i)); + fmpz_mul(fmpz_mat_entry(S, j, i), r1g, + fmpz_mat_entry(S, j, i)); + fmpz_submul(fmpz_mat_entry(S, j, i), r2g, + fmpz_mat_entry(S, j, i + 1)); + fmpz_set(fmpz_mat_entry(S, j, i + 1), b); + } + + fmpz_clear(v); + } + + /* compute extended gcd of entries in row i */ + t = _fmpz_vec_init(n - i - 1); + + fmpz_set(g, fmpz_mat_entry(S, i, i + 1)); + fmpz_one(t); + for (j = 2; j < n - i; j++) + { + fmpz_xgcd(g, u, t + j - 1, g, fmpz_mat_entry(S, i, i + j)); + for (k = 0; k < j - 1; k++) + fmpz_mul(t + k, t + k, u); + } + + /* reduce col i to have gcd in row i */ + for (k = i + 1; k < n; k++) + { + fmpz_mod(t + k - i - 1, t + k - i - 1, mod); + for (j = i; j < m; j++) + fmpz_addmul(fmpz_mat_entry(S, j, i), t + k - i - 1, + fmpz_mat_entry(S, j, k)); + } + + _fmpz_vec_clear(t, n - i - 1); + + /* reduce each col k with col i */ + if (!fmpz_is_zero(g)) /* if g = 0 then don't need to reduce */ + { + for (k = i + 1; k < n; k++) + { + fmpz_divexact(r1g, fmpz_mat_entry(S, i, k), g); + fmpz_neg(r1g, r1g); + for (j = i; j < m; j++) + fmpz_addmul(fmpz_mat_entry(S, j, k), r1g, + fmpz_mat_entry(S, j, i)); + } + } + for (j = i + 1; j < m; j++) + for (k = i; k < n; k++) + fmpz_fdiv_r(fmpz_mat_entry(S, j, k), fmpz_mat_entry(S, j, k), mod); + fmpz_gcd(fmpz_mat_entry(S, i, i), fmpz_mat_entry(S, i, i), mod); + + fmpz_clear(b); + fmpz_clear(g); + fmpz_clear(u); + fmpz_clear(r1g); + fmpz_clear(r2g); + fmpz_clear(halfmod); +} + +void fmpz_sparse_mat_snf_iliopoulos(fmpz_mat_t S, const fmpz_mat_t A, const fmpz_t mod) +{ + slong i, k, n; + int done; + + n = FLINT_MIN(A->c, A->r); + + fmpz_mat_set(S, A); + + for (i = 0; i < A->r; i++) + for (k = 0; k < A->c; k++) + fmpz_mod(fmpz_mat_entry(S, i, k), fmpz_mat_entry(S, i, k), mod); + + for (k = 0; k != n; k++) + { + do + { + _eliminate_row(S, k, mod); + _eliminate_col(S, k, mod); + done = 1; + if (fmpz_is_zero(fmpz_mat_entry(S, k, k))) + { + for (i = k + 1; i < A->c && done; i++) + done = fmpz_is_zero(fmpz_mat_entry(S, k, i)); + } + else + { + for (i = k + 1; i < A->c && done; i++) + done = fmpz_divisible(fmpz_mat_entry(S, k, i), + fmpz_mat_entry(S, k, k)); + } + } + while (!done); + for (i = k + 1; i < A->c; i++) + fmpz_zero(fmpz_mat_entry(S, k, i)); + } + + fmpz_mat_snf_diagonal(S, S); +} diff --git a/fmpz_sparse_mat/snf_kannan_bachem.c b/fmpz_sparse_mat/snf_kannan_bachem.c new file mode 100644 index 0000000000..d7669e8123 --- /dev/null +++ b/fmpz_sparse_mat/snf_kannan_bachem.c @@ -0,0 +1,137 @@ +/* + Copyright (C) 2014 Alex J. Best + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_mat.h" + +void fmpz_sparse_mat_snf_kannan_bachem(fmpz_mat_t S, const fmpz_mat_t A) +{ + slong i, j, k, d, m, n; + fmpz_t r1g, r2g, b, u, v, g; + m = A->r; + n = A->c; + d = FLINT_MIN(m, n); + fmpz_init(r1g); + fmpz_init(r2g); + fmpz_init(b); + fmpz_init(u); + fmpz_init(v); + fmpz_init(g); + + fmpz_mat_set(S, A); + + for (k = 0; k != d; k++) + { + int col_done; + do + { + /* clear column */ + for (i = k + 1; i != m; i++) + { + /* reduce row i - 1 with row i */ + if (fmpz_is_zero(fmpz_mat_entry(S, i - 1, k))) + continue; + if (fmpz_cmpabs(fmpz_mat_entry(S, i, k), + fmpz_mat_entry(S, i - 1, k)) == 0) + { + if (fmpz_equal(fmpz_mat_entry(S, i, k), + fmpz_mat_entry(S, i - 1, k))) + { + for (j = k; j != n; j++) + fmpz_sub(fmpz_mat_entry(S, i - 1, j), + fmpz_mat_entry(S, i - 1, j), + fmpz_mat_entry(S, i, j)); + } + else + { + for (j = k; j != n; j++) + fmpz_add(fmpz_mat_entry(S, i - 1, j), + fmpz_mat_entry(S, i - 1, j), + fmpz_mat_entry(S, i, j)); + } + continue; + } + fmpz_xgcd(g, u, v, fmpz_mat_entry(S, i, k), + fmpz_mat_entry(S, i - 1, k)); + fmpz_divexact(r2g, fmpz_mat_entry(S, i - 1, k), g); + fmpz_divexact(r1g, fmpz_mat_entry(S, i, k), g); + for (j = k; j != n; j++) + { + fmpz_mul(b, u, fmpz_mat_entry(S, i, j)); + fmpz_addmul(b, v, fmpz_mat_entry(S, i - 1, j)); + fmpz_mul(fmpz_mat_entry(S, i - 1, j), r1g, + fmpz_mat_entry(S, i - 1, j)); + fmpz_submul(fmpz_mat_entry(S, i - 1, j), r2g, + fmpz_mat_entry(S, i, j)); + fmpz_set(fmpz_mat_entry(S, i, j), b); + } + } + fmpz_mat_swap_rows(S, NULL, m - 1, k); + + /* clear row */ + for (j = k + 1; j != n; j++) + { + /* reduce col j with col k */ + if (fmpz_is_zero(fmpz_mat_entry(S, k, j))) + continue; + if (fmpz_cmpabs(fmpz_mat_entry(S, k, k), + fmpz_mat_entry(S, k, j)) == 0) + { + if (fmpz_equal(fmpz_mat_entry(S, k, k), + fmpz_mat_entry(S, k, j))) + { + for (i = k; i != m; i++) + fmpz_sub(fmpz_mat_entry(S, i, j), + fmpz_mat_entry(S, i, j), + fmpz_mat_entry(S, i, k)); + } + else + { + for (i = k; i != m; i++) + fmpz_add(fmpz_mat_entry(S, i, j), + fmpz_mat_entry(S, i, j), + fmpz_mat_entry(S, i, k)); + } + continue; + } + fmpz_xgcd(g, u, v, fmpz_mat_entry(S, k, k), + fmpz_mat_entry(S, k, j)); + fmpz_divexact(r2g, fmpz_mat_entry(S, k, j), g); + fmpz_divexact(r1g, fmpz_mat_entry(S, k, k), g); + for (i = k; i != m; i++) + { + fmpz_mul(b, u, fmpz_mat_entry(S, i, k)); + fmpz_addmul(b, v, fmpz_mat_entry(S, i, j)); + fmpz_mul(fmpz_mat_entry(S, i, j), r1g, + fmpz_mat_entry(S, i, j)); + fmpz_submul(fmpz_mat_entry(S, i, j), r2g, + fmpz_mat_entry(S, i, k)); + fmpz_set(fmpz_mat_entry(S, i, k), b); + } + } + col_done = 1; + for (i = 0; i != m; i++) + col_done &= (i == k) || fmpz_is_zero(fmpz_mat_entry(S, i, k)); + } + while (!col_done); + + if (fmpz_sgn(fmpz_mat_entry(S, k, k)) < 0) + fmpz_neg(fmpz_mat_entry(S, k, k), fmpz_mat_entry(S, k, k)); + } + + fmpz_clear(r2g); + fmpz_clear(r1g); + fmpz_clear(b); + fmpz_clear(u); + fmpz_clear(v); + fmpz_clear(g); + + fmpz_mat_snf_diagonal(S, S); +} diff --git a/fmpz_sparse_mat/solve_dixon.c b/fmpz_sparse_mat/solve_dixon.c index 3dec84fedc..bbaefd6583 100644 --- a/fmpz_sparse_mat/solve_dixon.c +++ b/fmpz_sparse_mat/solve_dixon.c @@ -126,7 +126,7 @@ int _fmpz_sparse_mat_solve_dixon(fmpz_mat_t X, fmpz_t mod, const fmpz_sparse_mat fmpz_init(D); fmpz_sparse_mat_solve_bound(N, D, A, B); p = find_good_prime_and_invert(Ainv, A, D); - if(p == 0) + if (p == 0) { fmpz_clear(N); fmpz_clear(D); diff --git a/fmpz_sparse_mat/strong_echelon_form_mod.c b/fmpz_sparse_mat/strong_echelon_form_mod.c index 6b1af06f42..91bcf857ed 100644 --- a/fmpz_sparse_mat/strong_echelon_form_mod.c +++ b/fmpz_sparse_mat/strong_echelon_form_mod.c @@ -18,13 +18,13 @@ static void scale_row(fmpz_sparse_mat_with_transpose_t MT, slong r, const fmpz_t mod) { fmpz_t g, a, b, n; - if(!fmpz_is_one(LT(MT->M, r).val)) + if (!fmpz_is_one(LT(MT->M, r).val)) { fmpz_init(g); fmpz_init(a); fmpz_init(b); fmpz_xgcd(g, a, b, LT(MT->M, r).val, mod); - if(!fmpz_is_one(g)) /* Need to lift a = (M[pr][pc]/g)^-1 mod N/g to a unit modulo N */ + if (!fmpz_is_one(g)) /* Need to lift a = (M[pr][pc]/g)^-1 mod N/g to a unit modulo N */ { fmpz_divexact(b, mod, g); fmpz_init_set(n, mod); @@ -68,7 +68,7 @@ fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) /* Final object must have at least as many rows as columns */ fmpz_sparse_vec_init(zero_vec); - while(M->r < M->c) fmpz_sparse_mat_append_row(M, zero_vec); + while (M->r < M->c) fmpz_sparse_mat_append_row(M, zero_vec); /* Need extra row to deal with final elimination */ fmpz_sparse_mat_append_row(M, zero_vec); @@ -99,7 +99,7 @@ fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) for (pc = 0; pc < M->c; ++pc) { hcol = &MT->cols[pc]; - if(!hcol->num) continue; + if (!hcol->num) continue; pr = -1, nnp = 0; /* Find incident row pr which is not a previous pivot and has minimal leading term */ @@ -116,7 +116,7 @@ fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) pr = r; } } - if(pr == -1) continue; /* Cannot perform elimination on this column (yet) */ + if (pr == -1) continue; /* Cannot perform elimination on this column (yet) */ scale_row(MT, pr, mod); Pr[pc] = pr, P[pr] = pc; @@ -154,11 +154,12 @@ fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) fmpz_sparse_vec_scalar_mod_fmpz(&M->rows[r], &M->rows[r], mod); ); - while(!fmpz_sparse_vec_is_zero(&M->rows[r])) + while (!fmpz_sparse_vec_is_zero(&M->rows[r])) { c = M->rows[r].entries[0].ind; /* If no previous pivot row exists, use this row */ - if (Pr[c] == -1) { + if (Pr[c] == -1) + { scale_row(MT, r, mod); Pr[c] = r; P[r] = c; break; @@ -166,7 +167,7 @@ fmpz_sparse_mat_strong_echelon_form_mod(fmpz_sparse_mat_t M, const fmpz_t mod) /* Otherwise, eliminate c using existing pivot */ _fmpz_sparse_mat_with_transpose_gauss_elim_ext_mod(MT, Pr[c], r, mod); - if(!fmpz_sparse_vec_is_zero(&M->rows[r]) && LT(M, r).ind == c) flint_abort(); + if (!fmpz_sparse_vec_is_zero(&M->rows[r]) && LT(M, r).ind == c) flint_abort(); } /* If row fully eliminated, add back to empty stock */ diff --git a/fmpz_sparse_mat/test/t-add.c b/fmpz_sparse_mat/test/t-add.c index f7ea70b5f7..48870e570d 100644 --- a/fmpz_sparse_mat/test/t-add.c +++ b/fmpz_sparse_mat/test/t-add.c @@ -27,7 +27,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); diff --git a/fmpz_sparse_mat/test/t-concat_horizontal.c b/fmpz_sparse_mat/test/t-concat_horizontal.c index 98281de443..083fd85b3e 100644 --- a/fmpz_sparse_mat/test/t-concat_horizontal.c +++ b/fmpz_sparse_mat/test/t-concat_horizontal.c @@ -29,7 +29,7 @@ int main(void) for (rep = 0; rep < nreps; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 20); c1 = n_randint(state, 20); c2 = n_randint(state, 20); diff --git a/fmpz_sparse_mat/test/t-concat_vertical.c b/fmpz_sparse_mat/test/t-concat_vertical.c index a42c8b20e0..0078dc0dd1 100644 --- a/fmpz_sparse_mat/test/t-concat_vertical.c +++ b/fmpz_sparse_mat/test/t-concat_vertical.c @@ -29,7 +29,7 @@ int main(void) for (rep = 0; rep < nreps; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r1 = n_randint(state, 100); r2 = n_randint(state, 100); c = n_randint(state, 100); diff --git a/fmpz_sparse_mat/test/t-construct.c b/fmpz_sparse_mat/test/t-construct.c index eb101e62b2..06fd3f06a6 100644 --- a/fmpz_sparse_mat/test/t-construct.c +++ b/fmpz_sparse_mat/test/t-construct.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = 1; /*n_randint(state, 10);*/ c = n_randint(state, 10); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-dense.c b/fmpz_sparse_mat/test/t-dense.c index 7d686d14c3..671bc1028d 100644 --- a/fmpz_sparse_mat/test/t-dense.c +++ b/fmpz_sparse_mat/test/t-dense.c @@ -30,7 +30,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 100); c = n_randint(state, 100); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-fflu.c b/fmpz_sparse_mat/test/t-fflu.c index 8925c83c24..a6d9fd0c36 100644 --- a/fmpz_sparse_mat/test/t-fflu.c +++ b/fmpz_sparse_mat/test/t-fflu.c @@ -50,18 +50,22 @@ main(void) rk = fmpz_sparse_mat_fflu(D, P, Q, L, U, M); /* Check that L is lower triangular (with ones on diagonal up to rank) */ - for (i = 0; i < r; ++i) { + for (i = 0; i < r; ++i) + { val = fmpz_sparse_vec_at(&L->rows[i], i); if (i < rk && (val == NULL || !fmpz_is_one(*val))) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } - for (j = 0; jrows[i].nnz; ++j) { - if (L->rows[i].entries[j].ind > i) { + for (j = 0; j < L->rows[i].nnz; ++j) + { + if (L->rows[i].entries[j].ind > i) + { flint_printf("FAIL: L not lower triangular\n"); abort(); } - if (L->rows[i].entries[j].ind >= rk) { + if (L->rows[i].entries[j].ind >= rk) + { flint_printf("FAIL: L not trivial past the rank\n"); flint_printf("rank = %wd\n", rk); flint_printf("L = "); @@ -71,7 +75,8 @@ main(void) } } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ - for (i = 0; i < r; ++i) { + for (i = 0; i < r; ++i) + { val = fmpz_sparse_vec_at(&U->rows[i], i); if (i < rk && (val == NULL || fmpz_is_zero(*val))) { @@ -83,8 +88,10 @@ main(void) flint_printf("FAIL: U not trivial past the rank\n"); abort(); } - for (j = 0; j < U->rows[i].nnz; ++j) { - if (U->rows[i].entries[j].ind < i) { + for (j = 0; j < U->rows[i].nnz; ++j) + { + if (U->rows[i].entries[j].ind < i) + { flint_printf("FAIL: U not upper triangular\n"); abort(); } @@ -104,7 +111,8 @@ main(void) fmpz_sparse_mat_to_dense(dU, U); fmpz_mat_mul(dLU, dL, dU); fmpz_sparse_mat_from_dense(LU, dLU); - if(!fmpz_sparse_mat_equal(M, LU)) { + if (!fmpz_sparse_mat_equal(M, LU)) + { flint_printf("FAIL: PDMQ != LU\n"); flint_printf("PDMQ="); fmpz_sparse_mat_print_pretty(M); diff --git a/fmpz_sparse_mat/test/t-init_clear.c b/fmpz_sparse_mat/test/t-init_clear.c index ee1b568a9e..a70e0d0a46 100644 --- a/fmpz_sparse_mat/test/t-init_clear.c +++ b/fmpz_sparse_mat/test/t-init_clear.c @@ -29,7 +29,7 @@ main(void) for (rep = 0; rep < 100; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while ((bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-mul.c b/fmpz_sparse_mat/test/t-mul.c index 3b0e40bdaa..5836cef308 100644 --- a/fmpz_sparse_mat/test/t-mul.c +++ b/fmpz_sparse_mat/test/t-mul.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 70); - while(bits < UWORD(2)); + while ((bits < UWORD(2)); r = 1 + n_randint(state, 20); c = 1 + n_randint(state, 20); k = 1 + n_randint(state, 20); diff --git a/fmpz_sparse_mat/test/t-neg.c b/fmpz_sparse_mat/test/t-neg.c index ef33d82ff5..e607563335 100644 --- a/fmpz_sparse_mat/test/t-neg.c +++ b/fmpz_sparse_mat/test/t-neg.c @@ -28,7 +28,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while ((bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-scalar_mul.c b/fmpz_sparse_mat/test/t-scalar_mul.c index c4eaaea3b0..91c4df9256 100644 --- a/fmpz_sparse_mat/test/t-scalar_mul.c +++ b/fmpz_sparse_mat/test/t-scalar_mul.c @@ -29,7 +29,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); fmpz_init(a); diff --git a/fmpz_sparse_mat/test/t-solve_dixon.c b/fmpz_sparse_mat/test/t-solve_dixon.c index ada103771c..a69605d9e0 100644 --- a/fmpz_sparse_mat/test/t-solve_dixon.c +++ b/fmpz_sparse_mat/test/t-solve_dixon.c @@ -35,7 +35,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 20); c = n_randint(state, 20); @@ -52,7 +52,8 @@ main(void) { fmpz_init(det); fmpz_sparse_mat_det(det, A); - if (!fmpz_is_zero(det)) { + if (!fmpz_is_zero(det)) + { num_bad_fail++; } fmpz_clear(det); diff --git a/fmpz_sparse_mat/test/t-solve_dixon_den.c b/fmpz_sparse_mat/test/t-solve_dixon_den.c index fa07dc65b1..65146a373c 100644 --- a/fmpz_sparse_mat/test/t-solve_dixon_den.c +++ b/fmpz_sparse_mat/test/t-solve_dixon_den.c @@ -36,7 +36,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 20); c = n_randint(state, 20); @@ -53,7 +53,8 @@ main(void) { fmpz_init(det); fmpz_sparse_mat_det(det, A); - if (!fmpz_is_zero(det)) { + if (!fmpz_is_zero(det)) + { num_bad_fail++; } fmpz_clear(det); diff --git a/fmpz_sparse_mat/test/t-transpose.c b/fmpz_sparse_mat/test/t-transpose.c index 9a70e01c93..cadc2ee77c 100644 --- a/fmpz_sparse_mat/test/t-transpose.c +++ b/fmpz_sparse_mat/test/t-transpose.c @@ -30,7 +30,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 20); c = n_randint(state, 20); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_vec.h b/fmpz_sparse_vec.h index 57cae848e6..3e18819a94 100644 --- a/fmpz_sparse_vec.h +++ b/fmpz_sparse_vec.h @@ -84,13 +84,13 @@ FMPZ_SPARSE_VEC_INLINE void _fmpz_sparse_vec_resize(fmpz_sparse_vec_t vec, slong nnz) { slong i; - if(nnz == 0) fmpz_sparse_vec_clear(vec); + if (nnz == 0) fmpz_sparse_vec_clear(vec); else if (nnz != vec->nnz) { - for(i = nnz; i < vec->nnz; ++i) + for (i = nnz; i < vec->nnz; ++i) fmpz_clear (vec->entries[i].val); vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); - for(i = vec->nnz; i < nnz; ++i) + for (i = vec->nnz; i < nnz; ++i) fmpz_init (vec->entries[i].val); } vec->nnz = nnz; @@ -140,7 +140,7 @@ FMPZ_SPARSE_VEC_INLINE void fmpz_sparse_vec_set_entry(fmpz_sparse_vec_t v, slong ind, const fmpz_t val) { fmpz_t * oval = fmpz_sparse_vec_at(v, ind); - if(oval == NULL) + if (oval == NULL) { _fmpz_sparse_vec_resize(v, v->nnz+1); v->entries[v->nnz-1].ind = ind; @@ -174,7 +174,7 @@ void fmpz_sparse_vec_to_dense(fmpz *vec, const fmpz_sparse_vec_t src, slong len) slong i; _fmpz_vec_zero(vec, len); for (i = 0; i < src->nnz; ++i) - if(src->entries[i].ind < len) + if (src->entries[i].ind < len) fmpz_set(&vec[src->entries[i].ind], src->entries[i].val); } @@ -192,7 +192,7 @@ void fmpz_sparse_vec_get_nmod_sparse_vec(nmod_sparse_vec_t dst, const fmpz_spars { dst->entries[ind].ind = src->entries[i].ind; dst->entries[ind].val = fmpz_fdiv_ui(src->entries[i].val, mod.n); - if(dst->entries[ind].val != UWORD(0)) ++ind; + if (dst->entries[ind].val != UWORD(0)) ++ind; } if (ind == 0) { @@ -349,9 +349,9 @@ slong _fmpz_sparse_vector_merge_descend(fmpz_sparse_entry_struct **we, { slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; - if(uind == -1 && vind == -1) return -1; - if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} - if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + if (uind == -1 && vind == -1) return -1; + if (uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if (uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} --*ue, --*we; (*we)->ind = uind; return 0; } @@ -369,9 +369,9 @@ slong _fmpz_sparse_vector_merge_descend_nmod(fmpz_sparse_entry_struct **we, { slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; - if(uind == -1 && vind == -1) return -1; - if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} - if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + if (uind == -1 && vind == -1) return -1; + if (uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if (uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} --*ue, --*we; (*we)->ind = uind; return 0; } @@ -381,7 +381,7 @@ void _fmpz_sparse_vector_shift_left (fmpz_sparse_vec_t v, slong amt) { slong i; if (amt == v->nnz) fmpz_sparse_vec_clear(v); - else if(amt > 0) + else if (amt > 0) { for (i = amt; i < v->nnz; ++i) { diff --git a/fmpz_sparse_vec/dot_dense.c b/fmpz_sparse_vec/dot_dense.c index b7baec33f4..bcf2c6746a 100644 --- a/fmpz_sparse_vec/dot_dense.c +++ b/fmpz_sparse_vec/dot_dense.c @@ -15,7 +15,8 @@ #include "flint.h" #include "fmpz_sparse_vec.h" -void fmpz_sparse_vec_dot_dense(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz *v) { +void fmpz_sparse_vec_dot_dense(fmpz_t ret, const fmpz_sparse_vec_t u, const fmpz *v) +{ slong i; fmpz_zero(ret); for (i = 0; i < u->nnz; ++i) fmpz_addmul(ret, u->entries[i].val, &v[u->entries[i].ind]); diff --git a/fmpz_sparse_vec/gauss_elim.c b/fmpz_sparse_vec/gauss_elim.c index 06fb9555d8..d5df05ca45 100644 --- a/fmpz_sparse_vec/gauss_elim.c +++ b/fmpz_sparse_vec/gauss_elim.c @@ -34,10 +34,10 @@ void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) { fmpz_t q, *uc; fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; - if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; + if (u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; fmpz_init(q); if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); - else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); + else if ((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); fmpz_clear(q); } @@ -50,17 +50,17 @@ void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) fmpz_sparse_entry_struct *lv = v->entries; fmpz_t g, vv, vu, uv, uu, a, b; fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; - if(u->nnz == 0 || v->nnz == 0) return; - if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} + if (u->nnz == 0 || v->nnz == 0) return; + if (lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} pc = lu->ind; - if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ + if (fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ { fmpz_sparse_vec_swap(u, v); fmpz_sparse_vec_neg(u, u); lu = u->entries, lv = v->entries; vnnz = v->nnz, unnz = u->nnz; } - if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ + if (fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ { fmpz_sparse_vec_neg(v, v); fmpz_sparse_vec_neg(u, u); diff --git a/fmpz_sparse_vec/gauss_elim_debugging b/fmpz_sparse_vec/gauss_elim_debugging deleted file mode 100644 index 48040a0972..0000000000 --- a/fmpz_sparse_vec/gauss_elim_debugging +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by th e Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "fmpz_sparse_vec.h" - -/* Reduce u by v */ -void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col) -{ - fmpz_t q; - fmpz_t *uc = fmpz_sparse_vec_at(u, col); - fmpz_t *vc = fmpz_sparse_vec_at(v, col); - if (uc == NULL || vc == NULL) return; - - fmpz_init(q); - fmpz_fdiv_q(q, *uc, *vc); - fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); - fmpz_clear(q); -} - -/* Reduce u by v */ -void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) -{ - fmpz_t q, *uc; - fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; - if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; - fmpz_init(q); - flint_printf("Doing ordinary gaussian elimination, found coefficient "); - if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); - else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); - fmpz_print(q); flint_printf(": %wd\n", q[0]); - fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); - fmpz_clear(q); -} - -/* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ -void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) -{ - slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; - fmpz_sparse_entry_struct *lu = u->entries; - fmpz_sparse_entry_struct *lv = v->entries; - fmpz_t g, vv, vu, uv, uu, a, b; - fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; - if(u->nnz == 0 || v->nnz == 0) return; - flint_printf("\t\t\t%wd, %wd\n", lu->ind, lv->ind); - if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} - pc = lu->ind; - if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ - { - flint_printf("Swapping\n"); - fmpz_sparse_vec_swap(u, v); - fmpz_sparse_vec_neg(u, u); - lu = u->entries, lv = v->entries; - vnnz = v->nnz, unnz = u->nnz; - } - if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ - { - fmpz_sparse_vec_neg(v, v); - fmpz_sparse_vec_neg(u, u); - } - flint_printf("pr[pc] = "), fmpz_print(lv->val), flint_printf("\n"); - flint_printf("r[pc] = "), fmpz_print(lu->val), flint_printf("\n"); - - /* Check for trivial cases */ - if (fmpz_divisible(lu->val, lv->val)) {fmpz_sparse_vec_gauss_elim(u, v); return;} - - fmpz_init(g); - fmpz_init(vv); - fmpz_init(vu); - fmpz_init(uv); - fmpz_init(uu); - fmpz_init(a); - fmpz_init(b); - - /* Construct transformation */ - fmpz_xgcd(g, vv, vu, lv->val, lu->val); - if (fmpz_sgn(g) < 0) - { - fmpz_neg(vv, vv); - fmpz_neg(vu, vu); - } - fmpz_divexact(uu, lv->val, g); - fmpz_divexact(uv, lu->val, g); - fmpz_neg(uv, uv); /* [[uu uv] [vu vv]] is unimodular */ - fmpz_set(g, uv); - flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); - flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); - flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); - - /* Reallocate vectors */ - nnz = _fmpz_sparse_vec_union_nnz (u, v); - _fmpz_sparse_vec_resize(u, nnz); - _fmpz_sparse_vec_resize(v, nnz); - ue = u->entries + unnz, ve = v->entries + vnnz; /* Old locations */ - nue = u->entries + nnz, nve = v->entries + nnz; /* New locations */ - while ((k = _fmpz_sparse_vector_merge_descend (&nue, &ue, &ve, u, v)) >= 0) - { - nve--; - flint_printf("%wd, %wd, %wd\n", nnz, nue - u->entries, nve-v->entries); - flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); - flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); - flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); - flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); - flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); - switch(k) - { - case 0: nve->ind = ue->ind; fmpz_mul(nve->val, ue->val, vu); fmpz_mul(nue->val, ue->val, uu); break; - case 1: nve->ind = ve->ind; fmpz_mul(nue->val, ve->val, g); fmpz_mul(nve->val, ve->val, vv); break; - default: nve->ind = ve->ind; - flint_printf("\t\tcur: [[%wd, %wd], [%wd, %wd]]\n", nue->val[0], nve->val[0], ue->val[0], ve->val[0]); - flint_printf("\t\tcur: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); - flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); - - fmpz_set(a, ve->val); - fmpz_set(b, ue->val); - fmpz_mul(nve->val, a, vv); fmpz_addmul(nve->val, b, vu); - fmpz_mul(nue->val, b, uu); fmpz_addmul(nue->val, a, uv); - flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(vu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(vv); flint_printf("\n"); - flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(uu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); flint_printf("\n"); - flint_printf("\t\tafter: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); - flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); - } - if (fmpz_is_zero(nue->val)) nue++; - if (fmpz_is_zero(nve->val)) nve++; - } - _fmpz_sparse_vector_shift_left (u, nue - u->entries); - _fmpz_sparse_vector_shift_left (v, nve - v->entries); - fmpz_clear(g); - fmpz_clear(vv); - fmpz_clear(vu); - fmpz_clear(uv); - fmpz_clear(uu); - fmpz_clear(a); - fmpz_clear(b); -} diff --git a/fmpz_sparse_vec/multi_CRT_ui.c b/fmpz_sparse_vec/multi_CRT_ui.c index ad13f836e7..bf2828ad68 100644 --- a/fmpz_sparse_vec/multi_CRT_ui.c +++ b/fmpz_sparse_vec/multi_CRT_ui.c @@ -31,7 +31,7 @@ fmpz_sparse_vec_multi_CRT_ui_precomp(fmpz_sparse_vec_t v, nmod_sparse_vec_struct rpos = flint_calloc(nres, sizeof(*rpos)); r = flint_malloc(nres * sizeof (*r)); - for(pos = 0; ; ++pos) + for (pos = 0; ; ++pos) { if (pos == max_nnz) max_nnz *= 2, _fmpz_sparse_vec_resize(v, max_nnz); e = &v->entries[pos]; diff --git a/fmpz_sparse_vec/set.c b/fmpz_sparse_vec/set.c index d8322b365e..e8813847f9 100644 --- a/fmpz_sparse_vec/set.c +++ b/fmpz_sparse_vec/set.c @@ -20,7 +20,7 @@ void fmpz_sparse_vec_set(fmpz_sparse_vec_t dst, const fmpz_sparse_vec_t src, slo slong i; if (dst == src) return; _fmpz_sparse_vec_resize(dst, src->nnz); - for(i=0; innz; ++i) + for (i = 0; i < dst->nnz; ++i) { dst->entries[i].ind = src->entries[i].ind - ioff; fmpz_set(dst->entries[i].val, src->entries[i].val); diff --git a/fmpz_sparse_vec/split.c b/fmpz_sparse_vec/split.c index c03d777181..b98eb4f222 100644 --- a/fmpz_sparse_vec/split.c +++ b/fmpz_sparse_vec/split.c @@ -19,7 +19,7 @@ void fmpz_sparse_vec_split(fmpz_sparse_vec_t res1, fmpz_sparse_vec_t res2, const { slong i, nnz1; fmpz_sparse_entry_struct *e1, *e2, *e; - for(nnz1=0; nnz1nnz; ++nnz1) if(vec->entries[nnz1].ind >= ind) break; + for (nnz1 = 0; nnz1 < vec->nnz; ++nnz1) if (vec->entries[nnz1].ind >= ind) break; _fmpz_sparse_vec_resize(res1, nnz1); _fmpz_sparse_vec_resize(res2, vec->nnz - nnz1); diff --git a/fmpz_sparse_vec/test/t-add.c b/fmpz_sparse_vec/test/t-add.c index c0c21b7efd..973f093057 100644 --- a/fmpz_sparse_vec/test/t-add.c +++ b/fmpz_sparse_vec/test/t-add.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 256); - while(bits < UWORD(2)); + while ((bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-concat.c b/fmpz_sparse_vec/test/t-concat.c index 5a59135963..ea499693f6 100644 --- a/fmpz_sparse_vec/test/t-concat.c +++ b/fmpz_sparse_vec/test/t-concat.c @@ -29,7 +29,7 @@ int main(void) for (rep = 0; rep < 100; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-construct.c b/fmpz_sparse_vec/test/t-construct.c index 319790bec9..d97263ee0d 100644 --- a/fmpz_sparse_vec/test/t-construct.c +++ b/fmpz_sparse_vec/test/t-construct.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 1; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 10); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-dense.c b/fmpz_sparse_vec/test/t-dense.c index 097c0addba..3187cc29b6 100644 --- a/fmpz_sparse_vec/test/t-dense.c +++ b/fmpz_sparse_vec/test/t-dense.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-dot.c b/fmpz_sparse_vec/test/t-dot.c index b48479d25d..795bee5037 100644 --- a/fmpz_sparse_vec/test/t-dot.c +++ b/fmpz_sparse_vec/test/t-dot.c @@ -33,7 +33,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 50); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-gauss_elim.c b/fmpz_sparse_vec/test/t-gauss_elim.c index 1996d62e9c..a3fc3afc17 100644 --- a/fmpz_sparse_vec/test/t-gauss_elim.c +++ b/fmpz_sparse_vec/test/t-gauss_elim.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 10; rep++) { do bits = n_randint(state, 10); - while(bits < UWORD(2)); + while ((bits < UWORD(2)); len = n_randint(state, 20); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-init_clear.c b/fmpz_sparse_vec/test/t-init_clear.c index 5d6145aabc..50a0ef18d0 100644 --- a/fmpz_sparse_vec/test/t-init_clear.c +++ b/fmpz_sparse_vec/test/t-init_clear.c @@ -44,7 +44,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 50); nnz = n_randint(state, len+1); fmpz_sparse_vec_init(vec); @@ -68,7 +68,7 @@ main(void) flint_printf("FAIL: found zero value\n"); abort(); } - if (i>0 && e->ind <= e[-1].ind) + if (i > 0 && e->ind <= e[-1].ind) { flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); abort(); diff --git a/fmpz_sparse_vec/test/t-max_bits.c b/fmpz_sparse_vec/test/t-max_bits.c index 2db9284fc0..92d3d0e12d 100644 --- a/fmpz_sparse_vec/test/t-max_bits.c +++ b/fmpz_sparse_vec/test/t-max_bits.c @@ -30,7 +30,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-neg.c b/fmpz_sparse_vec/test/t-neg.c index 7d303f0d99..9b6fce5712 100644 --- a/fmpz_sparse_vec/test/t-neg.c +++ b/fmpz_sparse_vec/test/t-neg.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-nmod.c b/fmpz_sparse_vec/test/t-nmod.c index bc53819cd9..22a112bd29 100644 --- a/fmpz_sparse_vec/test/t-nmod.c +++ b/fmpz_sparse_vec/test/t-nmod.c @@ -34,7 +34,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 256); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 50); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-scalar_divexact.c b/fmpz_sparse_vec/test/t-scalar_divexact.c index 162538d1db..47d2f2b88f 100644 --- a/fmpz_sparse_vec/test/t-scalar_divexact.c +++ b/fmpz_sparse_vec/test/t-scalar_divexact.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 1; rep++) { do bits = n_randint(state, 100); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 50); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-scalar_mod.c b/fmpz_sparse_vec/test/t-scalar_mod.c index a579a9612a..0210c9faa1 100644 --- a/fmpz_sparse_vec/test/t-scalar_mod.c +++ b/fmpz_sparse_vec/test/t-scalar_mod.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 10); - while(bits < UWORD(3)); + while (bits < UWORD(3)); len = n_randint(state, 50); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-scalar_mul.c b/fmpz_sparse_vec/test/t-scalar_mul.c index 664bb6914d..3e250be81a 100644 --- a/fmpz_sparse_vec/test/t-scalar_mul.c +++ b/fmpz_sparse_vec/test/t-scalar_mul.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while(bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 50); nnz = n_randint(state, len+1); diff --git a/fq_sparse_mat_templates/lu.c b/fq_sparse_mat_templates/lu.c index 0626c4c0dc..161d879afc 100644 --- a/fq_sparse_mat_templates/lu.c +++ b/fq_sparse_mat_templates/lu.c @@ -49,10 +49,13 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s heap_idx[c] = pos; } -/* static void print_heap(slong *heap, slong *scores, slong size) { +/* static void print_heap(slong *heap, slong *scores, slong size) +{ slong level, i; - for (level = 1; level <= size; level<<=1) { - for (i = level; i <= size && i < 2*level; ++i) { + for (level = 1; level <= size; level<<=1) + { + for (i = level; i <= size && i < 2*level; ++i) + { flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); } flint_printf("\n"); @@ -85,12 +88,12 @@ slong TEMPLATE(T, sparse_mat_lu)(slong *P, slong *Q, /* Set up permutations */ remr = M->r, remc = M->c; - for (r = 0; rr; ++r) + for (r = 0; r < M->r; ++r) { if (!U->rows[r].nnz) P[r] = --remr; else P[r] = -1; } - for (c = 0; cc; ++c) + for (c = 0; c < M->c; ++c) { if (!Lt->rows[c].nnz) Q[c] = --remc; else Q[c] = -1; @@ -109,7 +112,7 @@ slong TEMPLATE(T, sparse_mat_lu)(slong *P, slong *Q, } /* Run elimination */ rank = 0; - for (heap_size=M->c; heap_size > 0; ) + for (heap_size = M->c; heap_size > 0; ) { /* Get lowest weight column (top of heap) */ pc = heap[0]; diff --git a/fq_sparse_mat_templates/nullspace_block_lanczos.c b/fq_sparse_mat_templates/nullspace_block_lanczos.c index f535e3efbd..38229f8a27 100644 --- a/fq_sparse_mat_templates/nullspace_block_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_block_lanczos.c @@ -16,7 +16,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_block_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_block_wiedemann.c b/fq_sparse_mat_templates/nullspace_block_wiedemann.c index f4e759918c..681765a14c 100644 --- a/fq_sparse_mat_templates/nullspace_block_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_block_wiedemann.c @@ -16,7 +16,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_block_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, slong block_size, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_lanczos.c b/fq_sparse_mat_templates/nullspace_lanczos.c index 6ebf652b25..062bdd35ab 100644 --- a/fq_sparse_mat_templates/nullspace_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_lanczos.c @@ -16,7 +16,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_lanczos) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/nullspace_wiedemann.c b/fq_sparse_mat_templates/nullspace_wiedemann.c index 9dd7254709..feb8c72f71 100644 --- a/fq_sparse_mat_templates/nullspace_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_wiedemann.c @@ -16,7 +16,7 @@ slong TEMPLATE(T, sparse_mat_nullspace_wiedemann) (TEMPLATE(T, mat_t) X, const TEMPLATE(T, sparse_mat_t) M, flint_rand_t state, slong max_iters, const TEMPLATE(T, ctx_t) ctx) { - /* Generate random solutions to a random system Mx=b and stop when nullspace filled */ + /* Generate random solutions to a random system Mx = b and stop when nullspace filled */ slong i, j, iter, nxs, *xps; TEMPLATE(T, t) cc; TEMPLATE(T, struct) *x, **xs; diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c index 89acbc60a6..b32b24f2ec 100644 --- a/fq_sparse_mat_templates/rref.c +++ b/fq_sparse_mat_templates/rref.c @@ -33,7 +33,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( /* Set up permutations */ remr = M->r; - for (r = 0; rr; ++r) + for (r = 0; r < M->r; ++r) { if (!M->rows[r].nnz || M->rows[r].entries[0].ind >= M->c) P[r] = --remr; else P[r] = -1; @@ -41,7 +41,7 @@ slong TEMPLATE(T, sparse_mat_rref) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( /* Run elimination */ rank = 0; - for (pc = 0; pcc; ++pc) + for (pc = 0; pc < M->c; ++pc) { pcol = &Mt->rows[pc]; diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c index 4f178c30c9..bc0bfc162c 100644 --- a/fq_sparse_mat_templates/solve_block_wiedemann.c +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -56,8 +56,8 @@ static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLAT /* Set the pivot row to be the minimum degree row incident on column pc */ pr = b + pc; for (r = 0; r < b; r++) - if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; - if(TEMPLATE(T, is_zero) (&M->rows[pr][pc], ctx)) continue; + if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx) && d[r] < d[pr]) pr = r; + if (TEMPLATE(T, is_zero) (&M->rows[pr][pc], ctx)) continue; /* Try to move pivot row to appropriate position (if not already there) */ @@ -74,7 +74,7 @@ static void coppersmith_aux_gauss(TEMPLATE(T, mat_t) M, slong *d, const TEMPLAT /* Do Gaussian elimination on first b rows */ for (r = 0; r < b; ++r) - if(gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) + if (gamma[r] && !TEMPLATE(T, is_zero) (&M->rows[r][pc], ctx)) { TEMPLATE(T, mul) (cc, &M->rows[r][pc], cinv, ctx); TEMPLATE(T, neg) (cc, cc, ctx); @@ -183,7 +183,7 @@ static void make_block_sum(TEMPLATE(T, struct) *x, const TEMPLATE(T, mat_struct) _TEMPLATE(T, vec_zero) (x, M->c, ctx); for (i = iter = 0; iter <= d[l]; ++iter, i = 1 - i) { - if(iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); + if (iter > 0) TEMPLATE(T, sparse_mat_mul_mat) (&Z[i], M, &Z[1-i], ctx); TEMPLATE(T, mat_mul_vec) (xi, &Z[i], S[dd + iter].rows[l], ctx); _TEMPLATE(T, vec_add) (x, x, xi, M->c, ctx); } @@ -212,7 +212,7 @@ int TEMPLATE(T, sparse_mat_solve_block_wiedemann) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_append_row) (Mb, z, ctx); ret = TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (x1, Mb, block_size, state, ctx); - if(ret && !TEMPLATE(T, is_zero) (&x1[M->c], ctx)) + if (ret && !TEMPLATE(T, is_zero) (&x1[M->c], ctx)) { TEMPLATE(T, inv) (&x1[M->c], &x1[M->c], ctx); TEMPLATE(T, neg) (&x1[M->c], &x1[M->c], ctx); @@ -241,7 +241,7 @@ int TEMPLATE(T, sparse_mat_nullvector_block_wiedemann) (TEMPLATE(T, struct) *x, for (k = 0; k < ns; ++k) TEMPLATE(T, mat_init) (&S[k], block_size, block_size, ctx); for (l = 0; l < 3; ++l) TEMPLATE(T, mat_init) (&Y[l], M->c, block_size, ctx); do TEMPLATE(T, mat_randtest) (&Y[0], state, ctx); - while(TEMPLATE(T, mat_is_zero) (&Y[0], ctx)); + while (TEMPLATE(T, mat_is_zero) (&Y[0], ctx)); TEMPLATE(T, sparse_mat_mul_mat) (&Y[1], M, &Y[0], ctx); make_block_sequences(S, ns, M, &Y[1], ctx); diff --git a/fq_sparse_mat_templates/solve_lu.c b/fq_sparse_mat_templates/solve_lu.c index 372a9fd91c..26678ab4f8 100644 --- a/fq_sparse_mat_templates/solve_lu.c +++ b/fq_sparse_mat_templates/solve_lu.c @@ -14,7 +14,7 @@ #include #include "templates.h" -/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x=Qx' */ +/* PAQ = LU, Ax = b => set b' = Pb, solve Ly = b', solve Ux' = y, set x = Qx' */ int TEMPLATE(T, sparse_mat_solve_lu) (TEMPLATE(T, struct) *x, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, struct) *b, const TEMPLATE(T, ctx_t) ctx) { int good = 1; diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c index a6d49cecdf..a045a6426e 100644 --- a/fq_sparse_mat_templates/solve_wiedemann.c +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -35,7 +35,7 @@ static slong find_min_poly(TEMPLATE(T, struct) *s, slong N, const TEMPLATE(T, ct for (n = 0, m = 1; n < N; n++, m++) { - /* d_C = sum_{i=0}^L C_i * s_{n-i} */ + /* d_C = sum_{i = 0}^L C_i * s_{n-i} */ TEMPLATE(T, set) (d_C, &s[n], ctx); for (i = 1; i <= L; i++) { @@ -76,7 +76,7 @@ static slong find_min_poly(TEMPLATE(T, struct) *s, slong N, const TEMPLATE(T, ct return L; } -/* Compute s_ij=(A^j y)_i for i=0,...,ns-1, j=0,...,num-1*/ +/* Compute s_ij=(A^j y)_i for i = 0,...,ns-1, j = 0,...,num-1*/ static void make_sequences(TEMPLATE(T, struct) **s, slong ns, slong len, const TEMPLATE(T, sparse_mat_t) A, TEMPLATE(T, struct) **y, const TEMPLATE(T, ctx_t) ctx) { slong iter, i, j; @@ -87,7 +87,7 @@ static void make_sequences(TEMPLATE(T, struct) **s, slong ns, slong len, const T } } -/* Compute x = \Sigma_{i=0}^{L-1} s_i * A^i * b = 0 */ +/* Compute x = \Sigma_{i = 0}^{L-1} s_i * A^i * b = 0 */ static void make_sum(TEMPLATE(T, struct) *x, TEMPLATE(T, struct) *s, slong L, const TEMPLATE(T, sparse_mat_t) A, TEMPLATE(T, struct) **y, const TEMPLATE(T, ctx_t) ctx) { slong iter, i; @@ -127,7 +127,7 @@ int TEMPLATE(T, sparse_mat_solve_wiedemann) (TEMPLATE(T, struct) *x, const TEMPL L = find_min_poly(s[i], len, ctx); if (TEMPLATE(T, is_zero) (&s[i][0], ctx)) continue; - /* If \sum_{j=0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j=0}^{L-1} s_i(j-1) A^jb solves Ax=b */ + /* If \sum_{j = 0}^L s_ijA^jb = 0 => x = -1/s[0]\sum_{j = 0}^{L-1} s_i(j-1) A^jb solves Ax = b */ _TEMPLATE(T, vec_set) (y[0], b, A->r, ctx); make_sum(x, s[i]+1, L, A, y, ctx); TEMPLATE(T, inv) (cc, &s[i][0], ctx); @@ -167,7 +167,7 @@ int TEMPLATE(T, sparse_mat_nullvector_wiedemann) (TEMPLATE(T, struct) *x, const /* Get minimal polynomial */ L = find_min_poly(s[i], len, ctx); - /* \sum_{j=0}^L s_ijA^jb = 0 => x = \sum_{j=0}^L s_ijA^jx solves Ax=0 */ + /* \sum_{j = 0}^L s_ijA^jb = 0 => x = \sum_{j = 0}^L s_ijA^jx solves Ax = 0 */ _TEMPLATE(T, vec_set) (y[1], y[0], A->r, ctx); make_sum(x, s[i], L+1, A, &y[1], ctx); TEMPLATE(T, sparse_mat_mul_vec) (y[1], A, x, ctx); diff --git a/fq_sparse_mat_templates/test/t-inv.c b/fq_sparse_mat_templates/test/t-inv.c index 9f5ff66f72..177084f665 100644 --- a/fq_sparse_mat_templates/test/t-inv.c +++ b/fq_sparse_mat_templates/test/t-inv.c @@ -47,7 +47,8 @@ main(void) TEMPLATE(T, sparse_mat_inv) (Ai, A, ctx); TEMPLATE(T, sparse_mat_mul_mat) (dAiA, Ai, dA, ctx); TEMPLATE(T, mat_rref) (dA, ctx); - if (!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) { + if (!TEMPLATE(T, mat_equal) (dAiA, dA, ctx)) + { flint_printf("FAIL!\n"); flint_printf("A^-1 x A = "); TEMPLATE(T, mat_print_pretty) (dAiA, ctx); diff --git a/fq_sparse_mat_templates/test/t-lu.c b/fq_sparse_mat_templates/test/t-lu.c index a9b93f5afa..2c0d680efc 100644 --- a/fq_sparse_mat_templates/test/t-lu.c +++ b/fq_sparse_mat_templates/test/t-lu.c @@ -27,7 +27,7 @@ main(void) TEMPLATE(T, mat_t) dL, dU, dLU; FLINT_TEST_INIT(state); - flint_printf("decomposing PAQ=LU...."); + flint_printf("decomposing PAQ = LU...."); fflush(stdout); for (rep = 0; rep < 200; rep++) @@ -50,19 +50,23 @@ main(void) TEMPLATE(T, mat_init) (dLU, r, c, ctx); /* Check that L is lower triangular (with ones on diagonal up to rank) */ - for (i = 0; i < r; ++i) { + for (i = 0; i < r; ++i) + { val = TEMPLATE(T, sparse_vec_at) (&L->rows[i], i, ctx); if (i < rk && (val == NULL || !TEMPLATE(T, is_one) (*val, ctx))) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } - for (j = 0; jrows[i].nnz; ++j) { + for (j = 0; j < L->rows[i].nnz; ++j) + { TEMPLATE(T, sparse_entry_struct) *e = &L->rows[i].entries[j]; - if (e->ind > i) { + if (e->ind > i) + { flint_printf("FAIL: L not lower triangular\n"); abort(); } - if (e->ind >= rk) { + if (e->ind >= rk) + { flint_printf("FAIL: L not trivial past the rank\n"); /*TEMPLATE(T, sparse_mat_print_pretty) (L, ctx);*/ abort(); @@ -70,7 +74,8 @@ main(void) } } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ - for (i = 0; i < r; ++i) { + for (i = 0; i < r; ++i) + { val = TEMPLATE(T, sparse_vec_at) (&U->rows[i], i, ctx); if (i < rk && (val == NULL || TEMPLATE(T, is_zero) (*val, ctx))) { @@ -82,9 +87,11 @@ main(void) flint_printf("FAIL: U not trivial past the rank\n"); abort(); } - for (j = 0; j < U->rows[i].nnz; ++j) { + for (j = 0; j < U->rows[i].nnz; ++j) + { TEMPLATE(T, sparse_entry_struct) *e = &U->rows[i].entries[j]; - if (e->ind < i) { + if (e->ind < i) + { flint_printf("FAIL: U not upper triangular\n"); abort(); } @@ -96,7 +103,8 @@ main(void) TEMPLATE(T, sparse_mat_from_dense) (LU, dLU, ctx); TEMPLATE(T, sparse_mat_permute_rows) (A, P, ctx); TEMPLATE(T, sparse_mat_permute_cols) (A, Q, ctx); - if (!TEMPLATE(T, sparse_mat_equal) (A, LU, ctx)) { + if (!TEMPLATE(T, sparse_mat_equal) (A, LU, ctx)) + { flint_printf("FAIL: PAQ != LU\n"); flint_printf("PAQ="); TEMPLATE(T, sparse_mat_print_pretty) (A, ctx); diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c index bfded6b73b..ff22e2d7f1 100644 --- a/fq_sparse_mat_templates/test/t-nullspace.c +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -81,11 +81,11 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - for(i = 0; i < 6; ++i) + for (i = 0; i < 6; ++i) { flint_printf("Finding nullspace with %s\n", names[i]); /* flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps); */ - if(discrep[i] > 0) + if (discrep[i] > 0) flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", discrep[i], nreps); } diff --git a/fq_sparse_mat_templates/test/t-rref.c b/fq_sparse_mat_templates/test/t-rref.c index 230972ae54..7129698843 100644 --- a/fq_sparse_mat_templates/test/t-rref.c +++ b/fq_sparse_mat_templates/test/t-rref.c @@ -44,7 +44,8 @@ main(void) TEMPLATE(T, sparse_mat_rref) (A, ctx); TEMPLATE(T, mat_rref) (dA, ctx); TEMPLATE(T, sparse_mat_from_dense) (B, dA, ctx); - if (!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) { + if (!TEMPLATE(T, sparse_mat_equal) (A, B, ctx)) + { flint_printf("FAIL!\n"); abort(); } diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index 408200f195..27bfbb9bed 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -34,7 +34,7 @@ main(void) /* struct timeval start, end; */ FLINT_TEST_INIT(state); - flint_printf("solving Ax=b...."); + flint_printf("solving Ax = b...."); fflush(stdout); for (rep = 0; rep < nreps; rep++) @@ -62,10 +62,10 @@ main(void) { case 0: ret = TEMPLATE(T, sparse_mat_solve_rref) (x2, A, b, ctx); break; case 1: ret = TEMPLATE(T, sparse_mat_solve_lu) (x2, A, b, ctx); break; - case 2: do ret = TEMPLATE(T, sparse_mat_solve_lanczos) (x2, A, b, state, ctx); while(ret == 0 && ++iter < 3); break; - case 3: do ret = TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, A, b, 8, state, ctx); while(ret == 0 && ++iter < 3); break; + case 2: do ret = TEMPLATE(T, sparse_mat_solve_lanczos) (x2, A, b, state, ctx); while (ret == 0 && ++iter < 3); break; + case 3: do ret = TEMPLATE(T, sparse_mat_solve_block_lanczos) (x2, A, b, 8, state, ctx); while (ret == 0 && ++iter < 3); break; case 4: ret = TEMPLATE(T, sparse_mat_solve_wiedemann) (x2, A, b, ctx); break; - case 5: do ret = TEMPLATE(T, sparse_mat_solve_block_wiedemann) (x2, A, b, 8, state, ctx); while(ret == 0 && ++iter < 3); break; + case 5: do ret = TEMPLATE(T, sparse_mat_solve_block_wiedemann) (x2, A, b, 8, state, ctx); while (ret == 0 && ++iter < 3); break; } /* gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); */ diff --git a/fq_sparse_mat_templates/tmp b/fq_sparse_mat_templates/tmp deleted file mode 100644 index f16d89d6ca..0000000000 --- a/fq_sparse_mat_templates/tmp +++ /dev/null @@ -1,31 +0,0 @@ - int ret = 0; - slong l; - - std::vector combi(block_size,Vector(F,d[l]+1)); - for (size_t i=0;i 0;--i) { - lhs = lhs2 + combi[0][i]*y; - lhs2 = A^t*lhs; - } - Vector accu (lhs); - _TEMPLATE(T, vec_zero) (x, A->r, ctx); - for (size_t k=1;k= 0;--i) { - lhs = lhs2 + combi[k][i]*row; - lhs2 = A^t * lhs - } - _TEMPLATE(T, vec_add) (x, x, lhs, A->r, ctx); - } - TEMPLATE(T, neg) (cc, nmod_inv(S[0].rows[l][0], ctx), ctx); - _TEMPLATE(T, vec_scalar_mul) (x, x, A->r, cc, ctx); - return ret; diff --git a/fq_sparse_vec_templates.h b/fq_sparse_vec_templates.h index ce66c41317..faf88f6e08 100644 --- a/fq_sparse_vec_templates.h +++ b/fq_sparse_vec_templates.h @@ -60,7 +60,7 @@ void TEMPLATE(T, sparse_vec_clear)(TEMPLATE(T, sparse_vec_t) vec, const TEMPLATE(T, ctx_t) ctx) { slong i; - for(i = 0; i < vec->nnz; ++i) + for (i = 0; i < vec->nnz; ++i) TEMPLATE(T, clear) (vec->entries[i].val, ctx); flint_free(vec->entries); memset(vec, 0, sizeof(*vec)); @@ -71,13 +71,13 @@ void _TEMPLATE(T, sparse_vec_resize)(TEMPLATE(T, sparse_vec_t) vec, slong nnz, const TEMPLATE(T, ctx_t) ctx) { slong i; - if(nnz == 0) TEMPLATE(T, sparse_vec_clear) (vec, ctx); + if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (vec, ctx); else if (nnz != vec->nnz) { - for(i = nnz; i < vec->nnz; ++i) + for (i = nnz; i < vec->nnz; ++i) TEMPLATE(T, clear) (vec->entries[i].val, ctx); vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); - for(i = vec->nnz; i < nnz; ++i) + for (i = vec->nnz; i < nnz; ++i) TEMPLATE(T, init) (vec->entries[i].val, ctx); } vec->nnz = nnz; @@ -127,7 +127,7 @@ void TEMPLATE(T, sparse_vec_set)(TEMPLATE(T, sparse_vec_t) dst, const TEMPLATE(T slong i; if (dst == src) return; _TEMPLATE(T, sparse_vec_resize) (dst, src->nnz, ctx); - for(i=0; innz; ++i) + for (i = 0; i < dst->nnz; ++i) { dst->entries[i].ind = src->entries[i].ind - ioff; TEMPLATE(T, set) (dst->entries[i].val, src->entries[i].val, ctx); @@ -146,7 +146,7 @@ void TEMPLATE(T, sparse_vec_set_entry)(TEMPLATE(T, sparse_vec_t) v, slong ind, c _TEMPLATE(T, sparse_vec_resize) (v, v->nnz + 1, ctx); TEMPLATE(T, set) (v->entries[v->nnz-1].val, val, ctx); v->entries[v->nnz-1].ind = ind; - if(v->nnz >= 2 && ind < v->entries[v->nnz-2].ind) + if (v->nnz >= 2 && ind < v->entries[v->nnz-2].ind) qsort(v->entries, v->nnz, sizeof(*v->entries), TEMPLATE(T, sparse_entry_cmp)); } else TEMPLATE(T, set) (*oval, val, ctx); @@ -218,8 +218,8 @@ void TEMPLATE(T, sparse_vec_window_init)(TEMPLATE(T, sparse_vec_t) window, const const TEMPLATE(T, ctx_t) ctx) { slong start, end; - for (start = 0; startnnz && vec->entries[start].ind < i1; ++start); - for (end=vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); + for (start = 0; start < vec->nnz && vec->entries[start].ind < i1; ++start); + for (end = vec->nnz; end > 0 && vec->entries[end-1].ind >= i2; --end); window->entries = vec->entries + start; window->nnz = end - start; } @@ -252,7 +252,7 @@ void TEMPLATE(T, sparse_vec_split)(TEMPLATE(T, sparse_vec_t) res1, TEMPLATE(T, s { slong i, nnz1; TEMPLATE(T, sparse_entry_struct) *e1, *e2, *e; - for(nnz1=0; nnz1nnz; ++nnz1) if(vec->entries[nnz1].ind >= ind) break; + for (nnz1 = 0; nnz1 < vec->nnz; ++nnz1) if (vec->entries[nnz1].ind >= ind) break; _TEMPLATE(T, sparse_vec_resize) (res1, nnz1, ctx); _TEMPLATE(T, sparse_vec_resize) (res2, vec->nnz - nnz1, ctx); @@ -337,9 +337,9 @@ slong _TEMPLATE(T, sparse_vector_merge_descend) (TEMPLATE(T, sparse_entry_struct { slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; - if(uind == -1 && vind == -1) return -1; - if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} - if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + if (uind == -1 && vind == -1) return -1; + if (uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if (uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} --*ue, --*we; (*we)->ind = uind; return 0; } @@ -349,7 +349,7 @@ void _TEMPLATE(T, sparse_vector_shift_left) (TEMPLATE(T, sparse_vec_t) v, slong { slong i; if (amt == v->nnz) TEMPLATE(T, sparse_vec_clear) (v, ctx); - else if(amt > 0) + else if (amt > 0) { v->nnz -= amt; for (i = 0; i < amt; ++i) TEMPLATE(T, clear) (v->entries[i].val, ctx); @@ -403,7 +403,7 @@ void TEMPLATE(T, sparse_vec_dot_dense)(TEMPLATE(T, t) ret, const TEMPLATE(T, spa TEMPLATE(T, t) tmp; TEMPLATE(T, init) (tmp, ctx); TEMPLATE(T, zero) (ret, ctx); - for(i=0; innz; ++i) + for (i = 0; i < u->nnz; ++i) { TEMPLATE(T, mul) (tmp, u->entries[i].val, &v[u->entries[i].ind], ctx); TEMPLATE(T, add) (ret, ret, tmp, ctx); diff --git a/fq_sparse_vec_templates/add.c b/fq_sparse_vec_templates/add.c index ad6d992b06..7173bd166a 100644 --- a/fq_sparse_vec_templates/add.c +++ b/fq_sparse_vec_templates/add.c @@ -31,7 +31,7 @@ void TEMPLATE(T, sparse_vec_add)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; case 1: TEMPLATE(T, set)(we->val, ve->val, ctx); break; default: TEMPLATE(T, add)(we->val, ue->val, ve->val, ctx); - if(TEMPLATE(T, is_zero) (we->val, ctx)) we++; + if (TEMPLATE(T, is_zero) (we->val, ctx)) we++; } } _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c index c75a7375d4..016efd88e5 100644 --- a/fq_sparse_vec_templates/scalar_addmul.c +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -26,7 +26,7 @@ void TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(TEMPLATE(T, sparse_vec_t if (unnz == 0) {TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T)) (w, v, c, ctx); return;} TEMPLATE(T, init) (tmp, ctx); TEMPLATE(T, neg) (tmp, c, ctx); - if(TEMPLATE(T, is_one) (tmp, ctx)) TEMPLATE(T, sparse_vec_sub) (w, u, v, ctx); + if (TEMPLATE(T, is_one) (tmp, ctx)) TEMPLATE(T, sparse_vec_sub) (w, u, v, ctx); else /* Now just do standard addmul */ { wnnz = _TEMPLATE(T, sparse_vec_union_nnz) (u, v, ctx); diff --git a/fq_sparse_vec_templates/sub.c b/fq_sparse_vec_templates/sub.c index 21289fac98..19990f47d4 100644 --- a/fq_sparse_vec_templates/sub.c +++ b/fq_sparse_vec_templates/sub.c @@ -31,7 +31,7 @@ void TEMPLATE(T, sparse_vec_sub)(TEMPLATE(T, sparse_vec_t) w, const TEMPLATE(T, case 0: TEMPLATE(T, set)(we->val, ue->val, ctx); break; case 1: TEMPLATE(T, neg)(we->val, ve->val, ctx); break; default: TEMPLATE(T, sub)(we->val, ue->val, ve->val, ctx); - if(TEMPLATE(T, is_zero) (we->val, ctx)) we++; + if (TEMPLATE(T, is_zero) (we->val, ctx)) we++; } } _TEMPLATE(T, sparse_vector_shift_left) (w, we - w->entries, ctx); diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index bd46d76962..d71cca1b34 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -96,7 +96,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { slong i, rmax = FLINT_MIN(M->r, src->r); - if(M==src || M->r == 0) return; + if (M==src || M->r == 0) return; for (i = 0; i < rmax; ++i) nmod_sparse_vec_set(&M->rows[i], &src->rows[i], src->c_off); } @@ -194,8 +194,9 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; - for (i = 0; i < M->r; ++i) { - if(!M->rows[i].nnz) continue; + for (i = 0; i < M->r; ++i) + { + if (!M->rows[i].nnz) continue; nmod_sparse_vec_permute_inds(&M->rows[i], Q); qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), nmod_sparse_entry_cmp); } diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index dc07510e23..0e894fe0c7 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -51,10 +51,13 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s heap_idx[c] = pos; } -/* static void print_heap(slong *heap, slong *scores, slong size) { +/* static void print_heap(slong *heap, slong *scores, slong size) +{ slong level, i; - for (level = 1; level<=size; level<<=1) { - for (i = level; i<=size && i < 2*level; ++i) { + for (level = 1; level <= size; level<<=1) + { + for (i = level; i <= size && i < 2*level; ++i) + { flint_printf("%wd:%wd,%wd\t", i-1, heap[i-1], scores[heap[i-1]]); } flint_printf("\n"); diff --git a/nmod_sparse_mat/nullspace_block_lanczos.c b/nmod_sparse_mat/nullspace_block_lanczos.c index 588429530e..e8c6e352dc 100644 --- a/nmod_sparse_mat/nullspace_block_lanczos.c +++ b/nmod_sparse_mat/nullspace_block_lanczos.c @@ -27,10 +27,11 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_ma xps = NULL; for (iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_block_lanczos(x, M, block_size, state) == 0) {++iter; continue;} + if (nmod_sparse_mat_nullvector_block_lanczos(x, M, block_size, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } @@ -40,7 +41,8 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_ma _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } diff --git a/nmod_sparse_mat/nullspace_block_wiedemann.c b/nmod_sparse_mat/nullspace_block_wiedemann.c index bea2ac88d9..d8b5c30ace 100644 --- a/nmod_sparse_mat/nullspace_block_wiedemann.c +++ b/nmod_sparse_mat/nullspace_block_wiedemann.c @@ -27,10 +27,11 @@ slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_ xps = NULL; for (iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_block_wiedemann(x, M, block_size, state) == 0) {++iter; continue;} + if (nmod_sparse_mat_nullvector_block_wiedemann(x, M, block_size, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } @@ -40,7 +41,8 @@ slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_ _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index f35cc78e6f..0f5a9e0335 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -27,10 +27,11 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, xps = NULL; for (iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_lanczos(x, M, state) == 0) {++iter; continue;} + if (nmod_sparse_mat_nullvector_lanczos(x, M, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } @@ -40,7 +41,8 @@ slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index f8b0ef9447..3a571bf7f4 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -41,13 +41,15 @@ slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M) /* Mssign unit vectors to non-pivot columns */ for (i = M->c-1; i >= rk; --i) X->rows[Qi[i]][i-rk] = 1; - for (i = rk-1; i >= 0; --i) { + for (i = rk-1; i >= 0; --i) + { Urow = &U->rows[i]; Xrow = X->rows[Qi[i]]; - for (j = 1; j < Urow->nnz; ++j) { + for (j = 1; j < Urow->nnz; ++j) + { e = &Urow->entries[j]; /* Do in-place row elimination */ - if(e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, M->mod), M->mod); + if (e->ind < rk) _nmod_vec_scalar_addmul_nmod(Xrow, X->rows[Qi[e->ind]], X->c, nmod_neg(e->val, M->mod), M->mod); else Xrow[e->ind-rk] = nmod_sub(Xrow[e->ind-rk], e->val, M->mod); } diff --git a/nmod_sparse_mat/nullspace_rref.c b/nmod_sparse_mat/nullspace_rref.c index 68595e2074..defc31b100 100644 --- a/nmod_sparse_mat/nullspace_rref.c +++ b/nmod_sparse_mat/nullspace_rref.c @@ -26,7 +26,7 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M) nmod_sparse_mat_set(R, M); rk = nmod_sparse_mat_rref(R); nmod_mat_init(X, M->c, M->c-rk, M->mod.n); - if(rk != M->c) + if (rk != M->c) { numc = 0; /* Mark which cols are pivots and enumerate the nonpivots */ @@ -34,7 +34,7 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M) for (i = 0; i < rk; ++i) Q[R->rows[i].entries->ind] = -1; for (i = 0; i < M->c; ++i) - if(Q[i]==UWORD(0)) Q[i] = numc++, X->rows[i][Q[i]] = 1; + if (Q[i]==UWORD(0)) Q[i] = numc++, X->rows[i][Q[i]] = 1; /* For each pivot col, set the corresponding row in X as */ /* the negative of the associated row in R (reordered by Q) */ diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c index 895d8e939b..c6c3b8a0a3 100644 --- a/nmod_sparse_mat/nullspace_wiedemann.c +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -27,10 +27,11 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t xps = NULL; for (iter = 0; iter < max_iters; ) { - if(nmod_sparse_mat_nullvector_wiedemann(x, M, state) == 0) {++iter; continue;} + if (nmod_sparse_mat_nullvector_wiedemann(x, M, state) == 0) {++iter; continue;} /* Reduce by existing kernel vectors */ - for (j = nxs-1; j >= 0; --j) { + for (j = nxs-1; j >= 0; --j) + { _nmod_vec_scalar_addmul_nmod(x, xs[j], M->c, nmod_neg(x[xps[j]], M->mod), M->mod); } @@ -40,7 +41,8 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t _nmod_vec_scalar_mul_nmod(x, x, M->c, nmod_inv(x[i], M->mod), M->mod); /* Reduce previous vectors by this one */ - for (j = 0; j < nxs; ++j) { + for (j = 0; j < nxs; ++j) + { _nmod_vec_scalar_addmul_nmod(xs[j], x, M->c, nmod_neg(xs[j][i], M->mod), M->mod); } diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index fa1326c52a..6376a9539c 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -51,7 +51,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) if (P[r] >= 0) continue; if (pr==-1 || (row->nnz < prow->nnz)) pr = r, prow = row; } - if(pr == -1) continue; + if (pr == -1) continue; P[pr] = rank; cinv = nmod_inv(*nmod_sparse_vec_at(prow, pc), M->mod); @@ -61,7 +61,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) for (j = 0; j < pcol->nnz; ++j) { r = pcol->entries[j].ind, row = &M->rows[r]; - if(r==pr) {pcol->entries[j].val = UWORD(0); continue;} + if (r==pr) {pcol->entries[j].val = UWORD(0); continue;} cc = nmod_neg(*nmod_sparse_vec_at(row, pc), M->mod); nmod_sparse_vec_scalar_addmul_nmod(row, row, prow, cc, M->mod); @@ -72,7 +72,7 @@ slong nmod_sparse_mat_rref(nmod_sparse_mat_t M) for (j = 0; j < prow->nnz; ++j) { c = prow->entries[j].ind, col = &Mt->rows[c]; - if(c >= M->c || c==pc) continue; + if (c >= M->c || c==pc) continue; cc = nmod_neg(*nmod_sparse_vec_at(col, pr), M->mod); nmod_sparse_vec_scalar_addmul_nmod(col, col, pcol, cc, M->mod); } diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index 68aae02594..37f0b7ba86 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -25,7 +25,8 @@ /* the column c + b and zero out the row c. In addition, we reorder */ /* columns so that ones corresponding to zero entries in S go first. */ /* See Figure 1 in the above reference for details. */ -static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { +static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) +{ const slong b = Torig->r; slong pc, i, j, rk = 0; @@ -42,8 +43,8 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) { /* Set permutation to have previously dependent vectors at front */ P = flint_malloc(b*sizeof(*P)); j = 0; - for (i = 0; i < b; ++i) if(!S[i]) P[j++] = i; - for (i = 0; i < b; ++i) if(S[i]) P[j++] = i; + for (i = 0; i < b; ++i) if (!S[i]) P[j++] = i; + for (i = 0; i < b; ++i) if (S[i]) P[j++] = i; for (j = 0; j < b; ++j) { @@ -90,12 +91,13 @@ static void kill_columns(nmod_mat_t M, int *good) { slong r, c; for (c = 0; c < M->c; ++c) - if(good[c] == 0) + if (good[c] == 0) for (r = 0; r < M->r; ++r) M->rows[r][c] = UWORD(0); } -int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) { +int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state) +{ int ret = 0; slong i, prev_i, next_i, iter, cur_dim, total_dim = 0; nmod_sparse_mat_t Mt; /* Transpose of M, we work with A = MtM */ @@ -151,7 +153,7 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ i = iter % 3; next_i = (iter + 1) % 3; prev_i = (iter + 2) % 3; - if(iter>=2) + if (iter >= 2) { /* Compute the F value for this round (minus the final term) */ nmod_mat_addmul(DEF, I, VtAV, &nWi[prev_i]); @@ -189,14 +191,14 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ * F = -W_{i-2}^-1(I - V_{i-1}^tAV_{i-1}W_{i-1}^-1) * ((AV_{i-1})^tAV_{i-1}S_{i-1}S_{i-1}^t + V_{i-1}^tAV_{i-1})S_iS_i^t **/ - if(iter >= 2) + if (iter >= 2) { /* V_{i+1} = V_{i-2} F */ kill_columns(DEF, SSt); nmod_mat_mul(VSSt, &V[next_i], DEF); nmod_mat_set(&V[next_i], VSSt); } - if(iter >= 1) + if (iter >= 1) { /* V_{i+1} += V_{i-1} E */ nmod_mat_mul(DEF, &nWi[prev_i], VtAV); @@ -238,7 +240,8 @@ int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_ return ret; } -int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) { +int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state) +{ int ret = 1; mp_ptr x2, b; x2 = _nmod_vec_init(M->c); @@ -246,7 +249,7 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M _nmod_vec_randtest(x, state, M->c, M->mod); nmod_sparse_mat_mul_vec(b, M, x); - if(nmod_sparse_mat_solve_block_lanczos(x2, M, b, block_size, state) == 0) ret = 0; /* Lanczos failed */ + if (nmod_sparse_mat_solve_block_lanczos(x2, M, b, block_size, state) == 0) ret = 0; /* Lanczos failed */ if (ret) { _nmod_vec_sub(x, x, x2, M->c, M->mod); diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index 7d0ec45756..ab68719ddb 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -54,8 +54,8 @@ static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) /* Set the pivot row to be the minimum degree row incident on column pc */ pr = b + pc; for (r = 0; r < b; r++) - if(gamma[r] && M->rows[r][pc] && d[r] < d[pr]) pr = r; - if(M->rows[pr][pc] == UWORD(0)) continue; + if (gamma[r] && M->rows[r][pc] && d[r] < d[pr]) pr = r; + if (M->rows[pr][pc] == UWORD(0)) continue; /* Try to move pivot row to appropriate position (if not already there) */ @@ -72,7 +72,7 @@ static void coppersmith_aux_gauss(nmod_mat_t M, slong *d) /* Do Gaussian elimination on first b rows */ for (r = 0; r < b; ++r) - if(gamma[r] && M->rows[r][pc]) + if (gamma[r] && M->rows[r][pc]) _nmod_vec_scalar_addmul_nmod(M->rows[r], M->rows[pr], M->c, nmod_neg(nmod_mul(M->rows[r][pc], cinv, M->mod), M->mod), M->mod); } @@ -176,7 +176,7 @@ static void make_block_sum(mp_ptr x, const nmod_mat_struct *S, const slong *d, c _nmod_vec_zero(x, M->c); for (i = iter = 0; iter <= d[l]; ++iter, i = 1 - i) { - if(iter > 0) nmod_sparse_mat_mul_mat(&Z[i], M, &Z[1-i]); + if (iter > 0) nmod_sparse_mat_mul_mat(&Z[i], M, &Z[1-i]); nmod_mat_mul_vec(xi, &Z[i], S[dd + iter].rows[l]); _nmod_vec_add(x, x, xi, M->c, M->mod); } @@ -205,7 +205,7 @@ int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, m nmod_sparse_mat_append_row(Mb, z); ret = nmod_sparse_mat_nullvector_block_wiedemann(x1, Mb, block_size, state); - if(ret && x1[M->c] != UWORD(0)) + if (ret && x1[M->c] != UWORD(0)) { _nmod_vec_scalar_mul_nmod(x, x1, M->c, nmod_neg(nmod_inv(x1[M->c], M->mod), M->mod), M->mod); good = 1; @@ -232,7 +232,7 @@ int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t for (k = 0; k < ns; ++k) nmod_mat_init(&S[k], block_size, block_size, M->mod.n); for (l = 0; l < 3; ++l) nmod_mat_init(&Y[l], M->c, block_size, M->mod.n); do nmod_mat_randfull(&Y[0], state); - while(nmod_mat_is_zero(&Y[0])); + while (nmod_mat_is_zero(&Y[0])); nmod_sparse_mat_mul_mat(&Y[1], M, &Y[0]); make_block_sequences(S, ns, M, &Y[1]); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 0e1e908398..0b08e35543 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -82,7 +82,8 @@ int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr return ret; } -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) { +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) +{ int ret = 1; mp_ptr x2, b; x2 = _nmod_vec_init(M->c); @@ -90,7 +91,7 @@ int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flin _nmod_vec_randtest(x, state, M->c, M->mod); nmod_sparse_mat_mul_vec(b, M, x); - if(nmod_sparse_mat_solve_lanczos(x2, M, b, state) == 0) ret = 0; /* Lanczos failed */ + if (nmod_sparse_mat_solve_lanczos(x2, M, b, state) == 0) ret = 0; /* Lanczos failed */ if (ret) { _nmod_vec_sub(x, x, x2, M->c, M->mod); diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index fdd9bd2c57..5c0d40b92e 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -42,7 +42,7 @@ static slong find_min_poly(mp_limb_t *s, slong N, nmod_t mod) for (i = 0; i <= deg_B; ++i) C[m+i] = nmod_addmul(C[m+i], B[i], c, mod); deg_C = FLINT_MAX(deg_C, deg_B + m); - while(C[deg_C] == UWORD(0)) --deg_C; /* Probably unnecessary */ + while (C[deg_C] == UWORD(0)) --deg_C; /* Probably unnecessary */ if (2*L <= n) /* Increase number of errors */ { @@ -69,7 +69,7 @@ static void make_sequences(mp_limb_t **s, slong ns, slong len, const nmod_sparse memcpy(y, b, M->r*sizeof(*y)); for (j = 0; j < len; ++j) { - if(j > 0) nmod_sparse_mat_mul_vec(My, M, y), memcpy(y, My, M->r*sizeof(*y)); + if (j > 0) nmod_sparse_mat_mul_vec(My, M, y), memcpy(y, My, M->r*sizeof(*y)); for (i = 0; i < ns; ++i) s[i][j] = y[i]; } _nmod_vec_clear(y); @@ -99,7 +99,7 @@ int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcp slong i, L, ret = 0, ns = FLINT_MIN(M->r, 2), len = 2*M->r + 1; mp_limb_t **s; mp_ptr Mx; - if(M->r != M->c) return 0; /* TBD: reduce to square */ + if (M->r != M->c) return 0; /* TBD: reduce to square */ if (_nmod_vec_is_zero(b, M->c)) { _nmod_vec_zero(x, M->c); @@ -117,7 +117,7 @@ int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcp { /* Get minimal polynomial */ L = find_min_poly(s[i], len, M->mod); - if(s[i][0]==0) continue; + if (s[i][0]==0) continue; /* If \sum_{j = 0}^L s_ijM^jb = 0 => x = -1/s[0]\sum_{j = 0}^{L-1} s_i(j-1) M^jb solves Mx = b */ make_sum(x, s[i]+1, L, M, b); @@ -148,7 +148,7 @@ int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, fl _nmod_vec_randtest(x, state, M->r, M->mod); nmod_sparse_mat_mul_vec(b, M, x); - if(M->r != M->c) return 0; /* TBD: reduce to square */ + if (M->r != M->c) return 0; /* TBD: reduce to square */ make_sequences(s, ns, len, M, b); for (i = 0; i < ns && ret == 0; ++i) diff --git a/nmod_sparse_mat/strong_echelon_form.c b/nmod_sparse_mat/strong_echelon_form.c index 22965ff882..1f9ec5bc7c 100644 --- a/nmod_sparse_mat/strong_echelon_form.c +++ b/nmod_sparse_mat/strong_echelon_form.c @@ -46,7 +46,7 @@ _n_ppio(mp_ptr ppi, mp_ptr ppo, mp_limb_t a, mp_limb_t b) c = n_gcd(a, b); M->r = a/c; g = n_gcd(c, M->r); - while( g != 1 ) + while ( g != 1 ) { c = c * g; M->r = M->r/g; diff --git a/nmod_sparse_mat/test/t-inv.c b/nmod_sparse_mat/test/t-inv.c index 1131f50b78..2599e18bef 100644 --- a/nmod_sparse_mat/test/t-inv.c +++ b/nmod_sparse_mat/test/t-inv.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 100; rep++) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} do r = n_randint(state, 200), c = n_randint(state, 200); while (r==UWORD(0) || c==UWORD(0)); @@ -49,7 +49,8 @@ main(void) nmod_sparse_mat_inv(Ai, A); nmod_sparse_mat_mul_mat(dAiA, Ai, dA); nmod_mat_rref(dA); - if(!nmod_mat_equal(dAiA, dA)) { + if (!nmod_mat_equal(dAiA, dA)) + { flint_printf("FAIL!\n"); flint_printf("A^-1 x A = "); nmod_mat_print_pretty(dAiA); diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c index 842ea29a68..4a99bf4302 100644 --- a/nmod_sparse_mat/test/t-lu.c +++ b/nmod_sparse_mat/test/t-lu.c @@ -53,18 +53,22 @@ main(void) nmod_mat_init(dLU, r, c, n); /* Check that L is lower triangular (with ones on diagonal up to rank) */ - for (i = 0; i < r; ++i) { - if(i < rk && *nmod_sparse_vec_at(&L->rows[i], i) != UWORD(1)) + for (i = 0; i < r; ++i) + { + if (i < rk && *nmod_sparse_vec_at(&L->rows[i], i) != UWORD(1)) { flint_printf("FAIL: L does not have unit diagonal up to the rank\n"); } - for (j = 0; j < L->rows[i].nnz; ++j) { + for (j = 0; j < L->rows[i].nnz; ++j) + { nmod_sparse_entry_struct *e = &L->rows[i].entries[j]; - if(e->ind > i) { + if (e->ind > i) + { flint_printf("FAIL: L not lower triangular\n"); abort(); } - if(e->ind >= rk) { + if (e->ind >= rk) + { flint_printf("FAIL: L not trivial past the rank\n"); nmod_sparse_mat_print_pretty(L); abort(); @@ -72,20 +76,23 @@ main(void) } } /* Check that U is upper triangular (with nonzero diagonal up to rank) */ - for (i = 0; i < r; ++i) { - if(i < rk && *nmod_sparse_vec_at(&U->rows[i], i) == UWORD(0)) + for (i = 0; i < r; ++i) + { + if (i < rk && *nmod_sparse_vec_at(&U->rows[i], i) == UWORD(0)) { flint_printf("FAIL: U does not have nonzero diagonal\n"); abort(); } - if(i >= rk && U->rows[i].nnz != UWORD(0)) + if (i >= rk && U->rows[i].nnz != UWORD(0)) { flint_printf("FAIL: U not trivial pas the rank\n"); abort(); } - for (j = 0; j < U->rows[i].nnz; ++j) { + for (j = 0; j < U->rows[i].nnz; ++j) + { nmod_sparse_entry_struct *e = &U->rows[i].entries[j]; - if(e->ind < i) { + if (e->ind < i) + { flint_printf("FAIL: U not upper triangular\n"); abort(); } @@ -97,7 +104,8 @@ main(void) nmod_sparse_mat_from_dense(LU, dLU); nmod_sparse_mat_permute_rows(A, P); nmod_sparse_mat_permute_cols(A, Q); - if(!nmod_sparse_mat_equal(A, LU)) { + if (!nmod_sparse_mat_equal(A, LU)) + { flint_printf("FAIL: PAQ != LU\n"); flint_printf("PAQ="); nmod_sparse_mat_print_pretty(A); diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c index 9792da5527..d704fdeea2 100644 --- a/nmod_sparse_mat/test/t-nullspace.c +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -38,7 +38,7 @@ main(void) for (rep = 0; rep < nreps; ++rep) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} c = r = 200 + n_randint(state, 100); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); @@ -60,7 +60,7 @@ main(void) /* if (i == 0 && rk[0] == UWORD(0) ) { nmod_mat_clear(X); break;} */ /* gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); */ - if(X->c==0) continue; + if (X->c==0) continue; nmod_mat_init(AX, A->r, X->c, n); nmod_sparse_mat_mul_mat(AX, A, X); /*nmod_mat_print_pretty(AX); */ @@ -73,7 +73,7 @@ main(void) nmod_mat_print_pretty(X); abort(); } - if(rk[i] != rk[0]) discrep[i] += 1; + if (rk[i] != rk[0]) discrep[i] += 1; nmod_mat_clear(X); nmod_mat_clear(AX); @@ -83,11 +83,11 @@ main(void) FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - for(i = 0; i < 6; ++i) + for (i = 0; i < 6; ++i) { flint_printf("Found nullspace with %s\n", names[i]); /* flint_printf("\tAverage time %lf:\n", elapsed[i]/nreps); */ - if(discrep[i] > 0) + if (discrep[i] > 0) flint_printf("\tFailed to find full nullspace in %wd/%wd trials\n", discrep[i], nreps); } diff --git a/nmod_sparse_mat/test/t-rref.c b/nmod_sparse_mat/test/t-rref.c index aa5c1345c0..5ff22bd85d 100644 --- a/nmod_sparse_mat/test/t-rref.c +++ b/nmod_sparse_mat/test/t-rref.c @@ -47,7 +47,8 @@ main(void) nmod_sparse_mat_rref(A); nmod_mat_rref(dA); nmod_sparse_mat_from_dense(B, dA); - if(!nmod_sparse_mat_equal(A, B)) { + if (!nmod_sparse_mat_equal(A, B)) + { flint_printf("FAIL!\n"); abort(); } diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index c63b739ad6..9c87f2b960 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -41,7 +41,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} c = r = 100 + n_randint(state, 50); do n = n_randtest_not_zero(state); @@ -67,10 +67,10 @@ main(void) { case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; case 1: ret = nmod_sparse_mat_solve_lu(x2, A, b); break; - case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret == 0 && ++iter < 30); break; - case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while(ret == 0 && ++iter < 30); break; + case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while (ret == 0 && ++iter < 30); break; + case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while (ret == 0 && ++iter < 30); break; case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; - case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; + case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while (ret == 0 && ++iter < 3); break; } /*gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec);*/ diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index ea937c93cf..1e2dd3f30d 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -32,7 +32,7 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) for (i = 0; i < A->rows[r].nnz; ++i) { c = A->rows[r].entries[i].ind; - if(c >= A->c) break; + if (c >= A->c) break; B->rows[c].nnz += 1; } } @@ -51,7 +51,7 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) { Ae = &A->rows[r].entries[i]; c = Ae->ind; - if(c >= A->c) break; + if (c >= A->c) break; j = B->rows[c].nnz++; Be = &B->rows[c].entries[j]; Be->ind = r, Be->val = Ae->val; diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index f5226bef96..6357bd92d0 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -110,7 +110,7 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_set_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) { mp_limb_t *oval = nmod_sparse_vec_at(v, ind); - if(oval == NULL) + if (oval == NULL) { v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); v->entries[v->nnz].ind = ind; @@ -232,9 +232,9 @@ slong _nmod_sparse_vector_merge_descend(nmod_sparse_entry_struct **we, { slong uind = (*ue==u->entries) ? -1 : (*ue-1)->ind; slong vind = (*ve==v->entries) ? -1 : (*ve-1)->ind; - if(uind == -1 && vind == -1) return -1; - if(uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} - if(uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} + if (uind == -1 && vind == -1) return -1; + if (uind == vind) {--*ue, --*ve, --*we; (*we)->ind = uind; return 2;} + if (uind < vind) {--*ve, --*we; (*we)->ind = vind; return 1;} --*ue, --*we; (*we)->ind = uind; return 0; } @@ -243,7 +243,7 @@ NMOD_SPARSE_VEC_INLINE void _nmod_sparse_vector_shift_left (nmod_sparse_vec_t v, slong amt) { if (amt == v->nnz) nmod_sparse_vec_clear(v); - else if(amt > 0) + else if (amt > 0) { v->nnz -= amt; memmove(v->entries, v->entries + amt, v->nnz*sizeof(*v->entries)); diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c index d634052964..835e56e579 100644 --- a/nmod_sparse_vec/dot_dense.c +++ b/nmod_sparse_vec/dot_dense.c @@ -15,7 +15,8 @@ #include "flint.h" #include "nmod_sparse_vec.h" -mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) { +mp_limb_t nmod_sparse_vec_dot_dense(const nmod_sparse_vec_t u, mp_srcptr v, nmod_t mod) +{ slong i; mp_limb_t ret = UWORD(0); for (i = 0; i < u->nnz; ++i) NMOD_ADDMUL(ret, u->entries[i].val, v[u->entries[i].ind], mod); diff --git a/nmod_sparse_vec/split.c b/nmod_sparse_vec/split.c index 3d8b2bc541..af08c7f590 100644 --- a/nmod_sparse_vec/split.c +++ b/nmod_sparse_vec/split.c @@ -18,14 +18,14 @@ void nmod_sparse_vec_split(nmod_sparse_vec_t res1, nmod_sparse_vec_t res2, const nmod_sparse_vec_t vec, slong ind) { slong i; - for (i = 0; i < vec->nnz; ++i) if(vec->entries[i].ind >= ind) break; - if(i==0) nmod_sparse_vec_clear(res1); + for (i = 0; i < vec->nnz; ++i) if (vec->entries[i].ind >= ind) break; + if (i==0) nmod_sparse_vec_clear(res1); else { res1->nnz = i; res1->entries = flint_realloc(res1->entries, res1->nnz*sizeof(*res1->entries)); memcpy(res1->entries, vec->entries, res1->nnz*sizeof(*res1->entries)); } - if(i==vec->nnz) nmod_sparse_vec_clear(res2); + if (i==vec->nnz) nmod_sparse_vec_clear(res2); else { res2->nnz = vec->nnz - i; res2->entries = flint_realloc(res2->entries, res2->nnz*sizeof(*res2->entries)); diff --git a/nmod_sparse_vec/test/t-init_clear.c b/nmod_sparse_vec/test/t-init_clear.c index 608aa97405..1d320b7260 100644 --- a/nmod_sparse_vec/test/t-init_clear.c +++ b/nmod_sparse_vec/test/t-init_clear.c @@ -72,7 +72,7 @@ main(void) flint_printf("FAIL: found value %wd (not in (0,%wd))\n", e->val, n); abort(); } - if (i>0 && e->ind <= e[-1].ind) + if (i > 0 && e->ind <= e[-1].ind) { flint_printf("FAIL: found index %wd <= previous index %wd\n", e->ind, e[-1].ind); abort(); From 8c07eec4122f83f385a8eb1658e32550f967be2b Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 28 Apr 2020 22:49:00 -0700 Subject: [PATCH 22/42] Cleaned up some tests --- fmpz_sparse_mat/test/t-hnf_minors.c | 1 - fmpz_sparse_mat/test/t-howell_form_mod.c | 3 +-- fmpz_sparse_mat/test/t-init_clear.c | 2 +- fmpz_sparse_mat/test/t-mul.c | 2 +- fmpz_sparse_mat/test/t-neg.c | 2 +- fmpz_sparse_mat/test/t-solve_dixon_den.c | 2 +- fmpz_sparse_vec/test/t-add.c | 2 +- fmpz_sparse_vec/test/t-gauss_elim.c | 2 +- fmpz_sparse_vec/test/t-scalar_divexact.c | 3 --- 9 files changed, 7 insertions(+), 12 deletions(-) diff --git a/fmpz_sparse_mat/test/t-hnf_minors.c b/fmpz_sparse_mat/test/t-hnf_minors.c index 57983a8c9c..50c9a326a7 100644 --- a/fmpz_sparse_mat/test/t-hnf_minors.c +++ b/fmpz_sparse_mat/test/t-hnf_minors.c @@ -30,7 +30,6 @@ main(void) for (rep = 0; rep < nreps; rep++) { - if (rep % 20 == 0) {flint_printf("."); fflush(stdout);} bits = 2 + n_randint(state, 100); r = n_randint(state, 20); c = n_randint(state, 20); diff --git a/fmpz_sparse_mat/test/t-howell_form_mod.c b/fmpz_sparse_mat/test/t-howell_form_mod.c index 26f5aa1196..cbe3be54a3 100644 --- a/fmpz_sparse_mat/test/t-howell_form_mod.c +++ b/fmpz_sparse_mat/test/t-howell_form_mod.c @@ -20,7 +20,6 @@ main(void) { slong rep, r, c, min_nnz, max_nnz, bits, rk, rk2, nreps = 10; fmpz_t mod; - slong *P; fmpz_mat_t dH; fmpz_sparse_mat_t A, H, H2; FLINT_TEST_INIT(state); @@ -30,7 +29,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { - bits = 64 + n_randint(state, 10); + bits = 64 + n_randint(state, 70); c = n_randint(state, 10); r = c + n_randint(state, 10); min_nnz = 0; diff --git a/fmpz_sparse_mat/test/t-init_clear.c b/fmpz_sparse_mat/test/t-init_clear.c index a70e0d0a46..5d023ee3ca 100644 --- a/fmpz_sparse_mat/test/t-init_clear.c +++ b/fmpz_sparse_mat/test/t-init_clear.c @@ -29,7 +29,7 @@ main(void) for (rep = 0; rep < 100; rep++) { do bits = n_randint(state, 200); - while ((bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-mul.c b/fmpz_sparse_mat/test/t-mul.c index 5836cef308..bb8586efc0 100644 --- a/fmpz_sparse_mat/test/t-mul.c +++ b/fmpz_sparse_mat/test/t-mul.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 70); - while ((bits < UWORD(2)); + while (bits < UWORD(2)); r = 1 + n_randint(state, 20); c = 1 + n_randint(state, 20); k = 1 + n_randint(state, 20); diff --git a/fmpz_sparse_mat/test/t-neg.c b/fmpz_sparse_mat/test/t-neg.c index e607563335..645c690981 100644 --- a/fmpz_sparse_mat/test/t-neg.c +++ b/fmpz_sparse_mat/test/t-neg.c @@ -28,7 +28,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 200); - while ((bits < UWORD(2)); + while (bits < UWORD(2)); r = n_randint(state, 200); c = n_randint(state, 200); fmpz_sparse_mat_init(A, r, c); diff --git a/fmpz_sparse_mat/test/t-solve_dixon_den.c b/fmpz_sparse_mat/test/t-solve_dixon_den.c index 65146a373c..54aba9b8b2 100644 --- a/fmpz_sparse_mat/test/t-solve_dixon_den.c +++ b/fmpz_sparse_mat/test/t-solve_dixon_den.c @@ -87,6 +87,6 @@ main(void) FLINT_TEST_CLEANUP(state); - flint_printf("PASS\nNum bad fail: %wd\n", num_bad_fail); + flint_printf("PASS\n"); return 0; } diff --git a/fmpz_sparse_vec/test/t-add.c b/fmpz_sparse_vec/test/t-add.c index 973f093057..a2ff49d3ab 100644 --- a/fmpz_sparse_vec/test/t-add.c +++ b/fmpz_sparse_vec/test/t-add.c @@ -31,7 +31,7 @@ main(void) for (rep = 0; rep < 1000; rep++) { do bits = n_randint(state, 256); - while ((bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 200); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-gauss_elim.c b/fmpz_sparse_vec/test/t-gauss_elim.c index a3fc3afc17..60cba8d1b4 100644 --- a/fmpz_sparse_vec/test/t-gauss_elim.c +++ b/fmpz_sparse_vec/test/t-gauss_elim.c @@ -32,7 +32,7 @@ main(void) for (rep = 0; rep < 10; rep++) { do bits = n_randint(state, 10); - while ((bits < UWORD(2)); + while (bits < UWORD(2)); len = n_randint(state, 20); nnz = n_randint(state, len+1); diff --git a/fmpz_sparse_vec/test/t-scalar_divexact.c b/fmpz_sparse_vec/test/t-scalar_divexact.c index 47d2f2b88f..d3681dab28 100644 --- a/fmpz_sparse_vec/test/t-scalar_divexact.c +++ b/fmpz_sparse_vec/test/t-scalar_divexact.c @@ -46,11 +46,8 @@ main(void) fmpz_sparse_vec_randtest(u, state, nnz, len, bits); fmpz_sparse_vec_randtest(v, state, nnz, len, bits); - flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); - flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); fmpz_sparse_vec_scalar_mul_fmpz(v, u, c); - flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); fmpz_sparse_vec_scalar_divexact_fmpz(w, v, c); if (!fmpz_sparse_vec_equal(w, u, 0)) From f8f4b767eac8ebb9419d2a10219a33a4465438e9 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 29 Apr 2020 23:19:12 -0700 Subject: [PATCH 23/42] Changed mods -> smod, need to change function name later --- fmpz_sparse_vec/scalar_mods.c | 2 +- fmpz_sparse_vec/test/t-scalar_mod.c | 4 ++-- test/t-heap.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fmpz_sparse_vec/scalar_mods.c b/fmpz_sparse_vec/scalar_mods.c index 16db4c12d1..f71d70d8cd 100644 --- a/fmpz_sparse_vec/scalar_mods.c +++ b/fmpz_sparse_vec/scalar_mods.c @@ -25,7 +25,7 @@ void fmpz_sparse_vec_scalar_mods_fmpz(fmpz_sparse_vec_t v, const fmpz_sparse_vec for (i = ind = 0; i < v->nnz; ++i) { v->entries[ind].ind = v->entries[i].ind; - fmpz_mods(v->entries[ind].val, v->entries[i].val, mod); + fmpz_smod(v->entries[ind].val, v->entries[i].val, mod); if (!fmpz_is_zero(v->entries[ind].val)) ++ind; } _fmpz_sparse_vec_resize(v, ind); diff --git a/fmpz_sparse_vec/test/t-scalar_mod.c b/fmpz_sparse_vec/test/t-scalar_mod.c index 0210c9faa1..f34407168f 100644 --- a/fmpz_sparse_vec/test/t-scalar_mod.c +++ b/fmpz_sparse_vec/test/t-scalar_mod.c @@ -74,7 +74,7 @@ main(void) fmpz_sparse_vec_scalar_mods_fmpz(v, u, mod); for (i = j = 0; i < u->nnz; ++i) { - fmpz_mods(c, u->entries[i].val, mod); + fmpz_smod(c, u->entries[i].val, mod); if (fmpz_is_zero(c)) continue; if (u->entries[i].ind != v->entries[j].ind) { @@ -127,7 +127,7 @@ main(void) for (i = j = 0; i < u->nnz; ++i) { - fmpz_mods(c, u->entries[i].val, mod); + fmpz_smod(c, u->entries[i].val, mod); if (fmpz_is_zero(c)) continue; if (u->entries[i].ind != v->entries[j].ind) { diff --git a/test/t-heap.c b/test/t-heap.c index 2f6b90212c..7a6aa86c30 100644 --- a/test/t-heap.c +++ b/test/t-heap.c @@ -44,7 +44,7 @@ void check_heap(heap_t h, slong *vals) int main(void) { - slong rep, num, *vals, nreps = 1000, i, j, val, oval; + slong rep, num, *vals, nreps = 1000, i, val, oval; heap_t h; FLINT_TEST_INIT(state); From e0448b798482dfe4ea6acd3c45a4cd1db17dcb22 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 25 Mar 2020 18:50:39 -0700 Subject: [PATCH 24/42] Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters --- CMakeLists.txt | 2 +- nmod_sparse_mat/add.c | 54 ++++++++++++++++++++ nmod_sparse_mat/append_row.c | 33 +++++++++++++ nmod_sparse_mat/clear.c | 31 ++++++++++++ nmod_sparse_mat/concat_horizontal.c | 48 ++++++++++++++++++ nmod_sparse_mat/concat_vertical.c | 32 ++++++++++++ nmod_sparse_mat/equal.c | 50 +++++++++++++++++++ nmod_sparse_mat/from_dense.c | 47 ++++++++++++++++++ nmod_sparse_mat/from_entries.c | 8 --- nmod_sparse_mat/init.c | 31 ++++++++++++ nmod_sparse_mat/mul_mat.c | 34 +++++++++++++ nmod_sparse_mat/mul_vec.c | 34 +++++++++++++ nmod_sparse_mat/neg.c | 26 ++++++++++ nmod_sparse_mat/one.c | 31 ++++++++++++ nmod_sparse_mat/scalar_mul.c | 49 +++++++++++++++++++ nmod_sparse_mat/set.c | 35 +++++++++++++ nmod_sparse_mat/sub.c | 57 ++++++++++++++++++++++ nmod_sparse_mat/swap.c | 24 +++++++++ nmod_sparse_mat/test/t-concat_horizontal.c | 14 ++++++ nmod_sparse_mat/test/t-concat_vertical.c | 9 ++++ nmod_sparse_mat/test/t-construct.c | 17 +++++++ nmod_sparse_mat/to_dense.c | 28 +++++++++++ nmod_sparse_mat/window_clear.c | 23 +++++++++ nmod_sparse_mat/zero.c | 26 ++++++++++ 24 files changed, 734 insertions(+), 9 deletions(-) create mode 100644 nmod_sparse_mat/add.c create mode 100644 nmod_sparse_mat/append_row.c create mode 100644 nmod_sparse_mat/clear.c create mode 100644 nmod_sparse_mat/concat_horizontal.c create mode 100644 nmod_sparse_mat/concat_vertical.c create mode 100644 nmod_sparse_mat/equal.c create mode 100644 nmod_sparse_mat/from_dense.c create mode 100644 nmod_sparse_mat/init.c create mode 100644 nmod_sparse_mat/mul_mat.c create mode 100644 nmod_sparse_mat/mul_vec.c create mode 100644 nmod_sparse_mat/neg.c create mode 100644 nmod_sparse_mat/one.c create mode 100644 nmod_sparse_mat/scalar_mul.c create mode 100644 nmod_sparse_mat/set.c create mode 100644 nmod_sparse_mat/sub.c create mode 100644 nmod_sparse_mat/swap.c create mode 100644 nmod_sparse_mat/to_dense.c create mode 100644 nmod_sparse_mat/window_clear.c create mode 100644 nmod_sparse_mat/zero.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a74acbd3de..5fcfa4a546 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly - nmod_poly_factor arith mpn_extras nmod_mat fmpq fmpq_vec fmpq_mat padic + nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve double_extras d_vec d_mat padic_poly padic_mat qadic diff --git a/nmod_sparse_mat/add.c b/nmod_sparse_mat/add.c new file mode 100644 index 0000000000..b92d218d38 --- /dev/null +++ b/nmod_sparse_mat/add.c @@ -0,0 +1,54 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + +void +nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + slong i; + + C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); + memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); + C->nnz = 0; + + for (i = 0; i < C->r; i++) + { + C->row_starts[i] = C->nnz; + nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; + nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; + nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; + slong j = 0; + slong k = 0; + slong nnz = 0; + /* Interleave ith rows until one runs out */ + while(j < A->row_nnz[i] && k < B->row_nnz[i]) { + slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); + if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; + if(Be[k].col == col) Ce[nnz].val = nmod_add(Ce[nnz].val, Be[k++].val, C->mod); + if(Ce[nnz].val != UWORD(0)) ++nnz; + } + /* Add remainder of A row */ + for(; jrow_nnz[i]; ++j, ++nnz) Ce[nnz] = Ae[j]; + /* Add remainder of B row */ + for(; krow_nnz[i]; ++k, ++nnz) Ce[nnz]= Be[k]; + + C->row_nnz[i] = nnz; + C->nnz += nnz; + } + _nmod_sparse_mat_set_c(C); + C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); +} diff --git a/nmod_sparse_mat/append_row.c b/nmod_sparse_mat/append_row.c new file mode 100644 index 0000000000..1d0e4ad872 --- /dev/null +++ b/nmod_sparse_mat/append_row.c @@ -0,0 +1,33 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Elements must be ordered by row then col */ +void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong * cols, mp_limb_t * vals, slong nnz) +{ + slong i; + mat->entries = flint_realloc(mat->entries, (mat->nnz + nnz)* sizeof(*mat->entries)); + mat->row_starts[row] = mat->nnz; + mat->row_nnz[row] = nnz; + + nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[row]; + for(i = 0; i < nnz; i++) { + e[i].col = cols[i]; + e[i].val = vals[i]; + if(e[i].col >= mat->c) mat->c = e->col + 1; + } + mat->nnz += nnz; +} diff --git a/nmod_sparse_mat/clear.c b/nmod_sparse_mat/clear.c new file mode 100644 index 0000000000..9aec210a46 --- /dev/null +++ b/nmod_sparse_mat/clear.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_clear(nmod_sparse_mat_t mat) +{ + if(mat->entries) + { + flint_free(mat->entries); + } + if(mat->row_starts) { + flint_free(mat->row_starts); + } + if(mat->row_nnz) { + flint_free(mat->row_nnz); + } +} diff --git a/nmod_sparse_mat/concat_horizontal.c b/nmod_sparse_mat/concat_horizontal.c new file mode 100644 index 0000000000..b41849a0ef --- /dev/null +++ b/nmod_sparse_mat/concat_horizontal.c @@ -0,0 +1,48 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + if(res->r == 0) return; + if(mat1->c == 0) { + nmod_sparse_mat_set(res, mat2); + return; + } + if(mat2->c == 0) { + nmod_sparse_mat_set(res, mat1); + return; + } + slong i, j; + res->c = mat1->c + mat2->c; + res->nnz = mat1->nnz + mat2->nnz; + res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); + + for (i = 0; i < res->r; i++) + { + res->row_starts[i] = mat1->row_starts[i] + mat2->row_starts[i]; + nmod_sparse_mat_entry_struct *e = res->entries + res->row_starts[i]; + nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; + nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; + for(j = 0; j < mat1->row_nnz[i]; ++j, ++e, ++e1) { + e->col = e1->col; + e->val = e1->val; + } + for(j = 0; j < mat2->row_nnz[i]; ++j, ++e, ++e2) { + e->col = e2->col + mat1->c; + e->val = e2->val; + } + res->row_nnz[i] = mat1->row_nnz[i] + mat2->row_nnz[i]; + } +} diff --git a/nmod_sparse_mat/concat_vertical.c b/nmod_sparse_mat/concat_vertical.c new file mode 100644 index 0000000000..a964bf0f83 --- /dev/null +++ b/nmod_sparse_mat/concat_vertical.c @@ -0,0 +1,32 @@ +/* + Copyright (C) 2015 Elena Sergeicheva + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + + res->c = (mat1->c > mat2->c)?(mat1->c):(mat2->c); + res->nnz = mat1->nnz + mat2->nnz; + res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); + memcpy(res->entries, mat1->entries, mat1->nnz * sizeof(*res->entries)); + memcpy(res->entries + mat1->nnz, mat2->entries, mat2->nnz * sizeof(*res->entries)); + memcpy(res->row_starts, mat1->row_starts, mat1->r * sizeof(*res->row_starts)); + memcpy(res->row_starts+mat1->r, mat2->row_starts, mat2->r * sizeof(*res->row_starts)); + memcpy(res->row_nnz, mat1->row_nnz, mat1->r*sizeof(*res->row_nnz)); + memcpy(res->row_nnz+mat1->r, mat2->row_nnz, mat2->r*sizeof(*res->row_nnz)); + + for (i = 0; i < mat2->r; i++) + res->row_starts[mat1->r + i] += mat1->nnz; +} diff --git a/nmod_sparse_mat/equal.c b/nmod_sparse_mat/equal.c new file mode 100644 index 0000000000..98d0ad1922 --- /dev/null +++ b/nmod_sparse_mat/equal.c @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +int +nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + if (mat1->r != mat2->r) { + printf("Different number of rows\n"); + return 0; + } + + if (mat1->nnz != mat2->nnz) { + printf("Different number of nonzeroes\n"); + return 0; + } + + if (mat1->nnz == 0) + return 1; + + if(memcmp(mat1->row_nnz, mat2->row_nnz, mat1->r * sizeof(*mat1->row_nnz))) { + printf("Different row_nnz\n"); return 0; + } + + slong i, j; + for(i=0; ir; ++i) { + nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; + nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; + for(j=0; jrow_nnz[i]; ++j, ++e1, ++e2) { + if((e1->col - mat1->c_off != e2->col - mat2->c_off) || (e1->val != e2->val)) { + flint_printf("Mismatched row %d, entry %d\n", i, j); + return 0; + } + } + } + return 1; +} diff --git a/nmod_sparse_mat/from_dense.c b/nmod_sparse_mat/from_dense.c new file mode 100644 index 0000000000..ef7fdc6dba --- /dev/null +++ b/nmod_sparse_mat/from_dense.c @@ -0,0 +1,47 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Assumes B->c == A->r */ +void +nmod_sparse_mat_from_dense(nmod_sparse_mat_t B, const nmod_mat_t A) +{ + slong i, j; + if(A->r == 0) return; + if(A->c == 0) {nmod_sparse_mat_zero(B); return;} + B->entries = flint_realloc(B->entries, A->r * A->c * sizeof(*B->entries)); + B->nnz = 0; + B->c = 0; + for(i=0; i < A->r; ++i) { + B->row_starts[i] = B->nnz; + B->row_nnz[i] = 0; + for(j=0; j < A->c; ++j) { + if(A->rows[i][j] != UWORD(0)) { + B->entries[B->nnz].col = j; + B->entries[B->nnz].val = A->rows[i][j]; + B->row_nnz[i]++; + B->nnz++; + } + } + } + _nmod_sparse_mat_set_c(B); + if(B->nnz > 0) + B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); + else { + flint_free(B->entries); + B->entries = NULL; + } +} diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index 9b78f0842f..2c83f6511e 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -1,13 +1,5 @@ /* -<<<<<<< HEAD -<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters -======= - Copyright (C) 2011 Fredrik Johansson ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition This file is part of FLINT. diff --git a/nmod_sparse_mat/init.c b/nmod_sparse_mat/init.c new file mode 100644 index 0000000000..4601dcdc25 --- /dev/null +++ b/nmod_sparse_mat/init.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2010 William Hart + Copyright (C) 2010,2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + + +void +nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n) +{ + memset(mat, 0, sizeof(*mat)); + mat->r = rows; + mat->c = 0; + if(rows > 0) { + mat->row_starts = flint_calloc(rows, rows*sizeof(*mat->row_starts)); + mat->row_nnz = flint_calloc(rows, rows*sizeof(*mat->row_nnz)); + } + _nmod_sparse_mat_set_mod(mat, n); +} diff --git a/nmod_sparse_mat/mul_mat.c b/nmod_sparse_mat/mul_mat.c new file mode 100644 index 0000000000..28164c782b --- /dev/null +++ b/nmod_sparse_mat/mul_mat.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* TODO: save reductions to end? */ +void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) { + slong i,j,k; + if(Y->r == 0 || Y->c == 0) return; + memset(Y->entries, 0, Y->r * Y->c * sizeof(*Y->entries)); + nmod_sparse_mat_entry_struct *e = A->entries; + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++e) { + if(e->val==1) + _nmod_vec_add(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); + else if(e->val==A->mod.n-1) + _nmod_vec_sub(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); + else + _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->col], X->c, e->val, A->mod); + } + } +} diff --git a/nmod_sparse_mat/mul_vec.c b/nmod_sparse_mat/mul_vec.c new file mode 100644 index 0000000000..4e47c6f939 --- /dev/null +++ b/nmod_sparse_mat/mul_vec.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* TODO: save reductions to end? */ +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) { + slong i,j; + memset(y, 0, A->r * sizeof(*y)); + nmod_sparse_mat_entry_struct *e = A->entries; + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++e) { + if(e->val==1) + y[i] = nmod_add(y[i], x[e->col], A->mod); + else if(e->val==A->mod.n-1) + y[i] = nmod_sub(y[i], x[e->col], A->mod); + else + y[i] = nmod_add(y[i], nmod_mul(x[e->col], e->val, A->mod), A->mod); + } + } +} + diff --git a/nmod_sparse_mat/neg.c b/nmod_sparse_mat/neg.c new file mode 100644 index 0000000000..970bf71f17 --- /dev/null +++ b/nmod_sparse_mat/neg.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + +void +nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + slong i; + + nmod_sparse_mat_set(B, A); + for (i = 0; i < A->nnz; i++) + B->entries[i].val = nmod_neg(B->entries[i].val, B->mod); +} diff --git a/nmod_sparse_mat/one.c b/nmod_sparse_mat/one.c new file mode 100644 index 0000000000..3257bd97f8 --- /dev/null +++ b/nmod_sparse_mat/one.c @@ -0,0 +1,31 @@ +/* + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/*Function to convert a square matrix to an identity matrix + The matrix is assumed to be a square one*/ +void +nmod_sparse_mat_one(nmod_sparse_mat_t mat) +{ + mat->c = mat->nnz = mat->r; + mat->entries = flint_realloc(mat->entries, mat->r*sizeof(*mat->entries)); + slong i; + for(i = 0; i < mat->r; i++) { + mat->entries[i].val = 1; + mat->entries[i].col = i; + mat->row_starts[i] = i; + mat->row_nnz[i] = 1; + } +} diff --git a/nmod_sparse_mat/scalar_mul.c b/nmod_sparse_mat/scalar_mul.c new file mode 100644 index 0000000000..ff50dd81b8 --- /dev/null +++ b/nmod_sparse_mat/scalar_mul.c @@ -0,0 +1,49 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +void +nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) +{ + if (c == UWORD(0)) + { + nmod_sparse_mat_zero(B); + } + else if(c == UWORD(1)) + { + nmod_sparse_mat_set(B, A); + } + else if(c == B->mod.n - UWORD(1)) + { + nmod_sparse_mat_neg(B, A); + } + else + { + slong i; + nmod_sparse_mat_set(B, A); + if (A->nnz > 10 && A->mod.n < UWORD_HALF) + { + mp_limb_t w_pr = n_mulmod_precomp_shoup(c, A->mod.n); + for (i = 0; innz; i++) + B->entries[i].val = n_mulmod_shoup(c, B->entries[i].val, w_pr, A->mod.n); + } + else + { + for (i = 0; innz; i++) + B->entries[i].val = nmod_mul(c, B->entries[i].val, B->mod); + } + } +} diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c new file mode 100644 index 0000000000..76c1315409 --- /dev/null +++ b/nmod_sparse_mat/set.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +/* Assumes B->r == A->r */ +void +nmod_sparse_mat_set(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +{ + if (B == A) + return; + B->c = A->c; + B->nnz = A->nnz; + if(B->nnz == 0) { + flint_free(B->entries); + B->entries = NULL; + } else { + B->entries = flint_realloc(B->entries, A->nnz * sizeof(*B->entries)); + memcpy(B->entries, A->entries, A->nnz * sizeof(*B->entries)); + } + memcpy(B->row_starts, A->row_starts, A->r * sizeof(*B->row_starts)); + memcpy(B->row_nnz, A->row_nnz, A->r * sizeof(*B->row_nnz)); +} diff --git a/nmod_sparse_mat/sub.c b/nmod_sparse_mat/sub.c new file mode 100644 index 0000000000..80afd51edd --- /dev/null +++ b/nmod_sparse_mat/sub.c @@ -0,0 +1,57 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "nmod_vec.h" + + +void +nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + slong i; + + C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); + memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); + C->nnz = 0; + + for (i = 0; i < C->r; i++) + { + C->row_starts[i] = C->nnz; + nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; + nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; + nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; + slong j = 0; + slong k = 0; + slong nnz = 0; + /* Interleave ith rows until one runs out */ + while(j < A->row_nnz[i] && k < B->row_nnz[i]) { + slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); + if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; + if(Be[k].col == col) Ce[nnz].val = nmod_sub(Ce[nnz].val, Be[k++].val, C->mod); + if(Ce[nnz].val != UWORD(0)) ++nnz; + } + /* Add remainder of A row */ + for(; jrow_nnz[i]; ++j, ++nnz) + Ce[nnz] = Ae[j]; + /* Subtract remainder of B row */ + for(; krow_nnz[i]; ++k, ++nnz) + Ce[nnz] = Be[k], Ce[nnz].val = nmod_neg(Ce[nnz].val, C->mod); + + C->row_nnz[i] = nnz; + C->nnz += nnz; + } + _nmod_sparse_mat_set_c(C); + C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); +} diff --git a/nmod_sparse_mat/swap.c b/nmod_sparse_mat/swap.c new file mode 100644 index 0000000000..5657b63b05 --- /dev/null +++ b/nmod_sparse_mat/swap.c @@ -0,0 +1,24 @@ +/* + Copyright (C) 2014 Ashish Kedia + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) +{ + nmod_sparse_mat_t temp; + *temp = *mat1; + *mat1 = *mat2; + *mat2 = *temp; +} diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index a2b26bd4af..1d7429bc7f 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -56,6 +56,7 @@ int main(void) nmod_sparse_mat_print_pretty(A); flint_printf("B = \n"); nmod_sparse_mat_print_pretty(B); +<<<<<<< HEAD flint_printf("A | B = \n"); nmod_sparse_mat_print_pretty(C); flint_printf("window1 = \n"); @@ -80,6 +81,9 @@ int main(void) flint_printf("B = \n"); nmod_sparse_mat_print_pretty(B); flint_printf("A | B = \n"); +======= + flint_printf("A concat_horizontal B = \n"); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_print_pretty(C); flint_printf("window1 = \n"); nmod_sparse_mat_print_pretty(window1); @@ -88,6 +92,7 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } +<<<<<<< HEAD nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); @@ -95,6 +100,15 @@ int main(void) nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_sparse_mat_clear(C); +======= + + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(B); + nmod_sparse_mat_clear(C); + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters } diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index 5f61d34c6e..7c8f8a4d69 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -81,13 +81,22 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } +<<<<<<< HEAD nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); +======= +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_sparse_mat_clear(C); +<<<<<<< HEAD +======= + + nmod_sparse_mat_window_clear(window1); + nmod_sparse_mat_window_clear(window2); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters } diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 9ebecbf031..1fafcba1f9 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -66,6 +66,7 @@ main(void) if (!nmod_sparse_mat_equal(A, B)) { flint_printf("FAIL: A != B\n"); +<<<<<<< HEAD flint_printf("A = "); nmod_sparse_mat_print_pretty(A); flint_printf("B = "); @@ -81,6 +82,18 @@ main(void) nmod_sparse_mat_print_pretty(A); flint_printf("C = "); nmod_sparse_mat_print_pretty(C); +======= + abort(); + } + /* Construct C from rows of A */ + for(i=0; ir; ++i) { + nmod_sparse_mat_append_row(C, i, cols + A->row_starts[i], vals + A->row_starts[i], A->row_nnz[i]); + } + + if (!nmod_sparse_mat_equal(A, C)) + { + flint_printf("FAIL: A != C\n"); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters abort(); } flint_free(rows); @@ -88,6 +101,10 @@ main(void) flint_free(vals); nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); +<<<<<<< HEAD +======= + nmod_sparse_mat_clear(C); +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/to_dense.c b/nmod_sparse_mat/to_dense.c new file mode 100644 index 0000000000..8fe597983c --- /dev/null +++ b/nmod_sparse_mat/to_dense.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) +{ + if(mat->r == 0 || mat->c == 0) return; + slong i, j, k=0; + memset(mat->entries, 0, mat->r * mat->c * sizeof(*mat->entries)); + for(i=0; ir; ++i) { + for(j=0; jrow_nnz[i]; ++j, ++k) { + mat->rows[i][src->entries[k].col] = src->entries[k].val; + } + } +} diff --git a/nmod_sparse_mat/window_clear.c b/nmod_sparse_mat/window_clear.c new file mode 100644 index 0000000000..476fadfb22 --- /dev/null +++ b/nmod_sparse_mat/window_clear.c @@ -0,0 +1,23 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_window_clear(nmod_sparse_mat_t B) +{ + flint_free(B->row_starts); + flint_free(B->row_nnz); +} diff --git a/nmod_sparse_mat/zero.c b/nmod_sparse_mat/zero.c new file mode 100644 index 0000000000..f543a910da --- /dev/null +++ b/nmod_sparse_mat/zero.c @@ -0,0 +1,26 @@ +/* + Copyright (C) 2011 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" + +void +nmod_sparse_mat_zero(nmod_sparse_mat_t mat) +{ + memset(mat->row_nnz, 0, mat->r*sizeof(*mat->row_nnz)); + memset(mat->row_starts, 0, mat->r*sizeof(*mat->row_starts)); + flint_free(mat->entries); + mat->entries = NULL; + mat->nnz = 0; +} From c4514719eca0163e46b21e503cfad6b9b9f41094 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 21:43:25 -0700 Subject: [PATCH 25/42] Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition --- CMakeLists.txt | 2 +- nmod_sparse_mat.h | 21 +++++- nmod_sparse_mat/add.c | 54 -------------- nmod_sparse_mat/append_row.c | 33 --------- nmod_sparse_mat/clear.c | 31 -------- nmod_sparse_mat/concat_horizontal.c | 48 ------------ nmod_sparse_mat/concat_vertical.c | 32 -------- nmod_sparse_mat/equal.c | 50 ------------- nmod_sparse_mat/from_dense.c | 47 ------------ nmod_sparse_mat/init.c | 31 -------- nmod_sparse_mat/lu.c | 86 ++++++++++++++++++++++ nmod_sparse_mat/mul_mat.c | 34 --------- nmod_sparse_mat/mul_vec.c | 34 --------- nmod_sparse_mat/neg.c | 26 ------- nmod_sparse_mat/one.c | 31 -------- nmod_sparse_mat/scalar_mul.c | 49 ------------ nmod_sparse_mat/set.c | 26 +++---- nmod_sparse_mat/sub.c | 57 -------------- nmod_sparse_mat/swap.c | 24 ------ nmod_sparse_mat/test/t-concat_horizontal.c | 14 ---- nmod_sparse_mat/test/t-concat_vertical.c | 9 --- nmod_sparse_mat/test/t-construct.c | 9 +++ nmod_sparse_mat/to_dense.c | 28 ------- nmod_sparse_mat/window_clear.c | 23 ------ nmod_sparse_mat/zero.c | 26 ------- 25 files changed, 125 insertions(+), 700 deletions(-) delete mode 100644 nmod_sparse_mat/add.c delete mode 100644 nmod_sparse_mat/append_row.c delete mode 100644 nmod_sparse_mat/clear.c delete mode 100644 nmod_sparse_mat/concat_horizontal.c delete mode 100644 nmod_sparse_mat/concat_vertical.c delete mode 100644 nmod_sparse_mat/equal.c delete mode 100644 nmod_sparse_mat/from_dense.c delete mode 100644 nmod_sparse_mat/init.c delete mode 100644 nmod_sparse_mat/mul_mat.c delete mode 100644 nmod_sparse_mat/mul_vec.c delete mode 100644 nmod_sparse_mat/neg.c delete mode 100644 nmod_sparse_mat/one.c delete mode 100644 nmod_sparse_mat/scalar_mul.c delete mode 100644 nmod_sparse_mat/sub.c delete mode 100644 nmod_sparse_mat/swap.c delete mode 100644 nmod_sparse_mat/to_dense.c delete mode 100644 nmod_sparse_mat/window_clear.c delete mode 100644 nmod_sparse_mat/zero.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fcfa4a546..ad560f9320 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_poly + fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index d71cca1b34..cb758c89dc 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -84,7 +84,6 @@ void nmod_sparse_mat_zero(nmod_sparse_mat_t M) slong i; for (i = 0; i < M->r; ++i) nmod_sparse_vec_zero(&M->rows[i]); } - NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_one(nmod_sparse_mat_t M) { @@ -92,6 +91,7 @@ void nmod_sparse_mat_one(nmod_sparse_mat_t M) for (i = 0; i < M->r; ++i) nmod_sparse_vec_one(&M->rows[i], i); } +/* One-time instantiation */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { @@ -307,6 +307,25 @@ void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_m for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + nmod_sparse_mat_addmul(C, A, B, UWORD(1)); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +{ + nmod_sparse_mat_addmul(C, A, B, C->mod.n-UWORD(1)); +} + /* Matrix-vector and matrix-matrix multipliciation */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) diff --git a/nmod_sparse_mat/add.c b/nmod_sparse_mat/add.c deleted file mode 100644 index b92d218d38..0000000000 --- a/nmod_sparse_mat/add.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" - -void -nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) -{ - slong i; - - C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); - memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); - C->nnz = 0; - - for (i = 0; i < C->r; i++) - { - C->row_starts[i] = C->nnz; - nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; - nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; - nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; - slong j = 0; - slong k = 0; - slong nnz = 0; - /* Interleave ith rows until one runs out */ - while(j < A->row_nnz[i] && k < B->row_nnz[i]) { - slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); - if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; - if(Be[k].col == col) Ce[nnz].val = nmod_add(Ce[nnz].val, Be[k++].val, C->mod); - if(Ce[nnz].val != UWORD(0)) ++nnz; - } - /* Add remainder of A row */ - for(; jrow_nnz[i]; ++j, ++nnz) Ce[nnz] = Ae[j]; - /* Add remainder of B row */ - for(; krow_nnz[i]; ++k, ++nnz) Ce[nnz]= Be[k]; - - C->row_nnz[i] = nnz; - C->nnz += nnz; - } - _nmod_sparse_mat_set_c(C); - C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); -} diff --git a/nmod_sparse_mat/append_row.c b/nmod_sparse_mat/append_row.c deleted file mode 100644 index 1d0e4ad872..0000000000 --- a/nmod_sparse_mat/append_row.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* Elements must be ordered by row then col */ -void nmod_sparse_mat_append_row(nmod_sparse_mat_t mat, slong row, slong * cols, mp_limb_t * vals, slong nnz) -{ - slong i; - mat->entries = flint_realloc(mat->entries, (mat->nnz + nnz)* sizeof(*mat->entries)); - mat->row_starts[row] = mat->nnz; - mat->row_nnz[row] = nnz; - - nmod_sparse_mat_entry_struct *e = mat->entries + mat->row_starts[row]; - for(i = 0; i < nnz; i++) { - e[i].col = cols[i]; - e[i].val = vals[i]; - if(e[i].col >= mat->c) mat->c = e->col + 1; - } - mat->nnz += nnz; -} diff --git a/nmod_sparse_mat/clear.c b/nmod_sparse_mat/clear.c deleted file mode 100644 index 9aec210a46..0000000000 --- a/nmod_sparse_mat/clear.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2010 William Hart - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_clear(nmod_sparse_mat_t mat) -{ - if(mat->entries) - { - flint_free(mat->entries); - } - if(mat->row_starts) { - flint_free(mat->row_starts); - } - if(mat->row_nnz) { - flint_free(mat->row_nnz); - } -} diff --git a/nmod_sparse_mat/concat_horizontal.c b/nmod_sparse_mat/concat_horizontal.c deleted file mode 100644 index b41849a0ef..0000000000 --- a/nmod_sparse_mat/concat_horizontal.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2015 Elena Sergeicheva - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - if(res->r == 0) return; - if(mat1->c == 0) { - nmod_sparse_mat_set(res, mat2); - return; - } - if(mat2->c == 0) { - nmod_sparse_mat_set(res, mat1); - return; - } - slong i, j; - res->c = mat1->c + mat2->c; - res->nnz = mat1->nnz + mat2->nnz; - res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); - - for (i = 0; i < res->r; i++) - { - res->row_starts[i] = mat1->row_starts[i] + mat2->row_starts[i]; - nmod_sparse_mat_entry_struct *e = res->entries + res->row_starts[i]; - nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; - nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; - for(j = 0; j < mat1->row_nnz[i]; ++j, ++e, ++e1) { - e->col = e1->col; - e->val = e1->val; - } - for(j = 0; j < mat2->row_nnz[i]; ++j, ++e, ++e2) { - e->col = e2->col + mat1->c; - e->val = e2->val; - } - res->row_nnz[i] = mat1->row_nnz[i] + mat2->row_nnz[i]; - } -} diff --git a/nmod_sparse_mat/concat_vertical.c b/nmod_sparse_mat/concat_vertical.c deleted file mode 100644 index a964bf0f83..0000000000 --- a/nmod_sparse_mat/concat_vertical.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2015 Elena Sergeicheva - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - slong i; - - res->c = (mat1->c > mat2->c)?(mat1->c):(mat2->c); - res->nnz = mat1->nnz + mat2->nnz; - res->entries = flint_realloc(res->entries, res->nnz * sizeof(*res->entries)); - memcpy(res->entries, mat1->entries, mat1->nnz * sizeof(*res->entries)); - memcpy(res->entries + mat1->nnz, mat2->entries, mat2->nnz * sizeof(*res->entries)); - memcpy(res->row_starts, mat1->row_starts, mat1->r * sizeof(*res->row_starts)); - memcpy(res->row_starts+mat1->r, mat2->row_starts, mat2->r * sizeof(*res->row_starts)); - memcpy(res->row_nnz, mat1->row_nnz, mat1->r*sizeof(*res->row_nnz)); - memcpy(res->row_nnz+mat1->r, mat2->row_nnz, mat2->r*sizeof(*res->row_nnz)); - - for (i = 0; i < mat2->r; i++) - res->row_starts[mat1->r + i] += mat1->nnz; -} diff --git a/nmod_sparse_mat/equal.c b/nmod_sparse_mat/equal.c deleted file mode 100644 index 98d0ad1922..0000000000 --- a/nmod_sparse_mat/equal.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -int -nmod_sparse_mat_equal(const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) -{ - if (mat1->r != mat2->r) { - printf("Different number of rows\n"); - return 0; - } - - if (mat1->nnz != mat2->nnz) { - printf("Different number of nonzeroes\n"); - return 0; - } - - if (mat1->nnz == 0) - return 1; - - if(memcmp(mat1->row_nnz, mat2->row_nnz, mat1->r * sizeof(*mat1->row_nnz))) { - printf("Different row_nnz\n"); return 0; - } - - slong i, j; - for(i=0; ir; ++i) { - nmod_sparse_mat_entry_struct *e1 = mat1->entries + mat1->row_starts[i]; - nmod_sparse_mat_entry_struct *e2 = mat2->entries + mat2->row_starts[i]; - for(j=0; jrow_nnz[i]; ++j, ++e1, ++e2) { - if((e1->col - mat1->c_off != e2->col - mat2->c_off) || (e1->val != e2->val)) { - flint_printf("Mismatched row %d, entry %d\n", i, j); - return 0; - } - } - } - return 1; -} diff --git a/nmod_sparse_mat/from_dense.c b/nmod_sparse_mat/from_dense.c deleted file mode 100644 index ef7fdc6dba..0000000000 --- a/nmod_sparse_mat/from_dense.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* Assumes B->c == A->r */ -void -nmod_sparse_mat_from_dense(nmod_sparse_mat_t B, const nmod_mat_t A) -{ - slong i, j; - if(A->r == 0) return; - if(A->c == 0) {nmod_sparse_mat_zero(B); return;} - B->entries = flint_realloc(B->entries, A->r * A->c * sizeof(*B->entries)); - B->nnz = 0; - B->c = 0; - for(i=0; i < A->r; ++i) { - B->row_starts[i] = B->nnz; - B->row_nnz[i] = 0; - for(j=0; j < A->c; ++j) { - if(A->rows[i][j] != UWORD(0)) { - B->entries[B->nnz].col = j; - B->entries[B->nnz].val = A->rows[i][j]; - B->row_nnz[i]++; - B->nnz++; - } - } - } - _nmod_sparse_mat_set_c(B); - if(B->nnz > 0) - B->entries = flint_realloc(B->entries, B->nnz * sizeof(*B->entries)); - else { - flint_free(B->entries); - B->entries = NULL; - } -} diff --git a/nmod_sparse_mat/init.c b/nmod_sparse_mat/init.c deleted file mode 100644 index 4601dcdc25..0000000000 --- a/nmod_sparse_mat/init.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2010 William Hart - Copyright (C) 2010,2011 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - - -void -nmod_sparse_mat_init(nmod_sparse_mat_t mat, slong rows, mp_limb_t n) -{ - memset(mat, 0, sizeof(*mat)); - mat->r = rows; - mat->c = 0; - if(rows > 0) { - mat->row_starts = flint_calloc(rows, rows*sizeof(*mat->row_starts)); - mat->row_nnz = flint_calloc(rows, rows*sizeof(*mat->row_nnz)); - } - _nmod_sparse_mat_set_mod(mat, n); -} diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 0e894fe0c7..58cd0e880d 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -51,6 +51,7 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s heap_idx[c] = pos; } +<<<<<<< HEAD /* static void print_heap(slong *heap, slong *scores, slong size) { slong level, i; @@ -169,4 +170,89 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_permute_cols(U, Q); nmod_sparse_mat_permute_rows(U, P); return rank; +======= +void nmod_sparse_mat_lu(slong *P, slong *Q, + nmod_sparse_mat_t L, nmod_sparse_mat_t U, + const nmod_sparse_mat_t A) { + slong i, j, r, c; + nmod_sparse_mat_t Lt; + nmod_sparse_mat_init(Lt, A->c, A->r, A->mod); + nmod_sparse_mat_set(U, A); + nmod_sparse_mat_transpose(Lt, A); + + // Set up permutations + slong remr = U->r, remc = Lt->r; + for(r=0; rr; ++r) + { + if(!U->rows[r].nnz) P[r] = --remr; + else P[r] = -1; + } + for(c=0; cr; ++c) + { + if(!Lt->rows[c].nnz) Q[c] = --remc; + else Q[c] = -1; + } + + /* Make heap of nonzero columns by size */ + slong *heap, *heap_idx, *scores, heap_size = A->c; + heap = flint_malloc(A->c*sizeof(*heap)); + scores = flint_malloc(A->c*sizeof(*scores)); + heap_idx = flint_malloc(A->c*sizeof(*heap_idx)); + for(i=0; ic; ++i) { + scores[i] = Lt->rows[i].nnz; // TODO: randomized tiebreaker + heap[i] = i; + heap_up(heap, heap_idx, scores, i); + } + + /* Run elimination */ + slong pc, pr; + slong numr = 0, numc = 0; + nmod_sparse_vec_struct *pcol, *prow, *row, *col; + for(heap_size=A->c; heap_size > 0; --heap_size) { + /* Get lowest weight column (top of heap) */ + pc = heap[0]; + pcol = &Lt->rows[pc]; + heap[0] = heap[heap_size-1]; + heap_down(heap, heap_idx, scores, heap_size, 0); + if(pcol->nnz==0) continue; // Empty columns already dealt with + Q[pc] = numc++; // Move pivot column to front + + /* Get lowest weight incident row */ + pr = pcol->entries[0].ind, prow = &U->rows[pr]; + for(j=1; jnnz; ++j) { + r = pcol->entries[j].ind, row = &U->rows[r]; + if(row->nnz < prow->nnz) pr = r, prow = row; + } + P[pr] = numr++; // Move pivot row to front + + /* Invert pivot */ + mp_limb_t cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); + + /* Gaussian eliminate rows */ + mp_limb_t cc; + for(j=0; jnnz; ++j) { + r = pcol->entries[j].ind, row = &U->rows[r]; + if(P[r] >= 0) continue; // Skip previous pivot rows + cc = nmod_mul(cinv, nmod_sparse_vec_at(row, c), A->mod); + nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); + if(row->nnz==0) P[r] = --remr; + } + + /* Gaussian eliminate cols */ + for(j=0; jnnz; ++j) { + c = prow->entries[j].ind, col = &Lt->rows[c]; + if(Q[c] >= 0) continue; // Skip previous pivot columns + cc = nmod_mul(cinv, nmod_sparse_vec_at(col, c), A->mod); + nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); + if(col->nnz==0) Q[c] = --remc; + } + } + /* Reorder cols in U and L^t */ + nmod_sparse_mat_permute_cols(U, Q); + nmod_sparse_mat_permute_cols(Lt, P); + + /* Transpose L^t */ + nmod_sparse_mat_transpose(L, Lt); + nmod_sparse_mat_clear(Lt); +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition } diff --git a/nmod_sparse_mat/mul_mat.c b/nmod_sparse_mat/mul_mat.c deleted file mode 100644 index 28164c782b..0000000000 --- a/nmod_sparse_mat/mul_mat.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* TODO: save reductions to end? */ -void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t A, const nmod_mat_t X) { - slong i,j,k; - if(Y->r == 0 || Y->c == 0) return; - memset(Y->entries, 0, Y->r * Y->c * sizeof(*Y->entries)); - nmod_sparse_mat_entry_struct *e = A->entries; - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++e) { - if(e->val==1) - _nmod_vec_add(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); - else if(e->val==A->mod.n-1) - _nmod_vec_sub(Y->rows[i], Y->rows[i], X->rows[e->col], X->c, A->mod); - else - _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->col], X->c, e->val, A->mod); - } - } -} diff --git a/nmod_sparse_mat/mul_vec.c b/nmod_sparse_mat/mul_vec.c deleted file mode 100644 index 4e47c6f939..0000000000 --- a/nmod_sparse_mat/mul_vec.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/* TODO: save reductions to end? */ -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t A, const mp_ptr x) { - slong i,j; - memset(y, 0, A->r * sizeof(*y)); - nmod_sparse_mat_entry_struct *e = A->entries; - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++e) { - if(e->val==1) - y[i] = nmod_add(y[i], x[e->col], A->mod); - else if(e->val==A->mod.n-1) - y[i] = nmod_sub(y[i], x[e->col], A->mod); - else - y[i] = nmod_add(y[i], nmod_mul(x[e->col], e->val, A->mod), A->mod); - } - } -} - diff --git a/nmod_sparse_mat/neg.c b/nmod_sparse_mat/neg.c deleted file mode 100644 index 970bf71f17..0000000000 --- a/nmod_sparse_mat/neg.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" - -void -nmod_sparse_mat_neg(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) -{ - slong i; - - nmod_sparse_mat_set(B, A); - for (i = 0; i < A->nnz; i++) - B->entries[i].val = nmod_neg(B->entries[i].val, B->mod); -} diff --git a/nmod_sparse_mat/one.c b/nmod_sparse_mat/one.c deleted file mode 100644 index 3257bd97f8..0000000000 --- a/nmod_sparse_mat/one.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2014 Ashish Kedia - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -/*Function to convert a square matrix to an identity matrix - The matrix is assumed to be a square one*/ -void -nmod_sparse_mat_one(nmod_sparse_mat_t mat) -{ - mat->c = mat->nnz = mat->r; - mat->entries = flint_realloc(mat->entries, mat->r*sizeof(*mat->entries)); - slong i; - for(i = 0; i < mat->r; i++) { - mat->entries[i].val = 1; - mat->entries[i].col = i; - mat->row_starts[i] = i; - mat->row_nnz[i] = 1; - } -} diff --git a/nmod_sparse_mat/scalar_mul.c b/nmod_sparse_mat/scalar_mul.c deleted file mode 100644 index ff50dd81b8..0000000000 --- a/nmod_sparse_mat/scalar_mul.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "ulong_extras.h" - -void -nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t B, const nmod_sparse_mat_t A, mp_limb_t c) -{ - if (c == UWORD(0)) - { - nmod_sparse_mat_zero(B); - } - else if(c == UWORD(1)) - { - nmod_sparse_mat_set(B, A); - } - else if(c == B->mod.n - UWORD(1)) - { - nmod_sparse_mat_neg(B, A); - } - else - { - slong i; - nmod_sparse_mat_set(B, A); - if (A->nnz > 10 && A->mod.n < UWORD_HALF) - { - mp_limb_t w_pr = n_mulmod_precomp_shoup(c, A->mod.n); - for (i = 0; innz; i++) - B->entries[i].val = n_mulmod_shoup(c, B->entries[i].val, w_pr, A->mod.n); - } - else - { - for (i = 0; innz; i++) - B->entries[i].val = nmod_mul(c, B->entries[i].val, B->mod); - } - } -} diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c index 76c1315409..084ec19c4d 100644 --- a/nmod_sparse_mat/set.c +++ b/nmod_sparse_mat/set.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson This file is part of FLINT. @@ -15,21 +15,13 @@ #include "flint.h" #include "nmod_sparse_mat.h" -/* Assumes B->r == A->r */ -void -nmod_sparse_mat_set(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) +void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) { - if (B == A) - return; - B->c = A->c; - B->nnz = A->nnz; - if(B->nnz == 0) { - flint_free(B->entries); - B->entries = NULL; - } else { - B->entries = flint_realloc(B->entries, A->nnz * sizeof(*B->entries)); - memcpy(B->entries, A->entries, A->nnz * sizeof(*B->entries)); - } - memcpy(B->row_starts, A->row_starts, A->r * sizeof(*B->row_starts)); - memcpy(B->row_nnz, A->row_nnz, A->r * sizeof(*B->row_nnz)); + slong i; + if(mat==src || mat->r==0) return; + mat->r = src->r; + mat->c = src->c; + mat->c_off = src->c_off; + mat->rows = realloc(mat->rows, mat->r*sizeof(*mat->rows)); + for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); } diff --git a/nmod_sparse_mat/sub.c b/nmod_sparse_mat/sub.c deleted file mode 100644 index 80afd51edd..0000000000 --- a/nmod_sparse_mat/sub.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "nmod_vec.h" - - -void -nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) -{ - slong i; - - C->entries = flint_realloc(C->entries, (A->nnz + B->nnz)*sizeof(*C->entries)); - memset(C->entries, 0, (A->nnz + B->nnz)*sizeof(*C->entries)); - C->nnz = 0; - - for (i = 0; i < C->r; i++) - { - C->row_starts[i] = C->nnz; - nmod_sparse_mat_entry_struct *Ae = A->entries + A->row_starts[i]; - nmod_sparse_mat_entry_struct *Be = B->entries + B->row_starts[i]; - nmod_sparse_mat_entry_struct *Ce = C->entries + C->row_starts[i]; - slong j = 0; - slong k = 0; - slong nnz = 0; - /* Interleave ith rows until one runs out */ - while(j < A->row_nnz[i] && k < B->row_nnz[i]) { - slong col = Ce[nnz].col = FLINT_MIN(Ae[j].col, Be[k].col); - if(Ae[j].col == col) Ce[nnz].val = Ae[j++].val; - if(Be[k].col == col) Ce[nnz].val = nmod_sub(Ce[nnz].val, Be[k++].val, C->mod); - if(Ce[nnz].val != UWORD(0)) ++nnz; - } - /* Add remainder of A row */ - for(; jrow_nnz[i]; ++j, ++nnz) - Ce[nnz] = Ae[j]; - /* Subtract remainder of B row */ - for(; krow_nnz[i]; ++k, ++nnz) - Ce[nnz] = Be[k], Ce[nnz].val = nmod_neg(Ce[nnz].val, C->mod); - - C->row_nnz[i] = nnz; - C->nnz += nnz; - } - _nmod_sparse_mat_set_c(C); - C->entries = realloc(C->entries, C->nnz*sizeof(*C->entries)); -} diff --git a/nmod_sparse_mat/swap.c b/nmod_sparse_mat/swap.c deleted file mode 100644 index 5657b63b05..0000000000 --- a/nmod_sparse_mat/swap.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright (C) 2014 Ashish Kedia - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_swap(nmod_sparse_mat_t mat1, nmod_sparse_mat_t mat2) -{ - nmod_sparse_mat_t temp; - *temp = *mat1; - *mat1 = *mat2; - *mat2 = *temp; -} diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index 1d7429bc7f..a2b26bd4af 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -56,7 +56,6 @@ int main(void) nmod_sparse_mat_print_pretty(A); flint_printf("B = \n"); nmod_sparse_mat_print_pretty(B); -<<<<<<< HEAD flint_printf("A | B = \n"); nmod_sparse_mat_print_pretty(C); flint_printf("window1 = \n"); @@ -81,9 +80,6 @@ int main(void) flint_printf("B = \n"); nmod_sparse_mat_print_pretty(B); flint_printf("A | B = \n"); -======= - flint_printf("A concat_horizontal B = \n"); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_print_pretty(C); flint_printf("window1 = \n"); nmod_sparse_mat_print_pretty(window1); @@ -92,7 +88,6 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } -<<<<<<< HEAD nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); @@ -100,15 +95,6 @@ int main(void) nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_sparse_mat_clear(C); -======= - - nmod_sparse_mat_clear(A); - nmod_sparse_mat_clear(B); - nmod_sparse_mat_clear(C); - - nmod_sparse_mat_window_clear(window1); - nmod_sparse_mat_window_clear(window2); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters } diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index 7c8f8a4d69..5f61d34c6e 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -81,22 +81,13 @@ int main(void) flint_printf("FAIL: results not equal\n"); abort(); } -<<<<<<< HEAD nmod_sparse_mat_window_clear(window1); nmod_sparse_mat_window_clear(window2); -======= ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); nmod_sparse_mat_clear(C); -<<<<<<< HEAD -======= - - nmod_sparse_mat_window_clear(window1); - nmod_sparse_mat_window_clear(window2); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters } diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 1fafcba1f9..4002fa1b60 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -67,10 +67,14 @@ main(void) { flint_printf("FAIL: A != B\n"); <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition flint_printf("A = "); nmod_sparse_mat_print_pretty(A); flint_printf("B = "); nmod_sparse_mat_print_pretty(B); +<<<<<<< HEAD abort(); } @@ -94,6 +98,8 @@ main(void) { flint_printf("FAIL: A != C\n"); >>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters +======= +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition abort(); } flint_free(rows); @@ -102,9 +108,12 @@ main(void) nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); <<<<<<< HEAD +<<<<<<< HEAD ======= nmod_sparse_mat_clear(C); >>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters +======= +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/to_dense.c b/nmod_sparse_mat/to_dense.c deleted file mode 100644 index 8fe597983c..0000000000 --- a/nmod_sparse_mat/to_dense.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void nmod_sparse_mat_to_dense(nmod_mat_t mat, const nmod_sparse_mat_t src) -{ - if(mat->r == 0 || mat->c == 0) return; - slong i, j, k=0; - memset(mat->entries, 0, mat->r * mat->c * sizeof(*mat->entries)); - for(i=0; ir; ++i) { - for(j=0; jrow_nnz[i]; ++j, ++k) { - mat->rows[i][src->entries[k].col] = src->entries[k].val; - } - } -} diff --git a/nmod_sparse_mat/window_clear.c b/nmod_sparse_mat/window_clear.c deleted file mode 100644 index 476fadfb22..0000000000 --- a/nmod_sparse_mat/window_clear.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_window_clear(nmod_sparse_mat_t B) -{ - flint_free(B->row_starts); - flint_free(B->row_nnz); -} diff --git a/nmod_sparse_mat/zero.c b/nmod_sparse_mat/zero.c deleted file mode 100644 index f543a910da..0000000000 --- a/nmod_sparse_mat/zero.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2011 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void -nmod_sparse_mat_zero(nmod_sparse_mat_t mat) -{ - memset(mat->row_nnz, 0, mat->r*sizeof(*mat->row_nnz)); - memset(mat->row_starts, 0, mat->r*sizeof(*mat->row_starts)); - flint_free(mat->entries); - mat->entries = NULL; - mat->nnz = 0; -} From 3907bdc83abf9a52f410c01c1811e0af226ed26e Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 00:00:01 -0700 Subject: [PATCH 26/42] Rebased and merged --- nmod_sparse_mat/set.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c index 084ec19c4d..ad5d7abb3e 100644 --- a/nmod_sparse_mat/set.c +++ b/nmod_sparse_mat/set.c @@ -1,5 +1,9 @@ /* +<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson +======= + Copyright (C) 2010 Fredrik Johansson +>>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters This file is part of FLINT. From d618a8948f8e9be898269ba490d13fe9548fd4ca Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 21:43:25 -0700 Subject: [PATCH 27/42] Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition --- nmod_sparse_mat.h | 39 ++++++++++++++++++++++++++++-- nmod_sparse_mat/set.c | 31 ------------------------ nmod_sparse_mat/test/t-transpose.c | 5 ++++ 3 files changed, 42 insertions(+), 33 deletions(-) delete mode 100644 nmod_sparse_mat/set.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index cb758c89dc..c5b90ce76d 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -168,6 +168,7 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_ for (i = M1->r; i < B->r; ++i) nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); } +<<<<<<< HEAD /* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ /* M1->r and M2->r must equal B->r */ @@ -188,7 +189,35 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } +<<<<<<< HEAD +======= +======= + +/* res->r must equal mat1->r and mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, + const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = mat1->c + mat2->c; + for(i=0; ir; ++i) + nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); +} +/* res->r must equal mat1->r + mat2->r */ +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +{ + slong i; + res->c = FLINT_MAX(mat1->c, mat2->c); + for(i=0; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); + for(i=mat1->r; ir; ++i) + nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); +} + +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) @@ -339,9 +368,9 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod slong i, j; nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) -{ + { for (j = 0; j < M->rows[i].nnz; ++j) -{ + { nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } @@ -421,9 +450,15 @@ FLINT_DLL mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); /* Nullspace */ +<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); */ +======= +NMOD_SPARSE_MAT_INLINE +slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); + +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus } #endif diff --git a/nmod_sparse_mat/set.c b/nmod_sparse_mat/set.c deleted file mode 100644 index ad5d7abb3e..0000000000 --- a/nmod_sparse_mat/set.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -<<<<<<< HEAD - Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "nmod_sparse_mat.h" - -void nmod_sparse_mat_set(nmod_sparse_mat_t mat, const nmod_sparse_mat_t src) -{ - slong i; - if(mat==src || mat->r==0) return; - mat->r = src->r; - mat->c = src->c; - mat->c_off = src->c_off; - mat->rows = realloc(mat->rows, mat->r*sizeof(*mat->rows)); - for(i=0; ir; ++i) nmod_sparse_vec_set(&mat->rows[i], &src->rows[i]); -} diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index f87c3fb53b..c7832e634b 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,8 +20,13 @@ int main(void) { +<<<<<<< HEAD slong rep, r, c; mp_limb_t n; +======= + slong rep, r, c, i; + mp_limb_t n, a; +>>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition nmod_t mod; nmod_sparse_mat_t A, B, C; FLINT_TEST_INIT(state); From 57804241723555a6f8385deb095baa34d98b24be Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sat, 28 Mar 2020 23:17:40 -0700 Subject: [PATCH 28/42] Spacing and cuddling fixed --- nmod_sparse_mat.h | 58 +++++++++++++++++++++++++++--- nmod_sparse_mat/lu.c | 86 -------------------------------------------- 2 files changed, 54 insertions(+), 90 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index c5b90ce76d..b79a77fe5b 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -169,6 +169,7 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_ nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); } <<<<<<< HEAD +<<<<<<< HEAD /* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ /* M1->r and M2->r must equal B->r */ @@ -193,6 +194,8 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, ======= ======= +======= +>>>>>>> Spacing and cuddling fixed /* res->r must equal mat1->r and mat2->r */ NMOD_SPARSE_MAT_INLINE @@ -201,7 +204,7 @@ void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, { slong i; res->c = mat1->c + mat2->c; - for(i=0; ir; ++i) + for (i = 0; i < res->r; ++i) nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); } /* res->r must equal mat1->r + mat2->r */ @@ -210,19 +213,23 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_ma { slong i; res->c = FLINT_MAX(mat1->c, mat2->c); - for(i=0; ir; ++i) + for (i = 0; i < mat1->r; ++i) nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); - for(i=mat1->r; ir; ++i) + for (i = mat1->r; i < res->r; ++i) nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); } +<<<<<<< HEAD >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition +======= +>>>>>>> Spacing and cuddling fixed /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; +<<<<<<< HEAD for (i = 0; i < M->r; ++i) { if (!M->rows[i].nnz) continue; @@ -240,6 +247,9 @@ void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t M, slong *P) for (i = 0; i < M->r; ++i) prows[P[i]] = M->rows[i]; memcpy(M->rows, prows, M->r*sizeof(*M->rows)); flint_free(prows); +======= + for (i = 0; i < mat->r; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); +>>>>>>> Spacing and cuddling fixed } /* Random matrix generation */ @@ -260,9 +270,15 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_equal(const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; +<<<<<<< HEAD if (M1->r != M2->r) return 0; for (i = 0; i < M1->r; ++i) if (nmod_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off) == 0) return 0; +======= + if (mat1->r != mat2->r) return 0; + for (i = 0; i < mat1->r; ++i) + if (nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off) == 0) return 0; +>>>>>>> Spacing and cuddling fixed return 1; } @@ -270,8 +286,13 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) { slong i; +<<<<<<< HEAD for (i = 0; i < M->r; ++i) if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; +======= + for (i = 0; i < mat->r; ++i) + if (!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; +>>>>>>> Spacing and cuddling fixed return 1; } @@ -283,18 +304,31 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) { slong i; +<<<<<<< HEAD nmod_sparse_mat_set(N, M); for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); +======= + nmod_sparse_mat_set(B, A); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); +>>>>>>> Spacing and cuddling fixed } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { +<<<<<<< HEAD if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; nmod_sparse_mat_set(N, M); for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); +======= + if (c == UWORD(0)) nmod_sparse_mat_zero(B); + else { + slong i; + nmod_sparse_mat_set(B, A); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); +>>>>>>> Spacing and cuddling fixed } } @@ -340,7 +374,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); + for (i = 0; i < C->r; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); } NMOD_SPARSE_MAT_INLINE @@ -360,18 +394,30 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; +<<<<<<< HEAD for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); +======= + for (i = 0; i < A->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); +>>>>>>> Spacing and cuddling fixed } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; +<<<<<<< HEAD nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) { for (j = 0; j < M->rows[i].nnz; ++j) { nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; +======= + for (i = 0; i < A->r; ++i) +{ + for (j = 0; j < A->rows[i].nnz; ++j) +{ + nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; +>>>>>>> Spacing and cuddling fixed _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } } @@ -451,12 +497,16 @@ mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); /* Nullspace */ <<<<<<< HEAD +<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); */ ======= NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); +======= +// slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); +>>>>>>> Spacing and cuddling fixed >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 58cd0e880d..0e894fe0c7 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -51,7 +51,6 @@ static void heap_down(slong *heap, slong *heap_idx, slong *scores, slong size, s heap_idx[c] = pos; } -<<<<<<< HEAD /* static void print_heap(slong *heap, slong *scores, slong size) { slong level, i; @@ -170,89 +169,4 @@ slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_permute_cols(U, Q); nmod_sparse_mat_permute_rows(U, P); return rank; -======= -void nmod_sparse_mat_lu(slong *P, slong *Q, - nmod_sparse_mat_t L, nmod_sparse_mat_t U, - const nmod_sparse_mat_t A) { - slong i, j, r, c; - nmod_sparse_mat_t Lt; - nmod_sparse_mat_init(Lt, A->c, A->r, A->mod); - nmod_sparse_mat_set(U, A); - nmod_sparse_mat_transpose(Lt, A); - - // Set up permutations - slong remr = U->r, remc = Lt->r; - for(r=0; rr; ++r) - { - if(!U->rows[r].nnz) P[r] = --remr; - else P[r] = -1; - } - for(c=0; cr; ++c) - { - if(!Lt->rows[c].nnz) Q[c] = --remc; - else Q[c] = -1; - } - - /* Make heap of nonzero columns by size */ - slong *heap, *heap_idx, *scores, heap_size = A->c; - heap = flint_malloc(A->c*sizeof(*heap)); - scores = flint_malloc(A->c*sizeof(*scores)); - heap_idx = flint_malloc(A->c*sizeof(*heap_idx)); - for(i=0; ic; ++i) { - scores[i] = Lt->rows[i].nnz; // TODO: randomized tiebreaker - heap[i] = i; - heap_up(heap, heap_idx, scores, i); - } - - /* Run elimination */ - slong pc, pr; - slong numr = 0, numc = 0; - nmod_sparse_vec_struct *pcol, *prow, *row, *col; - for(heap_size=A->c; heap_size > 0; --heap_size) { - /* Get lowest weight column (top of heap) */ - pc = heap[0]; - pcol = &Lt->rows[pc]; - heap[0] = heap[heap_size-1]; - heap_down(heap, heap_idx, scores, heap_size, 0); - if(pcol->nnz==0) continue; // Empty columns already dealt with - Q[pc] = numc++; // Move pivot column to front - - /* Get lowest weight incident row */ - pr = pcol->entries[0].ind, prow = &U->rows[pr]; - for(j=1; jnnz; ++j) { - r = pcol->entries[j].ind, row = &U->rows[r]; - if(row->nnz < prow->nnz) pr = r, prow = row; - } - P[pr] = numr++; // Move pivot row to front - - /* Invert pivot */ - mp_limb_t cinv = nmod_inv(nmod_sparse_vec_at(prow, c), A->mod); - - /* Gaussian eliminate rows */ - mp_limb_t cc; - for(j=0; jnnz; ++j) { - r = pcol->entries[j].ind, row = &U->rows[r]; - if(P[r] >= 0) continue; // Skip previous pivot rows - cc = nmod_mul(cinv, nmod_sparse_vec_at(row, c), A->mod); - nmod_sparse_vec_scalar_addmul(row, row, prow, cc, A->mod); - if(row->nnz==0) P[r] = --remr; - } - - /* Gaussian eliminate cols */ - for(j=0; jnnz; ++j) { - c = prow->entries[j].ind, col = &Lt->rows[c]; - if(Q[c] >= 0) continue; // Skip previous pivot columns - cc = nmod_mul(cinv, nmod_sparse_vec_at(col, c), A->mod); - nmod_sparse_vec_scalar_addmul(col, col, pcol, cc, A->mod); - if(col->nnz==0) Q[c] = --remc; - } - } - /* Reorder cols in U and L^t */ - nmod_sparse_mat_permute_cols(U, Q); - nmod_sparse_mat_permute_cols(Lt, P); - - /* Transpose L^t */ - nmod_sparse_mat_transpose(L, Lt); - nmod_sparse_mat_clear(Lt); ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition } From 70ae8c1916d9b848246a1978244620133b88f7d8 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Sun, 29 Mar 2020 00:41:31 -0700 Subject: [PATCH 29/42] Lost a function in the last commit, fixed --- nmod_sparse_mat.h | 10 ---------- nmod_sparse_mat/test/t-transpose.c | 5 ----- 2 files changed, 15 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index b79a77fe5b..c51608458a 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -496,19 +496,9 @@ FLINT_DLL mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); /* Nullspace */ -<<<<<<< HEAD -<<<<<<< HEAD /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); */ -======= -NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); -======= -// slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t A); ->>>>>>> Spacing and cuddling fixed - ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition #ifdef __cplusplus } #endif diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index c7832e634b..f87c3fb53b 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -20,13 +20,8 @@ int main(void) { -<<<<<<< HEAD slong rep, r, c; mp_limb_t n; -======= - slong rep, r, c, i; - mp_limb_t n, a; ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition nmod_t mod; nmod_sparse_mat_t A, B, C; FLINT_TEST_INIT(state); From 83d12cf3bd7438557ac649dfabaa01e2f6a10e7f Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 31 Mar 2020 23:31:23 -0700 Subject: [PATCH 30/42] Added code to construct reduced row echelon form and associated solver, another construction option, and (untested) inversion code --- nmod_sparse_mat/test/t-solve.c | 141 --------------------------------- nmod_sparse_vec.h | 10 +++ 2 files changed, 10 insertions(+), 141 deletions(-) delete mode 100644 nmod_sparse_mat/test/t-solve.c diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c deleted file mode 100644 index 9c87f2b960..0000000000 --- a/nmod_sparse_mat/test/t-solve.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include -/*#include */ -#include "flint.h" -#include "nmod_sparse_mat.h" -#include "ulong_extras.h" - -int -main(void) -{ - int iter, ret; - slong rep, nreps = 100, r, c, i; - mp_limb_t n; - nmod_t mod; - nmod_mat_t dA; - nmod_sparse_mat_t A, At; - mp_ptr x, x2, b, Atb, Ax, AtAx; - slong niters[6] = {0, 0, 0, 0, 0, 0}; - slong psol[6] = {0, 0, 0, 0, 0, 0}; - slong nosol[6] = {0, 0, 0, 0, 0, 0}; - /*double elapsed[6] = {0, 0, 0, 0, 0};*/ - char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - /*struct timeval start, end;*/ - FLINT_TEST_INIT(state); - - flint_printf("solving Ax = b...."); - fflush(stdout); - - for (rep = 0; rep < nreps; rep++) - { - if (rep % 5==0) {flint_printf("."); fflush(stdout);} - - c = r = 100 + n_randint(state, 50); - do n = n_randtest_not_zero(state); - while (n <= 32 || !n_is_prime(n)); - nmod_init(&mod, n); - nmod_sparse_mat_init(A, r, c, mod); - nmod_mat_init(dA, r, c, n); - x = _nmod_vec_init(c); - x2 = _nmod_vec_init(c); - b = _nmod_vec_init(r); - Ax = _nmod_vec_init(r); - - nmod_sparse_mat_randtest(A, state, c/20, c/10); - nmod_sparse_mat_to_dense(dA, A); - _nmod_vec_randtest(x, state, c, mod); - nmod_sparse_mat_mul_vec(b, A, x); - - for (i = 0; i < 6; ++i) - { - iter = 0; - /*gettimeofday(&start, NULL);*/ - switch (i) - { - case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; - case 1: ret = nmod_sparse_mat_solve_lu(x2, A, b); break; - case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while (ret == 0 && ++iter < 30); break; - case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while (ret == 0 && ++iter < 30); break; - case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; - case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while (ret == 0 && ++iter < 3); break; - } - /*gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec);*/ - if (ret == 0) nosol[i] += 1; - else - { - niters[i] += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - if (!_nmod_vec_equal(b, Ax, A->r)) - { - if (i == 2 || i == 3) - { - nmod_sparse_mat_init(At, c, r, mod); - AtAx = _nmod_vec_init(c); - Atb = _nmod_vec_init(c); - nmod_sparse_mat_transpose(At, A); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) - { - flint_printf("FAIL on %s: AtAx != Atb\n", names[i]); - abort(); - } - else psol[i] += 1; - flint_free(AtAx); - flint_free(Atb); - nmod_sparse_mat_clear(At); - } - else - { - flint_printf("FAIL on %s: Ax != b\n", names[i]); - flint_printf("A = "); - nmod_sparse_mat_print_pretty(A); - flint_printf("x = "); - _nmod_vec_print_pretty(x, c, mod); - flint_printf("x2 = "); - _nmod_vec_print_pretty(x2, c, mod); - flint_printf("Ax2 = "); - _nmod_vec_print_pretty(Ax, r, mod); - flint_printf("b = "); - _nmod_vec_print_pretty(b, r, mod); - abort(); - } - } - } - } - flint_free(x); - flint_free(x2); - flint_free(b); - flint_free(Ax); - nmod_sparse_mat_clear(A); - } - FLINT_TEST_CLEANUP(state); - - flint_printf("PASS\n"); - for (i = 0; i < 6; ++i) - { - flint_printf("Solved with %s\n", names[i]); - /*flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps);*/ - if (nosol[i]) - flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); - if (psol[i]) - flint_printf("\tFound pseudo-solution for %wd/%wd examples\n", psol[i], nreps); - if (niters[i]) - flint_printf("\tRequired %f extra iters per solution (on average).\n", (double)niters[i]/nreps); - } - return 0; -} diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 6357bd92d0..db2e8d6cce 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -122,6 +122,16 @@ void nmod_sparse_vec_set_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) else *oval = val; } +NMOD_SPARSE_VEC_INLINE +void _nmod_sparse_vec_append_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) +{ + if (val == UWORD(0)) return; + v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); + v->entries[v->nnz].ind = ind; + v->entries[v->nnz].val = val; + v->nnz += 1; +} + FLINT_DLL void nmod_sparse_vec_from_entries(nmod_sparse_vec_t vec, slong * inds, mp_limb_t * vals, slong nnz); From f7e15196510c687200d85203eb8b875362ea76e3 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 1 Apr 2020 17:32:26 -0700 Subject: [PATCH 31/42] Now with additional utilities, more correct basic functions, and nullspace and inversion functions --- nmod_sparse_mat.h | 48 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index c51608458a..e026305811 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -197,6 +197,7 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, ======= >>>>>>> Spacing and cuddling fixed + /* res->r must equal mat1->r and mat2->r */ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, @@ -214,16 +215,36 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_ma slong i; res->c = FLINT_MAX(mat1->c, mat2->c); for (i = 0; i < mat1->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i]); + nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i], mat1->c_off); for (i = mat1->r; i < res->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r]); + nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r], mat2->c_off); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong c) +{ + slong i; + for(i=0; ir; ++i) nmod_sparse_vec_split(&res1->rows[i], &res2->rows[i], &mat->rows[i], c); } +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong r) +{ + slong i; + r = FLINT_MIN(r, mat->r); + for(i=0; irows[i], &mat->rows[i], mat->c_off); + for(i=r; ir; ++i) nmod_sparse_vec_set(&res2->rows[i-r], &mat->rows[i], mat->c_off); +} + +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition >>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition ======= >>>>>>> Spacing and cuddling fixed +======= + +>>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) @@ -476,12 +497,20 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M FLINT_DLL slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +<<<<<<< HEAD +======= +/* Decomposition/reduction */ +>>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions FLINT_DLL slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +<<<<<<< HEAD +======= +/* Solving */ +>>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions FLINT_DLL slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); @@ -491,9 +520,24 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); +<<<<<<< HEAD /* Determinant */ FLINT_DLL mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); +======= +/* Note: this should take in uninitialized matrix X */ +FLINT_DLL +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); + +FLINT_DLL +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); +>>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE From 36cef5f9e1f2cc7916c469413b351560ffe6cf02 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 2 Apr 2020 14:16:09 -0700 Subject: [PATCH 32/42] Added nullvector functions for Lanzcos, everything for basic Wiedemann --- nmod_sparse_mat.h | 28 +++++- nmod_sparse_mat/solve_lanczos.c | 20 +++++ nmod_sparse_mat/test/t-solve.c | 153 ++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 nmod_sparse_mat/test/t-solve.c diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index e026305811..ccec795e91 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -507,33 +507,55 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +<<<<<<< HEAD <<<<<<< HEAD ======= /* Solving */ >>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions +======= +/* Solve Ax=b */ +>>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann FLINT_DLL slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); FLINT_DLL +<<<<<<< HEAD slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); +======= +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); + +FLINT_DLL +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); +>>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); +<<<<<<< HEAD <<<<<<< HEAD /* Determinant */ FLINT_DLL mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); ======= +======= +/* Find single nullvector */ +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); + +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); + +>>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann /* Note: this should take in uninitialized matrix X */ FLINT_DLL -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); + +FLINT_DLL +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); FLINT_DLL slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 0b08e35543..97244208d1 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -102,3 +102,23 @@ int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flin _nmod_vec_clear(b); return ret; } + +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) { + int ret = 1; + mp_ptr x2, b; + x2 = _nmod_vec_init(A->c); + b = _nmod_vec_init(A->r); + + _nmod_vec_randtest(x, state, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) ret = 0; /* Lanczos failed */ + if (ret) + { + _nmod_vec_sub(x, x, x2, A->c, A->mod); + nmod_sparse_mat_mul_vec(b, A, x); + ret = _nmod_vec_is_zero(x, A->c) || !_nmod_vec_is_zero(b, A->r); + } + _nmod_vec_clear(x2); + _nmod_vec_clear(b); + return ret; +} \ No newline at end of file diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c new file mode 100644 index 0000000000..3315828a40 --- /dev/null +++ b/nmod_sparse_mat/test/t-solve.c @@ -0,0 +1,153 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include +#include +#include "flint.h" +#include "nmod_sparse_mat.h" +#include "ulong_extras.h" + +int +main(void) +{ + int iter, ret; + int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + slong rep, r, c, i, nrep = 100; + mp_limb_t n, a; + nmod_t mod; + nmod_sparse_mat_t A, At; + mp_ptr x, x2, b, Atb, Ax, AtAx; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + struct timeval start, end; + FLINT_TEST_INIT(state); + + flint_printf("solving Ax=b...."); + fflush(stdout); + + for (rep = 0; rep < nrep; rep++) + { + if(rep % 5==0) {flint_printf("."); fflush(stdout);} + + do c = r = n_randint(state, 200); + while(c == 0 || r == 0); + + do n = n_randtest_not_zero(state); + while (n <= 32 || !n_is_prime(n)); + nmod_init(&mod, n); + nmod_sparse_mat_init(A, r, c, mod); + nmod_sparse_mat_init(At, c, r, mod); + + nmod_sparse_mat_randtest(A, state, 30, 30); + nmod_sparse_mat_transpose(At, A); + x = _nmod_vec_init(c); + x2 = _nmod_vec_init(c); + b = _nmod_vec_init(r); + Ax = _nmod_vec_init(r); + AtAx = _nmod_vec_init(c); + Atb = _nmod_vec_init(c); + + _nmod_vec_randtest(x, state, c, mod); + nmod_sparse_mat_mul_vec(b, A, x); + + /* Solve via reduced row echelon form */ + gettimeofday(&start, NULL); + ret = nmod_sparse_mat_solve_rref(x2, A, b); + gettimeofday(&end, NULL); + rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + nmod_sparse_mat_mul_vec(Ax, A, x2); + if(!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve via lu decomposition */ + gettimeofday(&start, NULL); + ret = nmod_sparse_mat_solve_lu(x2, A, b); + gettimeofday(&end, NULL); + lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + nmod_sparse_mat_mul_vec(Ax, A, x2); + if(!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b, got ret %d\n", ret); + abort(); + } + + /* Solve iteratively */ + gettimeofday(&start, NULL); + ret=nmod_sparse_mat_solve_wiedemann(x2, A, b); + gettimeofday(&end, NULL); + wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) + { + wied_nosol += 1; + } + else + { + nmod_sparse_mat_mul_vec(Ax, A, x2); + if (!_nmod_vec_equal(b, Ax, A->r)) + { + flint_printf("FAIL: Ax != b\n"); + abort(); + } + } + + gettimeofday(&start, NULL); + iter = 0; + do ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state); + while(ret==0 && ++iter < 30); + gettimeofday(&end, NULL); + lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) + { + nosol += 1; + continue; + } + else + { + niters += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_nmod_vec_equal(b, Ax, A->r)) + { + psolved += 1; + } + } + + flint_free(x); + flint_free(x2); + flint_free(b); + flint_free(Ax); + flint_free(AtAx); + flint_free(Atb); + nmod_sparse_mat_clear(A); + nmod_sparse_mat_clear(At); + } + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); + flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); + flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); + flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); + flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); + return 0; +} From e2bc1145cda5d0523a176e517559961b784fb618 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 7 Apr 2020 21:46:34 -0700 Subject: [PATCH 33/42] Created sparse vector and matrix utilities for all the fq variants --- CMakeLists.txt | 7 +- Makefile.in | 6 +- fq_sparse_mat_templates/test/t-scalar_mul.c | 16 ++ fq_sparse_mat_templates/tmp | 31 ++++ nmod_sparse_mat.h | 176 ++++++++++++++++---- nmod_sparse_mat/solve_block_lanczos.c | 1 - nmod_sparse_mat/solve_lanczos.c | 20 +-- 7 files changed, 209 insertions(+), 48 deletions(-) create mode 100644 fq_sparse_mat_templates/tmp diff --git a/CMakeLists.txt b/CMakeLists.txt index ad560f9320..85a6576337 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,10 +65,9 @@ set(BUILD_DIRS fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve double_extras d_vec d_mat padic_poly padic_mat qadic - fq fq_vec fq_mat fq_poly fq_poly_factor - fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly fq_nmod_poly_factor - fq_zech fq_zech_vec fq_zech_mat fq_zech_poly fq_zech_poly_factor - fq_default fq_default_mat fq_default_poly fq_default_poly_factor + fq fq_vec fq_sparse_vec fq_mat fq_sparse_mat fq_poly fq_poly_factor + fq_nmod fq_nmod_vec fq_nmod_sparse_vec fq_nmod_mat fq_nmod_sparse_mat fq_nmod_poly fq_nmod_poly_factor + fq_zech fq_zech_vec fq_zech_sparse_vec fq_zech_mat fq_zech_sparse_mat fq_zech_poly fq_zech_poly_factor thread_pool fmpz_mod fmpz_mod_vec n_poly mpoly fmpz_mpoly fmpq_mpoly nmod_mpoly fq_nmod_mpoly fmpz_mod_mpoly fmpz_mpoly_factor fmpq_mpoly_factor nmod_mpoly_factor fmpz_mod_mpoly_factor diff --git a/Makefile.in b/Makefile.in index 630ca529dc..16a539c330 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,9 +12,9 @@ BUILD_DIRS = aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_sparse_vec f fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly \ fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve \ double_extras d_vec d_mat padic_poly padic_mat qadic \ - fq fq_vec fq_mat fq_poly fq_poly_factor fq_embed \ - fq_nmod fq_nmod_vec fq_nmod_mat fq_nmod_poly fq_nmod_poly_factor fq_nmod_embed \ - fq_zech fq_zech_vec fq_zech_mat fq_zech_poly fq_zech_poly_factor fq_zech_embed \ + fq fq_vec fq_sparse_vec fq_mat fq_sparse_mat fq_poly fq_poly_factor fq_embed \ + fq_nmod fq_nmod_vec fq_nmod_sparse_vec fq_nmod_mat fq_nmod_sparse_mat fq_nmod_poly fq_nmod_poly_factor fq_nmod_embed \ + fq_zech fq_zech_vec fq_zech_sparse_vec fq_zech_mat fq_zech_sparse_mat fq_zech_poly fq_zech_poly_factor fq_zech_embed \ fmpz_mod_mat mpoly fmpz_mpoly fmpq_mpoly nmod_mpoly fq_nmod_mpoly \ thread_pool fmpz_mod fmpz_mod_vec fmpz_mod_mpoly fmpz_mod_mpoly_factor \ n_poly fmpz_mpoly_factor fmpq_mpoly_factor nmod_mpoly_factor \ diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c index 0c1b8a5513..db595a22b0 100644 --- a/fq_sparse_mat_templates/test/t-scalar_mul.c +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -20,7 +20,11 @@ int main(void) { +<<<<<<< HEAD slong rep, r, c; +======= + slong rep, r, c, i; +>>>>>>> Created sparse vector and matrix utilities for all the fq variants TEMPLATE(T, t) a, cc; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C, D; @@ -44,10 +48,17 @@ main(void) TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); +<<<<<<< HEAD TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (B, A, a, ctx); TEMPLATE(T, one) (cc, ctx); TEMPLATE(T, sub) (cc, a, cc, ctx); TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, cc, ctx); +======= + TEMPLATE(T, sparse_mat_scalar_mul) (B, A, a, ctx); + TEMPLATE(T, one) (cc, ctx); + TEMPLATE(T, sub) (cc, a, cc, ctx); + TEMPLATE(T, sparse_mat_scalar_mul) (C, A, cc, ctx); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants /* c*A - (c-1)*A == A */ TEMPLATE(T, sparse_mat_sub) (D, B, C, ctx); @@ -59,8 +70,13 @@ main(void) } /* Aliasing */ +<<<<<<< HEAD TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, a, ctx); TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (A, A, a, ctx); +======= + TEMPLATE(T, sparse_mat_scalar_mul) (C, A, a, ctx); + TEMPLATE(T, sparse_mat_scalar_mul) (A, A, a, ctx); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants if (!TEMPLATE(T, sparse_mat_equal) (A, C, ctx)) { diff --git a/fq_sparse_mat_templates/tmp b/fq_sparse_mat_templates/tmp new file mode 100644 index 0000000000..f16d89d6ca --- /dev/null +++ b/fq_sparse_mat_templates/tmp @@ -0,0 +1,31 @@ + int ret = 0; + slong l; + + std::vector combi(block_size,Vector(F,d[l]+1)); + for (size_t i=0;i 0;--i) { + lhs = lhs2 + combi[0][i]*y; + lhs2 = A^t*lhs; + } + Vector accu (lhs); + _TEMPLATE(T, vec_zero) (x, A->r, ctx); + for (size_t k=1;k= 0;--i) { + lhs = lhs2 + combi[k][i]*row; + lhs2 = A^t * lhs + } + _TEMPLATE(T, vec_add) (x, x, lhs, A->r, ctx); + } + TEMPLATE(T, neg) (cc, nmod_inv(S[0].rows[l][0], ctx), ctx); + _TEMPLATE(T, vec_scalar_mul) (x, x, A->r, cc, ctx); + return ret; diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index ccec795e91..07ee6bf8fb 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -148,6 +148,7 @@ void nmod_sparse_mat_window_clear(nmod_sparse_mat_t W) /* Combine M1 and M2 into block matrix B = [M1 M2] */ /* B->r must equal M1->r and M2->r */ +<<<<<<< HEAD NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) @@ -199,41 +200,46 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, /* res->r must equal mat1->r and mat2->r */ +======= +>>>>>>> Created sparse vector and matrix utilities for all the fq variants NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t res, - const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, + const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; - res->c = mat1->c + mat2->c; - for (i = 0; i < res->r; ++i) - nmod_sparse_vec_concat(&res->rows[i], &mat1->rows[i], &mat2->rows[i], mat1->c); + B->c = M1->c + M2->c; + for (i = 0; i < B->r; ++i) + nmod_sparse_vec_concat(&B->rows[i], &M1->rows[i], &M2->rows[i], M1->c); } -/* res->r must equal mat1->r + mat2->r */ +/* Combine M1 and M2 into block matrix B = [M1^t M1^t]^t */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t res, const nmod_sparse_mat_t mat1, const nmod_sparse_mat_t mat2) +void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; - res->c = FLINT_MAX(mat1->c, mat2->c); - for (i = 0; i < mat1->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat1->rows[i], mat1->c_off); - for (i = mat1->r; i < res->r; ++i) - nmod_sparse_vec_set(&res->rows[i], &mat2->rows[i-mat1->r], mat2->c_off); + B->c = FLINT_MAX(M1->c, M2->c); + for (i = 0; i < M1->r; ++i) + nmod_sparse_vec_set(&B->rows[i], &M1->rows[i], M1->c_off); + for (i = M1->r; i < B->r; ++i) + nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); } +/* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ +/* M1->r and M2->r must equal B->r */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong c) +void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_split(&res1->rows[i], &res2->rows[i], &mat->rows[i], c); + for(i=0; ir; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); } +/* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t res1, nmod_sparse_mat_t res2, const nmod_sparse_mat_t mat, slong r) +void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong r) { slong i; - r = FLINT_MIN(r, mat->r); - for(i=0; irows[i], &mat->rows[i], mat->c_off); - for(i=r; ir; ++i) nmod_sparse_vec_set(&res2->rows[i-r], &mat->rows[i], mat->c_off); + r = FLINT_MIN(r, B->r); + for(i=0; irows[i], &B->rows[i], B->c_off); + for(i=r; ir; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } <<<<<<< HEAD @@ -250,10 +256,15 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; +<<<<<<< HEAD <<<<<<< HEAD for (i = 0; i < M->r; ++i) { if (!M->rows[i].nnz) continue; +======= + for (i = 0; i < M->r; ++i) { + if(!M->rows[i].nnz) continue; +>>>>>>> Created sparse vector and matrix utilities for all the fq variants nmod_sparse_vec_permute_inds(&M->rows[i], Q); qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), nmod_sparse_entry_cmp); } @@ -291,6 +302,7 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_equal(const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; +<<<<<<< HEAD <<<<<<< HEAD if (M1->r != M2->r) return 0; for (i = 0; i < M1->r; ++i) @@ -300,6 +312,11 @@ int nmod_sparse_mat_equal(const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2 for (i = 0; i < mat1->r; ++i) if (nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off) == 0) return 0; >>>>>>> Spacing and cuddling fixed +======= + if (M1->r != M2->r) return 0; + for (i = 0; i < M1->r; ++i) + if (nmod_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off) == 0) return 0; +>>>>>>> Created sparse vector and matrix utilities for all the fq variants return 1; } @@ -307,6 +324,7 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) { slong i; +<<<<<<< HEAD <<<<<<< HEAD for (i = 0; i < M->r; ++i) if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; @@ -317,6 +335,19 @@ int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) return 1; } +======= + for (i = 0; i < M->r; ++i) + if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; + return 1; +} + +NMOD_SPARSE_MAT_INLINE +int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) +{ + return (M->r == M->c); +} + +>>>>>>> Created sparse vector and matrix utilities for all the fq variants /* Must have M->r == N->c and M->c == N->r */ FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, const nmod_sparse_mat_t M); @@ -325,6 +356,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) { slong i; +<<<<<<< HEAD <<<<<<< HEAD nmod_sparse_mat_set(N, M); for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); @@ -350,6 +382,20 @@ void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_ nmod_sparse_mat_set(B, A); for (i = 0; i < B->r; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); >>>>>>> Spacing and cuddling fixed +======= + nmod_sparse_mat_set(N, M); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) +{ + if (c == UWORD(0)) nmod_sparse_mat_zero(N); + else { + slong i; + nmod_sparse_mat_set(N, M); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul(&N->rows[i], &N->rows[i], c, N->mod); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants } } @@ -359,11 +405,16 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, N->mod.n); +<<<<<<< HEAD nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); +======= + nmod_sparse_mat_scalar_mul(N, M, fmpz_get_ui(d)); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants fmpz_clear(d); } NMOD_SPARSE_MAT_INLINE +<<<<<<< HEAD void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; @@ -393,25 +444,29 @@ void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_m NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) +======= +void nmod_sparse_mat_addmul(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +>>>>>>> Created sparse vector and matrix utilities for all the fq variants { slong i; - for (i = 0; i < C->r; ++i) nmod_sparse_vec_scalar_addmul(&C->rows[i], &A->rows[i], &B->rows[i], c, C->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_add(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(C, A, B, UWORD(1)); + nmod_sparse_mat_addmul(O, M, N, UWORD(1)); } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_sub(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B) +void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(C, A, B, C->mod.n-UWORD(1)); + nmod_sparse_mat_addmul(O, M, N, O->mod.n-UWORD(1)); } /* Matrix-vector and matrix-matrix multipliciation */ NMOD_SPARSE_MAT_INLINE +<<<<<<< HEAD void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; @@ -420,11 +475,18 @@ void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) ======= for (i = 0; i < A->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); >>>>>>> Spacing and cuddling fixed +======= +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, const mp_ptr x) +{ + slong i; + for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; +<<<<<<< HEAD <<<<<<< HEAD nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) @@ -434,22 +496,40 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; ======= for (i = 0; i < A->r; ++i) +======= + for (i = 0; i < M->r; ++i) +>>>>>>> Created sparse vector and matrix utilities for all the fq variants { - for (j = 0; j < A->rows[i].nnz; ++j) + for (j = 0; j < M->rows[i].nnz; ++j) { +<<<<<<< HEAD nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; >>>>>>> Spacing and cuddling fixed +======= + nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; +>>>>>>> Created sparse vector and matrix utilities for all the fq variants _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } } } +<<<<<<< HEAD FLINT_DLL slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); +======= +/* Permutations */ +/* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t M, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t M, slong * perm); +FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t M, slong * perm, slong r, slong s); +FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t M, slong * perm); +FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t M, slong * P, slong n); + */ +>>>>>>> Created sparse vector and matrix utilities for all the fq variants /* Decomposition/reduction */ FLINT_DLL slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t M); +<<<<<<< HEAD FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); @@ -496,6 +576,11 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M /* Note: this should take in uninitialized matrix X */ FLINT_DLL slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +======= + +FLINT_DLL +slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants <<<<<<< HEAD ======= @@ -516,6 +601,7 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t /* Solve Ax=b */ >>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann FLINT_DLL +<<<<<<< HEAD slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); FLINT_DLL @@ -530,6 +616,24 @@ int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); +======= +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); + +FLINT_DLL +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); + +FLINT_DLL +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); + +FLINT_DLL +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants <<<<<<< HEAD <<<<<<< HEAD @@ -539,27 +643,39 @@ mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); ======= ======= /* Find single nullvector */ -int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); +FLINT_DLL +int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state); +FLINT_DLL +int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); + +FLINT_DLL +int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); >>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann /* Note: this should take in uninitialized matrix X */ FLINT_DLL -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t A, flint_rand_t state, slong max_iters); +slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); FLINT_DLL -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t A); +slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL +<<<<<<< HEAD slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); >>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions +======= +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); +>>>>>>> Created sparse vector and matrix utilities for all the fq variants /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index 37f0b7ba86..dec4ff7275 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -80,7 +80,6 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) _nmod_vec_zero(nWi->rows[pc], b); } } - nmod_mat_neg(nWi, nWi); nmod_mat_clear(T); diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 97244208d1..2c264e7368 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -103,22 +103,22 @@ int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flin return ret; } -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t A, flint_rand_t state) { +int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) { int ret = 1; mp_ptr x2, b; - x2 = _nmod_vec_init(A->c); - b = _nmod_vec_init(A->r); + x2 = _nmod_vec_init(M->c); + b = _nmod_vec_init(M->r); - _nmod_vec_randtest(x, state, A->c, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); - if(nmod_sparse_mat_solve_lanczos(x2, A, b, state) == 0) ret = 0; /* Lanczos failed */ + _nmod_vec_randtest(x, state, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + if(nmod_sparse_mat_solve_lanczos(x2, M, b, state) == 0) ret = 0; /* Lanczos failed */ if (ret) { - _nmod_vec_sub(x, x, x2, A->c, A->mod); - nmod_sparse_mat_mul_vec(b, A, x); - ret = _nmod_vec_is_zero(x, A->c) || !_nmod_vec_is_zero(b, A->r); + _nmod_vec_sub(x, x, x2, M->c, M->mod); + nmod_sparse_mat_mul_vec(b, M, x); + ret = !_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(b, M->r); } _nmod_vec_clear(x2); _nmod_vec_clear(b); return ret; -} \ No newline at end of file +} From 559f6910927c803057537a3cb445ef1f75e98092 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 7 Apr 2020 22:25:15 -0700 Subject: [PATCH 34/42] Fixed spacing --- nmod_sparse_mat.h | 18 +++++++++++++++--- nmod_sparse_mat/test/t-solve.c | 6 +++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 07ee6bf8fb..1c2bfba230 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -96,7 +96,11 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { slong i, rmax = FLINT_MIN(M->r, src->r); +<<<<<<< HEAD if (M==src || M->r == 0) return; +======= + if(M==src || M->r == 0) return; +>>>>>>> Fixed spacing for (i = 0; i < rmax; ++i) nmod_sparse_vec_set(&M->rows[i], &src->rows[i], src->c_off); } @@ -107,7 +111,11 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, mp_srcptr v) { slong i; +<<<<<<< HEAD for (i = 0; i < M->r; ++i) nmod_sparse_vec_set_entry(&M->rows[i], M->c, v[i]); +======= + for (i = 0; i < M->r; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); +>>>>>>> Fixed spacing M->c += 1; } @@ -229,7 +237,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) { slong i; - for(i=0; ir; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); + for (i = 0; i < B->r; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); } /* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ @@ -238,8 +246,8 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, { slong i; r = FLINT_MIN(r, B->r); - for(i=0; irows[i], &B->rows[i], B->c_off); - for(i=r; ir; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); + for (i = 0; i < r; ++i) nmod_sparse_vec_set(&M1->rows[i], &B->rows[i], B->c_off); + for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } <<<<<<< HEAD @@ -592,6 +600,7 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD ======= @@ -600,6 +609,9 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t ======= /* Solve Ax=b */ >>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann +======= +/* Solve Ax = b */ +>>>>>>> Fixed spacing FLINT_DLL <<<<<<< HEAD slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 3315828a40..30b3819fc3 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -32,7 +32,7 @@ main(void) struct timeval start, end; FLINT_TEST_INIT(state); - flint_printf("solving Ax=b...."); + flint_printf("solving Ax = b...."); fflush(stdout); for (rep = 0; rep < nrep; rep++) @@ -86,7 +86,7 @@ main(void) /* Solve iteratively */ gettimeofday(&start, NULL); - ret=nmod_sparse_mat_solve_wiedemann(x2, A, b); + ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); gettimeofday(&end, NULL); wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); if (ret == 0) @@ -105,7 +105,7 @@ main(void) gettimeofday(&start, NULL); iter = 0; - do ret=nmod_sparse_mat_solve_lanczos(x2, A, b, state); + do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret==0 && ++iter < 30); gettimeofday(&end, NULL); lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); From ff58185652c135a91efe64fee31f344e562ca11b Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Wed, 8 Apr 2020 18:42:28 -0700 Subject: [PATCH 35/42] Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) --- nmod_sparse_mat.h | 22 +++++++++----- nmod_sparse_mat/solve_block_lanczos.c | 1 + nmod_sparse_mat/test/t-solve.c | 44 ++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 1c2bfba230..c174d0e78d 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -96,11 +96,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_set(nmod_sparse_mat_t M, const nmod_sparse_mat_t src) { slong i, rmax = FLINT_MIN(M->r, src->r); -<<<<<<< HEAD if (M==src || M->r == 0) return; -======= - if(M==src || M->r == 0) return; ->>>>>>> Fixed spacing for (i = 0; i < rmax; ++i) nmod_sparse_vec_set(&M->rows[i], &src->rows[i], src->c_off); } @@ -111,11 +107,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_append_col(nmod_sparse_mat_t M, mp_srcptr v) { slong i; -<<<<<<< HEAD for (i = 0; i < M->r; ++i) nmod_sparse_vec_set_entry(&M->rows[i], M->c, v[i]); -======= - for (i = 0; i < M->r; ++i) _nmod_sparse_vec_append_entry(&M->rows[i], M->c, v[i]); ->>>>>>> Fixed spacing M->c += 1; } @@ -475,6 +467,7 @@ void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const n /* Matrix-vector and matrix-matrix multipliciation */ NMOD_SPARSE_MAT_INLINE <<<<<<< HEAD +<<<<<<< HEAD void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; @@ -485,6 +478,9 @@ void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) >>>>>>> Spacing and cuddling fixed ======= void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, const mp_ptr x) +======= +void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) +>>>>>>> Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) { slong i; for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); @@ -495,6 +491,7 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod { slong i, j; <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) @@ -505,6 +502,9 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod ======= for (i = 0; i < A->r; ++i) ======= +======= + nmod_mat_zero(Y); +>>>>>>> Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) for (i = 0; i < M->r; ++i) >>>>>>> Created sparse vector and matrix utilities for all the fq variants { @@ -672,9 +672,15 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M FLINT_DLL slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +FLINT_DLL +slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); + FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +FLINT_DLL +slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); + FLINT_DLL slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index dec4ff7275..37f0b7ba86 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -80,6 +80,7 @@ static int compute_nWi_S(nmod_mat_t nWi, int *S, const nmod_mat_t Torig) _nmod_vec_zero(nWi->rows[pc], b); } } + nmod_mat_neg(nWi, nWi); nmod_mat_clear(T); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 30b3819fc3..43d4697b06 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -23,12 +23,15 @@ main(void) { int iter, ret; int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; + int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; slong rep, r, c, i, nrep = 100; mp_limb_t n, a; nmod_t mod; nmod_sparse_mat_t A, At; + nmod_mat_t dA; mp_ptr x, x2, b, Atb, Ax, AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0, wiedemann_elapsed; + double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; + double block_lanczos_elapsed = 0, block_wiedemann_elapsed = 0, wiedemann_elapsed = 0; struct timeval start, end; FLINT_TEST_INIT(state); @@ -39,16 +42,17 @@ main(void) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - do c = r = n_randint(state, 200); - while(c == 0 || r == 0); + c = r = 500 + n_randint(state, 100); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); + nmod_mat_init(dA, r, c, n); nmod_sparse_mat_init(At, c, r, mod); - nmod_sparse_mat_randtest(A, state, 30, 30); + nmod_sparse_mat_randtest(A, state, c/20, c/10); + nmod_sparse_mat_to_dense(dA, A); nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); @@ -122,7 +126,7 @@ main(void) nmod_sparse_mat_mul_vec(Atb, At, b); if (!_nmod_vec_equal(AtAx, Atb, A->c)) { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + flint_printf("FAIL: AtAx != Atb, got ret %d\n", 5, ret); abort(); } else if (!_nmod_vec_equal(b, Ax, A->r)) @@ -131,6 +135,34 @@ main(void) } } + gettimeofday(&start, NULL); + iter = 0; + do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); + while(ret==0 && ++iter < 10); + gettimeofday(&end, NULL); + block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret==0) + { + block_lanczos_nosol += 1; + continue; + } + else + { + block_lanczos_niters += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); + abort(); + } + else if (!_nmod_vec_equal(b, Ax, A->r)) + { + block_lanczos_psolved += 1; + } + } + flint_free(x); flint_free(x2); flint_free(b); @@ -145,9 +177,11 @@ main(void) flint_printf("PASS\n"); flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); + flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); + flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); return 0; } From 7638bff367786f0eddc7af7b2a57c96726b7c730 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 9 Apr 2020 15:52:59 -0700 Subject: [PATCH 36/42] Now with working block Wiedemann (and nullspace for both block methods) --- nmod_sparse_mat/solve_rref.c | 1 - nmod_sparse_mat/test/t-solve.c | 193 +++++++++++++-------------------- 2 files changed, 73 insertions(+), 121 deletions(-) diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c index a2a8fccb9b..db8d1df34b 100644 --- a/nmod_sparse_mat/solve_rref.c +++ b/nmod_sparse_mat/solve_rref.c @@ -28,7 +28,6 @@ int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b) _nmod_vec_zero(x, M->c); return 1; } - nmod_sparse_mat_init(Mb, M->r, M->c, M->mod); nmod_sparse_mat_set(Mb, M); nmod_sparse_mat_append_col(Mb, b); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 43d4697b06..9e29833e13 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -22,166 +22,119 @@ int main(void) { int iter, ret; - int niters = 0, wied_nosol = 0, nosol = 0, psolved = 0; - int block_lanczos_niters = 0, block_lanczos_nosol = 0, block_lanczos_psolved = 0; - slong rep, r, c, i, nrep = 100; + slong rep, nreps = 100, r, c, i; mp_limb_t n, a; nmod_t mod; - nmod_sparse_mat_t A, At; nmod_mat_t dA; + nmod_sparse_mat_t A, At; mp_ptr x, x2, b, Atb, Ax, AtAx; - double rref_elapsed = 0, lu_elapsed = 0, lanczos_elapsed = 0; - double block_lanczos_elapsed = 0, block_wiedemann_elapsed = 0, wiedemann_elapsed = 0; + slong niters[6] = {0, 0, 0, 0, 0, 0}; + slong psol[6] = {0, 0, 0, 0, 0, 0}; + slong nosol[6] = {0, 0, 0, 0, 0, 0}; + double elapsed[6] = {0, 0, 0, 0, 0}; + char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; struct timeval start, end; FLINT_TEST_INIT(state); flint_printf("solving Ax = b...."); fflush(stdout); - for (rep = 0; rep < nrep; rep++) + for (rep = 0; rep < nreps; rep++) { if(rep % 5==0) {flint_printf("."); fflush(stdout);} - c = r = 500 + n_randint(state, 100); - + c = r = 100 + n_randint(state, 50); do n = n_randtest_not_zero(state); while (n <= 32 || !n_is_prime(n)); nmod_init(&mod, n); nmod_sparse_mat_init(A, r, c, mod); nmod_mat_init(dA, r, c, n); - nmod_sparse_mat_init(At, c, r, mod); - - nmod_sparse_mat_randtest(A, state, c/20, c/10); - nmod_sparse_mat_to_dense(dA, A); - nmod_sparse_mat_transpose(At, A); x = _nmod_vec_init(c); x2 = _nmod_vec_init(c); b = _nmod_vec_init(r); Ax = _nmod_vec_init(r); - AtAx = _nmod_vec_init(c); - Atb = _nmod_vec_init(c); + nmod_sparse_mat_randtest(A, state, c/20, c/10); + nmod_sparse_mat_to_dense(dA, A); _nmod_vec_randtest(x, state, c, mod); nmod_sparse_mat_mul_vec(b, A, x); - /* Solve via reduced row echelon form */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_rref(x2, A, b); - gettimeofday(&end, NULL); - rref_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - nmod_sparse_mat_mul_vec(Ax, A, x2); - if(!_nmod_vec_equal(b, Ax, A->r)) + for (i = 0; i < 6; ++i) { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve via lu decomposition */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_lu(x2, A, b); - gettimeofday(&end, NULL); - lu_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - nmod_sparse_mat_mul_vec(Ax, A, x2); - if(!_nmod_vec_equal(b, Ax, A->r)) - { - flint_printf("FAIL: Ax != b, got ret %d\n", ret); - abort(); - } - - /* Solve iteratively */ - gettimeofday(&start, NULL); - ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); - gettimeofday(&end, NULL); - wiedemann_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret == 0) - { - wied_nosol += 1; - } - else - { - nmod_sparse_mat_mul_vec(Ax, A, x2); - if (!_nmod_vec_equal(b, Ax, A->r)) + iter = 0; + gettimeofday(&start, NULL); + switch (i) { - flint_printf("FAIL: Ax != b\n"); - abort(); + case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; + case 1: ret = nmod_sparse_mat_solve_lu(x2, A, b); break; + case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret == 0 && ++iter < 30); break; + case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while(ret == 0 && ++iter < 30); break; + case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; + case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; } - } - - gettimeofday(&start, NULL); - iter = 0; - do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); - while(ret==0 && ++iter < 30); - gettimeofday(&end, NULL); - lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) - { - nosol += 1; - continue; - } - else - { - niters += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", 5, ret); - abort(); - } - else if (!_nmod_vec_equal(b, Ax, A->r)) + gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + if (ret == 0) nosol[i] += 1; + else { - psolved += 1; + niters[i] += iter; + nmod_sparse_mat_mul_vec(Ax, A, x2); + if (!_nmod_vec_equal(b, Ax, A->r)) + { + if (i == 2 || i == 3) + { + nmod_sparse_mat_init(At, c, r, mod); + AtAx = _nmod_vec_init(c); + Atb = _nmod_vec_init(c); + nmod_sparse_mat_transpose(At, A); + nmod_sparse_mat_mul_vec(AtAx, At, Ax); + nmod_sparse_mat_mul_vec(Atb, At, b); + if (!_nmod_vec_equal(AtAx, Atb, A->c)) + { + flint_printf("FAIL on %s: AtAx != Atb\n", names[i]); + abort(); + } + else psol[i] += 1; + flint_free(AtAx); + flint_free(Atb); + nmod_sparse_mat_clear(At); + } + else + { + flint_printf("FAIL on %s: Ax != b\n", names[i]); + flint_printf("A = "); + nmod_sparse_mat_print_pretty(A); + flint_printf("x = "); + _nmod_vec_print_pretty(x, c, mod); + flint_printf("x2 = "); + _nmod_vec_print_pretty(x2, c, mod); + flint_printf("Ax2 = "); + _nmod_vec_print_pretty(Ax, r, mod); + flint_printf("b = "); + _nmod_vec_print_pretty(b, r, mod); + abort(); + } + } } } - - gettimeofday(&start, NULL); - iter = 0; - do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); - while(ret==0 && ++iter < 10); - gettimeofday(&end, NULL); - block_lanczos_elapsed += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); - if (ret==0) - { - block_lanczos_nosol += 1; - continue; - } - else - { - block_lanczos_niters += iter; - nmod_sparse_mat_mul_vec(Ax, A, x2); - nmod_sparse_mat_mul_vec(AtAx, At, Ax); - nmod_sparse_mat_mul_vec(Atb, At, b); - if (!_nmod_vec_equal(AtAx, Atb, A->c)) - { - flint_printf("FAIL: AtAx != Atb, got ret %d\n", ret); - abort(); - } - else if (!_nmod_vec_equal(b, Ax, A->r)) - { - block_lanczos_psolved += 1; - } - } - flint_free(x); flint_free(x2); flint_free(b); flint_free(Ax); - flint_free(AtAx); - flint_free(Atb); nmod_sparse_mat_clear(A); - nmod_sparse_mat_clear(At); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); - flint_printf("Average time for Wiedemann: %lf\n", wiedemann_elapsed/nrep); - flint_printf("Average time for Lanzcos: %lf\n", lanczos_elapsed/nrep); - flint_printf("Average time for block Lanzcos: %lf\n", block_lanczos_elapsed/nrep); - flint_printf("Average time for LU: %lf\n", lu_elapsed/nrep); - flint_printf("Average time for rref: %lf\n", rref_elapsed/nrep); - flint_printf("Wiedemann found no solution for %wd/%wd examples.\n", wied_nosol, nrep); - flint_printf("Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", nosol, nrep, psolved, nrep, (double)niters/nrep); - flint_printf("Block Lanczos found no solution for %wd/%wd examples, pseudo-solution for %wd/%wd examples, and required %f extra iters per solution (on average).\n", block_lanczos_nosol, nrep, block_lanczos_psolved, nrep, (double)block_lanczos_niters/nrep); + for (i = 0; i < 6; ++i) + { + flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + if (nosol[i]) + flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); + if (psol[i]) + flint_printf("\tFound pseudo-solution for %wd/%wd examples\n", psol[i], nreps); + if (niters[i]) + flint_printf("\tRequired %f extra iters per solution (on average).\n", (double)niters[i]/nreps); + } return 0; } From 58cee49b20faef3e943169e74213bc28e8ed9536 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Thu, 9 Apr 2020 22:28:24 -0700 Subject: [PATCH 37/42] Added rst documentation for sparse vectors and matrices --- fq_sparse_mat_templates/test/t-scalar_mul.c | 16 ------- nmod_sparse_mat.h | 51 +++++++++++++++++---- nmod_sparse_vec.h | 16 +++++-- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c index db595a22b0..0c1b8a5513 100644 --- a/fq_sparse_mat_templates/test/t-scalar_mul.c +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -20,11 +20,7 @@ int main(void) { -<<<<<<< HEAD slong rep, r, c; -======= - slong rep, r, c, i; ->>>>>>> Created sparse vector and matrix utilities for all the fq variants TEMPLATE(T, t) a, cc; TEMPLATE(T, ctx_t) ctx; TEMPLATE(T, sparse_mat_t) A, B, C, D; @@ -48,17 +44,10 @@ main(void) TEMPLATE(T, sparse_mat_randtest) (A, state, 0, c, ctx); -<<<<<<< HEAD TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (B, A, a, ctx); TEMPLATE(T, one) (cc, ctx); TEMPLATE(T, sub) (cc, a, cc, ctx); TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, cc, ctx); -======= - TEMPLATE(T, sparse_mat_scalar_mul) (B, A, a, ctx); - TEMPLATE(T, one) (cc, ctx); - TEMPLATE(T, sub) (cc, a, cc, ctx); - TEMPLATE(T, sparse_mat_scalar_mul) (C, A, cc, ctx); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants /* c*A - (c-1)*A == A */ TEMPLATE(T, sparse_mat_sub) (D, B, C, ctx); @@ -70,13 +59,8 @@ main(void) } /* Aliasing */ -<<<<<<< HEAD TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (C, A, a, ctx); TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (A, A, a, ctx); -======= - TEMPLATE(T, sparse_mat_scalar_mul) (C, A, a, ctx); - TEMPLATE(T, sparse_mat_scalar_mul) (A, A, a, ctx); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants if (!TEMPLATE(T, sparse_mat_equal) (A, C, ctx)) { diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index c174d0e78d..e70741ac85 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -62,6 +62,7 @@ void nmod_sparse_mat_init(nmod_sparse_mat_t M, slong rows, slong cols, nmod_t mo M->c_off = 0; M->mod = mod; } + NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_clear(nmod_sparse_mat_t M) { @@ -70,6 +71,7 @@ void nmod_sparse_mat_clear(nmod_sparse_mat_t M) flint_free(M->rows); memset(M, 0, sizeof(*M)); } + NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_swap(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2) { @@ -341,6 +343,7 @@ int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) return 1; } +<<<<<<< HEAD NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) { @@ -348,6 +351,8 @@ int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) } >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= +>>>>>>> Added rst documentation for sparse vectors and matrices /* Must have M->r == N->c and M->c == N->r */ FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, const nmod_sparse_mat_t M); @@ -388,14 +393,18 @@ void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_ } NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_mul(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) +void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; nmod_sparse_mat_set(N, M); +<<<<<<< HEAD for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul(&N->rows[i], &N->rows[i], c, N->mod); >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= + for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); +>>>>>>> Added rst documentation for sparse vectors and matrices } } @@ -405,16 +414,21 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, N->mod.n); +<<<<<<< HEAD <<<<<<< HEAD nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); ======= nmod_sparse_mat_scalar_mul(N, M, fmpz_get_ui(d)); >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= + nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); +>>>>>>> Added rst documentation for sparse vectors and matrices fmpz_clear(d); } NMOD_SPARSE_MAT_INLINE <<<<<<< HEAD +<<<<<<< HEAD void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; @@ -447,21 +461,30 @@ void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, cons ======= void nmod_sparse_mat_addmul(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= +void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +>>>>>>> Added rst documentation for sparse vectors and matrices { slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); +} + +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) +{ + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, nmod_neg(c, O->mod)); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(O, M, N, UWORD(1)); + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, UWORD(1)); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { - nmod_sparse_mat_addmul(O, M, N, O->mod.n-UWORD(1)); + nmod_sparse_mat_scalar_addmul_nmod(O, M, N, O->mod.n-UWORD(1)); } /* Matrix-vector and matrix-matrix multipliciation */ @@ -521,6 +544,7 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod } } +<<<<<<< HEAD <<<<<<< HEAD FLINT_DLL slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); @@ -533,6 +557,10 @@ FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t M, slong * perm); FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t M, slong * P, slong n); */ >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= +FLINT_DLL +slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); +>>>>>>> Added rst documentation for sparse vectors and matrices /* Decomposition/reduction */ FLINT_DLL @@ -614,6 +642,7 @@ slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t >>>>>>> Fixed spacing FLINT_DLL <<<<<<< HEAD +<<<<<<< HEAD slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); FLINT_DLL @@ -630,18 +659,21 @@ FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); ======= int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); +======= +int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state); +>>>>>>> Added rst documentation for sparse vectors and matrices FLINT_DLL -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b); +int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); FLINT_DLL -int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, slong block_size, flint_rand_t state); +int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); FLINT_DLL int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); @@ -687,6 +719,7 @@ slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); +<<<<<<< HEAD FLINT_DLL <<<<<<< HEAD slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); @@ -695,6 +728,8 @@ slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); >>>>>>> Created sparse vector and matrix utilities for all the fq variants +======= +>>>>>>> Added rst documentation for sparse vectors and matrices /* Nullspace */ /* NMOD_SPARSE_MAT_INLINE slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index db2e8d6cce..4c59a7ce6e 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -125,11 +125,17 @@ void nmod_sparse_vec_set_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) NMOD_SPARSE_VEC_INLINE void _nmod_sparse_vec_append_entry(nmod_sparse_vec_t v, slong ind, mp_limb_t val) { - if (val == UWORD(0)) return; - v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); - v->entries[v->nnz].ind = ind; - v->entries[v->nnz].val = val; - v->nnz += 1; + mp_limb_t *oval = nmod_sparse_vec_at(v, ind); + if(oval == NULL) + { + v->entries = flint_realloc(v->entries, (v->nnz+1)*sizeof(*v->entries)); + v->entries[v->nnz].ind = ind; + v->entries[v->nnz].val = val; + v->nnz += 1; + if (v->nnz >= 2 && v->entries[v->nnz-2].ind > ind) + qsort(v->entries, v->nnz, sizeof(*v->entries), nmod_sparse_entry_cmp); + } + else *oval = val; } FLINT_DLL From aae4174fc7d2d4d9000ee99b9388747727b04eef Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 28 Apr 2020 22:08:32 -0700 Subject: [PATCH 38/42] Most of the desired code for sparse integer linear algebra, except for smith normal form --- CMakeLists.txt | 6 +- Makefile.in | 2 +- fmpz_sparse_vec/gauss_elim_debugging | 146 ++++++++++++++ fq_sparse_mat/from_entries.c | 8 - fq_sparse_mat_templates/from_entries.c | 8 - nmod_sparse_mat.h | 265 +------------------------ nmod_sparse_mat/test/t-construct.c | 26 --- nmod_sparse_mat/test/t-solve.c | 17 +- 8 files changed, 163 insertions(+), 315 deletions(-) create mode 100644 fmpz_sparse_vec/gauss_elim_debugging diff --git a/CMakeLists.txt b/CMakeLists.txt index 85a6576337..4e11930006 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,8 @@ endif() # Find sources set(BUILD_DIRS - aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_poly - fmpq_poly fmpz_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly + aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_sparse_vec fmpz_poly + fmpq_poly fmpz_mat fmpz_sparse_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve @@ -96,7 +96,7 @@ endif() set(HEADERS NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h - fmpz-conversions.h profiler.h templates.h exception.h hashmap.h + fmpz-conversions.h profiler.h templates.h exception.h heap.h hashmap.h ) foreach (build_dir IN LISTS BUILD_DIRS TEMPLATE_DIRS) diff --git a/Makefile.in b/Makefile.in index 16a539c330..4de9334a99 100644 --- a/Makefile.in +++ b/Makefile.in @@ -30,7 +30,7 @@ export SOURCES = printf.c fprintf.c sprintf.c scanf.c fscanf.c sscanf.c clz_tab.c memory_manager.c version.c profiler.c thread_support.c exception.c heap.c hashmap.c inlines.c LIB_SOURCES = $(wildcard $(patsubst %, %/*.c, $(BUILD_DIRS))) $(patsubst %, %/*.c, $(TEMPLATE_DIRS)) -HEADERS = $(patsubst %, %.h, $(BUILD_DIRS)) NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h fmpz-conversions.h profiler.h templates.h exception.h hashmap.h thread_support.h $(patsubst %, %.h, $(TEMPLATE_DIRS)) +HEADERS = $(patsubst %, %.h, $(BUILD_DIRS)) NTL-interface.h flint.h longlong.h flint-config.h gmpcompat.h fft_tuning.h fmpz-conversions.h profiler.h templates.h exception.h heap.h hashmap.h thread_support.h $(patsubst %, %.h, $(TEMPLATE_DIRS)) OBJS = $(patsubst %.c, build/%.o, $(SOURCES)) LIB_OBJS = $(patsubst %, build/%/*.o, $(BUILD_DIRS)) diff --git a/fmpz_sparse_vec/gauss_elim_debugging b/fmpz_sparse_vec/gauss_elim_debugging new file mode 100644 index 0000000000..48040a0972 --- /dev/null +++ b/fmpz_sparse_vec/gauss_elim_debugging @@ -0,0 +1,146 @@ +/* + Copyright (C) 2010 Fredrik Johansson + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by th e Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include +#include +#include +#include "flint.h" +#include "fmpz_sparse_vec.h" + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col) +{ + fmpz_t q; + fmpz_t *uc = fmpz_sparse_vec_at(u, col); + fmpz_t *vc = fmpz_sparse_vec_at(v, col); + if (uc == NULL || vc == NULL) return; + + fmpz_init(q); + fmpz_fdiv_q(q, *uc, *vc); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Reduce u by v */ +void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) +{ + fmpz_t q, *uc; + fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; + if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; + fmpz_init(q); + flint_printf("Doing ordinary gaussian elimination, found coefficient "); + if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); + else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); + fmpz_print(q); flint_printf(": %wd\n", q[0]); + fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); + fmpz_clear(q); +} + +/* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ +void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) +{ + slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; + fmpz_sparse_entry_struct *lu = u->entries; + fmpz_sparse_entry_struct *lv = v->entries; + fmpz_t g, vv, vu, uv, uu, a, b; + fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; + if(u->nnz == 0 || v->nnz == 0) return; + flint_printf("\t\t\t%wd, %wd\n", lu->ind, lv->ind); + if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} + pc = lu->ind; + if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ + { + flint_printf("Swapping\n"); + fmpz_sparse_vec_swap(u, v); + fmpz_sparse_vec_neg(u, u); + lu = u->entries, lv = v->entries; + vnnz = v->nnz, unnz = u->nnz; + } + if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ + { + fmpz_sparse_vec_neg(v, v); + fmpz_sparse_vec_neg(u, u); + } + flint_printf("pr[pc] = "), fmpz_print(lv->val), flint_printf("\n"); + flint_printf("r[pc] = "), fmpz_print(lu->val), flint_printf("\n"); + + /* Check for trivial cases */ + if (fmpz_divisible(lu->val, lv->val)) {fmpz_sparse_vec_gauss_elim(u, v); return;} + + fmpz_init(g); + fmpz_init(vv); + fmpz_init(vu); + fmpz_init(uv); + fmpz_init(uu); + fmpz_init(a); + fmpz_init(b); + + /* Construct transformation */ + fmpz_xgcd(g, vv, vu, lv->val, lu->val); + if (fmpz_sgn(g) < 0) + { + fmpz_neg(vv, vv); + fmpz_neg(vu, vu); + } + fmpz_divexact(uu, lv->val, g); + fmpz_divexact(uv, lu->val, g); + fmpz_neg(uv, uv); /* [[uu uv] [vu vv]] is unimodular */ + fmpz_set(g, uv); + flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); + flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); + flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); + + /* Reallocate vectors */ + nnz = _fmpz_sparse_vec_union_nnz (u, v); + _fmpz_sparse_vec_resize(u, nnz); + _fmpz_sparse_vec_resize(v, nnz); + ue = u->entries + unnz, ve = v->entries + vnnz; /* Old locations */ + nue = u->entries + nnz, nve = v->entries + nnz; /* New locations */ + while ((k = _fmpz_sparse_vector_merge_descend (&nue, &ue, &ve, u, v)) >= 0) + { + nve--; + flint_printf("%wd, %wd, %wd\n", nnz, nue - u->entries, nve-v->entries); + flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); + flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); + flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); + flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); + flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); + switch(k) + { + case 0: nve->ind = ue->ind; fmpz_mul(nve->val, ue->val, vu); fmpz_mul(nue->val, ue->val, uu); break; + case 1: nve->ind = ve->ind; fmpz_mul(nue->val, ve->val, g); fmpz_mul(nve->val, ve->val, vv); break; + default: nve->ind = ve->ind; + flint_printf("\t\tcur: [[%wd, %wd], [%wd, %wd]]\n", nue->val[0], nve->val[0], ue->val[0], ve->val[0]); + flint_printf("\t\tcur: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); + flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); + + fmpz_set(a, ve->val); + fmpz_set(b, ue->val); + fmpz_mul(nve->val, a, vv); fmpz_addmul(nve->val, b, vu); + fmpz_mul(nue->val, b, uu); fmpz_addmul(nue->val, a, uv); + flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(vu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(vv); flint_printf("\n"); + flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(uu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); flint_printf("\n"); + flint_printf("\t\tafter: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); + flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); + } + if (fmpz_is_zero(nue->val)) nue++; + if (fmpz_is_zero(nve->val)) nve++; + } + _fmpz_sparse_vector_shift_left (u, nue - u->entries); + _fmpz_sparse_vector_shift_left (v, nve - v->entries); + fmpz_clear(g); + fmpz_clear(vv); + fmpz_clear(vu); + fmpz_clear(uv); + fmpz_clear(uu); + fmpz_clear(a); + fmpz_clear(b); +} diff --git a/fq_sparse_mat/from_entries.c b/fq_sparse_mat/from_entries.c index f3ff7e5490..30de86fbff 100644 --- a/fq_sparse_mat/from_entries.c +++ b/fq_sparse_mat/from_entries.c @@ -1,13 +1,5 @@ /* -<<<<<<< HEAD -<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters -======= - Copyright (C) 2011 Fredrik Johansson ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition This file is part of FLINT. diff --git a/fq_sparse_mat_templates/from_entries.c b/fq_sparse_mat_templates/from_entries.c index c3fc5e1dff..70fa95bf0e 100644 --- a/fq_sparse_mat_templates/from_entries.c +++ b/fq_sparse_mat_templates/from_entries.c @@ -1,13 +1,5 @@ /* -<<<<<<< HEAD -<<<<<<< HEAD Copyright (C) 2011 Fredrik Johansson -======= - Copyright (C) 2010 Fredrik Johansson ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters -======= - Copyright (C) 2011 Fredrik Johansson ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition This file is part of FLINT. diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index e70741ac85..c97844858b 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -193,17 +193,7 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } -<<<<<<< HEAD - -======= -======= -======= ->>>>>>> Spacing and cuddling fixed - - /* res->r must equal mat1->r and mat2->r */ -======= ->>>>>>> Created sparse vector and matrix utilities for all the fq variants NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) @@ -244,29 +234,13 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition -======= ->>>>>>> Spacing and cuddling fixed -======= - ->>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions /* Matrix permutation */ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; -<<<<<<< HEAD -<<<<<<< HEAD - for (i = 0; i < M->r; ++i) - { - if (!M->rows[i].nnz) continue; -======= for (i = 0; i < M->r; ++i) { if(!M->rows[i].nnz) continue; ->>>>>>> Created sparse vector and matrix utilities for all the fq variants nmod_sparse_vec_permute_inds(&M->rows[i], Q); qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), nmod_sparse_entry_cmp); } @@ -281,9 +255,6 @@ void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t M, slong *P) for (i = 0; i < M->r; ++i) prows[P[i]] = M->rows[i]; memcpy(M->rows, prows, M->r*sizeof(*M->rows)); flint_free(prows); -======= - for (i = 0; i < mat->r; ++i) nmod_sparse_vec_permute_inds(&mat->rows[i], Q); ->>>>>>> Spacing and cuddling fixed } /* Random matrix generation */ @@ -304,21 +275,9 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_equal(const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) { slong i; -<<<<<<< HEAD -<<<<<<< HEAD - if (M1->r != M2->r) return 0; - for (i = 0; i < M1->r; ++i) - if (nmod_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off) == 0) return 0; -======= - if (mat1->r != mat2->r) return 0; - for (i = 0; i < mat1->r; ++i) - if (nmod_sparse_vec_equal(&mat1->rows[i], &mat2->rows[i], mat1->c_off-mat2->c_off) == 0) return 0; ->>>>>>> Spacing and cuddling fixed -======= if (M1->r != M2->r) return 0; for (i = 0; i < M1->r; ++i) if (nmod_sparse_vec_equal(&M1->rows[i], &M2->rows[i], M1->c_off-M2->c_off) == 0) return 0; ->>>>>>> Created sparse vector and matrix utilities for all the fq variants return 1; } @@ -326,14 +285,8 @@ NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) { slong i; -<<<<<<< HEAD -<<<<<<< HEAD for (i = 0; i < M->r; ++i) if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; -======= - for (i = 0; i < mat->r; ++i) - if (!nmod_sparse_vec_is_zero(&mat->rows[i])) return 0; ->>>>>>> Spacing and cuddling fixed return 1; } @@ -343,16 +296,12 @@ int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) return 1; } -<<<<<<< HEAD NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) { return (M->r == M->c); } ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -======= ->>>>>>> Added rst documentation for sparse vectors and matrices /* Must have M->r == N->c and M->c == N->r */ FLINT_DLL void nmod_sparse_mat_transpose(nmod_sparse_mat_t N, const nmod_sparse_mat_t M); @@ -361,35 +310,19 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) { slong i; -<<<<<<< HEAD -<<<<<<< HEAD nmod_sparse_mat_set(N, M); for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); -======= - nmod_sparse_mat_set(B, A); - for (i = 0; i < B->r; ++i) nmod_sparse_vec_neg(&B->rows[i], &B->rows[i], B->mod); ->>>>>>> Spacing and cuddling fixed } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { -<<<<<<< HEAD if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; nmod_sparse_mat_set(N, M); - for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); -======= - if (c == UWORD(0)) nmod_sparse_mat_zero(B); - else { - slong i; - nmod_sparse_mat_set(B, A); - for (i = 0; i < B->r; ++i) nmod_sparse_vec_scalar_mul(&B->rows[i], &B->rows[i], c, B->mod); ->>>>>>> Spacing and cuddling fixed -======= - nmod_sparse_mat_set(N, M); - for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); + for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); + } } NMOD_SPARSE_MAT_INLINE @@ -399,12 +332,7 @@ void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_ else { slong i; nmod_sparse_mat_set(N, M); -<<<<<<< HEAD - for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul(&N->rows[i], &N->rows[i], c, N->mod); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -======= for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); ->>>>>>> Added rst documentation for sparse vectors and matrices } } @@ -414,21 +342,10 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ fmpz_t d; fmpz_init(d); fmpz_mod_ui(d, c, N->mod.n); -<<<<<<< HEAD -<<<<<<< HEAD nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); -======= - nmod_sparse_mat_scalar_mul(N, M, fmpz_get_ui(d)); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -======= - nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); ->>>>>>> Added rst documentation for sparse vectors and matrices fmpz_clear(d); } -NMOD_SPARSE_MAT_INLINE -<<<<<<< HEAD -<<<<<<< HEAD void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; @@ -439,7 +356,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_sub(&O->rows[i], &M->rows[i], &N->rows[i], O->mod); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } NMOD_SPARSE_MAT_INLINE @@ -456,89 +373,23 @@ void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_m for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_addmul(nmod_sparse_mat_t C, const nmod_sparse_mat_t A, const nmod_sparse_mat_t B, mp_limb_t c) -======= -void nmod_sparse_mat_addmul(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -======= -void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) ->>>>>>> Added rst documentation for sparse vectors and matrices -{ - slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); -} - -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) -{ - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, nmod_neg(c, O->mod)); -} - -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) -{ - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, UWORD(1)); -} - -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) -{ - nmod_sparse_mat_scalar_addmul_nmod(O, M, N, O->mod.n-UWORD(1)); -} - /* Matrix-vector and matrix-matrix multipliciation */ -NMOD_SPARSE_MAT_INLINE -<<<<<<< HEAD -<<<<<<< HEAD void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; -<<<<<<< HEAD for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); -======= - for (i = 0; i < A->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&A->rows[i], x, A->mod); ->>>>>>> Spacing and cuddling fixed -======= -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, const mp_ptr x) -======= -void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) ->>>>>>> Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) -{ - slong i; - for (i = 0; i < M->r; ++i) y[i] = nmod_sparse_vec_dot_dense(&M->rows[i], x, M->mod); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants } + NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) { for (j = 0; j < M->rows[i].nnz; ++j) { nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; -======= - for (i = 0; i < A->r; ++i) -======= -======= - nmod_mat_zero(Y); ->>>>>>> Fixed bug in multiply, block Lanczos now works for solving (but not for nullspace) - for (i = 0; i < M->r; ++i) ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -{ - for (j = 0; j < M->rows[i].nnz; ++j) -{ -<<<<<<< HEAD - nmod_sparse_entry_struct *e = &A->rows[i].entries[j]; ->>>>>>> Spacing and cuddling fixed -======= - nmod_sparse_entry_struct *e = &M->rows[i].entries[j]; ->>>>>>> Created sparse vector and matrix utilities for all the fq variants _nmod_vec_scalar_addmul_nmod(Y->rows[i], X->rows[e->ind], X->c, e->val, Y->mod); } } @@ -556,16 +407,12 @@ FLINT_DLL void nmod_sparse_mat_swap_cols(nmod_sparse_mat_t M, slong * perm, slon FLINT_DLL void nmod_sparse_mat_invert_cols(nmod_sparse_mat_t M, slong * perm); FLINT_DLL void nmod_sparse_mat_apply_permutation(nmod_sparse_mat_t M, slong * P, slong n); */ ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -======= FLINT_DLL slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); ->>>>>>> Added rst documentation for sparse vectors and matrices /* Decomposition/reduction */ FLINT_DLL slong nmod_sparse_mat_lu(slong *P, slong *Q, nmod_sparse_mat_t L, nmod_sparse_mat_t U, const nmod_sparse_mat_t M); -<<<<<<< HEAD FLINT_DLL slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); @@ -612,128 +459,24 @@ int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M /* Note: this should take in uninitialized matrix X */ FLINT_DLL slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); -======= -FLINT_DLL -slong nmod_sparse_mat_rref(nmod_sparse_mat_t M); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants - -<<<<<<< HEAD -======= -/* Decomposition/reduction */ ->>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions FLINT_DLL slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= -/* Solving */ ->>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions -======= -/* Solve Ax=b */ ->>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann -======= -/* Solve Ax = b */ ->>>>>>> Fixed spacing -FLINT_DLL -<<<<<<< HEAD -<<<<<<< HEAD slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); -FLINT_DLL -<<<<<<< HEAD slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); -======= -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); - -FLINT_DLL -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t A, const mp_ptr b); ->>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann FLINT_DLL slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); -======= -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, const mp_ptr b, flint_rand_t state); -======= -int nmod_sparse_mat_solve_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, flint_rand_t state); ->>>>>>> Added rst documentation for sparse vectors and matrices - -FLINT_DLL -int nmod_sparse_mat_solve_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); - -FLINT_DLL -int nmod_sparse_mat_solve_lu(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); - -FLINT_DLL -int nmod_sparse_mat_solve_rref(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b); - -FLINT_DLL -int nmod_sparse_mat_solve_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); - -FLINT_DLL -int nmod_sparse_mat_solve_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, mp_srcptr b, slong block_size, flint_rand_t state); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants -<<<<<<< HEAD -<<<<<<< HEAD /* Determinant */ FLINT_DLL mp_limb_t nmod_sparse_mat_det(const nmod_sparse_mat_t M); -======= -======= -/* Find single nullvector */ -FLINT_DLL -int nmod_sparse_mat_nullvector_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); - -FLINT_DLL -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state); - -FLINT_DLL -int nmod_sparse_mat_nullvector_block_wiedemann(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); - -FLINT_DLL -int nmod_sparse_mat_nullvector_block_lanczos(mp_ptr x, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state); - ->>>>>>> Added nullvector functions for Lanzcos, everything for basic Wiedemann -/* Note: this should take in uninitialized matrix X */ -FLINT_DLL -slong nmod_sparse_mat_nullspace_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); -FLINT_DLL -slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); - -FLINT_DLL -slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); - -FLINT_DLL -slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); - -FLINT_DLL -slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); - -FLINT_DLL -slong nmod_sparse_mat_nullspace_lu(nmod_mat_t X, const nmod_sparse_mat_t M); - -<<<<<<< HEAD -FLINT_DLL -<<<<<<< HEAD -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t A); ->>>>>>> Now with additional utilities, more correct basic functions, and nullspace and inversion functions -======= -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); ->>>>>>> Created sparse vector and matrix utilities for all the fq variants - -======= ->>>>>>> Added rst documentation for sparse vectors and matrices -/* Nullspace */ -/* NMOD_SPARSE_MAT_INLINE -slong nmod_sparse_mat_nullspace(nmod_mat_t X, const nmod_sparse_mat_t M); - */ #ifdef __cplusplus } #endif diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 4002fa1b60..88a15093d0 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -62,19 +62,13 @@ main(void) } } nmod_sparse_mat_from_entries(B, rows, cols, vals, nnz); - if (!nmod_sparse_mat_equal(A, B)) { flint_printf("FAIL: A != B\n"); -<<<<<<< HEAD -<<<<<<< HEAD -======= ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition flint_printf("A = "); nmod_sparse_mat_print_pretty(A); flint_printf("B = "); nmod_sparse_mat_print_pretty(B); -<<<<<<< HEAD abort(); } @@ -86,20 +80,6 @@ main(void) nmod_sparse_mat_print_pretty(A); flint_printf("C = "); nmod_sparse_mat_print_pretty(C); -======= - abort(); - } - /* Construct C from rows of A */ - for(i=0; ir; ++i) { - nmod_sparse_mat_append_row(C, i, cols + A->row_starts[i], vals + A->row_starts[i], A->row_nnz[i]); - } - - if (!nmod_sparse_mat_equal(A, C)) - { - flint_printf("FAIL: A != C\n"); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters -======= ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition abort(); } flint_free(rows); @@ -107,13 +87,7 @@ main(void) flint_free(vals); nmod_sparse_mat_clear(A); nmod_sparse_mat_clear(B); -<<<<<<< HEAD -<<<<<<< HEAD -======= nmod_sparse_mat_clear(C); ->>>>>>> Initial code for sparse matrices mod limb size integers, just construction and arithmetic for starters -======= ->>>>>>> Added sparse vector class to nmod, changed sparse matrix class to use it for underlying, added (untested) LU decomposition } FLINT_TEST_CLEANUP(state); diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 9e29833e13..c63b739ad6 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -13,7 +13,7 @@ #include #include #include -#include +/*#include */ #include "flint.h" #include "nmod_sparse_mat.h" #include "ulong_extras.h" @@ -23,7 +23,7 @@ main(void) { int iter, ret; slong rep, nreps = 100, r, c, i; - mp_limb_t n, a; + mp_limb_t n; nmod_t mod; nmod_mat_t dA; nmod_sparse_mat_t A, At; @@ -31,9 +31,9 @@ main(void) slong niters[6] = {0, 0, 0, 0, 0, 0}; slong psol[6] = {0, 0, 0, 0, 0, 0}; slong nosol[6] = {0, 0, 0, 0, 0, 0}; - double elapsed[6] = {0, 0, 0, 0, 0}; + /*double elapsed[6] = {0, 0, 0, 0, 0};*/ char *names[6] = {"rref", "lu", "Lanczos", "block Lanczos", "Wiedemann", "block Wiedemann"}; - struct timeval start, end; + /*struct timeval start, end;*/ FLINT_TEST_INIT(state); flint_printf("solving Ax = b...."); @@ -62,7 +62,7 @@ main(void) for (i = 0; i < 6; ++i) { iter = 0; - gettimeofday(&start, NULL); + /*gettimeofday(&start, NULL);*/ switch (i) { case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; @@ -72,8 +72,8 @@ main(void) case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; } - gettimeofday(&end, NULL); - elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec); + /*gettimeofday(&end, NULL); + elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec);*/ if (ret == 0) nosol[i] += 1; else { @@ -128,7 +128,8 @@ main(void) flint_printf("PASS\n"); for (i = 0; i < 6; ++i) { - flint_printf("Solving with %s took average time %lf\n", names[i], elapsed[i]/nreps); + flint_printf("Solved with %s\n", names[i]); + /*flint_printf("\tAverage time: %lf\n", elapsed[i]/nreps);*/ if (nosol[i]) flint_printf("\tFound no solution for %wd/%wd examples\n", nosol[i], nreps); if (psol[i]) From fd54b3292b52b715008312d57fce370c886c01a8 Mon Sep 17 00:00:00 2001 From: Kartik Venkatram Date: Tue, 28 Apr 2020 22:31:09 -0700 Subject: [PATCH 39/42] Fixed spacing issues --- fmpz_sparse_vec/gauss_elim_debugging | 146 --------------------------- fq_sparse_mat_templates/tmp | 31 ------ nmod_sparse_mat.h | 5 +- nmod_sparse_mat/solve_lanczos.c | 20 ---- nmod_sparse_mat/test/t-solve.c | 8 +- 5 files changed, 7 insertions(+), 203 deletions(-) delete mode 100644 fmpz_sparse_vec/gauss_elim_debugging delete mode 100644 fq_sparse_mat_templates/tmp diff --git a/fmpz_sparse_vec/gauss_elim_debugging b/fmpz_sparse_vec/gauss_elim_debugging deleted file mode 100644 index 48040a0972..0000000000 --- a/fmpz_sparse_vec/gauss_elim_debugging +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2010 Fredrik Johansson - - This file is part of FLINT. - - FLINT is free software: you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License (LGPL) as published - by th e Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. See . -*/ - -#include -#include -#include -#include "flint.h" -#include "fmpz_sparse_vec.h" - -/* Reduce u by v */ -void fmpz_sparse_vec_gauss_elim_col(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v, slong col) -{ - fmpz_t q; - fmpz_t *uc = fmpz_sparse_vec_at(u, col); - fmpz_t *vc = fmpz_sparse_vec_at(v, col); - if (uc == NULL || vc == NULL) return; - - fmpz_init(q); - fmpz_fdiv_q(q, *uc, *vc); - fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); - fmpz_clear(q); -} - -/* Reduce u by v */ -void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) -{ - fmpz_t q, *uc; - fmpz_sparse_entry_struct *lu = u->entries, *lv = v->entries; - if(u->nnz == 0 || v->nnz == 0 || lu->ind > lv->ind) return; - fmpz_init(q); - flint_printf("Doing ordinary gaussian elimination, found coefficient "); - if (lu->ind == lv->ind) fmpz_fdiv_q(q, lu->val, lv->val); - else if((uc = fmpz_sparse_vec_at(u, lv->ind))) fmpz_fdiv_q(q, *uc, lv->val); - fmpz_print(q); flint_printf(": %wd\n", q[0]); - fmpz_sparse_vec_scalar_submul_fmpz(u, u, v, q); - fmpz_clear(q); -} - -/* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ -void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) -{ - slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; - fmpz_sparse_entry_struct *lu = u->entries; - fmpz_sparse_entry_struct *lv = v->entries; - fmpz_t g, vv, vu, uv, uu, a, b; - fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; - if(u->nnz == 0 || v->nnz == 0) return; - flint_printf("\t\t\t%wd, %wd\n", lu->ind, lv->ind); - if(lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} - pc = lu->ind; - if(fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ - { - flint_printf("Swapping\n"); - fmpz_sparse_vec_swap(u, v); - fmpz_sparse_vec_neg(u, u); - lu = u->entries, lv = v->entries; - vnnz = v->nnz, unnz = u->nnz; - } - if(fmpz_sgn(lv->val) < 0) /* Pre-apply transform [[-1, 0], [0, -1]] */ - { - fmpz_sparse_vec_neg(v, v); - fmpz_sparse_vec_neg(u, u); - } - flint_printf("pr[pc] = "), fmpz_print(lv->val), flint_printf("\n"); - flint_printf("r[pc] = "), fmpz_print(lu->val), flint_printf("\n"); - - /* Check for trivial cases */ - if (fmpz_divisible(lu->val, lv->val)) {fmpz_sparse_vec_gauss_elim(u, v); return;} - - fmpz_init(g); - fmpz_init(vv); - fmpz_init(vu); - fmpz_init(uv); - fmpz_init(uu); - fmpz_init(a); - fmpz_init(b); - - /* Construct transformation */ - fmpz_xgcd(g, vv, vu, lv->val, lu->val); - if (fmpz_sgn(g) < 0) - { - fmpz_neg(vv, vv); - fmpz_neg(vu, vu); - } - fmpz_divexact(uu, lv->val, g); - fmpz_divexact(uv, lu->val, g); - fmpz_neg(uv, uv); /* [[uu uv] [vu vv]] is unimodular */ - fmpz_set(g, uv); - flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); - flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); - flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); - - /* Reallocate vectors */ - nnz = _fmpz_sparse_vec_union_nnz (u, v); - _fmpz_sparse_vec_resize(u, nnz); - _fmpz_sparse_vec_resize(v, nnz); - ue = u->entries + unnz, ve = v->entries + vnnz; /* Old locations */ - nue = u->entries + nnz, nve = v->entries + nnz; /* New locations */ - while ((k = _fmpz_sparse_vector_merge_descend (&nue, &ue, &ve, u, v)) >= 0) - { - nve--; - flint_printf("%wd, %wd, %wd\n", nnz, nue - u->entries, nve-v->entries); - flint_printf("\t\tU: [[%wd, %wd], [%wd, %wd]]\n", uu[0], g[0], vu[0], vv[0]); - flint_printf("\t\tU: [["), fmpz_print(uu), flint_printf(", "), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); - flint_printf("], ["), fmpz_print(vu), flint_printf(", "), fmpz_print(vv), flint_printf("]]\n"); - flint_printf("u = "), fmpz_sparse_vec_print_pretty(u, 0, 0); - flint_printf("v = "), fmpz_sparse_vec_print_pretty(v, 0, 0); - switch(k) - { - case 0: nve->ind = ue->ind; fmpz_mul(nve->val, ue->val, vu); fmpz_mul(nue->val, ue->val, uu); break; - case 1: nve->ind = ve->ind; fmpz_mul(nue->val, ve->val, g); fmpz_mul(nve->val, ve->val, vv); break; - default: nve->ind = ve->ind; - flint_printf("\t\tcur: [[%wd, %wd], [%wd, %wd]]\n", nue->val[0], nve->val[0], ue->val[0], ve->val[0]); - flint_printf("\t\tcur: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); - flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); - - fmpz_set(a, ve->val); - fmpz_set(b, ue->val); - fmpz_mul(nve->val, a, vv); fmpz_addmul(nve->val, b, vu); - fmpz_mul(nue->val, b, uu); fmpz_addmul(nue->val, a, uv); - flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(vu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(vv); flint_printf("\n"); - flint_printf("\t\tComputed "), fmpz_print(b), flint_printf("*"), fmpz_print(uu), flint_printf("+"), fmpz_print(a), flint_printf("*"), fmpz_print(g); flint_printf(" == "), fmpz_print(uv); flint_printf("\n"); - flint_printf("\t\tafter: [[%wd:", nue->ind), fmpz_print(nue->val), flint_printf(", %wd:", nve->ind), fmpz_print(nve->val); - flint_printf("], [%wd:", ue->ind), fmpz_print(ue->val), flint_printf(", %wd:", ve->ind), fmpz_print(ve->val), flint_printf("]]\n"); - } - if (fmpz_is_zero(nue->val)) nue++; - if (fmpz_is_zero(nve->val)) nve++; - } - _fmpz_sparse_vector_shift_left (u, nue - u->entries); - _fmpz_sparse_vector_shift_left (v, nve - v->entries); - fmpz_clear(g); - fmpz_clear(vv); - fmpz_clear(vu); - fmpz_clear(uv); - fmpz_clear(uu); - fmpz_clear(a); - fmpz_clear(b); -} diff --git a/fq_sparse_mat_templates/tmp b/fq_sparse_mat_templates/tmp deleted file mode 100644 index f16d89d6ca..0000000000 --- a/fq_sparse_mat_templates/tmp +++ /dev/null @@ -1,31 +0,0 @@ - int ret = 0; - slong l; - - std::vector combi(block_size,Vector(F,d[l]+1)); - for (size_t i=0;i 0;--i) { - lhs = lhs2 + combi[0][i]*y; - lhs2 = A^t*lhs; - } - Vector accu (lhs); - _TEMPLATE(T, vec_zero) (x, A->r, ctx); - for (size_t k=1;k= 0;--i) { - lhs = lhs2 + combi[k][i]*row; - lhs2 = A^t * lhs - } - _TEMPLATE(T, vec_add) (x, x, lhs, A->r, ctx); - } - TEMPLATE(T, neg) (cc, nmod_inv(S[0].rows[l][0], ctx), ctx); - _TEMPLATE(T, vec_scalar_mul) (x, x, A->r, cc, ctx); - return ret; diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index c97844858b..274f129e20 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -239,8 +239,9 @@ NMOD_SPARSE_VEC_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; - for (i = 0; i < M->r; ++i) { - if(!M->rows[i].nnz) continue; + for (i = 0; i < M->r; ++i) + { + if (!M->rows[i].nnz) continue; nmod_sparse_vec_permute_inds(&M->rows[i], Q); qsort(M->rows[i].entries, M->rows[i].nnz, sizeof(*M->rows[i].entries), nmod_sparse_entry_cmp); } diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 2c264e7368..0b08e35543 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -102,23 +102,3 @@ int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flin _nmod_vec_clear(b); return ret; } - -int nmod_sparse_mat_nullvector_lanczos(mp_ptr x, const nmod_sparse_mat_t M, flint_rand_t state) { - int ret = 1; - mp_ptr x2, b; - x2 = _nmod_vec_init(M->c); - b = _nmod_vec_init(M->r); - - _nmod_vec_randtest(x, state, M->c, M->mod); - nmod_sparse_mat_mul_vec(b, M, x); - if(nmod_sparse_mat_solve_lanczos(x2, M, b, state) == 0) ret = 0; /* Lanczos failed */ - if (ret) - { - _nmod_vec_sub(x, x, x2, M->c, M->mod); - nmod_sparse_mat_mul_vec(b, M, x); - ret = !_nmod_vec_is_zero(x, M->c) && _nmod_vec_is_zero(b, M->r); - } - _nmod_vec_clear(x2); - _nmod_vec_clear(b); - return ret; -} diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index c63b739ad6..9c87f2b960 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -41,7 +41,7 @@ main(void) for (rep = 0; rep < nreps; rep++) { - if(rep % 5==0) {flint_printf("."); fflush(stdout);} + if (rep % 5==0) {flint_printf("."); fflush(stdout);} c = r = 100 + n_randint(state, 50); do n = n_randtest_not_zero(state); @@ -67,10 +67,10 @@ main(void) { case 0: ret = nmod_sparse_mat_solve_rref(x2, A, b); break; case 1: ret = nmod_sparse_mat_solve_lu(x2, A, b); break; - case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while(ret == 0 && ++iter < 30); break; - case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while(ret == 0 && ++iter < 30); break; + case 2: do ret = nmod_sparse_mat_solve_lanczos(x2, A, b, state); while (ret == 0 && ++iter < 30); break; + case 3: do ret = nmod_sparse_mat_solve_block_lanczos(x2, A, b, 8, state); while (ret == 0 && ++iter < 30); break; case 4: ret = nmod_sparse_mat_solve_wiedemann(x2, A, b); break; - case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while(ret == 0 && ++iter < 3); break; + case 5: do ret = nmod_sparse_mat_solve_block_wiedemann(x2, A, b, 4, state); while (ret == 0 && ++iter < 3); break; } /*gettimeofday(&end, NULL); elapsed[i] += (end.tv_sec - start.tv_sec) + .000001*(end.tv_usec-start.tv_usec);*/ From 8c6b44a6e57aa3c8374b440f1aeaa1d2d3911c12 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 24 May 2021 10:28:58 -0700 Subject: [PATCH 40/42] Added copyrights, resizing, and some asserts --- fmpz_sparse_mat.h | 49 +++++++++++++++++- fmpz_sparse_mat/CRT_ui.c | 1 + fmpz_sparse_mat/content.c | 1 + fmpz_sparse_mat/det.c | 8 +-- fmpz_sparse_mat/det_bareiss.c | 3 +- fmpz_sparse_mat/det_bound.c | 2 + fmpz_sparse_mat/det_cofactor.c | 2 + fmpz_sparse_mat/det_divisor.c | 3 +- fmpz_sparse_mat/det_modular.c | 2 + fmpz_sparse_mat/det_modular_accelerated.c | 2 + fmpz_sparse_mat/det_modular_given_divisor.c | 2 + fmpz_sparse_mat/fflu.c | 1 + fmpz_sparse_mat/from_entries.c | 1 + fmpz_sparse_mat/gram.c | 1 + fmpz_sparse_mat/hnf_classical.c | 1 + fmpz_sparse_mat/hnf_minors.c | 1 + fmpz_sparse_mat/hnf_modular.c | 1 + fmpz_sparse_mat/hnf_modular_eldiv.c | 1 + fmpz_sparse_mat/hnf_pernet_stein.c | 1 + fmpz_sparse_mat/hnf_xgcd.c | 1 + fmpz_sparse_mat/howell_form_mod.c | 1 + fmpz_sparse_mat/is_in_hnf.c | 1 + fmpz_sparse_mat/max_bits.c | 1 + fmpz_sparse_mat/multi_CRT_ui.c | 5 ++ fmpz_sparse_mat/multi_mod_ui.c | 4 ++ fmpz_sparse_mat/print_pretty.c | 1 + fmpz_sparse_mat/randtest.c | 1 + fmpz_sparse_mat/randtest_unsigned.c | 1 + fmpz_sparse_mat/snf.c | 1 + fmpz_sparse_mat/snf_diagonal.c | 1 + fmpz_sparse_mat/snf_iliopoulos.c | 1 + fmpz_sparse_mat/snf_kannan_bachem.c | 1 + fmpz_sparse_mat/solve_bound.c | 1 + fmpz_sparse_mat/solve_dixon.c | 1 + fmpz_sparse_mat/strong_echelon_form_mod.c | 1 + fmpz_sparse_mat/test/t-CRT_ui.c | 1 + fmpz_sparse_mat/test/t-CRT_ui_unsigned.c | 1 + fmpz_sparse_mat/test/t-add.c | 1 + fmpz_sparse_mat/test/t-concat_horizontal.c | 1 + fmpz_sparse_mat/test/t-concat_vertical.c | 1 + fmpz_sparse_mat/test/t-construct.c | 1 + fmpz_sparse_mat/test/t-content.c | 1 + fmpz_sparse_mat/test/t-dense.c | 1 + fmpz_sparse_mat/test/t-det.c | 1 + fmpz_sparse_mat/test/t-det_bareiss.c | 1 + fmpz_sparse_mat/test/t-det_bound.c | 1 + fmpz_sparse_mat/test/t-det_divisor.c | 1 + fmpz_sparse_mat/test/t-det_modular.c | 1 + .../test/t-det_modular_accelerated.c | 1 + fmpz_sparse_mat/test/t-fflu.c | 1 + fmpz_sparse_mat/test/t-hnf_classical.c | 1 + fmpz_sparse_mat/test/t-hnf_minors.c | 1 + fmpz_sparse_mat/test/t-hnf_modular.c | 1 + fmpz_sparse_mat/test/t-hnf_modular_eldiv.c | 1 + fmpz_sparse_mat/test/t-hnf_xgcd.c | 1 + fmpz_sparse_mat/test/t-howell_form_mod.c | 1 + fmpz_sparse_mat/test/t-init_clear.c | 1 + fmpz_sparse_mat/test/t-mul.c | 1 + fmpz_sparse_mat/test/t-multi_CRT_ui.c | 1 + .../test/t-multi_CRT_ui_unsigned.c | 1 + fmpz_sparse_mat/test/t-neg.c | 1 + fmpz_sparse_mat/test/t-scalar_mul.c | 1 + fmpz_sparse_mat/test/t-solve_dixon.c | 1 + fmpz_sparse_mat/test/t-solve_dixon_den.c | 1 + fmpz_sparse_mat/test/t-transpose.c | 1 + fmpz_sparse_mat/transpose.c | 3 ++ fmpz_sparse_mat/with_transpose_fix_support.c | 1 + fmpz_sparse_mat/with_transpose_init.c | 1 + fmpz_sparse_vec.h | 18 +++++++ fmpz_sparse_vec/CRT_ui.c | 1 + fmpz_sparse_vec/add.c | 1 + fmpz_sparse_vec/at.c | 1 + fmpz_sparse_vec/concat.c | 1 + fmpz_sparse_vec/dot.c | 1 + fmpz_sparse_vec/dot_dense.c | 1 + fmpz_sparse_vec/equal.c | 1 + fmpz_sparse_vec/from_dense.c | 1 + fmpz_sparse_vec/from_entries.c | 1 + fmpz_sparse_vec/gauss_elim.c | 4 +- fmpz_sparse_vec/max_bits.c | 1 + fmpz_sparse_vec/multi_CRT_ui.c | 15 +++--- fmpz_sparse_vec/multi_mod_ui.c | 1 + fmpz_sparse_vec/print_pretty.c | 1 + fmpz_sparse_vec/randtest.c | 1 + fmpz_sparse_vec/randtest_unsigned.c | 1 + fmpz_sparse_vec/scalar_addmul.c | 1 + fmpz_sparse_vec/scalar_divexact.c | 1 + fmpz_sparse_vec/scalar_mod.c | 1 + fmpz_sparse_vec/scalar_mods.c | 1 + fmpz_sparse_vec/scalar_mul.c | 1 + fmpz_sparse_vec/scalar_submul.c | 1 + fmpz_sparse_vec/set.c | 1 + fmpz_sparse_vec/split.c | 1 + fmpz_sparse_vec/sub.c | 1 + fmpz_sparse_vec/test/t-add.c | 1 + fmpz_sparse_vec/test/t-concat.c | 1 + fmpz_sparse_vec/test/t-construct.c | 1 + fmpz_sparse_vec/test/t-dense.c | 1 + fmpz_sparse_vec/test/t-dot.c | 1 + fmpz_sparse_vec/test/t-gauss_elim.c | 3 +- fmpz_sparse_vec/test/t-init_clear.c | 1 + fmpz_sparse_vec/test/t-max_bits.c | 1 + fmpz_sparse_vec/test/t-neg.c | 1 + fmpz_sparse_vec/test/t-nmod.c | 1 + fmpz_sparse_vec/test/t-scalar_divexact.c | 3 +- fmpz_sparse_vec/test/t-scalar_mod.c | 1 + fmpz_sparse_vec/test/t-scalar_mul.c | 3 +- fq_nmod_sparse_mat.h | 1 + fq_nmod_sparse_vec.h | 1 + fq_sparse_mat.h | 1 + fq_sparse_mat/from_entries.c | 1 + fq_sparse_mat/inv.c | 1 + fq_sparse_mat/lu.c | 1 + fq_sparse_mat/nullspace_block_lanczos.c | 1 + fq_sparse_mat/nullspace_block_wiedemann.c | 1 + fq_sparse_mat/nullspace_lanczos.c | 1 + fq_sparse_mat/nullspace_lu.c | 1 + fq_sparse_mat/nullspace_rref.c | 1 + fq_sparse_mat/nullspace_wiedemann.c | 1 + fq_sparse_mat/print_pretty.c | 1 + fq_sparse_mat/randtest.c | 1 + fq_sparse_mat/rref.c | 1 + fq_sparse_mat/solve_block_lanczos.c | 3 +- fq_sparse_mat/solve_block_wiedemann.c | 1 + fq_sparse_mat/solve_lanczos.c | 1 + fq_sparse_mat/solve_lu.c | 1 + fq_sparse_mat/solve_rref.c | 1 + fq_sparse_mat/solve_wiedemann.c | 1 + fq_sparse_mat/test/t-add.c | 1 + fq_sparse_mat/test/t-concat_horizontal.c | 1 + fq_sparse_mat/test/t-concat_vertical.c | 1 + fq_sparse_mat/test/t-construct.c | 1 + fq_sparse_mat/test/t-dense.c | 1 + fq_sparse_mat/test/t-init_clear.c | 1 + fq_sparse_mat/test/t-inv.c | 1 + fq_sparse_mat/test/t-lu.c | 1 + fq_sparse_mat/test/t-mul.c | 1 + fq_sparse_mat/test/t-neg.c | 1 + fq_sparse_mat/test/t-nullspace.c | 1 + fq_sparse_mat/test/t-rref.c | 1 + fq_sparse_mat/test/t-scalar_mul.c | 1 + fq_sparse_mat/test/t-solve.c | 1 + fq_sparse_mat/test/t-transpose.c | 1 + fq_sparse_mat/transpose.c | 1 + fq_sparse_mat_templates.h | 44 ++++++++++++++++ fq_sparse_mat_templates/from_entries.c | 1 + fq_sparse_mat_templates/inv.c | 1 + fq_sparse_mat_templates/lu.c | 1 + .../nullspace_block_lanczos.c | 1 + .../nullspace_block_wiedemann.c | 1 + fq_sparse_mat_templates/nullspace_lanczos.c | 1 + fq_sparse_mat_templates/nullspace_lu.c | 1 + fq_sparse_mat_templates/nullspace_rref.c | 1 + fq_sparse_mat_templates/nullspace_wiedemann.c | 1 + fq_sparse_mat_templates/print_pretty.c | 1 + fq_sparse_mat_templates/randtest.c | 1 + fq_sparse_mat_templates/rref.c | 1 + fq_sparse_mat_templates/solve_block_lanczos.c | 3 +- .../solve_block_wiedemann.c | 1 + fq_sparse_mat_templates/solve_lanczos.c | 1 + fq_sparse_mat_templates/solve_lu.c | 1 + fq_sparse_mat_templates/solve_rref.c | 1 + fq_sparse_mat_templates/solve_wiedemann.c | 1 + fq_sparse_mat_templates/test/t-add.c | 1 + .../test/t-concat_horizontal.c | 1 + .../test/t-concat_vertical.c | 1 + fq_sparse_mat_templates/test/t-construct.c | 1 + fq_sparse_mat_templates/test/t-dense.c | 1 + fq_sparse_mat_templates/test/t-init_clear.c | 1 + fq_sparse_mat_templates/test/t-inv.c | 1 + fq_sparse_mat_templates/test/t-lu.c | 1 + fq_sparse_mat_templates/test/t-mul.c | 1 + fq_sparse_mat_templates/test/t-neg.c | 1 + fq_sparse_mat_templates/test/t-nullspace.c | 1 + fq_sparse_mat_templates/test/t-rref.c | 1 + fq_sparse_mat_templates/test/t-scalar_mul.c | 1 + fq_sparse_mat_templates/test/t-solve.c | 1 + fq_sparse_mat_templates/test/t-transpose.c | 1 + fq_sparse_mat_templates/transpose.c | 2 + fq_sparse_vec.h | 1 + fq_sparse_vec/add.c | 1 + fq_sparse_vec/print_pretty.c | 1 + fq_sparse_vec/randtest.c | 1 + fq_sparse_vec/scalar_addmul.c | 1 + fq_sparse_vec/scalar_submul.c | 1 + fq_sparse_vec/sub.c | 1 + fq_sparse_vec/test/t-add.c | 1 + fq_sparse_vec/test/t-concat.c | 1 + fq_sparse_vec/test/t-construct.c | 1 + fq_sparse_vec/test/t-dense.c | 1 + fq_sparse_vec/test/t-dot.c | 1 + fq_sparse_vec/test/t-init_clear.c | 1 + fq_sparse_vec/test/t-neg.c | 1 + fq_sparse_vec/test/t-scalar_mul.c | 1 + fq_sparse_vec_templates.h | 18 +++++++ fq_sparse_vec_templates/add.c | 1 + fq_sparse_vec_templates/print_pretty.c | 1 + fq_sparse_vec_templates/randtest.c | 1 + fq_sparse_vec_templates/scalar_addmul.c | 1 + fq_sparse_vec_templates/scalar_submul.c | 1 + fq_sparse_vec_templates/sub.c | 1 + fq_sparse_vec_templates/test/t-add.c | 1 + fq_sparse_vec_templates/test/t-concat.c | 1 + fq_sparse_vec_templates/test/t-construct.c | 1 + fq_sparse_vec_templates/test/t-dense.c | 1 + fq_sparse_vec_templates/test/t-dot.c | 1 + fq_sparse_vec_templates/test/t-init_clear.c | 1 + fq_sparse_vec_templates/test/t-neg.c | 1 + fq_sparse_vec_templates/test/t-scalar_mul.c | 3 +- fq_zech_sparse_mat.h | 1 + fq_zech_sparse_mat/from_entries.c | 1 + fq_zech_sparse_mat/inv.c | 1 + fq_zech_sparse_mat/lu.c | 1 + fq_zech_sparse_mat/nullspace_block_lanczos.c | 1 + .../nullspace_block_wiedemann.c | 1 + fq_zech_sparse_mat/nullspace_lanczos.c | 1 + fq_zech_sparse_mat/nullspace_lu.c | 1 + fq_zech_sparse_mat/nullspace_rref.c | 1 + fq_zech_sparse_mat/nullspace_wiedemann.c | 1 + fq_zech_sparse_mat/print_pretty.c | 1 + fq_zech_sparse_mat/randtest.c | 1 + fq_zech_sparse_mat/rref.c | 1 + fq_zech_sparse_mat/solve_block_lanczos.c | 3 +- fq_zech_sparse_mat/solve_block_wiedemann.c | 1 + fq_zech_sparse_mat/solve_lanczos.c | 1 + fq_zech_sparse_mat/solve_lu.c | 1 + fq_zech_sparse_mat/solve_rref.c | 1 + fq_zech_sparse_mat/solve_wiedemann.c | 1 + fq_zech_sparse_mat/test/t-add.c | 1 + fq_zech_sparse_mat/test/t-concat_horizontal.c | 1 + fq_zech_sparse_mat/test/t-concat_vertical.c | 1 + fq_zech_sparse_mat/test/t-construct.c | 1 + fq_zech_sparse_mat/test/t-dense.c | 1 + fq_zech_sparse_mat/test/t-init_clear.c | 1 + fq_zech_sparse_mat/test/t-inv.c | 1 + fq_zech_sparse_mat/test/t-lu.c | 1 + fq_zech_sparse_mat/test/t-mul.c | 1 + fq_zech_sparse_mat/test/t-neg.c | 1 + fq_zech_sparse_mat/test/t-nullspace.c | 1 + fq_zech_sparse_mat/test/t-rref.c | 1 + fq_zech_sparse_mat/test/t-scalar_mul.c | 1 + fq_zech_sparse_mat/test/t-solve.c | 1 + fq_zech_sparse_mat/test/t-transpose.c | 1 + fq_zech_sparse_mat/transpose.c | 1 + fq_zech_sparse_vec.h | 1 + fq_zech_sparse_vec/add.c | 1 + fq_zech_sparse_vec/print_pretty.c | 1 + fq_zech_sparse_vec/randtest.c | 1 + fq_zech_sparse_vec/scalar_addmul.c | 1 + fq_zech_sparse_vec/scalar_submul.c | 1 + fq_zech_sparse_vec/sub.c | 1 + fq_zech_sparse_vec/test/t-add.c | 1 + fq_zech_sparse_vec/test/t-concat.c | 1 + fq_zech_sparse_vec/test/t-construct.c | 1 + fq_zech_sparse_vec/test/t-dense.c | 1 + fq_zech_sparse_vec/test/t-dot.c | 1 + fq_zech_sparse_vec/test/t-init_clear.c | 1 + fq_zech_sparse_vec/test/t-neg.c | 1 + fq_zech_sparse_vec/test/t-scalar_mul.c | 3 +- nmod_sparse_mat.h | 50 +++++++++++++++---- nmod_sparse_mat/det.c | 7 +-- nmod_sparse_mat/from_entries.c | 1 + nmod_sparse_mat/howell_form.c | 1 + nmod_sparse_mat/inv.c | 1 + nmod_sparse_mat/lu.c | 1 + nmod_sparse_mat/nullspace_block_lanczos.c | 1 + nmod_sparse_mat/nullspace_block_wiedemann.c | 1 + nmod_sparse_mat/nullspace_lanczos.c | 1 + nmod_sparse_mat/nullspace_lu.c | 1 + nmod_sparse_mat/nullspace_rref.c | 1 + nmod_sparse_mat/nullspace_wiedemann.c | 1 + nmod_sparse_mat/print_pretty.c | 1 + nmod_sparse_mat/randtest.c | 1 + nmod_sparse_mat/rref.c | 1 + nmod_sparse_mat/solve_block_lanczos.c | 3 +- nmod_sparse_mat/solve_block_wiedemann.c | 1 + nmod_sparse_mat/solve_lanczos.c | 1 + nmod_sparse_mat/solve_lu.c | 1 + nmod_sparse_mat/solve_rref.c | 1 + nmod_sparse_mat/solve_wiedemann.c | 1 + nmod_sparse_mat/strong_echelon_form.c | 1 + nmod_sparse_mat/test/t-add.c | 1 + nmod_sparse_mat/test/t-concat_horizontal.c | 1 + nmod_sparse_mat/test/t-concat_vertical.c | 1 + nmod_sparse_mat/test/t-construct.c | 1 + nmod_sparse_mat/test/t-dense.c | 1 + nmod_sparse_mat/test/t-init_clear.c | 5 +- nmod_sparse_mat/test/t-inv.c | 1 + nmod_sparse_mat/test/t-lu.c | 1 + nmod_sparse_mat/test/t-mul.c | 1 + nmod_sparse_mat/test/t-neg.c | 1 + nmod_sparse_mat/test/t-nullspace.c | 1 + nmod_sparse_mat/test/t-rref.c | 1 + nmod_sparse_mat/test/t-scalar_mul.c | 1 + nmod_sparse_mat/test/t-solve.c | 1 + nmod_sparse_mat/test/t-transpose.c | 1 + nmod_sparse_mat/transpose.c | 3 ++ nmod_sparse_vec.h | 30 +++++++++++ nmod_sparse_vec/add.c | 1 + nmod_sparse_vec/at.c | 1 + nmod_sparse_vec/concat.c | 1 + nmod_sparse_vec/dot.c | 1 + nmod_sparse_vec/dot_dense.c | 1 + nmod_sparse_vec/equal.c | 1 + nmod_sparse_vec/from_dense.c | 1 + nmod_sparse_vec/from_entries.c | 1 + nmod_sparse_vec/print_pretty.c | 1 + nmod_sparse_vec/randtest.c | 1 + nmod_sparse_vec/scalar_addmul.c | 1 + nmod_sparse_vec/scalar_mul.c | 1 + nmod_sparse_vec/scalar_submul.c | 1 + nmod_sparse_vec/set.c | 1 + nmod_sparse_vec/split.c | 1 + nmod_sparse_vec/sub.c | 1 + nmod_sparse_vec/test/t-add.c | 1 + nmod_sparse_vec/test/t-concat.c | 1 + nmod_sparse_vec/test/t-construct.c | 1 + nmod_sparse_vec/test/t-dense.c | 1 + nmod_sparse_vec/test/t-dot.c | 1 + nmod_sparse_vec/test/t-init_clear.c | 1 + nmod_sparse_vec/test/t-neg.c | 1 + nmod_sparse_vec/test/t-scalar_mul.c | 1 + nmod_sparse_vec/window_init.c | 1 + 323 files changed, 551 insertions(+), 48 deletions(-) diff --git a/fmpz_sparse_mat.h b/fmpz_sparse_mat.h index f7393d4bb5..965d324bb2 100644 --- a/fmpz_sparse_mat.h +++ b/fmpz_sparse_mat.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -67,6 +68,7 @@ typedef fmpz_sparse_mat_with_transpose_struct fmpz_sparse_mat_with_transpose_t[1 FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_init (fmpz_sparse_mat_t M, slong rows, slong cols) { + FLINT_ASSERT(rows >= 0 && cols >= 0); M->rows = flint_calloc(rows, sizeof(*M->rows)); M->r = rows; M->c = cols; @@ -77,10 +79,44 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_clear (fmpz_sparse_mat_t M) { slong i; - for (i = 0; i < M->r; ++i) fmpz_sparse_vec_clear(&M->rows[i]); + for (i = 0; i < M->r; ++i) + { + fmpz_sparse_vec_clear(&M->rows[i]); + } flint_free(M->rows); memset(M, 0, sizeof(*M)); } + +FMPZ_SPARSE_MAT_INLINE +void fmpz_sparse_mat_resize (fmpz_sparse_mat_t M, slong rows, slong cols) +{ + slong i; + FLINT_ASSERT(rows >= 0 && cols >= 0); + if (M->r != rows) { + if (M->r > rows) + { + for (i = rows; i < M->r; ++i) + { + fmpz_sparse_vec_clear(&M->rows[i]); + } + } + M->rows = flint_realloc(M->rows, rows*sizeof(*M->rows)); + if (M->r < rows) + { + memset(M->rows+M->r, 0, (rows-M->r)*sizeof(*M->rows)); + } + M->r = rows; + } + if (cols < M->c) + { + for (i = 0; i < M->r; ++i) + { + fmpz_sparse_vec_resize(&M->rows[i], cols); + } + } + M->c = cols; +} + FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_swap (fmpz_sparse_mat_t M1, fmpz_sparse_mat_t M2) { @@ -315,6 +351,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_neg (fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_neg(&N->rows[i], &M->rows[i]); } @@ -322,6 +359,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_mul_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t c) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mul_fmpz(&N->rows[i], &M->rows[i], c); } @@ -329,6 +367,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_mul_diag_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, fmpz * D) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mul_fmpz(&N->rows[i], &M->rows[i], &D[i]); } @@ -337,6 +376,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_divexact_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t c) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_divexact_fmpz(&N->rows[i], &M->rows[i], c); } @@ -345,6 +385,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_mod_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t mod) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mod_fmpz(&N->rows[i], &M->rows[i], mod); } @@ -352,6 +393,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_mods_fmpz(fmpz_sparse_mat_t N, const fmpz_sparse_mat_t M, const fmpz_t mod) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) fmpz_sparse_vec_scalar_mods_fmpz(&N->rows[i], &M->rows[i], mod); } @@ -360,6 +402,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_add (fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) fmpz_sparse_vec_add(&O->rows[i], &M->rows[i], &N->rows[i]); } @@ -367,6 +410,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_sub (fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) fmpz_sparse_vec_sub(&O->rows[i], &M->rows[i], &N->rows[i]); } @@ -374,6 +418,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_addmul_fmpz(fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N, const fmpz_t c) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) fmpz_sparse_vec_scalar_addmul_fmpz(&O->rows[i], &M->rows[i], &N->rows[i], c); } @@ -381,6 +426,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_scalar_submul_fmpz(fmpz_sparse_mat_t O, const fmpz_sparse_mat_t M, const fmpz_sparse_mat_t N, const fmpz_t c) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) fmpz_sparse_vec_scalar_submul_fmpz(&O->rows[i], &M->rows[i], &N->rows[i], c); } @@ -396,6 +442,7 @@ FMPZ_SPARSE_MAT_INLINE void fmpz_sparse_mat_mul_mat (fmpz_mat_t Y, const fmpz_sparse_mat_t M, const fmpz_mat_t X) { slong i, j; + FLINT_ASSERT(M->r == Y->r && M->c == X->r && X->c == Y->c); fmpz_mat_zero (Y); for (i = 0; i < M->r; ++i) { diff --git a/fmpz_sparse_mat/CRT_ui.c b/fmpz_sparse_mat/CRT_ui.c index 7e215b13b1..577b456dff 100644 --- a/fmpz_sparse_mat/CRT_ui.c +++ b/fmpz_sparse_mat/CRT_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/content.c b/fmpz_sparse_mat/content.c index 9fc8b73c12..f9a7d44b34 100644 --- a/fmpz_sparse_mat/content.c +++ b/fmpz_sparse_mat/content.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Dharak Kharod + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/det.c b/fmpz_sparse_mat/det.c index 9859cd7d4d..1bcad6cab3 100644 --- a/fmpz_sparse_mat/det.c +++ b/fmpz_sparse_mat/det.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -15,12 +16,7 @@ void fmpz_sparse_mat_det(fmpz_t det, const fmpz_sparse_mat_t A) { slong dim = A->r; - - if (dim != A->c) - { - flint_printf("Exception (fmpz_mat_det). Non-square matrix.\n"); - flint_abort(); - } + FLINT_ASSERT(A->r == A->c); if (dim < 5) fmpz_sparse_mat_det_cofactor(det, A); diff --git a/fmpz_sparse_mat/det_bareiss.c b/fmpz_sparse_mat/det_bareiss.c index 4414747a62..3d9ea39291 100644 --- a/fmpz_sparse_mat/det_bareiss.c +++ b/fmpz_sparse_mat/det_bareiss.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010,2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -18,7 +19,7 @@ fmpz_sparse_mat_det_bareiss(fmpz_t det, const fmpz_sparse_mat_t M) slong i, rk, *P, *Q; fmpz *D; fmpz_sparse_mat_t L, U; - if (M->r != M->c) {fmpz_zero(det); return;} + FLINT_ASSERT(M->r == M->c); fmpz_one(det); if (M->r == UWORD(0)) return; diff --git a/fmpz_sparse_mat/det_bound.c b/fmpz_sparse_mat/det_bound.c index fc1e25f858..b14f1ce389 100644 --- a/fmpz_sparse_mat/det_bound.c +++ b/fmpz_sparse_mat/det_bound.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -16,6 +17,7 @@ fmpz_sparse_mat_det_bound(fmpz_t bound, const fmpz_sparse_mat_t A) { fmpz_t s, t; slong i, j; + FLINT_ASSERT(A->r == A->c); fmpz_init(s); fmpz_init(t); diff --git a/fmpz_sparse_mat/det_cofactor.c b/fmpz_sparse_mat/det_cofactor.c index ed13e145bd..eccb5bbe3d 100644 --- a/fmpz_sparse_mat/det_cofactor.c +++ b/fmpz_sparse_mat/det_cofactor.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010,2011,2018 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under @@ -14,6 +15,7 @@ void fmpz_sparse_mat_det_cofactor(fmpz_t det, const fmpz_sparse_mat_t M) { fmpz_mat_t dM; + FLINT_ASSERT(M->r == M->c); if (M->r != M->c) {fmpz_zero(det); return;} if (M->r > 4) { diff --git a/fmpz_sparse_mat/det_divisor.c b/fmpz_sparse_mat/det_divisor.c index fcb69daef7..bb8d8a64b9 100644 --- a/fmpz_sparse_mat/det_divisor.c +++ b/fmpz_sparse_mat/det_divisor.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -19,7 +20,7 @@ fmpz_sparse_mat_det_divisor(fmpz_t d, const fmpz_sparse_mat_t M) slong i; fmpz_mat_t X, B; fmpz_t t, u, v, mod; - if (M->r != M->c) {fmpz_zero(d); return;} + FLINT_ASSERT(M->r == M->c); fmpz_mat_init(X, M->c, 1); fmpz_mat_init(B, M->r, 1); diff --git a/fmpz_sparse_mat/det_modular.c b/fmpz_sparse_mat/det_modular.c index 33ef2234f1..a56b1e1e5a 100644 --- a/fmpz_sparse_mat/det_modular.c +++ b/fmpz_sparse_mat/det_modular.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -15,6 +16,7 @@ void fmpz_sparse_mat_det_modular(fmpz_t det, const fmpz_sparse_mat_t A, int proved) { fmpz_t d; + FLINT_ASSERT(A->r == A->c); fmpz_init(d); fmpz_one(d); fmpz_sparse_mat_det_modular_given_divisor(det, A, d, proved); diff --git a/fmpz_sparse_mat/det_modular_accelerated.c b/fmpz_sparse_mat/det_modular_accelerated.c index 2a6f5b469b..ad39bd9b33 100644 --- a/fmpz_sparse_mat/det_modular_accelerated.c +++ b/fmpz_sparse_mat/det_modular_accelerated.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -15,6 +16,7 @@ void fmpz_sparse_mat_det_modular_accelerated(fmpz_t det, const fmpz_sparse_mat_t A, int proved) { fmpz_t d; + FLINT_ASSERT(A->r == A->c); fmpz_init(d); fmpz_sparse_mat_det_divisor(d, A); fmpz_sparse_mat_det_modular_given_divisor(det, A, d, proved); diff --git a/fmpz_sparse_mat/det_modular_given_divisor.c b/fmpz_sparse_mat/det_modular_given_divisor.c index ad51245795..bbb678f93e 100644 --- a/fmpz_sparse_mat/det_modular_given_divisor.c +++ b/fmpz_sparse_mat/det_modular_given_divisor.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -40,6 +41,7 @@ fmpz_sparse_mat_det_modular_given_divisor(fmpz_t det, const fmpz_sparse_mat_t A, nmod_t mod; nmod_sparse_mat_t Amod; slong n = A->r; + FLINT_ASSERT(A->r == A->c); if (A->r == 0) {fmpz_one(det); return;} if (fmpz_is_zero(d)) {fmpz_zero(det); return;} diff --git a/fmpz_sparse_mat/fflu.c b/fmpz_sparse_mat/fflu.c index fe7ed77d71..5038505bb6 100644 --- a/fmpz_sparse_mat/fflu.c +++ b/fmpz_sparse_mat/fflu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/from_entries.c b/fmpz_sparse_mat/from_entries.c index b1c3f3cb99..d31194a885 100644 --- a/fmpz_sparse_mat/from_entries.c +++ b/fmpz_sparse_mat/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/gram.c b/fmpz_sparse_mat/gram.c index 374f70b2fc..2cbb39531a 100644 --- a/fmpz_sparse_mat/gram.c +++ b/fmpz_sparse_mat/gram.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Abhinav Baid + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_classical.c b/fmpz_sparse_mat/hnf_classical.c index cc4fecf08b..d8acb15b07 100644 --- a/fmpz_sparse_mat/hnf_classical.c +++ b/fmpz_sparse_mat/hnf_classical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_minors.c b/fmpz_sparse_mat/hnf_minors.c index b12c25f686..cec18c70a8 100644 --- a/fmpz_sparse_mat/hnf_minors.c +++ b/fmpz_sparse_mat/hnf_minors.c @@ -1,6 +1,7 @@ /* Copyright (C) 2014 Alex J. Best Copyright (C) 2017 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_modular.c b/fmpz_sparse_mat/hnf_modular.c index bb10c1f580..c35acce450 100644 --- a/fmpz_sparse_mat/hnf_modular.c +++ b/fmpz_sparse_mat/hnf_modular.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_modular_eldiv.c b/fmpz_sparse_mat/hnf_modular_eldiv.c index 94b03bf2c0..2a5e334672 100644 --- a/fmpz_sparse_mat/hnf_modular_eldiv.c +++ b/fmpz_sparse_mat/hnf_modular_eldiv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_pernet_stein.c b/fmpz_sparse_mat/hnf_pernet_stein.c index c97eb6d522..836052ac81 100644 --- a/fmpz_sparse_mat/hnf_pernet_stein.c +++ b/fmpz_sparse_mat/hnf_pernet_stein.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014, 2015 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/hnf_xgcd.c b/fmpz_sparse_mat/hnf_xgcd.c index eb045eecf8..7d765057fb 100644 --- a/fmpz_sparse_mat/hnf_xgcd.c +++ b/fmpz_sparse_mat/hnf_xgcd.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/howell_form_mod.c b/fmpz_sparse_mat/howell_form_mod.c index 5839ef8fec..e07c84a7ad 100644 --- a/fmpz_sparse_mat/howell_form_mod.c +++ b/fmpz_sparse_mat/howell_form_mod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/is_in_hnf.c b/fmpz_sparse_mat/is_in_hnf.c index 8a3be06c8e..9caa46df77 100644 --- a/fmpz_sparse_mat/is_in_hnf.c +++ b/fmpz_sparse_mat/is_in_hnf.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/max_bits.c b/fmpz_sparse_mat/max_bits.c index 2a9f46888a..d5337efa80 100644 --- a/fmpz_sparse_mat/max_bits.c +++ b/fmpz_sparse_mat/max_bits.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/multi_CRT_ui.c b/fmpz_sparse_mat/multi_CRT_ui.c index 77946c9bb0..ee8bfdbdcf 100644 --- a/fmpz_sparse_mat/multi_CRT_ui.c +++ b/fmpz_sparse_mat/multi_CRT_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -37,6 +38,10 @@ fmpz_sparse_mat_multi_CRT_ui(fmpz_sparse_mat_t mat, nmod_sparse_mat_struct * res fmpz_comb_t comb; fmpz_comb_temp_t temp; + for(i = 0; i < nres; ++i) { + FLINT_ASSERT(mat->r == residues[i].r); + } + primes = flint_malloc(nres * sizeof(*primes)); for (i = 0; i < nres; i++) primes[i] = residues[i].mod.n; fmpz_comb_init(comb, primes, nres); diff --git a/fmpz_sparse_mat/multi_mod_ui.c b/fmpz_sparse_mat/multi_mod_ui.c index a9b0c4773e..28aa8ec705 100644 --- a/fmpz_sparse_mat/multi_mod_ui.c +++ b/fmpz_sparse_mat/multi_mod_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -41,6 +42,9 @@ void fmpz_sparse_mat_multi_mod_ui(nmod_sparse_mat_struct * residues, slong nres, const fmpz_sparse_mat_t M) { slong i; + for(i = 0; i < nres; ++i) { + FLINT_ASSERT(mat->r == residues[i].r); + } mp_limb_t *primes; fmpz_comb_t comb; fmpz_comb_temp_t temp; diff --git a/fmpz_sparse_mat/print_pretty.c b/fmpz_sparse_mat/print_pretty.c index f000cf9509..a2c4dcfd07 100644 --- a/fmpz_sparse_mat/print_pretty.c +++ b/fmpz_sparse_mat/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/randtest.c b/fmpz_sparse_mat/randtest.c index c0d260028b..1c7a184925 100644 --- a/fmpz_sparse_mat/randtest.c +++ b/fmpz_sparse_mat/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/randtest_unsigned.c b/fmpz_sparse_mat/randtest_unsigned.c index e637dd377c..06fdb1d90d 100644 --- a/fmpz_sparse_mat/randtest_unsigned.c +++ b/fmpz_sparse_mat/randtest_unsigned.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/snf.c b/fmpz_sparse_mat/snf.c index e733132b4e..f87b4e3d45 100644 --- a/fmpz_sparse_mat/snf.c +++ b/fmpz_sparse_mat/snf.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/snf_diagonal.c b/fmpz_sparse_mat/snf_diagonal.c index 21808d358b..b4e3dc2703 100644 --- a/fmpz_sparse_mat/snf_diagonal.c +++ b/fmpz_sparse_mat/snf_diagonal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/snf_iliopoulos.c b/fmpz_sparse_mat/snf_iliopoulos.c index 889f08a7f1..64abb62250 100644 --- a/fmpz_sparse_mat/snf_iliopoulos.c +++ b/fmpz_sparse_mat/snf_iliopoulos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/snf_kannan_bachem.c b/fmpz_sparse_mat/snf_kannan_bachem.c index d7669e8123..9851416d07 100644 --- a/fmpz_sparse_mat/snf_kannan_bachem.c +++ b/fmpz_sparse_mat/snf_kannan_bachem.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/solve_bound.c b/fmpz_sparse_mat/solve_bound.c index efe70349b0..cec4ae9b34 100644 --- a/fmpz_sparse_mat/solve_bound.c +++ b/fmpz_sparse_mat/solve_bound.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/solve_dixon.c b/fmpz_sparse_mat/solve_dixon.c index bbaefd6583..8532d6a54d 100644 --- a/fmpz_sparse_mat/solve_dixon.c +++ b/fmpz_sparse_mat/solve_dixon.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/strong_echelon_form_mod.c b/fmpz_sparse_mat/strong_echelon_form_mod.c index 91bcf857ed..9c8bba8449 100644 --- a/fmpz_sparse_mat/strong_echelon_form_mod.c +++ b/fmpz_sparse_mat/strong_echelon_form_mod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-CRT_ui.c b/fmpz_sparse_mat/test/t-CRT_ui.c index 4248181b86..daf3662893 100644 --- a/fmpz_sparse_mat/test/t-CRT_ui.c +++ b/fmpz_sparse_mat/test/t-CRT_ui.c @@ -1,6 +1,7 @@ /* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c b/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c index 4507517234..66339a71b0 100644 --- a/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c +++ b/fmpz_sparse_mat/test/t-CRT_ui_unsigned.c @@ -1,6 +1,7 @@ /* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-add.c b/fmpz_sparse_mat/test/t-add.c index 48870e570d..4640382989 100644 --- a/fmpz_sparse_mat/test/t-add.c +++ b/fmpz_sparse_mat/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-concat_horizontal.c b/fmpz_sparse_mat/test/t-concat_horizontal.c index 083fd85b3e..e57ad8973d 100644 --- a/fmpz_sparse_mat/test/t-concat_horizontal.c +++ b/fmpz_sparse_mat/test/t-concat_horizontal.c @@ -1,6 +1,7 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-concat_vertical.c b/fmpz_sparse_mat/test/t-concat_vertical.c index 0078dc0dd1..0bda166c21 100644 --- a/fmpz_sparse_mat/test/t-concat_vertical.c +++ b/fmpz_sparse_mat/test/t-concat_vertical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-construct.c b/fmpz_sparse_mat/test/t-construct.c index 06fd3f06a6..ba9014abb9 100644 --- a/fmpz_sparse_mat/test/t-construct.c +++ b/fmpz_sparse_mat/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-content.c b/fmpz_sparse_mat/test/t-content.c index b1911742a9..7f34d90a9c 100644 --- a/fmpz_sparse_mat/test/t-content.c +++ b/fmpz_sparse_mat/test/t-content.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Dharak Kharod + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-dense.c b/fmpz_sparse_mat/test/t-dense.c index 671bc1028d..5a70031e4b 100644 --- a/fmpz_sparse_mat/test/t-dense.c +++ b/fmpz_sparse_mat/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det.c b/fmpz_sparse_mat/test/t-det.c index dbebace188..12f99015b2 100644 --- a/fmpz_sparse_mat/test/t-det.c +++ b/fmpz_sparse_mat/test/t-det.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det_bareiss.c b/fmpz_sparse_mat/test/t-det_bareiss.c index fbd894c1e1..7c65540670 100644 --- a/fmpz_sparse_mat/test/t-det_bareiss.c +++ b/fmpz_sparse_mat/test/t-det_bareiss.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det_bound.c b/fmpz_sparse_mat/test/t-det_bound.c index 2dd2e4074b..b0a6e08c61 100644 --- a/fmpz_sparse_mat/test/t-det_bound.c +++ b/fmpz_sparse_mat/test/t-det_bound.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det_divisor.c b/fmpz_sparse_mat/test/t-det_divisor.c index 3217ace8fd..ee4873a7a7 100644 --- a/fmpz_sparse_mat/test/t-det_divisor.c +++ b/fmpz_sparse_mat/test/t-det_divisor.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det_modular.c b/fmpz_sparse_mat/test/t-det_modular.c index bf3c2d459f..de65ef2814 100644 --- a/fmpz_sparse_mat/test/t-det_modular.c +++ b/fmpz_sparse_mat/test/t-det_modular.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-det_modular_accelerated.c b/fmpz_sparse_mat/test/t-det_modular_accelerated.c index d317e979ea..23615aa08c 100644 --- a/fmpz_sparse_mat/test/t-det_modular_accelerated.c +++ b/fmpz_sparse_mat/test/t-det_modular_accelerated.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-fflu.c b/fmpz_sparse_mat/test/t-fflu.c index a6d9fd0c36..67775f7a9f 100644 --- a/fmpz_sparse_mat/test/t-fflu.c +++ b/fmpz_sparse_mat/test/t-fflu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-hnf_classical.c b/fmpz_sparse_mat/test/t-hnf_classical.c index 6dce52af0d..481fb7d7fa 100644 --- a/fmpz_sparse_mat/test/t-hnf_classical.c +++ b/fmpz_sparse_mat/test/t-hnf_classical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-hnf_minors.c b/fmpz_sparse_mat/test/t-hnf_minors.c index 50c9a326a7..64d26e8d71 100644 --- a/fmpz_sparse_mat/test/t-hnf_minors.c +++ b/fmpz_sparse_mat/test/t-hnf_minors.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-hnf_modular.c b/fmpz_sparse_mat/test/t-hnf_modular.c index 9077dc15c0..0fe0d9a5fe 100644 --- a/fmpz_sparse_mat/test/t-hnf_modular.c +++ b/fmpz_sparse_mat/test/t-hnf_modular.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c b/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c index 85eac68768..ffdc3f9320 100644 --- a/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c +++ b/fmpz_sparse_mat/test/t-hnf_modular_eldiv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-hnf_xgcd.c b/fmpz_sparse_mat/test/t-hnf_xgcd.c index d7ac5698ec..f518250af9 100644 --- a/fmpz_sparse_mat/test/t-hnf_xgcd.c +++ b/fmpz_sparse_mat/test/t-hnf_xgcd.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014 Alex J. Best + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-howell_form_mod.c b/fmpz_sparse_mat/test/t-howell_form_mod.c index cbe3be54a3..d346bfacca 100644 --- a/fmpz_sparse_mat/test/t-howell_form_mod.c +++ b/fmpz_sparse_mat/test/t-howell_form_mod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-init_clear.c b/fmpz_sparse_mat/test/t-init_clear.c index 5d023ee3ca..e5f3411131 100644 --- a/fmpz_sparse_mat/test/t-init_clear.c +++ b/fmpz_sparse_mat/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-mul.c b/fmpz_sparse_mat/test/t-mul.c index bb8586efc0..e9d332695e 100644 --- a/fmpz_sparse_mat/test/t-mul.c +++ b/fmpz_sparse_mat/test/t-mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-multi_CRT_ui.c b/fmpz_sparse_mat/test/t-multi_CRT_ui.c index 9456791a60..b51b8a5114 100644 --- a/fmpz_sparse_mat/test/t-multi_CRT_ui.c +++ b/fmpz_sparse_mat/test/t-multi_CRT_ui.c @@ -1,6 +1,7 @@ /* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c b/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c index 30cab7c705..c83d63418d 100644 --- a/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c +++ b/fmpz_sparse_mat/test/t-multi_CRT_ui_unsigned.c @@ -1,6 +1,7 @@ /* Copyright (C) 2007 William Hart and David Harvey Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-neg.c b/fmpz_sparse_mat/test/t-neg.c index 645c690981..b4fd5c1873 100644 --- a/fmpz_sparse_mat/test/t-neg.c +++ b/fmpz_sparse_mat/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-scalar_mul.c b/fmpz_sparse_mat/test/t-scalar_mul.c index 91c4df9256..98b5daba12 100644 --- a/fmpz_sparse_mat/test/t-scalar_mul.c +++ b/fmpz_sparse_mat/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-solve_dixon.c b/fmpz_sparse_mat/test/t-solve_dixon.c index a69605d9e0..7143abd9d7 100644 --- a/fmpz_sparse_mat/test/t-solve_dixon.c +++ b/fmpz_sparse_mat/test/t-solve_dixon.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-solve_dixon_den.c b/fmpz_sparse_mat/test/t-solve_dixon_den.c index 54aba9b8b2..64c842091a 100644 --- a/fmpz_sparse_mat/test/t-solve_dixon_den.c +++ b/fmpz_sparse_mat/test/t-solve_dixon_den.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/test/t-transpose.c b/fmpz_sparse_mat/test/t-transpose.c index cadc2ee77c..814f2fbe0c 100644 --- a/fmpz_sparse_mat/test/t-transpose.c +++ b/fmpz_sparse_mat/test/t-transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/transpose.c b/fmpz_sparse_mat/transpose.c index c6eab43ee1..7800152ae3 100644 --- a/fmpz_sparse_mat/transpose.c +++ b/fmpz_sparse_mat/transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -19,6 +20,8 @@ fmpz_sparse_mat_transpose(fmpz_sparse_mat_t B, const fmpz_sparse_mat_t A) { slong r, c, i, j, *nnz; fmpz_sparse_entry_struct *Ae, *Be; + FLINT_ASSERT(B->r == A->c); + FLINT_ASSERT(A->r == B->c); nnz = flint_calloc(A->c, sizeof(*nnz)); /* Get number of nnzs in each column of A (thus each row of B) */ for (c = 0; c < A->c; ++c) diff --git a/fmpz_sparse_mat/with_transpose_fix_support.c b/fmpz_sparse_mat/with_transpose_fix_support.c index fe8d8371f2..a5933fff2f 100644 --- a/fmpz_sparse_mat/with_transpose_fix_support.c +++ b/fmpz_sparse_mat/with_transpose_fix_support.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_mat/with_transpose_init.c b/fmpz_sparse_mat/with_transpose_init.c index a1666e48e7..f45781f7d2 100644 --- a/fmpz_sparse_mat/with_transpose_init.c +++ b/fmpz_sparse_mat/with_transpose_init.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec.h b/fmpz_sparse_vec.h index 3e18819a94..d25568ff0f 100644 --- a/fmpz_sparse_vec.h +++ b/fmpz_sparse_vec.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -70,6 +71,7 @@ void fmpz_sparse_vec_init(fmpz_sparse_vec_t vec) { memset(vec, 0, sizeof(*vec)); } + FMPZ_SPARSE_VEC_INLINE void fmpz_sparse_vec_clear(fmpz_sparse_vec_t vec) { @@ -84,6 +86,7 @@ FMPZ_SPARSE_VEC_INLINE void _fmpz_sparse_vec_resize(fmpz_sparse_vec_t vec, slong nnz) { slong i; + FLINT_ASSERT(nnz >= 0); if (nnz == 0) fmpz_sparse_vec_clear(vec); else if (nnz != vec->nnz) { @@ -96,6 +99,21 @@ void _fmpz_sparse_vec_resize(fmpz_sparse_vec_t vec, slong nnz) vec->nnz = nnz; } +FMPZ_SPARSE_VEC_INLINE +void fmpz_sparse_vec_resize(fmpz_sparse_vec_t vec, slong cols) +{ + slong i; + FLINT_ASSERT(cols >= 0); + if (vec->nnz == 0) return; + for (i = 0; i < vec->nnz; ++i) { + if (vec->entries[i].ind >= cols) + { + break; + } + } + _fmpz_sparse_vec_resize(vec, i); +} + FMPZ_SPARSE_VEC_INLINE slong _fmpz_sparse_vec_support(slong **supp, fmpz_sparse_vec_t vec) { diff --git a/fmpz_sparse_vec/CRT_ui.c b/fmpz_sparse_vec/CRT_ui.c index 3472717fe8..ed34f7616f 100644 --- a/fmpz_sparse_vec/CRT_ui.c +++ b/fmpz_sparse_vec/CRT_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/add.c b/fmpz_sparse_vec/add.c index 92282452c6..82248c5091 100644 --- a/fmpz_sparse_vec/add.c +++ b/fmpz_sparse_vec/add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/at.c b/fmpz_sparse_vec/at.c index f89a71fec4..78bc8443fe 100644 --- a/fmpz_sparse_vec/at.c +++ b/fmpz_sparse_vec/at.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/concat.c b/fmpz_sparse_vec/concat.c index 37b7caefd6..2ec111ad27 100644 --- a/fmpz_sparse_vec/concat.c +++ b/fmpz_sparse_vec/concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/dot.c b/fmpz_sparse_vec/dot.c index d7fb1f8774..63750299c3 100644 --- a/fmpz_sparse_vec/dot.c +++ b/fmpz_sparse_vec/dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/dot_dense.c b/fmpz_sparse_vec/dot_dense.c index bcf2c6746a..1ac529bd80 100644 --- a/fmpz_sparse_vec/dot_dense.c +++ b/fmpz_sparse_vec/dot_dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/equal.c b/fmpz_sparse_vec/equal.c index ef5ce60a1e..aec8f682d8 100644 --- a/fmpz_sparse_vec/equal.c +++ b/fmpz_sparse_vec/equal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/from_dense.c b/fmpz_sparse_vec/from_dense.c index 1eba2e3943..1689816c05 100644 --- a/fmpz_sparse_vec/from_dense.c +++ b/fmpz_sparse_vec/from_dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/from_entries.c b/fmpz_sparse_vec/from_entries.c index 1b5d0bdc72..4dd16974f3 100644 --- a/fmpz_sparse_vec/from_entries.c +++ b/fmpz_sparse_vec/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/gauss_elim.c b/fmpz_sparse_vec/gauss_elim.c index d5df05ca45..a36dae5755 100644 --- a/fmpz_sparse_vec/gauss_elim.c +++ b/fmpz_sparse_vec/gauss_elim.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -45,14 +46,13 @@ void fmpz_sparse_vec_gauss_elim(fmpz_sparse_vec_t u, const fmpz_sparse_vec_t v) /* Apply unimodular transformation to (u,v) to minimize both vectors lexicographically */ void fmpz_sparse_vec_gauss_elim_ext(fmpz_sparse_vec_t u, fmpz_sparse_vec_t v) { - slong vnnz = v->nnz, unnz = u->nnz, nnz, k, pc, i; + slong vnnz = v->nnz, unnz = u->nnz, nnz, k; fmpz_sparse_entry_struct *lu = u->entries; fmpz_sparse_entry_struct *lv = v->entries; fmpz_t g, vv, vu, uv, uu, a, b; fmpz_sparse_entry_struct *ue, *ve, *nue, *nve; if (u->nnz == 0 || v->nnz == 0) return; if (lu->ind != lv->ind) {fmpz_sparse_vec_gauss_elim(u, v); return;} - pc = lu->ind; if (fmpz_cmpabs(lu->val, lv->val) < 0) /* Pre-apply transform [[0, -1], [1, 0]] */ { fmpz_sparse_vec_swap(u, v); diff --git a/fmpz_sparse_vec/max_bits.c b/fmpz_sparse_vec/max_bits.c index 94e83083c4..e49ba507ea 100644 --- a/fmpz_sparse_vec/max_bits.c +++ b/fmpz_sparse_vec/max_bits.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/multi_CRT_ui.c b/fmpz_sparse_vec/multi_CRT_ui.c index bf2828ad68..2e47171933 100644 --- a/fmpz_sparse_vec/multi_CRT_ui.c +++ b/fmpz_sparse_vec/multi_CRT_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -15,16 +16,14 @@ void fmpz_sparse_vec_multi_CRT_ui_precomp(fmpz_sparse_vec_t v, nmod_sparse_vec_struct const * residues, slong nres, const fmpz_comb_t comb, fmpz_comb_temp_t temp, int sign) { - slong i, j, pos, *rpos, max_nnz, max_ind; + slong j, pos, *rpos, max_nnz, max_ind; mp_limb_t *r; - nmod_sparse_vec_struct *vm; fmpz_sparse_entry_struct *e; for (j = max_nnz = max_ind = 0; j < nres; ++j) { - vm = &residues[j]; - max_nnz = FLINT_MAX(max_nnz, vm->nnz); - if (vm->nnz != 0) max_ind = FLINT_MAX(max_ind, vm->entries[vm->nnz - 1].ind); + max_nnz = FLINT_MAX(max_nnz, residues[j].nnz); + if (residues[j].nnz != 0) max_ind = FLINT_MAX(max_ind, residues[j].entries[residues[j].nnz - 1].ind); } _fmpz_sparse_vec_resize(v, max_nnz); /* May change later */ if (max_nnz == 0) return; @@ -40,14 +39,12 @@ fmpz_sparse_vec_multi_CRT_ui_precomp(fmpz_sparse_vec_t v, nmod_sparse_vec_struct e->ind = max_ind + 1; for (j = 0; j < nres; ++j) { - vm = &residues[j]; - e->ind = (rpos[j] != vm->nnz && vm->entries[rpos[j]].ind < e->ind) ? vm->entries[rpos[j]].ind : e->ind; + e->ind = (rpos[j] != residues[j].nnz && residues[j].entries[rpos[j]].ind < e->ind) ? residues[j].entries[rpos[j]].ind : e->ind; } if (e->ind == max_ind + 1) break; for (j = 0; j < nres; ++j) { - vm = &residues[j]; - r[j] = (rpos[j] != vm->nnz && vm->entries[rpos[j]].ind == e->ind) ? vm->entries[rpos[j]++].val : 0; + r[j] = (rpos[j] != residues[j].nnz && residues[j].entries[rpos[j]].ind == e->ind) ? residues[j].entries[rpos[j]++].val : 0; } fmpz_multi_CRT_ui(e->val, r, comb, temp, sign); } diff --git a/fmpz_sparse_vec/multi_mod_ui.c b/fmpz_sparse_vec/multi_mod_ui.c index 05c752981a..c52f665f75 100644 --- a/fmpz_sparse_vec/multi_mod_ui.c +++ b/fmpz_sparse_vec/multi_mod_ui.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/print_pretty.c b/fmpz_sparse_vec/print_pretty.c index c385a71951..059237302d 100644 --- a/fmpz_sparse_vec/print_pretty.c +++ b/fmpz_sparse_vec/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/randtest.c b/fmpz_sparse_vec/randtest.c index 818c48b4cb..9a46c0a7df 100644 --- a/fmpz_sparse_vec/randtest.c +++ b/fmpz_sparse_vec/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/randtest_unsigned.c b/fmpz_sparse_vec/randtest_unsigned.c index 8c66e30271..457e1486c3 100644 --- a/fmpz_sparse_vec/randtest_unsigned.c +++ b/fmpz_sparse_vec/randtest_unsigned.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_addmul.c b/fmpz_sparse_vec/scalar_addmul.c index 4dab59b4f7..df39c6aaaf 100644 --- a/fmpz_sparse_vec/scalar_addmul.c +++ b/fmpz_sparse_vec/scalar_addmul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_divexact.c b/fmpz_sparse_vec/scalar_divexact.c index f45f27f2ea..c584202c97 100644 --- a/fmpz_sparse_vec/scalar_divexact.c +++ b/fmpz_sparse_vec/scalar_divexact.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_mod.c b/fmpz_sparse_vec/scalar_mod.c index 1273ba4bab..5fce2ba885 100644 --- a/fmpz_sparse_vec/scalar_mod.c +++ b/fmpz_sparse_vec/scalar_mod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_mods.c b/fmpz_sparse_vec/scalar_mods.c index f71d70d8cd..94c8409069 100644 --- a/fmpz_sparse_vec/scalar_mods.c +++ b/fmpz_sparse_vec/scalar_mods.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_mul.c b/fmpz_sparse_vec/scalar_mul.c index 50522125f0..e51ea0dace 100644 --- a/fmpz_sparse_vec/scalar_mul.c +++ b/fmpz_sparse_vec/scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/scalar_submul.c b/fmpz_sparse_vec/scalar_submul.c index 8ada9678f6..82c9860a8a 100644 --- a/fmpz_sparse_vec/scalar_submul.c +++ b/fmpz_sparse_vec/scalar_submul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/set.c b/fmpz_sparse_vec/set.c index e8813847f9..6e84f479db 100644 --- a/fmpz_sparse_vec/set.c +++ b/fmpz_sparse_vec/set.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/split.c b/fmpz_sparse_vec/split.c index b98eb4f222..6a3582cfc0 100644 --- a/fmpz_sparse_vec/split.c +++ b/fmpz_sparse_vec/split.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/sub.c b/fmpz_sparse_vec/sub.c index 927e9909b3..f0dfe72e06 100644 --- a/fmpz_sparse_vec/sub.c +++ b/fmpz_sparse_vec/sub.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-add.c b/fmpz_sparse_vec/test/t-add.c index a2ff49d3ab..797afc9aee 100644 --- a/fmpz_sparse_vec/test/t-add.c +++ b/fmpz_sparse_vec/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-concat.c b/fmpz_sparse_vec/test/t-concat.c index ea499693f6..3a1dbd483e 100644 --- a/fmpz_sparse_vec/test/t-concat.c +++ b/fmpz_sparse_vec/test/t-concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-construct.c b/fmpz_sparse_vec/test/t-construct.c index d97263ee0d..fdc2381532 100644 --- a/fmpz_sparse_vec/test/t-construct.c +++ b/fmpz_sparse_vec/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-dense.c b/fmpz_sparse_vec/test/t-dense.c index 3187cc29b6..ce84cffa53 100644 --- a/fmpz_sparse_vec/test/t-dense.c +++ b/fmpz_sparse_vec/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-dot.c b/fmpz_sparse_vec/test/t-dot.c index 795bee5037..87be4e5b20 100644 --- a/fmpz_sparse_vec/test/t-dot.c +++ b/fmpz_sparse_vec/test/t-dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-gauss_elim.c b/fmpz_sparse_vec/test/t-gauss_elim.c index 60cba8d1b4..0b60a408c4 100644 --- a/fmpz_sparse_vec/test/t-gauss_elim.c +++ b/fmpz_sparse_vec/test/t-gauss_elim.c @@ -1,5 +1,6 @@ /* - wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-init_clear.c b/fmpz_sparse_vec/test/t-init_clear.c index 50a0ef18d0..27deb5c8cd 100644 --- a/fmpz_sparse_vec/test/t-init_clear.c +++ b/fmpz_sparse_vec/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-max_bits.c b/fmpz_sparse_vec/test/t-max_bits.c index 92d3d0e12d..eceff4a41e 100644 --- a/fmpz_sparse_vec/test/t-max_bits.c +++ b/fmpz_sparse_vec/test/t-max_bits.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-neg.c b/fmpz_sparse_vec/test/t-neg.c index 9b6fce5712..18c4bf2f50 100644 --- a/fmpz_sparse_vec/test/t-neg.c +++ b/fmpz_sparse_vec/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-nmod.c b/fmpz_sparse_vec/test/t-nmod.c index 22a112bd29..7e19fc03dc 100644 --- a/fmpz_sparse_vec/test/t-nmod.c +++ b/fmpz_sparse_vec/test/t-nmod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-scalar_divexact.c b/fmpz_sparse_vec/test/t-scalar_divexact.c index d3681dab28..06cca65702 100644 --- a/fmpz_sparse_vec/test/t-scalar_divexact.c +++ b/fmpz_sparse_vec/test/t-scalar_divexact.c @@ -1,5 +1,6 @@ /* - wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-scalar_mod.c b/fmpz_sparse_vec/test/t-scalar_mod.c index f34407168f..3f8d026a27 100644 --- a/fmpz_sparse_vec/test/t-scalar_mod.c +++ b/fmpz_sparse_vec/test/t-scalar_mod.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fmpz_sparse_vec/test/t-scalar_mul.c b/fmpz_sparse_vec/test/t-scalar_mul.c index 3e250be81a..f4cdc116b0 100644 --- a/fmpz_sparse_vec/test/t-scalar_mul.c +++ b/fmpz_sparse_vec/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* - wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_nmod_sparse_mat.h b/fq_nmod_sparse_mat.h index 47643c88e3..c84f117223 100644 --- a/fq_nmod_sparse_mat.h +++ b/fq_nmod_sparse_mat.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_nmod_sparse_vec.h b/fq_nmod_sparse_vec.h index f243bc7391..a6037b3489 100644 --- a/fq_nmod_sparse_vec.h +++ b/fq_nmod_sparse_vec.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat.h b/fq_sparse_mat.h index e9425c87ec..d1e2c6411b 100644 --- a/fq_sparse_mat.h +++ b/fq_sparse_mat.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/from_entries.c b/fq_sparse_mat/from_entries.c index 30de86fbff..24ea5e68ef 100644 --- a/fq_sparse_mat/from_entries.c +++ b/fq_sparse_mat/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/inv.c b/fq_sparse_mat/inv.c index 1a510a64df..422d1a27ee 100644 --- a/fq_sparse_mat/inv.c +++ b/fq_sparse_mat/inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/lu.c b/fq_sparse_mat/lu.c index f34cf23b13..8b4a2fec4a 100644 --- a/fq_sparse_mat/lu.c +++ b/fq_sparse_mat/lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_block_lanczos.c b/fq_sparse_mat/nullspace_block_lanczos.c index 0da3550c03..d806b0a350 100644 --- a/fq_sparse_mat/nullspace_block_lanczos.c +++ b/fq_sparse_mat/nullspace_block_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_block_wiedemann.c b/fq_sparse_mat/nullspace_block_wiedemann.c index decfaf8ea1..54e56c2912 100644 --- a/fq_sparse_mat/nullspace_block_wiedemann.c +++ b/fq_sparse_mat/nullspace_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_lanczos.c b/fq_sparse_mat/nullspace_lanczos.c index 6cf17b90d1..cc2a572ef1 100644 --- a/fq_sparse_mat/nullspace_lanczos.c +++ b/fq_sparse_mat/nullspace_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_lu.c b/fq_sparse_mat/nullspace_lu.c index 5c1d34e5f4..81f0dc4b54 100644 --- a/fq_sparse_mat/nullspace_lu.c +++ b/fq_sparse_mat/nullspace_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_rref.c b/fq_sparse_mat/nullspace_rref.c index c0d8646b3a..f0f1b8d643 100644 --- a/fq_sparse_mat/nullspace_rref.c +++ b/fq_sparse_mat/nullspace_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/nullspace_wiedemann.c b/fq_sparse_mat/nullspace_wiedemann.c index 721fc4b9e1..32a1393376 100644 --- a/fq_sparse_mat/nullspace_wiedemann.c +++ b/fq_sparse_mat/nullspace_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/print_pretty.c b/fq_sparse_mat/print_pretty.c index 83d2b583d3..8090dcc69d 100644 --- a/fq_sparse_mat/print_pretty.c +++ b/fq_sparse_mat/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/randtest.c b/fq_sparse_mat/randtest.c index 344d5ccdec..5ffb7f0cf4 100644 --- a/fq_sparse_mat/randtest.c +++ b/fq_sparse_mat/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/rref.c b/fq_sparse_mat/rref.c index d8c2e69609..a5db83126a 100644 --- a/fq_sparse_mat/rref.c +++ b/fq_sparse_mat/rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/solve_block_lanczos.c b/fq_sparse_mat/solve_block_lanczos.c index 7b6e0ba4c1..30206162b3 100644 --- a/fq_sparse_mat/solve_block_lanczos.c +++ b/fq_sparse_mat/solve_block_lanczos.c @@ -1,11 +1,10 @@ /* + Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 Kartik Venkatram Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 - Copyright (C) 2010 Fredrik Johansson - This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under diff --git a/fq_sparse_mat/solve_block_wiedemann.c b/fq_sparse_mat/solve_block_wiedemann.c index 08cee373a5..208a05dd92 100644 --- a/fq_sparse_mat/solve_block_wiedemann.c +++ b/fq_sparse_mat/solve_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/solve_lanczos.c b/fq_sparse_mat/solve_lanczos.c index 2165bcfb7b..e9ffdb4c09 100644 --- a/fq_sparse_mat/solve_lanczos.c +++ b/fq_sparse_mat/solve_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/solve_lu.c b/fq_sparse_mat/solve_lu.c index c850b6b511..587186cf8f 100644 --- a/fq_sparse_mat/solve_lu.c +++ b/fq_sparse_mat/solve_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/solve_rref.c b/fq_sparse_mat/solve_rref.c index f718908bd6..9a8cd0257b 100644 --- a/fq_sparse_mat/solve_rref.c +++ b/fq_sparse_mat/solve_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/solve_wiedemann.c b/fq_sparse_mat/solve_wiedemann.c index bb5886b871..c40f0f79af 100644 --- a/fq_sparse_mat/solve_wiedemann.c +++ b/fq_sparse_mat/solve_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-add.c b/fq_sparse_mat/test/t-add.c index aba875a83e..c5e5c1590d 100644 --- a/fq_sparse_mat/test/t-add.c +++ b/fq_sparse_mat/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-concat_horizontal.c b/fq_sparse_mat/test/t-concat_horizontal.c index 5ccf74698a..a44d374233 100644 --- a/fq_sparse_mat/test/t-concat_horizontal.c +++ b/fq_sparse_mat/test/t-concat_horizontal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-concat_vertical.c b/fq_sparse_mat/test/t-concat_vertical.c index 5c207ea5a0..ee3b99ca6f 100644 --- a/fq_sparse_mat/test/t-concat_vertical.c +++ b/fq_sparse_mat/test/t-concat_vertical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-construct.c b/fq_sparse_mat/test/t-construct.c index 1f835d3797..b15335ce2c 100644 --- a/fq_sparse_mat/test/t-construct.c +++ b/fq_sparse_mat/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-dense.c b/fq_sparse_mat/test/t-dense.c index c9fcb894a7..c9207725d2 100644 --- a/fq_sparse_mat/test/t-dense.c +++ b/fq_sparse_mat/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-init_clear.c b/fq_sparse_mat/test/t-init_clear.c index 5fa52abb6c..ec140aa821 100644 --- a/fq_sparse_mat/test/t-init_clear.c +++ b/fq_sparse_mat/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-inv.c b/fq_sparse_mat/test/t-inv.c index f180442657..a4d51256ba 100644 --- a/fq_sparse_mat/test/t-inv.c +++ b/fq_sparse_mat/test/t-inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-lu.c b/fq_sparse_mat/test/t-lu.c index 327417bf86..f50b51f280 100644 --- a/fq_sparse_mat/test/t-lu.c +++ b/fq_sparse_mat/test/t-lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-mul.c b/fq_sparse_mat/test/t-mul.c index 6225c09304..0df33448d9 100644 --- a/fq_sparse_mat/test/t-mul.c +++ b/fq_sparse_mat/test/t-mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-neg.c b/fq_sparse_mat/test/t-neg.c index 6bc923de5e..99cd1b8ad1 100644 --- a/fq_sparse_mat/test/t-neg.c +++ b/fq_sparse_mat/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-nullspace.c b/fq_sparse_mat/test/t-nullspace.c index 039710f4f2..0703f1d579 100644 --- a/fq_sparse_mat/test/t-nullspace.c +++ b/fq_sparse_mat/test/t-nullspace.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-rref.c b/fq_sparse_mat/test/t-rref.c index d01a7ab372..00eb87f61c 100644 --- a/fq_sparse_mat/test/t-rref.c +++ b/fq_sparse_mat/test/t-rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-scalar_mul.c b/fq_sparse_mat/test/t-scalar_mul.c index 2aebfd1d45..0bbd83d529 100644 --- a/fq_sparse_mat/test/t-scalar_mul.c +++ b/fq_sparse_mat/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-solve.c b/fq_sparse_mat/test/t-solve.c index d2bbcaa132..d0c160e64c 100644 --- a/fq_sparse_mat/test/t-solve.c +++ b/fq_sparse_mat/test/t-solve.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/test/t-transpose.c b/fq_sparse_mat/test/t-transpose.c index b840457936..7adcfd3374 100644 --- a/fq_sparse_mat/test/t-transpose.c +++ b/fq_sparse_mat/test/t-transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat/transpose.c b/fq_sparse_mat/transpose.c index dcc14f275d..c64bd3c1ac 100644 --- a/fq_sparse_mat/transpose.c +++ b/fq_sparse_mat/transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates.h b/fq_sparse_mat_templates.h index 5dab0a3961..7d147edbac 100644 --- a/fq_sparse_mat_templates.h +++ b/fq_sparse_mat_templates.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -42,11 +43,13 @@ typedef TEMPLATE(T, sparse_mat_struct) TEMPLATE(T, sparse_mat_t)[1]; FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_init) (TEMPLATE(T, sparse_mat_t) M, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx) { + FLINT_ASSERT(rows >= 0 && cols >= 0); M->rows = flint_calloc(rows, sizeof(*M->rows)); M->r = rows; M->c = cols; M->c_off = 0; } + FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_clear) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) { @@ -55,6 +58,40 @@ void TEMPLATE(T, sparse_mat_clear) (TEMPLATE(T, sparse_mat_t) M, const TEMPLATE( flint_free(M->rows); memset(M, 0, sizeof(*M)); } + +FQ_SPARSE_MAT_TEMPLATES_INLINE +void TEMPLATE(T, sparse_mat_resize) (TEMPLATE(T, sparse_mat_t) M, slong rows, slong cols, const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + FLINT_ASSERT(rows >= 0 && cols >= 0); + if (M->r != rows) { + if (M->r > rows) + { + for (i = rows; i < M->r; ++i) + { + TEMPLATE(T, sparse_vec_clear)(&M->rows[i], ctx); + } + } + M->rows = flint_realloc(M->rows, rows*sizeof(*M->rows)); + if (M->r < rows) + { + for (i = M->r; i < rows; ++i) + { + TEMPLATE(T, sparse_vec_init)(&M->rows[i], ctx); + } + } + M->r = rows; + } + if (cols < M->c) + { + for (i = 0; i < M->r; ++i) + { + TEMPLATE(T, sparse_vec_resize)(&M->rows[i], cols, ctx); + } + } + M->c = cols; +} + FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_swap) (TEMPLATE(T, sparse_mat_t) M1, TEMPLATE(T, sparse_mat_t) M2, const TEMPLATE(T, ctx_t) ctx) { @@ -237,6 +274,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_neg) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) TEMPLATE(T, sparse_vec_neg)(&N->rows[i], &M->rows[i], ctx); } @@ -244,6 +282,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_mul, T)) (TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(M->r == N->r); for (i = 0; i < N->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_mul, T))(&N->rows[i], &M->rows[i], c, ctx); } @@ -252,6 +291,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_add) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_add)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); } @@ -259,6 +299,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_sub) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) TEMPLATE(T, sparse_vec_sub)(&O->rows[i], &M->rows[i], &N->rows[i], ctx); } @@ -266,6 +307,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_addmul, T)) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_addmul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); } @@ -273,6 +315,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, TEMPLATE(sparse_mat_scalar_submul, T)) (TEMPLATE(T, sparse_mat_t) O, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, sparse_mat_t) N, const TEMPLATE(T, t) c, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) TEMPLATE(T, TEMPLATE(sparse_vec_scalar_submul, T))(&O->rows[i], &M->rows[i], &N->rows[i], c, ctx); } @@ -287,6 +330,7 @@ FQ_SPARSE_MAT_TEMPLATES_INLINE void TEMPLATE(T, sparse_mat_mul_mat) (TEMPLATE(T, mat_t) Y, const TEMPLATE(T, sparse_mat_t) M, const TEMPLATE(T, mat_t) X, const TEMPLATE(T, ctx_t) ctx) { slong i, j; + FLINT_ASSERT(M->r == Y->r && M->c == X->r && X->c == Y->c); TEMPLATE(T, mat_zero) (Y, ctx); for (i = 0; i < M->r; ++i) { diff --git a/fq_sparse_mat_templates/from_entries.c b/fq_sparse_mat_templates/from_entries.c index 70fa95bf0e..05d2df253a 100644 --- a/fq_sparse_mat_templates/from_entries.c +++ b/fq_sparse_mat_templates/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/inv.c b/fq_sparse_mat_templates/inv.c index 22249dc340..9620a2753b 100644 --- a/fq_sparse_mat_templates/inv.c +++ b/fq_sparse_mat_templates/inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/lu.c b/fq_sparse_mat_templates/lu.c index 161d879afc..091bd775e6 100644 --- a/fq_sparse_mat_templates/lu.c +++ b/fq_sparse_mat_templates/lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_block_lanczos.c b/fq_sparse_mat_templates/nullspace_block_lanczos.c index 38229f8a27..3e7ab6b4a1 100644 --- a/fq_sparse_mat_templates/nullspace_block_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_block_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_block_wiedemann.c b/fq_sparse_mat_templates/nullspace_block_wiedemann.c index 681765a14c..ffe439616e 100644 --- a/fq_sparse_mat_templates/nullspace_block_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_lanczos.c b/fq_sparse_mat_templates/nullspace_lanczos.c index 062bdd35ab..7fbbadd999 100644 --- a/fq_sparse_mat_templates/nullspace_lanczos.c +++ b/fq_sparse_mat_templates/nullspace_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_lu.c b/fq_sparse_mat_templates/nullspace_lu.c index 64ecd0df4a..26a460374f 100644 --- a/fq_sparse_mat_templates/nullspace_lu.c +++ b/fq_sparse_mat_templates/nullspace_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_rref.c b/fq_sparse_mat_templates/nullspace_rref.c index e2cacf60bd..aec35ecee9 100644 --- a/fq_sparse_mat_templates/nullspace_rref.c +++ b/fq_sparse_mat_templates/nullspace_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/nullspace_wiedemann.c b/fq_sparse_mat_templates/nullspace_wiedemann.c index feb8c72f71..950b7126b7 100644 --- a/fq_sparse_mat_templates/nullspace_wiedemann.c +++ b/fq_sparse_mat_templates/nullspace_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/print_pretty.c b/fq_sparse_mat_templates/print_pretty.c index 8d7917756d..9189c984cf 100644 --- a/fq_sparse_mat_templates/print_pretty.c +++ b/fq_sparse_mat_templates/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/randtest.c b/fq_sparse_mat_templates/randtest.c index 11bb98c367..b53cde488e 100644 --- a/fq_sparse_mat_templates/randtest.c +++ b/fq_sparse_mat_templates/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/rref.c b/fq_sparse_mat_templates/rref.c index b32b24f2ec..9b675457ca 100644 --- a/fq_sparse_mat_templates/rref.c +++ b/fq_sparse_mat_templates/rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/solve_block_lanczos.c b/fq_sparse_mat_templates/solve_block_lanczos.c index 6b30543288..6f3a4cacce 100644 --- a/fq_sparse_mat_templates/solve_block_lanczos.c +++ b/fq_sparse_mat_templates/solve_block_lanczos.c @@ -1,11 +1,10 @@ /* + Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 Kartik Venkatram Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 - Copyright (C) 2010 Fredrik Johansson - This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under diff --git a/fq_sparse_mat_templates/solve_block_wiedemann.c b/fq_sparse_mat_templates/solve_block_wiedemann.c index bc0bfc162c..71298aa459 100644 --- a/fq_sparse_mat_templates/solve_block_wiedemann.c +++ b/fq_sparse_mat_templates/solve_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/solve_lanczos.c b/fq_sparse_mat_templates/solve_lanczos.c index 3b2216d5e3..4b1c076a0d 100644 --- a/fq_sparse_mat_templates/solve_lanczos.c +++ b/fq_sparse_mat_templates/solve_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/solve_lu.c b/fq_sparse_mat_templates/solve_lu.c index 26678ab4f8..5946414baf 100644 --- a/fq_sparse_mat_templates/solve_lu.c +++ b/fq_sparse_mat_templates/solve_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/solve_rref.c b/fq_sparse_mat_templates/solve_rref.c index 64286820b3..022bb21f29 100644 --- a/fq_sparse_mat_templates/solve_rref.c +++ b/fq_sparse_mat_templates/solve_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/solve_wiedemann.c b/fq_sparse_mat_templates/solve_wiedemann.c index a045a6426e..b67656b491 100644 --- a/fq_sparse_mat_templates/solve_wiedemann.c +++ b/fq_sparse_mat_templates/solve_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-add.c b/fq_sparse_mat_templates/test/t-add.c index a4e773a3e1..c7a001930a 100644 --- a/fq_sparse_mat_templates/test/t-add.c +++ b/fq_sparse_mat_templates/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-concat_horizontal.c b/fq_sparse_mat_templates/test/t-concat_horizontal.c index 65edca0e73..0fce63dcb4 100644 --- a/fq_sparse_mat_templates/test/t-concat_horizontal.c +++ b/fq_sparse_mat_templates/test/t-concat_horizontal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-concat_vertical.c b/fq_sparse_mat_templates/test/t-concat_vertical.c index 71cbcee37e..6af7034d74 100644 --- a/fq_sparse_mat_templates/test/t-concat_vertical.c +++ b/fq_sparse_mat_templates/test/t-concat_vertical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-construct.c b/fq_sparse_mat_templates/test/t-construct.c index df38083a77..347daea151 100644 --- a/fq_sparse_mat_templates/test/t-construct.c +++ b/fq_sparse_mat_templates/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-dense.c b/fq_sparse_mat_templates/test/t-dense.c index b689d697d2..49819c0205 100644 --- a/fq_sparse_mat_templates/test/t-dense.c +++ b/fq_sparse_mat_templates/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-init_clear.c b/fq_sparse_mat_templates/test/t-init_clear.c index 0890402a06..7f8f1833cb 100644 --- a/fq_sparse_mat_templates/test/t-init_clear.c +++ b/fq_sparse_mat_templates/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-inv.c b/fq_sparse_mat_templates/test/t-inv.c index 177084f665..e07bd8e1a6 100644 --- a/fq_sparse_mat_templates/test/t-inv.c +++ b/fq_sparse_mat_templates/test/t-inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-lu.c b/fq_sparse_mat_templates/test/t-lu.c index 2c0d680efc..a00a78aed5 100644 --- a/fq_sparse_mat_templates/test/t-lu.c +++ b/fq_sparse_mat_templates/test/t-lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-mul.c b/fq_sparse_mat_templates/test/t-mul.c index 73145de7dd..46734e6fe2 100644 --- a/fq_sparse_mat_templates/test/t-mul.c +++ b/fq_sparse_mat_templates/test/t-mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-neg.c b/fq_sparse_mat_templates/test/t-neg.c index f7b7562be7..30e6e7679b 100644 --- a/fq_sparse_mat_templates/test/t-neg.c +++ b/fq_sparse_mat_templates/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-nullspace.c b/fq_sparse_mat_templates/test/t-nullspace.c index ff22e2d7f1..f73dbc8eea 100644 --- a/fq_sparse_mat_templates/test/t-nullspace.c +++ b/fq_sparse_mat_templates/test/t-nullspace.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-rref.c b/fq_sparse_mat_templates/test/t-rref.c index 7129698843..2debca9ba0 100644 --- a/fq_sparse_mat_templates/test/t-rref.c +++ b/fq_sparse_mat_templates/test/t-rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-scalar_mul.c b/fq_sparse_mat_templates/test/t-scalar_mul.c index 0c1b8a5513..8708840ddb 100644 --- a/fq_sparse_mat_templates/test/t-scalar_mul.c +++ b/fq_sparse_mat_templates/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-solve.c b/fq_sparse_mat_templates/test/t-solve.c index 27bfbb9bed..92c37dffa3 100644 --- a/fq_sparse_mat_templates/test/t-solve.c +++ b/fq_sparse_mat_templates/test/t-solve.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/test/t-transpose.c b/fq_sparse_mat_templates/test/t-transpose.c index b24edf3ffb..5531e548c2 100644 --- a/fq_sparse_mat_templates/test/t-transpose.c +++ b/fq_sparse_mat_templates/test/t-transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_mat_templates/transpose.c b/fq_sparse_mat_templates/transpose.c index f227856165..d07ef9a043 100644 --- a/fq_sparse_mat_templates/transpose.c +++ b/fq_sparse_mat_templates/transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -19,6 +20,7 @@ TEMPLATE(T, sparse_mat_transpose) (TEMPLATE(T, sparse_mat_t) B, const TEMPLATE(T { slong r, c, i, j, *nnz; TEMPLATE(T, sparse_entry_struct) *Ae, *Be; + FLINT_ASSERT(B->r == A->c && A->r == B->c); nnz = flint_calloc(A->c, sizeof(*nnz)); /* Get number of nnzs in each column of A (thus each row of B) */ for (c = 0; c < A->c; ++c) diff --git a/fq_sparse_vec.h b/fq_sparse_vec.h index a1bad275b3..b1dd23f8fe 100644 --- a/fq_sparse_vec.h +++ b/fq_sparse_vec.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/add.c b/fq_sparse_vec/add.c index 7987451e2c..c847a3d8df 100644 --- a/fq_sparse_vec/add.c +++ b/fq_sparse_vec/add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/print_pretty.c b/fq_sparse_vec/print_pretty.c index 97eb13f973..82c54613ee 100644 --- a/fq_sparse_vec/print_pretty.c +++ b/fq_sparse_vec/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/randtest.c b/fq_sparse_vec/randtest.c index 6c07d2930d..5175ad52fb 100644 --- a/fq_sparse_vec/randtest.c +++ b/fq_sparse_vec/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/scalar_addmul.c b/fq_sparse_vec/scalar_addmul.c index 56bdb15ba6..443abc13b4 100644 --- a/fq_sparse_vec/scalar_addmul.c +++ b/fq_sparse_vec/scalar_addmul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/scalar_submul.c b/fq_sparse_vec/scalar_submul.c index 72924b1f11..18e0dcd76b 100644 --- a/fq_sparse_vec/scalar_submul.c +++ b/fq_sparse_vec/scalar_submul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/sub.c b/fq_sparse_vec/sub.c index 2658de6cd3..b29094bbd8 100644 --- a/fq_sparse_vec/sub.c +++ b/fq_sparse_vec/sub.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-add.c b/fq_sparse_vec/test/t-add.c index 00dfacf628..a88651ab39 100644 --- a/fq_sparse_vec/test/t-add.c +++ b/fq_sparse_vec/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-concat.c b/fq_sparse_vec/test/t-concat.c index 08fae5b5a4..92b2860a58 100644 --- a/fq_sparse_vec/test/t-concat.c +++ b/fq_sparse_vec/test/t-concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-construct.c b/fq_sparse_vec/test/t-construct.c index 95c23a936e..6d6b888664 100644 --- a/fq_sparse_vec/test/t-construct.c +++ b/fq_sparse_vec/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-dense.c b/fq_sparse_vec/test/t-dense.c index a00caa371e..9aea544724 100644 --- a/fq_sparse_vec/test/t-dense.c +++ b/fq_sparse_vec/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-dot.c b/fq_sparse_vec/test/t-dot.c index 4af6321c57..90b92211fb 100644 --- a/fq_sparse_vec/test/t-dot.c +++ b/fq_sparse_vec/test/t-dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-init_clear.c b/fq_sparse_vec/test/t-init_clear.c index b2e4095cb7..7b8da28369 100644 --- a/fq_sparse_vec/test/t-init_clear.c +++ b/fq_sparse_vec/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-neg.c b/fq_sparse_vec/test/t-neg.c index 1fed5ea23a..8b2c6cfaae 100644 --- a/fq_sparse_vec/test/t-neg.c +++ b/fq_sparse_vec/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec/test/t-scalar_mul.c b/fq_sparse_vec/test/t-scalar_mul.c index 1bda15e955..d62fac011d 100644 --- a/fq_sparse_vec/test/t-scalar_mul.c +++ b/fq_sparse_vec/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates.h b/fq_sparse_vec_templates.h index faf88f6e08..5488870712 100644 --- a/fq_sparse_vec_templates.h +++ b/fq_sparse_vec_templates.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -71,6 +72,7 @@ void _TEMPLATE(T, sparse_vec_resize)(TEMPLATE(T, sparse_vec_t) vec, slong nnz, const TEMPLATE(T, ctx_t) ctx) { slong i; + FLINT_ASSERT(nnz >= 0); if (nnz == 0) TEMPLATE(T, sparse_vec_clear) (vec, ctx); else if (nnz != vec->nnz) { @@ -83,6 +85,22 @@ void _TEMPLATE(T, sparse_vec_resize)(TEMPLATE(T, sparse_vec_t) vec, slong nnz, vec->nnz = nnz; } +FQ_SPARSE_VEC_TEMPLATES_INLINE +void TEMPLATE(T, sparse_vec_resize)(TEMPLATE(T, sparse_vec_t) vec, slong cols, + const TEMPLATE(T, ctx_t) ctx) +{ + slong i; + FLINT_ASSERT(cols >= 0); + if (vec->nnz == 0) return; + for (i = 0; i < vec->nnz; ++i) { + if (vec->entries[i].ind >= cols) + { + break; + } + } + _TEMPLATE(T, sparse_vec_resize)(vec, i, ctx); +} + FQ_SPARSE_VEC_TEMPLATES_INLINE void TEMPLATE(T, sparse_vec_swap)(TEMPLATE(T, sparse_vec_t) vec1, TEMPLATE(T, sparse_vec_t) vec2, const TEMPLATE(T, ctx_t) ctx) diff --git a/fq_sparse_vec_templates/add.c b/fq_sparse_vec_templates/add.c index 7173bd166a..9a611bd702 100644 --- a/fq_sparse_vec_templates/add.c +++ b/fq_sparse_vec_templates/add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/print_pretty.c b/fq_sparse_vec_templates/print_pretty.c index 453a5f0c14..213feff8dd 100644 --- a/fq_sparse_vec_templates/print_pretty.c +++ b/fq_sparse_vec_templates/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/randtest.c b/fq_sparse_vec_templates/randtest.c index d4eaa37447..368a3c2aa6 100644 --- a/fq_sparse_vec_templates/randtest.c +++ b/fq_sparse_vec_templates/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/scalar_addmul.c b/fq_sparse_vec_templates/scalar_addmul.c index 016efd88e5..c05bbb1e3f 100644 --- a/fq_sparse_vec_templates/scalar_addmul.c +++ b/fq_sparse_vec_templates/scalar_addmul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/scalar_submul.c b/fq_sparse_vec_templates/scalar_submul.c index 181cbff605..77b4bc89dc 100644 --- a/fq_sparse_vec_templates/scalar_submul.c +++ b/fq_sparse_vec_templates/scalar_submul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/sub.c b/fq_sparse_vec_templates/sub.c index 19990f47d4..1dc625c36b 100644 --- a/fq_sparse_vec_templates/sub.c +++ b/fq_sparse_vec_templates/sub.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-add.c b/fq_sparse_vec_templates/test/t-add.c index 067d6a35a1..dee40647f5 100644 --- a/fq_sparse_vec_templates/test/t-add.c +++ b/fq_sparse_vec_templates/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-concat.c b/fq_sparse_vec_templates/test/t-concat.c index fe29ba04cb..bd9fee8924 100644 --- a/fq_sparse_vec_templates/test/t-concat.c +++ b/fq_sparse_vec_templates/test/t-concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-construct.c b/fq_sparse_vec_templates/test/t-construct.c index f7f983b3c2..e1b956805a 100644 --- a/fq_sparse_vec_templates/test/t-construct.c +++ b/fq_sparse_vec_templates/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-dense.c b/fq_sparse_vec_templates/test/t-dense.c index 23f3f27a97..9ff08d030d 100644 --- a/fq_sparse_vec_templates/test/t-dense.c +++ b/fq_sparse_vec_templates/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-dot.c b/fq_sparse_vec_templates/test/t-dot.c index d83ff86d19..f7714b43d7 100644 --- a/fq_sparse_vec_templates/test/t-dot.c +++ b/fq_sparse_vec_templates/test/t-dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-init_clear.c b/fq_sparse_vec_templates/test/t-init_clear.c index 61a32ea3f8..01145bd904 100644 --- a/fq_sparse_vec_templates/test/t-init_clear.c +++ b/fq_sparse_vec_templates/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-neg.c b/fq_sparse_vec_templates/test/t-neg.c index f183c53612..0819d6bec3 100644 --- a/fq_sparse_vec_templates/test/t-neg.c +++ b/fq_sparse_vec_templates/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_sparse_vec_templates/test/t-scalar_mul.c b/fq_sparse_vec_templates/test/t-scalar_mul.c index d12d47d922..35e936f68b 100644 --- a/fq_sparse_vec_templates/test/t-scalar_mul.c +++ b/fq_sparse_vec_templates/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* - wopyright (w) 2011 Fredrik Johansson + Copyright (w) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat.h b/fq_zech_sparse_mat.h index 50de22b788..e6f79c5514 100644 --- a/fq_zech_sparse_mat.h +++ b/fq_zech_sparse_mat.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/from_entries.c b/fq_zech_sparse_mat/from_entries.c index cf823fe825..b77e12696e 100644 --- a/fq_zech_sparse_mat/from_entries.c +++ b/fq_zech_sparse_mat/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/inv.c b/fq_zech_sparse_mat/inv.c index e2915a21d6..a408e8b990 100644 --- a/fq_zech_sparse_mat/inv.c +++ b/fq_zech_sparse_mat/inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/lu.c b/fq_zech_sparse_mat/lu.c index ce3856921a..155df51f22 100644 --- a/fq_zech_sparse_mat/lu.c +++ b/fq_zech_sparse_mat/lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_block_lanczos.c b/fq_zech_sparse_mat/nullspace_block_lanczos.c index dfe4bf1ccb..432d782b3e 100644 --- a/fq_zech_sparse_mat/nullspace_block_lanczos.c +++ b/fq_zech_sparse_mat/nullspace_block_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_block_wiedemann.c b/fq_zech_sparse_mat/nullspace_block_wiedemann.c index 873b0a4b9c..3e90244b4a 100644 --- a/fq_zech_sparse_mat/nullspace_block_wiedemann.c +++ b/fq_zech_sparse_mat/nullspace_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_lanczos.c b/fq_zech_sparse_mat/nullspace_lanczos.c index 186d8efbad..0677b1c8a2 100644 --- a/fq_zech_sparse_mat/nullspace_lanczos.c +++ b/fq_zech_sparse_mat/nullspace_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_lu.c b/fq_zech_sparse_mat/nullspace_lu.c index 9622c8ac02..371d4b4464 100644 --- a/fq_zech_sparse_mat/nullspace_lu.c +++ b/fq_zech_sparse_mat/nullspace_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_rref.c b/fq_zech_sparse_mat/nullspace_rref.c index ef4a781520..2aa60ad53f 100644 --- a/fq_zech_sparse_mat/nullspace_rref.c +++ b/fq_zech_sparse_mat/nullspace_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/nullspace_wiedemann.c b/fq_zech_sparse_mat/nullspace_wiedemann.c index cab43b28b2..8545d09605 100644 --- a/fq_zech_sparse_mat/nullspace_wiedemann.c +++ b/fq_zech_sparse_mat/nullspace_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/print_pretty.c b/fq_zech_sparse_mat/print_pretty.c index f4d091fc8a..2a37fce791 100644 --- a/fq_zech_sparse_mat/print_pretty.c +++ b/fq_zech_sparse_mat/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/randtest.c b/fq_zech_sparse_mat/randtest.c index 6ce2a2f0be..5c8144874d 100644 --- a/fq_zech_sparse_mat/randtest.c +++ b/fq_zech_sparse_mat/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/rref.c b/fq_zech_sparse_mat/rref.c index cdbbeac30a..42cde0c19b 100644 --- a/fq_zech_sparse_mat/rref.c +++ b/fq_zech_sparse_mat/rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/solve_block_lanczos.c b/fq_zech_sparse_mat/solve_block_lanczos.c index 0fe1013eff..9f08f70926 100644 --- a/fq_zech_sparse_mat/solve_block_lanczos.c +++ b/fq_zech_sparse_mat/solve_block_lanczos.c @@ -1,11 +1,10 @@ /* + Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 Kartik Venkatram Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 - Copyright (C) 2010 Fredrik Johansson - This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under diff --git a/fq_zech_sparse_mat/solve_block_wiedemann.c b/fq_zech_sparse_mat/solve_block_wiedemann.c index aa56921df6..9004ad97e9 100644 --- a/fq_zech_sparse_mat/solve_block_wiedemann.c +++ b/fq_zech_sparse_mat/solve_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/solve_lanczos.c b/fq_zech_sparse_mat/solve_lanczos.c index 5a896d9309..58a88db3c7 100644 --- a/fq_zech_sparse_mat/solve_lanczos.c +++ b/fq_zech_sparse_mat/solve_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/solve_lu.c b/fq_zech_sparse_mat/solve_lu.c index 15685f8902..3569a870e9 100644 --- a/fq_zech_sparse_mat/solve_lu.c +++ b/fq_zech_sparse_mat/solve_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/solve_rref.c b/fq_zech_sparse_mat/solve_rref.c index ddb496768b..5691dde7af 100644 --- a/fq_zech_sparse_mat/solve_rref.c +++ b/fq_zech_sparse_mat/solve_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/solve_wiedemann.c b/fq_zech_sparse_mat/solve_wiedemann.c index 0fedb0e65a..c47c3741fa 100644 --- a/fq_zech_sparse_mat/solve_wiedemann.c +++ b/fq_zech_sparse_mat/solve_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-add.c b/fq_zech_sparse_mat/test/t-add.c index 7da2fdb588..783d295204 100644 --- a/fq_zech_sparse_mat/test/t-add.c +++ b/fq_zech_sparse_mat/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-concat_horizontal.c b/fq_zech_sparse_mat/test/t-concat_horizontal.c index 1d53c5f725..f3ee3eba0e 100644 --- a/fq_zech_sparse_mat/test/t-concat_horizontal.c +++ b/fq_zech_sparse_mat/test/t-concat_horizontal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-concat_vertical.c b/fq_zech_sparse_mat/test/t-concat_vertical.c index 8ef02c7014..d178c4047e 100644 --- a/fq_zech_sparse_mat/test/t-concat_vertical.c +++ b/fq_zech_sparse_mat/test/t-concat_vertical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-construct.c b/fq_zech_sparse_mat/test/t-construct.c index 04ce82c08b..d27df5fc1f 100644 --- a/fq_zech_sparse_mat/test/t-construct.c +++ b/fq_zech_sparse_mat/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-dense.c b/fq_zech_sparse_mat/test/t-dense.c index f5397ecb4d..38269a46f5 100644 --- a/fq_zech_sparse_mat/test/t-dense.c +++ b/fq_zech_sparse_mat/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-init_clear.c b/fq_zech_sparse_mat/test/t-init_clear.c index 00e1aacd13..5f9fe8ef63 100644 --- a/fq_zech_sparse_mat/test/t-init_clear.c +++ b/fq_zech_sparse_mat/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-inv.c b/fq_zech_sparse_mat/test/t-inv.c index 0866c19b0c..7f1d3f10cb 100644 --- a/fq_zech_sparse_mat/test/t-inv.c +++ b/fq_zech_sparse_mat/test/t-inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-lu.c b/fq_zech_sparse_mat/test/t-lu.c index 77a7087b1d..5e859d59fa 100644 --- a/fq_zech_sparse_mat/test/t-lu.c +++ b/fq_zech_sparse_mat/test/t-lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-mul.c b/fq_zech_sparse_mat/test/t-mul.c index efb364c74b..542761741e 100644 --- a/fq_zech_sparse_mat/test/t-mul.c +++ b/fq_zech_sparse_mat/test/t-mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-neg.c b/fq_zech_sparse_mat/test/t-neg.c index 67a9750a55..66520ae447 100644 --- a/fq_zech_sparse_mat/test/t-neg.c +++ b/fq_zech_sparse_mat/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-nullspace.c b/fq_zech_sparse_mat/test/t-nullspace.c index f0e78cd489..58be848415 100644 --- a/fq_zech_sparse_mat/test/t-nullspace.c +++ b/fq_zech_sparse_mat/test/t-nullspace.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-rref.c b/fq_zech_sparse_mat/test/t-rref.c index c8a9abc0fe..b84a2bfa95 100644 --- a/fq_zech_sparse_mat/test/t-rref.c +++ b/fq_zech_sparse_mat/test/t-rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-scalar_mul.c b/fq_zech_sparse_mat/test/t-scalar_mul.c index 2223d641e9..7166cfecfc 100644 --- a/fq_zech_sparse_mat/test/t-scalar_mul.c +++ b/fq_zech_sparse_mat/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-solve.c b/fq_zech_sparse_mat/test/t-solve.c index 8ba6081629..24f27df969 100644 --- a/fq_zech_sparse_mat/test/t-solve.c +++ b/fq_zech_sparse_mat/test/t-solve.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/test/t-transpose.c b/fq_zech_sparse_mat/test/t-transpose.c index 5ca1c4d587..8d474043aa 100644 --- a/fq_zech_sparse_mat/test/t-transpose.c +++ b/fq_zech_sparse_mat/test/t-transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_mat/transpose.c b/fq_zech_sparse_mat/transpose.c index 9e1ce8d711..c6d2fec1fd 100644 --- a/fq_zech_sparse_mat/transpose.c +++ b/fq_zech_sparse_mat/transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec.h b/fq_zech_sparse_vec.h index 3e26cc940b..b538e22721 100644 --- a/fq_zech_sparse_vec.h +++ b/fq_zech_sparse_vec.h @@ -1,5 +1,6 @@ /* Copyright (C) 2013 Mike Hansen + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/add.c b/fq_zech_sparse_vec/add.c index 628c65dcc2..a291ea8727 100644 --- a/fq_zech_sparse_vec/add.c +++ b/fq_zech_sparse_vec/add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/print_pretty.c b/fq_zech_sparse_vec/print_pretty.c index 1f9451e311..34009b3ae5 100644 --- a/fq_zech_sparse_vec/print_pretty.c +++ b/fq_zech_sparse_vec/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/randtest.c b/fq_zech_sparse_vec/randtest.c index db642232b9..14f33eb61d 100644 --- a/fq_zech_sparse_vec/randtest.c +++ b/fq_zech_sparse_vec/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/scalar_addmul.c b/fq_zech_sparse_vec/scalar_addmul.c index 1baaef6f9d..aa00297f87 100644 --- a/fq_zech_sparse_vec/scalar_addmul.c +++ b/fq_zech_sparse_vec/scalar_addmul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/scalar_submul.c b/fq_zech_sparse_vec/scalar_submul.c index f5bc3d54f6..28cfc80475 100644 --- a/fq_zech_sparse_vec/scalar_submul.c +++ b/fq_zech_sparse_vec/scalar_submul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/sub.c b/fq_zech_sparse_vec/sub.c index 2bf5a62707..f0d0fc2d3b 100644 --- a/fq_zech_sparse_vec/sub.c +++ b/fq_zech_sparse_vec/sub.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-add.c b/fq_zech_sparse_vec/test/t-add.c index 4f1d749ead..96d3f27408 100644 --- a/fq_zech_sparse_vec/test/t-add.c +++ b/fq_zech_sparse_vec/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-concat.c b/fq_zech_sparse_vec/test/t-concat.c index 5d788bc0f6..041ac0be20 100644 --- a/fq_zech_sparse_vec/test/t-concat.c +++ b/fq_zech_sparse_vec/test/t-concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-construct.c b/fq_zech_sparse_vec/test/t-construct.c index 9b5a886c96..96f77b9a85 100644 --- a/fq_zech_sparse_vec/test/t-construct.c +++ b/fq_zech_sparse_vec/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-dense.c b/fq_zech_sparse_vec/test/t-dense.c index 16ed02a415..ebf9a7513c 100644 --- a/fq_zech_sparse_vec/test/t-dense.c +++ b/fq_zech_sparse_vec/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-dot.c b/fq_zech_sparse_vec/test/t-dot.c index 57846654dd..e91ac6ba1e 100644 --- a/fq_zech_sparse_vec/test/t-dot.c +++ b/fq_zech_sparse_vec/test/t-dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-init_clear.c b/fq_zech_sparse_vec/test/t-init_clear.c index 3b0af13dd9..02c3ec966a 100644 --- a/fq_zech_sparse_vec/test/t-init_clear.c +++ b/fq_zech_sparse_vec/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-neg.c b/fq_zech_sparse_vec/test/t-neg.c index a234501817..6e014f89c3 100644 --- a/fq_zech_sparse_vec/test/t-neg.c +++ b/fq_zech_sparse_vec/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/fq_zech_sparse_vec/test/t-scalar_mul.c b/fq_zech_sparse_vec/test/t-scalar_mul.c index 23aec9e2ad..35d652fa68 100644 --- a/fq_zech_sparse_vec/test/t-scalar_mul.c +++ b/fq_zech_sparse_vec/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* - wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 274f129e20..8cf452c155 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -56,6 +57,7 @@ typedef nmod_sparse_mat_struct nmod_sparse_mat_t[1]; NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_init(nmod_sparse_mat_t M, slong rows, slong cols, nmod_t mod) { + FLINT_ASSERT(rows >= 0 && cols >= 0); M->rows = flint_calloc(rows, sizeof(*M->rows)); M->r = rows; M->c = cols; @@ -72,6 +74,36 @@ void nmod_sparse_mat_clear(nmod_sparse_mat_t M) memset(M, 0, sizeof(*M)); } +NMOD_SPARSE_MAT_INLINE +void nmod_sparse_mat_resize (nmod_sparse_mat_t M, slong rows, slong cols) +{ + slong i; + FLINT_ASSERT(rows >= 0 && cols >= 0); + if (M->r != rows) { + if (M->r > rows) + { + for (i = rows; i < M->r; ++i) + { + nmod_sparse_vec_clear(&M->rows[i]); + } + } + M->rows = flint_realloc(M->rows, rows*sizeof(*M->rows)); + if (M->r < rows) + { + memset(M->rows+M->r, 0, (rows-M->r)*sizeof(*M->rows)); + } + M->r = rows; + } + if (cols < M->c) + { + for (i = 0; i < M->r; ++i) + { + nmod_sparse_vec_resize(&M->rows[i], cols); + } + } + M->c = cols; +} + NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_swap(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2) { @@ -150,7 +182,6 @@ void nmod_sparse_mat_window_clear(nmod_sparse_mat_t W) /* Combine M1 and M2 into block matrix B = [M1 M2] */ /* B->r must equal M1->r and M2->r */ -<<<<<<< HEAD NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) @@ -171,8 +202,6 @@ void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_ for (i = M1->r; i < B->r; ++i) nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); } -<<<<<<< HEAD -<<<<<<< HEAD /* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ /* M1->r and M2->r must equal B->r */ @@ -311,6 +340,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) { slong i; + FLINT_ASSERT(M->r == N->r); nmod_sparse_mat_set(N, M); for (i = 0; i < N->r; ++i) nmod_sparse_vec_neg(&N->rows[i], &N->rows[i], N->mod); } @@ -318,6 +348,7 @@ void nmod_sparse_mat_neg(nmod_sparse_mat_t N, const nmod_sparse_mat_t M) NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) { + FLINT_ASSERT(M->r == N->r); if (c == UWORD(0)) nmod_sparse_mat_zero(N); else { slong i; @@ -341,6 +372,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, const fmpz_t c) { fmpz_t d; + FLINT_ASSERT(M->r == N->r); fmpz_init(d); fmpz_mod_ui(d, c, N->mod.n); nmod_sparse_mat_scalar_mul_nmod(N, M, fmpz_get_ui(d)); @@ -350,6 +382,7 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) nmod_sparse_vec_add(&O->rows[i], &M->rows[i], &N->rows[i], O->mod); } @@ -357,13 +390,15 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_sub(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; - for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); + FLINT_ASSERT(O->r == M->r && O->r == N->r); + for (i = 0; i < O->r; ++i) nmod_sparse_vec_sub(&O->rows[i], &M->rows[i], &N->rows[i], O->mod); } NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_addmul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_addmul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } @@ -371,6 +406,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N, mp_limb_t c) { slong i; + FLINT_ASSERT(O->r == M->r && O->r == N->r); for (i = 0; i < O->r; ++i) nmod_sparse_vec_scalar_submul_nmod(&O->rows[i], &M->rows[i], &N->rows[i], c, O->mod); } @@ -385,6 +421,7 @@ NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod_mat_t X) { slong i, j; + FLINT_ASSERT(M->r == Y->r && M->c == X->r && X->c == Y->c); nmod_mat_zero(Y); for (i = 0; i < M->r; ++i) { @@ -396,11 +433,6 @@ void nmod_sparse_mat_mul_mat(nmod_mat_t Y, const nmod_sparse_mat_t M, const nmod } } -<<<<<<< HEAD -<<<<<<< HEAD -FLINT_DLL -slong nmod_sparse_mat_inv(nmod_sparse_mat_t Ai, const nmod_sparse_mat_t M); -======= /* Permutations */ /* FLINT_DLL void nmod_sparse_mat_swap_rows(nmod_sparse_mat_t M, slong * perm, slong r, slong s); FLINT_DLL void nmod_sparse_mat_invert_rows(nmod_sparse_mat_t M, slong * perm); diff --git a/nmod_sparse_mat/det.c b/nmod_sparse_mat/det.c index 8021e371bf..1b8b7e7c03 100644 --- a/nmod_sparse_mat/det.c +++ b/nmod_sparse_mat/det.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -23,11 +24,7 @@ nmod_sparse_mat_det(const nmod_sparse_mat_t M) slong *P, *Q; mp_limb_t det; nmod_sparse_mat_t L, U; - if (M->r != M->c) - { - flint_printf("Exception (nmod_mat_det). Non-square matrix.\n"); - flint_abort(); - } + FLINT_ASSERT(M->r == M->c); if (M->r == 0) return UWORD(1); if (nmod_sparse_mat_is_zero(M)) return UWORD(0); diff --git a/nmod_sparse_mat/from_entries.c b/nmod_sparse_mat/from_entries.c index 2c83f6511e..96f1cc5952 100644 --- a/nmod_sparse_mat/from_entries.c +++ b/nmod_sparse_mat/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/howell_form.c b/nmod_sparse_mat/howell_form.c index 2bafcb8dc9..cba8fc4bce 100644 --- a/nmod_sparse_mat/howell_form.c +++ b/nmod_sparse_mat/howell_form.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/inv.c b/nmod_sparse_mat/inv.c index faf4438621..b6737d0459 100644 --- a/nmod_sparse_mat/inv.c +++ b/nmod_sparse_mat/inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/lu.c b/nmod_sparse_mat/lu.c index 0e894fe0c7..125cfcc23b 100644 --- a/nmod_sparse_mat/lu.c +++ b/nmod_sparse_mat/lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_block_lanczos.c b/nmod_sparse_mat/nullspace_block_lanczos.c index e8c6e352dc..8a7f578b9f 100644 --- a/nmod_sparse_mat/nullspace_block_lanczos.c +++ b/nmod_sparse_mat/nullspace_block_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_block_wiedemann.c b/nmod_sparse_mat/nullspace_block_wiedemann.c index d8b5c30ace..9ee3d8da43 100644 --- a/nmod_sparse_mat/nullspace_block_wiedemann.c +++ b/nmod_sparse_mat/nullspace_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_lanczos.c b/nmod_sparse_mat/nullspace_lanczos.c index 0f5a9e0335..0a69c496e2 100644 --- a/nmod_sparse_mat/nullspace_lanczos.c +++ b/nmod_sparse_mat/nullspace_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_lu.c b/nmod_sparse_mat/nullspace_lu.c index 3a571bf7f4..0f26b407a4 100644 --- a/nmod_sparse_mat/nullspace_lu.c +++ b/nmod_sparse_mat/nullspace_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_rref.c b/nmod_sparse_mat/nullspace_rref.c index defc31b100..17ea68ab3e 100644 --- a/nmod_sparse_mat/nullspace_rref.c +++ b/nmod_sparse_mat/nullspace_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/nullspace_wiedemann.c b/nmod_sparse_mat/nullspace_wiedemann.c index c6c3b8a0a3..83c65fef3d 100644 --- a/nmod_sparse_mat/nullspace_wiedemann.c +++ b/nmod_sparse_mat/nullspace_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/print_pretty.c b/nmod_sparse_mat/print_pretty.c index 00ba167283..9f058c764c 100644 --- a/nmod_sparse_mat/print_pretty.c +++ b/nmod_sparse_mat/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/randtest.c b/nmod_sparse_mat/randtest.c index afbbd2275a..3948ecfa7d 100644 --- a/nmod_sparse_mat/randtest.c +++ b/nmod_sparse_mat/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/rref.c b/nmod_sparse_mat/rref.c index 6376a9539c..7ddd7bbcde 100644 --- a/nmod_sparse_mat/rref.c +++ b/nmod_sparse_mat/rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/solve_block_lanczos.c b/nmod_sparse_mat/solve_block_lanczos.c index 37f0b7ba86..402a8075e9 100644 --- a/nmod_sparse_mat/solve_block_lanczos.c +++ b/nmod_sparse_mat/solve_block_lanczos.c @@ -1,11 +1,10 @@ /* + Copyright (C) 2010 Fredrik Johansson Copyright (C) 2020 Kartik Venkatram Algorithm taken from P. Montgomery, "A Block Lanczos Algorithm for Finding Dependencies over GF(2)", Advances in Cryptology - EUROCRYPT '95 - Copyright (C) 2010 Fredrik Johansson - This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under diff --git a/nmod_sparse_mat/solve_block_wiedemann.c b/nmod_sparse_mat/solve_block_wiedemann.c index ab68719ddb..45422cc18d 100644 --- a/nmod_sparse_mat/solve_block_wiedemann.c +++ b/nmod_sparse_mat/solve_block_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/solve_lanczos.c b/nmod_sparse_mat/solve_lanczos.c index 0b08e35543..961aa808cc 100644 --- a/nmod_sparse_mat/solve_lanczos.c +++ b/nmod_sparse_mat/solve_lanczos.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/solve_lu.c b/nmod_sparse_mat/solve_lu.c index 438e86acf8..173606852c 100644 --- a/nmod_sparse_mat/solve_lu.c +++ b/nmod_sparse_mat/solve_lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/solve_rref.c b/nmod_sparse_mat/solve_rref.c index db8d1df34b..1044ac6faf 100644 --- a/nmod_sparse_mat/solve_rref.c +++ b/nmod_sparse_mat/solve_rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/solve_wiedemann.c b/nmod_sparse_mat/solve_wiedemann.c index 5c0d40b92e..2d4329c799 100644 --- a/nmod_sparse_mat/solve_wiedemann.c +++ b/nmod_sparse_mat/solve_wiedemann.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/strong_echelon_form.c b/nmod_sparse_mat/strong_echelon_form.c index 1f9ec5bc7c..25bed4b5b3 100644 --- a/nmod_sparse_mat/strong_echelon_form.c +++ b/nmod_sparse_mat/strong_echelon_form.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Tommy Hofmann + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-add.c b/nmod_sparse_mat/test/t-add.c index b298df7332..665ba53ec3 100644 --- a/nmod_sparse_mat/test/t-add.c +++ b/nmod_sparse_mat/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-concat_horizontal.c b/nmod_sparse_mat/test/t-concat_horizontal.c index a2b26bd4af..4190aa517d 100644 --- a/nmod_sparse_mat/test/t-concat_horizontal.c +++ b/nmod_sparse_mat/test/t-concat_horizontal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-concat_vertical.c b/nmod_sparse_mat/test/t-concat_vertical.c index 5f61d34c6e..e8c7bde02a 100644 --- a/nmod_sparse_mat/test/t-concat_vertical.c +++ b/nmod_sparse_mat/test/t-concat_vertical.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-construct.c b/nmod_sparse_mat/test/t-construct.c index 88a15093d0..d907484120 100644 --- a/nmod_sparse_mat/test/t-construct.c +++ b/nmod_sparse_mat/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-dense.c b/nmod_sparse_mat/test/t-dense.c index ba167bc754..a051befba0 100644 --- a/nmod_sparse_mat/test/t-dense.c +++ b/nmod_sparse_mat/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-init_clear.c b/nmod_sparse_mat/test/t-init_clear.c index 913e56c30a..079877e87b 100644 --- a/nmod_sparse_mat/test/t-init_clear.c +++ b/nmod_sparse_mat/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -20,7 +21,7 @@ int main(void) { - slong rep, r, c, i; + slong rep, r, r2, c, i; mp_limb_t n; nmod_t mod; nmod_sparse_mat_t A; @@ -33,6 +34,7 @@ main(void) for (rep = 0; rep < 100; rep++) { r = n_randint(state, 200); + r2 = n_randint(state, 200); c = n_randint(state, 200); do n = n_randtest_not_zero(state); while (n == UWORD(1)); @@ -52,6 +54,7 @@ main(void) abort(); } } + nmod_sparse_mat_clear(A); } diff --git a/nmod_sparse_mat/test/t-inv.c b/nmod_sparse_mat/test/t-inv.c index 2599e18bef..2df2d0c7f0 100644 --- a/nmod_sparse_mat/test/t-inv.c +++ b/nmod_sparse_mat/test/t-inv.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-lu.c b/nmod_sparse_mat/test/t-lu.c index 4a99bf4302..03aa3f29b6 100644 --- a/nmod_sparse_mat/test/t-lu.c +++ b/nmod_sparse_mat/test/t-lu.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-mul.c b/nmod_sparse_mat/test/t-mul.c index 550cd18dd3..1fca229f3f 100644 --- a/nmod_sparse_mat/test/t-mul.c +++ b/nmod_sparse_mat/test/t-mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-neg.c b/nmod_sparse_mat/test/t-neg.c index 8961c42dec..38b07d63ad 100644 --- a/nmod_sparse_mat/test/t-neg.c +++ b/nmod_sparse_mat/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-nullspace.c b/nmod_sparse_mat/test/t-nullspace.c index d704fdeea2..e5191c09cc 100644 --- a/nmod_sparse_mat/test/t-nullspace.c +++ b/nmod_sparse_mat/test/t-nullspace.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-rref.c b/nmod_sparse_mat/test/t-rref.c index 5ff22bd85d..be8c071794 100644 --- a/nmod_sparse_mat/test/t-rref.c +++ b/nmod_sparse_mat/test/t-rref.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-scalar_mul.c b/nmod_sparse_mat/test/t-scalar_mul.c index a38f634d2e..f861934b8b 100644 --- a/nmod_sparse_mat/test/t-scalar_mul.c +++ b/nmod_sparse_mat/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-solve.c b/nmod_sparse_mat/test/t-solve.c index 9c87f2b960..7e5a64ae69 100644 --- a/nmod_sparse_mat/test/t-solve.c +++ b/nmod_sparse_mat/test/t-solve.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/test/t-transpose.c b/nmod_sparse_mat/test/t-transpose.c index f87c3fb53b..26b273b517 100644 --- a/nmod_sparse_mat/test/t-transpose.c +++ b/nmod_sparse_mat/test/t-transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_mat/transpose.c b/nmod_sparse_mat/transpose.c index 1e2dd3f30d..bf1e8d8fe8 100644 --- a/nmod_sparse_mat/transpose.c +++ b/nmod_sparse_mat/transpose.c @@ -1,5 +1,6 @@ /* Copyright (C) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -21,6 +22,8 @@ nmod_sparse_mat_transpose(nmod_sparse_mat_t B, const nmod_sparse_mat_t A) slong r, c, i, j; nmod_sparse_entry_struct *Ae, *Be; nmod_sparse_vec_struct *row; + FLINT_ASSERT(M->r == A->c); + FLINT_ASSERT(A->r == M->c); /* Get number of nnzs in each column of A (thus each row of B) */ for (c = 0; c < A->c; ++c) diff --git a/nmod_sparse_vec.h b/nmod_sparse_vec.h index 4c59a7ce6e..cfc0d0648c 100644 --- a/nmod_sparse_vec.h +++ b/nmod_sparse_vec.h @@ -2,6 +2,7 @@ Copyright (C) 2010 William Hart Copyright (C) 2010,2011 Fredrik Johansson Copyright (C) 2014 Ashish Kedia + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. @@ -76,6 +77,35 @@ void nmod_sparse_vec_clear(nmod_sparse_vec_t vec) flint_free(vec->entries); memset(vec, 0, sizeof(*vec)); } + +NMOD_SPARSE_VEC_INLINE +void _nmod_sparse_vec_resize(nmod_sparse_vec_t vec, slong nnz) +{ + FLINT_ASSERT(nnz >= 0); + if (nnz == 0) nmod_sparse_vec_clear(vec); + else if (nnz != vec->nnz) + { + vec->entries = flint_realloc(vec->entries, nnz*sizeof(*vec->entries)); + } + vec->nnz = nnz; +} + +NMOD_SPARSE_VEC_INLINE +void nmod_sparse_vec_resize(nmod_sparse_vec_t vec, slong cols) +{ + slong i; + FLINT_ASSERT(cols >= 0); + if (vec->nnz == 0) return; + for (i = 0; i < vec->nnz; ++i) { + if (vec->entries[i].ind >= cols) + { + break; + } + } + _nmod_sparse_vec_resize(vec, i); +} + + NMOD_SPARSE_VEC_INLINE void nmod_sparse_vec_swap(nmod_sparse_vec_t vec1, nmod_sparse_vec_t vec2) { diff --git a/nmod_sparse_vec/add.c b/nmod_sparse_vec/add.c index af85da0198..173c4b6d6d 100644 --- a/nmod_sparse_vec/add.c +++ b/nmod_sparse_vec/add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/at.c b/nmod_sparse_vec/at.c index e2e145294b..b7d385c555 100644 --- a/nmod_sparse_vec/at.c +++ b/nmod_sparse_vec/at.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/concat.c b/nmod_sparse_vec/concat.c index fedaabe317..0257fd6245 100644 --- a/nmod_sparse_vec/concat.c +++ b/nmod_sparse_vec/concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/dot.c b/nmod_sparse_vec/dot.c index f640e7827e..47876c1dc4 100644 --- a/nmod_sparse_vec/dot.c +++ b/nmod_sparse_vec/dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/dot_dense.c b/nmod_sparse_vec/dot_dense.c index 835e56e579..dfa7bce0fa 100644 --- a/nmod_sparse_vec/dot_dense.c +++ b/nmod_sparse_vec/dot_dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/equal.c b/nmod_sparse_vec/equal.c index 7d4cc036a7..1c1ae4d4b0 100644 --- a/nmod_sparse_vec/equal.c +++ b/nmod_sparse_vec/equal.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/from_dense.c b/nmod_sparse_vec/from_dense.c index 00c0be2798..57eceaf51d 100644 --- a/nmod_sparse_vec/from_dense.c +++ b/nmod_sparse_vec/from_dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/from_entries.c b/nmod_sparse_vec/from_entries.c index 479d3d1d75..dbaa73ebe6 100644 --- a/nmod_sparse_vec/from_entries.c +++ b/nmod_sparse_vec/from_entries.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/print_pretty.c b/nmod_sparse_vec/print_pretty.c index 106fff9da1..46797a3e08 100644 --- a/nmod_sparse_vec/print_pretty.c +++ b/nmod_sparse_vec/print_pretty.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/randtest.c b/nmod_sparse_vec/randtest.c index 9176b3baa4..4004859a1e 100644 --- a/nmod_sparse_vec/randtest.c +++ b/nmod_sparse_vec/randtest.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/scalar_addmul.c b/nmod_sparse_vec/scalar_addmul.c index 8c107973a6..fd4c3c0563 100644 --- a/nmod_sparse_vec/scalar_addmul.c +++ b/nmod_sparse_vec/scalar_addmul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/scalar_mul.c b/nmod_sparse_vec/scalar_mul.c index 03324ab09b..f5391c9b25 100644 --- a/nmod_sparse_vec/scalar_mul.c +++ b/nmod_sparse_vec/scalar_mul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/scalar_submul.c b/nmod_sparse_vec/scalar_submul.c index 2e1c6d396b..3625d175a5 100644 --- a/nmod_sparse_vec/scalar_submul.c +++ b/nmod_sparse_vec/scalar_submul.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/set.c b/nmod_sparse_vec/set.c index a78f588c6a..e469a1fbf9 100644 --- a/nmod_sparse_vec/set.c +++ b/nmod_sparse_vec/set.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/split.c b/nmod_sparse_vec/split.c index af08c7f590..766f4afc7d 100644 --- a/nmod_sparse_vec/split.c +++ b/nmod_sparse_vec/split.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/sub.c b/nmod_sparse_vec/sub.c index 675a034b7d..a88ba18299 100644 --- a/nmod_sparse_vec/sub.c +++ b/nmod_sparse_vec/sub.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-add.c b/nmod_sparse_vec/test/t-add.c index 86c0dc094f..5d819fece4 100644 --- a/nmod_sparse_vec/test/t-add.c +++ b/nmod_sparse_vec/test/t-add.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-concat.c b/nmod_sparse_vec/test/t-concat.c index 9b63ba3759..f57e103e85 100644 --- a/nmod_sparse_vec/test/t-concat.c +++ b/nmod_sparse_vec/test/t-concat.c @@ -1,5 +1,6 @@ /* Copyright (C) 2015 Elena Sergeicheva + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-construct.c b/nmod_sparse_vec/test/t-construct.c index 1345568e47..a7e4381824 100644 --- a/nmod_sparse_vec/test/t-construct.c +++ b/nmod_sparse_vec/test/t-construct.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-dense.c b/nmod_sparse_vec/test/t-dense.c index 49f218f52f..848b4ac62f 100644 --- a/nmod_sparse_vec/test/t-dense.c +++ b/nmod_sparse_vec/test/t-dense.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-dot.c b/nmod_sparse_vec/test/t-dot.c index 7f5ad3aaea..e8c5f9b86f 100644 --- a/nmod_sparse_vec/test/t-dot.c +++ b/nmod_sparse_vec/test/t-dot.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-init_clear.c b/nmod_sparse_vec/test/t-init_clear.c index 1d320b7260..5e0a24b7ca 100644 --- a/nmod_sparse_vec/test/t-init_clear.c +++ b/nmod_sparse_vec/test/t-init_clear.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-neg.c b/nmod_sparse_vec/test/t-neg.c index 70bae31051..bed03d2758 100644 --- a/nmod_sparse_vec/test/t-neg.c +++ b/nmod_sparse_vec/test/t-neg.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/test/t-scalar_mul.c b/nmod_sparse_vec/test/t-scalar_mul.c index 82c51d334c..aefd778f9e 100644 --- a/nmod_sparse_vec/test/t-scalar_mul.c +++ b/nmod_sparse_vec/test/t-scalar_mul.c @@ -1,5 +1,6 @@ /* wopyright (w) 2011 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. diff --git a/nmod_sparse_vec/window_init.c b/nmod_sparse_vec/window_init.c index 34ab51e428..609c6bd6ce 100644 --- a/nmod_sparse_vec/window_init.c +++ b/nmod_sparse_vec/window_init.c @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Fredrik Johansson + Copyright (C) 2020 Kartik Venkatram This file is part of FLINT. From af5c2b58da902e611ef284f88e10c25a2c48d7b5 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 24 May 2021 15:48:43 -0700 Subject: [PATCH 41/42] Removed some duplicate functions, re-added templates to cmake list --- CMakeLists.txt | 2 +- nmod_sparse_mat.h | 66 +++++------------------------------------------ nmod_vec.h | 9 ------- 3 files changed, 7 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e11930006..1693030e2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ set(BUILD_DIRS ) set(TEMPLATE_DIRS - fq_vec_templates fq_mat_templates fq_poly_templates + fq_vec_templates fq_sparse_vec_templates fq_mat_templates fq_sparse_mat_templates fq_poly_templates fq_poly_factor_templates fq_templates ) diff --git a/nmod_sparse_mat.h b/nmod_sparse_mat.h index 8cf452c155..4e1a913cf4 100644 --- a/nmod_sparse_mat.h +++ b/nmod_sparse_mat.h @@ -222,49 +222,8 @@ void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); } -/* res->r must equal mat1->r and mat2->r */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_horizontal(nmod_sparse_mat_t B, - const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) -{ - slong i; - B->c = M1->c + M2->c; - for (i = 0; i < B->r; ++i) - nmod_sparse_vec_concat(&B->rows[i], &M1->rows[i], &M2->rows[i], M1->c); -} -/* Combine M1 and M2 into block matrix B = [M1^t M1^t]^t */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_concat_vertical(nmod_sparse_mat_t B, const nmod_sparse_mat_t M1, const nmod_sparse_mat_t M2) -{ - slong i; - B->c = FLINT_MAX(M1->c, M2->c); - for (i = 0; i < M1->r; ++i) - nmod_sparse_vec_set(&B->rows[i], &M1->rows[i], M1->c_off); - for (i = M1->r; i < B->r; ++i) - nmod_sparse_vec_set(&B->rows[i], &M2->rows[i-M1->r], M2->c_off); -} - -/* Split block matrix B = [M1 M2] into submatrices M1 and M2 */ -/* M1->r and M2->r must equal B->r */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_horizontal(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong c) -{ - slong i; - for (i = 0; i < B->r; ++i) nmod_sparse_vec_split(&M1->rows[i], &M2->rows[i], &B->rows[i], c); -} - -/* Split block matix B = [M1^t M1^t]^t into submatrices M1 and M2 */ -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_split_vertical(nmod_sparse_mat_t M1, nmod_sparse_mat_t M2, const nmod_sparse_mat_t B, slong r) -{ - slong i; - r = FLINT_MIN(r, B->r); - for (i = 0; i < r; ++i) nmod_sparse_vec_set(&M1->rows[i], &B->rows[i], B->c_off); - for (i = r; i < B->r; ++i) nmod_sparse_vec_set(&M2->rows[i-r], &B->rows[i], B->c_off); -} - /* Matrix permutation */ -NMOD_SPARSE_VEC_INLINE +NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) { slong i; @@ -276,7 +235,7 @@ void nmod_sparse_mat_permute_cols(nmod_sparse_mat_t M, slong *Q) } } -NMOD_SPARSE_VEC_INLINE +NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_permute_rows(nmod_sparse_mat_t M, slong *P) { slong i; @@ -320,12 +279,6 @@ int nmod_sparse_mat_is_zero(const nmod_sparse_mat_t M) return 1; } -======= - for (i = 0; i < M->r; ++i) - if (!nmod_sparse_vec_is_zero(&M->rows[i])) return 0; - return 1; -} - NMOD_SPARSE_MAT_INLINE int nmod_sparse_mat_is_square(const nmod_sparse_mat_t M) { @@ -357,17 +310,6 @@ void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_ } } -NMOD_SPARSE_MAT_INLINE -void nmod_sparse_mat_scalar_mul_nmod(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, mp_limb_t c) -{ - if (c == UWORD(0)) nmod_sparse_mat_zero(N); - else { - slong i; - nmod_sparse_mat_set(N, M); - for (i = 0; i < N->r; ++i) nmod_sparse_vec_scalar_mul_nmod(&N->rows[i], &N->rows[i], c, N->mod); - } -} - NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_t M, const fmpz_t c) { @@ -379,6 +321,7 @@ void nmod_sparse_mat_scalar_mul_fmpz(nmod_sparse_mat_t N, const nmod_sparse_mat_ fmpz_clear(d); } +NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_add(nmod_sparse_mat_t O, const nmod_sparse_mat_t M, const nmod_sparse_mat_t N) { slong i; @@ -411,6 +354,7 @@ void nmod_sparse_mat_scalar_submul_nmod(nmod_sparse_mat_t O, const nmod_sparse_m } /* Matrix-vector and matrix-matrix multipliciation */ +NMOD_SPARSE_MAT_INLINE void nmod_sparse_mat_mul_vec(mp_ptr y, const nmod_sparse_mat_t M, mp_srcptr x) { slong i; @@ -499,8 +443,10 @@ slong nmod_sparse_mat_nullspace_block_lanczos(nmod_mat_t X, const nmod_sparse_ma FLINT_DLL slong nmod_sparse_mat_nullspace_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, flint_rand_t state, slong max_iters); +FLINT_DLL slong nmod_sparse_mat_nullspace_block_wiedemann(nmod_mat_t X, const nmod_sparse_mat_t M, slong block_size, flint_rand_t state, slong max_iters); +FLINT_DLL slong nmod_sparse_mat_nullspace_rref(nmod_mat_t X, const nmod_sparse_mat_t M); FLINT_DLL diff --git a/nmod_vec.h b/nmod_vec.h index 9637379201..1d40e78790 100644 --- a/nmod_vec.h +++ b/nmod_vec.h @@ -123,15 +123,6 @@ mp_limb_t nmod_sub(mp_limb_t a, mp_limb_t b, nmod_t mod) return diff; } -NMOD_VEC_INLINE -mp_limb_t nmod_addmul(mp_limb_t a, mp_limb_t b, mp_limb_t c, nmod_t mod) -{ - if(c==UWORD(1)) return nmod_add(a, b, mod); - if(c==mod.n-UWORD(1)) return nmod_sub(a, b, mod); - NMOD_ADDMUL(a, b, c, mod); - return a; -} - NMOD_VEC_INLINE mp_limb_t nmod_neg(mp_limb_t a, nmod_t mod) { From 61755491ce83b1e7336dca2be943b2e296ef53a7 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 26 May 2021 15:11:56 -0700 Subject: [PATCH 42/42] Added fmpz_mod_mat to cmakelists --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1693030e2b..77bb965ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif() set(BUILD_DIRS aprcl ulong_extras long_extras perm fmpz fmpz_vec fmpz_sparse_vec fmpz_poly - fmpq_poly fmpz_mat fmpz_sparse_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly + fmpq_poly fmpz_mat fmpz_sparse_mat fmpz_mod_mat fmpz_lll mpfr_vec mpfr_mat mpf_vec mpf_mat nmod_vec nmod_sparse_vec nmod_poly nmod_poly_factor arith mpn_extras nmod_mat nmod_sparse_mat fmpq fmpq_vec fmpq_mat padic fmpz_poly_q fmpz_poly_mat nmod_poly_mat fmpz_mod_poly fmpz_mod_poly_factor fmpz_factor fmpz_poly_factor fft qsieve