Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / mdspan / layouts.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2018,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*
36  * This file is a modified version of original work of Sandia Corporation.
37  * In the spirit of the original code, this particular file can be distributed
38  * on the terms of Sandia Corporation.
39  */
40 /*
41  *                          Kokkos v. 2.0
42  *               Copyright (2014) Sandia Corporation
43  *
44  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
45  * the U.S. Government retains certain rights in this software.
46  *
47  * Kokkos is licensed under 3-clause BSD terms of use:
48  *
49  * Redistribution and use in source and binary forms, with or without
50  * modification, are permitted provided that the following conditions are
51  * met:
52  *
53  * 1. Redistributions of source code must retain the above copyright
54  * notice, this list of conditions and the following disclaimer.
55  *
56  * 2. Redistributions in binary form must reproduce the above copyright
57  * notice, this list of conditions and the following disclaimer in the
58  * documentation and/or other materials provided with the distribution.
59  *
60  * 3. Neither the name of the Corporation nor the names of the
61  * contributors may be used to endorse or promote products derived from
62  * this software without specific prior written permission.
63  *
64  * THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
65  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
67  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
68  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
69  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
70  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
71  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
72  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
73  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
74  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75  *
76  * Questions? Contact Christian R. Trott (crtrott@sandia.gov)
77  */
78 /*! \libinternal \file
79  * \brief Declares gmx::layout_right for mdspan.
80  *
81  * \author David Hollman <dshollm@sandia.gov>
82  * \author Christian Blau <cblau@gwdg.de>
83  * \ingroup mdspan
84  */
85 #ifndef MDSPAN_LAYOUTS_H
86 #define MDSPAN_LAYOUTS_H
87 #include <cstddef>
88
89 #include <type_traits>
90
91 namespace gmx
92 {
93
94 /*! \libinternal \brief Right-aligned array layout indexer.
95  * Carries the mapping class performing the translation from multidimensional
96  * index to one-dimensional number.
97  */
98 class layout_right
99 {
100
101 public:
102     /*! \libinternal \brief Mapping from multidimensional indices within extents to 1D index.
103      * \tparam Extents the extents of the multidimensional integers for the mapping.
104      */
105     template<class Extents>
106     class mapping
107     {
108     private:
109         //! The extents.
110         Extents m_extents;
111
112     public:
113         //! exposing the type of indices
114         using index_type = ptrdiff_t;
115         //! exposing the type of the extents
116         using extents_type = Extents;
117         //! Default constructor.
118         constexpr mapping() noexcept = default;
119         //! Default move constructor.
120         constexpr mapping(mapping&&) noexcept = default;
121         //! Default copy constructor.
122         constexpr mapping(const mapping&) noexcept = default;
123         //! Default move assignment
124         mapping& operator=(mapping&&) noexcept = default;
125         //! Default copy assignment
126         mapping& operator=(const mapping&) noexcept = default;
127         /*! \brief Construct mapping, setting extents
128          * \param[in] ext the extents
129          */
130         constexpr mapping(const Extents& ext) noexcept : m_extents(ext) {}
131         /*! \brief Return the extents.
132          * \returns extents
133          */
134         constexpr const Extents& extents() const noexcept { return m_extents; }
135
136     private:
137         /* \brief End recursion helper function for static offset calculation.
138          * \param[in] sum The accumulated offset over all dimensions
139          * \returns The offset.
140          */
141         static constexpr index_type offset(const size_t /*r*/, const ptrdiff_t sum) { return sum; }
142
143         /* \brief Statically calculate offset from index and extent.
144          * For a multidimensional index (i0,i1,..,in), in a right memory
145          * layout, 'i0' denotes the slowest moving dimension and
146          * 'in' the fastest moving dimension.
147          * The overall offset within extents N = (N0,..,Nn) is then
148          * offest = i0 * N1 * .. * Nn + i1 * N2 * .. * Nn + in-1 * Nn + in
149          *        = (((i0*N1+i1)*N2+i2)*N3+i3) ...
150          * \param[in] r current rank
151          * \param[in] sum current sum up to this rank
152          * \param[in] i index
153          * \oaram[in] indices The rest of the paramter pack.
154          * \returns The offset.
155          */
156         template<class... Indices>
157         inline constexpr index_type
158         offset(const size_t r, ptrdiff_t sum, const index_type i, Indices... indices) const noexcept
159         {
160             return offset(r + 1, sum * m_extents.extent(r) + i, indices...);
161         }
162
163     public:
164         /*! \brief Return the size of the underlying one-dimensional
165          * data structure, so that the mapping is always valid.
166          *
167          * \returns number of span elements
168          */
169         constexpr index_type required_span_size() const noexcept
170         {
171             index_type size = 1;
172             for (size_t r = 0; r < m_extents.rank(); r++)
173             {
174                 size *= m_extents.extent(r);
175             }
176             return size;
177         }
178
179         /*! \brief Map the multidimensional indices to 1D.
180          * Requires number of indicies have the same dimensionality as the mapping.
181          * \tparam Indices type of the indices to be mapped
182          * \param[in] indices the indices to be mapped
183          * \returns One-dimensional integer index.
184          */
185         template<class... Indices>
186         std::enable_if_t<sizeof...(Indices) == Extents::rank(), index_type> constexpr
187         operator()(Indices... indices) const noexcept
188         {
189             return offset(0, 0, indices...);
190         }
191
192         //! Report that this mapping is always unique.
193         static constexpr bool is_always_unique() noexcept { return true; }
194         //! Report that this mapping is always contiguous.
195         static constexpr bool is_always_contiguous() noexcept { return true; }
196         //! Report that this mapping is always strided.
197         static constexpr bool is_always_strided() noexcept { return true; }
198
199         //! Report that this mapping is unique.
200         constexpr bool is_unique() const noexcept { return true; }
201         //! Report that this mapping is contiguous.
202         constexpr bool is_contiguous() const noexcept { return true; }
203         //! Report that this mapping is strided.
204         constexpr bool is_strided() const noexcept { return true; }
205         /*!\brief Return the stride of dimension r.
206          * \param[in] R rank of the stride to be queried.
207          * \returns the stride along dimension r.
208          */
209         constexpr index_type stride(const size_t R) const noexcept
210         {
211             ptrdiff_t stride = 1;
212             for (size_t r = m_extents.rank() - 1; r > R; r--)
213             {
214                 stride *= m_extents.extent(r);
215             }
216             return stride;
217         }
218
219     }; // class mapping
220
221 }; // class layout_right
222
223 } // namespace gmx
224 #endif /* end of include guard: MDSPAN_LAYOUTS_H */