From dda8e7ca616bb0639b90d30b4cf59f0e4cb9aa98 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Sat, 7 Sep 2024 16:29:00 +0200 Subject: [PATCH] Support 3 digit-range configs maybe more later --- MandelbrotDiscovery/mandelbrot_discovery.cpp | 61 +++- MandelbrotDiscovery/mandelbrot_discovery.h | 307 +++++++++++++++---- MandelbrotDiscovery/utility.h | 27 +- 3 files changed, 319 insertions(+), 76 deletions(-) diff --git a/MandelbrotDiscovery/mandelbrot_discovery.cpp b/MandelbrotDiscovery/mandelbrot_discovery.cpp index f8655ad..6b2191a 100644 --- a/MandelbrotDiscovery/mandelbrot_discovery.cpp +++ b/MandelbrotDiscovery/mandelbrot_discovery.cpp @@ -45,12 +45,23 @@ template auto center_y() -> typename local::cfg_type using rectangle_from_digits_type = geometry::rectangle_type::mandelbrot_coord_pnt_type>>; -constexpr inline auto default_digits10() -> unsigned { return 132U; } +constexpr inline auto default_00_digits10() -> unsigned { return unsigned { UINT32_C( 44) }; } // For magnification <= 20 +constexpr inline auto default_01_digits10() -> unsigned { return unsigned { UINT32_C(104) }; } // For magnification <= 80 +constexpr inline auto default_02_digits10() -> unsigned { return unsigned { UINT32_C(536) }; } // For magnification <= 512 + +using rectangle_00_type = rectangle_from_digits_type; +using rectangle_01_type = rectangle_from_digits_type; +using rectangle_02_type = rectangle_from_digits_type; + +using rectangle_tuple_type = std::tuple; -using rectangle_tuple_type = std::tuple&>; using rectangle_ref_00_type = typename std::tuple_element<0, rectangle_tuple_type>::type; -using rectangle_00_type = typename std::remove_reference::type; -using point_type = typename rectangle_00_type::point_type; +using rectangle_ref_01_type = typename std::tuple_element<1, rectangle_tuple_type>::type; +using rectangle_ref_02_type = typename std::tuple_element<2, rectangle_tuple_type>::type; + +using point_00_type = typename rectangle_00_type::point_type; +using point_01_type = typename rectangle_01_type::point_type; +using point_02_type = typename rectangle_02_type::point_type; using local_window_type = mandelbrot_discovery(INT16_C(800)), static_cast(INT16_C(800)), @@ -58,13 +69,45 @@ using local_window_type = mandelbrot_discovery(INT16_C(800)), mandelbrot_discovery_detail::WindowTitleDefault, IDI_MANDELBROT_DISCO>; -auto rectangle() -> rectangle_00_type& +auto rectangle_00() -> rectangle_00_type& { static rectangle_00_type my_rect { - point_type { center_x(), center_y() }, - dx_half(), - dy_half() + point_00_type { center_x(), center_y() }, + dx_half(), + dy_half() + }; + + static const bool result_pixel_assoc_is_ok { my_rect.set_pixel_assoc(768, 768) }; + + static_cast(result_pixel_assoc_is_ok); + + return my_rect; +} + +auto rectangle_01() -> rectangle_01_type& +{ + static rectangle_01_type my_rect + { + point_01_type { center_x(), center_y() }, + dx_half(), + dy_half() + }; + + static const bool result_pixel_assoc_is_ok { my_rect.set_pixel_assoc(768, 768) }; + + static_cast(result_pixel_assoc_is_ok); + + return my_rect; +} + +auto rectangle_02() -> rectangle_02_type& +{ + static rectangle_02_type my_rect + { + point_02_type { center_x(), center_y() }, + dx_half(), + dy_half() }; static const bool result_pixel_assoc_is_ok { my_rect.set_pixel_assoc(768, 768) }; @@ -76,7 +119,7 @@ auto rectangle() -> rectangle_00_type& auto WINAPI WinMain(_In_ ::HINSTANCE h_wnd, _In_opt_ ::HINSTANCE, _In_ LPSTR, _In_ int) -> int { - rectangle_tuple_type rectangle_tuple(rectangle()); + rectangle_tuple_type rectangle_tuple(rectangle_00(), rectangle_01(), rectangle_02()); local_window_type::set_rectangle_tuple(rectangle_tuple); diff --git a/MandelbrotDiscovery/mandelbrot_discovery.h b/MandelbrotDiscovery/mandelbrot_discovery.h index 659aa48..626f0f5 100644 --- a/MandelbrotDiscovery/mandelbrot_discovery.h +++ b/MandelbrotDiscovery/mandelbrot_discovery.h @@ -18,6 +18,7 @@ #include #include + #include #include #include @@ -54,9 +55,13 @@ public: using rectangle_tuple_type = MandelbrotRectangleTupleType; using rectangle_00_type = typename std::remove_reference::type>::type; + using rectangle_01_type = typename std::remove_reference::type>::type; + using rectangle_02_type = typename std::remove_reference::type>::type; private: using value_00_type = typename rectangle_00_type::point_type::value_type; + using value_01_type = typename rectangle_01_type::point_type::value_type; + using value_02_type = typename rectangle_02_type::point_type::value_type; static constexpr int screen_coordinate_x = static_cast(ScreenCoordinateX); // Screen coordinate X static constexpr int screen_coordinate_y = static_cast(ScreenCoordinateY); // Screen coordinate Y @@ -69,6 +74,8 @@ public: using point_00_type = typename rectangle_00_type::point_type; + using point_01_type = typename rectangle_01_type::point_type; + using point_02_type = typename rectangle_02_type::point_type; using rectangle_tuple_ref_type = std::reference_wrapper; mandelbrot_discovery() = default; @@ -266,14 +273,18 @@ ::HWND my_handle_to_window { nullptr }; ::HINSTANCE my_handle_to_instance { nullptr }; - static point_00_type my_rectangle_center; + static point_00_type my_rectangle_center_00; + static point_01_type my_rectangle_center_01; + static point_02_type my_rectangle_center_02; static rectangle_tuple_ref_type my_ref_to_rectangle_tuple; static std::thread my_thread; static std::atomic my_thread_wants_exit; static std::atomic my_thread_did_exit; static std::atomic my_thread_wait_for_new_set_click; - static value_00_type my_mandelbrot_zoom_factor; + static value_00_type my_mandelbrot_zoom_factor_00; + static value_01_type my_mandelbrot_zoom_factor_01; + static value_02_type my_mandelbrot_zoom_factor_02; static std::uint_fast32_t my_mandelbrot_iterations; static constexpr auto window_title() noexcept -> const char* { return WindowTitle; } @@ -300,35 +311,18 @@ return my_thread_wait_for_new_set_click.load(); } - static auto mandelbrot_iterate_engine() -> void - { - constexpr auto MANDELBROT_CALCULATION_PIXELS_X = static_cast(768); - constexpr auto MANDELBROT_CALCULATION_PIXELS_Y = static_cast(768); - - using mandelbrot_generator_type = - ckormanyos::mandelbrot::mandelbrot_generator_trivial; - - ckormanyos::mandelbrot::color::color_stretch_histogram_method local_color_stretches; - const ckormanyos::mandelbrot::color::color_functions_bw local_color_functions; + static auto zoom_factor_p10() -> int { return ilogb(my_mandelbrot_zoom_factor_02); }; - using local_mandelbrot_config_type = - ckormanyos::mandelbrot::mandelbrot_config(MANDELBROT_CALCULATION_PIXELS_X), - static_cast(MANDELBROT_CALCULATION_PIXELS_Y)>; - - const local_mandelbrot_config_type - mandelbrot_config_object - ( - std::get<0>(my_ref_to_rectangle_tuple.get()).center().get_x() - std::get<0>(my_ref_to_rectangle_tuple.get()).dx_half(), - std::get<0>(my_ref_to_rectangle_tuple.get()).center().get_x() + std::get<0>(my_ref_to_rectangle_tuple.get()).dx_half(), - std::get<0>(my_ref_to_rectangle_tuple.get()).center().get_y() - std::get<0>(my_ref_to_rectangle_tuple.get()).dy_half(), - std::get<0>(my_ref_to_rectangle_tuple.get()).center().get_y() + std::get<0>(my_ref_to_rectangle_tuple.get()).dy_half(), - my_mandelbrot_iterations - ); + static auto rectangle_tuple_index() -> int + { + const int zoom { zoom_factor_p10() }; - mandelbrot_generator_type mandelbrot_generator(mandelbrot_config_object); + return ((zoom <= 20) ? 0 : (zoom <= 80) ? 1 : 2); + }; + template + static auto mandelbrot_iterate_engine_worker(MandelbrotGeneratorType& mandelbrot_generator) -> void + { util::text::text_output_alloc_console text_out(mandelbrot_discovery::write_string); using stopwatch_type = ::stopwatch; @@ -338,6 +332,9 @@ // Generate the Mandelbrot image. Note: The filename suffix // will be provided by the interface. + ckormanyos::mandelbrot::color::color_stretch_histogram_method local_color_stretches; + const ckormanyos::mandelbrot::color::color_functions_bw local_color_functions; + mandelbrot_generator.generate_mandelbrot_image("mandelbrot_zooming", local_color_functions, local_color_stretches, @@ -358,13 +355,107 @@ }() }; - const auto zoom_factor_p10 = ilogb(my_mandelbrot_zoom_factor); - - write_string("mandelbrot_zoom: " + std::to_string(zoom_factor_p10) + "\n"); + write_string("mandelbrot_zoom: " + std::to_string(zoom_factor_p10()) + "\n"); write_string("mandelbrot_iter: " + std::to_string(my_mandelbrot_iterations) + "\n"); write_string("iteration_time : " + str_iteration_time + "s\n\n"); } + static auto mandelbrot_iterate_engine_00() -> void + { + constexpr auto MANDELBROT_CALCULATION_PIXELS_X = static_cast(768); + constexpr auto MANDELBROT_CALCULATION_PIXELS_Y = static_cast(768); + + using mandelbrot_generator_00_type = + ckormanyos::mandelbrot::mandelbrot_generator_trivial; + + using local_mandelbrot_config_00_type = + ckormanyos::mandelbrot::mandelbrot_config(MANDELBROT_CALCULATION_PIXELS_X), + static_cast(MANDELBROT_CALCULATION_PIXELS_Y)>; + + const rectangle_00_type& local_rectangle_00_ref { std::get<0>(my_ref_to_rectangle_tuple.get()) }; + + local_mandelbrot_config_00_type + mandelbrot_config_object_00 + ( + local_rectangle_00_ref.center().get_x() - local_rectangle_00_ref.dx_half(), + local_rectangle_00_ref.center().get_x() + local_rectangle_00_ref.dx_half(), + local_rectangle_00_ref.center().get_y() - local_rectangle_00_ref.dy_half(), + local_rectangle_00_ref.center().get_y() + local_rectangle_00_ref.dy_half(), + my_mandelbrot_iterations + ); + + mandelbrot_generator_00_type gen_00 { mandelbrot_config_object_00 }; + + mandelbrot_iterate_engine_worker(gen_00); + } + + static auto mandelbrot_iterate_engine_01() -> void + { + constexpr auto MANDELBROT_CALCULATION_PIXELS_X = static_cast(768); + constexpr auto MANDELBROT_CALCULATION_PIXELS_Y = static_cast(768); + + using mandelbrot_generator_01_type = + ckormanyos::mandelbrot::mandelbrot_generator_trivial; + + using local_mandelbrot_config_01_type = + ckormanyos::mandelbrot::mandelbrot_config(MANDELBROT_CALCULATION_PIXELS_X), + static_cast(MANDELBROT_CALCULATION_PIXELS_Y)>; + + const rectangle_01_type& local_rectangle_01_ref { std::get<1>(my_ref_to_rectangle_tuple.get()) }; + + local_mandelbrot_config_01_type + mandelbrot_config_object_01 + ( + local_rectangle_01_ref.center().get_x() - local_rectangle_01_ref.dx_half(), + local_rectangle_01_ref.center().get_x() + local_rectangle_01_ref.dx_half(), + local_rectangle_01_ref.center().get_y() - local_rectangle_01_ref.dy_half(), + local_rectangle_01_ref.center().get_y() + local_rectangle_01_ref.dy_half(), + my_mandelbrot_iterations + ); + + mandelbrot_generator_01_type gen_01 { mandelbrot_config_object_01 }; + + mandelbrot_iterate_engine_worker(gen_01); + } + + static auto mandelbrot_iterate_engine_02() -> void + { + constexpr auto MANDELBROT_CALCULATION_PIXELS_X = static_cast(768); + constexpr auto MANDELBROT_CALCULATION_PIXELS_Y = static_cast(768); + + using mandelbrot_generator_02_type = + ckormanyos::mandelbrot::mandelbrot_generator_perturbative; + + ckormanyos::mandelbrot::color::color_stretch_histogram_method local_color_stretches; + const ckormanyos::mandelbrot::color::color_functions_bw local_color_functions; + + using local_mandelbrot_config_02_type = + ckormanyos::mandelbrot::mandelbrot_config(MANDELBROT_CALCULATION_PIXELS_X), + static_cast(MANDELBROT_CALCULATION_PIXELS_Y)>; + + const rectangle_02_type& local_rectangle_02_ref { std::get<2>(my_ref_to_rectangle_tuple.get()) }; + + local_mandelbrot_config_02_type + mandelbrot_config_object_02 + ( + local_rectangle_02_ref.center().get_x() - local_rectangle_02_ref.dx_half(), + local_rectangle_02_ref.center().get_x() + local_rectangle_02_ref.dx_half(), + local_rectangle_02_ref.center().get_y() - local_rectangle_02_ref.dy_half(), + local_rectangle_02_ref.center().get_y() + local_rectangle_02_ref.dy_half(), + my_mandelbrot_iterations + ); + + mandelbrot_generator_02_type gen_02 { mandelbrot_config_object_02 }; + + mandelbrot_iterate_engine_worker(gen_02); + } + static auto CALLBACK my_window_callback(::HWND handle_to_window, ::UINT message, ::WPARAM w_param, @@ -383,8 +474,8 @@ { load_jpeg_image ( - (my_mandelbrot_zoom_factor > 1) ? L"mandelbrot_zooming.jpg" - : L"mandelbrot_MANDELBROT_01_FULL.jpg" + (my_mandelbrot_zoom_factor_00 > 1) ? L"mandelbrot_zooming.jpg" + : L"mandelbrot_MANDELBROT_01_FULL.jpg" ) }; @@ -455,14 +546,38 @@ static_cast(static_cast<::WORD>(static_cast<::DWORD>(l_param) >> static_cast(UINT8_C(16)))) }; - auto result_is_ok = std::get<0>(my_ref_to_rectangle_tuple.get()).pixel_to_point(pixel_x, pixel_y, my_rectangle_center); + bool result_is_ok { true }; + + result_is_ok = { std::get<0>(my_ref_to_rectangle_tuple.get()).pixel_to_point(pixel_x, pixel_y, my_rectangle_center_00) && result_is_ok }; + result_is_ok = { std::get<1>(my_ref_to_rectangle_tuple.get()).pixel_to_point(pixel_x, pixel_y, my_rectangle_center_01) && result_is_ok }; + result_is_ok = { std::get<2>(my_ref_to_rectangle_tuple.get()).pixel_to_point(pixel_x, pixel_y, my_rectangle_center_02) && result_is_ok }; if(result_is_ok) { - result_is_ok = (write_number("x_val : ", my_rectangle_center.get_x()) && result_is_ok); - result_is_ok = (write_number("y_val : ", my_rectangle_center.get_y()) && result_is_ok); - result_is_ok = (write_number("dx_half: ", std::get<0>(my_ref_to_rectangle_tuple.get()).dx_half(), 3) && result_is_ok); - result_is_ok = (write_string("\n") && result_is_ok); + switch(rectangle_tuple_index()) + { + case 0: + result_is_ok = (write_number("x_val : ", my_rectangle_center_00.get_x()) && result_is_ok); + result_is_ok = (write_number("y_val : ", my_rectangle_center_00.get_y()) && result_is_ok); + result_is_ok = (write_number("dx_half: ", std::get<0>(my_ref_to_rectangle_tuple.get()).dx_half(), 3) && result_is_ok); + result_is_ok = (write_string("\n") && result_is_ok); + break; + + case 1: + result_is_ok = (write_number("x_val : ", my_rectangle_center_01.get_x()) && result_is_ok); + result_is_ok = (write_number("y_val : ", my_rectangle_center_01.get_y()) && result_is_ok); + result_is_ok = (write_number("dx_half: ", std::get<1>(my_ref_to_rectangle_tuple.get()).dx_half(), 3) && result_is_ok); + result_is_ok = (write_string("\n") && result_is_ok); + break; + + case 2: + default: + result_is_ok = (write_number("x_val : ", my_rectangle_center_02.get_x()) && result_is_ok); + result_is_ok = (write_number("y_val : ", my_rectangle_center_02.get_y()) && result_is_ok); + result_is_ok = (write_number("dx_half: ", std::get<2>(my_ref_to_rectangle_tuple.get()).dx_half(), 3) && result_is_ok); + result_is_ok = (write_string("\n") && result_is_ok); + break; + } } const auto lresult = @@ -562,12 +677,24 @@ } else if(str_cmd == "calc") { - // Rescale and re-center the rectangle. - std::get<0>(my_ref_to_rectangle_tuple.get()) /= 10; + // Rescale and re-center the rectangles. + + util::caller::for_each_in_tuple + ( + my_ref_to_rectangle_tuple.get(), + [](auto& obj) + { + obj.operator/=(10); + } + ); - my_mandelbrot_zoom_factor *= 10; + my_mandelbrot_zoom_factor_00 *= 10; + my_mandelbrot_zoom_factor_01 *= 10; + my_mandelbrot_zoom_factor_02 *= 10; - std::get<0>(my_ref_to_rectangle_tuple.get()).recenter(my_rectangle_center); + std::get<0>(my_ref_to_rectangle_tuple.get()).recenter(my_rectangle_center_00); + std::get<1>(my_ref_to_rectangle_tuple.get()).recenter(my_rectangle_center_01); + std::get<2>(my_ref_to_rectangle_tuple.get()).recenter(my_rectangle_center_02); // Set the flag to redraw the client window with the new JPEG. // The redrawing will occur below. @@ -575,10 +702,20 @@ } else if(str_cmd == "out") { - // Rescale and re-center the rectangle. - std::get<0>(my_ref_to_rectangle_tuple.get()) *= 10; + // Rescale and re-center the rectangles. - my_mandelbrot_zoom_factor /= 10; + util::caller::for_each_in_tuple + ( + my_ref_to_rectangle_tuple.get(), + [](auto& obj) + { + obj.operator*=(10); + } + ); + + my_mandelbrot_zoom_factor_00 /= 10; + my_mandelbrot_zoom_factor_01 /= 10; + my_mandelbrot_zoom_factor_02 /= 10; // Set the flag to redraw the client window with the new JPEG. // The redrawing will occur below. @@ -611,7 +748,12 @@ do_iterate_and_redraw = false; // Perform the mandelbrot iteration with the iterate-engine. - mandelbrot_iterate_engine(); + + const int local_rectangle_tuple_index { rectangle_tuple_index() }; + + if (local_rectangle_tuple_index == 0) { mandelbrot_iterate_engine_00(); } + else if(local_rectangle_tuple_index == 1) { mandelbrot_iterate_engine_01(); } + else { mandelbrot_iterate_engine_02(); } // Redraw the client window with the new JPEG. using local_window_type = mandelbrot_discovery; @@ -776,9 +918,10 @@ return result_write_is_ok; } - static auto write_number(const std::string& str_prefix, const value_00_type& val, const int prec = -1) -> bool + template + static auto write_number(const std::string& str_prefix, const ValueType& val, const int prec = -1) -> bool { - using local_value_type = value_00_type; + using local_value_type = ValueType; std::stringstream strm { }; @@ -806,7 +949,7 @@ auto mandelbrot_discovery::default_rectangle_tuple() noexcept -> typename mandelbrot_discovery::rectangle_tuple_type& { static rectangle_00_type - my_default_rect + my_default_rect_00 { point_00_type { @@ -817,7 +960,31 @@ value_00_type { "+1.35" } }; - static rectangle_tuple_type my_default_rectangle_tuple(my_default_rect); + static rectangle_01_type + my_default_rect_01 + { + point_01_type + { + value_01_type { "-0.75" }, + value_01_type { "+0.00" } + }, + value_01_type { "+1.35" }, + value_01_type { "+1.35" } + }; + + static rectangle_02_type + my_default_rect_02 + { + point_02_type + { + value_02_type { "-0.75" }, + value_02_type { "+0.00" } + }, + value_02_type { "+1.35" }, + value_02_type { "+1.35" } + }; + + static rectangle_tuple_type my_default_rectangle_tuple(my_default_rect_00, my_default_rect_01, my_default_rect_02); return my_default_rectangle_tuple; } @@ -907,7 +1074,25 @@ const int IconId, const int ScreenCoordinateX, const int ScreenCoordinateY> - typename mandelbrot_discovery::point_00_type mandelbrot_discovery::my_rectangle_center { }; + typename mandelbrot_discovery::point_00_type mandelbrot_discovery::my_rectangle_center_00 { }; + + template + typename mandelbrot_discovery::point_01_type mandelbrot_discovery::my_rectangle_center_01 { }; + + template + typename mandelbrot_discovery::point_02_type mandelbrot_discovery::my_rectangle_center_02 { }; template - typename mandelbrot_discovery::value_00_type mandelbrot_discovery::my_mandelbrot_zoom_factor { 1 }; + typename mandelbrot_discovery::value_00_type mandelbrot_discovery::my_mandelbrot_zoom_factor_00 { 1 }; + + template + typename mandelbrot_discovery::value_01_type mandelbrot_discovery::my_mandelbrot_zoom_factor_01 { 1 }; + + template + typename mandelbrot_discovery::value_02_type mandelbrot_discovery::my_mandelbrot_zoom_factor_02 { 1 }; template(index); - - // Call `some_method` with parameter `param` on each element of the tuple. - for_each_in_tuple - ( - t, - [param](auto& obj) - { - // Call the method with the parameter. - obj.operator*=(param); - } - ); - } + static_cast(index); + + // Call `some_method` with parameter `param` on each element of the tuple. + for_each_in_tuple + ( + t, + [param](auto& obj) + { + // Call the method with the parameter. + obj.operator*=(param); + } + ); } #endif