From f4061d9534e32de1642519941045f80c16d79bf2 Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Tue, 20 Nov 2018 16:25:52 +0700 Subject: [PATCH] add rcarray C++ header (#160) * add rcarray C++ header --- .travis.yml | 22 +++++--- cpp_example/eye.d | 12 ++++- cpp_example/init_rcarray.d | 20 +++++++ cpp_example/main.cpp | 24 +++++++++ cpp_example/meson.build | 7 +++ cpp_example/run.sh | 2 +- include/mir/ndslice.h | 16 +++++- include/mir/rcarray.h | 103 +++++++++++++++++++++++++++++++++++++ include/mir/series.h | 6 +++ meson.build | 16 +++++- source/mir/rcarray.d | 24 ++++++--- 11 files changed, 234 insertions(+), 18 deletions(-) create mode 100644 cpp_example/init_rcarray.d create mode 100644 cpp_example/meson.build create mode 100644 include/mir/rcarray.h diff --git a/.travis.yml b/.travis.yml index e519f5a1..542dd930 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,14 @@ language: d sudo: required +addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-5.0 + packages: + - g++-7 + - gcc-7-multilib + - clang-5.0 packages: - pkg-config d: @@ -12,13 +21,14 @@ branches: only: - master env: - - ARCH="x86_64" + - CC="clang-5.0" CXX="clang++-5.0" ARCH="x86_64" + matrix: include: - - {os: linux, d: ldc-beta, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} - - {os: linux, d: ldc, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} - - {os: linux, d: dmd-beta, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} - - {os: linux, d: dmd, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} + - {os: linux, d: ldc-beta, env: CC="clang-5.0" CXX="clang++-5.0" ARCH="x86"} + - {os: linux, d: ldc, env: CC="clang-5.0" CXX="clang++-5.0" ARCH="x86"} + - {os: linux, d: dmd-beta, env: CC="clang-5.0" CXX="clang++-5.0" ARCH="x86"} + - {os: linux, d: dmd, env: CC="clang-5.0" CXX="clang++-5.0" ARCH="x86"} allow_failures: - {d: dmd-nightly} - {d: ldc-beta} @@ -37,7 +47,7 @@ script: - travis_wait 100 dub test --arch "$ARCH" --build=unittest-cov - travis_wait 100 dub test --arch "$ARCH" -c dips - ./test_examples.sh - - meson build -D with_test=true && cd build && ninja -j4 && ninja -j4 test -v && cd .. # TODO: 32bit meson test + - meson build -D with_test=true --default-library=static && cd build && ninja -j4 && ninja -j4 test -v && cd .. # TODO: 32bit meson test # - travis_wait 100 dub test --arch "$ARCH" --build=unittest-release after_success: diff --git a/cpp_example/eye.d b/cpp_example/eye.d index dd912131..684ef322 100644 --- a/cpp_example/eye.d +++ b/cpp_example/eye.d @@ -12,7 +12,7 @@ extern(C++, Space) return ret; } - void printMatrix(Slice!(double*, 2) matrix) + void printMatrix(mir_slice!(double*, 2) matrix) { import core.stdc.stdio; @@ -24,3 +24,13 @@ extern(C++, Space) } } } + + +// Space::printMatrix(mir_slice) +// Space::printMatrix(mir_slice) +// Space::reverseRcSlice(mir_slice, 1ull, (mir_slice_kind)2>&) + +//Space::printMatrix(mir_slice) + + +pragma(msg, printMatrix.mangleof); \ No newline at end of file diff --git a/cpp_example/init_rcarray.d b/cpp_example/init_rcarray.d new file mode 100644 index 00000000..a73a4fc5 --- /dev/null +++ b/cpp_example/init_rcarray.d @@ -0,0 +1,20 @@ +module init_rcarray; + +import mir.ndslice; +import mir.rcarray; + +extern(C++, Space) +{ + void initWithIota(ref RCArray!double a) + { + foreach(i, ref e; a) + e = i; + } + + void reverseRcSlice(ref Slice!(RCI!double) a) + { + import mir.utility: swap; + foreach(i; 0 .. a.length / 2) + swap(a[i], a[$ - 1 - i]); + } +} diff --git a/cpp_example/main.cpp b/cpp_example/main.cpp index ce221ade..cc5a1c89 100644 --- a/cpp_example/main.cpp +++ b/cpp_example/main.cpp @@ -1,10 +1,15 @@ +#include +#include #include +#include "mir/rcarray.h" #include "mir/ndslice.h" namespace Space { mir_slice eye(size_t n); void printMatrix(mir_slice matrix); + void initWithIota(mir_rcarray &a); + void reverseRcSlice(mir_slice>& a); } int main() @@ -12,5 +17,24 @@ int main() mir_slice matrix = Space::eye(3); Space::printMatrix(matrix); std::free(matrix._iterator); + + + // test rcarray constructors and destructors + mir_rcarray a(3); // [NaN, NaN, NaN] + assert(a.size() == 3); + + Space::initWithIota(a); //[0, 1, 2] + auto b = a; // check copy constructor + auto c = b.asSlice(); + auto d = c; // check copy constructor + Space::reverseRcSlice(d); //[2, 1, 0] + + // reversed 0 1 2 (iota) + assert(a[0] == 2); + assert(a[1] == 1); + assert(a[2] == 0); + + assert(d._iterator._iterator == a.data()); + return 0; } diff --git a/cpp_example/meson.build b/cpp_example/meson.build new file mode 100644 index 00000000..519c83e3 --- /dev/null +++ b/cpp_example/meson.build @@ -0,0 +1,7 @@ +mir_algorithm_cpp_test_exe = executable(meson.project_name() + '-test', + ['eye.d', 'init_rcarray.d', 'main.cpp'], + include_directories: mir_algorithm_dir, + dependencies: mir_algorithm_dep, +) + +test(meson.project_name() + '-cpp-test', mir_algorithm_cpp_test_exe) diff --git a/cpp_example/run.sh b/cpp_example/run.sh index c2f94bf4..abf24d0f 100644 --- a/cpp_example/run.sh +++ b/cpp_example/run.sh @@ -1,3 +1,3 @@ -ldmd2 -betterC -O -inline -release eye.d -I../source -c +ldmd2 -betterC -O -inline -release eye.d init_rcarray.d -I../source -c g++ main.cpp eye.o -std=c++11 -I../include ./a.out diff --git a/include/mir/ndslice.h b/include/mir/ndslice.h index 3c522565..bbe3a3d1 100644 --- a/include/mir/ndslice.h +++ b/include/mir/ndslice.h @@ -8,6 +8,11 @@ License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Copyright: Copyright © 2017-, Ilya Yaroshenko Authors: Ilya Yaroshenko */ + +#ifndef MIR_NDSLICE + +#define MIR_NDSLICE + #include #include @@ -15,8 +20,13 @@ Authors: Ilya Yaroshenko #define mir_size_t unsigned int #define mir_ptrdiff_t int #elif INTPTR_MAX == INT64_MAX - #define mir_size_t unsigned long long - #define mir_ptrdiff_t long long + #ifdef _WIN32 + #define mir_size_t unsigned long long + #define mir_ptrdiff_t long long + #else + #define mir_size_t unsigned long + #define mir_ptrdiff_t long + #endif #else #error "Environment not 32 or 64-bit." #endif @@ -40,3 +50,5 @@ struct mir_slice mir_ptrdiff_t _strides[kind == mir_slice_kind::universal ? N : kind == mir_slice_kind::canonical ? N - 1 : 0]; Iterator _iterator; }; + +#endif diff --git a/include/mir/rcarray.h b/include/mir/rcarray.h new file mode 100644 index 00000000..23a04327 --- /dev/null +++ b/include/mir/rcarray.h @@ -0,0 +1,103 @@ +#ifndef MIR_RCARRAY + +#define MIR_RCARRAY + +#include +#include +#include "mir/ndslice.h" + +template +struct mir_rci; + +template +struct mir_rcarray +{ +private: + + void* _context; + +public: + + ~mir_rcarray(); + mir_rcarray(mir_rcarray& rhs); + bool initialize(size_t length, unsigned int alignment, bool deallocate, bool initialize); + + mir_slice> asSlice(); + + inline mir_rcarray(size_t length, unsigned int alignment = alignof(T), bool deallocate = true, bool initialize = true) + { + if (!this->initialize(length, alignment, deallocate, initialize)) + { + throw std::runtime_error("mir_rcarray: out of memory arror."); + } + } + + inline size_t size() noexcept + { + return _context ? *(size_t*)((char*)_context + sizeof(void*)) : 0; + } + + inline T& at(size_t index) + { + assert(index < this->size()); + return ((T*)((char*)_context + sizeof(void*) * 4))[index]; + } + + inline const T& at(size_t index) const + { + assert(index < this->size()); + return ((const T*)((char*)_context + sizeof(void*) * 4))[index]; + } + + inline T& operator[](size_t index) + { + assert(index < this->size()); + return ((T*)((char*)_context + sizeof(void*) * 4))[index]; + } + + inline const T& operator[](size_t index) const + { + assert(index < this->size()); + return ((const T*)((char*)_context + sizeof(void*) * 4))[index]; + } + + inline T* data() noexcept + { + return _context ? (T*)((char*)_context + sizeof(void*) * 4) : NULL; + } + + inline T* begin() noexcept + { + return _context ? (T*)((char*)_context + sizeof(void*) * 4) : NULL; + } + + inline const T* cbegin() const noexcept + { + return _context ? (const T*)((char*)_context + sizeof(void*) * 4) : NULL; + } + + inline T* end() noexcept + { + return this->begin() + this->size(); + } + + inline const T* cend() const noexcept + { + return this->cbegin() + this->size(); + } +}; + + +template +struct mir_rci +{ +public: + + T* _iterator; + mir_rcarray _array; + + ~mir_rci() = default; + mir_rci(mir_rci& rhs) = default; +}; + +#endif diff --git a/include/mir/series.h b/include/mir/series.h index d01434d5..8035a68d 100644 --- a/include/mir/series.h +++ b/include/mir/series.h @@ -1,3 +1,7 @@ +#ifndef MIR_SERIES + +#define MIR_SERIES + #include "mir/ndslice.h" template < @@ -21,3 +25,5 @@ struct mir_series mir_slice _data; IndexIterator _index; }; + +#endif diff --git a/meson.build b/meson.build index d8dc6597..dd004065 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,16 @@ -project('mir-algorithm', 'd', version : '3.1.0', license: 'BSL-1.0') +project('mir-algorithm', 'cpp', 'd', version : '3.1.0', license: 'BSL-1.0', + default_options : ['cpp_std=c++1z']) + + +add_global_arguments([ + '-dip1008', + ], language: 'd') + +add_project_arguments([ + '-dip25', + '-dip1000', + ], language: 'd') + mir_algorithm_dir = include_directories('source/', 'include/') @@ -89,4 +101,6 @@ if get_option('with_test') test(meson.project_name() + '-test', mir_algorithm_test_exe) + subdir('cpp_example') + endif diff --git a/source/mir/rcarray.d b/source/mir/rcarray.d index 02306788..f39cf181 100644 --- a/source/mir/rcarray.d +++ b/source/mir/rcarray.d @@ -136,11 +136,20 @@ struct mir_rcarray(T) } /// + pragma(inline, false) this(ref typeof(this) rhs) pure nothrow @nogc { this._context = rhs._context; this.__xpostblit; } + + /// + auto asSlice() scope return @property + { + import mir.ndslice.slice: mir_slice; + alias It = mir_rci!T; + return mir_slice!It([length], It((()@trusted => ptr)(), this)); + } } else { @@ -156,6 +165,14 @@ struct mir_rcarray(T) { return initializeImpl(length, alignment, deallocate, initialize); } + + /// + auto asSlice()() scope return @property + { + import mir.ndslice.slice: mir_slice; + alias It = mir_rci!T; + return mir_slice!It([length], It((()@trusted => ptr)(), this)); + } } /// @@ -344,13 +361,6 @@ struct mir_rcarray(T) { return _context !is null ? _context.length : 0; } - - auto asSlice()() scope return @property - { - import mir.ndslice.slice: mir_slice; - alias It = mir_rci!T; - return mir_slice!It([length], It((()@trusted => ptr)(), this)); - } } /// ditto