File Debug.h¶
Go to the documentation of this file
#pragma once
// TODO: this file has the downside, that it defines ostream operators and formatToVec for specific types. This means, that files that define these
// types cannot include this file, due to circular dependencies. In order to improve this, the ostream operators and formatToVec functions should be
// moved to the files that define these types.
#include <array>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
// This include is necessary, as Debug implements a special formatting for Ray.
#include "Rays.h"
#include "Shader/Ray.h"
// Debug only code; use it as: DEBUG(<statement>);
#ifdef RAYX_DEBUG_MODE
#define RAYX_DEBUG(x) (x)
#else
#define RAYX_DEBUG(x) \
do { \
} while (0)
#endif
#define STRING(s) #s
namespace rayx {
// OSTREAM CONVERSION
inline std::ostream& operator<<(std::ostream& os, const complex::Complex& c) { return os << "{" << c.real() << ", " << c.imag() << "}"; }
template <typename T>
inline std::ostream& operator<<(std::ostream& os, const glm::tvec2<T>& v) {
return os << "{" << v.x << ", " << v.y << "}";
}
template <typename T>
inline std::ostream& operator<<(std::ostream& os, const glm::tvec3<T>& v) {
return os << "{" << v.x << ", " << v.y << ", " << v.z << "}";
}
template <typename T>
inline std::ostream& operator<<(std::ostream& os, const glm::tvec4<T>& v) {
return os << "{" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << "}";
}
// LOGGING SYSTEM
// activates / deactivates the printing of RAYX_VERB "verbose" prints.
void RAYX_API setDebugVerbose(bool);
// reads the "verbose" flag.
bool RAYX_API getDebugVerbose();
// The implementation of RAYX_LOG
struct RAYX_API Log {
Log(std::string filename, int line);
~Log();
template <typename T>
Log& operator<<(T t) {
std::cout << t;
return *this;
}
};
// The implementation of RAYX_WARN
struct RAYX_API Warn {
Warn(std::string filename, int line);
~Warn();
template <typename T>
Warn& operator<<(T t) {
std::cerr << t;
return *this;
}
};
// The implementation of RAYX_EXIT
struct RAYX_API Exit {
std::string filename;
int line;
Exit(const std::string& filename, int line);
~Exit();
template <typename T>
Exit& operator<<(T t) {
std::cerr << t;
return *this;
}
};
// The implementation of RAYX_VERB
struct RAYX_API Verb {
Verb(std::string filename, int line);
~Verb();
template <typename T>
Verb& operator<<(T t) {
if (getDebugVerbose()) { std::cout << t; }
return *this;
}
};
// An empty implementation used in release when using "debug-only" prints like RAYX_D_LOG.
struct RAYX_API IgnoreLog{template <typename T> IgnoreLog & operator<<(T){return *this;
} // namespace rayx
}
;
// the function to be called after RAYX_EXIT happens.
// normally exit(1), but in the test suite it's ADD_FAILURE.
extern void RAYX_API (*error_fn)();
// Defines the actual RAYX logging macros using the structs defined above.
// The __FILE__ and __LINE__ macros contain the current filename and linenumber.
// They are defined for us by c++ https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
#define RAYX_LOG rayx::Log(__FILE__, __LINE__)
#define RAYX_WARN rayx::Warn(__FILE__, __LINE__)
#define RAYX_EXIT rayx::Exit(__FILE__, __LINE__)
#define RAYX_VERB rayx::Verb(__FILE__, __LINE__)
#ifdef RAYX_DEBUG_MODE
// In debug mode, RAYX_D_LOG is just the same as RAYX_LOG.
#define RAYX_D_LOG RAYX_LOG
#define RAYX_D_WARN RAYX_WARN
#define RAYX_D_ERR RAYX_EXIT
#define RAYX_D_VERB RAYX_VERB
#else
// In release mode, RAYX_D_LOG instead calls the IgnoreLog, hence discarding the print.
#define RAYX_D_LOG rayx::IgnoreLog()
#define RAYX_D_WARN rayx::IgnoreLog()
#define RAYX_D_ERR rayx::IgnoreLog()
#define RAYX_D_VERB rayx::IgnoreLog()
#endif
// COLLECTION DEBUGGING SYSTEM
/*
*
* In the following we define
* RAYX_DBG: prints collection to RAYX_LOG for debugging
*
* example usage:
* RAYX_DBG(orientation);
* RAYX_DBG(position);
* */
// catch any unimplemented usage of formatAsVec
template <typename T>
inline std::vector<double> formatAsVec(T) {
// abort compilation and print type T
[[maybe_unused]] typedef typename T::something_made_up X;
return {};
}
inline std::vector<double> formatAsVec(int arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(RandCounter arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(EventType arg) { return {static_cast<double>(arg)}; }
inline std::vector<double> formatAsVec(double arg) { return {arg}; }
inline std::vector<double> formatAsVec(complex::Complex arg) { return {arg.real(), arg.imag()}; }
template <int N, int M, typename T>
inline std::vector<double> formatAsVec(const glm::mat<N, M, T> arg) {
std::vector<double> out;
for (size_t i = 0; i < N * M; i++) {
auto data = formatAsVec(arg[i / N][i % N]);
out.insert(out.end(), data.begin(), data.end());
}
return out;
}
template <int N, typename T>
inline std::vector<double> formatAsVec(const glm::vec<N, T> arg) {
std::vector<double> out;
for (size_t i = 0; i < N; i++) {
auto data = formatAsVec(arg[i]);
out.insert(out.end(), data.begin(), data.end());
}
return out;
}
template <size_t N, typename T>
inline std::vector<double> formatAsVec(const std::array<T, N> arg) {
std::vector<double> out;
for (size_t i = 0; i < N; i++) {
auto data = formatAsVec(arg[i]);
out.insert(out.end(), data.begin(), data.end());
}
return out;
}
template <typename T>
inline std::vector<double> formatAsVec(const std::vector<T> arg) {
std::vector<double> out;
for (size_t i = 0; i < arg.size(); i++) {
auto data = formatAsVec(arg[i]);
out.insert(out.end(), data.begin(), data.end());
}
return out;
}
template <>
inline std::vector<double> formatAsVec<double>(const std::vector<double> arg) {
return arg;
}
inline std::vector<double> formatAsVec(const Rays& rays) {
std::vector<double> out;
auto insert = [&out](const std::vector<double>& v) { out.insert(out.end(), v.begin(), v.end()); };
#define X(type, name, flag) insert(formatAsVec(rays.name));
RAYX_X_MACRO_RAY_ATTR
#undef X
return out;
}
void dbg(const std::string& filename, int line, std::string name, std::vector<double> v);
#define RAYX_DBG(C) rayx::dbg(__FILE__, __LINE__, #C, rayx::formatAsVec(C))
} // namespace RAYX