destructors are not possible currently. use a gc if you need them.

thread
Brett 2024-08-11 20:21:53 -04:00
parent e9954f5065
commit 4735c6c21b
5 changed files with 70 additions and 41 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.135) project(blt-gp VERSION 0.0.136)
include(CTest) include(CTest)

View File

@ -101,8 +101,17 @@ namespace blt::gp
allocator.from<detail::remove_cv_ref<Args>>(getByteOffset<indices>())...); allocator.from<detail::remove_cv_ref<Args>>(getByteOffset<indices>())...);
} }
template<typename context = void, typename... NoCtxArgs>
void call_destructors_without_first(stack_allocator& read_allocator)
{
if constexpr (sizeof...(NoCtxArgs) > 0)
{
read_allocator.call_destructors<detail::remove_cv_ref<NoCtxArgs>...>();
}
}
template<typename Func, typename... ExtraArgs> template<typename Func, typename... ExtraArgs>
Return operator()(Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args) Return operator()(bool, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
{ {
constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>(); constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
#if BLT_DEBUG_LEVEL > 0 #if BLT_DEBUG_LEVEL > 0
@ -110,7 +119,10 @@ namespace blt::gp
{ {
#endif #endif
Return ret = exec_sequence_to_indices(std::forward<Func>(func), read_allocator, seq, std::forward<ExtraArgs>(args)...); Return ret = exec_sequence_to_indices(std::forward<Func>(func), read_allocator, seq, std::forward<ExtraArgs>(args)...);
read_allocator.call_destructors<detail::remove_cv_ref<Args>...>(); /*if (has_context)
call_destructors_without_first<Args...>(read_allocator);
else
read_allocator.call_destructors<detail::remove_cv_ref<Args>...>();*/
read_allocator.pop_bytes((stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() + ...)); read_allocator.pop_bytes((stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() + ...));
return ret; return ret;
#if BLT_DEBUG_LEVEL > 0 #if BLT_DEBUG_LEVEL > 0
@ -153,7 +165,7 @@ namespace blt::gp
return func(); return func();
} else } else
{ {
return call_with<Return, Args...>()(func, read_allocator); return call_with<Return, Args...>()(false, func, read_allocator);
} }
} }
@ -170,7 +182,7 @@ namespace blt::gp
return func(ctx_ref); return func(ctx_ref);
} else } else
{ {
return call_without_first<Return, Args...>()(func, read_allocator, ctx_ref); return call_without_first<Return, Args...>()(true, func, read_allocator, ctx_ref);
} }
} }
@ -214,16 +226,24 @@ namespace blt::gp
}; };
template<typename Lambda> template<typename Lambda>
operation_t(Lambda) -> operation_t<Lambda, decltype(&Lambda::operator())>; operation_t(Lambda)
->
operation_t<Lambda, decltype(&Lambda::operator())>;
template<typename Return, typename... Args> template<typename Return, typename... Args>
operation_t(Return(*)(Args...)) -> operation_t<Return(*)(Args...), Return(Args...)>; operation_t(Return(*)
(Args...)) ->
operation_t<Return(*)(Args...), Return(Args...)>;
template<typename Lambda> template<typename Lambda>
operation_t(Lambda, std::optional<std::string_view>) -> operation_t<Lambda, decltype(&Lambda::operator())>; operation_t(Lambda, std::optional<std::string_view>
) ->
operation_t<Lambda, decltype(&Lambda::operator())>;
template<typename Return, typename... Args> template<typename Return, typename... Args>
operation_t(Return(*)(Args...), std::optional<std::string_view>) -> operation_t<Return(*)(Args...), Return(Args...)>; operation_t(Return(*)
(Args...), std::optional<std::string_view>) ->
operation_t<Return(*)(Args...), Return(Args...)>;
} }
#endif //BLT_GP_OPERATIONS_H #endif //BLT_GP_OPERATIONS_H

View File

@ -205,14 +205,15 @@ namespace blt::gp
* @param value universal reference to the object to push * @param value universal reference to the object to push
*/ */
template<typename T> template<typename T>
void push(T&& value) void push(const T& value)
{ {
using NO_REF_T = std::remove_cv_t<std::remove_reference_t<T>>; using NO_REF_T = std::remove_cv_t<std::remove_reference_t<T>>;
static_assert(std::is_trivially_copyable_v<NO_REF_T> && "Type must be bitwise copyable!"); static_assert(std::is_trivially_copyable_v<NO_REF_T> && "Type must be bitwise copyable!");
static_assert(alignof(NO_REF_T) <= MAX_ALIGNMENT && "Type must not be greater than the max alignment!"); static_assert(alignof(NO_REF_T) <= MAX_ALIGNMENT && "Type must not be greater than the max alignment!");
auto ptr = allocate_bytes<NO_REF_T>(); auto ptr = allocate_bytes<NO_REF_T>();
head->metadata.offset = static_cast<blt::u8*>(ptr) + aligned_size<NO_REF_T>(); head->metadata.offset = static_cast<blt::u8*>(ptr) + aligned_size<NO_REF_T>();
new(ptr) NO_REF_T(std::forward<T>(value)); //new(ptr) NO_REF_T(std::forward<T>(value));
std::memcpy(ptr, &value, sizeof(NO_REF_T));
} }
template<typename T> template<typename T>
@ -233,7 +234,7 @@ namespace blt::gp
NO_REF_T t = *reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE); NO_REF_T t = *reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE);
// call destructor // call destructor
if constexpr (detail::has_func_drop_v<T>) if constexpr (detail::has_func_drop_v<T>)
reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE)->~NO_REF_T(); call_drop<NO_REF_T>(0);
// move offset back // move offset back
head->metadata.offset -= TYPE_SIZE; head->metadata.offset -= TYPE_SIZE;
// moving back allows us to allocate with other data, if there is room. // moving back allows us to allocate with other data, if there is room.
@ -348,9 +349,9 @@ namespace blt::gp
template<typename... Args> template<typename... Args>
void call_destructors() void call_destructors()
{ {
blt::size_t offset = 0; blt::size_t offset = (stack_allocator::aligned_size<NO_REF_T<Args>>() + ...) -
stack_allocator::aligned_size<NO_REF_T<typename blt::meta::arg_helper<Args...>::First>>();
((call_drop<Args>(offset), offset += stack_allocator::aligned_size<NO_REF_T<Args>>()), ...); ((call_drop<Args>(offset), offset -= stack_allocator::aligned_size<NO_REF_T<Args>>()), ...);
} }
[[nodiscard]] bool empty() const noexcept [[nodiscard]] bool empty() const noexcept

@ -1 +1 @@
Subproject commit 4327b34c841fd6d8fb6509757d5cab2717d35457 Subproject commit 92300bc6a29927f5354d516df76ad40be7fca868

View File

@ -43,39 +43,46 @@
//static constexpr long SEED = 41912; //static constexpr long SEED = 41912;
static const unsigned long SEED = std::random_device()(); static const unsigned long SEED = std::random_device()();
inline std::atomic_uint64_t last_value = 0;
inline std::atomic_uint64_t constructions = 0; inline std::atomic_uint64_t constructions = 0;
inline std::atomic_uint64_t destructions = 0; inline std::atomic_uint64_t destructions = 0;
class move_float class move_float
{ {
public: public:
move_float(): f(new float()) move_float(): f(new float()), assignment(++last_value)
{ constructions++; }
explicit move_float(float f): f(new float(f))
{ {
constructions++; constructions++;
// BLT_TRACE("Value Constructed"); BLT_TRACE("Value %ld Default Constructed", assignment);
}
explicit move_float(float f): f(new float(f)), assignment(++last_value)
{
constructions++;
BLT_TRACE("Value %ld Constructed", assignment);
} }
explicit operator float() const explicit operator float() const
{ {
BLT_TRACE("Using value %ld", assignment);
return *f; return *f;
} }
float get() const [[nodiscard]] float get() const
{ {
BLT_TRACE("Using value %ld", assignment);
return *f; return *f;
} }
float operator*() const float operator*() const
{ {
BLT_TRACE("Using value %ld", assignment);
return *f; return *f;
} }
void drop() // NOLINT void drop() // NOLINT
{ {
//BLT_TRACE("Drop Called"); BLT_TRACE("Drop Called On %ld", assignment);
delete f; delete f;
f = nullptr; f = nullptr;
destructions++; destructions++;
@ -83,6 +90,7 @@ class move_float
private: private:
float* f = nullptr; float* f = nullptr;
blt::size_t assignment;
}; };
static_assert(std::is_trivially_copyable_v<move_float>); static_assert(std::is_trivially_copyable_v<move_float>);
@ -90,7 +98,7 @@ static_assert(std::is_trivially_copyable_v<move_float>);
struct context struct context
{ {
move_float x, y; float x, y;
}; };
std::array<context, 200> fitness_cases; std::array<context, 200> fitness_cases;
@ -104,32 +112,32 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t()
.set_reproduction_chance(0) .set_reproduction_chance(0)
.set_max_generations(1) .set_max_generations(1)
.set_pop_size(1) .set_pop_size(1)
.set_thread_count(0); .set_thread_count(1);
blt::gp::type_provider type_system; blt::gp::type_provider type_system;
blt::gp::gp_program program{type_system, SEED, config}; blt::gp::gp_program program{type_system, SEED, config};
blt::gp::operation_t add([](const move_float& a, const move_float& b) { return move_float(*a + *b); }, "add"); blt::gp::operation_t add([](const move_float& a, const move_float& b) { return move_float(*a + *b); }, "add"); // 0
blt::gp::operation_t sub([](const move_float& a, const move_float& b) { return move_float(*a - *b); }, "sub"); blt::gp::operation_t sub([](const move_float& a, const move_float& b) { return move_float(*a - *b); }, "sub"); // 1
blt::gp::operation_t mul([](const move_float& a, const move_float& b) { return move_float(*a * *b); }, "mul"); blt::gp::operation_t mul([](const move_float& a, const move_float& b) { return move_float(*a * *b); }, "mul"); // 2
blt::gp::operation_t pro_div([](const move_float& a, const move_float& b) { return move_float(*b == 0.0f ? 1.0f : *a / *b); }, "div"); blt::gp::operation_t pro_div([](const move_float& a, const move_float& b) { return move_float(*b == 0.0f ? 1.0f : *a / *b); }, "div"); // 3
blt::gp::operation_t op_sin([](const move_float& a) { return move_float(std::sin(*a)); }, "sin"); blt::gp::operation_t op_sin([](const move_float& a) { return move_float(std::sin(*a)); }, "sin"); // 4
blt::gp::operation_t op_cos([](const move_float& a) { return move_float(std::cos(*a)); }, "cos"); blt::gp::operation_t op_cos([](const move_float& a) { return move_float(std::cos(*a)); }, "cos"); // 5
blt::gp::operation_t op_exp([](const move_float& a) { return move_float(std::exp(*a)); }, "exp"); blt::gp::operation_t op_exp([](const move_float& a) { return move_float(std::exp(*a)); }, "exp"); // 6
blt::gp::operation_t op_log([](const move_float& a) { return move_float(*a == 0.0f ? 0.0f : std::log(*a)); }, "log"); blt::gp::operation_t op_log([](const move_float& a) { return move_float(*a == 0.0f ? 0.0f : std::log(*a)); }, "log"); // 7
blt::gp::operation_t lit([]() { blt::gp::operation_t lit([]() { // 8
return move_float(program.get_random().get_float(-320.0f, 320.0f)); return move_float(program.get_random().get_float(-320.0f, 320.0f));
}, "lit"); }, "lit");
blt::gp::operation_t op_x([](const context& context) { blt::gp::operation_t op_x([](const context& context) { // 9
return context.x; return move_float(context.x);
}, "x"); }, "x");
constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fitness_t& fitness, blt::size_t) { constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fitness_t& fitness, blt::size_t) {
constexpr double value_cutoff = 1.e15; constexpr double value_cutoff = 1.e15;
for (auto& fitness_case : fitness_cases) for (auto& fitness_case : fitness_cases)
{ {
auto diff = std::abs(*fitness_case.y - *current_tree.get_evaluation_value<move_float>(&fitness_case)); auto diff = std::abs(fitness_case.y - *current_tree.get_evaluation_value<move_float>(&fitness_case));
if (diff < value_cutoff) if (diff < value_cutoff)
{ {
fitness.raw_fitness += diff; fitness.raw_fitness += diff;
@ -159,7 +167,7 @@ int main()
constexpr float half_range = range / 2.0; constexpr float half_range = range / 2.0;
auto x = program.get_random().get_float(-half_range, half_range); auto x = program.get_random().get_float(-half_range, half_range);
auto y = example_function(x); auto y = example_function(x);
fitness_case = {move_float(x), move_float(y)}; fitness_case = {x, y};
} }
BLT_DEBUG("Setup Types and Operators"); BLT_DEBUG("Setup Types and Operators");