Skip to content

Commit

Permalink
Built include
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Jul 24, 2024
1 parent f65b443 commit 218dece
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 121 deletions.
55 changes: 19 additions & 36 deletions include/cxalgos/Search.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
// SOFTWARE.
#define CX_FINISHED
#ifndef CXSTRUCTS_BINARYSEARCH_H
# define CXSTRUCTS_BINARYSEARCH_H
#define CXSTRUCTS_BINARYSEARCH_H

# include <cstdint>
# include "../cxconfig.h"
#include <cstdint>
#include "../cxconfig.h"

namespace cxhelper { // helper methods to provide clean calling interface
template <typename T>
Expand Down Expand Up @@ -61,7 +61,8 @@ bool binary_search(T* arr, T target, int_32_cx len) {
mid = low + (high - low) / 2;
if (arr[mid] == target) {
return true;
} else if (arr[mid] < target) {
}
if (arr[mid] < target) {
low = mid + 1;
} else {
high = mid - 1;
Expand Down Expand Up @@ -89,6 +90,7 @@ bool binary_search_recursive(T* arr, T target, int_32_cx len) {
return cxhelper::binarySearch_recursive_internal(arr, target, 0, len - 1);
}

// Returns the index at which the element should be inserted
template <typename T>
int binary_search_index(T* arr, T target, int_32_cx len, bool ascending) {
if (ascending) {
Expand All @@ -103,41 +105,22 @@ int binary_search_index(T* arr, T target, int_32_cx len, bool ascending) {
}
}
return low;
} else {
int_32_cx low = 0;
int_32_cx high = len;
}

while (low < high) {
int_32_cx mid = low + (high - low) / 2;
if (arr[mid] > target) {
low = mid + 1;
} else {
high = mid;
}
}
int_32_cx low = 0;
int_32_cx high = len;

return low;
while (low < high) {
int_32_cx mid = low + (high - low) / 2;
if (arr[mid] > target) {
low = mid + 1;
} else {
high = mid;
}
}

return low;
}

} // namespace cxstructs
# ifdef CX_INCLUDE_TESTS
namespace cxtests {
using namespace cxstructs;
static void TEST_SEARCH() {
std::cout << "TESTING BINARY SEARCH" << std::endl;
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
CX_ASSERT(binary_search(arr, 5, 9) == true, "");
CX_ASSERT(binary_search(arr, -1, 9) == false, "");

std::cout << "TESTING BINARY SEARCH RECURSIVE" << std::endl;
CX_ASSERT(binary_search_recursive(arr, 5, 9) == true, "");
CX_ASSERT(binary_search_recursive(arr, -1, 9) == false, "");

std::cout << "TESTING BINARY SEARCH INDEX" << std::endl;
CX_ASSERT(binary_search_index(arr, 7, 9, true) == 6, "");
CX_ASSERT(binary_search_index(arr, 2, 9, true) == 1, "");
}
} // namespace cxtests
# endif
#endif // CXSTRUCTS_BINARYSEARCH_H
#endif // CXSTRUCTS_BINARYSEARCH_H
19 changes: 8 additions & 11 deletions include/cxstructs/HashGrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@

#include <cassert>
#include <vector>
#include <unordered_map>

// IMPORTANT: Use a custom hashmap here (dense map optimally) and possibly a custom vector
// You can then remove the includes
template <typename Key, typename Value>
using HashMapType = std::unordered_map<Key, Value>; // Insert custom type here

template <typename Value>
using VectorType = std::vector<Value>; // Inset custom type here
Expand All @@ -37,12 +31,13 @@ using VectorType = std::vector<Value>; // Inset custom type here
// https://stackoverflow.com/questions/41946007/efficient-and-well-explained-implementation-of-a-quadtree-for-2d-collision-det
// Originally inspired by the above post to just move all the data of the structure to the top level
// This simplifies memory management and layout, it uses just a single vector for data
// This is achieve by mapping between dimensions, here between a cell and a memory block
// This is achieved by mapping between dimensions, here between a cell and a memory block
// Now its still not perfect but definitely very fast
// Also the problem of multiple insertions is efficiently solved by accumulating with a hashmap
// Its almost mandatory to use a memory consistent map like a dense map thats a vector internally aswell
// This simplifies memory and thus cache friendlyness even more
// With this setup you have 0 (zero) allocations in game ticks which involves completely clearing and refilling grid

namespace cxstructs {
using CellID = uint64_t;
// This creates a unique value - both values are unqiue themselves so their concatenated version is aswell
Expand Down Expand Up @@ -74,9 +69,10 @@ struct DataBlock final {
}
};

template <typename V, int blockSize = 16>
// IMPORTANT: Use a custom hashmap here (dense map optimally) and possibly a custom vector
template <typename V, class HashMapType, int blockSize = 16>
struct SingleResolutionHashGrid final {
HashMapType<CellID, int> cellMap{};
HashMapType cellMap{};
VectorType<DataBlock<V, blockSize>> dataBlocks{};
int cellSize;

Expand Down Expand Up @@ -205,7 +201,8 @@ struct SingleResolutionHashGrid final {
static_assert(sizeof(V) <= 8, "You should only use small id types");
};

template <typename Value, int blockSize = 16>
using HashGrid = SingleResolutionHashGrid<Value, blockSize>;
template <typename Value, template<typename, typename> class HashMaptype, int blockSize = 16>
using HashGrid = SingleResolutionHashGrid<Value, HashMaptype<CellID, int>, blockSize>;

} // namespace cxstructs
#endif //CXSTRUCTS_MULTIRESOLUTIONGRID_H
138 changes: 108 additions & 30 deletions include/cxstructs/SmallVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,79 +22,157 @@
#define SMALLVECTOR_H

#include <cstdint>
#include <cstring>
#include <cassert>

template <typename T>
class VectorIterator {
public:
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;

VectorIterator(pointer ptr) : ptr_(ptr) {}

reference operator*() const { return *ptr_; }
pointer operator->() { return ptr_; }

// Prefix increment
VectorIterator& operator++() {
++ptr_;
return *this;
}
// Postfix increment
VectorIterator operator++(int) {
VectorIterator tmp = *this;
++*this;
return tmp;
}

// Prefix decrement
VectorIterator& operator--() {
--ptr_;
return *this;
}
// Postfix decrement
VectorIterator operator--(int) {
VectorIterator tmp = *this;
--*this;
return tmp;
}

// Arithmetic operators
VectorIterator& operator+=(difference_type offset) {
ptr_ += offset;
return *this;
}
VectorIterator operator+(difference_type offset) const { return VectorIterator(ptr_ + offset); }
VectorIterator& operator-=(difference_type offset) {
ptr_ -= offset;
return *this;
}
VectorIterator operator-(difference_type offset) const { return VectorIterator(ptr_ - offset); }
difference_type operator-(const VectorIterator& other) const { return ptr_ - other.ptr_; }

reference operator[](difference_type index) const { return *(ptr_ + index); }

// Comparison operators
bool operator==(const VectorIterator& other) const { return ptr_ == other.ptr_; }
bool operator!=(const VectorIterator& other) const { return ptr_ != other.ptr_; }
bool operator<(const VectorIterator& other) const { return ptr_ < other.ptr_; }
bool operator<=(const VectorIterator& other) const { return ptr_ <= other.ptr_; }
bool operator>(const VectorIterator& other) const { return ptr_ > other.ptr_; }
bool operator>=(const VectorIterator& other) const { return ptr_ >= other.ptr_; }

private:
pointer ptr_;
};

namespace cxstructs {
template <typename T, uint32_t N = 16, typename size_type = uint16_t>
struct SmallVector {
SmallVector() : m_size(0), m_capacity(N), m_data(m_stack_data) {}
SmallVector() : size_(0), capacity_(N), data_(stack_data_) {}

~SmallVector() {
if (m_data != m_stack_data) {
delete[] m_data;
if (data_ != stack_data_) {
delete[] data_;
}
}

void push_back(const T& value) {
ensure_capacity(m_size + 1);
m_data[m_size++] = value;
ensure_capacity(size_ + 1);
data_[size_++] = value;
}

void pop_back() {
assert(m_size > 0);
--m_size;
assert(size_ > 0);
--size_;
}

// ensures capacity - initializes all new values
void resize(size_type new_size, const T& val) {
if (new_size > m_size) {
if (new_size > size_) {
ensure_capacity(new_size);
for (size_type i = m_size; i < new_size; ++i) {
m_data[i] = val;
for (size_type i = size_; i < new_size; ++i) {
data_[i] = val;
}
m_size = new_size;
size_ = new_size;
}
}

T& operator[](size_type index) {
assert(index < m_size);
return m_data[index];
assert(index < size_);
return data_[index];
}

const T& operator[](size_type index) const {
assert(index < m_size);
return m_data[index];
assert(index < size_);
return data_[index];
}

size_type size() const { return m_size; }
size_type size() const { return size_; }

size_type capacity() const { return m_capacity; }
size_type capacity() const { return capacity_; }

const T* data() const { return m_data; }
const T* data() const { return data_; }

T* data() { return m_data; }
T* data() { return data_; }

bool empty() const { return size_ == 0; }

using iterator = VectorIterator<T>;
using const_iterator = VectorIterator<const T>;

iterator begin() { return iterator(data_); }
const_iterator begin() const { return const_iterator(data_); }
iterator end() { return iterator(data_ + size_); }
const_iterator end() const { return const_iterator(data_ + size_); }

private:
void ensure_capacity(size_type new_capacity) {
if (new_capacity <= m_capacity) {
if (new_capacity <= capacity_) {
return;
}

new_capacity = m_capacity * 2;
new_capacity = capacity_ * 2;
T* new_data = new T[new_capacity];

std::memcpy(new_data, m_data, m_size * sizeof(T));
std::memcpy(new_data, data_, size_ * sizeof(T));

if (m_data != m_stack_data) {
delete[] m_data;
if (data_ != stack_data_) {
delete[] data_;
}

m_data = new_data;
m_capacity = new_capacity;
data_ = new_data;
capacity_ = new_capacity;
}
size_type m_size;
size_type m_capacity;
T* m_data;
T m_stack_data[N];

size_type size_;
size_type capacity_;
T* data_;
T stack_data_[N];
};
} // namespace cxstructs
#endif //SMALLVECTOR_H
Loading

0 comments on commit 218dece

Please sign in to comment.