`leven_diff()`: Added string literal overloads for comptime string comparison load and allocation reductions.

Fortune for libexopt's current commit: Blessing − 吉
boxed_is_boxed_value
Avril 2 years ago
parent b778b47ae8
commit 1752c89056
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -4,10 +4,12 @@
#include "exopt.h" #include "exopt.h"
#ifdef __cplusplus #ifdef __cplusplus
//#include "util.hh"
#include <string_view> #include <string_view>
#include <concepts> #include <concepts>
#include <vector> #include <vector>
#include <array>
#include <span> #include <span>
#include <tuple> #include <tuple>
@ -24,6 +26,7 @@ size_t _EO(leven_diff)(const char* _EO(restrict), const char* _EO(restrict), siz
} }
namespace exopt { namespace util [[gnu::visibility("internal")]] { namespace exopt { namespace util [[gnu::visibility("internal")]] {
template<size_t N =0> // NOTE: Do not change this manually //
constexpr auto leven_diff(std::string_view s1, std::string_view s2) noexcept { constexpr auto leven_diff(std::string_view s1, std::string_view s2) noexcept {
const size_t const size_t
m(s1.size()), m(s1.size()),
@ -58,7 +61,9 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
return costs[n]; return costs[n];
}; };
if consteval { if constexpr(N > 0) {
return work_on_d(std::array<size_t, N+1>{});
} else if consteval {
return work_on_d(std::vector<size_t>(n + 1)); return work_on_d(std::vector<size_t>(n + 1));
} else { } else {
thread_local static std::vector<size_t> d; thread_local static std::vector<size_t> d;
@ -74,6 +79,16 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
return leven_diff(str{sa}, str{sb}); return leven_diff(str{sa}, str{sb});
} }
template<size_t M, size_t N>
constexpr decltype(auto) leven_diff(const char (&sa)[M], const char (&sb)[N]) noexcept {
if constexpr(!N) return M;
else if constexpr(!M) return N;
else if constexpr(M < N) return N - M; //XXX: Are these lines correct?
else if constexpr(N < M) return M - N; // ^
else return leven_diff<N>(std::string_view{sa}, std::string_view{sb});
}
} } } }
#endif #endif

@ -1,16 +1,17 @@
#pragma once #pragma once
#include <string_view>
#include <utility> #include <utility>
#include "exopt.h" #include "exopt.h"
#define _EO_CONSTANT_VALUE(X) ([] { \ #define _EO_CONSTANT_VALUE(X) ([]() { \
struct { \ struct { \
typedef decltype(X) comptime_constant_t; \ typedef decltype(X) comptime_constant_t; \
consteval operator comptime_constant_t() const noexcept { return (X); } \ consteval operator comptime_constant_t() const noexcept { return (X); } \
} inner; \ } inner; \
return inner; \ return inner; \
}()) })()
namespace exopt { namespace util [[gnu::visibility("internal")]] { namespace exopt { namespace util [[gnu::visibility("internal")]] {
template<typename T, typename U> template<typename T, typename U>

@ -1,4 +1,6 @@
#include <string>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -18,5 +20,7 @@ namespace exopt {
namespace util [[gnu::visibility("internal")]] { namespace util [[gnu::visibility("internal")]] {
static_assert(leven_diff("hello world", "Hello World") == 2, "Levelshtein distance incorrect for non-matching strings"); static_assert(leven_diff("hello world", "Hello World") == 2, "Levelshtein distance incorrect for non-matching strings");
static_assert(leven_diff("hello world", "hello world") == 0, "Levelshtein distance incorrect for matching strings"); static_assert(leven_diff("hello world", "hello world") == 0, "Levelshtein distance incorrect for matching strings");
static_assert(leven_diff("hello world", std::string_view{"hello world"}) == 0, "Levelshtein distance incorrect for matching string container type 1");
static_assert(leven_diff(std::string{"llo world"}, std::string_view{"hello world"}) == 2, "Levelshtein distance incorrect for matching string container type 2");
} }
} }

Loading…
Cancel
Save