Program Listing for File misc.h
↰ Return to documentation for file (include/amici/misc.h
)
#ifndef AMICI_MISC_H
#define AMICI_MISC_H
#include "amici/defines.h"
#include "amici/exception.h"
#include "amici/vector.h"
#include <sunmatrix/sunmatrix_sparse.h> // SUNMatrixContent_Sparse
#include <algorithm>
#include <ctime>
#include <functional>
#include <regex>
#include <vector>
#ifdef HAS_BOOST_CHRONO
#include <boost/chrono/thread_clock.hpp>
#endif
#include <gsl/gsl-lite.hpp>
namespace amici {
template <class T>
gsl::span<T> slice(std::vector<T>& data, int index, unsigned size) {
if ((index + 1) * size > data.size())
throw std::out_of_range("requested slice is out of data range");
if (size > 0)
return gsl::make_span(&data.at(index * size), size);
return gsl::make_span(static_cast<T*>(nullptr), 0);
}
template <class T>
gsl::span<T const> slice(std::vector<T> const& data, int index, unsigned size) {
if ((index + 1) * size > data.size())
throw std::out_of_range("requested slice is out of data range");
if (size > 0)
return gsl::make_span(&data.at(index * size), size);
return gsl::make_span(static_cast<T*>(nullptr), 0);
}
template <class T>
void checkBufferSize(
gsl::span<T> buffer, typename gsl::span<T>::index_type expected_size
) {
if (buffer.size() != expected_size)
throw AmiException(
"Incorrect buffer size! Was %u, expected %u.", buffer.size(),
expected_size
);
}
/* TODO: templating writeSlice breaks implicit conversion between vector & span
not sure whether this is fixable */
template <class T>
void writeSlice(gsl::span<T const> const slice, gsl::span<T> buffer) {
checkBufferSize(buffer, slice.size());
std::copy(slice.begin(), slice.end(), buffer.data());
};
template <class T>
void addSlice(gsl::span<T const> const slice, gsl::span<T> buffer) {
checkBufferSize(buffer, slice.size());
std::transform(
slice.begin(), slice.end(), buffer.begin(), buffer.begin(),
std::plus<T>()
);
};
template <class T> void writeSlice(std::vector<T> const& s, std::vector<T>& b) {
writeSlice(
gsl::make_span(s.data(), s.size()), gsl::make_span(b.data(), b.size())
);
};
template <class T> void writeSlice(std::vector<T> const& s, gsl::span<T> b) {
writeSlice(gsl::make_span(s.data(), s.size()), b);
};
template <class T> void addSlice(std::vector<T> const& s, gsl::span<T> b) {
addSlice(gsl::make_span(s.data(), s.size()), b);
};
void writeSlice(AmiVector const& s, gsl::span<realtype> b);
void unscaleParameters(
gsl::span<realtype const> bufferScaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferUnscaled
);
double getUnscaledParameter(double scaledParameter, ParameterScaling scaling);
double getScaledParameter(double unscaledParameter, ParameterScaling scaling);
void scaleParameters(
gsl::span<realtype const> bufferUnscaled,
gsl::span<ParameterScaling const> pscale, gsl::span<realtype> bufferScaled
);
std::string backtraceString(int maxFrames, int const first_frame = 0);
std::string regexErrorToString(std::regex_constants::error_type err_type);
std::string printfToString(char const* fmt, va_list ap);
class ContextManager {
public:
ContextManager() = default;
ContextManager(ContextManager& other) = delete;
ContextManager(ContextManager&& other) = delete;
};
auto unravel_index(size_t flat_idx, size_t num_cols)
-> std::pair<size_t, size_t>;
template <class T> bool is_equal(T const& a, T const& b) {
if (a.size() != b.size())
return false;
auto a_data = a.data();
auto b_data = b.data();
for (typename T::size_type i = 0; i < a.size(); ++i) {
if (a_data[i] != b_data[i]
&& !(std::isnan(a_data[i]) && std::isnan(b_data[i])))
return false;
}
return true;
}
#ifdef BOOST_CHRONO_HAS_THREAD_CLOCK
class CpuTimer {
using clock = boost::chrono::thread_clock;
using time_point = clock::time_point;
using d_seconds = boost::chrono::duration<double>;
using d_milliseconds = boost::chrono::duration<double, boost::milli>;
public:
CpuTimer()
: start_(clock::now()) {}
void reset() { start_ = clock::now(); }
double elapsed_seconds() const {
return d_seconds(clock::now() - start_).count();
}
double elapsed_milliseconds() const {
return d_milliseconds(clock::now() - start_).count();
}
static bool const uses_thread_clock = true;
private:
time_point start_;
};
#else
class CpuTimer {
public:
CpuTimer()
: start_(std::clock()) {}
void reset() { start_ = std::clock(); }
double elapsed_seconds() const {
return static_cast<double>(std::clock() - start_) / CLOCKS_PER_SEC;
}
double elapsed_milliseconds() const {
return static_cast<double>(std::clock() - start_) * 1000.0
/ CLOCKS_PER_SEC;
}
static bool const uses_thread_clock = false;
private:
std::clock_t start_;
};
#endif
} // namespace amici
#endif // AMICI_MISC_H