Persistence_on_a_line.h
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Marc Glisse
4 *
5 * Copyright (C) 2022 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
11#ifndef PERSISTENCE_ON_A_LINE_H_
12#define PERSISTENCE_ON_A_LINE_H_
13
14#include <vector>
15#include <limits>
16#include <type_traits>
17#include <stdexcept>
18#include <gudhi/Debug_utils.h>
19
20namespace Gudhi::persistent_cohomology {
36template<class FiltrationRange, class OutputFunctor, class Compare = std::less<>>
37void compute_persistence_of_function_on_line(FiltrationRange const& input, OutputFunctor&& out, Compare&& lt = {}) {
38 // We process the elements of input 1 by 1, simplifying and outputting as much as possible.
39 // The simplified sequence with the elements that are still active is stored in data.
40 // Invariant: data contains a sequence of type 1 9 2 8 3 7 ...
41 using std::begin;
42 using std::end;
43 auto it = begin(input);
44 auto stop = end(input);
45 if (it == stop) return;
46 typedef std::decay_t<decltype(*it)> Filtration;
47 std::vector<Filtration> data;
48 Filtration v;
49 auto le = [&lt](auto& x, auto& y){ return !lt(y, x); };
50 auto ge = [&lt](auto& x, auto& y){ return !lt(x, y); };
51 auto gt = [&lt](auto& x, auto& y){ return lt(y, x); };
52 data.push_back(*it++);
53state1: // data contains a single element
54 if (it == stop) goto infinite;
55 v = *it++;
56 if (le(v, data[0])) {
57state1down:
58 data[0] = v;
59 goto state1;
60 }
61 data.push_back(v);
62 goto state12;
63state12: // data contains only 2 elements, necessarily data[0] < data[1]
64 if (it == stop) goto endup;
65 v = *it++;
66 if (ge(v, data[1])) {
67 data[1] = v;
68 goto state12;
69 }
70state12down:
71 if (le(v, data[0])) {
72 out(data[0], data[1]);
73 data.pop_back();
74 data[0] = v;
75 goto state1;
76 }
77 data.push_back(v);
78 goto state132;
79state132: // data[-3] < data[-1] < data[-2]
80 if (it == stop) goto enddown;
81 v = *it++;
82 if (le(v, data.back())) {
83 if (gt(v,data.end()[-3])) {
84 data.back() = v; goto state132;
85 } else {
86 out(data.end()[-3], data.end()[-2]);
87 data.erase(data.end()-3, data.end());
88 if (data.empty()) { data.push_back(v); goto state1; }
89 goto down;
90 }
91 } else {
92state132up:
93 if (ge(v, data.end()[-2])) {
94 out(data.end()[-1], data.end()[-2]);
95 data.erase(data.end()-2, data.end());
96 goto up;
97 } else {
98 data.push_back(v);
99 goto state312;
100 }
101 }
102state312: // data[-2] < data[-1] < data[-3]
103 if (it == stop) goto endup;
104 v = *it++;
105 if (ge(v, data.back())) {
106 if (lt(v,data.end()[-3])) {
107 data.back() = v; goto state312;
108 } else {
109 out(data.end()[-2], data.end()[-3]);
110 data.erase(data.end()-3, data.end());
111 GUDHI_CHECK (!data.empty(), std::logic_error("Bug in Gudhi"));
112 goto up;
113 }
114 } else {
115state312down:
116 if (le(v, data.end()[-2])) {
117 out(data.end()[-2], data.end()[-1]);
118 data.erase(data.end()-2, data.end());
119 goto down;
120 } else {
121 data.push_back(v);
122 goto state132;
123 }
124 }
125up: // data[-1] < v after a simplification
126 if (data.size() == 1) { data.push_back(v); goto state12; }
127 goto state132up;
128down: // v < data[-1] after a simplification
129 switch (data.size()) {
130 case 1:
131 goto state1down;
132 case 2:
133 goto state12down;
134 default:
135 goto state312down;
136 }
137 // From here on, we have finished reading input
138endup: // data[-2] < data[-1]
139 data.pop_back();
140 goto enddown;
141enddown: // data[-1] < data[-2]
142 if (data.size() > 1) {
143 out(data.end()[-1], data.end()[-2]);
144 data.erase(data.end()-2, data.end());
145 goto enddown;
146 }
147 goto infinite;
148infinite: // data only contains the global minimum
149 out(data[0], std::numeric_limits<Filtration>::infinity());
150}
151} // namespace Gudhi::persistent_cohomology
152#endif
void compute_persistence_of_function_on_line(FiltrationRange const &input, OutputFunctor &&out, Compare &&lt={})
Computes the persistent homology of the sublevelsets of a PL function defined on in linear time.
Definition: Persistence_on_a_line.h:37