1 #ifndef LAS_WHERE_AM_I_DEBUG_HPP_
2 #define LAS_WHERE_AM_I_DEBUG_HPP_
3 
4 // IWYU pragma: private, include "las-where-am-i.hpp"
5 
6 #include <array>                      // for array
7 #include <climits>                    // for UINT_MAX
8 #include <cstdint>                    // for uint64_t, int64_t
9 #include <cstddef>                    // for NULL
10 
11 #include "las-where-am-i-proxy.hpp"        // for where_am_I
12 #include "fb-types.h"   // for fbprime_t, fbroot_t, slice_index_t
13 #include "fb.hpp"       // for fb_factorbase
14 #include "las-config.h" // for LOG_BUCKET_REGION
15 struct cxx_mpz;          // IWYU pragma: keep
16 struct las_info;         // IWYU pragma: keep
17 struct qlattice_basis;   // IWYU pragma: keep
18 
19 /* Define CHECK_UNDERFLOW to check for underflow when subtracting
20    the rounded log(p) from sieve array locations */
21 //#define CHECK_UNDERFLOW
22 
23 /* Define TRACK_CODE_PATH in order to have the where_am_I structures
24  * propagate info on the current situation of the data being handled.
25  * This more or less makes the variables global, in that every function
26  * can then access the totality of the variables. But it's for debug and
27  * inspection purposes only.
28  *
29  * Note that WANT_ASSERT_EXPENSIVE, a flag which exists in broader
30  * context, augments the scope of the tracking here by performing a
31  * divisibility test on each sieve update. This is obviously very
32  * expensive, but provides nice checking.
33  *
34  * Another useful tool for debugging is the sieve-area checksums that get
35  * printed with verbose output (-v) enabled.
36  */
37 #define xxxTRACK_CODE_PATH
38 #define xxxWANT_ASSERT_EXPENSIVE
39 
40 /* TRACE_K *requires* TRACK_CODE_PATH -- or it displays rubbish */
41 #if defined(TRACE_K) && !defined(TRACK_CODE_PATH)
42 #define TRACK_CODE_PATH
43 #endif
44 
45 /* idem for CHECK_UNDERFLOW */
46 #if defined(CHECK_UNDERFLOW) && !defined(TRACK_CODE_PATH)
47 #define TRACK_CODE_PATH
48 #endif
49 
50 /*  where_am_I (debug) */
51 struct where_am_I::impl {
52     int logI = 0;
53     const qlattice_basis * pQ = NULL;
54     struct side_data {
55         const fb_factorbase::slicing * fbs = NULL;
56     };
57     side_data sides[2];
58     fbprime_t p = 0;        /* current prime or prime power, when applicable */
59     fbroot_t r = 0;         /* current root */
60     slice_index_t i = 0;    /* Slice index, if applicable */
61     slice_offset_t h = 0;   /* Prime hint, if not decoded yet */
62     unsigned int j = 0;     /* row number in bucket */
63     unsigned int x = 0;     /* value in bucket */
64     unsigned int N = 0;     /* bucket number */
65     int side = 0;
66     const las_info * plas = NULL;
67 };
68 
69 #define WHERE_AM_I_UPDATE(w, field, value) (w)->field = (value)
70 
71 extern int test_divisible(where_am_I const & w);
72 
73 struct trace_Nx_t { unsigned int N; unsigned int x; };
74 struct trace_ab_t { int64_t a; uint64_t b; };
75 struct trace_ij_t { int i; unsigned int j; };
76 
77 extern struct trace_Nx_t trace_Nx;
78 extern struct trace_ab_t trace_ab;
79 extern struct trace_ij_t trace_ij;
80 
81 extern std::array<cxx_mpz, 2> traced_norms;
82 
trace_on_spot_N(unsigned int N)83 static inline int trace_on_spot_N(unsigned int N) {
84     if (trace_Nx.x == UINT_MAX) return 0;
85     return N == trace_Nx.N;
86 }
87 
trace_on_spot_Nx(unsigned int N,unsigned int x)88 static inline int trace_on_spot_Nx(unsigned int N, unsigned int x) {
89     if (trace_Nx.x == UINT_MAX) return 0;
90     return N == trace_Nx.N && x == trace_Nx.x;
91 }
92 
trace_on_range_Nx(unsigned int N,unsigned int x0,unsigned int x1)93 static inline int trace_on_range_Nx(unsigned int N, unsigned int x0, unsigned int x1) {
94     if (trace_Nx.x == UINT_MAX) return 0;
95     return N == trace_Nx.N && x0 <= trace_Nx.x && trace_Nx.x < x1;
96 }
97 
trace_on_spot_x(uint64_t x)98 static inline int trace_on_spot_x(uint64_t x) {
99     return x == (((uint64_t)trace_Nx.N) << LOG_BUCKET_REGION)
100         + (uint64_t)trace_Nx.x;
101 }
102 
trace_on_spot_ab(int64_t a,uint64_t b)103 static inline int trace_on_spot_ab(int64_t a, uint64_t b) {
104     return a == trace_ab.a && b == trace_ab.b;
105 }
106 
trace_on_spot_ij(int i,unsigned int j)107 static inline int trace_on_spot_ij(int i, unsigned int j) {
108     return i == trace_ij.i && j == trace_ij.j;
109 }
110 
111 void sieve_increase_logging(unsigned char *S, const unsigned char logp, where_am_I const & w);
112 void sieve_increase(unsigned char *S, const unsigned char logp, where_am_I const & w);
113 
114 #endif	/* LAS_WHERE_AM_I_DEBUG_HPP_ */
115