diff --git a/include/cxstructs/StackHashMap.h b/include/cxstructs/StackHashMap.h index 56c285c..2ec8060 100644 --- a/include/cxstructs/StackHashMap.h +++ b/include/cxstructs/StackHashMap.h @@ -73,14 +73,14 @@ class StackHashMap { size_type size_ = 0; int rand_ = rand(); - [[nodiscard]] inline constexpr size_t impl_hash_func(const K& key) const noexcept { + [[nodiscard]] constexpr size_t impl_hash_func(const K& key) const noexcept { if constexpr ((N & (N - 1)) == 0) { //Power of 2 optimization return hash_func_(key) & (N - 1); } return (hash_func_(key) * rand_) % N; } - inline void add_node(size_t hash, const_key_ref key, auto val) noexcept { + void add_node(size_t hash, const_key_ref key, auto val) noexcept { if (!register_[hash]) { if constexpr (std::is_trivially_copyable_v && std::is_trivially_copyable_v) { data_[hash].key = key; @@ -96,7 +96,7 @@ class StackHashMap { } } - inline void insert_non_empty(const K& key, auto val) noexcept { + void insert_non_empty(const K& key, auto val) noexcept { Node org_data[N]; bool org_register[N]; std::memcpy(org_data, data_, N * sizeof(Node)); @@ -180,7 +180,7 @@ class StackHashMap { } //Call can result in endless loop at high load factor - inline void insert(const K& key, V&& val) noexcept { + void insert(const K& key, V&& val) noexcept { CX_ASSERT(size_ < N, "Trying to add to full StackHashMap"); CX_STACK_ABORT_IMPL(); @@ -194,7 +194,7 @@ class StackHashMap { } //Call can result in endless loop at high load factor - inline void insert(const K& key, const V& val) noexcept { + void insert(const K& key, const V& val) noexcept { CX_ASSERT(size_ < N, "Trying to add to full StackHashMap"); CX_STACK_ABORT_IMPL(); @@ -207,7 +207,7 @@ class StackHashMap { add_node(hash, key, val); } - inline void insert(const std::pair& keyValue) noexcept { + void insert(const std::pair& keyValue) noexcept { CX_ASSERT(size_ < N, "Trying to add to full StackHashMap"); CX_STACK_ABORT_IMPL(); @@ -223,13 +223,15 @@ class StackHashMap { add_node(hash, key, val); } - inline V& operator[](const K& key) noexcept { + auto operator[](const K& key) noexcept -> V& { const size_t hash = impl_hash_func(key); if (!register_[hash]) { add_node(hash, key, V()); return data_[hash].val; - } else if (data_[hash].key == key) { + } + + if (data_[hash].key == key) { return data_[hash].val; } @@ -237,9 +239,9 @@ class StackHashMap { return data_[impl_hash_func(key)].val; } - [[nodiscard]] size_type size() const noexcept { return size_; } + [[nodiscard]] auto size() const noexcept -> size_type { return size_; } - inline bool erase(const K& key) noexcept { + auto erase(const K& key) noexcept -> bool { const size_t hash = impl_hash_func(key); if (register_[hash]) { if constexpr (!std::is_trivial_v) { @@ -255,24 +257,24 @@ class StackHashMap { return false; } - [[nodiscard]] inline bool contains(const K& key) const noexcept { + [[nodiscard]] auto contains(const K& key) const noexcept -> bool { const size_t hash = impl_hash_func(key); return register_[hash] && data_[hash].key == key; } //The multiplier for the hash | Set to 1 if you supply a perfect hash function | Resets on collision - inline void set_rand(int rand) noexcept { rand_ = rand; } + void set_rand(int rand) noexcept { rand_ = rand; } - inline void clear() noexcept { + void clear() noexcept { std::memset(register_, false, N); size_ = 0; } - [[nodiscard]] inline bool empty() const noexcept { return !register_.any(); } + [[nodiscard]] auto empty() const noexcept -> bool { return !register_.any(); } - [[nodiscard]] inline float load_factor() const noexcept { return (float)size_ / (float)N; } + [[nodiscard]] auto load_factor() const noexcept -> float { return (float)size_ / (float)N; } - [[nodiscard]] inline size_t get_hash(const K& key) const noexcept { return impl_hash_func(key); } + [[nodiscard]] auto get_hash(const K& key) const noexcept -> size_t { return impl_hash_func(key); } // Iterator support class KeyIterator { @@ -319,6 +321,7 @@ class StackHashMap { size_t size_; size_t index_; }; + class ValueIterator { public: using iterator_category = std::forward_iterator_tag; @@ -371,8 +374,7 @@ class StackHashMap { using pointer = Node*; using reference = Node&; - explicit PairIterator(Node* ptr, bool* reg, size_t size) - : ptr_(ptr), reg_(reg), size_(size), index_(0) { + explicit PairIterator(Node* ptr, bool* reg, size_t size) : ptr_(ptr), reg_(reg), size_(size) { if (!reg_[index_]) { ++(*this); } @@ -407,7 +409,7 @@ class StackHashMap { Node* ptr_; bool* reg_; size_t size_; - size_t index_; + size_t index_{0}; }; KeyIterator key_begin() { return KeyIterator(data_, register_, N); } diff --git a/include/cxstructs/StackVector.h b/include/cxstructs/StackVector.h index 6bdea88..5586c84 100644 --- a/include/cxstructs/StackVector.h +++ b/include/cxstructs/StackVector.h @@ -137,61 +137,48 @@ class StackVector { } const T* data() { return data_; } - // Iterator support - class Iterator { + template + class IteratorTemplate { public: using iterator_category = std::forward_iterator_tag; - using value_type = T; + using value_type = std::remove_const_t; // Remove const for value_type using difference_type = std::ptrdiff_t; - using pointer = T*; - using reference = T&; + using pointer = PtrType*; + using reference = PtrType&; - explicit Iterator(pointer ptr) : ptr_(ptr) {} + explicit IteratorTemplate(pointer ptr) : ptr_(ptr) {} reference operator*() const { return *ptr_; } - pointer operator->() { return ptr_; } + pointer operator->() const { return ptr_; } // Prefix increment - Iterator& operator++() { + IteratorTemplate& operator++() { ptr_++; return *this; } // Postfix increment - Iterator operator++(int) { - Iterator tmp = *this; + IteratorTemplate operator++(int) { + IteratorTemplate tmp = *this; ++(*this); return tmp; } - friend bool operator==(const Iterator& a, const Iterator& b) { return a.ptr_ == b.ptr_; }; - friend bool operator!=(const Iterator& a, const Iterator& b) { return a.ptr_ != b.ptr_; }; + friend bool operator==(const IteratorTemplate& a, const IteratorTemplate& b) { + return a.ptr_ == b.ptr_; + } + friend bool operator!=(const IteratorTemplate& a, const IteratorTemplate& b) { + return a.ptr_ != b.ptr_; + } private: pointer ptr_; }; - Iterator erase(Iterator pos) { - // Direct pointer arithmetic on the underlying pointers to find the index - auto posPtr = &(*pos); // Convert Iterator to pointer - size_type index = posPtr - &(*begin()); // Use underlying pointers for subtraction - - // Move elements after pos one position to the left - std::move(posPtr + 1, &(*end()), posPtr); - - // Destroy the last element (now a duplicate) if it's not trivially - // destructible - if constexpr (!std::is_trivially_destructible_v) { - data_[size_ - 1].~T(); - } - - // Adjust the size - --size_; - - // Return iterator to the next element after the erased one - // Convert back to Iterator at the correct position - return Iterator(data_ + index); - } + using Iterator = IteratorTemplate; + using ConstIterator = IteratorTemplate; + ConstIterator begin() const { return ConstIterator(&data_[0]); } + ConstIterator end() const { return ConstIterator(&data_[size_]); } Iterator begin() { return Iterator(&data_[0]); } Iterator end() { return Iterator(&data_[size_]); } diff --git a/include/cxutil/cxbits.h b/include/cxutil/cxbits.h index 6e77eb6..d6e4159 100644 --- a/include/cxutil/cxbits.h +++ b/include/cxutil/cxbits.h @@ -23,6 +23,7 @@ #include "../cxconfig.h" #include +#include #include //For type traits //Assumes little endian for all operations @@ -64,7 +65,7 @@ enum Endianness { LITTLE_ENDIAN, BIG_ENDIAN }; template struct is_same_size_and_sign { static constexpr bool value = - (sizeof(T) == sizeof(U)) && (std::is_signed::value == std::is_signed::value); + (sizeof(T) == sizeof(U)) && (std::is_signed_v == std::is_signed_v); }; template @@ -82,8 +83,8 @@ struct ConcatType { template struct ConcatPaddingType { // Calculate the total size needed, considering padding. - inline static constexpr size_t paddedSize = PadToBytes > sizeof(T) ? PadToBytes : sizeof(T); - inline static constexpr size_t totalSize = + static constexpr size_t paddedSize = PadToBytes > sizeof(T) ? PadToBytes : sizeof(T); + static constexpr size_t totalSize = paddedSize + (PadToBytes > sizeof(U) ? PadToBytes : sizeof(U)); // Select the smallest standard integer type that fits the total size. @@ -106,7 +107,7 @@ struct ConcatPaddingType { template inline auto bits_concat_ex(T first, U second) { - static_assert(std::is_integral::value && std::is_integral::value, + static_assert(std::is_integral_v && std::is_integral_v, "Only integer types are supported."); using ResultType = typename ConcatPaddingType::type; @@ -126,8 +127,8 @@ inline auto bits_concat_ex(T first, U second) { * @return */ template -inline constexpr auto bits_concat(T first, T second) { - static_assert(std::is_integral::value, "Only integer types are supported."); +constexpr auto bits_concat(T first, T second) { + static_assert(std::is_integral_v, "Only integer types are supported."); constexpr auto same = is_same_size_and_sign::value; constexpr bool fits = !std::is_same_v::type, void>; static_assert(fits, "Resulting type is too large to represent."); @@ -144,14 +145,14 @@ inline constexpr auto bits_concat(T first, T second) { */ template inline void bits_print(T num) { - static_assert(std::is_integral::value, "Only integral types are supported."); + static_assert(std::is_integral_v, "Only integral types are supported."); constexpr size_t numBits = sizeof(T) * 8; // Total bits in type T char bitRepresentation[numBits + 1]; // +1 for null terminator bitRepresentation[numBits] = '\0'; // Null-terminate the string for (size_t i = 0; i < numBits; ++i) { - bitRepresentation[(numBits-1) -i] = (num & (T(1) << i)) ? '1' : '0'; + bitRepresentation[(numBits - 1) - i] = (num & (T(1) << i)) ? '1' : '0'; } fputs(bitRepresentation, stdout); @@ -167,18 +168,18 @@ inline void bits_print(T num) { */ template inline void bits_print_bytes(const T& num, Endianness endian = LITTLE_ENDIAN) { - static_assert(std::is_integral::value, "Only integral types are supported."); + static_assert(std::is_integral_v, "Only integral types are supported."); const size_t numBytes = sizeof(T); const auto* bytePointer = reinterpret_cast(&num); if (endian == LITTLE_ENDIAN) { for (size_t i = 0; i < numBytes; ++i) { - printf("%02X ", bytePointer[i]); + std::print("{:02X} ", bytePointer[i]); } } else { for (size_t i = numBytes; i > 0; --i) { - printf("%02X ", bytePointer[i - 1]); + std::print("{:02X} ", bytePointer[i - 1]); } } fputc('\n', stdout); @@ -194,8 +195,8 @@ inline void bits_print_bytes(const T& num, Endianness endian = LITTLE_ENDIAN) { * @return a number of type r created from the specified bit range */ template -inline constexpr R bits_get(T num, uint8_t off = 0) { - static_assert(std::is_integral::value, "Only integer type are supported."); +constexpr auto bits_get(T num, uint8_t off = 0) -> R { + static_assert(std::is_integral_v, "Only integer type are supported."); return static_cast(num >> off); } diff --git a/include/cxutil/cxmath.h b/include/cxutil/cxmath.h index 07749ed..6074348 100644 --- a/include/cxutil/cxmath.h +++ b/include/cxutil/cxmath.h @@ -32,28 +32,28 @@ namespace cxstructs { struct mat; //function pointer typedef -typedef float (*func)(float); -typedef mat (*func_M)(mat&, mat&); // mat function -typedef float (*D_func)(float p1x, float p1y, float p2x, float p2y); +using func = float (*)(float); +using func_M = mat (*)(mat &, mat &); // mat function +using D_func = float (*)(float, float, float, float); //activation functions -inline float sig(float x) noexcept { +inline auto sig(float x) noexcept -> float { return 1.0F / (1.0F + std::exp(-x)); } -inline float tanh(float x) noexcept { +inline auto tanh(float x) noexcept -> float { return std::tanh(x); } -inline float relu(float x) noexcept { +inline auto relu(float x) noexcept -> float { return x > 0 ? x : 0; } //derivatives -inline float d_sig(float x) noexcept { +inline auto d_sig(float x) noexcept -> float { return sig(x) * (1 - sig(x)); } -inline float d_relu(float x) noexcept { +inline auto d_relu(float x) noexcept -> float { return x > 0 ? 1.0F : 0.0F; } -inline float d_tanh(float x) noexcept { +inline auto d_tanh(float x) noexcept -> float { float t = std::tanh(x); return 1 - t * t; } @@ -64,7 +64,7 @@ inline float d_tanh(float x) noexcept { * @param n the start number * @return the next power of two or n, if n is a power of 2 */ -inline uint32_t next_power_of_2(uint32_t n) noexcept { +inline auto next_power_of_2(uint32_t n) noexcept -> uint32_t { n--; n |= n >> 1; n |= n >> 2; @@ -79,7 +79,7 @@ inline uint32_t next_power_of_2(uint32_t n) noexcept { * @param n * @return the square root of n */ -inline float fast_sqrt(float n) noexcept { +inline auto fast_sqrt(float n) noexcept -> float { long i; float x2, y; constexpr float threehalfs = 1.5F; @@ -100,21 +100,24 @@ inline float fast_sqrt(float n) noexcept { * @param high highest possible value * @return low if val is smaller than low, val if val is between low and high, and high if val is bigger than high */ -template ::value, int> = 0> -inline constexpr T clamp(const T& val, const T& low, const T& high) { +template +constexpr auto clamp(const T& val, const T& low, const T& high) -> T requires (!std::is_integral_v) { if (val < low) { return low; - } else if (val > high) { + } + if (val > high) { return high; } + return val; } -template ::value, int> = 0> -inline constexpr T clamp(T val, T low, T high) { +template +constexpr auto clamp(T val, T low, T high) -> T requires std::is_integral_v { if (val < low) { return low; - } else if (val > high) { + } + if (val > high) { return high; } return val; @@ -122,10 +125,10 @@ inline constexpr T clamp(T val, T low, T high) { //-----------DISTANCE-----------// -inline float euclidean(float p1x, float p1y, float p2x, float p2y) noexcept { +inline auto euclidean(float p1x, float p1y, float p2x, float p2y) noexcept -> float { return fast_sqrt((p2x - p1x) * (p2x - p1x) + (p2y - p1y) * (p2y - p1y)); } -inline float manhattan(float p1x, float p1y, float p2x, float p2y) noexcept { +inline auto manhattan(float p1x, float p1y, float p2x, float p2y) noexcept -> float { return abs(p2x - p1x) + abs(p2y - p1y); }