1 #include "cado.h" // IWYU pragma: keep
2 #include <stdint.h> // for uint64_t
3 #ifndef SELECT_MPFQ_LAYER_u64k1
4 #include <cmath>
5 #include <gmp.h> // for mpz_get_d, mpz_fdiv_q_ui, mpz_s...
6 #include <stddef.h> // for size_t
7 #include "cxx_mpz.hpp"
8 #endif
9 #include "macros.h" // for ASSERT_ALWAYS
10 #include "lingen_average_matsize.hpp"
11 #include "lingen_matpoly_select.hpp"
12
13 /*{{{ avg_matsize */
14 template<bool over_gf2>
15 double avg_matsize(abdst_field, unsigned int m, unsigned int n, int ascii);
16
17 template<>
avg_matsize(abdst_field,unsigned int m,unsigned int n,int ascii)18 double avg_matsize<true>(abdst_field, unsigned int m, unsigned int n, int ascii)
19 {
20 ASSERT_ALWAYS(!ascii);
21 ASSERT_ALWAYS((m*n) % 64 == 0);
22 return ((m*n)/64) * sizeof(uint64_t);
23 }
24
25 #ifndef SELECT_MPFQ_LAYER_u64k1
26 template<>
avg_matsize(abdst_field ab,unsigned int m,unsigned int n,int ascii)27 double avg_matsize<false>(abdst_field ab, unsigned int m, unsigned int n, int ascii)
28 {
29 if (!ascii) {
30 /* Easy case first. If we have binary input, then we know a priori
31 * that the input data must have size a multiple of the element size.
32 */
33 size_t elemsize = abvec_elt_stride(ab, 1);
34 size_t matsize = elemsize * m * n;
35 return matsize;
36 }
37
38 /* Ascii is more complicated. We're necessarily fragile here.
39 * However, assuming that each coefficient comes with only one space,
40 * and each matrix with an extra space (this is how the GPU program
41 * prints data -- not that this ends up having a considerable impact
42 * anyway...), we can guess the number of bytes per matrix. */
43
44 /* Formula for the average number of digits of an integer mod p,
45 * written in base b:
46 *
47 * (k-((b^k-1)/(b-1)-1)/p) with b = Ceiling(Log(p)/Log(b)).
48 */
49 double avg;
50 cxx_mpz a;
51 double pd = mpz_get_d(abfield_characteristic_srcptr(ab));
52 unsigned long k = ceil(log(pd)/log(10));
53 unsigned long b = 10;
54 mpz_ui_pow_ui(a, b, k);
55 mpz_sub_ui(a, a, 1);
56 mpz_fdiv_q_ui(a, a, b-1);
57 avg = k - mpz_get_d(a) / pd;
58 // printf("Expect roughly %.2f decimal digits for integers mod p.\n", avg);
59 double matsize = (avg + 1) * m * n + 1;
60 // printf("Expect roughly %.2f bytes for each sequence matrix.\n", matsize);
61 return matsize;
62 }
63 #endif
64
average_matsize(abdst_field ab,unsigned int m,unsigned int n,int ascii)65 double average_matsize(abdst_field ab, unsigned int m, unsigned int n, int ascii)
66 {
67 return avg_matsize<matpoly::over_gf2>(ab, m, n, ascii);
68 }
69 /*}}}*/
70
71