Skip to content

Instantly share code, notes, and snippets.

@DBJDBJ

DBJDBJ/modern_matrix

Last active Jul 23, 2021
Embed
What would you like to do?
Very simple but light and probably fast 2D array. C++17. Version 6. Types left in here, from std lib are in just for testing code. Used Visual Studio 2019 and clang-cl .
// exactly the same as: https://godbolt.org/z/v1zhb7Er8
#define DBJ_MTX_TESTING
// (c) 2019-2021 by dbj@dbj.org
// License: CC BY SA 4.0
#include <iomanip> // setw
#include <sstream>
#include <assert.h>
#include <string.h> // memcoy
namespace dbj::mtx {
enum class version { major = 6, minor = 0, patch = 0 };
constexpr auto MAX_STACK_BLOCK = 0xFF;
constexpr auto MAX_HEAP_BLOCK = 0xFFFF;
////////////////////////////////////////////////////////////////////////////////////////
// ntdll.dll does not like you naming thigs data_ or data
template< typename T, size_t N >
inline auto simple_stack() noexcept {
static_assert(N < MAX_STACK_BLOCK, "max stack block is 0xFF");
T buff_[N]{};
return[buff_, size = N](size_t const& idx) mutable->T& {
assert(idx < size);
return buff_[idx];
};
}
template< typename T, size_t N >
inline auto simple_heap() noexcept
{
static_assert(N < MAX_HEAP_BLOCK, "max heap block is 0xFFFF");
struct heap
{
size_t size{ N };
// has to be proper copy/move able struct
// heap allocated block is not copy/moved by compiler
// seeing bellow compiler does not know the block size
T* block{};
heap() noexcept : block((T*)calloc(N, sizeof(T))) { assert(block); }
~heap() noexcept { if (block) { free(block); block = nullptr; } }
void copy(heap& left, heap const& right) noexcept {
assert(left.block);
assert(left.size == right.size);
::memcpy(left.block, right.block, left.size);
}
heap(heap const& other_) noexcept : block((T*)calloc(N, sizeof(T))) {
copy(*this, other_);
}
heap& operator = (heap const& other_) noexcept {
copy(*this, other_); return *this;
}
void swap(heap& left, heap& right) noexcept {
using namespace std;
left.size = right.size;
left.block = right.block;
right.block = nullptr;
}
heap(heap&& other_) noexcept {
swap(*this, other_);
}
heap& operator = (heap&& other_) noexcept {
swap(*this, other_); return *this;
}
};
return[heap_instance_ = heap{}, size = N](size_t const& idx) mutable->T& {
assert(idx < size);
return heap_instance_.block[idx];
};
}
////////////////////////////////////////////////////////////////////////////////////////
template< typename T, size_t rows, size_t cols, typename F >
inline constexpr auto mx(F source_)
{
return[arry = source_()]
(size_t row_, size_t col_) mutable->T&
{
assert(row_ < rows);
assert(col_ < cols);
return arry(row_ * rows + col_);
};
} // mx
#undef dbj_mx_make
#undef dbj_mx_make_heap
#undef dbj_mx_make_stack
#define dbj_mx_make(T, R, C, K) dbj::mtx::mx<T, R, C>(dbj::mtx::K<T, (R+1) * (C+1)>)
#define dbj_mx_make_heap(T,R,C) dbj_mx_make(T, R, C, simple_heap)
#define dbj_mx_make_stack(T,R,C) dbj_mx_make(T, R, C, simple_stack)
///
/// Testing
///
#ifdef DBJ_MTX_TESTING
inline auto changer = [](auto matrix_, size_t row_, size_t col_, auto value_) {
matrix_(row_, col_) = value_;
return matrix_;
};
// print to buffer
// NOTE: compared to C, this is almost tragi-comical code
inline auto
printer = [](auto matrix_, size_t width_, size_t height_)
-> std::string {
using namespace std;
std::ostringstream rez_;
for (size_t row_ = 0; row_ < width_; row_++) {
rez_ << "\n";
for (size_t col_ = 0; col_ < height_; col_++) {
rez_ << setw(3) << matrix_(row_, col_) << " ";
}
}
rez_ << "\n";
return rez_.str();
};
///
/// log callback signature:
/// void (*)( std::string_view )
///
template<
typename log_callback,
typename value_type = int,
size_t width_ = 3, // 0,1,2
size_t height_ = 3, // 0,1,2
size_t last_col_ = width_ - 1, // 0,1,2
size_t last_row_ = height_ - 1 // 0,1,2
>
inline void test_dbj_matrix_creation(log_callback log, value_type const& val_)
{
using namespace dbj::mtx;
using namespace std;
// test move in, move out and the rest
auto reporter = [&](auto matrix_, const char* prompt_) {
string report = prompt_ +
printer(changer(matrix_, last_col_, last_row_, val_), width_, height_);
log(report);
return matrix_;
};
(void)reporter(dbj_mx_make_stack(value_type, width_, height_),
"\n matrix_on_stack \n");
(void)reporter(dbj_mx_make_heap(value_type, width_, height_),
"\n matrix_on_heap \n");
}
#endif // DBJ_MTX_TESTING
} // dbj::mtx
///
/// log callback signature:
/// void (*)( std::string_view )
///
void log_(std::string_view sv)
{
printf("%s", sv.data());
}
int main(void)
{
dbj::mtx::test_dbj_matrix_creation(log_, 42);
dbj::mtx::test_dbj_matrix_creation(log_, 42.42f);
return 42;
}
@DBJDBJ

This comment has been minimized.

Copy link
Owner Author

@DBJDBJ DBJDBJ commented Mar 16, 2021

Please read this https://dbj.org/lambda-powered-matrix/ beforehand

@DBJDBJ

This comment has been minimized.

Copy link
Owner Author

@DBJDBJ DBJDBJ commented Jul 23, 2021

Copied over the source from: https://godbolt.org/z/v1zhb7Er8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment