From: Luca Heltai Date: Mon, 12 Aug 2024 21:00:55 +0000 (-0600) Subject: Added support for magic_enum. X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=927fbba0a11110717e1805e40b8eb47739d470fc;p=dealii.git Added support for magic_enum. --- diff --git a/cmake/configure/configure_50_magic_enum.cmake b/cmake/configure/configure_50_magic_enum.cmake new file mode 100644 index 0000000000..0310523425 --- /dev/null +++ b/cmake/configure/configure_50_magic_enum.cmake @@ -0,0 +1,19 @@ +## ------------------------------------------------------------------------ +## +## SPDX-License-Identifier: LGPL-2.1-or-later +## Copyright (C) 2012 - 2022 by the deal.II authors +## +## This file is part of the deal.II library. +## +## Part of the source code is dual licensed under Apache-2.0 WITH +## LLVM-exception OR LGPL-2.1-or-later. Detailed license information +## governing the source code and code contributions can be found in +## LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II. +## +## ------------------------------------------------------------------------ + +# +# Configuration for the MAGIC_ENUM library: +# + +configure_feature(MAGIC_ENUM) diff --git a/cmake/modules/FindDEAL_II_MAGIC_ENUM.cmake b/cmake/modules/FindDEAL_II_MAGIC_ENUM.cmake new file mode 100644 index 0000000000..220cfc7b72 --- /dev/null +++ b/cmake/modules/FindDEAL_II_MAGIC_ENUM.cmake @@ -0,0 +1,37 @@ +## ------------------------------------------------------------------------ +## +## SPDX-License-Identifier: LGPL-2.1-or-later +## Copyright (C) 2012 - 2022 by the deal.II authors +## +## This file is part of the deal.II library. +## +## Part of the source code is dual licensed under Apache-2.0 WITH +## LLVM-exception OR LGPL-2.1-or-later. Detailed license information +## governing the source code and code contributions can be found in +## LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II. +## +## ------------------------------------------------------------------------ + +# +# Try to find the MAGIC ENUM library +# +# This module exports +# +# MAGIC_ENUM_FOUND +# MAGIC_ENUM_INCLUDE_DIRS +# + +set(MAGIC_ENUM_DIR "" CACHE PATH "An optional hint to a MAGIC_ENUM installation") +set_if_empty(MAGIC_ENUM_DIR "$ENV{MAGIC_ENUM_DIR}") + +deal_ii_find_path(MAGIC_ENUM_INCLUDE_DIR magic_enum.hpp + HINTS ${MAGIC_ENUM_DIR} + PATH_SUFFIXES include + ) + +process_feature(MAGIC_ENUM + LIBRARIES + INCLUDE_DIRS + REQUIRED MAGIC_ENUM_INCLUDE_DIR + CLEAR MAGIC_ENUM_INCLUDE_DIR + ) diff --git a/doc/news/changes/minor/20240812LucaHeltai b/doc/news/changes/minor/20240812LucaHeltai new file mode 100644 index 0000000000..7dd5a03a51 --- /dev/null +++ b/doc/news/changes/minor/20240812LucaHeltai @@ -0,0 +1,3 @@ +New: Added support for magic_enum.hpp. Now PatternsTools::Convert works also when T is an enum type. +
+(Luca Heltai, 2024/08/12) diff --git a/include/deal.II/base/config.h.in b/include/deal.II/base/config.h.in index e09209db4d..b04b8ec1ca 100644 --- a/include/deal.II/base/config.h.in +++ b/include/deal.II/base/config.h.in @@ -51,6 +51,7 @@ #cmakedefine DEAL_II_WITH_LAPACK #cmakedefine LAPACK_WITH_64BIT_BLAS_INDICES #cmakedefine DEAL_II_LAPACK_WITH_MKL +#cmakedefine DEAL_II_WITH_MAGIC_ENUM #cmakedefine DEAL_II_WITH_METIS #cmakedefine DEAL_II_WITH_MPI #cmakedefine DEAL_II_WITH_MUPARSER diff --git a/include/deal.II/base/patterns.h b/include/deal.II/base/patterns.h index 0001f9e833..f906cea13b 100644 --- a/include/deal.II/base/patterns.h +++ b/include/deal.II/base/patterns.h @@ -48,6 +48,10 @@ #include #include +#ifdef DEAL_II_WITH_MAGIC_ENUM +# include +#endif + DEAL_II_NAMESPACE_OPEN // forward declarations for interfaces and friendship @@ -2384,6 +2388,64 @@ namespace Patterns } }; +#ifdef DEAL_II_WITH_MAGIC_ENUM + // Enums + template + struct Convert::value>::type> + { + static std::unique_ptr + to_pattern() + { + const auto n = magic_enum::enum_names(); + std::vector names = {n.begin(), n.end()}; + const auto selection = + Patterns::Tools::Convert::to_string( + names, + Patterns::List( + Patterns::Anything(), names.size(), names.size(), "|")); + // Allow parsing a list of enums, and make bitwise or between them + return Patterns::List(Patterns::Selection(selection), + 0, + names.size(), + "|") + .clone(); + } + + static std::string + to_string(const T &value, + const Patterns::PatternBase &p = *Convert::to_pattern()) + { + namespace B = magic_enum::bitwise_operators; + const auto values = magic_enum::enum_values(); + std::vector names; + for (const auto &v : values) + if (B::operator&(value, v) == v) + names.push_back(std::string(magic_enum::enum_name(v))); + return Patterns::Tools::Convert::to_string(names, p); + } + + static T + to_value(const std::string &s, + const dealii::Patterns::PatternBase &p = *to_pattern()) + { + namespace B = magic_enum::bitwise_operators; + // Make sure we have a valid enum value, or empty value + AssertThrow(p.match(s), ExcNoMatch(s, p.description())); + T value = T(); + std::vector value_names; + value_names = + Patterns::Tools::Convert::to_value(s, p); + for (const auto &name : value_names) + { + auto v = magic_enum::enum_cast(name); + if (v.has_value()) + value = B::operator|(value, v.value()); + } + return value; + } + }; +#endif + // Utility function with default Pattern template std::string diff --git a/tests/parameter_handler/pattern_tools_14.cc b/tests/parameter_handler/pattern_tools_14.cc new file mode 100644 index 0000000000..3500246b69 --- /dev/null +++ b/tests/parameter_handler/pattern_tools_14.cc @@ -0,0 +1,38 @@ +// ------------------------------------------------------------------------ +// +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (C) 2010 - 2022 by the deal.II authors +// +// This file is part of the deal.II library. +// +// Part of the source code is dual licensed under Apache-2.0 WITH +// LLVM-exception OR LGPL-2.1-or-later. Detailed license information +// governing the source code and code contributions can be found in +// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II. +// +// ------------------------------------------------------------------------ + +// Check Patterns::Tools::Convert for enum types + +#include + +#include + +#include "../tests.h" + +int +main() +{ + initlog(); + + UpdateFlags flags = update_values; + + deallog << Patterns::Tools::Convert::to_string(flags) + << std::endl; + + flags = Patterns::Tools::Convert::to_value( + "update_values|update_gradients"); + + deallog << Patterns::Tools::Convert::to_string(flags) + << std::endl; +} diff --git a/tests/parameter_handler/pattern_tools_14.with_magic_enum=true.output b/tests/parameter_handler/pattern_tools_14.with_magic_enum=true.output new file mode 100644 index 0000000000..947cc1ce02 --- /dev/null +++ b/tests/parameter_handler/pattern_tools_14.with_magic_enum=true.output @@ -0,0 +1,3 @@ + +DEAL::update_default| update_values +DEAL::update_default| update_values| update_gradients