Skip to content

Instantly share code, notes, and snippets.

@DBJDBJ

DBJDBJ/modern_matrix

Last active Mar 18, 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 .
#pragma once
// (c) 2019-2021 by dbj@dbj.org
// License: CC BY SA 4.0
#include <iomanip> // setw
#include <sstream>
#include <assert.h>
#define DBJ_MAX_HEAP_CHUNK 0xFFFF
#define DBJ_MAX_STACK_CHUNK 0xFF
namespace dbj::mtx {
enum class version { major = 6, minor = 0, patch = 0 };
////////////////////////////////////////////////////////////////////////////////////////
// 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 < DBJ_MAX_STACK_CHUNK, __FILE__": bigger than DBJ_MAX_STACK_CHUNK");
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 < DBJ_MAX_HEAP_CHUNK, __FILE__ ": bigger than DBJ_MAX_HEAP_CHUNK") ;
// very minimal heap block holder (inner class),
// instance can be moved and copied arround
// note: inner classes have limitations imposed by language
struct heap
{
size_t size{ N };
// has to be proper copy/move able struct
// heap allocated block is not copy/moved by compiler
// seeing this pointer 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;
}
// inner class -- not a proper swap
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];
};
}
////////////////////////////////////////////////////////////////////////////////////////
/// practicaly this is the matrix aka 2D array
/// 'arry' aka array is instance of lambda actually holding the
/// heap or stack made memory block
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
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_ << endl << "{";
for (size_t col_ = 0; col_ < height_; col_++) {
rez_ << setw(3) << matrix_(row_, col_) << " ";
}
rez_ << "}";
}
rez_ << endl;
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
//
// how to test:
//
// void log_(std::string_view sv)
// {
// printf("%s", sv.data());
// }
//
// int main()
// {
// 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

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