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