Commits

CarloWood committed a035d6a

Add option --debug-mzd.

This allows one to run heavy consistency checks on the elements
of mzd_t (which are heavily correlated) without dumping the
hash values. Using just --debug-dump also does the consistency
checks on top of printing the hash values.

Comments (0)

Files changed (3)

 fi
 AC_SUBST(M4RI_DEBUG_DUMP)
 
+AC_ARG_ENABLE([debug-mzd],
+        AS_HELP_STRING([--enable-debug-mzd], [Add consistency checks on matrix structures.]))
+
+if test "x$enable_debug_mzd" = "xyes"; then
+  M4RI_DEBUG_MZD=1
+else
+  M4RI_DEBUG_MZD=0
+fi
+AC_SUBST(M4RI_DEBUG_MZD)
+
 # For the testsuite. Detect if PAPI is installed. See http://icl.cs.utk.edu/papi/ .
 
 if test -z "$m4ri_config_papi"; then
 
 static void entry(char const* function, char const* file, int line)
 {
+#if !__M4RI_DD_QUIET
   printf("Sequence#: %ld; %s @ %s:%d; ", dd_sequence_number, function, file, line);
+#endif
   ++dd_sequence_number;
 }
 
   return (w << shift) | (w >> (m4ri_radix - w));
 }
 
+static inline void consistency_check_row(mzd_t const *M, rci_t row)
+{
+  assert(row >= 0 && row < M->nrows);
+  if (mzd_is_windowed(M))
+    return;
+  // Check that the excess bits are zero.
+  assert((M->rows[row][M->width - 1] & ~M->high_bitmask) == 0);
+  // Check that the padding bits are zero, if any.
+  assert(M->width == M->rowstride || M->rows[row][M->width] == 0);
+}
+
+static void consistency_check(mzd_t const *M)
+{
+  assert(M->nrows >= 0 && M->ncols >= 0);
+  assert(M->offset >= 0 && M->offset < m4ri_radix);
+  assert(M->width * m4ri_radix >= M->ncols + M->offset);
+  assert((M->width - 1) * m4ri_radix < M->ncols + M->offset);
+  assert(M->width < mzd_paddingwidth || (M->rowstride & 1) == 0);
+  assert((M->blockrows_mask + 1) == (1 << M->blockrows_log));
+  assert((1 << M->blockrows_log) * M->rowstride <= __M4RI_MAX_MZD_BLOCKSIZE);
+  assert((1 << M->blockrows_log) * M->rowstride > __M4RI_MAX_MZD_BLOCKSIZE / 2);
+  assert((M->width > 1 && M->low_bitmask == __M4RI_RIGHT_BITMASK(m4ri_radix - M->offset)) ||
+         (M->width < 2 && M->low_bitmask == __M4RI_MIDDLE_BITMASK(M->ncols, M->offset)));
+  assert((M->width > 1 && M->high_bitmask == __M4RI_LEFT_BITMASK((M->ncols + M->offset) % m4ri_radix)) ||
+         (M->width < 2 && M->high_bitmask == __M4RI_MIDDLE_BITMASK(M->ncols, M->offset)));
+  assert(((M->flags & mzd_flag_nonzero_offset) == 0) == (M->offset == 0));
+  assert(((M->flags & mzd_flag_nonzero_excess) == 0) == ((M->ncols + M->offset) % m4ri_radix == 0));
+  assert((M->flags & mzd_flag_windowed_zerooffset) == 0 || M->offset == 0);
+  assert((M->flags & mzd_flag_windowed_zeroexcess) == 0 || ((M->ncols + M->offset) % m4ri_radix == 0));
+  assert(M->blocks != NULL || mzd_is_windowed(M));
+  assert(M->blocks == NULL || (((M->flags & mzd_flag_multiple_blocks) == 0) == (M->blocks[1].size == 0)));
+  if (mzd_is_windowed(M))
+    return;
+  assert(M->rowstride == M->width || (M->rowstride == M->width + 1 && M->width >= mzd_paddingwidth));
+  for (rci_t r = 0; r < M->nrows; ++r) {
+    consistency_check_row(M, r);
+  }
+}
+
 void m4ri_dd_int(char const* function, char const* file, int line, int i)
 {
   entry(function, file, line);
+#if !__M4RI_DD_QUIET
   printf("int: %d\n", i);
+#endif
 }
 
 void m4ri_dd_rci(char const* function, char const* file, int line, rci_t rci)
 {
   entry(function, file, line);
+#if !__M4RI_DD_QUIET
   printf("rci: %d\n", rci);
+#endif
 }
 
 void m4ri_dd_rci_array(char const* function, char const* file, int line, rci_t *rciptr, int len)
 {
   entry(function, file, line);
+#if !__M4RI_DD_QUIET
   unsigned long long hash = 0;
   for (int i = 0; i < len; ++i)
     hash ^= rotate_word(rciptr[i], i % m4ri_radix);
   printf("rci array (size %d) hash: %llx\n", len, hash);
+#endif
 }
 
 void m4ri_dd_rawrow(char const* function, char const* file, int line, word const* rowptr, wi_t wide)
 {
   entry(function, file, line);
+#if !__M4RI_DD_QUIET
   unsigned long long hash = calculate_hash(rowptr, wide);
   printf("raw row (%d words) hash: %llx\n", wide, hash);
+#endif
 }
 
 void m4ri_dd_row(char const* function, char const* file, int line, mzd_t const* M, rci_t row)
 {
   entry(function, file, line);
+  consistency_check_row(M, row);
+#if !__M4RI_DD_QUIET
   unsigned long long hash = calculate_hash(M->rows[row], M->width);
   printf("row %d hash: %llx\n", row, hash);
+#endif
 }
 
 void m4ri_dd_mzd(char const* function, char const* file, int line, mzd_t const* M)
 {
   entry(function, file, line);
+  consistency_check(M);
+#if !__M4RI_DD_QUIET
   unsigned long long hash = 0;
   for (rci_t r = 0; r < M->nrows; ++r)
     hash ^= rotate_word(calculate_hash(M->rows[r], M->width), r % m4ri_radix);
   printf("mzd hash: %llx\n", hash);
+#endif
 }
 
 void m4ri_dd_mzp(char const* function, char const* file, int line, mzp_t const* P)
 {
   entry(function, file, line);
+#if !__M4RI_DD_QUIET
   unsigned long long hash = 0;
   for (rci_t i = 0; i < P->length; ++i)
     hash ^= rotate_word(P->values[i], i % m4ri_radix);
   printf("mzp hash: %llx\n", hash);
+#endif
 }
 
 #endif

src/m4ri_config.h.in

 #define __M4RI_HAVE_POSIX_MEMALIGN	@M4RI_HAVE_POSIX_MEMALIGN@
 #define __M4RI_HAVE_SSE2		@M4RI_HAVE_SSE2@
 #define __M4RI_HAVE_OPENMP		@M4RI_HAVE_OPENMP@
-#define __M4RI_DEBUG_DUMP		@M4RI_DEBUG_DUMP@
+#define __M4RI_DEBUG_DUMP		(@M4RI_DEBUG_DUMP@ || @M4RI_DEBUG_MZD@)
+#define __M4RI_DEBUG_MZD		@M4RI_DEBUG_MZD@
 
 // Helper macros.
 #define __M4RI_USE_MM_MALLOC		(__M4RI_HAVE_MM_MALLOC && __M4RI_HAVE_SSE2)
 #define __M4RI_USE_POSIX_MEMALIGN	(__M4RI_HAVE_POSIX_MEMALIGN && __M4RI_HAVE_SSE2)
+#define __M4RI_DD_QUIET			(@M4RI_DEBUG_MZD@ && !@M4RI_DEBUG_DUMP@)
 
 #endif // M4RI_M4RI_CONFIG_H