Skip to content

Commit

Permalink
Merge pull request dealii#17491 from luca-heltai/patterns-enums
Browse files Browse the repository at this point in the history
Added support for magic_enum.
  • Loading branch information
blaisb authored Sep 2, 2024
2 parents 8100761 + 2bf5c4e commit 70dd868
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 0 deletions.
19 changes: 19 additions & 0 deletions cmake/configure/configure_50_magic_enum.cmake
Original file line number Diff line number Diff line change
@@ -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)
37 changes: 37 additions & 0 deletions cmake/modules/FindDEAL_II_MAGIC_ENUM.cmake
Original file line number Diff line number Diff line change
@@ -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
)
3 changes: 3 additions & 0 deletions doc/news/changes/minor/20240812LucaHeltai
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
New: Added support for magic_enum.hpp. Now PatternsTools::Convert<T> works also when T is an enum type.
<br>
(Luca Heltai, 2024/08/12)
1 change: 1 addition & 0 deletions include/deal.II/base/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,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
Expand Down
61 changes: 61 additions & 0 deletions include/deal.II/base/patterns.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
#include <utility>
#include <vector>

#ifdef DEAL_II_WITH_MAGIC_ENUM
# include <magic_enum.hpp>
#endif

DEAL_II_NAMESPACE_OPEN

// forward declarations for interfaces and friendship
Expand Down Expand Up @@ -2384,6 +2388,63 @@ namespace Patterns
}
};

#ifdef DEAL_II_WITH_MAGIC_ENUM
// Enums
template <class T>
struct Convert<T, typename std::enable_if<std::is_enum<T>::value>::type>
{
static std::unique_ptr<Patterns::PatternBase>
to_pattern()
{
const auto n = magic_enum::enum_names<T>();
std::vector<std::string> names = {n.begin(), n.end()};
const auto selection =
Patterns::Tools::Convert<decltype(names)>::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<T>::to_pattern())
{
const auto values = magic_enum::enum_values<T>();
std::vector<std::string> names;
for (const auto &v : values)
if (magic_enum::bitwise_operators::operator&(value, v) == v)
names.push_back(std::string(magic_enum::enum_name(v)));
return Patterns::Tools::Convert<decltype(names)>::to_string(names, p);
}

static T
to_value(const std::string &s,
const dealii::Patterns::PatternBase &p = *to_pattern())
{
// Make sure we have a valid enum value, or empty value
AssertThrow(p.match(s), ExcNoMatch(s, p.description()));
T value = T();
std::vector<std::string> value_names;
value_names =
Patterns::Tools::Convert<decltype(value_names)>::to_value(s, p);
for (const auto &name : value_names)
{
auto v = magic_enum::enum_cast<T>(name);
if (v.has_value())
value =
magic_enum::bitwise_operators::operator|(value, v.value());
}
return value;
}
};
#endif

// Utility function with default Pattern
template <typename T>
std::string
Expand Down
39 changes: 39 additions & 0 deletions tests/parameter_handler/pattern_tools_14.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ------------------------------------------------------------------------
//
// 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
// Test the conversion of UpdateFlags to string and back

#include <deal.II/fe/fe_values.h>

#include <memory>

#include "../tests.h"

int
main()
{
initlog();

UpdateFlags flags = update_values;

deallog << Patterns::Tools::Convert<UpdateFlags>::to_string(flags)
<< std::endl;

flags = Patterns::Tools::Convert<UpdateFlags>::to_value(
"update_values|update_gradients");

deallog << Patterns::Tools::Convert<UpdateFlags>::to_string(flags)
<< std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

DEAL::update_default| update_values
DEAL::update_default| update_values| update_gradients
58 changes: 58 additions & 0 deletions tests/parameter_handler/pattern_tools_15.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// ------------------------------------------------------------------------
//
// 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 custom enum types
// Test the conversion of a standard enum to string and back, and of an enum
// class to string and back

#include <deal.II/fe/fe_values.h>

#include <memory>

#include "../tests.h"

enum TestFlag
{
red = 1,
green = 2,
blue = 4
};

enum class TestFlagClass
{
yellow = 1,
orange = 2,
white = 4
};

template <typename T>
using C = Patterns::Tools::Convert<T>;

int
main()
{
initlog();
{
TestFlag flags = red;
deallog << C<TestFlag>::to_string(flags) << std::endl;
flags = C<TestFlag>::to_value("green|blue");
deallog << C<TestFlag>::to_string(flags) << std::endl;
}
{
TestFlagClass flags = TestFlagClass::yellow;
deallog << C<TestFlagClass>::to_string(flags) << std::endl;
flags = C<TestFlagClass>::to_value("orange|white");
deallog << C<TestFlagClass>::to_string(flags) << std::endl;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

DEAL::red
DEAL::green| blue
DEAL::yellow
DEAL::orange| white

0 comments on commit 70dd868

Please sign in to comment.