1
0
mirror of synced 2024-12-22 20:45:53 +01:00
ImHex/plugins/builtin/source/content/tools/euclidean_alg.cpp

88 lines
2.8 KiB
C++
Raw Normal View History

#include <hex/api/localization_manager.hpp>
#include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h>
2023-11-30 11:23:12 +01:00
#include <fonts/codicons_font.h>
2023-11-30 11:23:12 +01:00
#include <numeric>
namespace hex::plugin::builtin {
void drawEuclidianAlgorithm() {
static u64 a, b;
static i64 gcdResult = 0;
static i64 lcmResult = 0;
static i64 p = 0, q = 0;
static bool overflow = false;
constexpr static auto extendedGcd = []<typename T>(T a, T b) -> std::pair<T, T> {
T x = 1, y = 0;
T xLast = 0, yLast = 1;
while (b > 0) {
T quotient = a / b;
std::tie(x, xLast) = std::tuple { xLast, x - quotient * xLast };
std::tie(y, yLast) = std::tuple { yLast, y - quotient * yLast };
std::tie(a, b) = std::tuple { b, a - quotient * b };
}
return { x, y };
};
ImGuiExt::TextFormattedWrapped("{}", "hex.builtin.tools.euclidean_algorithm.description"_lang);
ImGui::NewLine();
if (ImGuiExt::BeginBox()) {
bool hasChanged = false;
hasChanged = ImGui::InputScalar("A", ImGuiDataType_U64, &a) || hasChanged;
hasChanged = ImGui::InputScalar("B", ImGuiDataType_U64, &b) || hasChanged;
// Update results when input changed
if (hasChanged) {
// Detect overflow
const u64 multiplicationResult = a * b;
if (a != 0 && multiplicationResult / a != b) {
gcdResult = 0;
lcmResult = 0;
p = 0;
q = 0;
overflow = true;
} else {
gcdResult = std::gcd<i128, i128>(a, b);
lcmResult = std::lcm<i128, i128>(a, b);
std::tie(p, q) = extendedGcd(a, b);
overflow = false;
}
}
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().DisabledAlpha);
ImGui::InputScalar("gcd(A, B)", ImGuiDataType_S64, &gcdResult, nullptr, nullptr, "%llu", ImGuiInputTextFlags_ReadOnly);
ImGui::Indent();
ImGuiExt::TextFormatted(ICON_VS_ARROW_RIGHT " a \u00D7 p + b \u00D7 q = ({0}) \u00D7 ({1}) + ({2}) \u00D7 ({3})", a, p, b, q);
ImGui::Unindent();
ImGui::InputScalar("lcm(A, B)", ImGuiDataType_S64, &lcmResult, nullptr, nullptr, "%llu", ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleVar();
ImGuiExt::EndBox();
}
if (overflow)
ImGuiExt::TextFormattedColored(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed), "{}", "hex.builtin.tools.euclidean_algorithm.overflow"_lang);
else
ImGui::NewLine();
}
}