From e390cd262d6c47af4db5bea50a291384c3f0fcd5 Mon Sep 17 00:00:00 2001 From: Brett Date: Sun, 13 Jul 2025 14:21:52 -0400 Subject: [PATCH] weird complexity --- include/gp_system.h | 2 +- include/image_storage.h | 32 +++++++++--- src/gp_system.cpp | 108 ++++++++++++++++++++++------------------ src/image_storage.cpp | 6 +++ src/main.cpp | 21 +------- 5 files changed, 94 insertions(+), 75 deletions(-) diff --git a/include/gp_system.h b/include/gp_system.h index e3a42ee..0646a3d 100644 --- a/include/gp_system.h +++ b/include/gp_system.h @@ -35,7 +35,7 @@ void regenerate_image(blt::size_t index, float& image_storage, blt::i32 width, b void set_population_size(blt::u32 size); -std::array& get_image(blt::size_t index); +std::array& get_image(blt::size_t index); void cleanup(); diff --git a/include/image_storage.h b/include/image_storage.h index aeaedff..90163d1 100644 --- a/include/image_storage.h +++ b/include/image_storage.h @@ -28,6 +28,7 @@ #include using image_pixel_t = float; +using image_ipixel_t = blt::u32; constexpr blt::i32 IMAGE_DIMENSIONS = 256; constexpr blt::i32 IMAGE_CHANNELS = 1; @@ -54,6 +55,25 @@ struct image_storage_t void normalize(); }; +struct image_istorage_t +{ + std::array data; + + static std::array from_file(const std::string& path); + + image_ipixel_t& get(const blt::size_t x, const blt::size_t y) + { + return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS]; + } + + [[nodiscard]] const image_ipixel_t& get(const blt::size_t x, const blt::size_t y) const + { + return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS]; + } + + void normalize(); +}; + inline std::atomic_uint64_t g_allocated_blocks = 0; inline std::atomic_uint64_t g_deallocated_blocks = 0; @@ -67,7 +87,7 @@ struct image_cleaner_t delete v; } - std::vector images; + std::vector images; }; inline image_cleaner_t g_image_list; @@ -76,7 +96,7 @@ struct image_t { explicit image_t() { - image_storage_t* front = nullptr; + image_istorage_t* front = nullptr; { std::scoped_lock lock(g_image_list_mutex); if (!g_image_list.images.empty()) @@ -88,7 +108,7 @@ struct image_t if (front) data = front; else - data = new image_storage_t; + data = new image_istorage_t{}; ++g_allocated_blocks; } @@ -125,18 +145,18 @@ struct image_t friend image_t operator/(const image_t& lhs, const image_t& rhs); - image_storage_t& get_data() + image_istorage_t& get_data() { return *data; } - [[nodiscard]] const image_storage_t& get_data() const + [[nodiscard]] const image_istorage_t& get_data() const { return *data; } private: - image_storage_t* data; + image_istorage_t* data; }; #endif //IMAGE_STORAGE_H diff --git a/src/gp_system.cpp b/src/gp_system.cpp index 212eccb..d77a314 100644 --- a/src/gp_system.cpp +++ b/src/gp_system.cpp @@ -40,7 +40,7 @@ float filter_nan(const float f, const float failure = 0.0f) std::array programs; prog_config_t config{}; -std::vector> images; +std::vector> images; auto reference_image = image_storage_t::from_file("../silly.png"); std::vector average_fitness; @@ -52,7 +52,7 @@ template void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t index) { auto image = tree.get_evaluation_ref(); - image->normalize(); + // image->normalize(); // std::memcpy(images[index].data.data(), image->get_data().data.data(), IMAGE_SIZE_BYTES); auto& data = image->get_data(); @@ -64,117 +64,127 @@ void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t inde auto multiplier = (1 - std::abs((static_cast(x) / (static_cast(IMAGE_DIMENSIONS) / 2)) - 1)) + (1 - std::abs( (static_cast(y) / (static_cast(IMAGE_DIMENSIONS) / 2)) - 1)); - auto our = data.get(x, y); - auto our2 = blt::mem::type_cast(our); - auto our3 = static_cast(our2) / static_cast(std::numeric_limits::max()); + + auto our3 = static_cast(data.get(x, y)) / static_cast(std::numeric_limits::max()); + + auto theirs = reference_image[Channel].get(x, y); - const auto diff = std::pow(our3, 1.0f/2.2f) - std::pow(theirs, 1.0f/2.2f); - fitness.raw_fitness += static_cast(diff * multiplier); + const auto diff = std::pow(our3, 2.2f) - std::pow(theirs, 2.2f); + if (std::isnan(diff)) + { + if (std::isnan(our3)) + BLT_DEBUG("Our is nan"); + if (std::isnan(theirs)) + BLT_DEBUG("Theirs is nan"); + BLT_TRACE("We got {} vs {}", our3, theirs); + continue; + } + fitness.raw_fitness += static_cast(diff); } } // fitness.raw_fitness /= static_cast(IMAGE_SIZE_CHANNELS); - fitness.raw_fitness = static_cast(std::sqrt(fitness.raw_fitness)); + // fitness.raw_fitness = static_cast(std::sqrt(fitness.raw_fitness)); fitness.standardized_fitness = fitness.raw_fitness; - fitness.adjusted_fitness = 1 - 1 / (1 + fitness.standardized_fitness); + fitness.adjusted_fitness = -fitness.standardized_fitness; } template void setup_operations(gp_program* program) { static operation_t op_image_x([]() { + constexpr auto mul = std::numeric_limits::max() - static_cast(IMAGE_DIMENSIONS - 1); image_t ret{}; - for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x) + for (blt::u32 x = 0; x < IMAGE_DIMENSIONS; ++x) { - for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y) - ret.get_data().get(x, y) = static_cast(x) / static_cast(IMAGE_DIMENSIONS - 1); + for (blt::u32 y = 0; y < IMAGE_DIMENSIONS; ++y) + ret.get_data().get(x, y) = x * mul; } return ret; }); static operation_t op_image_y([]() { + constexpr auto mul = std::numeric_limits::max() - static_cast(IMAGE_DIMENSIONS - 1); image_t ret{}; - for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x) + for (blt::u32 x = 0; x < IMAGE_DIMENSIONS; ++x) { - for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y) - ret.get_data().get(x, y) = static_cast(y) / static_cast(IMAGE_DIMENSIONS - 1); + for (blt::u32 y = 0; y < IMAGE_DIMENSIONS; ++y) + ret.get_data().get(x, y) = y * mul; } return ret; }); static auto op_image_noise = operation_t([program]() { image_t ret{}; for (auto& v : ret.get_data().data) - v = program->get_random().get_float(0, 1.0f); + v = program->get_random().get_u32(0, std::numeric_limits::max()); return ret; }).set_ephemeral(); static auto op_image_ephemeral = operation_t([program]() { image_t ret{}; - const auto value = program->get_random().get_float(); + const auto value = program->get_random().get_u32(0, std::numeric_limits::max()); for (auto& v : ret.get_data().data) v = value; return ret; }).set_ephemeral(); - static operation_t op_image_blend([](const image_t a, const image_t b, const float f) { - const auto blend = std::min(std::max(f, 0.0f), 1.0f); - const auto beta = 1.0f - blend; - image_t ret{}; - const cv::Mat src1{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, a.as_void_const()}; - const cv::Mat src2{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, b.as_void_const()}; - cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, ret.get_data().data.data()}; - addWeighted(src1, blend, src2, beta, 0.0, dst); - return ret; - }, "blend_image"); + // static operation_t op_image_blend([](const image_t a, const image_t b, const float f) { + // const auto blend = std::min(std::max(f, 0.0f), 1.0f); + // const auto beta = 1.0f - blend; + // image_t ret{}; + // const cv::Mat src1{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, a.as_void_const()}; + // const cv::Mat src2{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, b.as_void_const()}; + // cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, ret.get_data().data.data()}; + // addWeighted(src1, blend, src2, beta, 0.0, dst); + // return ret; + // }, "blend_image"); static operation_t op_image_sin([](const image_t a) { image_t ret{}; for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) - ret.get_data().data[i] = filter_nan(std::sin(v)); + ret.get_data().data[i] = blt::mem::type_cast(static_cast(std::sin(v))); return ret; }, "sin_image"); static operation_t op_image_cos([](const image_t a) { image_t ret{}; for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) - ret.get_data().data[i] = filter_nan(std::cos(v)); + ret.get_data().data[i] = blt::mem::type_cast(static_cast(std::cos(v))); return ret; }, "cos_image"); static operation_t op_image_log([](const image_t a) { image_t ret{}; for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) { - if (blt::f_equal(v, 0)) + if (v == 0) ret.get_data().data[i] = 0; - else if (v < 0) - ret.get_data().data[i] = -filter_nan(std::log(-v)); else - ret.get_data().data[i] = filter_nan(std::log(v)); + ret.get_data().data[i] = blt::mem::type_cast(static_cast(std::log(v))); } return ret; }, "log_image"); static operation_t op_image_exp([](const image_t a) { image_t ret{}; for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) - ret.get_data().data[i] = filter_nan(std::exp(v)); + ret.get_data().data[i] = blt::mem::type_cast(static_cast(std::exp(v))); return ret; }, "exp_image"); static operation_t op_image_or([](const image_t a, const image_t b) { image_t ret{}; for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten()) - ret.get_data().data[i] = blt::mem::type_cast(blt::mem::type_cast(av) | blt::mem::type_cast(bv)); + ret.get_data().data[i] = av | bv; return ret; }, "bit_or_image"); static operation_t op_image_and([](const image_t a, const image_t b) { image_t ret{}; for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten()) - ret.get_data().data[i] = blt::mem::type_cast(blt::mem::type_cast(av) & blt::mem::type_cast(bv)); + ret.get_data().data[i] = av & bv; return ret; }, "bit_and_image"); static operation_t op_image_xor([](const image_t a, const image_t b) { image_t ret{}; for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten()) - ret.get_data().data[i] = blt::mem::type_cast(blt::mem::type_cast(av) ^ blt::mem::type_cast(bv)); + ret.get_data().data[i] = av ^ bv; return ret; }, "bit_xor_image"); - static operation_t op_image_not([](const image_t a, const image_t b) { + static operation_t op_image_not([](const image_t a) { image_t ret{}; - for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten()) - ret.get_data().data[i] = blt::mem::type_cast(~blt::mem::type_cast(av)); + for (const auto& [i, av] : blt::enumerate(std::as_const(a.get_data().data)).flatten()) + ret.get_data().data[i] = ~av; return ret; }, "bit_not_image"); static operation_t op_image_gt([](const image_t a, const image_t b) { @@ -193,16 +203,18 @@ void setup_operations(gp_program* program) const float octaves) { image_t ret{}; for (const auto& [i, out] : blt::enumerate(ret.get_data().data)) - out = stb_perlin_ridge_noise3(static_cast(i % IMAGE_DIMENSIONS) + ofx, static_cast(i / IMAGE_DIMENSIONS) + ofy, ofz, - lacunarity + 2, gain + 0.5f, 1.0f, static_cast(octaves)); + out = blt::mem::type_cast(stb_perlin_ridge_noise3(static_cast(i % IMAGE_DIMENSIONS) + ofx, + static_cast(i / IMAGE_DIMENSIONS) + ofy, ofz, lacunarity + 2, + gain + 0.5f, 1.0f, static_cast(octaves))); return ret; }, "perlin_image"); static operation_t op_image_perlin_bounded([](float octaves) { octaves = std::min(std::max(octaves, 4.0f), 8.0f); image_t ret{}; for (const auto& [i, out] : blt::enumerate(ret.get_data().data)) - out = stb_perlin_fbm_noise3(static_cast(i % IMAGE_DIMENSIONS) + 0.23423f, static_cast(i / IMAGE_DIMENSIONS) + 0.6234f, - 0.4861f, 2, 0.5, static_cast(octaves)); + out = blt::mem::type_cast(stb_perlin_fbm_noise3(static_cast(i % IMAGE_DIMENSIONS) + 0.23423f, + static_cast(i) / IMAGE_DIMENSIONS + 0.6234f, 0.4861f, 2, 0.5, + static_cast(octaves))); return ret; }, "perlin_image_bounded"); static operation_t op_sin([](const float a) { @@ -228,7 +240,7 @@ void setup_operations(gp_program* program) operator_builder builder{}; builder.build(op_image_ephemeral, make_add(), make_sub(), make_mul(), make_div(), op_image_x, op_image_y, op_image_sin, op_image_gt, op_image_lt, op_image_cos, op_image_log, op_image_exp, op_image_or, op_image_and, op_image_xor, - op_image_not, op_image_perlin_bounded, op_image_blend, make_add(), make_sub(), make_mul(), + op_image_not, op_image_perlin_bounded, make_add(), make_sub(), make_mul(), make_prot_div(), op_sin, op_cos, op_exp, op_log, lit); program->set_operations(builder.grab()); } @@ -309,7 +321,7 @@ bool should_terminate() return programs[0]->should_terminate() || programs[1]->should_terminate() || programs[2]->should_terminate(); } -std::array& get_image(const blt::size_t index) +std::array& get_image(const blt::size_t index) { return images[index]; } @@ -362,9 +374,7 @@ void reset_programs() } void regenerate_image(blt::size_t index, float& image_storage, blt::i32 width, blt::i32 height) -{ - -} +{} std::tuple&, const std::vector&, const std::vector&, const std::vector&> get_fitness_history() { diff --git a/src/image_storage.cpp b/src/image_storage.cpp index 627d088..7a076ec 100644 --- a/src/image_storage.cpp +++ b/src/image_storage.cpp @@ -48,6 +48,12 @@ std::array image_storage_t::from_file(const std::string& pat return {storage_r, storage_g, storage_b}; } +std::array image_istorage_t::from_file(const std::string& path) +{} + +void image_istorage_t::normalize() +{} + void image_storage_t::normalize() { float min = std::numeric_limits::max(); diff --git a/src/main.cpp b/src/main.cpp index d6169ef..ef24b47 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -191,7 +191,7 @@ void update(const blt::gfx::window_data& data) if (ImGui::BeginTabItem("Reference")) { - auto w = data.width; + blt::f32 w = data.width; auto h = data.height - top_bar_height - 10; renderer_2d.drawRectangle({static_cast(w / 2), h / 2, w, h}, "reference"); ImGui::EndTabItem(); @@ -241,24 +241,7 @@ void update(const blt::gfx::window_data& data) for (blt::size_t i = 0; i < population_size; i++) { - auto& image = get_image(i); - float min = std::numeric_limits::max(); - float max = std::numeric_limits::min(); - - for (auto& pixel : image) - { - if (std::isnan(pixel) || std::isinf(pixel)) - pixel = 0; - if (pixel > max) - max = pixel; - if (pixel < min) - min = pixel; - } - - for (auto& pixel : image) - pixel = (pixel - min) / (max - min); - - gl_images[i]->upload(get_image(i).data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGB, GL_FLOAT); + gl_images[i]->upload(get_image(i).data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGB, GL_UNSIGNED_INT); } if ((blt::gfx::isMousePressed(0) && blt::gfx::mousePressedLastFrame() && !clicked_on_image) || (blt::gfx::isKeyPressed(GLFW_KEY_ESCAPE) && blt::gfx::keyPressedLastFrame()))