common.hpp

This header file provides common definitions and utilities. It defines macros, types, and functions that are used across various components of the library.

Macros

SCTL_DATA_PATH:

This macro defines the path to the data directory used by the library. If not defined, it defaults to “./data/”.

SCTL_PROFILE:

This macro defines the granularity level for profiling. If not defined, it defaults to -1.

SCTL_ALIGN_BYTES:

This macro defines the alignment requirement for memory allocation based on the processor architecture.

SCTL_MEM_ALIGN:

This macro defines the alignment requirement for memory management. It defaults to the maximum of 64 and SCTL_ALIGN_BYTES.

SCTL_GLOBAL_MEM_BUFF:

This macro defines the size of the global memory buffer in MB used for memory management. It defaults to 0.

Functions

SCTL_WARN(msg):

Prints a warning message to the standard error stream.

SCTL_ERROR(msg):

Prints an error message to the standard error stream and aborts the program.

SCTL_ASSERT_MSG(cond, msg):

Asserts a condition and prints an error message if the condition is not met.

SCTL_ASSERT(cond):

Asserts a condition and prints an error message if the condition is not met, including file name, line number, and function name.

SCTL_UNUSED(x):

Macro to silence unused variable warnings.

Namespaces

sctl:

The namespace under which all SCTL components reside.

Classes and Types

sctl::ConstIterator:

Template class representing a constant iterator.

sctl::Iterator:

Template class representing a mutable iterator.

sctl::StaticArray:

Template class representing a static array.

  • Parameters:
    • ValueType: Type of elements in the array.

    • DIM: Dimension of the array.

If SCTL_MEMDEBUG is defined, these classes are defined with additional debugging functionality. Otherwise, they are defined as aliases for pointer types.

sctl::Integer:

Alias for a long integer type representing bounded numbers less than 32k.

sctl::Long:

Alias for a 64-bit integer type representing problem size.



#ifndef _SCTL_COMMON_HPP_
#define _SCTL_COMMON_HPP_

#include <stdio.h>      // for NULL, stderr
#include <stdlib.h>     // for abort
#include <cstdint>      // for int64_t
#include <iostream>     // for char_traits, basic_ostream, operator<<, cerr
#include <type_traits>  // for underlying_type_t (Periodicity helpers)

#ifndef SCTL_DATA_PATH
#  define SCTL_DATA_PATH ./data/
#endif

#ifdef _OPENMP
#include <omp.h>
#define SCTL_GET_WTIME()       (omp_get_wtime())
#define SCTL_GET_NUM_THREADS() (omp_get_num_threads())
#define SCTL_GET_MAX_THREADS() (omp_get_max_threads())
#define SCTL_GET_THREAD_NUM()  (omp_get_thread_num())
#define SCTL_IN_PARALLEL()     (omp_in_parallel())
#else
#include <chrono>
#define SCTL_GET_WTIME() \
    (std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch()).count())
#define SCTL_GET_NUM_THREADS() (1)
#define SCTL_GET_MAX_THREADS() (1)
#define SCTL_GET_THREAD_NUM()  (0)
#define SCTL_IN_PARALLEL()     (0)
#endif

#if defined(__AVX512__) || defined(__AVX512F__)
  #define SCTL_ALIGN_BYTES 64
#elif defined(__AVX__)
  #define SCTL_ALIGN_BYTES 32
#elif defined(__SSE__) || defined(__ARM_NEON)
  #define SCTL_ALIGN_BYTES 16
#else
  #define SCTL_ALIGN_BYTES 8
#endif

// Parameters for memory manager
#ifndef SCTL_MEM_ALIGN
#define SCTL_MEM_ALIGN (64 > SCTL_ALIGN_BYTES ? 64 : SCTL_ALIGN_BYTES)
#endif
#ifndef SCTL_GLOBAL_MEM_BUFF
#define SCTL_GLOBAL_MEM_BUFF 1024LL * 0LL  // in MB
#endif

namespace sctl {
typedef long Integer;  // bounded numbers < 32k
typedef int64_t Long;  // problem size

// Per-axis periodicity bitmask (bit d = axis d). Widen the underlying type for more than 8 axes.
enum class Periodicity : uint8_t {
  NONE = 0,
  X = 1u << 0,
  Y = 1u << 1,
  Z = 1u << 2,
  XY = X | Y,
  XYZ = X | Y | Z
};

using PeriodicityT = std::underlying_type_t<Periodicity>;
constexpr Integer PERIODICITY_MAX_DIM = static_cast<Integer>(sizeof(PeriodicityT) * 8);

constexpr Periodicity operator|(Periodicity a, Periodicity b) {
  return static_cast<Periodicity>(static_cast<PeriodicityT>(a) | static_cast<PeriodicityT>(b));
}

// True iff axis dim is periodic in p.
constexpr bool is_periodic(Periodicity p, Integer dim) {
  return ((static_cast<PeriodicityT>(p) >> dim) & PeriodicityT(1)) != 0;
}

// Mask with axes 0..dim-1 periodic.
constexpr Periodicity all_periodic(Integer dim) {
  return static_cast<Periodicity>(dim >= PERIODICITY_MAX_DIM ? static_cast<PeriodicityT>(~PeriodicityT(0))
                                                             : static_cast<PeriodicityT>((PeriodicityT(1) << dim) - 1));
}
}

#define SCTL_WARN(msg)                                         \
  do {                                                          \
    std::cerr << "\n\033[1;31mSCTL Warning:\033[0m " << msg << '\n'; \
  } while (0)

#define SCTL_ERROR(msg)                                      \
  do {                                                        \
    std::cerr << "\n\033[1;31mSCTL Error:\033[0m " << msg << '\n'; \
    abort();                                                  \
  } while (0)

#define SCTL_ASSERT_MSG(cond, msg) \
  do {                              \
    if (!(cond)) SCTL_ERROR(msg);  \
  } while (0)

#define SCTL_ASSERT(cond)                                                                                      \
  do {                                                                                                          \
    if (!(cond)) {                                                                                              \
      std::cerr << '\n' << __FILE__ << ':' << __LINE__ << ": " << __PRETTY_FUNCTION__                          \
                << ": SCTL Assertion `" << #cond << "' failed.\n";                                              \
      abort();                                                                                                  \
    }                                                                                                           \
  } while (0)

#define SCTL_UNUSED(x) (void)(x)  // to ignore unused variable warning.

namespace sctl {
#ifdef SCTL_MEMDEBUG
template <class ValueType> class ConstIterator;
template <class ValueType> class Iterator;
template <class ValueType, Long DIM> class StaticArray;
#else
template <typename ValueType> using Iterator = ValueType*;
template <typename ValueType> using ConstIterator = const ValueType*;
template <typename ValueType, Long DIM> using StaticArray = ValueType[DIM];
#endif
}

#endif // _SCTL_COMMON_HPP_