From: Matthias Maier Date: Sat, 13 Feb 2021 19:35:04 +0000 (-0600) Subject: Introduce an ndarray type alias X-Git-Tag: v9.3.0-rc1~429^2~2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc5a7e0303ec5f880d3b4d52fbc4971e1ba03663;p=dealii.git Introduce an ndarray type alias The ndarray type alias models an multidimensional array. It has a variable number of template arguments denoting the size of each index that get internally converted to stacked std::arrays. For example: dealii::ndarray my_array is an alias for the following construct: std::array, 3>, 2>, 1> --- diff --git a/include/deal.II/base/ndarray.h b/include/deal.II/base/ndarray.h new file mode 100644 index 0000000000..74b558e844 --- /dev/null +++ b/include/deal.II/base/ndarray.h @@ -0,0 +1,112 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2021 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + +#ifndef dealii_ndarray_h +#define dealii_ndarray_h + +#include + +#include + +#include + +DEAL_II_NAMESPACE_OPEN + +#ifndef DOXYGEN +namespace internal +{ + namespace ndarray + { + // clang-format off + /** + * A variadic template helper class to recursively "unroll" the size + * information of the ndarray. This is best explained on an example: + * @code + * HelperArray::type + * == std::array::type, 1> + * == std::array::type, 2>, 1> + * == std::array::type, 3>, 2>, 1> + * == std::array::type, 4>, 3>, 2>, 1> + * == std::array, 3>, 2>, 1> + * @endcode + */ + template + struct HelperArray; + // clang-format on + + /** + * Recursively define the type alias "type" of HelperArray + * by wrapping a std::array around HelperArray::type + */ + template + struct HelperArray + { + using type = std::array::type, N>; + }; + + /** + * End recursion once no std::size_t template parameters are left and + * simply set the type alias to type T + */ + template + struct HelperArray + { + using type = T; + }; + } // namespace ndarray +} // namespace internal +#endif // DOXYGEN + +/** + * A (variadic template) type alias for conveniently defining multidimensional + * std::arrays + * + * The problem we try to address with the type alias is the following. + * Suppose you want to create a multdimensional array of doubles of, for + * example, rank 3, with sizes 2, 3, 4 for the first, middle, and last + * index. Then using C-style arrays you could simply write + * @code + * double my_array[2][3][4] = { ... }; + * @endcode + * Nowadays, there are a number of good reasons why using C-style arrays is + * usually discouraged (ranging from incompatibilities with STL functions + * requiring awkward wrappers, surprises when comparing for equality, etc.) + * If you want to do the same, however, using the more modern (and + * encouraged) `std::array` class, then you would have to declare + * @code + * std::array, 3>, 2> = { ... }; + * @endcode + * The repetitions of `std::array` look awkward and, worse, the index + * ranges have reversed: the leftmost index has range [0,2), the middle + * index has rnage [0,3) and the rightmost index has range [0,4). + * We address this issue by providing a class ndarray that allows to you + * declare the above stacked `std::array` type by simply writing: + * @code + * dealii::ndarray my_array = { ... }; + * @endcode + * + * @note dealii::ndarray is merely syntactic sugar in form of a + * type + * alias + * (`using` declaration). It is not a deal.II specific class, but merely a + * helper to cleanly define multidimensional arrays realized by "stacked" + * `std::array` classes. + */ +template +using ndarray = typename internal::ndarray::HelperArray::type; + +DEAL_II_NAMESPACE_CLOSE + +#endif