diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8c27b0..d7f36d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.25)
-project(blt-gp VERSION 0.0.33)
+project(blt-gp VERSION 0.0.34)
+
+include(CTest)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
@@ -36,29 +38,38 @@ if (${ENABLE_TSAN} MATCHES ON)
endif ()
if (${BUILD_EXAMPLES})
- project(blt-gp-example)
+ macro(blt_add_example name source)
- add_executable(blt-gp-example examples/main.cpp examples/gp_test_2.cpp)
+ project(${name}-example)
- target_link_libraries(blt-gp-example PUBLIC BLT blt-gp)
+ add_executable(${name}-example ${source})
- target_compile_options(blt-gp-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
- target_link_options(blt-gp-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
+ target_link_libraries(${name}-example PRIVATE BLT blt-gp)
- if (${ENABLE_ADDRSAN} MATCHES ON)
- target_compile_options(blt-gp-example PRIVATE -fsanitize=address)
- target_link_options(blt-gp-example PRIVATE -fsanitize=address)
- endif ()
+ target_compile_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
+ target_link_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
- if (${ENABLE_UBSAN} MATCHES ON)
- target_compile_options(blt-gp-example PRIVATE -fsanitize=undefined)
- target_link_options(blt-gp-example PRIVATE -fsanitize=undefined)
- endif ()
+ if (${ENABLE_ADDRSAN} MATCHES ON)
+ target_compile_options(${name}-example PRIVATE -fsanitize=address)
+ target_link_options(${name}-example PRIVATE -fsanitize=address)
+ endif ()
- if (${ENABLE_TSAN} MATCHES ON)
- target_compile_options(blt-gp-example PRIVATE -fsanitize=thread)
- target_link_options(blt-gp-example PRIVATE -fsanitize=thread)
- endif ()
+ if (${ENABLE_UBSAN} MATCHES ON)
+ target_compile_options(${name}-example PRIVATE -fsanitize=undefined)
+ target_link_options(${name}-example PRIVATE -fsanitize=undefined)
+ endif ()
+
+ if (${ENABLE_TSAN} MATCHES ON)
+ target_compile_options(${name}-example PRIVATE -fsanitize=thread)
+ target_link_options(${name}-example PRIVATE -fsanitize=thread)
+ endif ()
+
+ add_test(NAME ${name}-test COMMAND ${name}-example)
+
+ project(blt-gp)
+ endmacro()
+
+ blt_add_example(blt-gp1 examples/main.cpp)
+ blt_add_example(blt-gp2 examples/gp_test_2.cpp)
- project(blt-gp)
endif ()
\ No newline at end of file
diff --git a/examples/gp_test_2.cpp b/examples/gp_test_2.cpp
index 894e2ad..9e8fee1 100644
--- a/examples/gp_test_2.cpp
+++ b/examples/gp_test_2.cpp
@@ -16,6 +16,10 @@
* along with this program. If not, see .
*/
#include
+#include
+#include
+#include
+
static constexpr long SEED = 41912;
@@ -27,7 +31,8 @@ blt::gp::operation_t sub([](float a, float b) { return a - b; });
blt::gp::operation_t mul([](float a, float b) { return a * b; });
blt::gp::operation_t pro_div([](float a, float b) { return b == 0 ? 0.0f : a / b; });
blt::gp::operation_t lit([]() {
- static std::uniform_real_distribution dist(-32000, 32000);
+ //static std::uniform_real_distribution dist(-32000, 32000);
+ static std::uniform_real_distribution dist(0.0f, 10.0f);
return dist(program.get_random());
});
@@ -45,5 +50,12 @@ int main()
program.set_operations(std::move(silly));
+ blt::gp::grow_generator_t grow;
+ auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7});
+
+ auto value = tree.get_evaluation_value(nullptr);
+
+ BLT_TRACE(value);
+
return 0;
}
\ No newline at end of file
diff --git a/examples/main.cpp b/examples/main.cpp
index 58cd793..a1fa8fd 100644
--- a/examples/main.cpp
+++ b/examples/main.cpp
@@ -270,7 +270,7 @@ void test()
}
std::cout << process.size() << std::endl;
- std::cout << process.top() << std::endl;
+ std::cout << "Total Results: " << process.top() << std::endl;
}
@@ -326,7 +326,7 @@ namespace blt::gp::detail
blt::gp::stack_allocator alloc;
-int main_old()
+int main()
{
constexpr blt::size_t MAX_ALIGNMENT = 8;
test();
@@ -431,15 +431,15 @@ int main_old()
context hello{5, 10};
alloc.push(1.153f);
- de[0](static_cast(&hello), alloc);
+ de[0](static_cast(&hello), alloc, alloc);
BLT_TRACE("first value: %f", alloc.pop());
- de[1](static_cast(&hello), alloc);
+ de[1](static_cast(&hello), alloc, alloc);
BLT_TRACE("second value: %f", alloc.pop());
alloc.push(1.0f);
alloc.push(52.213f);
- de[2](static_cast(&hello), alloc);
+ de[2](static_cast(&hello), alloc, alloc);
BLT_TRACE("third value: %f", alloc.pop());
//auto* pointer = static_cast(head->metadata.offset);
diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h
index 2981220..18ea465 100644
--- a/include/blt/gp/fwdecl.h
+++ b/include/blt/gp/fwdecl.h
@@ -19,6 +19,8 @@
#ifndef BLT_GP_FWDECL_H
#define BLT_GP_FWDECL_H
+#include
+#include
namespace blt::gp
{
@@ -43,9 +45,15 @@ namespace blt::gp
class full_generator_t;
+ class stack_allocator;
+
namespace detail
{
class operator_storage_test;
+ // context*, read stack, write stack
+ using callable_t = std::function;
+ // to, from
+ using transfer_t = std::function;
}
}
diff --git a/include/blt/gp/operations.h b/include/blt/gp/operations.h
index 9813213..ac7ffd0 100644
--- a/include/blt/gp/operations.h
+++ b/include/blt/gp/operations.h
@@ -29,8 +29,6 @@ namespace blt::gp
{
namespace detail
{
- using callable_t = std::function;
-
template
using remove_cv_ref = std::remove_cv_t>;
@@ -85,19 +83,19 @@ namespace blt::gp
template
inline static constexpr Return exec_sequence_to_indices(Func&& func, stack_allocator& allocator, std::integer_sequence,
- ExtraArgs&& ... args)
+ ExtraArgs&&... args)
{
// expands Args and indices, providing each argument with its index calculating the current argument byte offset
return std::forward(func)(std::forward(args)..., allocator.from(getByteOffset())...);
}
template
- Return operator()(Func&& func, stack_allocator& allocator, ExtraArgs&& ... args)
+ Return operator()(Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
{
constexpr auto seq = std::make_integer_sequence();
- Return ret = exec_sequence_to_indices(std::forward(func), allocator, seq, std::forward(args)...);
- allocator.call_destructors();
- allocator.pop_bytes((stack_allocator::aligned_size() + ...));
+ Return ret = exec_sequence_to_indices(std::forward(func), read_allocator, seq, std::forward(args)...);
+ read_allocator.call_destructors();
+ read_allocator.pop_bytes((stack_allocator::aligned_size() + ...));
return ret;
}
};
@@ -125,18 +123,18 @@ namespace blt::gp
constexpr explicit operation_t(const Functor& functor): func(functor)
{}
- [[nodiscard]] constexpr inline Return operator()(stack_allocator& allocator) const
+ [[nodiscard]] constexpr inline Return operator()(stack_allocator& read_allocator) const
{
if constexpr (sizeof...(Args) == 0)
{
return func();
} else
{
- return call_with()(func, allocator);
+ return call_with()(func, read_allocator);
}
}
- [[nodiscard]] constexpr inline Return operator()(void* context, stack_allocator& allocator) const
+ [[nodiscard]] constexpr inline Return operator()(void* context, stack_allocator& read_allocator) const
{
// should be an impossible state
if constexpr (sizeof...(Args) == 0)
@@ -149,22 +147,22 @@ namespace blt::gp
return func(ctx_ref);
} else
{
- return call_without_first()(func, allocator, ctx_ref);
+ return call_without_first()(func, read_allocator, ctx_ref);
}
}
template
[[nodiscard]] detail::callable_t make_callable() const
{
- return [this](void* context, stack_allocator& values) {
+ return [this](void* context, stack_allocator& read_allocator, stack_allocator& write_allocator) {
if constexpr (detail::is_same_v::type>>)
{
// first arg is context
- values.push(this->operator()(context, values));
+ write_allocator.push(this->operator()(context, read_allocator));
} else
{
// first arg isn't context
- values.push(this->operator()(values));
+ write_allocator.push(this->operator()(read_allocator));
}
};
}
diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h
index 8da47a3..f1b1c37 100644
--- a/include/blt/gp/program.h
+++ b/include/blt/gp/program.h
@@ -63,15 +63,6 @@ namespace blt::gp
explicit gp_operations(type_system& system): system(system)
{}
- template
- void add_non_context_argument(blt::gp::operator_id operator_id)
- {
- if constexpr (!std::is_same_v>)
- {
- argument_types[operator_id].push_back(system.get_type());
- }
- }
-
template
gp_operations& add_operator(const operation_t& op, bool is_static = false)
{
@@ -96,12 +87,24 @@ namespace blt::gp
operator_argc[operator_id] = argc;
operators.push_back(op.template make_callable());
+ transfer_funcs.push_back([](stack_allocator& to, stack_allocator& from) {
+ to.push(from.pop());
+ });
if (is_static)
static_types.insert(operator_id);
return *this;
}
private:
+ template
+ void add_non_context_argument(blt::gp::operator_id operator_id)
+ {
+ if constexpr (!std::is_same_v>)
+ {
+ argument_types[operator_id].push_back(system.get_type());
+ }
+ }
+
type_system& system;
// indexed from return TYPE ID, returns index of operator
@@ -112,6 +115,7 @@ namespace blt::gp
blt::expanding_buffer operator_argc;
blt::hashset_t static_types;
std::vector operators;
+ std::vector transfer_funcs;
};
class gp_program
@@ -194,6 +198,11 @@ namespace blt::gp
return operators[id];
}
+ inline detail::transfer_t& get_transfer_func(operator_id id)
+ {
+ return transfer_funcs[id];
+ }
+
inline bool is_static(operator_id id)
{
return static_types.contains(static_cast(id));
@@ -208,6 +217,7 @@ namespace blt::gp
static_types = std::move(op.static_types);
operator_argc = std::move(op.operator_argc);
operators = std::move(op.operators);
+ transfer_funcs = std::move(op.transfer_funcs);
}
private:
@@ -223,6 +233,7 @@ namespace blt::gp
blt::expanding_buffer operator_argc;
blt::hashset_t static_types;
std::vector operators;
+ std::vector transfer_funcs;
};
}
diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h
index 94b899d..9e5762f 100644
--- a/include/blt/gp/stack.h
+++ b/include/blt/gp/stack.h
@@ -20,6 +20,7 @@
#define BLT_GP_STACK_H
#include
+#include
#include
#include
#include
@@ -110,9 +111,16 @@ namespace blt::gp
if (diff <= 0)
{
bytes -= head->used_bytes_in_block();
+ auto old = head;
head = head->metadata.prev;
- } else // otherwise update the offset pointer
+ free(old);
+ if (diff == 0)
+ break;
+ } else {
+ // otherwise update the offset pointer
head->metadata.offset -= bytes;
+ break;
+ }
}
}
@@ -143,6 +151,9 @@ namespace blt::gp
stack_allocator(const stack_allocator& copy)
{
+ if (copy.empty())
+ return;
+
head = nullptr;
block* list_itr = nullptr;
@@ -158,6 +169,8 @@ namespace blt::gp
{
push_block(list_itr->metadata.size);
std::memcpy(head->buffer, list_itr->buffer, list_itr->storage_size());
+ head->metadata.size = list_itr->metadata.size;
+ head->metadata.offset = head->buffer + list_itr->used_bytes_in_block();
list_itr = list_itr->metadata.next;
}
}
diff --git a/lib/blt b/lib/blt
index 2a34be2..3426c5d 160000
--- a/lib/blt
+++ b/lib/blt
@@ -1 +1 @@
-Subproject commit 2a34be2e7b452aa623b9043b7decf83c2e367cc7
+Subproject commit 3426c5d2ad982eb7d04f20d877085e4aae4001a3
diff --git a/src/generators.cpp b/src/generators.cpp
index 59c5f87..a6ec198 100644
--- a/src/generators.cpp
+++ b/src/generators.cpp
@@ -17,6 +17,7 @@
*/
#include
#include
+#include
#include
namespace blt::gp
@@ -61,16 +62,17 @@ namespace blt::gp
tree.get_operations().emplace_back(
args.program.get_operation(top.id),
- static_cast(top.depth),
- args.program.is_static(top.id),
- static_cast(args.program.get_argc(top.id).argc),
- static_cast(args.program.get_argc(top.id).argc_context)
+ args.program.get_transfer_func(top.id),
+ //static_cast(top.depth),
+ args.program.is_static(top.id)
+ //static_cast(args.program.get_argc(top.id).argc),
+ //static_cast(args.program.get_argc(top.id).argc_context)
);
max_depth = std::max(max_depth, top.depth);
if (args.program.is_static(top.id))
{
- args.program.get_operation(top.id)(nullptr, tree.get_values());
+ args.program.get_operation(top.id)(nullptr, tree.get_values(), tree.get_values());
continue;
}
diff --git a/src/tree.cpp b/src/tree.cpp
index 54b3408..477a7c6 100644
--- a/src/tree.cpp
+++ b/src/tree.cpp
@@ -16,17 +16,38 @@
* along with this program. If not, see .
*/
#include
+#include
+#include
+#include
namespace blt::gp
{
+ inline auto empty_callable = detail::callable_t([](void*, stack_allocator&, stack_allocator&) { BLT_ABORT("This should never be called!"); });
+
evaluation_context tree_t::evaluate(void* context)
{
- evaluation_context results {values};
+ // copy the initial values
+ evaluation_context results{};
- auto& value_stack = results.values;
- std::stack operations_stack;
+ auto value_stack = values;
+ auto& values_process = results.values;
+ auto operations_stack = operations;
+ while (!operations_stack.empty())
+ {
+ auto operation = operations_stack.back();
+ // keep the last value in the stack on the process stack stored in the eval context, this way it can be accessed easily.
+ operations_stack.pop_back();
+ if (operation.is_value)
+ {
+ operation.transfer(values_process, value_stack);
+ continue;
+ }
+ operation.func(context, values_process, value_stack);
+ operations_stack.emplace_back(empty_callable, operation.transfer, true);
+ }
+ BLT_TRACE("Bytes Left: %ld | %ld", values_process.bytes_in_head(), value_stack.bytes_in_head());
return results;
}