1 #ifndef LINGEN_POLYMAT_HPP_
2 #define LINGEN_POLYMAT_HPP_
3 
4 #ifdef SELECT_MPFQ_LAYER_u64k1
5 #error "lingen_polymat does not work with binary (maybe use bblas instead -- could end up being the same interface, IDK)"
6 #endif
7 
8 #include <cstddef>      // for size_t, NULL
9 #include <gmp.h>         // for gmp_randstate_t
10 #include "mpfq_layer.h"
11 #include "macros.h"
12 
13 class matpoly;
14 
15 /* This is used only for lingen. */
16 struct polymat {
17     abdst_field ab = NULL;
18     unsigned int m = 0;
19     unsigned int n = 0;
20     private:
21     size_t size = 0;
22     size_t alloc = 0;
23     public:
capacitypolymat24     inline size_t capacity() const { return alloc; }
get_sizepolymat25     inline size_t get_size() const { return size; }
set_sizepolymat26     void set_size(size_t s) { size = s; }
27     abvec x = NULL;
28 
polymatpolymat29     polymat() : polymat(NULL, 0,0,0) {}
30     polymat(polymat const&) = delete;
31     polymat& operator=(polymat const&) = delete;
32     polymat(polymat &&);
33     polymat& operator=(polymat &&);
34     ~polymat();
35     polymat(abdst_field ab, unsigned int m, unsigned int n, int len);
36     int check_pre_init() const;
37     void realloc(size_t newalloc);
38     void zero();
39 #if 0
40     void swap(polymat & b);
41 #endif
42     void fill_random(unsigned int nsize, gmp_randstate_t rstate);
43     int cmp(polymat const & b);
44 
45     /* {{{ access interface for polymat */
partpolymat46     inline abdst_vec part(unsigned int i, unsigned int j, unsigned int k) {
47         /* Assume row-major in all circumstances. Old code used to support
48          * various orderings, here we don't */
49         ASSERT_ALWAYS(size);
50         return abvec_subvec(ab, x, (k*m+i)*n+j);
51     }
coeffpolymat52     inline abdst_elt coeff(unsigned int i, unsigned int j, unsigned int k) {
53         return abvec_coeff_ptr(ab, part(i,j,k),0);
54     }
partpolymat55     inline absrc_vec part(unsigned int i, unsigned int j, unsigned int k) const {
56         /* Assume row-major in all circumstances. Old code used to support
57          * various orderings, here we don't */
58         ASSERT_ALWAYS(size);
59         return abvec_subvec_const(ab, (absrc_vec)x,(k*m+i)*n+j);
60     }
coeffpolymat61     inline absrc_elt coeff(unsigned int i, unsigned int j, unsigned int k) const {
62         return abvec_coeff_ptr_const(ab, part(i,j,k),0);
63     }
64     /* }}} */
65 
66     void addmat(
67         unsigned int kc,
68         polymat const & a, unsigned int ka,
69         polymat const & b, unsigned int kb);
70     void submat(
71         unsigned int kc,
72         polymat const & a, unsigned int ka,
73         polymat const & b, unsigned int kb);
74     void mulmat(
75         unsigned int kc,
76         polymat const & a, unsigned int ka,
77         polymat const & b, unsigned int kb);
78     void addmulmat(
79         unsigned int kc,
80         polymat const & a, unsigned int ka,
81         polymat const & b, unsigned int kb);
82     void multiply_column_by_x(unsigned int j, unsigned int size);
83     void truncate(polymat const & src, unsigned int nsize);
84     void extract_column(
85         unsigned int jdst, unsigned int kdst,
86         polymat const & src, unsigned int jsrc, unsigned int ksrc);
87     void extract_row_fragment(
88         unsigned int i1, unsigned int j1,
89         polymat const & src, unsigned int i0, unsigned int j0,
90         unsigned int n);
91     void mul(polymat const & a, polymat const & b);
92     void addmul(polymat const & a, polymat const & b);
93     void mp(polymat const & a, polymat const & b);
94     void addmp(polymat const & a, polymat const & b);
95 
96     void set_matpoly(matpoly const &);
97     void rshift(polymat const & src, unsigned int k);
98 
99 };
100 
101 /* {{{ cut-off structures */
102 /* This structure is used to decide which algorithm to use for a given
103  * input length. This essentially is a function from N*N to a finite set of
104  * choices (so far, {0,1} only). The value returned for a balanced input
105  * length x*x is:
106  * if x >= cut: 1
107  * if x < cut:
108  *      if table == NULL:
109  *              return 0
110  *      find last (s,a) in table such that s <= x
111  *      return a
112  * For unbalanced input length x*y, we compare MIN(x,y) with subdivide.
113  * At the moment there is no additional table designed to improve the
114  * choice.
115  *
116  * Cutoffs are used only by lingen-polymat.c and lingen-bigpolymat.c -- however the
117  * tuning program also uses it, so we expose it here too.
118  */
119 /* Such a cutoff structure is used for finding which algorithm to used
120  * for:
121  *  - a balanced x*x product. -> basecase(0) or karatsuba(1)
122  *  - an unbalanced x*y product. -> basecase(0) or split into balanced
123  *  sizes(1)
124  */
125 
126 struct polymat_cutoff_info {
127     unsigned int cut;
128     unsigned int subdivide;
129     unsigned int (*table)[2];
130     unsigned int table_size;
131 };
132 #ifdef __cplusplus
133 extern "C" {
134 #endif
135 void polymat_cutoff_info_init(struct polymat_cutoff_info * c);
136 void polymat_cutoff_info_clear(struct polymat_cutoff_info * c);
137 void polymat_cutoff_add_step(struct polymat_cutoff_info * c, unsigned int size, unsigned int alg);
138 void polymat_set_mul_kara_cutoff(const struct polymat_cutoff_info * new_cutoff, struct polymat_cutoff_info * old_cutoff);
139 void polymat_set_mp_kara_cutoff(const struct polymat_cutoff_info * new_cutoff, struct polymat_cutoff_info * old_cutoff);
140 #ifdef __cplusplus
141 }
142 #endif
143 /* }}} */
144 
145 #endif	/* LINGEN_POLYMAT_HPP_ */
146