Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
name: Formatting Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Run clang-format style check for C/C++/Protobuf programs.
uses: jidicula/clang-format-action@v4.15.0
with:
Expand Down Expand Up @@ -46,7 +46,7 @@ jobs:
enable_fortran_tests: true
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Install common packages
run: |
Expand Down
98 changes: 94 additions & 4 deletions containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "debug.h"
#include "typedefs.h"
#include <initializer_list>

namespace __otfcpt {

Expand All @@ -19,6 +20,98 @@ template <typename T> struct Hash<T *> {
}
};

template <typename T, std::size_t N> class Array {
protected:
T begin_[N]{}; // zero‑initialized (if T is POD)
public:
constexpr Array() = default;
// -------------------------------------------------
// list constructor
// -------------------------------------------------
//  Not declared as `explicit`, so that
//  copy‑list‑initialization (`Array a = {…}`) works.
constexpr Array(std::initializer_list<T> init) noexcept {
DCHECK_LE(init.size(), N);

// Copy values from initializer list to the internal
size_t i = 0;
for (auto elem : init) {
begin_[i++] = elem;
}

// Init remaining elements to default initializer
for (i = init.size(); i < N; i++) {
begin_[i] = T{};
}
}

constexpr std::size_t size() const { return N; }
constexpr T *data() { return begin_; }
constexpr const T *data() const { return begin_; }
constexpr T *begin() { return begin_; }
constexpr const T *begin() const { return begin_; }
constexpr T *end() { return begin_ + N; }
constexpr const T *end() const { return begin_ + N; }
constexpr const T &operator[](uptr i) const {
DCHECK_LT(i, N);
return begin_[i];
}
constexpr T &operator[](uptr i) {
DCHECK_LT(i, N);
return begin_[i];
}
/* -------------------------------------------------
operator+= -- elementwise addition
------------------------------------------------- */
// only activ, if both elements have same base type
template <typename U>
constexpr std::enable_if_t<std::is_same_v<T, U>, Array &> operator+=(
const Array<U, N> &rhs) noexcept(std::is_nothrow_assignable_v<T &, T>) {
// std::transform might be elegant, but a simple loop avoids dependency to
// <algorithm>.
for (std::size_t i = 0; i < N; ++i) {
begin_[i] += rhs.begin_[i];
}
return *this;
}
/* -------------------------------------------------
operator+ -- using operator+=
------------------------------------------------- */
// implemented as non-member function, so that
// lhs and rhs can be implizitly converted.
template <typename U>
friend constexpr std::enable_if_t<std::is_same_v<T, U>, Array<T, N>>
operator+(Array<T, N> lhs, const Array<U, N> &rhs) noexcept {
lhs += rhs; // using above += operator
return lhs; // Return‑By‑Value (RVO / NRVO)
}
/* -------------------------------------------------
operator-= -- elementwise substraction
------------------------------------------------- */
// only activ, if both elements have same base type
template <typename U>
constexpr std::enable_if_t<std::is_same_v<T, U>, Array &> operator-=(
const Array<U, N> &rhs) noexcept(std::is_nothrow_assignable_v<T &, T>) {
// std::transform might be elegant, but a simple loop avoids dependency to
// <algorithm>.
for (std::size_t i = 0; i < N; ++i) {
begin_[i] -= rhs.begin_[i];
}
return *this;
}
/* -------------------------------------------------
operator- -- using operator-=
------------------------------------------------- */
// implemented as non-member function, so that
// lhs and rhs can be implizitly converted.
template <typename U>
friend constexpr std::enable_if_t<std::is_same_v<T, U>, Array<T, N>>
operator-(Array<T, N> lhs, const Array<U, N> &rhs) noexcept {
lhs -= rhs; // using above -= operator
return lhs; // Return‑By‑Value (RVO / NRVO)
}
};

template <typename T> class Vector {
public:
Vector() : begin_(), end_(), last_() {}
Expand Down Expand Up @@ -171,10 +264,7 @@ template <typename K, typename V> class CompactHashMap {
using const_iterator = const I *;
CompactHashMap() {}

~CompactHashMap() {
if (begin_)
free(begin_);
}
~CompactHashMap() { Reset(); }

// Default copy constructor would lead to double-free
CompactHashMap(const CompactHashMap &) = delete;
Expand Down
2 changes: 2 additions & 0 deletions debug.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "debug.h"

#include "containers.h"
#include "parse_flags.h"
#include "typedefs.h"
#include <execinfo.h>
Expand Down
2 changes: 1 addition & 1 deletion debug.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef DEBUG_H
#define DEBUG_H

#include "containers.h"
#include "typedefs.h"
#include <initializer_list>
#include <mutex>
Expand Down Expand Up @@ -100,6 +99,7 @@ void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2,
#define DCHECK_EQ_VA(a, b, ...) CHECK_EQ_VA(a, b, __VA_ARGS__)
#else
#define DCHECK(a)
#define DCHECK_NOT(a)
#define DCHECK_EQ(a, b)
#define DCHECK_NE(a, b)
#define DCHECK_LT(a, b)
Expand Down
4 changes: 3 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ add_custom_target(build-tests)
add_custom_target(build-mpi-only-tests)
add_custom_target(build-omp-only-tests)
add_custom_target(build-hybrid-tests)
add_custom_target(build-container-tests)
add_dependencies(build-omp-only-tests OTFCPT OTFCPT_omp)
add_dependencies(build-mpi-only-tests OTFCPT OTFCPT_omp)
add_dependencies(build-hybrid-tests OTFCPT OTFCPT_omp)
add_dependencies(build-tests build-mpi-only-tests build-omp-only-tests build-hybrid-tests)
add_dependencies(build-tests build-mpi-only-tests build-omp-only-tests build-hybrid-tests build-container-tests)
if (TARGET FileCheck_Standalone AND BUILD_FILECHECK)
add_dependencies(build-tests FileCheck_Standalone)
endif()
Expand All @@ -74,6 +75,7 @@ ENDIF()
add_subdirectory(datastructures)
add_subdirectory(mpi-only)

add_subdirectory(containers)
if(OpenMP_C_FOUND)
add_subdirectory(hybrid)
add_subdirectory(omp-only)
Expand Down
15 changes: 15 additions & 0 deletions tests/containers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Output/)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/Output/)
set(CMAKE_EXECUTABLE_SUFFIX_C .c.tmp)
set(CMAKE_EXECUTABLE_SUFFIX_CXX .cpp.tmp)

set(containerTests
array
)

include_directories(../../)

FOREACH(tests ${containerTests})
add_executable(${tests} ${tests}.cpp ../../debug.cpp ../../parse_flags.cpp)
add_dependencies(build-container-tests ${tests})
ENDFOREACH()
19 changes: 19 additions & 0 deletions tests/containers/array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// clang-format off
// RUN: %t
// clang-format on

#include "containers.h"

int main() {
Array<int, 5> A = {{1, 2, 3, 4, 5}}, B{};
for (auto b : B)
CHECK_EQ(b, 0);
for (int i = 0; i < A.size(); i++)
CHECK_EQ(A[i], i + 1);
B += A;
for (int i = 0; i < B.size(); i++)
CHECK_EQ(B[i], i + 1);
B -= A;
for (auto b : B)
CHECK_EQ(b, 0);
}