Compare commits

..

8 commits

58 changed files with 1968 additions and 4433 deletions

3
.gitignore vendored
View file

@ -1,6 +1,3 @@
tags
compile_commands.json
.clangd
.cache
subprojects/Catch2/
subprojects/sprout/

3
.gitmodules vendored
View file

@ -0,0 +1,3 @@
[submodule "lib/Catch2"]
path = lib/Catch2
url = https://github.com/catchorg/Catch2.git

View file

@ -2,15 +2,16 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(duckhandy VERSION 0.1.0)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
include(shared_git_project)
include(CTest)
find_package(Sprout REQUIRED)
set(DUCKHANDY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
if (BUILD_TESTING)
set(BUILD_TESTING CACHE BOOL ON)
set(BUILD_TESTS CACHE BOOL ON)
else()
set(BUILD_TESTING CACHE BOOL OFF)
set(BUILD_TESTS CACHE BOOL OFF)
endif()
add_library(${PROJECT_NAME} INTERFACE)
@ -26,7 +27,7 @@ target_compile_features(${PROJECT_NAME}
INTERFACE cxx_decltype_incomplete_return_types
INTERFACE cxx_noexcept
INTERFACE cxx_rvalue_references
INTERFACE cxx_std_20
INTERFACE cxx_std_17
)
target_include_directories(${PROJECT_NAME}
@ -41,10 +42,6 @@ target_compile_definitions(${PROJECT_NAME}
INTERFACE SPROUT_USE_TEMPLATE_ALIASES
)
target_compile_options(${PROJECT_NAME}
INTERFACE -mprfchw
)
if (BUILD_TESTING)
add_subdirectory(test/unit)
endif()

View file

@ -0,0 +1,85 @@
cmake_minimum_required(VERSION 2.8.12.2 FATAL_ERROR)
function (add_shared_git_project SUBMODULE_PATH)
if (IS_ABSOLUTE "${SUBMODULE_PATH}")
set(submod_path "${SUBMODULE_PATH}")
else()
set(submod_path "${CMAKE_CURRENT_SOURCE_DIR}/${SUBMODULE_PATH}")
endif()
if (NOT EXISTS "${submod_path}")
message(FATAL_ERROR "Path \"${submod_path}\" doesn't exist")
endif()
if (NOT IS_DIRECTORY "${submod_path}")
message(FATAL_ERROR "Path \"${submod_path}\" is not a valid directory")
endif()
if (NOT EXISTS "${submod_path}/.git")
message(FATAL_ERROR ".git not found in \"${submod_path}\". Not a git submodule?")
endif()
if (IS_DIRECTORY "${submod_path}/.git")
message(FATAL_ERROR "\"${submod_path}.git\" is a directory, not a file as expected. Not a git submodule?")
endif()
get_filename_component(proj_name_orig "${submod_path}" NAME)
if ("${proj_name_orig}" STREQUAL "")
message(FATAL_ERROR "Couldn't make up a name for given project in \"${submod_path}\"")
endif()
string(MAKE_C_IDENTIFIER "${proj_name_orig}" proj_name_c_id)
string(TOUPPER ${proj_name_c_id} proj_name)
get_property(shared_projects_list GLOBAL PROPERTY SHARED_PROJECTS_LIST)
list(FIND shared_projects_list ${proj_name} found_index)
if (${found_index} GREATER -1)
#nothing to do, the variable is already set so the project must have been
#included already
return()
endif()
#Obtain the path to the working tree
# see http://stackoverflow.com/questions/27379818/git-possible-to-use-same-submodule-working-copy-by-multiple-projects
# git rev-parse --git-dir --show-toplevel
execute_process(
COMMAND git rev-parse --show-toplevel
WORKING_DIRECTORY "${submod_path}"
OUTPUT_VARIABLE matched_gitdir
OUTPUT_STRIP_TRAILING_WHITESPACE
)
#Make sure we got an absolute path
if (IS_ABSOLUTE "${matched_gitdir}")
set(reported_submodule_dir "${matched_gitdir}")
else()
file(RELATIVE_PATH reported_submodule_dir "${CMAKE_CURRENT_SOURCE_DIR}" "${submod_path}/${matched_gitdir}")
endif()
unset(matched_gitdir)
#Check if submodule is a subdirectory of the current source dir
file(RELATIVE_PATH reported_submodule_rel_path "${CMAKE_CURRENT_SOURCE_DIR}" "${reported_submodule_dir}")
string(LENGTH "${reported_submodule_rel_path}" rel_path_len)
if (${rel_path_len} GREATER 2)
string(SUBSTRING "${reported_submodule_rel_path}" 0 3 first_bit)
if ("../" STREQUAL "${first_bit}")
set(is_out_of_dirtree ON)
else()
set(is_out_of_dirtree OFF)
endif()
unset(first_bit)
else()
set(is_out_of_dirtree OFF)
endif()
unset(rel_path_len)
#Globally mark current submodule as handled
set_property(GLOBAL APPEND PROPERTY SHARED_PROJECTS_LIST ${proj_name})
set(shared_project_binary "${CMAKE_CURRENT_BINARY_DIR}/shared_projects/${proj_name_orig}")
if (is_out_of_dirtree)
#message(FATAL_ERROR "Would call add_subdirectory(\"${reported_submodule_dir}\" \"${shared_project_binary}\")")
add_subdirectory("${reported_submodule_dir}" "${shared_project_binary}" ${ARGN})
else()
#message(FATAL_ERROR "Would call add_subdirectory(\"${reported_submodule_rel_path}\")")
add_subdirectory("${reported_submodule_rel_path}" ${ARGN})
endif()
endfunction()

2
flat_git.yml Normal file
View file

@ -0,0 +1,2 @@
inplace_submodules:
- Sprout

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2025 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -99,8 +99,7 @@ namespace dhandy {
};
template <typename T>
[[gnu::const]]
constexpr inline T make_mask (std::size_t len) noexcept {
constexpr inline T make_mask (std::size_t len) {
return (1 << len) - 1;
}
} //namespace implem
@ -119,7 +118,7 @@ namespace dhandy {
template <std::size_t Idx, typename U, std::size_t... S> friend U get (const BitfieldPack<U, S...>&);
template <std::size_t Idx, typename U, typename V, std::size_t... S> friend void set (BitfieldPack<U, S...>&, V);
typedef implem::BitfieldData<T, Facts::ElementCount> base_type;
static_assert(Facts::LargestSize <= sizeof(T) * CHAR_BIT, "Bitfield size can't be larger than the data type itself");
static_assert(Facts::LargestSize <= sizeof(T) * CHAR_BIT, "Bitfield size can't be larget than the data type itself");
public:
BitfieldPack (T init=T{}) : base_type(init) {}
};
@ -137,16 +136,15 @@ namespace dhandy {
const constexpr bool bleeds_into_next = reloffs + so.size > sizeof(T) * CHAR_BIT;
const T bottom = static_cast<const BitfieldData<T, index + 1>&>(pack).value() >> reloffs;
if constexpr (bleeds_into_next) {
const std::size_t safe_index = index + 2;
if (bleeds_into_next) {
const std::size_t safe_index = index + 2 - not bleeds_into_next;
const T val = static_cast<const BitfieldData<T, safe_index>&>(pack).value();
const T top = val << (sizeof(T) * CHAR_BIT - reloffs);
return static_cast<T>(top | bottom) & make_mask<T>(so.size);
}
else {
return bottom & make_mask<T>(so.size);
}
}
template <std::size_t Idx, typename T, typename V, std::size_t... Sizes>
void set (BitfieldPack<T, Sizes...>& pack, V val) {

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -18,13 +18,11 @@
#ifndef id4754A95F12BE4ADEA65642A056A51907
#define id4754A95F12BE4ADEA65642A056A51907
#include "reversed_sized_array_bt.hpp"
#include "../has_method.hpp"
#include "duckhandy/implem/reversed_sized_array_bt.hpp"
#include <sprout/math/log10.hpp>
#include <sprout/math/abs.hpp>
#include <sprout/math/ceil.hpp>
#include <cstddef>
#include <cstdint>
#include <array>
#include <limits>
#include <emmintrin.h>
@ -35,7 +33,6 @@
# include <string_view>
# include <string>
#endif
#include <type_traits>
namespace dhandy {
namespace implem {
@ -52,14 +49,6 @@ namespace dhandy {
}
} //unnamed namespace
//Used for checking ASCIITranslator::AltLetter
define_has_enum(AltLetter, AltLetter);
template <typename Tr, bool=HasAltLetterEnum<Tr>::value != 0>
inline auto g_AltLetterOrZero = Tr::AltLetter;
template <typename Tr>
inline auto g_AltLetterOrZero<Tr, false> = Tr::NullChar;
template <typename T, typename C, unsigned int Base, typename Tr>
T to_integer_sse (const C* s, std::size_t l);
@ -79,9 +68,6 @@ namespace dhandy {
static const constexpr std::size_t max_len = max_digit_count<typename std::conditional<always_unsigned, std::make_unsigned_t<I>, I>::type, Base> + is_signed;
};
template <typename I, unsigned int Base, typename Tr>
using RevArray = ReversedSizedArray<typename Tr::char_type, int_info<I, Base>::max_len + 1>;
template <typename I, unsigned int Base, bool Signed=int_info<I, Base>::is_signed>
struct IsNegative { static constexpr bool check (I) { return false; } };
template <typename I, unsigned int Base>
@ -104,35 +90,21 @@ namespace dhandy {
template <typename L>
[[gnu::pure,gnu::always_inline]]
static constexpr L abs(L v);
static constexpr L abs(L in) { return (not BecomesUnsigned and std::numeric_limits<L>::is_signed and in < L(0) ? -in : in); }
[[gnu::pure,gnu::always_inline]]
static constexpr CastedType cast (I in) { return static_cast<CastedType>(in); }
};
template <typename I, std::size_t Base, bool IsSigned, bool ForceUnsigned>
template <typename L>
[[gnu::const,gnu::always_inline]]
inline constexpr L NumberAdaptation<I, Base, IsSigned, ForceUnsigned>::abs(L v) {
if constexpr (not BecomesUnsigned and std::numeric_limits<L>::is_signed) {
//https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
const L mask = v >> (sizeof(L) * CHAR_BIT - 1);
const UnsignedType r = (v + mask) ^ mask;
return static_cast<L>(r);
}
else {
return v;
}
}
template <typename I, unsigned int Base, typename Tr, typename=void>
struct IntConversion {
static constexpr RevArray<I, Base, Tr> to_ary (I in) {
static constexpr ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, implem::int_info<I, Base>::max_len + 1> to_ary (I in) {
using RetType = ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, implem::int_info<I, Base>::max_len + 1>;
using Num = implem::NumberAdaptation<I, Base>;
const bool was_negative = implem::is_negative<I, Base>(in);
RevArray<I, Base, Tr> arr;
arr.push_front(Tr::NullChar);
RetType arr;
arr.push_front('\0');
do {
arr.push_front(Tr::to_digit(static_cast<int>(Num::abs(Num::cast(in)) % Base)));
in = static_cast<I>(Num::cast(in) / static_cast<I>(Base));
@ -145,9 +117,11 @@ namespace dhandy {
template <unsigned int Base, typename Tr>
struct IntConversion<bool, Base, Tr, void> {
static constexpr ReversedSizedArray<typename Tr::char_type, 2> to_ary (bool in) {
ReversedSizedArray<typename Tr::char_type, 2> arr;
arr.push_front(Tr::NullChar);
static constexpr ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, 2> to_ary (bool in) {
using RetType = ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, 2>;
RetType arr;
arr.push_front('\0');
arr.push_front(in ? Tr::to_digit(1) : Tr::to_digit(0));
return arr;
}
@ -155,8 +129,11 @@ namespace dhandy {
template <typename I, typename Tr>
struct IntConversion<I, 10, Tr, typename std::enable_if<std::is_integral<I>::value and not std::is_same<I, bool>::value>::type> {
private:
static const constexpr char lookup[200] = {
static constexpr ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, implem::int_info<I, 10>::max_len + 1> to_ary (I in) {
using RetType = ReversedSizedArray<std::decay_t<decltype(std::declval<Tr>().to_digit(1))>, implem::int_info<I, 10>::max_len + 1>;
using Num = implem::NumberAdaptation<I, 10>;
const constexpr char lookup[200] = {
0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,1,0,1,1,1,2,1,3,1,4,
1,5,1,6,1,7,1,8,1,9,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,
3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,4,0,4,1,4,2,4,3,4,4,
@ -165,30 +142,21 @@ namespace dhandy {
7,5,7,6,7,7,7,8,7,9,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9,
9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9
};
public:
static constexpr RevArray<I, 10, Tr> to_ary (I in) {
using RetType = RevArray<I, 10, Tr>;
using Num = implem::NumberAdaptation<I, 10>;
const bool was_negative = implem::is_negative<I, 10>(in);
RetType arr;
if (not std::is_constant_evaluated())
__builtin_prefetch(arr.base_ptr(), 1, 3);
arr.push_front(Tr::NullChar);
in = Num::abs(in);
while (in >= static_cast<I>(100)) {
const auto index = (in % 100) * 2;
arr.push_front('\0');
while (Num::abs(in) >= static_cast<I>(100)) {
const auto index = (Num::abs(in) % 100) * 2;
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 1])));
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 0])));
in = static_cast<I>(in / static_cast<I>(100));
};
if (in < static_cast<I>(10)) {
arr.push_front(Tr::to_digit(static_cast<int>(in)));
if (Num::abs(in) < static_cast<I>(10)) {
arr.push_front(Tr::to_digit(static_cast<int>(Num::abs(in))));
}
else {
const auto index = in * 2;
const auto index = Num::abs(in) * 2;
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 1])));
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 0])));
}
@ -198,22 +166,10 @@ namespace dhandy {
}
};
template <typename I, I In, unsigned int Base, typename Tr>
inline constexpr const auto g_int_to_str = IntConversion<std::remove_cvref_t<I>, Base, Tr>::to_ary(In);
template <typename T>
[[gnu::always_inline,gnu::pure]]
constexpr inline T negated_ifn (T n, bool negate) {
//return static_cast<int32_t>(((static_cast<unsigned int>(n) - (mask bitand 1)) xor mask) bitor ((mask bitand 1) << 31));
return (negate ? -n : n);
}
template <typename I, unsigned int Base, typename Tr, bool Constexpr, typename=void>
template <typename I, unsigned int Base, typename Tr>
struct AryConversion {
constexpr static const bool is_sse = false;
template <typename C>
constexpr static I from_ary (const C* beg, const C* end) {
static I from_ary (const C* beg, const C* end) {
I retval = 0;
I factor = 1;
std::size_t i = end - beg;
@ -227,26 +183,34 @@ namespace dhandy {
retval += Tr::from_digit(beg[i]) * factor;
factor *= Base;
}
return negated_ifn(retval, was_negative);
return retval;
}
};
template <typename I, typename Tr, typename=typename std::enable_if<Tr::BehavesLikeASCII and std::is_integral<I>::value and not std::is_same<I, bool>::value and sizeof(I) <= sizeof(uint32_t)>::type>
using SelectIForSSEToInt = I;
template <typename I, unsigned int Base, typename Tr>
struct AryConversion<I, Base, Tr, false, typename std::enable_if<std::is_integral<I>::value and not std::is_same<I, bool>::value and sizeof(I) <= sizeof(std::uint32_t)>::type> {
constexpr static const bool is_sse = true;
struct AryConversion<SelectIForSSEToInt<I, Tr>, Base, Tr> {
template <typename C> static I from_ary (C* beg, C* end) { return to_integer_sse<I, C, Base, Tr>(beg, end - beg); }
};
template <unsigned int Base, typename Tr, bool Constexpr>
struct AryConversion<bool, Base, Tr, Constexpr> {
constexpr static const bool is_sse = false;
template <typename C> constexpr static bool from_ary (C* beg, C* end) {
template <unsigned int Base, typename Tr>
struct AryConversion<bool, Base, Tr> {
template <typename C> static bool from_ary (C* beg, C* end) {
if (end == beg)
return false;
return (Tr::from_digit(*beg) ? true : false);
}
};
template <typename T>
[[gnu::always_inline,gnu::pure]]
inline T negated_ifn (T n, bool negate) {
//return static_cast<int32_t>(((static_cast<unsigned int>(n) - (mask bitand 1)) xor mask) bitor ((mask bitand 1) << 31));
return (negate ? -n : n);
}
template <typename T, typename C, unsigned int Base, typename Tr>
[[gnu::pure]]
T to_integer_sse (const C* s, std::size_t l) {
@ -276,24 +240,13 @@ namespace dhandy {
__m128i factor = _mm_set_epi32(base3, base2, base1, 1);
__m128i res = _mm_set1_epi32(0);
const __m128i char_0 = _mm_set1_epi32(Tr::FirstDigit);
const __m128i char_befo_a = _mm_set1_epi32(Tr::FirstLetter - 1);
const __m128i char_past_f = _mm_set1_epi32(Tr::FirstLetter + Base - Tr::DigitCount);
const __m128i char_a = _mm_set1_epi32(Tr::FirstLetter);
std::size_t idx = 0;
const std::size_t cap = l bitand -4;
do {
const __m128i digits = _mm_set_epi32(s[cap - idx - 3 - 1], s[cap - idx - 2 - 1], s[cap - idx - 1 - 1], s[cap - idx - 0 - 1]);
__m128i mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_a), _mm_cmplt_epi32(digits, char_past_f));
__m128i offs = _mm_and_si128(mask, _mm_set1_epi32(Tr::FirstLetter - Tr::DigitCount));
if constexpr (HasAltLetterEnum<Tr>::value) {
const __m128i char_befo_A = _mm_set1_epi32(g_AltLetterOrZero<Tr> - 1);
const __m128i char_past_F = _mm_set1_epi32(g_AltLetterOrZero<Tr> + Base - Tr::DigitCount);
const __m128i alt_mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_A), _mm_cmplt_epi32(digits, char_past_F));
const __m128i alt_offs = _mm_and_si128(alt_mask, _mm_set1_epi32(g_AltLetterOrZero<Tr> - Tr::DigitCount));
offs = _mm_add_epi32(alt_offs, offs);
mask = _mm_or_si128(mask, alt_mask);
}
const __m128i addend = _mm_add_epi32(offs, _mm_andnot_si128(mask, char_0));
const __m128i mask = _mm_cmplt_epi32(digits, char_a);
const __m128i addend = _mm_add_epi32(_mm_andnot_si128(mask, _mm_sub_epi32(char_a, _mm_set1_epi32(10))), _mm_and_si128(mask, char_0));
res = _mm_add_epi32(res, muly(_mm_sub_epi32(digits, addend), factor));
factor = muly(factor, _mm_set1_epi32(base4));
idx += 4;
@ -302,7 +255,7 @@ namespace dhandy {
{
res = _mm_add_epi32(res, _mm_srli_si128(res, 8));
res = _mm_add_epi32(res, _mm_srli_si128(res, 4));
constexpr const std::array<int, 4> scale {1, base1, base2, base3};
const std::array<int, 4> scale {1, base1, base2, base3};
return negated_ifn(to_integer_sse<T, C, Base, Tr>(s + idx, l - idx) + _mm_cvtsi128_si32(res) * scale[l - idx], was_negative);
}
}
@ -310,57 +263,39 @@ namespace dhandy {
}
} //namespace implem
template <typename C, C FDigit='0', C FLetter='a', C CPlus='+', C CMinus='-', C CNull='\0', unsigned int DCount=10>
template <typename C, C FDigit='0', C FLetter='a', C CPlus='+', C CMinus='-'>
struct ASCIITranslator {
typedef C char_type;
static const constexpr bool BehavesLikeASCII = true;
static const constexpr C FirstDigit = FDigit;
static const constexpr C FirstLetter = FLetter;
//static const constexpr C AltLetter = FAltLetter;
static const constexpr C Plus = CPlus;
static const constexpr C Minus = CMinus;
static const constexpr C NullChar = CNull;
static const constexpr unsigned int DigitCount = DCount;
static constexpr C to_digit (unsigned int num) {
constexpr const C ret[2] = {FirstDigit, FirstLetter - DigitCount};
#if 0
//https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching
const bool f = num >= DigitCount;
constexpr const unsigned int m = 1;
const unsigned int w = (-f & m);
#else
const auto w = (DigitCount - 1 - num) >> (sizeof(unsigned int) * CHAR_BIT - 1);
#endif
return num + ret[w];
return (num <= 9 ?
static_cast<C>(num + FirstDigit) :
static_cast<C>(num + FirstLetter - 10)
);
}
static constexpr int from_digit (C dig) {
//return (dig < FirstLetter ? dig - FirstDigit : dig - FirstLetter + DigitCount);
typedef typename std::make_unsigned<C>::type UC;
constexpr const C ret[2] = {FirstLetter - DigitCount, FirstDigit};
const auto w = static_cast<UC>(dig - FirstLetter) >> (sizeof(UC) * CHAR_BIT - 1);
return dig - ret[w];
return (dig < FirstLetter ?
dig - FirstDigit :
dig - FirstLetter + 10
);
}
};
template <typename C>
using ASCIITranslatorUpcase = ASCIITranslator<C, '0', 'A'>;
template <typename I, I In, unsigned int Base=10, typename Tr=ASCIITranslator<char>>
constexpr inline const auto& buildtime_int_to_ary() {
return implem::g_int_to_str<I, In, Base, Tr>;
}
using ASCIITranslatorUpcase = ASCIITranslator<C, 'A'>;
template <typename I, unsigned int Base=10, typename Tr=ASCIITranslator<char>>
constexpr inline auto int_to_ary (I in) {
return implem::IntConversion<std::remove_cvref_t<I>, Base, Tr>::to_ary(in);
return implem::IntConversion<std::decay_t<I>, Base, Tr>::to_ary(in);
}
template <typename R, typename C, unsigned int Base=10, typename Tr=ASCIITranslator<C>>
constexpr inline R ary_to_int (const C* beg, const C* end) {
if (std::is_constant_evaluated())
return implem::AryConversion<R, Base, Tr, true>::from_ary(beg, end);
else
return implem::AryConversion<R, Base, Tr, false>::from_ary(beg, end);
inline R ary_to_int (const C* beg, const C* end) {
return implem::AryConversion<R, Base, Tr>::from_ary(beg, end);
}
#if !defined(INT_CONV_WITHOUT_HELPERS)
@ -369,9 +304,8 @@ namespace dhandy {
return std::string(int_to_ary(num).to_string_view());
}
template <typename C, std::size_t S>
inline
std::basic_string<C> operator+ (std::basic_string<C> a, const ReversedSizedArray<C, S>& b) {
template <std::size_t S>
std::string operator+ (std::string a, const ReversedSizedArray<char, S>& b) {
a.append(b.data(), b.size() - 1);
return a;
}

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -18,7 +18,7 @@
#ifndef idFC25566D624140559C54B39FFFE52F04
#define idFC25566D624140559C54B39FFFE52F04
#include "../variadic_repeat_bt.hpp"
#include <array>
#include <type_traits>
#include <stdexcept>
#if !defined(INT_CONV_WITHOUT_HELPERS)
@ -26,7 +26,6 @@
# include <string>
# include <sstream>
#endif
#include <tuple>
namespace dhandy {
template <typename T, std::size_t S>
@ -34,75 +33,38 @@ namespace dhandy {
static_assert(S > 0, "This container requires size to be at least 1");
static_assert(std::is_trivial<T>::value, "Only use this container with trivial types");
public:
constexpr static const std::size_t capacity = S;
using iterator = T*;
using iterator = typename std::array<T, S>::iterator;
constexpr ReversedSizedArray() = default;
constexpr ReversedSizedArray (const ReversedSizedArray&) = default;
constexpr ReversedSizedArray (ReversedSizedArray&&) = default;
template <typename... Items> constexpr explicit ReversedSizedArray (Items&&... items);
~ReversedSizedArray() = default;
constexpr std::size_t size() const { return S - (m_curr + 1); }
constexpr bool empty() const { return m_curr + 1 == S; }
constexpr const T operator[] (std::size_t idx) const { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; }
constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; }
constexpr void push_front (const T& itm) { /*if (size() == S) throw std::length_error("ReversedSizedArray is full");*/ m_data[m_curr--] = itm; }
constexpr const T* data() const { return m_data + m_curr + 1; }
constexpr const T* base_ptr() const { return m_data; }
constexpr iterator begin() { return m_data + m_curr + 1; }
constexpr iterator end() { return m_data + S; }
constexpr const T& back() const { return *(m_data + S - 1); }
constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; }
constexpr const T* data() const { return m_data.data() + m_curr + 1; }
constexpr iterator begin() { return m_data.begin() + m_curr + 1; }
constexpr iterator end() { return m_data.end(); }
constexpr const T& back() const { return *(m_data.data() + S - 1); }
template <typename V>
constexpr V to() const { return V(data(), size() - (not empty() and not back() ? 1 : 0)); }
constexpr auto to_tuple() const;
#if !defined(INT_CONV_WITHOUT_HELPERS)
constexpr std::basic_string_view<T> to_string_view() const { return to<std::basic_string_view<T>>(); }
bool operator== (const std::basic_string_view<T>& other) const { return to_string_view() == other; }
bool operator!= (const std::basic_string_view<T>& other) const { return not operator==(other); }
bool operator== (const std::basic_string<T>& other) const { return to_string_view() == other; }
bool operator!= (const std::basic_string<T>& other) const { return not operator==(other); }
bool operator== (const std::string& other) const { return to_string_view() == other; }
bool operator!= (const std::string& other) const { return not operator==(other); }
bool operator== (const T* other) const { return to_string_view() == std::basic_string_view<T>(other); }
bool operator!= (const T* other) const { return not operator==(other); }
std::string to_string() const { return to<std::basic_string<T>>(); }
#endif
private:
template <T... ItemsFill, typename... Items>
constexpr explicit ReversedSizedArray (bt::variadic_repeat<T, ItemsFill...>, Items&&... items);
T m_data[S];
std::array<T, S> m_data {};
std::size_t m_curr {S - 1};
};
namespace implem {
template <typename T, std::size_t S, std::size_t... Indices>
constexpr auto elements_or_empty_to_tuple (const T (&elems)[S], std::size_t from_idx, std::index_sequence<Indices...>) {
return std::make_tuple((from_idx + Indices < S ? elems[from_idx + Indices] : T{})...);
}
} //namespace implem
template <typename T, std::size_t S>
template <typename... Items>
inline constexpr ReversedSizedArray<T, S>::ReversedSizedArray (Items&&... items) :
ReversedSizedArray<T, S>(
bt::make_variadic_repeat<S - sizeof...(Items), T>{},
std::forward<Items>(items)...
)
{ }
template <typename T, std::size_t S>
template <T... ItemsFill, typename... Items>
constexpr ReversedSizedArray<T, S>::ReversedSizedArray (bt::variadic_repeat<T, ItemsFill...>, Items&&... items) :
m_data{ItemsFill..., std::forward<Items>(items)...},
m_curr(S - 1 - sizeof...(Items))
{
static_assert(sizeof...(ItemsFill) + sizeof...(Items) == S, "Wrong number of input elements");
}
#if !defined(INT_CONV_WITHOUT_HELPERS)
template <typename T, std::size_t S>
inline
@ -110,12 +72,14 @@ namespace dhandy {
stream << arr.to_string_view();
return stream;
}
#endif
template <typename T, std::size_t S>
constexpr auto ReversedSizedArray<T, S>::to_tuple() const {
return implem::elements_or_empty_to_tuple(m_data, m_curr + 1, std::make_index_sequence<S>{});
inline
std::basic_string<T> operator+ (std::basic_string<T>&& a, const ReversedSizedArray<T, S>& b) {
a.insert(a.end(), b.begin(), b.end());
return a;
}
#endif
} //namespace dhandy
#endif

View file

@ -0,0 +1,64 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
namespace duckmem {
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::DerivedPair() {
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::DerivedPair (typename Loki::TypeTraits<key_type>::ParameterType parKey, typename Loki::TypeTraits<value_type>::ParameterType parValue) :
parent_type(parKey, parValue)
{
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
ScapegoatMap<K, V, Hasher>::DerivedPair::~DerivedPair() {
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
// template <typename K, typename V, typename Hasher>
// bool ScapegoatMap<K, V, Hasher>::DerivedPair::operator< (const DerivedPair& parOther) const {
// const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first);
// const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first);
// if (thisHash == otherHash) {
// const bool typeMinor = (this->first < parOther.first);
//
// else
//wrong - this breaks total ordering condition return (thisHash < otherHash);
// }
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K, typename V, typename Hasher>
bool ScapegoatMap<K, V, Hasher>::DerivedPair::operator== (const DerivedPair& parOther) const {
const typename Hasher::HashType thisHash = Hasher::ComputeFullHash(this->first);
const typename Hasher::HashType otherHash = Hasher::ComputeFullHash(parOther->first);
if (thisHash != otherHash)
return false;
else
return (this->first == parOther.first);
}
} //namespace duckmem

View file

@ -0,0 +1,725 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
namespace duckmem {
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::ScapegoatTree() :
m_root(NULL),
m_count(0),
m_countMax(0),
m_reserved(0),
m_alpha(0.6f)
{
m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::ScapegoatTree (float parAlpha) :
m_root(NULL),
m_count(0),
m_countMax(0),
m_reserved(0),
m_alpha(parAlpha)
{
Assert(parAlpha < 1.0f);
Assert(parAlpha >= 0.5f);
m_alphainvloginv = 1.0f / std::log(1.0f / m_alpha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
ScapegoatTree<K>::~ScapegoatTree() {
delete_nodes(m_root);
#if defined(DUCK_DEBUG)
m_root = NULL;
m_count = 0xDEADBEEF;
m_countMax = 0xDEADBEEF;
m_reserved = 0xDEADBEEF;
#endif
}
///-------------------------------------------------------------------------
///I can't really find a good optimization for this method, so I'll just
///ignore the hint and rely on the normal insert().
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::iterator ScapegoatTree<K>::insert (const iterator&, const K& parValue) {
std::pair<iterator, bool> retVal = insert(parValue);
return retVal.first;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
std::pair<typename ScapegoatTree<K>::iterator, bool> ScapegoatTree<K>::insert (const K& parKey) {
const size_type depthHint = get_max_balanced_depth(std::max<size_type>(m_reserved, m_count + 1), m_alphainvloginv) + 3;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "insert(): depthHint = " << depthHint << ", m_count = " << m_count << ", m_countMax = " << m_countMax << ", m_reserved = " << m_reserved << std::endl;
#endif
if (NULL == m_root) {
m_root = get_new_node(parKey);
m_root->left = m_root->right = NULL;
m_root->size = 1;
m_count = 1;
m_countMax = 1;
m_reserved = std::max(m_count, m_reserved);
IteratorOnPtr<NodeType**, NodeType*, false> rootWrapper(&m_root, 1);
return std::pair<iterator, bool>(iterator(rootWrapper, 1, depthHint), true);
}
else {
//Refuse to add a new item if the tree has more items than it
//can count
if (std::numeric_limits<size_type>::max() == m_count or std::numeric_limits<typename NodeType::size_type>::max() == m_root->size) {
AssertNotReached();
return std::pair<iterator, bool>(end(), false);
}
NodeStack stack;
stack.reserve(depthHint);
NodeType* const closestMatch = get_insert_parent(m_root, parKey, stack);
Assert(stack.size() <= depthHint);
if (closestMatch->content == parKey)
return std::pair<iterator, bool>(iterator(stack.begin(), stack.size(), depthHint), false);
Assert(NULL == closestMatch->left or closestMatch->left->content < parKey);
Assert(NULL == closestMatch->right or parKey < closestMatch->right->content);
NodeType* const newNode = get_new_node(parKey);
newNode->left = newNode->right = NULL;
newNode->size = 1;
if (parKey < closestMatch->content) {
Assert(NULL == closestMatch->left);
closestMatch->left = newNode;
}
else {
Assert(NULL == closestMatch->right);
closestMatch->right = newNode;
}
++m_count;
m_countMax = std::max(m_count, m_countMax);
m_reserved = std::max(m_reserved, m_count);
//Update the count of every node
for (auto& node : stack) {
++node->size;
}
//Add the new node to the stack
Assert(stack.capacity() > stack.size());
stack.push_back(newNode);
#if defined(SCAPEGOATTREE_PARANOID)
const size_type totalSize = AssertNodeSize(m_root);
Assert(totalSize == m_count);
Assert(m_root->size == duckcore::checked_numcast<typename NodeType::size_type>(m_count));
#endif
size_type newNodeDepth = stack.size() - 1;
//Rebalance if necessary
if (not is_alpha_height_balanced(newNodeDepth, this->size())) {
#if defined(SCAPEGOATTREE_PARANOID)
Assert(find_max_depth(m_root) == newNodeDepth);
#endif
Assert(get_max_balanced_depth(static_cast<size_type>(m_root->size), m_alphainvloginv) + 1 == newNodeDepth);
std::pair<NodeType*, NodeType*> scapegoatAndParent = find_scapegoat(stack);
AssertRelease(NULL != scapegoatAndParent.first);
NodeType* const newRoot = rebalance(scapegoatAndParent.first, newNodeDepth + 1);
NodeType* const parent = scapegoatAndParent.second;
if (parent == NULL) {
Assert(scapegoatAndParent.first == m_root);
m_root = newRoot;
m_countMax = m_count;
}
else {
Assert(newRoot != parent);
if (parent->left == scapegoatAndParent.first) {
parent->left = newRoot;
}
else {
Assert(parent->right == scapegoatAndParent.first);
parent->right = newRoot;
}
}
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(m_root);
Assert(find_max_depth(m_root) <= get_max_balanced_depth(static_cast<size_type>(m_root->size), m_alphainvloginv));
#endif
//Rebuild the stack.
//TODO: this is ugly and slow, see if you can find a better way
stack.clear();
get_insert_parent(m_root, parKey, stack);
newNodeDepth = stack.size() - 1;
Assert(is_alpha_height_balanced(newNodeDepth, this->size()));
}
return std::pair<iterator, bool>(iterator(stack.begin(), newNodeDepth + 1, duckmath::log2_fast(m_reserved + 1)), true);
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::rebalance (NodeType* parSubtree, size_type parDepthHint) {
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Rebalancing subtree" << std::endl;
#endif
Assert(NULL != parSubtree);
NodeType* const newRoot = compress_first(parSubtree, parDepthHint);
NodeType* const retVal = compress(newRoot);
return retVal;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeTypePair ScapegoatTree<K>::find_scapegoat (NodeStack& parParents) const {
Assert(not parParents.empty());
const size_type height = parParents.size();
for (size_type z = parParents.size() - 1; z > 0; --z) {
NodeType& currNode = *(parParents[z - 1]);
Assert(height - z > 0);
if (not is_alpha_height_balanced(height - z, static_cast<size_type>(currNode.size))) {
NodeType* parent;
if (z == 1)
parent = NULL;
else
parent = parParents[z - 2];
return NodeTypePair(&currNode, parent);
}
}
AssertNotReached();
__builtin_unreachable();
return NodeTypePair(NULL, NULL);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::get_new_node (const K& parKey) {
return new NodeType(parKey);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
template <typename T>
T* ScapegoatTree<K>::find_closest_match (T* parTree, const K& parKey) {
Assert(NULL != parTree);
//if (parTree->left and parKey <= parTree->left->content)
if (parTree->left and not (parTree->left->content < parKey))
return FindClosestMatch(parTree->left, parKey);
//else if (parTree->right and parKey >= parTree->right->content)
else if (parTree->right and not (parKey < parTree->right->content))
return FindClosestMatch(parTree->right, parKey);
else
return parTree;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::get_insert_parent (NodeType* parTree, const K& parKey, NodeStack& parRewind) {
Assert(NULL != parTree);
NodeType* retVal = parTree;
bool goLeft;
while ((goLeft = (retVal->left and parKey < retVal->content)) or (retVal->right and retVal->content < parKey)) {
parRewind.push_back(retVal);
if (goLeft) {
Assert(NULL != retVal->left);
Assert(parKey < retVal->content);
retVal = retVal->left;
}
else {
Assert(NULL != retVal->right);
Assert(retVal->content < parKey);
retVal = retVal->right;
}
}
Assert(NULL != retVal);
Assert(parRewind.empty() or parRewind.back() != retVal);
parRewind.push_back(retVal);
return retVal;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::delete_nodes (NodeType* parNode) {
if (parNode) {
delete_nodes(parNode->left);
delete_nodes(parNode->right);
delete parNode;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
bool ScapegoatTree<K>::is_alpha_height_balanced (size_type parHeight, size_type parSize) const {
const float sz = static_cast<float>(parSize);
const float ha = std::floor(std::log(sz) * m_alphainvloginv);
const float height = static_cast<float>(parHeight);
return height <= ha;
}
///-------------------------------------------------------------------------
///Stout/Warren vine to tree.
///This function destroys the links of the given subtree and creates a
///structure that is suitable for compress(). Input is treated as if it
///was a linked list.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::compress_first (NodeType* parFrom, size_type parDepthHint) {
const size_type vineSize = static_cast<size_type>(parFrom->size);
const size_type iteratorDepth = parDepthHint;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "compress_first(): vineSize = " << vineSize << ", iteratorDepth = " << iteratorDepth << std::endl;
#endif
iterator itFirstStep(parFrom, iteratorDepth);
struct DummyNode {
DummyNode ( void ) : right(NULL) {}
NodeType* right;
};
class NodeWrapper {
public:
NodeWrapper ( void ) {}
explicit NodeWrapper ( NodeType* parOther ) : m_current(parOther), m_right(&parOther->right) {}
explicit NodeWrapper ( DummyNode* parOther ) : m_current(NULL), m_right(&parOther->right) {}
void Replace ( NodeType* parOther ) { m_current = parOther; m_right = &parOther->right; }
void Replace ( NodeWrapper* parOther ) { m_current = parOther->m_current; m_right = parOther->m_right; }
NodeType*& left ( void ) { Assert(m_current); return m_current->left; }
NodeType*& right ( void ) { Assert(m_right); return *m_right; }
typename NodeType::size_type& size ( void ) { Assert(m_current); return m_current->size; }
NodeType* pointer ( void ) { return m_current; }
private:
NodeType* m_current;
NodeType** m_right;
};
DummyNode pseudorootMem;
NodeWrapper parent(&pseudorootMem);
NodeWrapper current;
NodeWrapper child(&pseudorootMem);
size_type iterationsCount;
if (implem::is_power_of_two(vineSize + 1))
iterationsCount = (1 << (duckmath::log2_fast(vineSize))) - 1;
else
iterationsCount = (vineSize - ((1 << duckmath::log2_fast(vineSize)) - 1));
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "vineSize = " << vineSize << ", iterationsCount = " << iterationsCount << std::endl;
#endif
Assert(iterationsCount < vineSize); //Underflow error?
Assert(iterationsCount > 0);
for (size_type z = 0; z < iterationsCount; ++z) {
current.Replace(itFirstStep.GetPointer());
++itFirstStep;
child.Replace(itFirstStep.GetPointer());
++itFirstStep;
current.left() = NULL;
current.right() = NULL;
current.size() = 1;
parent.right() = child.pointer();
child.left() = current.pointer();
Assert(z * 2 < vineSize);
child.size() = static_cast<typename NodeType::size_type>(vineSize - z * 2);
Assert(child.size() >= 1);
parent.Replace(&child);
}
Assert(iterationsCount * 2 <= vineSize);
for (size_type z = iterationsCount * 2; z < vineSize; ++z) {
child.right() = itFirstStep.GetPointer();
child.Replace(itFirstStep.GetPointer());
++itFirstStep;
child.left() = NULL;
child.size() = static_cast<typename NodeType::size_type>(vineSize - z);
}
child.right() = NULL;
child.size() = (child.left() ? 2 : 1);
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "Original size was " << vineSize << ", root's size is " << pseudorootMem.right->size << std::endl;
#endif
Assert(vineSize == static_cast<size_type>(pseudorootMem.right->size));
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(pseudorootMem.right);
Assert(find_max_depth(pseudorootMem.right) <= vineSize);
#endif
return pseudorootMem.right;
}
///-------------------------------------------------------------------------
///Stout/Warren vine to tree.
///Performs the second and subsequent steps for compressing.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::compress (NodeType* parFrom) {
Assert(NULL != parFrom);
//We don't know if the tree is complete, so let's calculate its depth
//rounded up to the nearest complete tree
const size_type treeSize = static_cast<size_type>(parFrom->size);
const size_type m = duckmath::log2_fast(1 + treeSize);
const size_type treeHeight = duckmath::log2_fast(treeSize + (1 << m));
#if defined(SCAPEGOATTREE_PARANOID)
size_type maxDepthInTree = find_max_depth(parFrom);
{
//We know step 0 of compression has already been done, so on with
//the spine size at step 1 (the one we're willing to do)
const size_type vineSize = (1 << (treeHeight - 1)) - 1;
size_type count = 0;
NodeType* currNode = parFrom;
do {
++count;
currNode = currNode->right;
} while (currNode);
const size_type countedNodes = ((count + 1) bitand ~1) - 1;
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "treeSize = " << treeSize << ", vineSize = " << vineSize << ", treeHeight = " << treeHeight << ", manually counted " << countedNodes << " nodes (" << count << ")\n";
#endif
Assert(implem::is_power_of_two(countedNodes + 1));
Assert(vineSize == countedNodes);
}
#endif
NodeType* retVal = parFrom;
Assert(treeHeight >= 2);
for (size_type k = 1; k < treeHeight - 1; ++k) {
#if defined(SCAPEGOATTREE_VERBOSE)
std::cout << "compress() step " << k << std::endl;
#endif
//The rebalanced tree takes treeHeight-1 steps. One step has been done
//already, so we perform the remaining treeHeight-2 steps.
NodeType* scanner;
NodeType* child = retVal;
retVal = child->right;
Assert(NULL != retVal);
const size_type spineSize = (1 << (treeHeight - k - 1)) - 1;
Assert(spineSize > 0);
for (size_type s = 0; s < spineSize; ++s) {
scanner = child->right;
Assert(NULL != scanner);
child->right = scanner->left;
scanner->left = child;
const typename NodeType::size_type leftBranchSize = (child->right ? child->right->size : 0);
child->size -= scanner->size - leftBranchSize;
scanner->size += child->size - leftBranchSize;
if (s + 1 < spineSize) {
child = scanner->right;
Assert(NULL != child);
scanner->right = child->right;
}
#if defined(SCAPEGOATTREE_VERBOSE)
const size_type subtreeSize = (1 << (k + 1)) - 1;
std::cout << "k=" << k << " - Scanner's size updated to " << scanner->size << ", calculated subtreeSize = " << subtreeSize << std::endl;
#endif
}
Assert(NULL != scanner);
Assert(NULL != retVal);
Assert(treeSize == static_cast<size_type>(retVal->size));
#if defined(SCAPEGOATTREE_PARANOID)
AssertNodeSize(retVal);
{
const size_type newDepth = find_max_depth(retVal);
Assert(newDepth <= maxDepthInTree);
maxDepthInTree = newDepth;
}
#endif
}
Assert(static_cast<size_type>(retVal->size) == treeSize);
return retVal;
}
#if defined(SCAPEGOATTREE_PARANOID)
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::assert_node_size (const NodeType* parSubtree) {
Assert(parSubtree);
typename NodeType::size_type localSize = 1;
if (parSubtree->left) {
localSize += AssertNodeSize(parSubtree->left);
}
if (parSubtree->right) {
localSize += AssertNodeSize(parSubtree->right);
}
Assert(parSubtree->size == localSize);
return localSize;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::find_max_depth_rec (const NodeType* parSubtree) {
Assert(parSubtree);
typename NodeType::size_type depthLeft = 0;
typename NodeType::size_type depthRight = 0;
if (parSubtree->left) {
depthLeft = FindMaxDepth_rec(parSubtree->left);
}
if (parSubtree->right) {
depthRight = FindMaxDepth_rec(parSubtree->right);
}
return 1 + std::max(depthLeft, depthRight);
}
#endif
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::get_max_balanced_depth (size_type parSize, float parAlphaInvLogInv) {
const float ha = std::log(static_cast<float>(parSize)) * parAlphaInvLogInv;
return static_cast<size_type>(ha);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::iterator ScapegoatTree<K>::begin() {
if (NULL == m_root)
return iterator();
const size_type depthHint = get_tree_min_depth_ib(m_reserved, m_alphainvloginv) + 1;
#if defined(SCAPEGOATTREE_PARANOID)
Assert(is_alpha_height_balanced(find_max_depth(m_root), static_cast<size_type>(m_root->size)));
Assert(find_max_depth(m_root) + 1 <= depthHint);
#endif
return iterator(m_root, depthHint + 1);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::const_iterator ScapegoatTree<K>::begin() const {
if (NULL == m_root)
return iterator();
const size_type depthHint = get_tree_min_depth_ib(m_count, m_alphainvloginv) + 1;
#if defined(SCAPEGOATTREE_PARANOID)
Assert(is_alpha_height_balanced(find_max_depth(m_root), static_cast<size_type>(m_root->size)));
Assert(find_max_depth(m_root) + 1 <= depthHint);
#endif
return const_iterator(m_root, depthHint + 1);
}
///-------------------------------------------------------------------------
///Get min tree depth if balanced
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::size_type ScapegoatTree<K>::get_tree_min_depth_ib (size_type parSize, float parAlphaInvLogInv) {
const float sz = static_cast<float>(parSize);
const size_type roundedDownDepthBase2 = duckmath::log2_fast(parSize + 1);
const float nodesAtLastLevel = (roundedDownDepthBase2 == 0 ? 0 : static_cast<float>(1 << roundedDownDepthBase2) - 1.0f);
const float retVal = std::log(sz + nodesAtLastLevel) * parAlphaInvLogInv;
return static_cast<size_type>(retVal);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::clear() {
delete_nodes(m_root);
m_count = 0;
m_countMax = 0;
m_root = NULL;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::find_ifp (NodeType* parTree, const K& parKey) {
while (parTree) {
if (parKey < parTree->content)
parTree = parTree->left;
else if (parTree->content < parKey)
parTree = parTree->right;
else
break;
}
return parTree;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::find_parent_ifp (NodeType* parTree, const NodeType* parSearchNodeAddr) {
if (parTree == parSearchNodeAddr)
return NULL;
NodeType* parent = parTree;
while (parTree and (parTree->left != parSearchNodeAddr and parTree->right != parSearchNodeAddr)) {
if (parSearchNodeAddr->content < parTree->content)
parTree = parTree->left;
else if (parTree->content < parSearchNodeAddr->content)
parTree = parTree->right;
else
break;
parent = parTree;
}
return parent;
}
///-------------------------------------------------------------------------
///Set parSuccessor to true to get the in-order successor, or false to
///get the in-order predecessor.
///-------------------------------------------------------------------------
template <typename K>
typename ScapegoatTree<K>::NodeType* ScapegoatTree<K>::detach_bottom_node (NodeType* parTree, bool parSuccessor) {
AssertRelease(NULL != parTree);
AssertRelease(NULL != parTree->left and NULL != parTree->right);
if (parSuccessor) {
NodeType* inorderSuccessor = parTree->right;
NodeType* successorsParent = parTree;
while (NULL != inorderSuccessor->left) {
successorsParent = inorderSuccessor;
inorderSuccessor = inorderSuccessor->left;
}
Assert(inorderSuccessor == successorsParent->left and inorderSuccessor != successorsParent->right);
Assert(NULL == inorderSuccessor->left);
Assert(NULL == inorderSuccessor->right or inorderSuccessor->right->content < successorsParent->content);
successorsParent->left = inorderSuccessor->right;
Assert(inorderSuccessor);
return inorderSuccessor;
}
else {
NodeType* inorderPredecessor = parTree->left;
NodeType* predecessorsParent = parTree;
while (NULL != inorderPredecessor->right) {
predecessorsParent = inorderPredecessor;
inorderPredecessor = inorderPredecessor->right;
}
Assert(inorderPredecessor == predecessorsParent->right and inorderPredecessor != predecessorsParent->left);
Assert(NULL == inorderPredecessor->right);
Assert(NULL == inorderPredecessor->left or predecessorsParent->content < inorderPredecessor->left->content);
predecessorsParent->right = inorderPredecessor->left;
Assert(inorderPredecessor);
return inorderPredecessor;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
bool ScapegoatTree<K>::include (const K& parSearch) const {
const NodeType* const found = find_ifp(m_root, parSearch);
Assert(not found or not (parSearch < found->content or found->content < parSearch));
return static_cast<bool>(NULL != found);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::rebalance_after_deletion_ifn() {
const float sz = static_cast<float>(m_count);
const float m = static_cast<float>(m_countMax);
if (sz < m_alpha * m) {
const size_type sizeHint = static_cast<size_type>(std::ceil(std::log(sz) * m_alphainvloginv)) + 1;
rebalance(m_root, sizeHint);
m_countMax = m_count;
}
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
void ScapegoatTree<K>::erase (iterator parItem) {
NodeType* const dele = parItem.GetPointer();
AssertRelease(NULL != dele);
Assert(m_count > 0);
NodeType* parent;
if (dele == m_root)
parent = m_root;
else
parent = find_parent_ifp(m_root, dele);
Assert(NULL != parent);
if (parent) {
Assert(dele == parent->left or dele == parent->right or dele == parent);
NodeType*& parentChildRef = (dele == m_root ? m_root : (dele == parent->left ? parent->left : parent->right));
if (NULL == dele->left and NULL == dele->right) {
parentChildRef = NULL;
}
else if (NULL == dele->left xor NULL == dele->right) {
parentChildRef = (dele->left ? dele->left : dele->right);
}
else {
NodeType* const inorderSuccessor = detach_bottom_node(dele, true);
parentChildRef = inorderSuccessor;
inorderSuccessor->left = dele->left;
inorderSuccessor->right = dele->right;
}
Assert(NULL == parent->left or parent->left->content < parent->content);
Assert(NULL == parent->right or parent->content < parent->right->content);
}
--m_count;
delete dele;
rebalance_after_deletion_ifn();
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
inline typename ScapegoatTree<K>::iterator ScapegoatTree<K>::find (const K& parSearch) {
NodeStack stack;
const size_type depthHint = get_max_balanced_depth(std::max<size_type>(m_reserved, m_count + 1), m_alphainvloginv) + 3;
stack.reserve(depthHint);
NodeType* const closestMatch = get_insert_parent(m_root, parSearch, stack);
Assert(stack.size() <= depthHint);
if (closestMatch->content == parSearch)
return iterator(stack.begin(), stack.size(), depthHint);
else
return this->end();
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename K>
inline typename ScapegoatTree<K>::const_iterator ScapegoatTree<K>::find (const K& parSearch) const {
return const_cast<ScapegoatTree<K>*>(this)->find(parSearch);
}
// ///-------------------------------------------------------------------------
// ///-------------------------------------------------------------------------
// template <typename K>
// void ScapegoatTree<K>::erase (iterator parFrom, iterator parLast) {
// }
//
// ///-------------------------------------------------------------------------
// ///-------------------------------------------------------------------------
// template <typename K>
// typename ScapegoatTree<K>::size_type ScapegoatTree<K>::erase (typename Loki::TypeTraits<value_type>::ParameterType parKey) {
// }
} //namespace duckmem

View file

@ -0,0 +1,258 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
namespace duckmem {
namespace Implem {
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename P>
bool TreeIterator_base<P>::Exhausted() const {
return m_stack.empty();
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename P>
TreeIterator_base<P>::TreeIterator_base (const TreeIterator_base& parOther) :
m_stack()
{
m_stack.reserve(parOther.m_stack.capacity());
m_stack = parOther.m_stack;
Assert(m_stack.capacity() == parOther.m_stack.capacity());
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename P>
template <typename P1>
TreeIterator_base<P>::TreeIterator_base (const TreeIterator_base<P1>& parOther) {
typename TreeIterator_base<P1>::StackType otherStackCopy(parOther.m_stack);
std::vector<P> localCopy;
localCopy.reserve(parOther.m_stack.size());
while (not otherStackCopy.empty()) {
P convertedItem = otherStackCopy.back();
localCopy.push_back(convertedItem);
otherStackCopy.pop_back();
}
m_stack.reserve(parOther.m_stack.capacity());
for (typename std::vector<P>::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) {
Assert(m_stack.capacity() > m_stack.size());
m_stack.push_back(*itRev);
}
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, false>::reference TreeIterator_const_layer<T, N, false>::operator* () {
AssertRelease(not this->Exhausted());
return this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, false>::const_reference TreeIterator_const_layer<T, N, false>::operator* () const {
AssertRelease(not this->Exhausted());
return this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, false>::pointer TreeIterator_const_layer<T, N, false>::operator-> () {
AssertRelease(not this->Exhausted());
return &this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, false>::const_pointer TreeIterator_const_layer<T, N, false>::operator-> () const {
AssertRelease(not this->Exhausted());
return &this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
N* TreeIterator_const_layer<T, N, false>::GetPointer() {
AssertRelease(not this->Exhausted());
return this->m_stack.back();
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
const N* TreeIterator_const_layer<T, N, false>::GetPointer() const {
AssertRelease(not this->Exhausted());
return this->m_stack.back();
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, true>::const_reference TreeIterator_const_layer<T, N, true>::operator* () const {
AssertRelease(not this->Exhausted());
return this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
typename TreeIterator_const_layer<T, N, true>::const_pointer TreeIterator_const_layer<T, N, true>::operator-> () const {
AssertRelease(not this->Exhausted());
return &this->m_stack.back()->content;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <typename T, typename N>
const N* TreeIterator_const_layer<T, N, true>::GetPointer() const {
AssertRelease(not this->Exhausted());
return this->m_stack.back();
}
} //namespace Implem
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N>::TreeIterator() {
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N>::TreeIterator (const TreeIterator& parOther) :
parent_type(parOther)
{
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
template <typename T1>
TreeIterator<T, N>::TreeIterator (const TreeIterator<T1, N>& parOther) :
parent_type(parOther)
{
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
template <typename S>
TreeIterator<T, N>::TreeIterator (S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint) {
AssertRelease(parStackLen > 0);
this->m_stack.reserve(std::max(parStackLen, parMaxDepthHint));
typename StackType::value_type prevNode = *parCopyStackBottomUp;
++parCopyStackBottomUp;
this->m_stack.push_back(prevNode);
for (size_type z = 1; z < parStackLen; ++z) {
typename StackType::value_type currNode = *parCopyStackBottomUp;
if (prevNode->left == currNode) {
Assert(this->m_stack.capacity() > this->m_stack.size());
this->m_stack.push_back(currNode);
}
else {
//If you get this assertion make sure the iterator you are
//passing in is reversed (ie: from leaf to root)
AssertRelease(currNode == prevNode->right);
this->m_stack.pop_back();
this->m_stack.push_back(currNode);
}
prevNode = currNode;
++parCopyStackBottomUp;
}
Assert(not this->Exhausted());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N>::TreeIterator (NodeTypePointer parRoot, size_type parMaxDepthHint) {
if (parMaxDepthHint > 0)
this->m_stack.reserve(parMaxDepthHint);
RecurseLeft(parRoot);
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N>::~TreeIterator() {
}
///-------------------------------------------------------------------------
///Post-increment
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N> TreeIterator<T, N>::operator++ (int) {
AssertRelease(not this->Exhausted());
TreeIterator<T, N> retVal = *this;
++(*this);
return retVal;
}
///-------------------------------------------------------------------------
///Pre-increment
///-------------------------------------------------------------------------
template <typename T, typename N>
TreeIterator<T, N>& TreeIterator<T, N>::operator++() {
AssertRelease(not this->Exhausted());
NodeTypePointer currNode = this->m_stack.back();
#if defined(ASSERTIONSENABLED)
const size_type stackCapacity = this->m_stack.capacity();
#endif
AssertRelease(not this->m_stack.empty());
this->m_stack.pop_back();
#if defined(ASSERTIONSENABLED)
//It shouldn't normally happen, but it's just to make sure
Assert(stackCapacity == this->m_stack.capacity());
#endif
RecurseLeft(currNode->right);
return *this;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
const TreeIterator<T, N>& TreeIterator<T, N>::operator= (const TreeIterator& parOther) {
this->m_stack = parOther.m_stack;
Assert(this->m_stack.capacity() >= parOther.m_stack.capacity());
return *this;
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
bool TreeIterator<T, N>::operator== (const TreeIterator& parOther) const {
return this->m_stack.size() == parOther.m_stack.size() and (this->m_stack.empty() or parOther.m_stack.back() == this->m_stack.back());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, typename N>
void TreeIterator<T, N>::RecurseLeft (NodeTypePointer parFrom) {
NodeTypePointer currNode = parFrom;
while (NULL != currNode) {
Assert(this->m_stack.capacity() > this->m_stack.size());
this->m_stack.push_back(currNode);
currNode = currNode->left;
}
}
} //namespace duckmem

View file

@ -5,12 +5,12 @@
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
namespace dhandy {
#include <iterator>
template <class T,
class charT=char,
class traits=std::char_traits<charT> >
class infix_ostream_iterator
class infix_ostream_iterator :
public std::iterator<std::output_iterator_tag,void,void,void,void>
{
std::basic_ostream<charT,traits> *os;
charT const* delimiter;
@ -19,13 +19,6 @@ public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT,traits> ostream_type;
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
infix_ostream_iterator(ostream_type& s)
: os(&s),delimiter(0), first_elem(true)
{}
@ -52,5 +45,4 @@ public:
return *this;
}
};
} //namespace dhandy
#endif

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -22,96 +22,36 @@
#include <type_traits>
#include <string>
#include <string_view>
#include <array>
#define DHANDY_INTCONV_USE_STDSTRING
namespace dhandy {
namespace implem {
template <typename T, typename F, typename Tr, bool FromInt=std::is_integral_v<F>>
template <typename T, typename F>
struct IntConv;
template <typename Tr>
using IntConvString = std::basic_string<typename Tr::char_type>;
template <typename Tr>
using IntConvStringView = std::basic_string_view<typename Tr::char_type>;
template <typename F, typename Tr>
struct IntConv<IntConvString<Tr>, F, Tr, true> {
static IntConvString<Tr> conv (const F& in) {
auto retval = dhandy::int_to_ary<F, 10, Tr>(in);
return IntConvString<Tr>{retval.begin(), retval.end() - 1};
template <typename F>
struct IntConv<std::enable_if_t<std::is_integral_v<F>, std::string>, F> {
static std::string conv (const F& in) {
auto retval = dhandy::int_to_ary(in);
return std::string(retval.begin(), retval.end() - 1);
}
};
#if defined(DHANDY_INTCONV_USE_STDSTRING)
template <typename F, typename C>
struct IntConv<IntConvString<ASCIITranslator<C>>, F, ASCIITranslator<C>, true> {
static IntConvString<ASCIITranslator<C>> conv (const F& in) {
return std::to_string(in);
template <typename T>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, std::string>> {
static T conv (const std::string& in) {
return dhandy::ary_to_int<T>(in.data(), in.data() + in.size());
}
};
#endif
template <typename F, typename Tr>
struct IntConv<IntConvStringView<Tr>, F, Tr, true> {
consteval static IntConvStringView<Tr> conv (const F& in) {
return dhandy::int_to_ary<F, 10, Tr>(in).to_string_view();
}
};
template <typename F, typename Tr, typename C, std::size_t N>
struct IntConv<std::array<C, N>, F, Tr, true> {
private:
template <typename... Args, std::size_t... Indices>
constexpr static std::array<C, N> to_array (const std::tuple<Args...>& vals, std::index_sequence<Indices...>) {
return std::array<C, N>{std::get<Indices>(vals)...};
}
public:
constexpr static std::array<C, N> conv (const F& in) {
return to_array(
dhandy::int_to_ary<F, 10, Tr>(in).to_tuple(),
std::make_index_sequence<
std::min(decltype(dhandy::int_to_ary<F, 10, Tr>(in))::capacity, N)
>{}
);
}
};
template <typename T, typename Tr>
struct IntConv<T, IntConvString<Tr>, Tr, false> {
constexpr static T conv (const IntConvString<Tr>& in) {
return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
in.data() + in.size()
);
}
};
template <typename T, typename Tr>
struct IntConv<T, IntConvStringView<Tr>, Tr, false> {
constexpr static T conv (const IntConvStringView<Tr>& in) {
return dhandy::ary_to_int<T, char, 10, Tr>(
in.data(),
in.data() + in.size()
);
}
};
template <typename T, typename F, F In, typename Tr, bool FromInt>
struct IntConv<T, std::integral_constant<F, In>, Tr, FromInt> {
constexpr static T conv (const std::integral_constant<F, In>&) {
return dhandy::buildtime_int_to_ary<F, In, 10, Tr>().to_string_view();
template <typename T>
struct IntConv<T, std::enable_if_t<std::is_integral_v<T>, std::string_view>> {
static T conv (const std::string_view& in) {
return dhandy::ary_to_int<T>(in.data(), in.data() + in.size());
}
};
} //namespace implem
template <typename To, typename From, bool AllCaps=false>
constexpr inline To int_conv (const From& from, std::integral_constant<bool, AllCaps> = std::integral_constant<bool, AllCaps>{}) {
if constexpr (AllCaps)
return implem::IntConv<To, From, ASCIITranslatorUpcase<char>>::conv(from);
else
return implem::IntConv<To, From, ASCIITranslator<char>>::conv(from);
}
template <typename From>
inline auto int_conv_raw (const From& from) {
return int_to_ary<From, 10, ASCIITranslator<char>>(from);
template <typename To, typename From>
inline To int_conv (const From& from) {
return implem::IntConv<To, From>::conv(from);
}
} //namespace dhandy

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -0,0 +1,76 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id28695193476D4A9499151FC175A49196
#define id28695193476D4A9499151FC175A49196
#include <cstdint>
#if defined(__linux)
# include <strings.h>
#endif
namespace duckmath {
namespace implem {
#if !defined(__linux)
[[gnu::pure]]
inline uint_fast32_t LowestBitSet ( uint_fast32_t x ) pure_function;
//Precomputed lookup table
const constexpr uint_fast32_t g_multiplyDeBruijnBitPosition[32] = {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
///---------------------------------------------------------------------
///Thanks to: http://bits.stephan-brumme.com/lowestBitSet.html
///---------------------------------------------------------------------
[[gnu::pure]]
inline uint_fast32_t LowestBitSet (uint_fast32_t x) {
//Leave only lowest bit
x &= -i32(x);
//DeBruijn constant
x *= 0x077CB531;
//Get upper 5 bits
x >>= 27;
//Convert to actual position
return g_multiplyDeBruijnBitPosition[x];
}
#endif
[[gnu::pure]]
inline uint32_t GetHighestBitOnly (uint32_t parIn) {
parIn |= (parIn >> 1);
parIn |= (parIn >> 2);
parIn |= (parIn >> 4);
parIn |= (parIn >> 8);
parIn |= (parIn >> 16);
return parIn - (parIn >> 1);
}
} //namespace implem
uint_fast32_t log2_fast (uint_fast32_t parX) {
const uint_fast32_t highestPow2 = implem::GetHighestBitOnly(parX);
#if defined(__linux)
const uint_fast32_t retVal = ffs(highestPow2) - 1;
#else
const uint_fast32_t retVal = LowestBitSet(highestPow2);
#endif
return retVal;
}
} //namespace duckmath
#endif

View file

@ -1,194 +0,0 @@
/* Copyright 2016-2025 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id83CE9FAB90684250B98EA584C548E13F
#define id83CE9FAB90684250B98EA584C548E13F
#include "bitfield_pack.hpp"
#include <cstdint>
#include <utility>
#include <climits>
namespace dhandy {
namespace implem {
//This monster expression is just the one-liner version of this
//implementation of log2:
//unsigned int v; // 32-bit value to find the log2 of
//register unsigned int r; // result of log2(v) will go here
//register unsigned int shift;
//
//r = (v > 0xFFFF) << 4; v >>= r;
//shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
//shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
//shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
// r |= (v >> 1);
//see https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog for
//an explanation of that.
//This is a shorter version of it but it only works if the input is a power
//of 2:
//(((((NUM&0xAAAAAAAA)!=0)|((NUM&0xFFFF0000)!=0)<<4)|((NUM&0xFF00FF00)!=0)<<
//3)|((NUM&0xF0F0F0F0)!=0)<<2)|((NUM&0xCCCCCCCC)!=0)<<1
//Source for that is also available at the page linked above.
template <std::uint32_t NUM> const constexpr std::size_t
pointer_unused_bit_count =
((((((NUM > 0xFFFF) << 4) | (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) <<
3)) | ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) <<
4)) > 0xFF) << 3)) > 0xF) << 2)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >>
(((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM >
0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF)
<< 2)) > 0x3) << 1)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> (
(NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4)
) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) >> ((
(((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) >
0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM >
0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) > 0x3) << 1)) >> 1))
;
template <std::size_t... S>
BitfieldPack<
std::uintptr_t,
sizeof(std::uintptr_t) * CHAR_BIT - sizeof...(S), (S+1)/(S+1)...
>
guess_bitfield_type (std::index_sequence<S...>);
template <typename T>
using BaseBitfieldPackForPackedPointer = decltype(
implem::guess_bitfield_type(
std::make_index_sequence<implem::pointer_unused_bit_count<alignof(T)>>()
)
);
} //namespace implem
template <typename T>
class PackedPointer : private implem::BaseBitfieldPackForPackedPointer<T> {
static_assert(sizeof(T*) == sizeof(std::uintptr_t), "Mismatching int/pointer size");
typedef implem::BaseBitfieldPackForPackedPointer<T> parent_type;
public:
static const constexpr std::size_t FlagsCount = parent_type::TotalEntries - 1;
PackedPointer();
PackedPointer (T* ptr);
~PackedPointer() = default;
operator T*() const;
operator bool() const;
template <std::size_t Idx> bool flag () const;
template <std::size_t Idx> void set_flag (bool v);
PackedPointer& operator= (T* ptr);
T* operator->();
const T* operator->() const;
T& operator*();
const T& operator*() const;
bool operator== (const PackedPointer& other) const;
bool operator== (T* other) const;
bool operator!= (const PackedPointer& other) const;
bool operator!= (T* other) const;
private:
//static const constexpr uintptr_t PtrMask = static_cast<uintptr_t>(-1) << FlagsCount;
};
template <typename T> const constexpr std::size_t PackedPointer<T>::FlagsCount;
//template <typename T> const constexpr std::uintptr_t PackedPointer<T>::PtrMask;
template <typename T>
PackedPointer<T>::PackedPointer() :
PackedPointer(nullptr)
{
}
template <typename T>
PackedPointer<T>::PackedPointer (T* ptr) :
parent_type(0)
{
(*this) = ptr;
}
template <typename T>
PackedPointer<T>::operator T*() const {
return reinterpret_cast<T*>(this->get(0) << FlagsCount);
}
template <typename T>
PackedPointer<T>::operator bool() const {
return static_cast<T*>(*this) != nullptr;
}
template <typename T>
template <std::size_t Idx>
bool PackedPointer<T>::flag() const {
static_assert(Idx < FlagsCount, "Index out of range");
return static_cast<bool>(this->get(Idx + 1));
}
template <typename T>
template <std::size_t Idx>
void PackedPointer<T>::set_flag (bool v) {
static_assert(Idx < FlagsCount, "Index out of range");
this->set(Idx + 1, (v ? 1 : 0));
}
template <typename T>
PackedPointer<T>& PackedPointer<T>::operator= (T* ptr) {
this->set(0, reinterpret_cast<std::uintptr_t>(ptr) >> FlagsCount);
return *this;
}
template <typename T>
T* PackedPointer<T>::operator->() {
return static_cast<T*>(*this);
}
template <typename T>
const T* PackedPointer<T>::operator->() const {
return static_cast<T*>(*this);
}
template <typename T>
T& PackedPointer<T>::operator*() {
return *static_cast<T*>(*this);
}
template <typename T>
const T& PackedPointer<T>::operator*() const {
return *static_cast<T*>(*this);
}
template <typename T>
bool PackedPointer<T>::operator== (const PackedPointer& other) const {
return this == &other or static_cast<T*>(*this) == static_cast<T*>(other);
}
template <typename T>
bool PackedPointer<T>::operator== (T* other) const {
return static_cast<T*>(*this) == other;
}
template <typename T>
bool PackedPointer<T>::operator!= (const PackedPointer& other) const {
return not this->operator==(other);
}
template <typename T>
bool PackedPointer<T>::operator!= (T* other) const {
return not this->operator==(other);
}
} //namepace dhandy
#endif

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -0,0 +1,51 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef idDD2D1A57ABEB4BEEA0F7E46C347D1637
#define idDD2D1A57ABEB4BEEA0F7E46C347D1637
#include "scapegoat_tree.hpp"
namespace duckmem {
template <typename K, typename V, typename Hasher>
class ScapegoatMap {
public:
typedef K key_type;
typedef V value_type;
ScapegoatMap ( void );
~ScapegoatMap ( void );
private:
class DerivedPair : public std::pair<key_type, value_type> {
typedef std::pair<key_type, value_type> parent_type;
public:
DerivedPair ( void );
DerivedPair ( typename Loki::TypeTraits<key_type>::ParameterType parKey, typename Loki::TypeTraits<value_type>::ParameterType parValue );
~DerivedPair ( void );
bool operator< ( const DerivedPair& parOther ) const;
bool operator== ( const DerivedPair& parOther ) const;
};
ScapegoatTree<DerivedPair> m_tree;
};
} //namespace duckmem
#include "implem/scapegoat_map.inl"
#endif

View file

@ -0,0 +1,163 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id79CEDB2530B54204A6BEDCBE0B767EA1
#define id79CEDB2530B54204A6BEDCBE0B767EA1
#include "tree_iterator.hpp"
#include "implem/IteratorOnPtr.hpp"
#include "log2_fast.hpp"
#include <limits>
#include <utility>
#include <cmath>
#include <cassert>
#include <cstdint>
//#define SCAPEGOATTREE_VERBOSE
//#define SCAPEGOATTREE_PARANOID
#define SCAPEGOATTREE_DYNAMIC_SIZE_TYPE
#if defined(DUCK_FINAL)
# if defined(SCAPEGOATTREE_VERBOSE)
# undef(SCAPEGOATTREE_VERBOSE)
# endif
#endif
#if !defined(ASSERTIONSENABLED)
# if defined(SCAPEGOATTREE_PARANOID)
# undef(SCAPEGOATTREE_PARANOID)
# endif
#endif
namespace duckmem {
using dhandy::IteratorOnPtr;
namespace implem {
[[gnu::pure]]
inline bool is_power_of_two (unsigned int parValue) {
return (parValue != 0 and (parValue bitand (~parValue + 1)) == parValue);
}
} //namespace implem
//TODO: implement or remove
class SmallObject {
public:
protected:
SmallObject ( void )=default;
~SmallObject ( void ) noexcept =default;
private:
};
template <typename K>
class ScapegoatTree {
public:
typedef K value_type;
typedef size_t size_type;
private:
template <typename SizeType>
struct TreeNodeStruct : public SmallObject {
typedef SizeType size_type;
TreeNodeStruct ( void );
TreeNodeStruct ( const K& parContent ) : content(parContent) {}
K content;
TreeNodeStruct* left;
TreeNodeStruct* right;
size_type size;
};
#if defined(SCAPEGOATTREE_DYNAMIC_SIZE_TYPE)
typedef typename std::conditional<sizeof(TreeNodeStruct<size_type>) == sizeof(TreeNodeStruct<uint32_t>), size_type, uint32_t>::type TreeNodeSizeType;
typedef TreeNodeStruct<TreeNodeSizeType> TreeNode;
#else
typedef TreeNodeStruct<size_type> TreeNode;
#endif
static_assert(sizeof(typename TreeNode::size_type) <= sizeof(size_type), "Mismatching size_type size");
typedef TreeNode NodeType;
typedef std::vector<NodeType*> NodeStack;
typedef std::pair<NodeType*, NodeType*> NodeTypePair;
public:
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type* const_pointer;
typedef const value_type& const_reference;
typedef duckmem::TreeIterator<value_type, NodeType> iterator;
typedef duckmem::TreeIterator<const value_type, NodeType> const_iterator;
ScapegoatTree ( void );
explicit ScapegoatTree ( float parAlpha );
~ScapegoatTree ( void );
float get_alpha ( void ) const { return m_alpha; }
bool include ( const K& parSearch ) const;
std::pair<iterator, bool> insert ( const K& parKey );
iterator insert ( const iterator&, const K& parValue );
bool empty ( void ) const { return m_count == 0; }
size_type size ( void ) const { return m_count; }
void reserve ( size_type parSize ) { m_reserved = std::max(parSize, m_count); }
size_type capacity ( void ) const { return m_reserved; }
void clear ( void );
void erase ( iterator parItem );
void erase ( iterator parFrom, iterator parLast );
size_type erase ( const value_type& parKey );
iterator find ( const K& parSearch );
const_iterator find ( const K& parSearch ) const;
iterator begin ( void );
const_iterator begin ( void ) const;
iterator end ( void ) { return iterator(); }
const_iterator end ( void ) const { return const_iterator(); }
private:
template <typename T>
static T* find_closest_match ( T* parTree, const K& parKey );
static NodeType* get_insert_parent ( NodeType* parTree, const K& parKey, NodeStack& parRewind );
static NodeType* find_ifp ( NodeType* parTree, const K& parKey );
static NodeType* find_parent_ifp ( NodeType* parTree, const NodeType* parSearchNodeAddr );
static NodeType* get_new_node ( const K& parKey );
static void delete_nodes ( NodeType* parNode );
[[gnu::pure]] bool is_alpha_height_balanced ( size_type parHeight, size_type parSize ) const;
NodeTypePair find_scapegoat ( NodeStack& parParents ) const;
static NodeType* rebalance ( NodeType* parSubtree, size_type parDepthHint );
static NodeType* compress_first ( NodeType* parFrom, size_type parDepthHint );
static NodeType* compress ( NodeType* parFrom );
[[gnu::pure]] static size_type get_max_balanced_depth ( size_type parSize, float parAlphaInvLogInv );
[[gnu::pure]] static size_type get_tree_min_depth_ib ( size_type parSize, float parAlphaInvLogInv );
static NodeType* detach_bottom_node ( NodeType* parTree, bool parSuccessor );
void rebalance_after_deletion_ifn ( void );
#if defined(SCAPEGOATTREE_PARANOID)
static size_type assert_node_size ( const NodeType* parSubtree );
static size_type find_max_depth ( const NodeType* parSubtree ) { return FindMaxDepth_rec(parSubtree) - 1; }
static size_type find_max_depth_rec ( const NodeType* parSubtree );
#endif
NodeType* m_root;
size_type m_count;
size_type m_countMax;
size_type m_reserved;
float m_alpha;
float m_alphainvloginv;
};
} //namespace duckmem
#include "implem/scapegoat_tree.inl"
#endif

View file

@ -0,0 +1,54 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id4FAEF395B9ED47CB9D6B50B54C9A289A
#define id4FAEF395B9ED47CB9D6B50B54C9A289A
#include <cstddef>
namespace dhandy {
namespace bt {
template <typename T, T... I>
struct number_seq {
};
template <std::size_t... I>
using index_seq = number_seq<std::size_t, I...>;
namespace implem {
template <typename T, T MIN, T MAX, T... I>
struct range_builder;
template <typename T, T MIN, T... I>
struct range_builder<T, MIN, MIN, I...> {
typedef number_seq<T, I...> type;
};
template <typename T, T MIN, T N, T... I>
struct range_builder : public range_builder<T, MIN, N - 1, N - 1, I...> {
};
} //namespace implem
template <typename T, T MIN, T MAX>
using number_range = typename implem::range_builder<T, MIN, MAX>::type;
template <std::size_t MIN, std::size_t MAX>
using index_range = number_range<std::size_t, MIN, MAX>;
} //namespace bt
} //namespace dhandy
#endif

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -18,7 +18,7 @@
#ifndef id170B0E6C34D14EBA9B92A35977BDBFB3
#define id170B0E6C34D14EBA9B92A35977BDBFB3
#include <utility>
#include "sequence_bt.hpp"
#include <cstddef>
#include <iostream>
#include <stdexcept>
@ -58,19 +58,14 @@ namespace dhandy {
private:
template <std::size_t... I>
constexpr string ( const std::index_sequence<I...>&, const value_type* parString );
constexpr string ( const index_seq<I...>&, const value_type* parString );
const value_type m_data[S];
};
template <std::size_t S, typename Ch>
constexpr auto string<S, Ch>::operator[] (std::size_t parIndex) const -> value_type {
return (parIndex < S ? m_data[parIndex] : throw std::out_of_range(""));
}
namespace implem {
template <std::size_t S, std::size_t S2, std::size_t... I>
constexpr string<S + S2 - 1> concat ( const std::index_sequence<I...>&, const string<S>& parLeft, const string<S2>& parRight ) {
constexpr string<S + S2 - 1> concat ( const index_seq<I...>&, const string<S>& parLeft, const string<S2>& parRight ) {
return string<S + S2 - 1>(
(I < S - 1 ? parLeft[I] : (I < S + S2 - 2 ? parRight[I - (S - 1)] : '\0'))...
);
@ -83,14 +78,14 @@ namespace dhandy {
template <std::size_t S, typename Ch>
template <std::size_t... I>
constexpr string<S, Ch>::string (const std::index_sequence<I...>&, const value_type* parString) :
constexpr string<S, Ch>::string (const index_seq<I...>&, const value_type* parString) :
m_data{parString[I]...}
{
}
template <std::size_t S, typename Ch>
inline constexpr string<S, Ch>::string (const value_type* parString) :
string(std::make_index_sequence<S>(), parString)
string(index_range<0, S>(), parString)
{
}
@ -104,7 +99,7 @@ namespace dhandy {
template <std::size_t S, typename Ch>
template <std::size_t S2>
constexpr inline string<S + S2 - 1, Ch> string<S, Ch>::operator+ (const string<S2, Ch>& parOther) const {
return implem::concat(std::make_index_sequence<S + S2 - 1>(), string<S>(m_data), parOther);
return implem::concat(index_range<0, S + S2 - 1>(), string<S>(m_data), parOther);
}
template <std::size_t S, typename Ch>
@ -113,6 +108,11 @@ namespace dhandy {
return parStream;
}
template <std::size_t S, typename Ch>
constexpr auto string<S, Ch>::operator[] (std::size_t parIndex) const -> value_type {
return (parIndex < S ? m_data[parIndex] : throw std::out_of_range(""));
}
template <std::size_t S, typename Ch>
constexpr string<S, Ch> make_string (const Ch (&parData)[S]) {
return string<S>(parData);

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify

View file

@ -1,61 +0,0 @@
/* Copyright 2016-2024, Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id1E6CCE44307549A9B6C9E4E5923AC002
#define id1E6CCE44307549A9B6C9E4E5923AC002
#include "lengthof.h"
#include <cstdint>
#include <ciso646>
#include <climits>
namespace dhandy::bt {
struct TigerHash {
consteval TigerHash ( uint64_t parA, uint64_t parB, uint64_t parC ) :
a(parA), b(parB), c(parC)
{
}
consteval TigerHash ( uint64_t parAP, uint64_t parA, uint64_t parBP, uint64_t parB, uint64_t parCP, uint64_t parC ) :
a(0 == parAP ? parA : (0 == parBP ? parB : (0 == parCP ? parC : throw 0))),
b(1 == parAP ? parA : (1 == parBP ? parB : (1 == parCP ? parC : throw 0))),
c(2 == parAP ? parA : (2 == parBP ? parB : (2 == parCP ? parC : throw 0)))
{
}
consteval TigerHash ( const TigerHash& ) = default;
consteval uint64_t operator[] ( uint64_t parIndex ) const {
return (parIndex == 0 ? a :
(parIndex == 1 ? b :
(parIndex == 2 ? c : throw 0)
)
);
}
uint64_t a;
uint64_t b;
uint64_t c;
};
inline const constexpr char TigerPaddingV1 = 0x01;
inline const constexpr char TigerPaddingV2 = 0x80;
[[gnu::const]]
consteval TigerHash tiger ( const char* parStr, uint64_t parLen, char parPad );
} //namespace dhandy::bt
#include "tiger_bt.inl"
#endif

View file

@ -1,488 +0,0 @@
/* Copyright 2016-2024, Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
namespace dhandy::bt {
namespace implem {
constexpr const uint64_t table[4*256] = {0x02AAB17CF7E90C5EULL, 0xAC424B03E243A8ECULL,
0x72CD5BE30DD5FCD3ULL, 0x6D019B93F6F97F3AULL, 0xCD9978FFD21F9193ULL, 0x7573A1C9708029E2ULL,
0xB164326B922A83C3ULL, 0x46883EEE04915870ULL, 0xEAACE3057103ECE6ULL, 0xC54169B808A3535CULL,
0x4CE754918DDEC47CULL, 0x0AA2F4DFDC0DF40CULL, 0x10B76F18A74DBEFAULL, 0xC6CCB6235AD1AB6AULL,
0x13726121572FE2FFULL, 0x1A488C6F199D921EULL, 0x4BC9F9F4DA0007CAULL, 0x26F5E6F6E85241C7ULL,
0x859079DBEA5947B6ULL, 0x4F1885C5C99E8C92ULL, 0xD78E761EA96F864BULL, 0x8E36428C52B5C17DULL,
0x69CF6827373063C1ULL, 0xB607C93D9BB4C56EULL, 0x7D820E760E76B5EAULL, 0x645C9CC6F07FDC42ULL,
0xBF38A078243342E0ULL, 0x5F6B343C9D2E7D04ULL, 0xF2C28AEB600B0EC6ULL, 0x6C0ED85F7254BCACULL,
0x71592281A4DB4FE5ULL, 0x1967FA69CE0FED9FULL, 0xFD5293F8B96545DBULL, 0xC879E9D7F2A7600BULL,
0x860248920193194EULL, 0xA4F9533B2D9CC0B3ULL, 0x9053836C15957613ULL, 0xDB6DCF8AFC357BF1ULL,
0x18BEEA7A7A370F57ULL, 0x037117CA50B99066ULL, 0x6AB30A9774424A35ULL, 0xF4E92F02E325249BULL,
0x7739DB07061CCAE1ULL, 0xD8F3B49CECA42A05ULL, 0xBD56BE3F51382F73ULL, 0x45FAED5843B0BB28ULL,
0x1C813D5C11BF1F83ULL, 0x8AF0E4B6D75FA169ULL, 0x33EE18A487AD9999ULL, 0x3C26E8EAB1C94410ULL,
0xB510102BC0A822F9ULL, 0x141EEF310CE6123BULL, 0xFC65B90059DDB154ULL, 0xE0158640C5E0E607ULL,
0x884E079826C3A3CFULL, 0x930D0D9523C535FDULL, 0x35638D754E9A2B00ULL, 0x4085FCCF40469DD5ULL,
0xC4B17AD28BE23A4CULL, 0xCAB2F0FC6A3E6A2EULL, 0x2860971A6B943FCDULL, 0x3DDE6EE212E30446ULL,
0x6222F32AE01765AEULL, 0x5D550BB5478308FEULL, 0xA9EFA98DA0EDA22AULL, 0xC351A71686C40DA7ULL,
0x1105586D9C867C84ULL, 0xDCFFEE85FDA22853ULL, 0xCCFBD0262C5EEF76ULL, 0xBAF294CB8990D201ULL,
0xE69464F52AFAD975ULL, 0x94B013AFDF133E14ULL, 0x06A7D1A32823C958ULL, 0x6F95FE5130F61119ULL,
0xD92AB34E462C06C0ULL, 0xED7BDE33887C71D2ULL, 0x79746D6E6518393EULL, 0x5BA419385D713329ULL,
0x7C1BA6B948A97564ULL, 0x31987C197BFDAC67ULL, 0xDE6C23C44B053D02ULL, 0x581C49FED002D64DULL,
0xDD474D6338261571ULL, 0xAA4546C3E473D062ULL, 0x928FCE349455F860ULL, 0x48161BBACAAB94D9ULL,
0x63912430770E6F68ULL, 0x6EC8A5E602C6641CULL, 0x87282515337DDD2BULL, 0x2CDA6B42034B701BULL,
0xB03D37C181CB096DULL, 0xE108438266C71C6FULL, 0x2B3180C7EB51B255ULL, 0xDF92B82F96C08BBCULL,
0x5C68C8C0A632F3BAULL, 0x5504CC861C3D0556ULL, 0xABBFA4E55FB26B8FULL, 0x41848B0AB3BACEB4ULL,
0xB334A273AA445D32ULL, 0xBCA696F0A85AD881ULL, 0x24F6EC65B528D56CULL, 0x0CE1512E90F4524AULL,
0x4E9DD79D5506D35AULL, 0x258905FAC6CE9779ULL, 0x2019295B3E109B33ULL, 0xF8A9478B73A054CCULL,
0x2924F2F934417EB0ULL, 0x3993357D536D1BC4ULL, 0x38A81AC21DB6FF8BULL, 0x47C4FBF17D6016BFULL,
0x1E0FAADD7667E3F5ULL, 0x7ABCFF62938BEB96ULL, 0xA78DAD948FC179C9ULL, 0x8F1F98B72911E50DULL,
0x61E48EAE27121A91ULL, 0x4D62F7AD31859808ULL, 0xECEBA345EF5CEAEBULL, 0xF5CEB25EBC9684CEULL,
0xF633E20CB7F76221ULL, 0xA32CDF06AB8293E4ULL, 0x985A202CA5EE2CA4ULL, 0xCF0B8447CC8A8FB1ULL,
0x9F765244979859A3ULL, 0xA8D516B1A1240017ULL, 0x0BD7BA3EBB5DC726ULL, 0xE54BCA55B86ADB39ULL,
0x1D7A3AFD6C478063ULL, 0x519EC608E7669EDDULL, 0x0E5715A2D149AA23ULL, 0x177D4571848FF194ULL,
0xEEB55F3241014C22ULL, 0x0F5E5CA13A6E2EC2ULL, 0x8029927B75F5C361ULL, 0xAD139FABC3D6E436ULL,
0x0D5DF1A94CCF402FULL, 0x3E8BD948BEA5DFC8ULL, 0xA5A0D357BD3FF77EULL, 0xA2D12E251F74F645ULL,
0x66FD9E525E81A082ULL, 0x2E0C90CE7F687A49ULL, 0xC2E8BCBEBA973BC5ULL, 0x000001BCE509745FULL,
0x423777BBE6DAB3D6ULL, 0xD1661C7EAEF06EB5ULL, 0xA1781F354DAACFD8ULL, 0x2D11284A2B16AFFCULL,
0xF1FC4F67FA891D1FULL, 0x73ECC25DCB920ADAULL, 0xAE610C22C2A12651ULL, 0x96E0A810D356B78AULL,
0x5A9A381F2FE7870FULL, 0xD5AD62EDE94E5530ULL, 0xD225E5E8368D1427ULL, 0x65977B70C7AF4631ULL,
0x99F889B2DE39D74FULL, 0x233F30BF54E1D143ULL, 0x9A9675D3D9A63C97ULL, 0x5470554FF334F9A8ULL,
0x166ACB744A4F5688ULL, 0x70C74CAAB2E4AEADULL, 0xF0D091646F294D12ULL, 0x57B82A89684031D1ULL,
0xEFD95A5A61BE0B6BULL, 0x2FBD12E969F2F29AULL, 0x9BD37013FEFF9FE8ULL, 0x3F9B0404D6085A06ULL,
0x4940C1F3166CFE15ULL, 0x09542C4DCDF3DEFBULL, 0xB4C5218385CD5CE3ULL, 0xC935B7DC4462A641ULL,
0x3417F8A68ED3B63FULL, 0xB80959295B215B40ULL, 0xF99CDAEF3B8C8572ULL, 0x018C0614F8FCB95DULL,
0x1B14ACCD1A3ACDF3ULL, 0x84D471F200BB732DULL, 0xC1A3110E95E8DA16ULL, 0x430A7220BF1A82B8ULL,
0xB77E090D39DF210EULL, 0x5EF4BD9F3CD05E9DULL, 0x9D4FF6DA7E57A444ULL, 0xDA1D60E183D4A5F8ULL,
0xB287C38417998E47ULL, 0xFE3EDC121BB31886ULL, 0xC7FE3CCC980CCBEFULL, 0xE46FB590189BFD03ULL,
0x3732FD469A4C57DCULL, 0x7EF700A07CF1AD65ULL, 0x59C64468A31D8859ULL, 0x762FB0B4D45B61F6ULL,
0x155BAED099047718ULL, 0x68755E4C3D50BAA6ULL, 0xE9214E7F22D8B4DFULL, 0x2ADDBF532EAC95F4ULL,
0x32AE3909B4BD0109ULL, 0x834DF537B08E3450ULL, 0xFA209DA84220728DULL, 0x9E691D9B9EFE23F7ULL,
0x0446D288C4AE8D7FULL, 0x7B4CC524E169785BULL, 0x21D87F0135CA1385ULL, 0xCEBB400F137B8AA5ULL,
0x272E2B66580796BEULL, 0x3612264125C2B0DEULL, 0x057702BDAD1EFBB2ULL, 0xD4BABB8EACF84BE9ULL,
0x91583139641BC67BULL, 0x8BDC2DE08036E024ULL, 0x603C8156F49F68EDULL, 0xF7D236F7DBEF5111ULL,
0x9727C4598AD21E80ULL, 0xA08A0896670A5FD7ULL, 0xCB4A8F4309EBA9CBULL, 0x81AF564B0F7036A1ULL,
0xC0B99AA778199ABDULL, 0x959F1EC83FC8E952ULL, 0x8C505077794A81B9ULL, 0x3ACAAF8F056338F0ULL,
0x07B43F50627A6778ULL, 0x4A44AB49F5ECCC77ULL, 0x3BC3D6E4B679EE98ULL, 0x9CC0D4D1CF14108CULL,
0x4406C00B206BC8A0ULL, 0x82A18854C8D72D89ULL, 0x67E366B35C3C432CULL, 0xB923DD61102B37F2ULL,
0x56AB2779D884271DULL, 0xBE83E1B0FF1525AFULL, 0xFB7C65D4217E49A9ULL, 0x6BDBE0E76D48E7D4ULL,
0x08DF828745D9179EULL, 0x22EA6A9ADD53BD34ULL, 0xE36E141C5622200AULL, 0x7F805D1B8CB750EEULL,
0xAFE5C7A59F58E837ULL, 0xE27F996A4FB1C23CULL, 0xD3867DFB0775F0D0ULL, 0xD0E673DE6E88891AULL,
0x123AEB9EAFB86C25ULL, 0x30F1D5D5C145B895ULL, 0xBB434A2DEE7269E7ULL, 0x78CB67ECF931FA38ULL,
0xF33B0372323BBF9CULL, 0x52D66336FB279C74ULL, 0x505F33AC0AFB4EAAULL, 0xE8A5CD99A2CCE187ULL,
0x534974801E2D30BBULL, 0x8D2D5711D5876D90ULL, 0x1F1A412891BC038EULL, 0xD6E2E71D82E56648ULL,
0x74036C3A497732B7ULL, 0x89B67ED96361F5ABULL, 0xFFED95D8F1EA02A2ULL, 0xE72B3BD61464D43DULL,
0xA6300F170BDC4820ULL, 0xEBC18760ED78A77AULL, 0xE6A6BE5A05A12138ULL, 0xB5A122A5B4F87C98ULL,
0x563C6089140B6990ULL, 0x4C46CB2E391F5DD5ULL, 0xD932ADDBC9B79434ULL, 0x08EA70E42015AFF5ULL,
0xD765A6673E478CF1ULL, 0xC4FB757EAB278D99ULL, 0xDF11C6862D6E0692ULL, 0xDDEB84F10D7F3B16ULL,
0x6F2EF604A665EA04ULL, 0x4A8E0F0FF0E0DFB3ULL, 0xA5EDEEF83DBCBA51ULL, 0xFC4F0A2A0EA4371EULL,
0xE83E1DA85CB38429ULL, 0xDC8FF882BA1B1CE2ULL, 0xCD45505E8353E80DULL, 0x18D19A00D4DB0717ULL,
0x34A0CFEDA5F38101ULL, 0x0BE77E518887CAF2ULL, 0x1E341438B3C45136ULL, 0xE05797F49089CCF9ULL,
0xFFD23F9DF2591D14ULL, 0x543DDA228595C5CDULL, 0x661F81FD99052A33ULL, 0x8736E641DB0F7B76ULL,
0x15227725418E5307ULL, 0xE25F7F46162EB2FAULL, 0x48A8B2126C13D9FEULL, 0xAFDC541792E76EEAULL,
0x03D912BFC6D1898FULL, 0x31B1AAFA1B83F51BULL, 0xF1AC2796E42AB7D9ULL, 0x40A3A7D7FCD2EBACULL,
0x1056136D0AFBBCC5ULL, 0x7889E1DD9A6D0C85ULL, 0xD33525782A7974AAULL, 0xA7E25D09078AC09BULL,
0xBD4138B3EAC6EDD0ULL, 0x920ABFBE71EB9E70ULL, 0xA2A5D0F54FC2625CULL, 0xC054E36B0B1290A3ULL,
0xF6DD59FF62FE932BULL, 0x3537354511A8AC7DULL, 0xCA845E9172FADCD4ULL, 0x84F82B60329D20DCULL,
0x79C62CE1CD672F18ULL, 0x8B09A2ADD124642CULL, 0xD0C1E96A19D9E726ULL, 0x5A786A9B4BA9500CULL,
0x0E020336634C43F3ULL, 0xC17B474AEB66D822ULL, 0x6A731AE3EC9BAAC2ULL, 0x8226667AE0840258ULL,
0x67D4567691CAECA5ULL, 0x1D94155C4875ADB5ULL, 0x6D00FD985B813FDFULL, 0x51286EFCB774CD06ULL,
0x5E8834471FA744AFULL, 0xF72CA0AEE761AE2EULL, 0xBE40E4CDAEE8E09AULL, 0xE9970BBB5118F665ULL,
0x726E4BEB33DF1964ULL, 0x703B000729199762ULL, 0x4631D816F5EF30A7ULL, 0xB880B5B51504A6BEULL,
0x641793C37ED84B6CULL, 0x7B21ED77F6E97D96ULL, 0x776306312EF96B73ULL, 0xAE528948E86FF3F4ULL,
0x53DBD7F286A3F8F8ULL, 0x16CADCE74CFC1063ULL, 0x005C19BDFA52C6DDULL, 0x68868F5D64D46AD3ULL,
0x3A9D512CCF1E186AULL, 0x367E62C2385660AEULL, 0xE359E7EA77DCB1D7ULL, 0x526C0773749ABE6EULL,
0x735AE5F9D09F734BULL, 0x493FC7CC8A558BA8ULL, 0xB0B9C1533041AB45ULL, 0x321958BA470A59BDULL,
0x852DB00B5F46C393ULL, 0x91209B2BD336B0E5ULL, 0x6E604F7D659EF19FULL, 0xB99A8AE2782CCB24ULL,
0xCCF52AB6C814C4C7ULL, 0x4727D9AFBE11727BULL, 0x7E950D0C0121B34DULL, 0x756F435670AD471FULL,
0xF5ADD442615A6849ULL, 0x4E87E09980B9957AULL, 0x2ACFA1DF50AEE355ULL, 0xD898263AFD2FD556ULL,
0xC8F4924DD80C8FD6ULL, 0xCF99CA3D754A173AULL, 0xFE477BACAF91BF3CULL, 0xED5371F6D690C12DULL,
0x831A5C285E687094ULL, 0xC5D3C90A3708A0A4ULL, 0x0F7F903717D06580ULL, 0x19F9BB13B8FDF27FULL,
0xB1BD6F1B4D502843ULL, 0x1C761BA38FFF4012ULL, 0x0D1530C4E2E21F3BULL, 0x8943CE69A7372C8AULL,
0xE5184E11FEB5CE66ULL, 0x618BDB80BD736621ULL, 0x7D29BAD68B574D0BULL, 0x81BB613E25E6FE5BULL,
0x071C9C10BC07913FULL, 0xC7BEEB7909AC2D97ULL, 0xC3E58D353BC5D757ULL, 0xEB017892F38F61E8ULL,
0xD4EFFB9C9B1CC21AULL, 0x99727D26F494F7ABULL, 0xA3E063A2956B3E03ULL, 0x9D4A8B9A4AA09C30ULL,
0x3F6AB7D500090FB4ULL, 0x9CC0F2A057268AC0ULL, 0x3DEE9D2DEDBF42D1ULL, 0x330F49C87960A972ULL,
0xC6B2720287421B41ULL, 0x0AC59EC07C00369CULL, 0xEF4EAC49CB353425ULL, 0xF450244EEF0129D8ULL,
0x8ACC46E5CAF4DEB6ULL, 0x2FFEAB63989263F7ULL, 0x8F7CB9FE5D7A4578ULL, 0x5BD8F7644E634635ULL,
0x427A7315BF2DC900ULL, 0x17D0C4AA2125261CULL, 0x3992486C93518E50ULL, 0xB4CBFEE0A2D7D4C3ULL,
0x7C75D6202C5DDD8DULL, 0xDBC295D8E35B6C61ULL, 0x60B369D302032B19ULL, 0xCE42685FDCE44132ULL,
0x06F3DDB9DDF65610ULL, 0x8EA4D21DB5E148F0ULL, 0x20B0FCE62FCD496FULL, 0x2C1B912358B0EE31ULL,
0xB28317B818F5A308ULL, 0xA89C1E189CA6D2CFULL, 0x0C6B18576AAADBC8ULL, 0xB65DEAA91299FAE3ULL,
0xFB2B794B7F1027E7ULL, 0x04E4317F443B5BEBULL, 0x4B852D325939D0A6ULL, 0xD5AE6BEEFB207FFCULL,
0x309682B281C7D374ULL, 0xBAE309A194C3B475ULL, 0x8CC3F97B13B49F05ULL, 0x98A9422FF8293967ULL,
0x244B16B01076FF7CULL, 0xF8BF571C663D67EEULL, 0x1F0D6758EEE30DA1ULL, 0xC9B611D97ADEB9B7ULL,
0xB7AFD5887B6C57A2ULL, 0x6290AE846B984FE1ULL, 0x94DF4CDEACC1A5FDULL, 0x058A5BD1C5483AFFULL,
0x63166CC142BA3C37ULL, 0x8DB8526EB2F76F40ULL, 0xE10880036F0D6D4EULL, 0x9E0523C9971D311DULL,
0x45EC2824CC7CD691ULL, 0x575B8359E62382C9ULL, 0xFA9E400DC4889995ULL, 0xD1823ECB45721568ULL,
0xDAFD983B8206082FULL, 0xAA7D29082386A8CBULL, 0x269FCD4403B87588ULL, 0x1B91F5F728BDD1E0ULL,
0xE4669F39040201F6ULL, 0x7A1D7C218CF04ADEULL, 0x65623C29D79CE5CEULL, 0x2368449096C00BB1ULL,
0xAB9BF1879DA503BAULL, 0xBC23ECB1A458058EULL, 0x9A58DF01BB401ECCULL, 0xA070E868A85F143DULL,
0x4FF188307DF2239EULL, 0x14D565B41A641183ULL, 0xEE13337452701602ULL, 0x950E3DCF3F285E09ULL,
0x59930254B9C80953ULL, 0x3BF299408930DA6DULL, 0xA955943F53691387ULL, 0xA15EDECAA9CB8784ULL,
0x29142127352BE9A0ULL, 0x76F0371FFF4E7AFBULL, 0x0239F450274F2228ULL, 0xBB073AF01D5E868BULL,
0xBFC80571C10E96C1ULL, 0xD267088568222E23ULL, 0x9671A3D48E80B5B0ULL, 0x55B5D38AE193BB81ULL,
0x693AE2D0A18B04B8ULL, 0x5C48B4ECADD5335FULL, 0xFD743B194916A1CAULL, 0x2577018134BE98C4ULL,
0xE77987E83C54A4ADULL, 0x28E11014DA33E1B9ULL, 0x270CC59E226AA213ULL, 0x71495F756D1A5F60ULL,
0x9BE853FB60AFEF77ULL, 0xADC786A7F7443DBFULL, 0x0904456173B29A82ULL, 0x58BC7A66C232BD5EULL,
0xF306558C673AC8B2ULL, 0x41F639C6B6C9772AULL, 0x216DEFE99FDA35DAULL, 0x11640CC71C7BE615ULL,
0x93C43694565C5527ULL, 0xEA038E6246777839ULL, 0xF9ABF3CE5A3E2469ULL, 0x741E768D0FD312D2ULL,
0x0144B883CED652C6ULL, 0xC20B5A5BA33F8552ULL, 0x1AE69633C3435A9DULL, 0x97A28CA4088CFDECULL,
0x8824A43C1E96F420ULL, 0x37612FA66EEEA746ULL, 0x6B4CB165F9CF0E5AULL, 0x43AA1C06A0ABFB4AULL,
0x7F4DC26FF162796BULL, 0x6CBACC8E54ED9B0FULL, 0xA6B7FFEFD2BB253EULL, 0x2E25BC95B0A29D4FULL,
0x86D6A58BDEF1388CULL, 0xDED74AC576B6F054ULL, 0x8030BDBC2B45805DULL, 0x3C81AF70E94D9289ULL,
0x3EFF6DDA9E3100DBULL, 0xB38DC39FDFCC8847ULL, 0x123885528D17B87EULL, 0xF2DA0ED240B1B642ULL,
0x44CEFADCD54BF9A9ULL, 0x1312200E433C7EE6ULL, 0x9FFCC84F3A78C748ULL, 0xF0CD1F72248576BBULL,
0xEC6974053638CFE4ULL, 0x2BA7B67C0CEC4E4CULL, 0xAC2F4DF3E5CE32EDULL, 0xCB33D14326EA4C11ULL,
0xA4E9044CC77E58BCULL, 0x5F513293D934FCEFULL, 0x5DC9645506E55444ULL, 0x50DE418F317DE40AULL,
0x388CB31A69DDE259ULL, 0x2DB4A83455820A86ULL, 0x9010A91E84711AE9ULL, 0x4DF7F0B7B1498371ULL,
0xD62A2EABC0977179ULL, 0x22FAC097AA8D5C0EULL, 0xF49FCC2FF1DAF39BULL, 0x487FD5C66FF29281ULL,
0xE8A30667FCDCA83FULL, 0x2C9B4BE3D2FCCE63ULL, 0xDA3FF74B93FBBBC2ULL, 0x2FA165D2FE70BA66ULL,
0xA103E279970E93D4ULL, 0xBECDEC77B0E45E71ULL, 0xCFB41E723985E497ULL, 0xB70AAA025EF75017ULL,
0xD42309F03840B8E0ULL, 0x8EFC1AD035898579ULL, 0x96C6920BE2B2ABC5ULL, 0x66AF4163375A9172ULL,
0x2174ABDCCA7127FBULL, 0xB33CCEA64A72FF41ULL, 0xF04A4933083066A5ULL, 0x8D970ACDD7289AF5ULL,
0x8F96E8E031C8C25EULL, 0xF3FEC02276875D47ULL, 0xEC7BF310056190DDULL, 0xF5ADB0AEBB0F1491ULL,
0x9B50F8850FD58892ULL, 0x4975488358B74DE8ULL, 0xA3354FF691531C61ULL, 0x0702BBE481D2C6EEULL,
0x89FB24057DEDED98ULL, 0xAC3075138596E902ULL, 0x1D2D3580172772EDULL, 0xEB738FC28E6BC30DULL,
0x5854EF8F63044326ULL, 0x9E5C52325ADD3BBEULL, 0x90AA53CF325C4623ULL, 0xC1D24D51349DD067ULL,
0x2051CFEEA69EA624ULL, 0x13220F0A862E7E4FULL, 0xCE39399404E04864ULL, 0xD9C42CA47086FCB7ULL,
0x685AD2238A03E7CCULL, 0x066484B2AB2FF1DBULL, 0xFE9D5D70EFBF79ECULL, 0x5B13B9DD9C481854ULL,
0x15F0D475ED1509ADULL, 0x0BEBCD060EC79851ULL, 0xD58C6791183AB7F8ULL, 0xD1187C5052F3EEE4ULL,
0xC95D1192E54E82FFULL, 0x86EEA14CB9AC6CA2ULL, 0x3485BEB153677D5DULL, 0xDD191D781F8C492AULL,
0xF60866BAA784EBF9ULL, 0x518F643BA2D08C74ULL, 0x8852E956E1087C22ULL, 0xA768CB8DC410AE8DULL,
0x38047726BFEC8E1AULL, 0xA67738B4CD3B45AAULL, 0xAD16691CEC0DDE19ULL, 0xC6D4319380462E07ULL,
0xC5A5876D0BA61938ULL, 0x16B9FA1FA58FD840ULL, 0x188AB1173CA74F18ULL, 0xABDA2F98C99C021FULL,
0x3E0580AB134AE816ULL, 0x5F3B05B773645ABBULL, 0x2501A2BE5575F2F6ULL, 0x1B2F74004E7E8BA9ULL,
0x1CD7580371E8D953ULL, 0x7F6ED89562764E30ULL, 0xB15926FF596F003DULL, 0x9F65293DA8C5D6B9ULL,
0x6ECEF04DD690F84CULL, 0x4782275FFF33AF88ULL, 0xE41433083F820801ULL, 0xFD0DFE409A1AF9B5ULL,
0x4325A3342CDB396BULL, 0x8AE77E62B301B252ULL, 0xC36F9E9F6655615AULL, 0x85455A2D92D32C09ULL,
0xF2C7DEA949477485ULL, 0x63CFB4C133A39EBAULL, 0x83B040CC6EBC5462ULL, 0x3B9454C8FDB326B0ULL,
0x56F56A9E87FFD78CULL, 0x2DC2940D99F42BC6ULL, 0x98F7DF096B096E2DULL, 0x19A6E01E3AD852BFULL,
0x42A99CCBDBD4B40BULL, 0xA59998AF45E9C559ULL, 0x366295E807D93186ULL, 0x6B48181BFAA1F773ULL,
0x1FEC57E2157A0A1DULL, 0x4667446AF6201AD5ULL, 0xE615EBCACFB0F075ULL, 0xB8F31F4F68290778ULL,
0x22713ED6CE22D11EULL, 0x3057C1A72EC3C93BULL, 0xCB46ACC37C3F1F2FULL, 0xDBB893FD02AAF50EULL,
0x331FD92E600B9FCFULL, 0xA498F96148EA3AD6ULL, 0xA8D8426E8B6A83EAULL, 0xA089B274B7735CDCULL,
0x87F6B3731E524A11ULL, 0x118808E5CBC96749ULL, 0x9906E4C7B19BD394ULL, 0xAFED7F7E9B24A20CULL,
0x6509EADEEB3644A7ULL, 0x6C1EF1D3E8EF0EDEULL, 0xB9C97D43E9798FB4ULL, 0xA2F2D784740C28A3ULL,
0x7B8496476197566FULL, 0x7A5BE3E6B65F069DULL, 0xF96330ED78BE6F10ULL, 0xEEE60DE77A076A15ULL,
0x2B4BEE4AA08B9BD0ULL, 0x6A56A63EC7B8894EULL, 0x02121359BA34FEF4ULL, 0x4CBF99F8283703FCULL,
0x398071350CAF30C8ULL, 0xD0A77A89F017687AULL, 0xF1C1A9EB9E423569ULL, 0x8C7976282DEE8199ULL,
0x5D1737A5DD1F7ABDULL, 0x4F53433C09A9FA80ULL, 0xFA8B0C53DF7CA1D9ULL, 0x3FD9DCBC886CCB77ULL,
0xC040917CA91B4720ULL, 0x7DD00142F9D1DCDFULL, 0x8476FC1D4F387B58ULL, 0x23F8E7C5F3316503ULL,
0x032A2244E7E37339ULL, 0x5C87A5D750F5A74BULL, 0x082B4CC43698992EULL, 0xDF917BECB858F63CULL,
0x3270B8FC5BF86DDAULL, 0x10AE72BB29B5DD76ULL, 0x576AC94E7700362BULL, 0x1AD112DAC61EFB8FULL,
0x691BC30EC5FAA427ULL, 0xFF246311CC327143ULL, 0x3142368E30E53206ULL, 0x71380E31E02CA396ULL,
0x958D5C960AAD76F1ULL, 0xF8D6F430C16DA536ULL, 0xC8FFD13F1BE7E1D2ULL, 0x7578AE66004DDBE1ULL,
0x05833F01067BE646ULL, 0xBB34B5AD3BFE586DULL, 0x095F34C9A12B97F0ULL, 0x247AB64525D60CA8ULL,
0xDCDBC6F3017477D1ULL, 0x4A2E14D4DECAD24DULL, 0xBDB5E6D9BE0A1EEBULL, 0x2A7E70F7794301ABULL,
0xDEF42D8A270540FDULL, 0x01078EC0A34C22C1ULL, 0xE5DE511AF4C16387ULL, 0x7EBB3A52BD9A330AULL,
0x77697857AA7D6435ULL, 0x004E831603AE4C32ULL, 0xE7A21020AD78E312ULL, 0x9D41A70C6AB420F2ULL,
0x28E06C18EA1141E6ULL, 0xD2B28CBD984F6B28ULL, 0x26B75F6C446E9D83ULL, 0xBA47568C4D418D7FULL,
0xD80BADBFE6183D8EULL, 0x0E206D7F5F166044ULL, 0xE258A43911CBCA3EULL, 0x723A1746B21DC0BCULL,
0xC7CAA854F5D7CDD3ULL, 0x7CAC32883D261D9CULL, 0x7690C26423BA942CULL, 0x17E55524478042B8ULL,
0xE0BE477656A2389FULL, 0x4D289B5E67AB2DA0ULL, 0x44862B9C8FBBFD31ULL, 0xB47CC8049D141365ULL,
0x822C1B362B91C793ULL, 0x4EB14655FB13DFD8ULL, 0x1ECBBA0714E2A97BULL, 0x6143459D5CDE5F14ULL,
0x53A8FBF1D5F0AC89ULL, 0x97EA04D81C5E5B00ULL, 0x622181A8D4FDB3F3ULL, 0xE9BCD341572A1208ULL,
0x1411258643CCE58AULL, 0x9144C5FEA4C6E0A4ULL, 0x0D33D06565CF620FULL, 0x54A48D489F219CA1ULL,
0xC43E5EAC6D63C821ULL, 0xA9728B3A72770DAFULL, 0xD7934E7B20DF87EFULL, 0xE35503B61A3E86E5ULL,
0xCAE321FBC819D504ULL, 0x129A50B3AC60BFA6ULL, 0xCD5E68EA7E9FB6C3ULL, 0xB01C90199483B1C7ULL,
0x3DE93CD5C295376CULL, 0xAED52EDF2AB9AD13ULL, 0x2E60F512C0A07884ULL, 0xBC3D86A3E36210C9ULL,
0x35269D9B163951CEULL, 0x0C7D6E2AD0CDB5FAULL, 0x59E86297D87F5733ULL, 0x298EF221898DB0E7ULL,
0x55000029D1A5AA7EULL, 0x8BC08AE1B5061B45ULL, 0xC2C31C2B6C92703AULL, 0x94CC596BAF25EF42ULL,
0x0A1D73DB22540456ULL, 0x04B6A0F9D9C4179AULL, 0xEFFDAFA2AE3D3C60ULL, 0xF7C8075BB49496C4ULL,
0x9CC5C7141D1CD4E3ULL, 0x78BD1638218E5534ULL, 0xB2F11568F850246AULL, 0xEDFABCFA9502BC29ULL,
0x796CE5F2DA23051BULL, 0xAAE128B0DC93537CULL, 0x3A493DA0EE4B29AEULL, 0xB5DF6B2C416895D7ULL,
0xFCABBD25122D7F37ULL, 0x70810B58105DC4B1ULL, 0xE10FDD37F7882A90ULL, 0x524DCAB5518A3F5CULL,
0x3C9E85878451255BULL, 0x4029828119BD34E2ULL, 0x74A05B6F5D3CECCBULL, 0xB610021542E13ECAULL,
0x0FF979D12F59E2ACULL, 0x6037DA27E4F9CC50ULL, 0x5E92975A0DF1847DULL, 0xD66DE190D3E623FEULL,
0x5032D6B87B568048ULL, 0x9A36B7CE8235216EULL, 0x80272A7A24F64B4AULL, 0x93EFED8B8C6916F7ULL,
0x37DDBFF44CCE1555ULL, 0x4B95DB5D4B99BD25ULL, 0x92D3FDA169812FC0ULL, 0xFB1A4A9A90660BB6ULL,
0x730C196946A4B9B2ULL, 0x81E289AA7F49DA68ULL, 0x64669A0F83B1A05FULL, 0x27B3FF7D9644F48BULL,
0xCC6B615C8DB675B3ULL, 0x674F20B9BCEBBE95ULL, 0x6F31238275655982ULL, 0x5AE488713E45CF05ULL,
0xBF619F9954C21157ULL, 0xEABAC46040A8EAE9ULL, 0x454C6FE9F2C0C1CDULL, 0x419CF6496412691CULL,
0xD3DC3BEF265B0F70ULL, 0x6D0E60F5C3578A9EULL, 0x5B0E608526323C55ULL, 0x1A46C1A9FA1B59F5ULL,
0xA9E245A17C4C8FFAULL, 0x65CA5159DB2955D7ULL, 0x05DB0A76CE35AFC2ULL, 0x81EAC77EA9113D45ULL,
0x528EF88AB6AC0A0DULL, 0xA09EA253597BE3FFULL, 0x430DDFB3AC48CD56ULL, 0xC4B3A67AF45CE46FULL,
0x4ECECFD8FBE2D05EULL, 0x3EF56F10B39935F0ULL, 0x0B22D6829CD619C6ULL, 0x17FD460A74DF2069ULL,
0x6CF8CC8E8510ED40ULL, 0xD6C824BF3A6ECAA7ULL, 0x61243D581A817049ULL, 0x048BACB6BBC163A2ULL,
0xD9A38AC27D44CC32ULL, 0x7FDDFF5BAAF410ABULL, 0xAD6D495AA804824BULL, 0xE1A6A74F2D8C9F94ULL,
0xD4F7851235DEE8E3ULL, 0xFD4B7F886540D893ULL, 0x247C20042AA4BFDAULL, 0x096EA1C517D1327CULL,
0xD56966B4361A6685ULL, 0x277DA5C31221057DULL, 0x94D59893A43ACFF7ULL, 0x64F0C51CCDC02281ULL,
0x3D33BCC4FF6189DBULL, 0xE005CB184CE66AF1ULL, 0xFF5CCD1D1DB99BEAULL, 0xB0B854A7FE42980FULL,
0x7BD46A6A718D4B9FULL, 0xD10FA8CC22A5FD8CULL, 0xD31484952BE4BD31ULL, 0xC7FA975FCB243847ULL,
0x4886ED1E5846C407ULL, 0x28CDDB791EB70B04ULL, 0xC2B00BE2F573417FULL, 0x5C9590452180F877ULL,
0x7A6BDDFFF370EB00ULL, 0xCE509E38D6D9D6A4ULL, 0xEBEB0F00647FA702ULL, 0x1DCC06CF76606F06ULL,
0xE4D9F28BA286FF0AULL, 0xD85A305DC918C262ULL, 0x475B1D8732225F54ULL, 0x2D4FB51668CCB5FEULL,
0xA679B9D9D72BBA20ULL, 0x53841C0D912D43A5ULL, 0x3B7EAA48BF12A4E8ULL, 0x781E0E47F22F1DDFULL,
0xEFF20CE60AB50973ULL, 0x20D261D19DFFB742ULL, 0x16A12B03062A2E39ULL, 0x1960EB2239650495ULL,
0x251C16FED50EB8B8ULL, 0x9AC0C330F826016EULL, 0xED152665953E7671ULL, 0x02D63194A6369570ULL,
0x5074F08394B1C987ULL, 0x70BA598C90B25CE1ULL, 0x794A15810B9742F6ULL, 0x0D5925E9FCAF8C6CULL,
0x3067716CD868744EULL, 0x910AB077E8D7731BULL, 0x6A61BBDB5AC42F61ULL, 0x93513EFBF0851567ULL,
0xF494724B9E83E9D5ULL, 0xE887E1985C09648DULL, 0x34B1D3C675370CFDULL, 0xDC35E433BC0D255DULL,
0xD0AAB84234131BE0ULL, 0x08042A50B48B7EAFULL, 0x9997C4EE44A3AB35ULL, 0x829A7B49201799D0ULL,
0x263B8307B7C54441ULL, 0x752F95F4FD6A6CA6ULL, 0x927217402C08C6E5ULL, 0x2A8AB754A795D9EEULL,
0xA442F7552F72943DULL, 0x2C31334E19781208ULL, 0x4FA98D7CEAEE6291ULL, 0x55C3862F665DB309ULL,
0xBD0610175D53B1F3ULL, 0x46FE6CB840413F27ULL, 0x3FE03792DF0CFA59ULL, 0xCFE700372EB85E8FULL,
0xA7BE29E7ADBCE118ULL, 0xE544EE5CDE8431DDULL, 0x8A781B1B41F1873EULL, 0xA5C94C78A0D2F0E7ULL,
0x39412E2877B60728ULL, 0xA1265EF3AFC9A62CULL, 0xBCC2770C6A2506C5ULL, 0x3AB66DD5DCE1CE12ULL,
0xE65499D04A675B37ULL, 0x7D8F523481BFD216ULL, 0x0F6F64FCEC15F389ULL, 0x74EFBE618B5B13C8ULL,
0xACDC82B714273E1DULL, 0xDD40BFE003199D17ULL, 0x37E99257E7E061F8ULL, 0xFA52626904775AAAULL,
0x8BBBF63A463D56F9ULL, 0xF0013F1543A26E64ULL, 0xA8307E9F879EC898ULL, 0xCC4C27A4150177CCULL,
0x1B432F2CCA1D3348ULL, 0xDE1D1F8F9F6FA013ULL, 0x606602A047A7DDD6ULL, 0xD237AB64CC1CB2C7ULL,
0x9B938E7225FCD1D3ULL, 0xEC4E03708E0FF476ULL, 0xFEB2FBDA3D03C12DULL, 0xAE0BCED2EE43889AULL,
0x22CB8923EBFB4F43ULL, 0x69360D013CF7396DULL, 0x855E3602D2D4E022ULL, 0x073805BAD01F784CULL,
0x33E17A133852F546ULL, 0xDF4874058AC7B638ULL, 0xBA92B29C678AA14AULL, 0x0CE89FC76CFAADCDULL,
0x5F9D4E0908339E34ULL, 0xF1AFE9291F5923B9ULL, 0x6E3480F60F4A265FULL, 0xEEBF3A2AB29B841CULL,
0xE21938A88F91B4ADULL, 0x57DFEFF845C6D3C3ULL, 0x2F006B0BF62CAAF2ULL, 0x62F479EF6F75EE78ULL,
0x11A55AD41C8916A9ULL, 0xF229D29084FED453ULL, 0x42F1C27B16B000E6ULL, 0x2B1F76749823C074ULL,
0x4B76ECA3C2745360ULL, 0x8C98F463B91691BDULL, 0x14BCC93CF1ADE66AULL, 0x8885213E6D458397ULL,
0x8E177DF0274D4711ULL, 0xB49B73B5503F2951ULL, 0x10168168C3F96B6BULL, 0x0E3D963B63CAB0AEULL,
0x8DFC4B5655A1DB14ULL, 0xF789F1356E14DE5CULL, 0x683E68AF4E51DAC1ULL, 0xC9A84F9D8D4B0FD9ULL,
0x3691E03F52A0F9D1ULL, 0x5ED86E46E1878E80ULL, 0x3C711A0E99D07150ULL, 0x5A0865B20C4E9310ULL,
0x56FBFC1FE4F0682EULL, 0xEA8D5DE3105EDF9BULL, 0x71ABFDB12379187AULL, 0x2EB99DE1BEE77B9CULL,
0x21ECC0EA33CF4523ULL, 0x59A4D7521805C7A1ULL, 0x3896F5EB56AE7C72ULL, 0xAA638F3DB18F75DCULL,
0x9F39358DABE9808EULL, 0xB7DEFA91C00B72ACULL, 0x6B5541FD62492D92ULL, 0x6DC6DEE8F92E4D5BULL,
0x353F57ABC4BEEA7EULL, 0x735769D6DA5690CEULL, 0x0A234AA642391484ULL, 0xF6F9508028F80D9DULL,
0xB8E319A27AB3F215ULL, 0x31AD9C1151341A4DULL, 0x773C22A57BEF5805ULL, 0x45C7561A07968633ULL,
0xF913DA9E249DBE36ULL, 0xDA652D9B78A64C68ULL, 0x4C27A97F3BC334EFULL, 0x76621220E66B17F4ULL,
0x967743899ACD7D0BULL, 0xF3EE5BCAE0ED6782ULL, 0x409F753600C879FCULL, 0x06D09A39B5926DB6ULL,
0x6F83AEB0317AC588ULL, 0x01E6CA4A86381F21ULL, 0x66FF3462D19F3025ULL, 0x72207C24DDFD3BFBULL,
0x4AF6B6D3E2ECE2EBULL, 0x9C994DBEC7EA08DEULL, 0x49ACE597B09A8BC4ULL, 0xB38C4766CF0797BAULL,
0x131B9373C57C2A75ULL, 0xB1822CCE61931E58ULL, 0x9D7555B909BA1C0CULL, 0x127FAFDD937D11D2ULL,
0x29DA3BADC66D92E4ULL, 0xA2C1D57154C2ECBCULL, 0x58C5134D82F6FE24ULL, 0x1C3AE3515B62274FULL,
0xE907C82E01CB8126ULL, 0xF8ED091913E37FCBULL, 0x3249D8F9C80046C9ULL, 0x80CF9BEDE388FB63ULL,
0x1881539A116CF19EULL, 0x5103F3F76BD52457ULL, 0x15B7E6F5AE47F7A8ULL, 0xDBD7C6DED47E9CCFULL,
0x44E55C410228BB1AULL, 0xB647D4255EDB4E99ULL, 0x5D11882BB8AAFC30ULL, 0xF5098BBB29D3212AULL,
0x8FB5EA14E90296B3ULL, 0x677B942157DD025AULL, 0xFB58E7C0A390ACB5ULL, 0x89D3674C83BD4A01ULL,
0x9E2DA4DF4BF3B93BULL, 0xFCC41E328CAB4829ULL, 0x03F38C96BA582C52ULL, 0xCAD1BDBD7FD85DB2ULL,
0xBBB442C16082AE83ULL, 0xB95FE86BA5DA9AB0ULL, 0xB22E04673771A93FULL, 0x845358C9493152D8ULL,
0xBE2A488697B4541EULL, 0x95A2DC2DD38E6966ULL, 0xC02C11AC923C852BULL, 0x2388B1990DF2A87BULL,
0x7C8008FA1B4F37BEULL, 0x1F70D0C84D54E503ULL, 0x5490ADEC7ECE57D4ULL, 0x002B3C27D9063A3AULL,
0x7EAEA3848030A2BFULL, 0xC602326DED2003C0ULL, 0x83A7287D69A94086ULL, 0xC57A5FCB30F57A8AULL,
0xB56844E479EBE779ULL, 0xA373B40F05DCBCE9ULL, 0xD71A786E88570EE2ULL, 0x879CBACDBDE8F6A0ULL,
0x976AD1BCC164A32FULL, 0xAB21E25E9666D78BULL, 0x901063AAE5E5C33CULL, 0x9818B34448698D90ULL,
0xE36487AE3E1E8ABBULL, 0xAFBDF931893BDCB4ULL, 0x6345A0DC5FBBD519ULL, 0x8628FE269B9465CAULL,
0x1E5D01603F9C51ECULL, 0x4DE44006A15049B7ULL, 0xBF6C70E5F776CBB1ULL, 0x411218F2EF552BEDULL,
0xCB0C0708705A36A3ULL, 0xE74D14754F986044ULL, 0xCD56D9430EA8280EULL, 0xC12591D7535F5065ULL,
0xC83223F1720AEF96ULL, 0xC3A0396F7363A51FULL };
consteval uint64_t buff_to_uint64_with_filling (const char* parStr, const uint64_t parAvailLen) {
return (
parAvailLen == 0 ?
0
:
//static_cast<uint64_t>(static_cast<uint8_t>(parStr[0])) <<
// (CHAR_BIT * (parAvailLen - 1)) bitor buff_to_uint64_with_filling(parStr + 1, parAvailLen - 1)
static_cast<uint64_t>(static_cast<uint8_t>(parStr[0])) bitor (buff_to_uint64_with_filling(parStr + 1, parAvailLen - 1) << CHAR_BIT)
);
}
consteval uint64_t buff_to_uint64_fill_ifn (const char* parStr, uint64_t parIndex, uint64_t parBuffLen, char parPad) {
return (sizeof(uint64_t) * parIndex >= parBuffLen ?
(sizeof(uint64_t) * parIndex == parBuffLen ?
static_cast<uint64_t>(static_cast<uint8_t>(parPad))
:
0
)
:
(sizeof(uint64_t) * parIndex + sizeof(uint64_t) <= parBuffLen ?
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * parIndex, sizeof(uint64_t))
:
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * parIndex, parBuffLen % sizeof(uint64_t)) bitor
static_cast<uint64_t>(static_cast<uint8_t>(parPad)) << ((parBuffLen % sizeof(uint64_t)) * CHAR_BIT)
)
);
}
struct TigerBlock {
consteval explicit TigerBlock ( const char* parStr ) :
data{
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 0, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 1, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 2, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 3, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 4, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 5, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 6, sizeof(uint64_t)),
buff_to_uint64_with_filling(parStr + sizeof(uint64_t) * 7, sizeof(uint64_t))
}
{
}
consteval TigerBlock ( const TigerBlock& ) = default;
consteval TigerBlock ( uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t g, uint64_t h) :
data{a, b, c, d, e, f, g, h}
{
}
consteval TigerBlock ( const char* parStr, uint64_t parLen, char parPad ) :
data{
buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 2, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 3, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 4, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 5, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 6, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 7, parLen, parPad)
}
{
}
consteval TigerBlock ( const char* parStr, uint64_t parLen, char parPad, uint64_t parData7 ) :
data{
buff_to_uint64_fill_ifn(parStr, 0, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 1, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 2, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 3, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 4, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 5, parLen, parPad),
buff_to_uint64_fill_ifn(parStr, 6, parLen, parPad),
(parLen + 1 <= sizeof(uint64_t) * 7 ? parData7 : throw 0)
}
{
}
consteval uint64_t operator[] (std::size_t parIndex) const { return (parIndex < lengthof(data) ? data[parIndex] : throw 0); }
const uint64_t data[8];
};
consteval uint64_t gb (uint64_t r, uint64_t a) {
return (r >> (a * CHAR_BIT)) bitand 0xff;
}
consteval TigerHash round (uint64_t mul, uint64_t a, uint64_t b, uint64_t c, uint64_t x, const TigerBlock& block, const TigerHash& hash) {
return TigerHash(
a,
hash[a] - (
table[ gb(hash[c] xor block[x], 0)] xor
table[256 + gb(hash[c] xor block[x], 2)] xor
table[512 + gb(hash[c] xor block[x], 4)] xor
table[768 + gb(hash[c] xor block[x], 6)]),
b,
(hash[b] + (
table[768 + gb(hash[c] xor block[x], 1)] xor
table[512 + gb(hash[c] xor block[x], 3)] xor
table[256 + gb(hash[c] xor block[x], 5)] xor
table[ gb(hash[c] xor block[x], 7)])) * mul,
c,
hash[c] xor block[x]
);
}
consteval TigerHash pass (uint64_t a, uint64_t b, uint64_t c, uint64_t mul, const TigerBlock& block, const TigerHash& hash, uint64_t x=0) {
return (
8 == x ?
//if 0 == x
hash
: //else
pass(
b,
c,
a,
mul,
block,
round(mul, a, b, c, x, block, hash),
x + 1
)
);
}
template <uint64_t I, uint64_t S> consteval uint64_t key_sched_op (const TigerBlock& i);
template<> consteval uint64_t key_sched_op<0,1> (const TigerBlock& i) { return i[0] - (i[7] ^ 0xA5A5A5A5A5A5A5A5ULL); }
template<> consteval uint64_t key_sched_op<1,1> (const TigerBlock& i) { return i[1] ^ key_sched_op<0,1>(i); }
template<> consteval uint64_t key_sched_op<2,1> (const TigerBlock& i) { return i[2] + key_sched_op<1,1>(i); }
template<> consteval uint64_t key_sched_op<3,1> (const TigerBlock& i) { return i[3] - (key_sched_op<2,1>(i) ^ ((~key_sched_op<1,1>(i)) << 19)); }
template<> consteval uint64_t key_sched_op<4,1> (const TigerBlock& i) { return i[4] ^ key_sched_op<3,1>(i); }
template<> consteval uint64_t key_sched_op<5,1> (const TigerBlock& i) { return i[5] + key_sched_op<4,1>(i); }
template<> consteval uint64_t key_sched_op<6,1> (const TigerBlock& i) { return i[6] - (key_sched_op<5,1>(i) ^ ((~key_sched_op<4,1>(i)) >> 23)); }
template<> consteval uint64_t key_sched_op<7,1> (const TigerBlock& i) { return i[7] ^ key_sched_op<6,1>(i); }
template<> consteval uint64_t key_sched_op<0,2> (const TigerBlock& i) { return key_sched_op<0,1>(i) + key_sched_op<7,1>(i); }
template<> consteval uint64_t key_sched_op<1,2> (const TigerBlock& i) { return key_sched_op<1,1>(i) - (key_sched_op<0,2>(i) ^ ((~key_sched_op<7,1>(i)) << 19)); }
template<> consteval uint64_t key_sched_op<2,2> (const TigerBlock& i) { return key_sched_op<2,1>(i) ^ key_sched_op<1,2>(i); }
template<> consteval uint64_t key_sched_op<3,2> (const TigerBlock& i) { return key_sched_op<3,1>(i) + key_sched_op<2,2>(i); }
template<> consteval uint64_t key_sched_op<4,2> (const TigerBlock& i) { return key_sched_op<4,1>(i) - (key_sched_op<3,2>(i) ^ ((~key_sched_op<2,2>(i)) >> 23)); }
template<> consteval uint64_t key_sched_op<5,2> (const TigerBlock& i) { return key_sched_op<5,1>(i) ^ key_sched_op<4,2>(i); }
template<> consteval uint64_t key_sched_op<6,2> (const TigerBlock& i) { return key_sched_op<6,1>(i) + key_sched_op<5,2>(i); }
template<> consteval uint64_t key_sched_op<7,2> (const TigerBlock& i) { return key_sched_op<7,1>(i) - (key_sched_op<6,2>(i) ^ 0x0123456789ABCDEFULL); }
consteval TigerBlock key_sched (const TigerBlock& parBlock) {
return TigerBlock(
key_sched_op<0,2>(parBlock),
key_sched_op<1,2>(parBlock),
key_sched_op<2,2>(parBlock),
key_sched_op<3,2>(parBlock),
key_sched_op<4,2>(parBlock),
key_sched_op<5,2>(parBlock),
key_sched_op<6,2>(parBlock),
key_sched_op<7,2>(parBlock)
);
}
consteval TigerHash finalize_tiger_step (TigerHash parOriginal, TigerHash parPartial) {
return TigerHash(
parPartial.a ^ parOriginal.a,
parPartial.b - parOriginal.b,
parPartial.c + parOriginal.c
);
}
consteval TigerHash tiger_block (const TigerBlock& parBlock, TigerHash parHash) {
return finalize_tiger_step(
parHash,
pass(1, 2, 0, 9, key_sched(key_sched(parBlock)),
pass(2, 0, 1, 7, key_sched(parBlock),
pass(0, 1, 2, 5, parBlock, parHash)
)
)
);
}
consteval TigerHash tiger_block (const char* parStr, TigerHash parHash) {
return tiger_block(TigerBlock(parStr), parHash);
}
consteval TigerHash tiger_chunk (const char* parStr, uint64_t parLen, TigerHash parHash) {
return (parLen == 0 ?
//if parLen == 0
parHash
:
//else
tiger_chunk(parStr + 64, parLen - 64, tiger_block(parStr, parHash))
);
}
consteval TigerHash tiger_last_chunk (const char* parStr, uint64_t parLen, uint64_t parRealLen, TigerHash parHash, char parPad) {
return (
parLen + 1 + ((8 - parLen - 1) bitand 7) == 64 ?
tiger_block(
TigerBlock(0, 0, 0, 0, 0, 0, 0, parRealLen << uint64_t(3)),
tiger_block(TigerBlock(parStr, parLen, parPad), parHash)
)
:
tiger_block(TigerBlock(parStr, parLen, parPad, parRealLen << uint64_t(3)), parHash)
);
}
} //namespace implem
consteval TigerHash tiger (const char* parStr, uint64_t parLen, char parPad) {
return implem::tiger_last_chunk(
parStr + (parLen bitand ~static_cast<uint64_t>(0x3f)),
parLen - (parLen bitand ~static_cast<uint64_t>(0x3f)),
parLen,
implem::tiger_chunk(
parStr,
parLen bitand ~static_cast<uint64_t>(0x3f),
TigerHash{0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL}
),
parPad
);
}
} //namespace dhandy::bt

View file

@ -0,0 +1,149 @@
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id6109D5EDE99D43C4909F084A231BF2C2
#define id6109D5EDE99D43C4909F084A231BF2C2
#include <vector>
#include <cstddef>
#include <type_traits>
#include <cassert>
#if !defined(AssertNotReached)
# define AssertNotReached() assert(false)
#endif
#if !defined(AssertRelease)
# define AssertRelease(a) assert(a)
#endif
#if !defined(Assert)
# define Assert(a) assert(a)
#endif
namespace duckmem {
namespace Implem {
template <typename P>
class TreeIterator_base {
template <typename P1> friend class TreeIterator_base;
public:
explicit TreeIterator_base ( void ) {}
TreeIterator_base ( const TreeIterator_base& parOther );
template <typename P1>
explicit TreeIterator_base ( const TreeIterator_base<P1>& parOther );
~TreeIterator_base ( void ) {}
protected:
typedef std::vector<P> StackType;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
bool Exhausted ( void ) const;
StackType m_stack;
};
template <typename T, typename N, bool Const>
class TreeIterator_const_layer;
template <typename T, typename N>
class TreeIterator_const_layer<T, N, true> : protected TreeIterator_base<const N*> {
template <typename T1, typename N1, bool Const1> friend class TreeIterator_const_layer;
typedef TreeIterator_base<const N*> parent_type;
public:
typedef const T* pointer;
typedef const T* const_pointer;
typedef const T& reference;
typedef const T& const_reference;
typedef typename parent_type::size_type size_type;
typedef typename parent_type::difference_type difference_type;
typedef N NodeType;
typedef const N* NodeTypePointer;
enum { IS_CONST = 1 };
TreeIterator_const_layer ( void ) {}
TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {}
TreeIterator_const_layer ( TreeIterator_const_layer&& ) = default;
template <typename T1, bool C1>
explicit TreeIterator_const_layer ( const TreeIterator_const_layer<T1, N, C1>& parOther ) : parent_type(parOther) {}
const_reference operator* ( void ) const;
const_pointer operator-> ( void ) const;
const N* GetPointer ( void ) const;
protected:
typedef typename parent_type::StackType StackType;
};
template <typename T, typename N>
class TreeIterator_const_layer<T, N, false> : protected TreeIterator_base<N*> {
template <typename T1, typename N1, bool Const1> friend class TreeIterator_const_layer;
typedef TreeIterator_base<N*> parent_type;
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef typename parent_type::size_type size_type;
typedef typename parent_type::difference_type difference_type;
typedef N NodeType;
typedef N* NodeTypePointer;
enum { IS_CONST = 0 };
TreeIterator_const_layer ( void ) {}
TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {}
template <typename T1, bool C1>
explicit TreeIterator_const_layer ( const TreeIterator_const_layer<T1, N, C1>& parOther ) : parent_type(parOther) {}
reference operator* ( void );
const_reference operator* ( void ) const;
pointer operator-> ( void );
const_pointer operator-> ( void ) const;
const N* GetPointer ( void ) const;
N* GetPointer ( void );
protected:
typedef typename parent_type::StackType StackType;
};
} //namespace Implem
template <typename T, typename N>
class TreeIterator : public Implem::TreeIterator_const_layer<T, N, std::is_const<T>::value> {
typedef Implem::TreeIterator_const_layer<T, N, std::is_const<T>::value> parent_type;
typedef typename parent_type::NodeTypePointer NodeTypePointer;
typedef typename parent_type::NodeType NodeType;
typedef typename parent_type::StackType StackType;
public:
typedef T value_type;
typedef std::forward_iterator_tag iterator_category;
typedef typename parent_type::difference_type difference_type;
typedef typename parent_type::size_type size_type;
typedef typename parent_type::pointer pointer;
typedef typename parent_type::const_pointer const_pointer;
typedef typename parent_type::reference reference;
typedef typename parent_type::const_reference const_reference;
TreeIterator ( void );
TreeIterator ( const TreeIterator& parOther );
TreeIterator ( NodeTypePointer parRoot, size_type parMaxDepthHint );
template <typename S>
TreeIterator ( S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint );
template <typename T1>
TreeIterator ( const TreeIterator<T1, N>& parOther );
~TreeIterator ( void );
const TreeIterator& operator= ( const TreeIterator& parOther );
bool operator== ( const TreeIterator& parOther ) const;
bool operator!= ( const TreeIterator& parOther ) const { return not (*this == parOther); }
TreeIterator& operator++ ( void ); //pre
TreeIterator operator++ ( int ); //post
private:
void RecurseLeft ( NodeTypePointer parFrom );
};
} //namespace duckmem
#include "implem/tree_iterator.inl"
#endif

View file

@ -1,41 +0,0 @@
/* Copyright 2016-2024 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstddef>
namespace dhandy::bt {
template <typename T, T... V>
struct variadic_repeat {
};
namespace detail {
template <std::size_t N, typename T, T V0, T... V>
struct VariadicRepeatBuilder;
template <typename T, T V0, T... V>
struct VariadicRepeatBuilder<0, T, V0, V...> {
typedef variadic_repeat<T, V...> type;
};
template <std::size_t N, typename T, T V0, T... V>
struct VariadicRepeatBuilder : public VariadicRepeatBuilder<N-1, T, V0, V..., V0> {
};
} //namespace detail
template <std::size_t Count, typename T, T Val=T{}>
using make_variadic_repeat = typename detail::VariadicRepeatBuilder<Count, T, Val>::type;
} //namespace dhandy::bt

View file

@ -1,101 +0,0 @@
/* Copyright 2016-2024 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef id5594416333AA4792BFEC94E863E03B08
#define id5594416333AA4792BFEC94E863E03B08
#include "int_conv.hpp"
#include <cstddef>
#include <stdexcept>
namespace dhandy::bt {
template <std::size_t N>
class Version {
public:
constexpr static const std::size_t count = N;
constexpr Version (const char* const ver, bool accept_less=false);
constexpr unsigned int operator[] (std::size_t idx) const;
constexpr unsigned int major() const;
constexpr unsigned int minor() const;
constexpr unsigned int revision() const;
private:
unsigned int m_versions[N];
};
template <std::size_t N>
inline constexpr Version<N>::Version (const char* const ver, bool accept_less) :
m_versions{0}
{
std::size_t z = 0;
std::size_t s = 0;
std::size_t idx = 0;
bool commit = false;
do {
if (ver[z] >= '0' and ver[z] <= '9') {
commit = true;
}
else if (commit) {
commit = false;
m_versions[idx++] = dhandy::ary_to_int<unsigned int>(ver + s, ver + z);
s = z + 1;
}
else {
s = z + 1;
}
} while(ver[z++] and idx < N);
if (not accept_less and idx < N)
throw std::invalid_argument("Input version doesn't contain enough version numbers");
}
template <std::size_t N>
inline constexpr unsigned int Version<N>::operator[] (std::size_t idx) const {
if (idx < N)
return m_versions[idx];
else
throw std::out_of_range("Index is out of range");
}
template <std::size_t N>
inline constexpr unsigned int Version<N>::major() const {
return m_versions[0];
}
template <std::size_t N>
inline constexpr unsigned int Version<N>::minor() const {
if constexpr (N > 1)
return m_versions[1];
else
throw std::out_of_range("Not enough version entries, there is no minor number");
}
template <std::size_t N>
inline constexpr unsigned int Version<N>::revision() const {
if constexpr (N > 2)
return m_versions[2];
else
throw std::out_of_range("Not enough version entries, there is no revision number");
}
} //namespace dhandy::bt
#endif

View file

@ -1,32 +0,0 @@
if not meson.is_subproject() and meson.version().version_compare('>=0.63.0')
install_headers(
'duckhandy/implem/IteratorOnPtr.hpp',
'duckhandy/implem/AutomemBase.hpp',
'duckhandy/implem/AutomemBase.inl',
'duckhandy/implem/int_conv.hpp',
'duckhandy/implem/reversed_sized_array_bt.hpp',
'duckhandy/version_bt.hpp',
'duckhandy/has_method.hpp',
'duckhandy/MaxSizedArray.hpp',
'duckhandy/MaxSizedArray.inl',
'duckhandy/bitfield_pack.hpp',
'duckhandy/cmake_on_off.h',
'duckhandy/compatibility.h',
'duckhandy/ducktypes.hpp',
'duckhandy/endianness.hpp',
'duckhandy/tiger_bt.hpp',
'duckhandy/infix_iterator.hpp',
'duckhandy/int_conv.hpp',
'duckhandy/int_types.hpp',
'duckhandy/lengthof.h',
'duckhandy/nomove_storage.hpp',
'duckhandy/resource_pool.hpp',
'duckhandy/tiger_bt.inl',
'duckhandy/string.hpp',
'duckhandy/string_bt.hpp',
'duckhandy/string_view.hpp',
'duckhandy/stringize.h',
'duckhandy/variadic_repeat_bt.hpp',
preserve_path: true, #meson v0.63.0
)
endif

1
lib/Catch2 Submodule

@ -0,0 +1 @@
Subproject commit 89f5f8435176aad44624442b7f1e874a513bee67

View file

@ -1,23 +0,0 @@
project('duckhandy', 'cpp',
version: '0.1.0',
meson_version: '>=0.56.0',
default_options: ['buildtype=release', 'cpp_std=gnu++20', 'b_ndebug=if-release']
)
sprout_dep = dependency('sprout', allow_fallback: true)
public_incl = include_directories('include')
duckhandy_dep = declare_dependency(
include_directories: [
public_incl,
],
dependencies: [sprout_dep],
)
meson.override_dependency(meson.project_name(), duckhandy_dep)
if get_option('build_testing')
subdir('test')
endif
subdir('include')

View file

@ -1 +0,0 @@
option('build_testing', type: 'boolean', value: true)

View file

@ -1,56 +0,0 @@
#include "duckhandy/int_conv.hpp"
#include <iostream>
#include <random>
#include <chrono>
#include <vector>
#include <string>
#include <algorithm>
#include <ctime>
namespace {
template <typename Conv>
void run_with_timing (
const std::string& test_name,
const std::vector<unsigned int>& src,
std::vector<std::string>& dst,
Conv&& conv_func
) {
dst.clear();
dst.resize(src.size());
std::cout << test_name << "...\n";
const std::size_t count = src.size();
const auto t0 = std::chrono::high_resolution_clock::now();
for (std::size_t z = 0; z < count; ++z) {
dst[z] = conv_func(src[z]);
}
const auto t1 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = t1 - t0;
std::cout << count << " conversions completed in " << duration.count() << " seconds\n";
}
} //unnamed namespace
int main() {
using dhandy::int_conv;
constexpr const std::size_t count = 70'000'000;
std::vector<unsigned int> nums;
std::vector<std::string> strings;
std::mt19937 gen;
std::cout << "Setting up data...\n";
nums.resize(count);
strings.reserve(count);
gen.seed(std::time(nullptr));
std::cout << "Generating " << count << " random values...\n";
std::generate(nums.begin(), nums.end(), gen);
run_with_timing("Conversions with std::to_string", nums, strings, [](unsigned int n) { return std::to_string(n); });
run_with_timing("AryConversion with dhandy::int_conv", nums, strings, [](unsigned int n) { return int_conv<std::string>(n); });
std::cout << "All done, bye!\n";
return 0;
}

View file

@ -1,7 +0,0 @@
[wrap-git]
revision = b5373dadca40b7edc8570cf9470b9b1cb1934d40
url = https://github.com/catchorg/Catch2.git
[provide]
catch2-with-main = catch2_with_main_dep
Catch2 = catch2_dep

File diff suppressed because it is too large Load diff

View file

@ -1,7 +0,0 @@
[wrap-git]
url = https://github.com/bolero-MURAKAMI/Sprout.git
revision = head
patch_directory = sprout
[provide]
dependency_names = sprout-20190615

View file

@ -1 +0,0 @@
subdir('unit')

View file

@ -1,20 +1,19 @@
project(dhandy_unit_test CXX)
add_executable(${PROJECT_NAME}
int_conv_test.cpp
main.cpp
endianness_test.cpp
int_conv_test.cpp
reversed_sized_array_test.cpp
bitfield_pack_test.cpp
resource_pool_test.cpp
version_test.cpp
tiger_test.cpp
scapegoat_tree_test.cpp
)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
target_include_directories(${PROJECT_NAME}
PRIVATE ${DUCKHANDY_SOURCE_DIR}/subprojects/Catch2/Catch2/single_include
PRIVATE ${DUCKHANDY_SOURCE_DIR}/lib/Catch2/single_include
)
target_link_libraries(${PROJECT_NAME}

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,7 +15,7 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "catch2/catch.hpp"
#include "duckhandy/bitfield_pack.hpp"
#include <cstdint>

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,7 +15,7 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "catch2/catch.hpp"
#include "duckhandy/endianness.hpp"
#include <endian.h>

View file

@ -1,58 +0,0 @@
/* Copyright 2016-2024 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "duckhandy/infix_iterator.hpp"
#include <algorithm>
#include <sstream>
#include <vector>
TEST_CASE("infix_iterator tests", "[iterator][infix_iterator]") {
using std::vector;
using std::string;
using std::copy;
using std::ostringstream;
using dhandy::infix_ostream_iterator;
{
ostringstream oss;
vector<string> empty{};
copy(empty.begin(), empty.end(), infix_ostream_iterator<string>(oss, "lalala"));
CHECK(oss.str() == "");
}
{
ostringstream oss;
vector<string> data{"apple", "pear", "cherry", "mango"};
copy(data.begin(), data.end(), infix_ostream_iterator<string>(oss, "lalala"));
CHECK(oss.str() == "applelalalapearlalalacherrylalalamango");
}
{
ostringstream oss;
vector<int> data{1, 2, 3, 4, 5, 6, 7};
copy(data.begin(), data.end(), infix_ostream_iterator<int>(oss, ", "));
CHECK(oss.str() == "1, 2, 3, 4, 5, 6, 7");
}
{
ostringstream oss;
vector<string> data{"just one value"};
copy(data.begin(), data.end(), infix_ostream_iterator<string>(oss, ", "));
CHECK(oss.str() == "just one value");
}
}

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,7 +15,7 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "catch2/catch.hpp"
#include "duckhandy/int_conv.hpp"
#include "duckhandy/string_bt.hpp"
#include "sprout/cstring/strlen.hpp"
@ -23,47 +23,20 @@
#include <cstdint>
#include <random>
#include <string>
#include <ctime>
template <typename T> using int_info_10 = dhandy::implem::int_info<T, 10>;
template <typename T> using int_info_16 = dhandy::implem::int_info<T, 16>;
template <typename T> using int_info_2 = dhandy::implem::int_info<T, 2>;
namespace {
template <unsigned int Base>
struct ASCIITranslatorIns : public dhandy::ASCIITranslator<char> {
static const constexpr char AltLetter = 'A';
static constexpr int from_digit (char dig) {
if (dig >= FirstLetter and dig <= FirstLetter + Base - 10 - 1)
return dig - FirstLetter + 10;
else
return dig - AltLetter + 10;
}
};
template <typename T, unsigned int Base>
void AryConversionTestHelper (const std::string_view& s, T expected, bool expect_sse) {
using AryConversion = dhandy::implem::AryConversion<T, Base, dhandy::ASCIITranslator<char>, false>;
CHECK(AryConversion::is_sse == expect_sse);
CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected);
}
template <typename T, unsigned int Base>
void AryConversionTestHelperUp (const std::string_view& s, T expected, bool expect_sse) {
using AryConversion = dhandy::implem::AryConversion<T, Base, dhandy::ASCIITranslatorUpcase<char>, false>;
CHECK(AryConversion::is_sse == expect_sse);
CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected);
}
template <typename T, unsigned int Base>
void AryConversionTestHelperIns (const std::string_view& s, T expected, bool expect_sse) {
using AryConversion = dhandy::implem::AryConversion<T, Base, ASCIITranslatorIns<Base>, false>;
CHECK(AryConversion::is_sse == expect_sse);
void AryConversionTestHelper (const std::string_view& s, T expected) {
using AryConversion = dhandy::implem::AryConversion<T, Base, dhandy::ASCIITranslator<char>>;
CHECK(AryConversion::from_ary(s.data(), s.data() + s.size()) == expected);
}
} //unnamed namespace
TEST_CASE ("Check int to char array conversions", "[i2s][int_conv]") {
TEST_CASE ("Check int to char array conversions", "[s2i][int_conv]") {
using dhandy::int_to_ary;
using dhandy::bt::string;
using dhandy::bt::make_string;
@ -101,7 +74,6 @@ TEST_CASE ("Check int to char array conversions", "[i2s][int_conv]") {
CHECK(int_to_ary<int64_t>(-1) == "-1");
CHECK(int_to_ary<int64_t>(0x1000000000000000) == "1152921504606846976");
CHECK(int_to_ary<int64_t>(0xF000000000000000) == "-1152921504606846976");
CHECK(int_to_ary<int, 16, dhandy::ASCIITranslatorUpcase<char>>(255) == "FF");
CHECK(int_to_ary<uint16_t SPROUT_PP_COMMA() 16>(0xFFFF) == "ffff");
CHECK(int_to_ary<uint16_t SPROUT_PP_COMMA() 16>(0xCACA) == "caca");
@ -143,7 +115,7 @@ TEST_CASE ("Check int to char array conversions", "[i2s][int_conv]") {
{
//Try a random test, which should not compile as constexpr
std::mt19937 gen;
gen.seed(std::time(nullptr));
gen.seed(1234);
for (int z = 0; z < 10; ++z) {
const int num = gen();
CHECK(int_to_ary(num) == std::to_string(num));
@ -157,137 +129,30 @@ TEST_CASE ("Check int to char array conversions", "[i2s][int_conv]") {
}
}
TEST_CASE ("Check char array to int conversions", "[s2i][int_conv]") {
AryConversionTestHelper<std::uint32_t, 10>("0", 0, true);
AryConversionTestHelper<std::int32_t, 10>("0", 0, true);
AryConversionTestHelper<std::int16_t, 10>("0", 0, true);
AryConversionTestHelper<std::int16_t, 16>("ff", 0xff, true);
AryConversionTestHelper<std::uint8_t, 16>("ff", 0xff, true);
AryConversionTestHelper<std::uint32_t, 36>("rs", 1000, true);
AryConversionTestHelper<std::uint16_t, 8>("20", 16, true);
AryConversionTestHelper<std::int32_t, 10>("1", 1, true);
AryConversionTestHelper<std::int32_t, 10>("10", 10, true);
AryConversionTestHelper<std::int32_t, 10>("100", 100, true);
AryConversionTestHelper<std::int32_t, 10>("999", 999, true);
AryConversionTestHelper<std::int32_t, 10>("1000", 1000, true);
AryConversionTestHelper<std::int32_t, 10>("1001", 1001, true);
AryConversionTestHelper<std::int32_t, 10>("12345", 12345, true);
AryConversionTestHelper<std::int32_t, 10>("123456", 123456, true);
AryConversionTestHelper<std::int32_t, 10>("1234567", 1234567, true);
AryConversionTestHelper<std::int32_t, 10>("12345678", 12345678, true);
AryConversionTestHelper<std::int32_t, 10>("123456789", 123456789, true);
AryConversionTestHelper<std::int32_t, 10>("2147483647", 2147483647, true);
AryConversionTestHelper<std::uint64_t, 16>("ffffffffffffffff", 0xffffffffffffffff, false);
AryConversionTestHelper<std::int64_t, 16>("ffffffffffffffff", 0xffffffffffffffff, false);
AryConversionTestHelper<std::int64_t, 16>("7fffffffffffffff", 0x7fffffffffffffff, false);
AryConversionTestHelper<std::int32_t, 16>("7fffffff", 0x7fffffff, true);
AryConversionTestHelper<bool, 10>("1", true, false);
AryConversionTestHelper<bool, 10>("0", false, false);
AryConversionTestHelperUp<std::uint64_t, 16>("ABCDEF123456ABCD", 0xabcdef123456abcd, false);
AryConversionTestHelper<signed int, 10>("-1", -1, sizeof(signed int) <= sizeof(std::uint32_t));
AryConversionTestHelper<signed int, 10>("-50000", -50000, sizeof(signed int) <= sizeof(std::uint32_t));
AryConversionTestHelper<std::int64_t, 10>("-1", -1, false);
AryConversionTestHelper<std::int64_t, 10>("-510123123123", -510123123123, false);
//case insensitive SSE conversions
AryConversionTestHelperIns<std::int32_t, 16>("7FfFfFfF", 0x7fffffff, true);
AryConversionTestHelperIns<std::int32_t, 16>("AbCdEf01", 0xabcdef01, true);
AryConversionTestHelperIns<std::int32_t, 16>("aBcDeF01", 0xabcdef01, true);
AryConversionTestHelperIns<std::uint8_t, 16>("Ff", 0xff, true);
AryConversionTestHelperIns<std::int16_t, 16>("AfBe", 0xafbe, true);
AryConversionTestHelperIns<std::int32_t, 16>("aAb", 0xaab, true);
AryConversionTestHelperIns<std::int32_t, 16>("aAbBc", 0xaabbc, true);
}
TEST_CASE ("Check string_view conversions work as expected", "[s2i][int_conv]") {
using dhandy::int_conv;
using dhandy::int_conv_raw;
using std::string_view;
using std::integral_constant;
using std::string;
constexpr auto str71 = int_conv<string_view>(integral_constant<short int, 71>{});
CHECK("71" == str71);
{
//test random number to force non-constexpr
std::mt19937 gen;
gen.seed(std::time(nullptr));
const int num = gen();
const string num_str {int_conv_raw(num).to_string_view()};
CHECK(num_str == std::to_string(num));
}
const auto str123 = int_conv<string>(123);
CHECK("123" == str123);
}
TEST_CASE ("Check std::array conversion works as expected", "[i2s][int_conv]") {
using std::array;
using dhandy::int_conv;
auto arr748 = int_conv<array<char, 3>>(748);
CHECK(arr748[0] == '7');
CHECK(arr748[1] == '4');
CHECK(arr748[2] == '8');
auto arr19000 = int_conv<array<char, 5>>(19);
CHECK(arr19000[0] == '1');
CHECK(arr19000[1] == '9');
CHECK(arr19000[2] == '\0');
CHECK(arr19000[3] == '\0');
CHECK(arr19000[4] == '\0');
}
TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]") {
using dhandy::int_conv;
using std::string_view;
using std::integral_constant;
constexpr auto bool1 = int_conv<string_view>(integral_constant<bool, true>{});
CHECK("1" == bool1);
constexpr auto bool2 = int_conv<string_view>(integral_constant<bool, false>{});
CHECK("0" == bool2);
constexpr auto int1 = int_conv<string_view>(integral_constant<int, 42>{});
CHECK("42" == int1);
constexpr auto int2 = int_conv<string_view>(integral_constant<unsigned int, 7777777>{});
CHECK("7777777" == int2);
constexpr auto int3 = int_conv<string_view>(integral_constant<int, -1234>{});
CHECK("-1234" == int3);
constexpr auto int4 = int_conv<string_view>(integral_constant<short int, -256>{});
CHECK("-256" == int4);
}
TEST_CASE ("Try int conv with non-char", "[s2i][int_conv]") {
using dhandy::buildtime_int_to_ary;
using dhandy::ASCIITranslator;
std::wstring_view exp1(L"235713");
auto val1 = buildtime_int_to_ary<int, 235713, 10, ASCIITranslator<wchar_t>>().to_string_view();
CHECK(exp1 == val1);
}
TEST_CASE ("Check some fancy conversions", "[i2s][int_conv]") {
using dhandy::int_to_ary;
using std::string;
using MyFancyTranslator = dhandy::ASCIITranslator<char, '0', 'a', '+', '-', '\0', 4>;
string str1 = int_to_ary<int, 10, MyFancyTranslator>(3).to_string();
CHECK("3" == str1);
string str2 = int_to_ary<int, 10, MyFancyTranslator>(5).to_string();
CHECK("b" == str2);
string str3 = int_to_ary<int, 10, MyFancyTranslator>(11).to_string();
CHECK("11" == str3);
string str4 = int_to_ary<int, 10, MyFancyTranslator>(537).to_string();
CHECK("b3d" == str4);
TEST_CASE ("Check char array to int conversions", "[i2s][int_conv]") {
AryConversionTestHelper<uint32_t, 10>("0", 0);
AryConversionTestHelper<int32_t, 10>("0", 0);
AryConversionTestHelper<int16_t, 10>("0", 0);
AryConversionTestHelper<int16_t, 16>("ff", 0xff);
AryConversionTestHelper<uint8_t, 16>("ff", 0xff);
AryConversionTestHelper<uint32_t, 36>("rs", 1000);
AryConversionTestHelper<uint16_t, 8>("20", 16);
AryConversionTestHelper<int32_t, 10>("1", 1);
AryConversionTestHelper<int32_t, 10>("10", 10);
AryConversionTestHelper<int32_t, 10>("100", 100);
AryConversionTestHelper<int32_t, 10>("999", 999);
AryConversionTestHelper<int32_t, 10>("1000", 1000);
AryConversionTestHelper<int32_t, 10>("1001", 1001);
AryConversionTestHelper<int32_t, 10>("12345", 12345);
AryConversionTestHelper<int32_t, 10>("123456", 123456);
AryConversionTestHelper<int32_t, 10>("1234567", 1234567);
AryConversionTestHelper<int32_t, 10>("12345678", 12345678);
AryConversionTestHelper<int32_t, 10>("123456789", 123456789);
AryConversionTestHelper<int32_t, 10>("2147483647", 2147483647);
AryConversionTestHelper<uint64_t, 16>("ffffffffffffffff", 0xffffffffffffffff);
AryConversionTestHelper<int64_t, 16>("ffffffffffffffff", 0xffffffffffffffff);
AryConversionTestHelper<int64_t, 16>("7fffffffffffffff", 0x7fffffffffffffff);
AryConversionTestHelper<int32_t, 16>("7fffffff", 0x7fffffff);
AryConversionTestHelper<bool, 10>("1", true);
AryConversionTestHelper<bool, 10>("0", false);
}

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,5 +15,5 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
//#define CATCH_CONFIG_MAIN
//#include "catch2/catch_test_macros.hpp"
#define CATCH_CONFIG_MAIN
#include "catch2/catch.hpp"

View file

@ -1,20 +0,0 @@
catch2_dep = dependency('catch2-with-main', version: '>=3.5.2')
unit_test_prog = executable(meson.project_name(),
'int_conv_test.cpp',
'main.cpp',
'endianness_test.cpp',
'reversed_sized_array_test.cpp',
'bitfield_pack_test.cpp',
'resource_pool_test.cpp',
'version_test.cpp',
'tiger_test.cpp',
'infix_iterator.cpp',
install: false,
dependencies: [sprout_dep, catch2_dep],
include_directories: [public_incl],
)
test('unit_' + meson.project_name(),
unit_test_prog,
)

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,7 +15,7 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "catch2/catch.hpp"
#include "duckhandy/resource_pool.hpp"
#include <cstdint>

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2024 Michele Santullo
/* Copyright 2016-2020 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
@ -15,7 +15,7 @@
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "catch2/catch.hpp"
#include "duckhandy/implem/reversed_sized_array_bt.hpp"
TEST_CASE ("Check conversion functions in ReversedSizedArray", "[ReversedSizedArray][containers]") {

View file

@ -0,0 +1,152 @@
/* Copyright 2016-2018 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch.hpp"
#include "duckhandy/scapegoat_tree.hpp"
#include <set>
TEST_CASE ("Insert values in a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") {
using duckmem::ScapegoatTree;
ScapegoatTree<int> tree;
{
auto it = tree.insert(25);
CHECK(it.second == true);
CHECK(it.first != tree.end());
CHECK(*it.first == 25);
CHECK(tree.size() == 1);
}
{
auto it = tree.insert(25);
CHECK(tree.size() == 1);
CHECK(it.second == false);
CHECK(it.first != tree.end());
CHECK(*it.first == 25);
}
{
auto it = tree.insert(26);
CHECK(it.second == true);
CHECK(it.first != tree.end());
CHECK(*it.first == 26);
CHECK(tree.size() == 2);
}
{
for (std::size_t z = 0; z < 100; ++z) {
const int val = static_cast<int>(z);
auto it = tree.insert(val);
if (z < 25) {
CHECK(tree.size() == z + 2 + 1);
CHECK(it.second == true);
}
else if (z < 26) {
CHECK(tree.size() == z + 1 + 1);
CHECK(it.second == false);
}
else if (z < 27) {
CHECK(tree.size() == z + 1);
CHECK(it.second == false);
}
else {
CHECK(tree.size() == z + 1);
CHECK(it.second == true);
}
CHECK(*it.first == val);
}
}
{
auto end = tree.end();
int val = 0;
for (auto it = tree.begin(); it != end; ++it, ++val) {
CHECK(val == *it);
}
CHECK(static_cast<int>(tree.size()) == val);
val = 75;
for (auto it = tree.insert(val).first; it != end; ++it, ++val) {
CHECK(val == *it);
}
CHECK(static_cast<int>(tree.size()) == val);
}
}
TEST_CASE ("Erase values from a ScapegoatTree", "[Scapegoat][ScapegoatTree][containers]") {
using duckmem::ScapegoatTree;
//auto rand_num = std::bind(std::uniform_int_distribution<int>(1, 1000), std::mt19937(std::time(0)));
ScapegoatTree<int> tree;
for (int z = 0; z < 5000; ++z) {
tree.insert(z + 1);
}
CHECK(tree.size() == 5000);
std::set<int> cpy(tree.begin(), tree.end());
CHECK(cpy.size() == 5000);
{
auto it_num = tree.find(0);
CHECK(it_num == tree.end());
}
{
auto it_num = tree.find(1);
REQUIRE(it_num != tree.end());
CHECK(*it_num == 1);
CHECK(it_num == tree.begin());
tree.erase(it_num);
cpy.erase(1);
CHECK(tree.size() == 4999);
it_num = tree.find(1);
CHECK(it_num == tree.end());
CHECK(not tree.include(1));
}
{
auto it_num = tree.find(2345);
REQUIRE(it_num != tree.end());
CHECK(*it_num == 2345);
tree.erase(it_num);
cpy.erase(2345);
CHECK(tree.size() == 4998);
it_num = tree.find(2345);
CHECK(it_num == tree.end());
CHECK(not tree.include(2345));
}
{
auto it_num = tree.find(3000);
REQUIRE(it_num != tree.end());
int test_num = 3000;
for (; it_num != tree.end(); ++it_num) {
CHECK(*it_num == test_num);
test_num++;
}
CHECK(test_num == 5001);
}
{
const ScapegoatTree<int>& ref = tree;
auto it_num = ref.find(18);
REQUIRE(it_num != ref.end());
CHECK(*it_num == 18);
CHECK(ref.include(18));
}
REQUIRE(tree.size() == cpy.size());
CHECK(std::equal(tree.begin(), tree.end(), cpy.begin()));
}

View file

@ -1,56 +0,0 @@
/* Copyright 2016-2024 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "duckhandy/tiger_bt.hpp"
TEST_CASE("Build-time Tiger hash tests", "[hash][bt][tiger]") {
using dhandy::bt::tiger;
using dhandy::bt::TigerHash;
using dhandy::bt::TigerPaddingV1;
using dhandy::bt::TigerPaddingV2;
constexpr TigerHash h1 = tiger("", 0, TigerPaddingV2);
CHECK(h1.a == 0x738701f675be4144);
CHECK(h1.b == 0x924b374527c206c2);
CHECK(h1.c == 0x419f91ef3f31a84a);
constexpr TigerHash h2 = tiger("", 0, TigerPaddingV1);
CHECK(h2.a == 0x24f0130c63ac9332);
CHECK(h2.b == 0x16166e76b1bb925f);
CHECK(h2.c == 0xf373de2d49584e7a);
constexpr TigerHash h3 = tiger("message digest", 14, TigerPaddingV2);
CHECK(h3.a == 0x9d25fab5a11994e2);
CHECK(h3.b == 0xea7850e77d5e00e8);
CHECK(h3.c == 0x2d465225ef42a581);
constexpr TigerHash h4 = tiger("message digest", 14, TigerPaddingV1);
CHECK(h4.a == 0x951a2078cbf881d9);
CHECK(h4.b == 0x1c441e754830cf0d);
CHECK(h4.c == 0xf6295aa51aca7f51);
constexpr TigerHash h5 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV2);
CHECK(h5.a == 0x517bee8c22b69aea);
CHECK(h5.b == 0x8c6c06a6fc4475b7);
CHECK(h5.c == 0xcd059531e6ba5bbb);
constexpr TigerHash h6 = tiger("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, TigerPaddingV1);
CHECK(h6.a == 0xee8375a180a6ce8d);
CHECK(h6.b == 0x5186363c8aa32b50);
CHECK(h6.c == 0xcca849dcccfb0f89);
}

View file

@ -1,94 +0,0 @@
/* Copyright 2016-2024 Michele Santullo
* This file is part of "duckhandy".
*
* "duckhandy" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "duckhandy" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch2/catch_test_macros.hpp"
#include "duckhandy/version_bt.hpp"
TEST_CASE ("Version class tests", "[version][bt]") {
using dhandy::bt::Version;
{
constexpr Version<1> ver{"102"};
static_assert(ver.major() == 102, "Version error");
static_assert(ver.count == 1, "Version error");
CHECK(ver[0] == 102);
CHECK_THROWS(ver[1]);
CHECK_THROWS(ver[2]);
CHECK_THROWS(ver[3]);
CHECK_THROWS(ver[4]);
}
{
constexpr Version<3> ver{".aheud15,a.ud22,cu.sh81,.nuad.h44"};
static_assert(ver.count == 3, "Version error");
static_assert(ver.major() == 15, "Version error");
static_assert(ver.minor() == 22, "Version error");
static_assert(ver.revision() == 81, "Version error");
CHECK(ver[0] == 15);
CHECK(ver[1] == 22);
CHECK(ver[2] == 81);
CHECK_THROWS(ver[3]);
CHECK_THROWS(ver[4]);
}
{
constexpr Version<10> ver{"1.2.3.44.55.66.777.888.999.101010"};
static_assert(ver.count == 10, "Version error");
static_assert(ver.major() == 1, "Version error");
static_assert(ver.minor() == 2, "Version error");
static_assert(ver.revision() == 3, "Version error");
CHECK(ver[0] == 1);
CHECK(ver[1] == 2);
CHECK(ver[2] == 3);
CHECK(ver[3] == 44);
CHECK(ver[4] == 55);
CHECK(ver[5] == 66);
CHECK(ver[6] == 777);
CHECK(ver[7] == 888);
CHECK(ver[8] == 999);
CHECK(ver[9] == 101010);
CHECK_THROWS(ver[10]);
}
{
constexpr Version<4> ver{"1.2.3.", true};
static_assert(ver.count == 4, "Version error");
static_assert(ver.major() == 1, "Version error");
static_assert(ver.minor() == 2, "Version error");
static_assert(ver.revision() == 3, "Version error");
CHECK(ver[0] == 1);
CHECK(ver[1] == 2);
CHECK(ver[2] == 3);
CHECK(ver[3] == 0);
CHECK_THROWS(ver[10]);
}
{
constexpr Version<4> ver{"6.7.2-r1"};
static_assert(ver.count == 4, "Version error");
static_assert(ver.major() == 6, "Version error");
static_assert(ver.minor() == 7, "Version error");
static_assert(ver.revision() == 2, "Version error");
CHECK(ver[0] == 6);
CHECK(ver[1] == 7);
CHECK(ver[2] == 2);
CHECK(ver[3] == 1);
CHECK_THROWS(ver[10]);
}
CHECK_THROWS(Version<4>{"4.5"});
}