[+] AuToIterator (function)

[+] AuToElementType (function)
[+] AuToValueType (function)
[+] Optimized 32bit/64bit hash routines
[+] AuFnv1aRuntime (32bit/64bit auto variant)
[+] std::array reimplementation for reasons i deleted from the file bc sperging
[+] AuArrayList
This commit is contained in:
Reece Wilson 2023-01-18 10:49:32 +00:00
parent 117390825c
commit f4487c589c
8 changed files with 382 additions and 41 deletions

View File

@ -76,4 +76,8 @@
//#define _AURORA_NULLEXPT_USE_TRY_EMPLACE_AFTER_FIND
//#define _AURORA_MISSING_STD_EXCEPTION
//#define _AURORA_MISSING_STD_EXCEPTION
//#define _AURORA_AVOID_DUMB_STL_TYPES
#define _AURORA_AVOID_EXTREMLY_DUMB_STL_TYPES

View File

@ -1,4 +1,4 @@
/***
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auArray.hpp
@ -7,9 +7,221 @@
***/
#pragma once
#if !defined(AURORA_RUNTIME_AU_ARRAY)
#define AURORA_RUNTIME_AU_ARRAY std::array
#endif
#if defined(_AURORA_AVOID_EXTREMLY_DUMB_STL_TYPES) && !defined(_AURORA_FORCE_STD_ARRAY)
template <class T, size_t Count>
struct AuArray
{
T elements[Count] {};
template <class T, size_t Z>
using AuArray = AURORA_RUNTIME_AU_ARRAY<T, Z>;
static const AuUInt kElementCount = Count;
using value_type = T;
using size_type = AuUInt;
using difference_type = AuSInt;
using pointer = value_type *;
using const_pointer = const value_type *;
using reference = value_type &;
using const_reference = const value_type &;
using iterator = pointer;
using const_iterator = const_pointer;
void fill(const T &value)
{
if constexpr (AuIsSame_v<T, AuUInt8> || AuIsSame_v<T, AuInt8>)
{
AuMemset(this->elements, value, sizeof(this->elements));
}
else
{
for (AU_ITERATE_N(i, kElementCount))
{
this->elements[i] = value;
}
}
}
void swap(AuArray &other)
{
AuArray temp;
if constexpr (std::is_trivially_copyable_v<T>)
{
AuMemcpy(temp, this->elements, sizeof(this->elements));
AuMemcpy(this->elements, other.elements, sizeof(this->elements));
AuMemcpy(other.elements, temp, sizeof(this->elements));
}
else
{
AuArray temp;
for (AU_ITERATE_N(i, kElementCount))
{
temp[i] = this->elements[i];
}
for (AU_ITERATE_N(i, kElementCount))
{
this->elements[i] = other.elements[i];
}
for (AU_ITERATE_N(i, kElementCount))
{
other.elements[i] = temp[i];
}
}
}
constexpr iterator begin()
{
return this->elements;
}
constexpr const_iterator begin() const
{
return this->elements;
}
constexpr iterator end()
{
return this->elements + kElementCount;
}
constexpr const_iterator end() const
{
return this->elements + kElementCount;
}
constexpr const_iterator cbegin() const
{
return begin();
}
constexpr const_iterator cend() const
{
return end();
}
constexpr size_type size() const
{
return kElementCount;
}
constexpr size_type max_size() const
{
return kElementCount;
}
constexpr bool empty() const
{
return false;
}
reference at(size_type pos)
{
#if defined(AU_CFG_ID_DEBUG)
if (pos >= kElementCount)
{
AuMemoryPanic("out of bounds access");
}
#endif
return this->elements[pos];
}
constexpr const_reference at(size_type pos) const
{
#if defined(AU_CFG_ID_DEBUG)
if (pos >= kElementCount)
{
AuMemoryPanic("out of bounds access");
}
#endif
return this->elements[pos];
}
reference operator[](size_type pos)
{
#if defined(AU_CFG_ID_DEBUG)
if (pos >= kElementCount)
{
AuMemoryPanic("out of bounds access");
}
#endif
return this->elements[pos];
}
constexpr const_reference operator[](size_type pos) const
{
#if defined(AU_CFG_ID_DEBUG)
if (pos >= Count)
{
AuMemoryPanic("out of bounds access");
}
#endif
return this->elements[pos];
}
constexpr reference front()
{
return this->elements[0];
}
constexpr const_reference front() const
{
return this->elements[0];
}
constexpr reference back()
{
return this->elements[Count - 1];
}
constexpr const_reference back() const
{
return this->elements[Count - 1];
}
constexpr T *data()
{
return this->elements;
}
constexpr const T *data() const
{
return this->elements;
}
// oh look, its that feature in that nearly 30 year old programming language intended to replace xerox alto's OOP language for the internet era.
AuUInt HashCode() const
{
AuUInt uRet {};
if constexpr (std::is_trivially_copyable_v<T>)
{
return AuFnv1aRuntime(this->elements, sizeof(this->elements));
}
else
{
for (AU_ITERATE_N(i, kElementCount))
{
uRet ^= AuHashCode(this->elements[i]);
}
}
return uRet;
}
};
#else
#if !defined(AURORA_RUNTIME_AU_ARRAY)
#define AURORA_RUNTIME_AU_ARRAY std::array
#endif
template <class T, size_t Z>
using AuArray = AURORA_RUNTIME_AU_ARRAY<T, Z>;
#endif

View File

@ -0,0 +1,15 @@
/***
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auArrayList.hpp
Date: 2023-1-18
Author: Reece
***/
#pragma once
#if !defined(AURORA_RUNTIME_AU_ARRAY_LIST)
#define AURORA_RUNTIME_AU_ARRAY_LIST std::list
#endif
template <class T>
using AuArrayList = AURORA_RUNTIME_AU_ARRAY_LIST<T>;

View File

@ -137,4 +137,11 @@ inline AuUInt64 AuFnv1a64Runtime(const void *base, AuUInt length) noexcept
return result;
}
inline auto AuFnv1aRuntime(const void *base, AuUInt length) noexcept
{
return _AU_FNV1_32 ?
AuFnv1a32Runtime(base, length) :
AuFnv1a64Runtime(base, length);
}
#undef _AU_FNV1_32

View File

@ -46,47 +46,135 @@ namespace AuHash
}
};
#define _HASH_F_CPP(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type b) const \
{ \
return AuFnv1aType<type>(b); \
} \
// Thomas Wang, Integer Hash Functions: https://web.archive.org/web/20061201032901/http://www.concentric.net/%7ETtwang/tech/inthash.htm
// Updated version under V8: V8/v9-11/src/utils/utils.h
//
// I'm sure Google's tweaks and subsequence implementations have justification grounded in reality more so than the initial publishing of a 1999ish article by some dude at HP
// Real world experience > 1999 HP guy > whatever the fuck the stl is doing (i think ms just uses fnv1s for everything)
//
// Preserving original function names for ease of xref. unseeded vs implied seeded doesnt mean anything. see: ComputeLongHash comment.
inline constexpr AuUInt32 ComputeUnseededHash(AuUInt32 key)
{
AuUInt32 hash = key;
hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
hash = hash ^ (hash >> 12);
hash = hash + (hash << 2);
hash = hash ^ (hash >> 4);
hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
hash = hash ^ (hash >> 16);
return hash;
}
// ComputeLongHash(base::double_to_uint64(AsNumber())); ( pre-maglev V8 wasn't u64 optimizated. )
// ComputeLongHash(static_cast<uint64_t>(digit(0))); ( most js wont touch >31bit ints. )
inline constexpr AuUInt64 ComputeLongHash(AuUInt64 key)// ( i'm sure this function's fine for all ranges. )
{
AuUInt64 hash = key;
hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
hash = hash ^ (hash >> 31);
hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
hash = hash ^ (hash >> 11); // key = key ^ (key >>> 28); ?
hash = hash + (hash << 6); // key = key + (key << 31); ?
hash = hash ^ (hash >> 22); // ???????????
return hash;
}
#define _HASH_INT(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type b) const \
{ \
return AuFnv1aType<type>(b); \
} \
};
_HASH_F_CPP(bool);
_HASH_F_CPP(char);
_HASH_F_CPP(signed char);
_HASH_F_CPP(unsigned char);
_HASH_F_CPP(char8_t);
_HASH_F_CPP(char16_t);
_HASH_F_CPP(char32_t);
_HASH_F_CPP(wchar_t);
_HASH_F_CPP(short);
_HASH_F_CPP(unsigned short);
_HASH_F_CPP(int);
_HASH_F_CPP(unsigned int);
_HASH_F_CPP(long);
_HASH_F_CPP(long long);
_HASH_F_CPP(unsigned long);
_HASH_F_CPP(unsigned long long);
_HASH_F_CPP(float);
_HASH_F_CPP(double);
_HASH_F_CPP(long double);
_HASH_F_CPP(std::nullptr_t);
#if defined(AURORA_IS_32BIT)
#undef _HASH_F_CPP
#define _HASH_INT32BIT(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type intValue) const \
{ \
return ComputeUnseededHash(AuUInt32(intValue)); \
} \
};
template <class T> struct hash<T *>
#else
#define _HASH_INT32BIT(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type intValue) const \
{ \
return ComputeLongHash(AuUInt64(intValue)); \
} \
};
#endif
#if defined(AURORA_IS_32BIT)
#define _HASH_INT64BIT(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type intValue) const \
{ \
return AuUInt32(ComputeLongHash(AuUInt64(intValue)) & 0xFFFFFFFF); \
} \
};
#else
#define _HASH_INT64BIT(type) \
template <> \
struct hash<type> \
{ \
constexpr AuUInt operator ()(const type intValue) const \
{ \
return ComputeLongHash(AuUInt64(intValue)); \
} \
};
#endif
_HASH_INT32BIT(bool);
_HASH_INT32BIT(char);
_HASH_INT32BIT(signed char);
_HASH_INT32BIT(unsigned char);
_HASH_INT32BIT(char8_t);
_HASH_INT32BIT(char16_t);
_HASH_INT32BIT(char32_t);
_HASH_INT32BIT(wchar_t);
_HASH_INT32BIT(short);
_HASH_INT32BIT(unsigned short);
_HASH_INT32BIT(int);
_HASH_INT32BIT(unsigned int);
_HASH_INT64BIT(long);
_HASH_INT64BIT(long long);
_HASH_INT64BIT(unsigned long);
_HASH_INT64BIT(unsigned long long);
_HASH_INT(float);
_HASH_INT(double);
_HASH_INT(long double);
_HASH_INT(std::nullptr_t);
#undef _HASH_INT
#undef _HASH_INT32BIT
#undef _HASH_INT64BIT
template <class T>
struct hash<T *>
{
AuUInt operator ()(T *ptr) const
{
#if defined(AURORA_IS_32BIT)
return AuFnv1a32Runtime(&ptr, sizeof(T *));
return ComputeUnseededHash(AuUInt(ptr));
#else
return AuFnv1a64Runtime(&ptr, sizeof(T *));
return ComputeLongHash(AuUInt(ptr));
#endif
}
};

View File

@ -11,5 +11,10 @@
#define AURORA_RUNTIME_AU_OPTIONAL std::optional
#endif
template <class T>
using AuOptional = AURORA_RUNTIME_AU_OPTIONAL<T>;
#if defined(_AURORA_AVOID_DUMB_STL_TYPES)
template <class T>
using AuOptional = AuOptionalEx<T>;
#else
template <class T>
using AuOptional = AURORA_RUNTIME_AU_OPTIONAL<T>;
#endif

View File

@ -39,6 +39,15 @@ using AuToElementType_t = typename T::element_type;
template <class T>
using AuToIterator_t = typename T::iterator;
template <typename T>
static AuToIterator_t<T> AuToIterator(const T &a); // intended use case: screwing over nasty ass lines of `AuToIterator_t<decltype(muh member)>` or worse.
// example usage: `decltype(AuToIterator(myHashMap)) itr;`
template <typename T>
static AuToElementType_t<T> AuToElementType(const T &a);
template <typename T>
static AuToValueType_t<T> AuToValueType(const T &a);
template <class T, class U>
struct AuIsSame : AuFalseType
{};

View File

@ -42,6 +42,7 @@
#include <auROXTL/auTuple.hpp>
#include <auROXTL/auOptional.hpp>
#include <auROXTL/auVector.hpp>
#include <auROXTL/auArrayList.hpp>
namespace Aurora::Memory
{