ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
periodic_fold.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <cmath>
23#include <concepts>
24#include <limits>
25#include <utility>
26
27namespace Algorithm {
28/**
29 * @brief Fold value into primary interval.
30 *
31 * @param x Value to fold
32 * @param i Image count before folding
33 * @param l Length of primary interval
34 * @return x folded into [0, l) and number of folds.
35 */
36inline auto periodic_fold(std::floating_point auto x, std::integral auto i,
37 std::floating_point auto l) {
38 static_assert(std::is_same_v<decltype(x), decltype(l)>);
39 using limits = std::numeric_limits<decltype(i)>;
40 using value_type = decltype(x);
41
42 while ((x < value_type{0}) && (i > limits::min())) {
43 x += l;
44 --i;
45 }
46
47 while ((x >= l) && (i < limits::max())) {
48 x -= l;
49 ++i;
50 }
51
52 return std::make_pair(x, i);
53}
54
55/**
56 * @brief Fold value into primary interval.
57 *
58 * @param x Value to fold
59 * @param l Length of primary interval
60 * @return x folded into [0, l).
61 */
62inline auto periodic_fold(std::floating_point auto x,
63 std::floating_point auto l) {
64 using value_type = decltype(x);
65#ifndef __FAST_MATH__
66 /* Can't fold if either x or l is nan or inf. */
67 if (std::isnan(x) or std::isnan(l) or std::isinf(x) or (l == value_type{0})) {
68 return std::nan("");
69 }
70 if (std::isinf(l)) {
71 return x;
72 }
73#endif // __FAST_MATH__
74
75 while (x < value_type{0}) {
76 x += l;
77 }
78
79 while (x >= l) {
80 x -= l;
81 }
82
83 return x;
84}
85} // namespace Algorithm
auto periodic_fold(std::floating_point auto x, std::integral auto i, std::floating_point auto l)
Fold value into primary interval.