Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sparse3 #1845

Open
wants to merge 64 commits into
base: main
Choose a base branch
from
Open

Sparse3 #1845

Changes from 1 commit
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
57912d7
API for sparse vectors
Feb 6, 2024
52d7fbe
adding gr_sparse_vec dir
Feb 6, 2024
75d157b
adding fit, set, update
Feb 7, 2024
5dd99b0
working on sparse vec
Feb 7, 2024
45f4d45
adding macros
Feb 7, 2024
da2e5d4
gr sparse vec template stuff
Feb 8, 2024
d928055
working on gr_sparse vec templates
aldenwalker Feb 8, 2024
c14897c
working on several sparse vec functions
Feb 9, 2024
701127c
added some other creation and tests
Feb 9, 2024
efe5d72
starting to try to compile
Feb 9, 2024
511ab5c
compiles
Feb 9, 2024
9cc6a03
added into dense functions
Feb 9, 2024
3d6ea81
working on documentation
Feb 10, 2024
b6617f7
more documentation
Feb 10, 2024
3b42d5d
cmake and compiling
Feb 13, 2024
c39f222
working on tests and get/set individual entries
Feb 14, 2024
e1ce9e5
find/set entry
Feb 15, 2024
bfc4bca
debugging sparse vec creation test failure
Feb 16, 2024
edca4ac
unsorted creation test passing
aldenwalker Feb 21, 2024
fd2fad5
added conversion test
aldenwalker Feb 21, 2024
94aa615
Added shallow transpose macro
Mar 17, 2024
49b1a8e
Merge remote-tracking branch 'overcrimp2/sparse3_akwalke' into sparse3
Mar 17, 2024
1427ffa
Some nomenclature changes
Mar 17, 2024
3f53d01
Beginning of gr sparse matrix
Mar 17, 2024
72d3b91
Bug fix
Mar 17, 2024
ae7f8af
Forgot to save
Mar 17, 2024
9a75954
Fixed setting functions
Mar 17, 2024
a687079
A few more functions
Mar 18, 2024
967ee80
Added negation
Mar 18, 2024
2aa7bb5
Added scaling ops
Mar 18, 2024
cb8c911
Sparse vector and matrix multiplication
Mar 18, 2024
1d22885
Merge branch 'main' into sparse3
Mar 18, 2024
26cd947
Fixed documentation
Mar 18, 2024
98ecdf7
Bug fixes
Mar 18, 2024
5da9446
Changed more col to ind, ind to nzidx
Mar 18, 2024
4eb5ca1
Updated sparse vector docs
Mar 18, 2024
34908ed
Finished basic API analogous to sparse vector
Mar 18, 2024
fd083fd
Merge branch 'main' into sparse3
Mar 18, 2024
6108953
Fixed test
Mar 18, 2024
d9cebe6
Various nomenclature changes, added randtest, testing more rings
Mar 19, 2024
e931f8d
More doc fixes
Mar 19, 2024
6b3ed70
More doc fixes
Mar 19, 2024
9436272
Fixed equality and tested scaling
Mar 20, 2024
1565c9b
Fixed bug in riffling
Mar 20, 2024
6eb88f7
Fixed other testing
Mar 20, 2024
1a49b2d
Weakened test because of ring compatibility issues, decent coverage now
Mar 20, 2024
9bce9ee
Added missed tests
Mar 20, 2024
0b4ac8b
Moved inline arithmetic functions to files
Mar 20, 2024
a3be3d5
Moved column permutations to file
Mar 20, 2024
ca8e38e
Added newline
Mar 20, 2024
ecf1f65
Fixed a few bugs, test for generation and conversion
Mar 20, 2024
1152d15
More conversion tests
Mar 21, 2024
971f11a
A little more coverage
Mar 21, 2024
0b5eee6
Basic stuff mostly tested, have most of the functionality for solving
Mar 21, 2024
71eb7d2
Added solvers, compiles but will not work yet
Mar 22, 2024
a3cdc82
Fixed tests
Mar 22, 2024
fe248bd
Everything but block lanczos works
Mar 22, 2024
61fc72c
Merged upstream
Mar 22, 2024
f9f9e51
Forgot a file
Mar 22, 2024
ad3dfe5
Updated documentation, added functions to update a dense matrix with …
Mar 22, 2024
7b5ec2b
fix sparse_vec arithmetic for length zero
fredrik-johansson Apr 27, 2024
4ec61b0
Added LU and rref
Apr 29, 2024
83ebaaa
Forgot to add files
Apr 29, 2024
4996074
Merge branch 'main' into sparse3
Apr 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
more documentation
  • Loading branch information
Alden Walker committed Feb 10, 2024
commit b6617f7b9ff88272477cfe8611997445ebfbd627
99 changes: 82 additions & 17 deletions doc/source/gr_sparse_vec.rst
Original file line number Diff line number Diff line change
@@ -5,10 +5,11 @@

A :type:`gr_sparse_vec_t` is a represention of a vector over a generic
ring which is optimized for the situation where there are many entries which
are zero (the vector is sparse). Internally, the vector records only
the positions of the nonzeros and their values. Although technically the
type and all its functions will operate correctly with any density,
a :type:`gr_vec_t` may be more efficient in the number of nonzeros is not small.
are zero (the vector is *sparse*, or has *low density*). Internally, the
vector records only the positions of the nonzeros and their values.
Although technically the type and all its functions will operate correctly
with any density, a regular :type:`gr_vec_t` may be more efficient in the number
of nonzeros is not small.

Types and basic access
--------------------------------------------------------------------------------
@@ -113,29 +114,32 @@ Setting and conversion

.. function:: int gr_sparse_vec_randtest(gr_sparse_vec_t vec, double density, slong len, flint_rand_t state, gr_ctx_t ctx)

Initialize *vec* to a random vector with density (fraction of nonzeros) *density* and length *len*.
The algorithm is suitable when *density* is small. Specifically, column indices
are generated randomly and deduped. So if the density is
larger than ``1/sqrt(len)``, the true density of the returned vector is likely to be
lower than *density*.
Initialize *vec* to a random vector with density (fraction of nonzeros)
*density* and length *len*. The algorithm is suitable when *density* is small.
Specifically, column indices are generated randomly and deduped. So if the
density is larger than ``1/sqrt(len)``, the true density of the returned vector
is likely to be lower than *density*.

.. function:: int gr_sparse_vec_from_dense(gr_sparse_vec_t vec, gr_srcptr src, slong len, gr_ctx_t ctx)

Convert the dense vector *src* of length *len* to the sparse vector *vec*.

.. function:: int gr_sparse_vec_to_dense(gr_ptr vec, gr_sparse_vec_t src, gr_ctx_t ctx)

Convert the sparse vector *src* into a dense vector *vec*, which must have sufficient space.
Convert the sparse vector *src* into a dense vector *vec*, which must have
sufficient space (i.e. ``vec->length``).

.. function:: int gr_sparse_vec_slice(gr_sparse_vec_t res, const gr_sparse_vec_t src, slong col_start, slong col_end, gr_ctx_t ctx)

Set *res* to a copy of the slice of *src* given by any entries whose column indices
lie in the half open interval ``[col_start, col_end)``. Column indices are shifted
by *col_start* (a column index of ``col_start`` would become ``0``).
Set *res* to a copy of the slice of *src* given by any entries whose
column indices lie in the half open interval ``[col_start, col_end)``.
Column indices are shifted by *col_start* (a column index of ``col_start``
would become ``0``).

.. function:: int gr_sparse_vec_permute_cols(gr_sparse_vec_t vec, const gr_sparse_vec_t src, slong * p, gr_ctx_t ctx)

Set *vec* to a copy of *src* with the columns permuted. The column indices are shifted as: ``vec[p[i]] = src[i]``.
Set *vec* to a copy of *src* with the columns permuted. The column
indices are shifted as: ``vec[p[i]] = src[i]``.


Comparison
@@ -147,7 +151,7 @@ Comparison

.. function:: truth_t gr_sparse_vec_is_zero(const gr_sparse_vec_t vec, gr_ctx_t ctx)

Return ``T_TRUE`` if *vec* represents the zero vector, and ``T_FALSE`` otherwise.
Return ``T_TRUE`` if *vec* represents the zero vector and ``T_FALSE`` otherwise.


Output
@@ -163,22 +167,27 @@ Output
Print the nonzeros of *vec* to ``stdout``. See ``gr_sparse_vec_to_dense``
if it is desired to print out the entire vector, zeros and all.


Arithmetic
--------------------------------------------------------------------------------

.. function:: int gr_sparse_vec_add(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, slong len, gr_ctx_t ctx)
int gr_sparse_vec_sub(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, slong len, gr_ctx_t ctx)
int gr_sparse_vec_mul(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, slong len, gr_ctx_t ctx)

Componentwise operations. (We do not provide analogous multiplication or division routines due to issues with zero.)
Componentwise operations. (We do not provide analogous division or exponentiation
routines due since sparse inputs to these operations would be undefined or
fully dense.)

.. function:: int gr_sparse_vec_add_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx)
int gr_sparse_vec_sub_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx)
int gr_sparse_vec_mul_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx)

Componentwise operations where the second input is allowed to have a different ring.

.. function:: int gr_other_add_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx)
int gr_other_sub_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx)
int gr_other_mul_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx)

Componentwise operations where the first input is allowed to have a different ring.

@@ -194,6 +203,54 @@ Arithmetic
Set *res* to -*src*


Arithmetic into dense vectors
--------------------------------------------------------------------------------

.. function:: int gr_sparse_vec_update_to_dense(gr_ptr dres, const gr_sparse_vec_t src, gr_ctx_t ctx)
int gr_sparse_vec_add_to_dense(gr_ptr dres, gr_srcptr dvec1, const gr_sparse_vec_t svec2, gr_ctx_t ctx)
int gr_sparse_vec_sub_to_dense(gr_ptr dres, gr_srcptr dvec1, const gr_sparse_vec_t svec2, gr_ctx_t ctx)
int gr_sparse_vec_nz_mul_to_dense(gr_ptr dres, gr_srcptr dvec1, const gr_sparse_vec_t svec2, gr_ctx_t ctx)
int gr_sparse_vec_nz_div_to_dense(gr_ptr dres, gr_srcptr dvec1, const gr_sparse_vec_t svec2, gr_ctx_t ctx)
int gr_sparse_vec_addmul_scalar_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, gr_srcptr c, gr_ctx_t ctx)
int gr_sparse_vec_submul_scalar_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, gr_srcptr c, gr_ctx_t ctx)
int gr_sparse_vec_addmul_scalar_si_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, slong c, gr_ctx_t ctx)
int gr_sparse_vec_submul_scalar_si_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, slong c, gr_ctx_t ctx)
int gr_sparse_vec_addmul_scalar_fmpz_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, const fmpz_t c, gr_ctx_t ctx)
int gr_sparse_vec_submul_scalar_fmpz_to_dense(gr_ptr dres, const gr_sparse_vec_t svec, const fmpz_t c, gr_ctx_t ctx)

These functions facilitate accumulating a sparse vector into a dense
target. They have one dense input, one sparse input, and a dense output.
For all functions, it is assumed that *dres* and *dvec1* have the same
length as *svec* or *svec2*, as appropriate. The functions
``gr_sparse_vec_update_to_dense()`` (overwrite the entries in *dres*),
``gr_sparse_vec_nz_mul_to_dense()``, and ``gr_sparse_vec_nz_div_to_dense()``
only operate on the locations for which *svec2* is nonzero.


Componentwise multiplication and division
--------------------------------------------------------------------------------

.. function:: int gr_sparse_vec_mul_scalar(gr_sparse_vec_t res, const gr_sparse_vec_t src, gr_srcptr c, gr_ctx_t ctx)
int gr_sparse_vec_mul_scalar_si(gr_sparse_vec_t res, const gr_sparse_vec_t src, slong c, gr_ctx_t ctx)
int gr_sparse_vec_mul_scalar_ui(gr_sparse_vec_t res, const gr_sparse_vec_t src, ulong c, gr_ctx_t ctx)
int gr_sparse_vec_mul_scalar_fmpz(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpz_t c, gr_ctx_t ctx)
int gr_sparse_vec_mul_scalar_fmpq(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpq_t c, gr_ctx_t ctx)
int gr_sparse_vec_mul_scalar_2exp_si(gr_sparse_vec_t res, const gr_sparse_vec_t src, slong c, gr_ctx_t ctx)
int gr_sparse_vec_div_scalar(gr_sparse_vec_t res, const gr_sparse_vec_t src, gr_srcptr c, gr_ctx_t ctx)
int gr_sparse_vec_div_scalar_si(gr_sparse_vec_t res, const gr_sparse_vec_t src, slong c, gr_ctx_t ctx)
int gr_sparse_vec_div_scalar_ui(gr_sparse_vec_t res, const gr_sparse_vec_t src, ulong c, gr_ctx_t ctx)
int gr_sparse_vec_div_scalar_fmpz(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpz_t c, gr_ctx_t ctx)
int gr_sparse_vec_div_scalar_fmpq(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpq_t c, gr_ctx_t ctx)
int gr_sparse_vec_divexact_scalar(gr_sparse_vec_t res, const gr_sparse_vec_t src, gr_srcptr c, gr_ctx_t ctx)
int gr_sparse_vec_divexact_scalar_si(gr_sparse_vec_t res, const gr_sparse_vec_t src, slong c, gr_ctx_t ctx)
int gr_sparse_vec_divexact_scalar_ui(gr_sparse_vec_t res, const gr_sparse_vec_t src, ulong c, gr_ctx_t ctx)
int gr_sparse_vec_divexact_scalar_fmpz(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpz_t c, gr_ctx_t ctx)
int gr_sparse_vec_divexact_scalar_fmpq(gr_sparse_vec_t res, const gr_sparse_vec_t src, const fmpq_t c, gr_ctx_t ctx)

Set *res* to be *src* multiplied or divided by *c*.
(Addition and subtraction are not provided because they would create
dense output.)

Sum and product
--------------------------------------------------------------------------------

@@ -209,7 +266,15 @@ Sum and product
Dot products
--------------------------------------------------------------------------------

Hello
.. function:: int gr_sparse_vec_dot(gr_ptr res, gr_srcptr c, int subtract, const gr_sparse_vec_t x, const gr_sparse_vec_t y, gr_ctx_t ctx)

Set *res* equal to `c \pm x \cdot y`.

.. function:: int gr_sparse_vec_dot_rev(gr_ptr res, gr_srcptr c, int subtract, const gr_sparse_vec_t x, const gr_sparse_vec_t y, gr_ctx_t ctx)

Set *res* equal to `c \pm \sum_{i=0}^{n-1}x_iy_{n-1-i}`.




.. raw:: latex
4 changes: 3 additions & 1 deletion src/gr_sparse_vec.h
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ slong _gr_sparse_vec_count_unique_cols(const ulong *cols0, slong nnz0, const ulo

/* This is used for operations like add which have to riffle through the entries of two vectors */
/* It's an annoying macro that combines with the macros below. This is so we can handle */
/* Different arguments in different orders, etc */
/* different arguments in different orders, etc */
#define GR_SPV_RFL_TEMPLATE(FUNC_A, FUNC_B, FUNC_AB, DEST_VEC, A_VEC, B_VEC, CTX) \
int status; \
slong sz, new_nnz, a_ind, b_ind, dest_ind, a_nnz, b_nnz, i; \
@@ -180,11 +180,13 @@ GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_sparse_vec_mul(gr_sparse_vec_t re

GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_sparse_vec_add_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_UOP(gr_set, src1, a_ind), GR_SPV_RFL_UOP_OTHER(gr_set_other, src2, b_ind, ctx2), GR_SPV_RFL_BOP_OTHER(gr_add_other, src1, a_ind, src2, b_ind, ctx2), res, src1, src2, ctx); }
GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_sparse_vec_sub_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_UOP(gr_set, src1, a_ind), GR_SPV_RFL_UOP_OTHER(gr_neg_other, src2, a_ind, ctx2), GR_SPV_RFL_BOP_OTHER(gr_sub_other, src1, a_ind, src2, b_ind, ctx2), res, src1, src2, ctx); }
GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_sparse_vec_mul_other(gr_sparse_vec_t res, const gr_sparse_vec_t src1, const gr_sparse_vec_t src2, gr_ctx_t ctx2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_ZERO, GR_SPV_RFL_ZERO, GR_SPV_RFL_BOP_OTHER(gr_mul_other, src1, a_ind, src2, b_ind, ctx2), res, src1, src2, ctx); }

#define GR_SPV_RFL_OTHER_BOP(F, Y, Y_ind, CTX2, Z, Z_ind) F(GR_ENTRY(res->entries, dest_ind, sz), GR_ENTRY(Y->entries, Y_ind, CTX2->sizeof_elem), (CTX2), GR_ENTRY(Z->entries, Z_ind, sz), ctx)

GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_other_add_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_UOP_OTHER(gr_set_other, src1, a_ind, ctx1), GR_SPV_RFL_UOP(gr_set, src2, b_ind), GR_SPV_RFL_OTHER_BOP(gr_other_add, src1, a_ind, ctx1, src2, b_ind), res, src1, src2, ctx); }
GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_other_sub_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_UOP_OTHER(gr_set_other, src1, a_ind, ctx1), GR_SPV_RFL_UOP(gr_neg, src2, b_ind), GR_SPV_RFL_OTHER_BOP(gr_other_sub, src1, a_ind, ctx1, src2, b_ind), res, src1, src2, ctx); }
GR_SPARSE_VEC_INLINE WARN_UNUSED_RESULT int gr_other_mul_sparse_vec(gr_sparse_vec_t res, const gr_sparse_vec_t src1, gr_ctx_t ctx1, const gr_sparse_vec_t src2, gr_ctx_t ctx) { GR_SPV_RFL_TEMPLATE(GR_SPV_RFL_ZERO, GR_SPV_RFL_ZERO, GR_SPV_RFL_OTHER_BOP(gr_other_mul, src1, a_ind, ctx1, src2, b_ind), res, src1, src2, ctx); }

#define GR_SPV_RFL_UOP_SCALAR(F, Y, Y_ind) F(GR_ENTRY(res->entries, dest_ind, sz), GR_ENTRY(Y->entries, Y_ind, sz), c, ctx)