multipers 2.3.3b6__cp313-cp313-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- multipers/.dylibs/libc++.1.0.dylib +0 -0
- multipers/.dylibs/libtbb.12.16.dylib +0 -0
- multipers/__init__.py +33 -0
- multipers/_signed_measure_meta.py +453 -0
- multipers/_slicer_meta.py +211 -0
- multipers/array_api/__init__.py +45 -0
- multipers/array_api/numpy.py +41 -0
- multipers/array_api/torch.py +58 -0
- multipers/data/MOL2.py +458 -0
- multipers/data/UCR.py +18 -0
- multipers/data/__init__.py +1 -0
- multipers/data/graphs.py +466 -0
- multipers/data/immuno_regions.py +27 -0
- multipers/data/minimal_presentation_to_st_bf.py +0 -0
- multipers/data/pytorch2simplextree.py +91 -0
- multipers/data/shape3d.py +101 -0
- multipers/data/synthetic.py +113 -0
- multipers/distances.py +202 -0
- multipers/filtration_conversions.pxd +229 -0
- multipers/filtration_conversions.pxd.tp +84 -0
- multipers/filtrations/__init__.py +18 -0
- multipers/filtrations/density.py +574 -0
- multipers/filtrations/filtrations.py +361 -0
- multipers/filtrations.pxd +224 -0
- multipers/function_rips.cpython-313-darwin.so +0 -0
- multipers/function_rips.pyx +105 -0
- multipers/grids.cpython-313-darwin.so +0 -0
- multipers/grids.pyx +433 -0
- multipers/gudhi/Persistence_slices_interface.h +132 -0
- multipers/gudhi/Simplex_tree_interface.h +239 -0
- multipers/gudhi/Simplex_tree_multi_interface.h +551 -0
- multipers/gudhi/cubical_to_boundary.h +59 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex.h +450 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_base.h +1070 -0
- multipers/gudhi/gudhi/Bitmap_cubical_complex_periodic_boundary_conditions_base.h +579 -0
- multipers/gudhi/gudhi/Debug_utils.h +45 -0
- multipers/gudhi/gudhi/Fields/Multi_field.h +484 -0
- multipers/gudhi/gudhi/Fields/Multi_field_operators.h +455 -0
- multipers/gudhi/gudhi/Fields/Multi_field_shared.h +450 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small.h +531 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_operators.h +507 -0
- multipers/gudhi/gudhi/Fields/Multi_field_small_shared.h +531 -0
- multipers/gudhi/gudhi/Fields/Z2_field.h +355 -0
- multipers/gudhi/gudhi/Fields/Z2_field_operators.h +376 -0
- multipers/gudhi/gudhi/Fields/Zp_field.h +420 -0
- multipers/gudhi/gudhi/Fields/Zp_field_operators.h +400 -0
- multipers/gudhi/gudhi/Fields/Zp_field_shared.h +418 -0
- multipers/gudhi/gudhi/Flag_complex_edge_collapser.h +337 -0
- multipers/gudhi/gudhi/Matrix.h +2107 -0
- multipers/gudhi/gudhi/Multi_critical_filtration.h +1038 -0
- multipers/gudhi/gudhi/Multi_persistence/Box.h +174 -0
- multipers/gudhi/gudhi/Multi_persistence/Line.h +282 -0
- multipers/gudhi/gudhi/Off_reader.h +173 -0
- multipers/gudhi/gudhi/One_critical_filtration.h +1441 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix.h +769 -0
- multipers/gudhi/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +686 -0
- multipers/gudhi/gudhi/Persistence_matrix/Boundary_matrix.h +842 -0
- multipers/gudhi/gudhi/Persistence_matrix/Chain_matrix.h +1350 -0
- multipers/gudhi/gudhi/Persistence_matrix/Id_to_index_overlay.h +1105 -0
- multipers/gudhi/gudhi/Persistence_matrix/Position_to_index_overlay.h +859 -0
- multipers/gudhi/gudhi/Persistence_matrix/RU_matrix.h +910 -0
- multipers/gudhi/gudhi/Persistence_matrix/allocators/entry_constructors.h +139 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_pairing.h +230 -0
- multipers/gudhi/gudhi/Persistence_matrix/base_swap.h +211 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +60 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_pairing.h +136 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_rep_cycles.h +190 -0
- multipers/gudhi/gudhi/Persistence_matrix/chain_vine_swap.h +616 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/chain_column_extra_properties.h +150 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_dimension_holder.h +106 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/column_utilities.h +219 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/entry_types.h +327 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/heap_column.h +1140 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_list_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/intrusive_set_column.h +934 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/list_column.h +980 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/naive_vector_column.h +1092 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/row_access.h +192 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/set_column.h +921 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/small_vector_column.h +1093 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/unordered_set_column.h +1012 -0
- multipers/gudhi/gudhi/Persistence_matrix/columns/vector_column.h +1244 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_dimension_holders.h +186 -0
- multipers/gudhi/gudhi/Persistence_matrix/matrix_row_access.h +164 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_pairing.h +156 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_rep_cycles.h +376 -0
- multipers/gudhi/gudhi/Persistence_matrix/ru_vine_swap.h +540 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Field_Zp.h +118 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Multi_field.h +173 -0
- multipers/gudhi/gudhi/Persistent_cohomology/Persistent_cohomology_column.h +128 -0
- multipers/gudhi/gudhi/Persistent_cohomology.h +745 -0
- multipers/gudhi/gudhi/Points_off_io.h +171 -0
- multipers/gudhi/gudhi/Simple_object_pool.h +69 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_iterators.h +463 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_node_explicit_storage.h +83 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_siblings.h +106 -0
- multipers/gudhi/gudhi/Simplex_tree/Simplex_tree_star_simplex_iterators.h +277 -0
- multipers/gudhi/gudhi/Simplex_tree/hooks_simplex_base.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/indexing_tag.h +27 -0
- multipers/gudhi/gudhi/Simplex_tree/serialization_utils.h +62 -0
- multipers/gudhi/gudhi/Simplex_tree/simplex_tree_options.h +157 -0
- multipers/gudhi/gudhi/Simplex_tree.h +2794 -0
- multipers/gudhi/gudhi/Simplex_tree_multi.h +152 -0
- multipers/gudhi/gudhi/distance_functions.h +62 -0
- multipers/gudhi/gudhi/graph_simplicial_complex.h +104 -0
- multipers/gudhi/gudhi/persistence_interval.h +253 -0
- multipers/gudhi/gudhi/persistence_matrix_options.h +170 -0
- multipers/gudhi/gudhi/reader_utils.h +367 -0
- multipers/gudhi/mma_interface_coh.h +256 -0
- multipers/gudhi/mma_interface_h0.h +223 -0
- multipers/gudhi/mma_interface_matrix.h +293 -0
- multipers/gudhi/naive_merge_tree.h +536 -0
- multipers/gudhi/scc_io.h +310 -0
- multipers/gudhi/truc.h +1403 -0
- multipers/io.cpython-313-darwin.so +0 -0
- multipers/io.pyx +644 -0
- multipers/ml/__init__.py +0 -0
- multipers/ml/accuracies.py +90 -0
- multipers/ml/invariants_with_persistable.py +79 -0
- multipers/ml/kernels.py +176 -0
- multipers/ml/mma.py +713 -0
- multipers/ml/one.py +472 -0
- multipers/ml/point_clouds.py +352 -0
- multipers/ml/signed_measures.py +1589 -0
- multipers/ml/sliced_wasserstein.py +461 -0
- multipers/ml/tools.py +113 -0
- multipers/mma_structures.cpython-313-darwin.so +0 -0
- multipers/mma_structures.pxd +128 -0
- multipers/mma_structures.pyx +2786 -0
- multipers/mma_structures.pyx.tp +1094 -0
- multipers/multi_parameter_rank_invariant/diff_helpers.h +84 -0
- multipers/multi_parameter_rank_invariant/euler_characteristic.h +97 -0
- multipers/multi_parameter_rank_invariant/function_rips.h +322 -0
- multipers/multi_parameter_rank_invariant/hilbert_function.h +769 -0
- multipers/multi_parameter_rank_invariant/persistence_slices.h +148 -0
- multipers/multi_parameter_rank_invariant/rank_invariant.h +369 -0
- multipers/multiparameter_edge_collapse.py +41 -0
- multipers/multiparameter_module_approximation/approximation.h +2330 -0
- multipers/multiparameter_module_approximation/combinatory.h +129 -0
- multipers/multiparameter_module_approximation/debug.h +107 -0
- multipers/multiparameter_module_approximation/euler_curves.h +0 -0
- multipers/multiparameter_module_approximation/format_python-cpp.h +286 -0
- multipers/multiparameter_module_approximation/heap_column.h +238 -0
- multipers/multiparameter_module_approximation/images.h +79 -0
- multipers/multiparameter_module_approximation/list_column.h +174 -0
- multipers/multiparameter_module_approximation/list_column_2.h +232 -0
- multipers/multiparameter_module_approximation/ru_matrix.h +347 -0
- multipers/multiparameter_module_approximation/set_column.h +135 -0
- multipers/multiparameter_module_approximation/structure_higher_dim_barcode.h +36 -0
- multipers/multiparameter_module_approximation/unordered_set_column.h +166 -0
- multipers/multiparameter_module_approximation/utilities.h +403 -0
- multipers/multiparameter_module_approximation/vector_column.h +223 -0
- multipers/multiparameter_module_approximation/vector_matrix.h +331 -0
- multipers/multiparameter_module_approximation/vineyards.h +464 -0
- multipers/multiparameter_module_approximation/vineyards_trajectories.h +649 -0
- multipers/multiparameter_module_approximation.cpython-313-darwin.so +0 -0
- multipers/multiparameter_module_approximation.pyx +235 -0
- multipers/pickle.py +90 -0
- multipers/plots.py +456 -0
- multipers/point_measure.cpython-313-darwin.so +0 -0
- multipers/point_measure.pyx +395 -0
- multipers/simplex_tree_multi.cpython-313-darwin.so +0 -0
- multipers/simplex_tree_multi.pxd +134 -0
- multipers/simplex_tree_multi.pyx +10840 -0
- multipers/simplex_tree_multi.pyx.tp +2009 -0
- multipers/slicer.cpython-313-darwin.so +0 -0
- multipers/slicer.pxd +3034 -0
- multipers/slicer.pxd.tp +234 -0
- multipers/slicer.pyx +20481 -0
- multipers/slicer.pyx.tp +1088 -0
- multipers/tensor/tensor.h +672 -0
- multipers/tensor.pxd +13 -0
- multipers/test.pyx +44 -0
- multipers/tests/__init__.py +62 -0
- multipers/torch/__init__.py +1 -0
- multipers/torch/diff_grids.py +240 -0
- multipers/torch/rips_density.py +310 -0
- multipers-2.3.3b6.dist-info/METADATA +128 -0
- multipers-2.3.3b6.dist-info/RECORD +183 -0
- multipers-2.3.3b6.dist-info/WHEEL +6 -0
- multipers-2.3.3b6.dist-info/licenses/LICENSE +21 -0
- multipers-2.3.3b6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1441 @@
|
|
|
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): David Loiseaux
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2023 Inria
|
|
6
|
+
*
|
|
7
|
+
* Modification(s):
|
|
8
|
+
* - 2024/08 Hannah Schreiber: Generalization to all signed arithmetic types for T + doc
|
|
9
|
+
* - YYYY/MM Author: Description of the modification
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @file One_critical_filtration.h
|
|
14
|
+
* @author David Loiseaux
|
|
15
|
+
* @brief Contains the @ref Gudhi::multi_filtration::One_critical_filtration class.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef ONE_CRITICAL_FILTRATIONS_H_
|
|
19
|
+
#define ONE_CRITICAL_FILTRATIONS_H_
|
|
20
|
+
|
|
21
|
+
#include <algorithm> //std::lower_bound
|
|
22
|
+
#include <cmath> //std::isnan
|
|
23
|
+
#include <cstddef> //std::size_t
|
|
24
|
+
#include <cstdint> //std::int32_t
|
|
25
|
+
#include <ostream> //std::ostream
|
|
26
|
+
#include <limits> //std::numerical_limits
|
|
27
|
+
#include <stdexcept> //std::logic_error
|
|
28
|
+
#include <vector>
|
|
29
|
+
|
|
30
|
+
#include <gudhi/Debug_utils.h>
|
|
31
|
+
|
|
32
|
+
namespace Gudhi {
|
|
33
|
+
namespace multi_filtration {
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @class One_critical_filtration one_critical_filtration.h gudhi/one_critical_filtration.h
|
|
37
|
+
* @ingroup multi_filtration
|
|
38
|
+
*
|
|
39
|
+
* @brief Class encoding the apparition time, i.e., filtration value of an object
|
|
40
|
+
* (e.g., simplex, cell, abstract algebraic generator) in the setting of 1-critical multiparameter filtrations.
|
|
41
|
+
* The class can be used as a vector whose indices correspond to one parameter each.
|
|
42
|
+
* It also follows numpy-like broadcast semantic.
|
|
43
|
+
*
|
|
44
|
+
* @details Inherits of `std::vector<T>`. Overloads `std::numeric_limits` such that:
|
|
45
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::has_infinity` returns `true`,
|
|
46
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::infinity()` returns @ref One_critical_filtration<T>::inf() "",
|
|
47
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::minus_infinity()` returns
|
|
48
|
+
* @ref One_critical_filtration<T>::minus_inf() "",
|
|
49
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::max()` throws,
|
|
50
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::max(n)` returns a @ref One_critical_filtration<T> with `n`
|
|
51
|
+
* parameters evaluated at value `std::numeric_limits<T>::max()`,
|
|
52
|
+
* - `std::numeric_limits<One_critical_filtration<T> >::quiet_NaN()` returns @ref One_critical_filtration<T>::nan() "".
|
|
53
|
+
*
|
|
54
|
+
* One critical simplicial filtrations are filtrations such that the lifetime of each object is a positive cone, e.g.
|
|
55
|
+
* - \f$ \{ x \in \mathbb R^2 : x>=(1,2)\} \f$ is valid, while
|
|
56
|
+
* - \f$ \{ x \in \mathbb R^2 : x>=(1,2)\} \cap \{x \in \mathbb R^2 : x>=(2,1)\} \f$ is not.
|
|
57
|
+
*
|
|
58
|
+
* If the lifetime corresponds to a union of such positive cones, the filtration is called a multi-critical filtration.
|
|
59
|
+
* For those cases, use @ref Multi_critical_filtration instead.
|
|
60
|
+
*
|
|
61
|
+
* @tparam T Arithmetic type of an entry for one parameter of the filtration value. Has to be **signed** and
|
|
62
|
+
* to implement `std::isnan(T)`, `std::numeric_limits<T>::has_quiet_NaN`, `std::numeric_limits<T>::quiet_NaN()`,
|
|
63
|
+
* `std::numeric_limits<T>::has_infinity`, `std::numeric_limits<T>::infinity()` and `std::numeric_limits<T>::max()`.
|
|
64
|
+
* If `std::numeric_limits<T>::has_infinity` returns `false`, a call to `std::numeric_limits<T>::infinity()`
|
|
65
|
+
* can simply throw. Examples are the native types `double`, `float` and `int`.
|
|
66
|
+
*/
|
|
67
|
+
template <typename T>
|
|
68
|
+
class One_critical_filtration : public std::vector<T> {
|
|
69
|
+
private:
|
|
70
|
+
using Base = std::vector<T>;
|
|
71
|
+
|
|
72
|
+
public:
|
|
73
|
+
/**
|
|
74
|
+
* @brief Type of the origin of a "lifetime cone", i.e., of a one-critical filtration value.
|
|
75
|
+
* Common with @ref Multi_critical_filtration "". In the 1-critical case, simply the class it-self.
|
|
76
|
+
*/
|
|
77
|
+
using Generator = One_critical_filtration<T>;
|
|
78
|
+
|
|
79
|
+
// CONSTRUCTORS
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @brief Default constructor. Constructs a value at minus infinity.
|
|
83
|
+
*/
|
|
84
|
+
One_critical_filtration() : Base{-T_inf} {};
|
|
85
|
+
/**
|
|
86
|
+
* @brief Constructs a vector of the size of the given number of parameters with -inf as value for each entry.
|
|
87
|
+
*
|
|
88
|
+
* @warning The vector `{-inf, -inf, ...}` with \f$ n > 1 \f$ entries is not considered as "minus infinity" (the
|
|
89
|
+
* method @ref is_minus_inf() will not return true). The `-inf` are just meant as placeholders, at least one entry
|
|
90
|
+
* should be modified by the user. Otherwise, either use the static method @ref minus_inf() or set @p n to 1 instead.
|
|
91
|
+
*
|
|
92
|
+
* @param n Number of parameters.
|
|
93
|
+
*/
|
|
94
|
+
One_critical_filtration(int n) : Base(n, -T_inf) {};
|
|
95
|
+
/**
|
|
96
|
+
* @brief Constructs a vector of the size of the given number of parameters and the given value for each entry.
|
|
97
|
+
*
|
|
98
|
+
* @warning If @p value is `inf`, `-inf`, or `NaN`, the vector `{value, value, ...}` with \f$ n > 1 \f$ entries
|
|
99
|
+
* is not wrong but will not be considered as respectively "infinity", "minus infinity" or "NaN" (the corresponding
|
|
100
|
+
* methods @ref is_plus_inf(), @ref is_minus_inf() and @ref is_nan() will return false). For this purpose, please use
|
|
101
|
+
* the static methods @ref inf(), @ref minus_inf() and @ref nan() instead.
|
|
102
|
+
*
|
|
103
|
+
* @param n Number of parameters.
|
|
104
|
+
* @param value Value which will be used for each entry.
|
|
105
|
+
*/
|
|
106
|
+
One_critical_filtration(int n, T value) : Base(n, value) {};
|
|
107
|
+
/**
|
|
108
|
+
* @brief Construct a vector from the given initializer list.
|
|
109
|
+
*
|
|
110
|
+
* @param init Initializer list with values for each parameter.
|
|
111
|
+
*/
|
|
112
|
+
One_critical_filtration(std::initializer_list<T> init) : Base(init) {};
|
|
113
|
+
/**
|
|
114
|
+
* @brief Construct a vector from the given vector.
|
|
115
|
+
*
|
|
116
|
+
* @param v Vector with values for each parameter.
|
|
117
|
+
*/
|
|
118
|
+
One_critical_filtration(const std::vector<T> &v) : Base(v) {};
|
|
119
|
+
/**
|
|
120
|
+
* @brief Construct a vector from the given vector by moving it to the new vector.
|
|
121
|
+
*
|
|
122
|
+
* @param v Vector with values for each parameter.
|
|
123
|
+
*/
|
|
124
|
+
One_critical_filtration(std::vector<T> &&v) : Base(std::move(v)) {};
|
|
125
|
+
/**
|
|
126
|
+
* @brief Construct a vector from the range given by the begin and end iterators.
|
|
127
|
+
*
|
|
128
|
+
* @param it_begin Start of the range.
|
|
129
|
+
* @param it_end End of the range.
|
|
130
|
+
*/
|
|
131
|
+
One_critical_filtration(typename std::vector<T>::iterator it_begin, typename std::vector<T>::iterator it_end)
|
|
132
|
+
: Base(it_begin, it_end) {};
|
|
133
|
+
/**
|
|
134
|
+
* @brief Construct a vector from the range given by the begin and end const iterators.
|
|
135
|
+
*
|
|
136
|
+
* @param it_begin Start of the range.
|
|
137
|
+
* @param it_end End of the range.
|
|
138
|
+
*/
|
|
139
|
+
One_critical_filtration(typename std::vector<T>::const_iterator it_begin,
|
|
140
|
+
typename std::vector<T>::const_iterator it_end)
|
|
141
|
+
: Base(it_begin, it_end) {};
|
|
142
|
+
|
|
143
|
+
// HERITAGE
|
|
144
|
+
|
|
145
|
+
using std::vector<T>::operator[]; /**< Inheritance of entry access. */
|
|
146
|
+
using value_type = T; /**< Entry type. */
|
|
147
|
+
|
|
148
|
+
// CONVERTERS
|
|
149
|
+
|
|
150
|
+
// like numpy
|
|
151
|
+
/**
|
|
152
|
+
* @brief Returns a copy with entries casted into the type given as template parameter.
|
|
153
|
+
*
|
|
154
|
+
* @tparam U New type for the entries.
|
|
155
|
+
* @return Copy with new entry type.
|
|
156
|
+
*/
|
|
157
|
+
template <typename U>
|
|
158
|
+
One_critical_filtration<U> as_type() const {
|
|
159
|
+
One_critical_filtration<U> out(0);
|
|
160
|
+
out.reserve(Base::size());
|
|
161
|
+
for (std::size_t i = 0u; i < Base::size(); i++) out.push_back(static_cast<U>(Base::operator[](i)));
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ACCESS
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @brief Returns the number of parameters of the finite filtration value. If the value is "inf", "-inf" or "NaN",
|
|
169
|
+
* returns 1.
|
|
170
|
+
*
|
|
171
|
+
* @return Number of parameters.
|
|
172
|
+
*/
|
|
173
|
+
std::size_t num_parameters() const { return Base::size(); }
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @brief Returns a filtration value for which @ref is_plus_inf() returns `true`.
|
|
177
|
+
*
|
|
178
|
+
* @return Infinity.
|
|
179
|
+
*/
|
|
180
|
+
constexpr static One_critical_filtration inf() { return {T_inf}; }
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @brief Returns a filtration value for which @ref is_minus_inf() returns `true`.
|
|
184
|
+
*
|
|
185
|
+
* @return Minus infinity.
|
|
186
|
+
*/
|
|
187
|
+
constexpr static One_critical_filtration minus_inf() { return {-T_inf}; }
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @brief Returns a filtration value for which @ref is_nan() returns `true`.
|
|
191
|
+
*
|
|
192
|
+
* @return NaN.
|
|
193
|
+
*/
|
|
194
|
+
constexpr static One_critical_filtration nan() {
|
|
195
|
+
if constexpr (std::numeric_limits<T>::has_quiet_NaN) {
|
|
196
|
+
return {std::numeric_limits<T>::quiet_NaN()};
|
|
197
|
+
} else {
|
|
198
|
+
return One_critical_filtration(0); // to differentiate it from 0, an empty filtration value can't do much anyway.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// DESCRIPTORS
|
|
203
|
+
|
|
204
|
+
// TODO: Accept {-inf, -inf, ...} / {inf, inf, ...} / {NaN, NaN, ...} as resp. -inf / inf / NaN.
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @brief Returns `true` if and only if the filtration value is considered as infinity.
|
|
208
|
+
*/
|
|
209
|
+
bool is_plus_inf() const {
|
|
210
|
+
if (Base::size() != 1) return false;
|
|
211
|
+
return (Base::operator[](0) == T_inf);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @brief Returns `true` if and only if the filtration value is considered as minus infinity.
|
|
216
|
+
*/
|
|
217
|
+
bool is_minus_inf() const {
|
|
218
|
+
if (Base::size() != 1) return false;
|
|
219
|
+
return (Base::operator[](0) == -T_inf);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @brief Returns `true` if and only if the filtration value is considered as NaN.
|
|
224
|
+
*/
|
|
225
|
+
bool is_nan() const {
|
|
226
|
+
if constexpr (std::numeric_limits<T>::has_quiet_NaN) {
|
|
227
|
+
if (Base::size() != 1) return false;
|
|
228
|
+
return is_nan_(Base::operator[](0));
|
|
229
|
+
} else {
|
|
230
|
+
return Base::empty();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @brief Returns `true` if and only if the filtration value is non-empty and is not considered as infinity,
|
|
236
|
+
* minus infinity or NaN.
|
|
237
|
+
*/
|
|
238
|
+
bool is_finite() const {
|
|
239
|
+
if (Base::size() > 1) return true;
|
|
240
|
+
if (Base::size() == 0) return false;
|
|
241
|
+
auto first_value = Base::operator[](0); // TODO : Maybe check all entries ?
|
|
242
|
+
if (is_nan_(first_value) || first_value == -T_inf || first_value == T_inf) return false;
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// COMPARAISON OPERATORS
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @brief Returns `true` if and only if for each \f$ i \f$, \f$ a[i] \f$ is strictly smaller than \f$ b[i] \f$.
|
|
250
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
251
|
+
*
|
|
252
|
+
* Note that not all filtration values are comparable. That is, \f$ a < b \f$ and \f$ b < a \f$ returning both false
|
|
253
|
+
* does **not** imply \f$ a == b \f$.
|
|
254
|
+
*/
|
|
255
|
+
friend bool operator<(const One_critical_filtration &a, const One_critical_filtration &b) {
|
|
256
|
+
if (a.is_plus_inf() || a.is_nan() || b.is_nan() || b.is_minus_inf()) return false;
|
|
257
|
+
if (b.is_plus_inf() || a.is_minus_inf()) return true;
|
|
258
|
+
bool isSame = true;
|
|
259
|
+
auto n = a.size();
|
|
260
|
+
GUDHI_CHECK(a.size() == b.size(), "Two filtration values with different number of parameters are not comparable.");
|
|
261
|
+
for (auto i = 0u; i < n; ++i) {
|
|
262
|
+
if (a[i] > b[i]) return false;
|
|
263
|
+
if (isSame && a[i] != b[i]) isSame = false;
|
|
264
|
+
}
|
|
265
|
+
return !isSame;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @brief Returns `true` if and only if for each \f$ i \f$, \f$ a[i] \f$ is smaller or equal than \f$ b[i] \f$.
|
|
270
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
271
|
+
*
|
|
272
|
+
* Note that not all filtration values are comparable. That is, \f$ a \le b \f$ and \f$ b \le a \f$ can both return
|
|
273
|
+
* `false`.
|
|
274
|
+
*/
|
|
275
|
+
friend bool operator<=(const One_critical_filtration &a, const One_critical_filtration &b) {
|
|
276
|
+
if (a.is_nan() || b.is_nan()) return false;
|
|
277
|
+
if (b.is_plus_inf() || a.is_minus_inf()) return true;
|
|
278
|
+
if (a.is_plus_inf() || b.is_minus_inf()) return false;
|
|
279
|
+
auto n = a.size();
|
|
280
|
+
GUDHI_CHECK(a.size() == b.size(), "Two filtration values with different number of parameters are not comparable.");
|
|
281
|
+
for (std::size_t i = 0u; i < n; ++i) {
|
|
282
|
+
if (a[i] > b[i]) return false;
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @brief Returns `true` if and only if for each \f$ i \f$, \f$ a[i] \f$ is strictly greater than \f$ b[i] \f$.
|
|
289
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
290
|
+
*
|
|
291
|
+
* Note that not all filtration values are comparable. That is, \f$ a > b \f$ and \f$ b > a \f$ returning both false
|
|
292
|
+
* does **not** imply \f$ a == b \f$.
|
|
293
|
+
*/
|
|
294
|
+
friend bool operator>(const One_critical_filtration &a, const One_critical_filtration &b) { return b < a; }
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* @brief Returns `true` if and only if for each \f$ i \f$, \f$ a[i] \f$ is greater or equal than \f$ b[i] \f$.
|
|
298
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
299
|
+
*
|
|
300
|
+
* Note that not all filtration values are comparable. That is, \f$ a \ge b \f$ and \f$ b \ge a \f$ can both return
|
|
301
|
+
* `false`.
|
|
302
|
+
*/
|
|
303
|
+
friend bool operator>=(const One_critical_filtration &a, const One_critical_filtration &b) { return b <= a; }
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @brief Returns `true` if and only if for each \f$ i \f$, \f$ a[i] \f$ is equal to \f$ b[i] \f$.
|
|
307
|
+
*/
|
|
308
|
+
friend bool operator==(const One_critical_filtration &a, const One_critical_filtration &b) {
|
|
309
|
+
return static_cast<const Base &>(a) == static_cast<const Base &>(b);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @brief Returns `true` if and only if \f$ a == b \f$ returns `false`.
|
|
314
|
+
*/
|
|
315
|
+
friend bool operator!=(const One_critical_filtration &a, const One_critical_filtration &b) { return !(a == b); }
|
|
316
|
+
|
|
317
|
+
// ARITHMETIC OPERATORS
|
|
318
|
+
|
|
319
|
+
// opposite
|
|
320
|
+
/**
|
|
321
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ -f[i] \f$.
|
|
322
|
+
*
|
|
323
|
+
* Used conventions:
|
|
324
|
+
* - \f$ -NaN = NaN \f$.
|
|
325
|
+
*
|
|
326
|
+
* @param f Value to opposite.
|
|
327
|
+
* @return The opposite of @p f.
|
|
328
|
+
*/
|
|
329
|
+
friend One_critical_filtration operator-(const One_critical_filtration &f) {
|
|
330
|
+
One_critical_filtration result(0);
|
|
331
|
+
result.reserve(f.size());
|
|
332
|
+
for (auto val : f) {
|
|
333
|
+
result.push_back(-val);
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// subtraction
|
|
339
|
+
/**
|
|
340
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ a[i] - b[i] \f$.
|
|
341
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
342
|
+
*
|
|
343
|
+
* Used conventions:
|
|
344
|
+
* - \f$ inf - inf = NaN \f$,
|
|
345
|
+
* - \f$ -inf - (-inf) = NaN \f$,
|
|
346
|
+
* - \f$ NaN - b = NaN \f$,
|
|
347
|
+
* - \f$ a - NaN = NaN \f$.
|
|
348
|
+
*
|
|
349
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
350
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
351
|
+
*
|
|
352
|
+
* @param a First element of the subtraction.
|
|
353
|
+
* @param b Second element of the subtraction.
|
|
354
|
+
* @return Entry-wise \f$ a - b \f$.
|
|
355
|
+
*/
|
|
356
|
+
friend One_critical_filtration operator-(One_critical_filtration a, const One_critical_filtration &b) {
|
|
357
|
+
a -= b;
|
|
358
|
+
return a;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ f[i] - val \f$.
|
|
363
|
+
*
|
|
364
|
+
* Used conventions:
|
|
365
|
+
* - \f$ inf - inf = NaN \f$,
|
|
366
|
+
* - \f$ -inf - (-inf) = NaN \f$,
|
|
367
|
+
* - \f$ NaN - b = NaN \f$,
|
|
368
|
+
* - \f$ a - NaN = NaN \f$.
|
|
369
|
+
*
|
|
370
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
371
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
372
|
+
*
|
|
373
|
+
* @param f First element of the subtraction.
|
|
374
|
+
* @param val Second element of the subtraction.
|
|
375
|
+
* @return Entry-wise \f$ f - val \f$.
|
|
376
|
+
*/
|
|
377
|
+
friend One_critical_filtration operator-(One_critical_filtration f, const T &val) {
|
|
378
|
+
f -= val;
|
|
379
|
+
return f;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ val - f[i] \f$.
|
|
384
|
+
*
|
|
385
|
+
* Used conventions:
|
|
386
|
+
* - \f$ inf - inf = NaN \f$,
|
|
387
|
+
* - \f$ -inf - (-inf) = NaN \f$,
|
|
388
|
+
* - \f$ NaN - b = NaN \f$,
|
|
389
|
+
* - \f$ a - NaN = NaN \f$.
|
|
390
|
+
*
|
|
391
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
392
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
393
|
+
*
|
|
394
|
+
* @param val First element of the subtraction.
|
|
395
|
+
* @param f Second element of the subtraction.
|
|
396
|
+
* @return Entry-wise \f$ val - f \f$.
|
|
397
|
+
*/
|
|
398
|
+
friend One_critical_filtration operator-(const T &val, One_critical_filtration f) {
|
|
399
|
+
// TODO: in one go
|
|
400
|
+
f = -f;
|
|
401
|
+
f += val;
|
|
402
|
+
return f;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
407
|
+
* \f$ result[i] - to\_subtract[i] \f$.
|
|
408
|
+
* If @p result and @p to_subtract are both not infinite or NaN, they have to have the same number of parameters.
|
|
409
|
+
*
|
|
410
|
+
* Used conventions:
|
|
411
|
+
* - \f$ inf - inf = NaN \f$,
|
|
412
|
+
* - \f$ -inf - (-inf) = NaN \f$,
|
|
413
|
+
* - \f$ NaN - b = NaN \f$,
|
|
414
|
+
* - \f$ a - NaN = NaN \f$.
|
|
415
|
+
*
|
|
416
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
417
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
418
|
+
*
|
|
419
|
+
* @param result First element of the subtraction.
|
|
420
|
+
* @param to_subtract Second element of the subtraction.
|
|
421
|
+
* @return Entry-wise \f$ result - to\_subtract \f$.
|
|
422
|
+
*/
|
|
423
|
+
friend One_critical_filtration &operator-=(One_critical_filtration &result,
|
|
424
|
+
const One_critical_filtration &to_subtract) {
|
|
425
|
+
if (result.empty()) return result;
|
|
426
|
+
|
|
427
|
+
if (result.is_nan() || to_subtract.is_nan() || (result.is_plus_inf() && to_subtract.is_plus_inf()) ||
|
|
428
|
+
(result.is_minus_inf() && to_subtract.is_minus_inf())) {
|
|
429
|
+
result = nan();
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
if (result.is_plus_inf() || to_subtract.is_minus_inf()) {
|
|
433
|
+
result = inf();
|
|
434
|
+
return result;
|
|
435
|
+
}
|
|
436
|
+
if (result.is_minus_inf() || to_subtract.is_plus_inf()) {
|
|
437
|
+
result = minus_inf();
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
GUDHI_CHECK(result.size() == to_subtract.size(),
|
|
442
|
+
"Two filtration values with different number of parameters cannot be subtracted.");
|
|
443
|
+
|
|
444
|
+
return apply_operation_with_finite_values_(result, to_subtract, subtract_);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
449
|
+
* \f$ result[i] - to\_subtract \f$.
|
|
450
|
+
*
|
|
451
|
+
* Used conventions:
|
|
452
|
+
* - \f$ inf - inf = NaN \f$,
|
|
453
|
+
* - \f$ -inf - (-inf) = NaN \f$,
|
|
454
|
+
* - \f$ NaN - b = NaN \f$,
|
|
455
|
+
* - \f$ a - NaN = NaN \f$.
|
|
456
|
+
*
|
|
457
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
458
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
459
|
+
*
|
|
460
|
+
* @param result First element of the subtraction.
|
|
461
|
+
* @param to_subtract Second element of the subtraction.
|
|
462
|
+
* @return Entry-wise \f$ result - to\_subtract \f$.
|
|
463
|
+
*/
|
|
464
|
+
friend One_critical_filtration &operator-=(One_critical_filtration &result, const T &to_subtract) {
|
|
465
|
+
if (result.empty()) return result;
|
|
466
|
+
|
|
467
|
+
if (result.is_nan() || is_nan_(to_subtract) || (result.is_plus_inf() && to_subtract == T_inf) ||
|
|
468
|
+
(result.is_minus_inf() && to_subtract == -T_inf)) {
|
|
469
|
+
result = nan();
|
|
470
|
+
return result;
|
|
471
|
+
}
|
|
472
|
+
if (result.is_plus_inf() || to_subtract == -T_inf) {
|
|
473
|
+
result = inf();
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
if (result.is_minus_inf() || to_subtract == T_inf) {
|
|
477
|
+
result = minus_inf();
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return apply_scalar_operation_on_finite_value_(result, to_subtract, subtract_);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// addition
|
|
485
|
+
/**
|
|
486
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ a[i] + b[i] \f$.
|
|
487
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
488
|
+
*
|
|
489
|
+
* Used conventions:
|
|
490
|
+
* - \f$ NaN + b = NaN \f$,
|
|
491
|
+
* - \f$ a + NaN = NaN \f$.
|
|
492
|
+
*
|
|
493
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
494
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
495
|
+
*
|
|
496
|
+
* @param a First element of the addition.
|
|
497
|
+
* @param b Second element of the addition.
|
|
498
|
+
* @return Entry-wise \f$ a + b \f$.
|
|
499
|
+
*/
|
|
500
|
+
friend One_critical_filtration operator+(One_critical_filtration a, const One_critical_filtration &b) {
|
|
501
|
+
a += b;
|
|
502
|
+
return a;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ f[i] + val \f$.
|
|
507
|
+
*
|
|
508
|
+
* Used conventions:
|
|
509
|
+
* - \f$ NaN + b = NaN \f$,
|
|
510
|
+
* - \f$ a + NaN = NaN \f$.
|
|
511
|
+
*
|
|
512
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
513
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
514
|
+
*
|
|
515
|
+
* @param f First element of the addition.
|
|
516
|
+
* @param val Second element of the addition.
|
|
517
|
+
* @return Entry-wise \f$ f + val \f$.
|
|
518
|
+
*/
|
|
519
|
+
friend One_critical_filtration operator+(One_critical_filtration f, const T &val) {
|
|
520
|
+
f += val;
|
|
521
|
+
return f;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ val + f[i] \f$.
|
|
526
|
+
*
|
|
527
|
+
* Used conventions:
|
|
528
|
+
* - \f$ NaN + b = NaN \f$,
|
|
529
|
+
* - \f$ a + NaN = NaN \f$.
|
|
530
|
+
*
|
|
531
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
532
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
533
|
+
*
|
|
534
|
+
* @param val First element of the addition.
|
|
535
|
+
* @param f Second element of the addition.
|
|
536
|
+
* @return Entry-wise \f$ val + f \f$.
|
|
537
|
+
*/
|
|
538
|
+
friend One_critical_filtration operator+(const T &val, One_critical_filtration f) {
|
|
539
|
+
f += val;
|
|
540
|
+
return f;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
545
|
+
* \f$ result[i] + to\_add[i] \f$.
|
|
546
|
+
* If @p result and @p to_add are both not infinite or NaN, they have to have the same number of parameters.
|
|
547
|
+
*
|
|
548
|
+
* Used conventions:
|
|
549
|
+
* - \f$ NaN + b = NaN \f$,
|
|
550
|
+
* - \f$ a + NaN = NaN \f$.
|
|
551
|
+
*
|
|
552
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
553
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
554
|
+
*
|
|
555
|
+
* @param result First element of the addition.
|
|
556
|
+
* @param to_add Second element of the addition.
|
|
557
|
+
* @return Entry-wise \f$ result + to\_add \f$.
|
|
558
|
+
*/
|
|
559
|
+
friend One_critical_filtration &operator+=(One_critical_filtration &result, const One_critical_filtration &to_add) {
|
|
560
|
+
if (result.empty()) return result;
|
|
561
|
+
|
|
562
|
+
if (result.is_nan() || to_add.is_nan() || (result.is_plus_inf() && to_add.is_minus_inf()) ||
|
|
563
|
+
(result.is_minus_inf() && to_add.is_plus_inf())) {
|
|
564
|
+
result = nan();
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
567
|
+
if (result.is_plus_inf() || to_add.is_plus_inf()) {
|
|
568
|
+
result = inf();
|
|
569
|
+
return result;
|
|
570
|
+
}
|
|
571
|
+
if (result.is_minus_inf() || to_add.is_minus_inf()) {
|
|
572
|
+
result = minus_inf();
|
|
573
|
+
return result;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
GUDHI_CHECK(result.size() == to_add.size(),
|
|
577
|
+
"Two filtration values with different number of parameters cannot be added.");
|
|
578
|
+
|
|
579
|
+
return apply_operation_with_finite_values_(result, to_add, add_);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
584
|
+
* \f$ result[i] + to\_add \f$.
|
|
585
|
+
*
|
|
586
|
+
* Used conventions:
|
|
587
|
+
* - \f$ NaN + b = NaN \f$,
|
|
588
|
+
* - \f$ a + NaN = NaN \f$.
|
|
589
|
+
*
|
|
590
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
591
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
592
|
+
*
|
|
593
|
+
* @param result First element of the addition.
|
|
594
|
+
* @param to_add Second element of the addition.
|
|
595
|
+
* @return Entry-wise \f$ result + to\_add \f$.
|
|
596
|
+
*/
|
|
597
|
+
friend One_critical_filtration &operator+=(One_critical_filtration &result, const T &to_add) {
|
|
598
|
+
if (result.empty()) return result;
|
|
599
|
+
|
|
600
|
+
if (result.is_nan() || is_nan_(to_add) || (result.is_plus_inf() && to_add == -T_inf) ||
|
|
601
|
+
(result.is_minus_inf() && to_add == T_inf)) {
|
|
602
|
+
result = nan();
|
|
603
|
+
return result;
|
|
604
|
+
}
|
|
605
|
+
if (result.is_plus_inf() || to_add == T_inf) {
|
|
606
|
+
result = inf();
|
|
607
|
+
return result;
|
|
608
|
+
}
|
|
609
|
+
if (result.is_minus_inf() || to_add == -T_inf) {
|
|
610
|
+
result = minus_inf();
|
|
611
|
+
return result;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
return apply_scalar_operation_on_finite_value_(result, to_add, add_);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// multiplication
|
|
618
|
+
/**
|
|
619
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ a[i] * b[i] \f$.
|
|
620
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
621
|
+
*
|
|
622
|
+
* Used conventions:
|
|
623
|
+
* - \f$ inf * 0 = NaN \f$,
|
|
624
|
+
* - \f$ 0 * inf = NaN \f$,
|
|
625
|
+
* - \f$ -inf * 0 = NaN \f$,
|
|
626
|
+
* - \f$ 0 * -inf = NaN \f$,
|
|
627
|
+
* - \f$ NaN * b = NaN \f$,
|
|
628
|
+
* - \f$ a * NaN = NaN \f$.
|
|
629
|
+
*
|
|
630
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
631
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
632
|
+
*
|
|
633
|
+
* @param a First element of the multiplication.
|
|
634
|
+
* @param b Second element of the multiplication.
|
|
635
|
+
* @return Entry-wise \f$ a * b \f$.
|
|
636
|
+
*/
|
|
637
|
+
friend One_critical_filtration operator*(One_critical_filtration a, const One_critical_filtration &b) {
|
|
638
|
+
a *= b;
|
|
639
|
+
return a;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ f[i] * val \f$.
|
|
644
|
+
*
|
|
645
|
+
* Used conventions:
|
|
646
|
+
* - \f$ inf * 0 = NaN \f$,
|
|
647
|
+
* - \f$ 0 * inf = NaN \f$,
|
|
648
|
+
* - \f$ -inf * 0 = NaN \f$,
|
|
649
|
+
* - \f$ 0 * -inf = NaN \f$,
|
|
650
|
+
* - \f$ NaN * b = NaN \f$,
|
|
651
|
+
* - \f$ a * NaN = NaN \f$.
|
|
652
|
+
*
|
|
653
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
654
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
655
|
+
*
|
|
656
|
+
* @param f First element of the multiplication.
|
|
657
|
+
* @param val Second element of the multiplication.
|
|
658
|
+
* @return Entry-wise \f$ f * val \f$.
|
|
659
|
+
*/
|
|
660
|
+
friend One_critical_filtration operator*(One_critical_filtration f, const T &val) {
|
|
661
|
+
f *= val;
|
|
662
|
+
return f;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ val * f[i] \f$.
|
|
667
|
+
*
|
|
668
|
+
* Used conventions:
|
|
669
|
+
* - \f$ inf * 0 = NaN \f$,
|
|
670
|
+
* - \f$ 0 * inf = NaN \f$,
|
|
671
|
+
* - \f$ -inf * 0 = NaN \f$,
|
|
672
|
+
* - \f$ 0 * -inf = NaN \f$,
|
|
673
|
+
* - \f$ NaN * b = NaN \f$,
|
|
674
|
+
* - \f$ a * NaN = NaN \f$.
|
|
675
|
+
*
|
|
676
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
677
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
678
|
+
*
|
|
679
|
+
* @param val First element of the multiplication.
|
|
680
|
+
* @param f Second element of the multiplication.
|
|
681
|
+
* @return Entry-wise \f$ val * f \f$.
|
|
682
|
+
*/
|
|
683
|
+
friend One_critical_filtration operator*(const T &val, One_critical_filtration f) {
|
|
684
|
+
f *= val;
|
|
685
|
+
return f;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
690
|
+
* \f$ result[i] * to\_mul[i] \f$.
|
|
691
|
+
* If @p result and @p to_mul are both not infinite or NaN, they have to have the same number of parameters.
|
|
692
|
+
*
|
|
693
|
+
* Used conventions:
|
|
694
|
+
* - \f$ inf * 0 = NaN \f$,
|
|
695
|
+
* - \f$ 0 * inf = NaN \f$,
|
|
696
|
+
* - \f$ -inf * 0 = NaN \f$,
|
|
697
|
+
* - \f$ 0 * -inf = NaN \f$,
|
|
698
|
+
* - \f$ NaN * b = NaN \f$,
|
|
699
|
+
* - \f$ a * NaN = NaN \f$.
|
|
700
|
+
*
|
|
701
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
702
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
703
|
+
*
|
|
704
|
+
* @param result First element of the multiplication.
|
|
705
|
+
* @param to_mul Second element of the multiplication.
|
|
706
|
+
* @return Entry-wise \f$ result * to\_mul \f$.
|
|
707
|
+
*/
|
|
708
|
+
friend One_critical_filtration &operator*=(One_critical_filtration &result, const One_critical_filtration &to_mul) {
|
|
709
|
+
if (result.empty()) return result;
|
|
710
|
+
|
|
711
|
+
if (result.is_nan() || to_mul.is_nan()) {
|
|
712
|
+
result = nan();
|
|
713
|
+
return result;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
bool res_is_infinite = result.is_plus_inf() || result.is_minus_inf();
|
|
717
|
+
bool to_mul_is_infinite = to_mul.is_plus_inf() || to_mul.is_minus_inf();
|
|
718
|
+
|
|
719
|
+
if (res_is_infinite && to_mul_is_infinite) {
|
|
720
|
+
if (to_mul.is_minus_inf()) {
|
|
721
|
+
result[0] = -result[0];
|
|
722
|
+
}
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (res_is_infinite || to_mul_is_infinite) {
|
|
727
|
+
const One_critical_filtration &finite = res_is_infinite ? to_mul : result;
|
|
728
|
+
const T infinite = res_is_infinite ? result[0] : to_mul[0];
|
|
729
|
+
result = finite;
|
|
730
|
+
return apply_scalar_operation_on_finite_value_(result, infinite, multiply_);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
GUDHI_CHECK(result.size() == to_mul.size(),
|
|
734
|
+
"Two filtration values with different number of parameters cannot be multiplied.");
|
|
735
|
+
|
|
736
|
+
return apply_operation_with_finite_values_(result, to_mul, multiply_);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
741
|
+
* \f$ result[i] * to\_mul \f$.
|
|
742
|
+
*
|
|
743
|
+
* Used conventions:
|
|
744
|
+
* - \f$ inf * 0 = NaN \f$,
|
|
745
|
+
* - \f$ 0 * inf = NaN \f$,
|
|
746
|
+
* - \f$ -inf * 0 = NaN \f$,
|
|
747
|
+
* - \f$ 0 * -inf = NaN \f$,
|
|
748
|
+
* - \f$ NaN * b = NaN \f$,
|
|
749
|
+
* - \f$ a * NaN = NaN \f$.
|
|
750
|
+
*
|
|
751
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
752
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
753
|
+
*
|
|
754
|
+
* @param result First element of the multiplication.
|
|
755
|
+
* @param to_mul Second element of the multiplication.
|
|
756
|
+
* @return Entry-wise \f$ result * to\_mul \f$.
|
|
757
|
+
*/
|
|
758
|
+
friend One_critical_filtration &operator*=(One_critical_filtration &result, const T &to_mul) {
|
|
759
|
+
if (result.empty()) return result;
|
|
760
|
+
|
|
761
|
+
if (result.is_nan() || is_nan_(to_mul)) {
|
|
762
|
+
result = nan();
|
|
763
|
+
return result;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (result.is_plus_inf() || result.is_minus_inf()) {
|
|
767
|
+
if (to_mul == 0)
|
|
768
|
+
result = nan();
|
|
769
|
+
else if (to_mul < 0)
|
|
770
|
+
result[0] = -result[0];
|
|
771
|
+
return result;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
return apply_scalar_operation_on_finite_value_(result, to_mul, multiply_);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// division
|
|
778
|
+
/**
|
|
779
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ a[i] / b[i] \f$.
|
|
780
|
+
* If @p a and @p b are both not infinite or NaN, they have to have the same number of parameters.
|
|
781
|
+
*
|
|
782
|
+
* Used conventions:
|
|
783
|
+
* - \f$ a / 0 = NaN \f$,
|
|
784
|
+
* - \f$ inf / inf = NaN \f$,
|
|
785
|
+
* - \f$ -inf / inf = NaN \f$,
|
|
786
|
+
* - \f$ inf / -inf = NaN \f$,
|
|
787
|
+
* - \f$ -inf / -inf = NaN \f$,
|
|
788
|
+
* - \f$ NaN / b = NaN \f$,
|
|
789
|
+
* - \f$ a / NaN = NaN \f$,
|
|
790
|
+
* - \f$ a / inf = 0 \f$,
|
|
791
|
+
* - \f$ a / -inf = 0 \f$.
|
|
792
|
+
*
|
|
793
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
794
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
795
|
+
*
|
|
796
|
+
* @param a First element of the division.
|
|
797
|
+
* @param b Second element of the division.
|
|
798
|
+
* @return Entry-wise \f$ a / b \f$.
|
|
799
|
+
*/
|
|
800
|
+
friend One_critical_filtration operator/(One_critical_filtration a, const One_critical_filtration &b) {
|
|
801
|
+
a /= b;
|
|
802
|
+
return a;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ f[i] / val \f$.
|
|
807
|
+
*
|
|
808
|
+
* Used conventions:
|
|
809
|
+
* - \f$ a / 0 = NaN \f$,
|
|
810
|
+
* - \f$ inf / inf = NaN \f$,
|
|
811
|
+
* - \f$ -inf / inf = NaN \f$,
|
|
812
|
+
* - \f$ inf / -inf = NaN \f$,
|
|
813
|
+
* - \f$ -inf / -inf = NaN \f$,
|
|
814
|
+
* - \f$ NaN / b = NaN \f$,
|
|
815
|
+
* - \f$ a / NaN = NaN \f$,
|
|
816
|
+
* - \f$ a / inf = 0 \f$,
|
|
817
|
+
* - \f$ a / -inf = 0 \f$.
|
|
818
|
+
*
|
|
819
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
820
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
821
|
+
*
|
|
822
|
+
* @param f First element of the division.
|
|
823
|
+
* @param val Second element of the division.
|
|
824
|
+
* @return Entry-wise \f$ f / val \f$.
|
|
825
|
+
*/
|
|
826
|
+
friend One_critical_filtration operator/(One_critical_filtration f, const T &val) {
|
|
827
|
+
f /= val;
|
|
828
|
+
return f;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* @brief Returns a filtration value such that an entry at index \f$ i \f$ is equal to \f$ val / f[i] \f$.
|
|
833
|
+
*
|
|
834
|
+
* Used conventions:
|
|
835
|
+
* - \f$ a / 0 = NaN \f$,
|
|
836
|
+
* - \f$ inf / inf = NaN \f$,
|
|
837
|
+
* - \f$ -inf / inf = NaN \f$,
|
|
838
|
+
* - \f$ inf / -inf = NaN \f$,
|
|
839
|
+
* - \f$ -inf / -inf = NaN \f$,
|
|
840
|
+
* - \f$ NaN / b = NaN \f$,
|
|
841
|
+
* - \f$ a / NaN = NaN \f$,
|
|
842
|
+
* - \f$ a / inf = 0 \f$,
|
|
843
|
+
* - \f$ a / -inf = 0 \f$.
|
|
844
|
+
*
|
|
845
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
846
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
847
|
+
*
|
|
848
|
+
* @param val First element of the division.
|
|
849
|
+
* @param f Second element of the division.
|
|
850
|
+
* @return Entry-wise \f$ val / f \f$.
|
|
851
|
+
*/
|
|
852
|
+
friend One_critical_filtration operator/(const T &val, const One_critical_filtration &f) {
|
|
853
|
+
if (f.empty()) return f;
|
|
854
|
+
if (is_nan_(val) || f.is_nan()) return nan();
|
|
855
|
+
|
|
856
|
+
One_critical_filtration result(f.size(), val);
|
|
857
|
+
result /= f;
|
|
858
|
+
return result;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
863
|
+
* \f$ result[i] / to\_div[i] \f$.
|
|
864
|
+
* If @p result and @p to_div are both not infinite or NaN, they have to have the same number of parameters.
|
|
865
|
+
*
|
|
866
|
+
* Used conventions:
|
|
867
|
+
* - \f$ a / 0 = NaN \f$,
|
|
868
|
+
* - \f$ inf / inf = NaN \f$,
|
|
869
|
+
* - \f$ -inf / inf = NaN \f$,
|
|
870
|
+
* - \f$ inf / -inf = NaN \f$,
|
|
871
|
+
* - \f$ -inf / -inf = NaN \f$,
|
|
872
|
+
* - \f$ NaN / b = NaN \f$,
|
|
873
|
+
* - \f$ a / NaN = NaN \f$,
|
|
874
|
+
* - \f$ a / inf = 0 \f$,
|
|
875
|
+
* - \f$ a / -inf = 0 \f$.
|
|
876
|
+
*
|
|
877
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
878
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
879
|
+
*
|
|
880
|
+
* @param result First element of the division.
|
|
881
|
+
* @param to_div Second element of the division.
|
|
882
|
+
* @return Entry-wise \f$ result / to\_div \f$.
|
|
883
|
+
*/
|
|
884
|
+
friend One_critical_filtration &operator/=(One_critical_filtration &result, const One_critical_filtration &to_div) {
|
|
885
|
+
if (result.empty()) return result;
|
|
886
|
+
|
|
887
|
+
bool res_is_infinite = result.is_plus_inf() || result.is_minus_inf();
|
|
888
|
+
bool to_div_is_infinite = to_div.is_plus_inf() || to_div.is_minus_inf();
|
|
889
|
+
|
|
890
|
+
if (result.is_nan() || to_div.is_nan() || (res_is_infinite && to_div_is_infinite)) {
|
|
891
|
+
result = nan();
|
|
892
|
+
return result;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (to_div_is_infinite) {
|
|
896
|
+
return apply_scalar_operation_on_finite_value_with_all_nan_possible_(result, to_div[0], divide_);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
GUDHI_CHECK(res_is_infinite || result.size() == to_div.size(),
|
|
900
|
+
"Two filtration values with different number of parameters cannot be divided.");
|
|
901
|
+
|
|
902
|
+
if (res_is_infinite) {
|
|
903
|
+
result.resize(to_div.size(), result[0]);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
return apply_operation_with_finite_values_(result, to_div, divide_);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
constexpr static bool is_multicritical() { return false; }
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* @brief Modifies the first parameters such that an entry at index \f$ i \f$ is equal to
|
|
913
|
+
* \f$ result[i] / to\_div \f$.
|
|
914
|
+
*
|
|
915
|
+
* Used conventions:
|
|
916
|
+
* - \f$ a / 0 = NaN \f$,
|
|
917
|
+
* - \f$ inf / inf = NaN \f$,
|
|
918
|
+
* - \f$ -inf / inf = NaN \f$,
|
|
919
|
+
* - \f$ inf / -inf = NaN \f$,
|
|
920
|
+
* - \f$ -inf / -inf = NaN \f$,
|
|
921
|
+
* - \f$ NaN / b = NaN \f$,
|
|
922
|
+
* - \f$ a / NaN = NaN \f$,
|
|
923
|
+
* - \f$ a / inf = 0 \f$,
|
|
924
|
+
* - \f$ a / -inf = 0 \f$.
|
|
925
|
+
*
|
|
926
|
+
* If `std::numeric_limits<T>::has_quiet_NaN` is false, then the returned filtration value will be @ref nan()
|
|
927
|
+
* if any operation results in NaN, not only if all operations result in NaN.
|
|
928
|
+
*
|
|
929
|
+
* @param result First element of the division.
|
|
930
|
+
* @param to_div Second element of the division.
|
|
931
|
+
* @return Entry-wise \f$ result / to\_div \f$.
|
|
932
|
+
*/
|
|
933
|
+
friend One_critical_filtration &operator/=(One_critical_filtration &result, const T &to_div) {
|
|
934
|
+
if (result.empty()) return result;
|
|
935
|
+
|
|
936
|
+
bool res_is_infinite = result.is_plus_inf() || result.is_minus_inf();
|
|
937
|
+
bool to_div_is_infinite = to_div == T_inf || to_div == -T_inf;
|
|
938
|
+
|
|
939
|
+
if (to_div == 0 || is_nan_(to_div) || result.is_nan() || (res_is_infinite && to_div_is_infinite)) {
|
|
940
|
+
result = nan();
|
|
941
|
+
return result;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
if (res_is_infinite) {
|
|
945
|
+
if (to_div < 0) result[0] = -result[0];
|
|
946
|
+
return result;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
return apply_scalar_operation_on_finite_value_with_all_nan_possible_(result, to_div, divide_);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// MODIFIERS
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* @brief Sets the filtration value to the least common upper bound between the current value and the given value.
|
|
956
|
+
*
|
|
957
|
+
* More formally, it pushes the current filtration value to the cone \f$ \{ y \in \mathbb R^n : y \ge x \} \f$
|
|
958
|
+
* originating in the given filtration value \f$ x \f$. The resulting value corresponds to the intersection of both
|
|
959
|
+
* cones: \f$ \mathrm{this} = \min \{ y \in \mathbb R^n : y \ge this \} \cap \{ y \in \mathbb R^n : y \ge x \} \f$.
|
|
960
|
+
*
|
|
961
|
+
* @param x The target filtration value towards which to push.
|
|
962
|
+
* @return True if and only if the value of this actually changed.
|
|
963
|
+
*/
|
|
964
|
+
bool push_to_least_common_upper_bound(const One_critical_filtration &x) {
|
|
965
|
+
if (this->is_plus_inf() || this->is_nan() || x.is_nan() || x.is_minus_inf()) return false;
|
|
966
|
+
if (x.is_plus_inf() || this->is_minus_inf()) {
|
|
967
|
+
if (!x.is_minus_inf() && !this->is_plus_inf()) {
|
|
968
|
+
*this = x;
|
|
969
|
+
return true;
|
|
970
|
+
}
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
GUDHI_CHECK(this->num_parameters() == x.num_parameters(),
|
|
975
|
+
"A filtration value cannot be pushed to another one with different numbers of parameters.");
|
|
976
|
+
|
|
977
|
+
bool modified = false;
|
|
978
|
+
for (std::size_t i = 0; i < x.num_parameters(); i++) {
|
|
979
|
+
modified |= Base::operator[](i) < x[i];
|
|
980
|
+
Base::operator[](i) = Base::operator[](i) > x[i] ? Base::operator[](i) : x[i];
|
|
981
|
+
}
|
|
982
|
+
return modified;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* @brief Sets the filtration value to the greatest common lower bound between the current value and the given value.
|
|
987
|
+
*
|
|
988
|
+
* More formally, it pulls the current filtration value to the cone \f$ \{ y \in \mathbb R^n : y \le x \} \f$
|
|
989
|
+
* originating in the given filtration value \f$ x \f$. The resulting value corresponds to the intersection of both
|
|
990
|
+
* cones: \f$ \mathrm{this} = \min \{ y \in \mathbb R^n : y \le this \} \cap \{ y \in \mathbb R^n : y \le x \} \f$.
|
|
991
|
+
*
|
|
992
|
+
* @param x The target filtration value towards which to pull.
|
|
993
|
+
* @return True if and only if the value of this actually changed.
|
|
994
|
+
*/
|
|
995
|
+
bool pull_to_greatest_common_lower_bound(const One_critical_filtration &x) {
|
|
996
|
+
if (x.is_plus_inf() || this->is_nan() || x.is_nan() || this->is_minus_inf()) return false;
|
|
997
|
+
if (this->is_plus_inf() || x.is_minus_inf()) {
|
|
998
|
+
if (!x.is_plus_inf() && !this->is_minus_inf()) {
|
|
999
|
+
*this = x;
|
|
1000
|
+
return true;
|
|
1001
|
+
}
|
|
1002
|
+
return false;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
GUDHI_CHECK(this->num_parameters() == x.num_parameters(),
|
|
1006
|
+
"A filtration value cannot be pulled to another one with different numbers of parameters.");
|
|
1007
|
+
|
|
1008
|
+
bool modified = false;
|
|
1009
|
+
for (std::size_t i = 0; i < x.num_parameters(); i++) {
|
|
1010
|
+
modified |= Base::operator[](i) > x[i];
|
|
1011
|
+
Base::operator[](i) = Base::operator[](i) > x[i] ? x[i] : Base::operator[](i);
|
|
1012
|
+
}
|
|
1013
|
+
return modified;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* @brief Projects the filtration value into the given grid. If @p coordinate is false, the entries are set to
|
|
1018
|
+
* the nearest upper bound value with the same parameter in the grid. Otherwise, the entries are set to the indices
|
|
1019
|
+
* of those nearest upper bound values.
|
|
1020
|
+
* The grid has to be represented as a vector of ordered ranges of values convertible into `T`. An index
|
|
1021
|
+
* \f$ i \f$ of the vector corresponds to the same parameter as the index \f$ i \f$ in the filtration value.
|
|
1022
|
+
* The ranges correspond to the possible values of the parameters, ordered by increasing value, forming therefore
|
|
1023
|
+
* all together a 2D grid.
|
|
1024
|
+
*
|
|
1025
|
+
* @tparam oned_array A range of values convertible into `T` ordered by increasing value. Has to implement
|
|
1026
|
+
* a begin, end and operator[] method.
|
|
1027
|
+
* @param grid Vector of @p oned_array with size at least number of filtration parameters.
|
|
1028
|
+
* @param coordinate If true, the values are set to the coordinates of the projection in the grid. If false,
|
|
1029
|
+
* the values are set to the values at the coordinates of the projection.
|
|
1030
|
+
*/
|
|
1031
|
+
template <typename oned_array>
|
|
1032
|
+
void project_onto_grid(const std::vector<oned_array> &grid, bool coordinate = true) {
|
|
1033
|
+
GUDHI_CHECK(grid.size() >= Base::size(),
|
|
1034
|
+
"The grid should not be smaller than the number of parameters in the filtration value.");
|
|
1035
|
+
for (std::size_t parameter = 0u; parameter < Base::size(); ++parameter) {
|
|
1036
|
+
const auto &filtration = grid[parameter];
|
|
1037
|
+
int num_filtration_values = filtration.size();
|
|
1038
|
+
auto this_at_param = static_cast<typename oned_array::value_type>(Base::operator[](parameter));
|
|
1039
|
+
auto it = std::lower_bound(filtration.begin(), filtration.end(), this_at_param);
|
|
1040
|
+
std::size_t idx;
|
|
1041
|
+
if (it == filtration.end()) {
|
|
1042
|
+
idx = num_filtration_values - 1;
|
|
1043
|
+
} else if (it == filtration.begin()) {
|
|
1044
|
+
idx = 0;
|
|
1045
|
+
} else {
|
|
1046
|
+
auto prev = it - 1;
|
|
1047
|
+
idx = (std::abs(*prev - this_at_param) <= std::abs(*it - this_at_param))
|
|
1048
|
+
? std::distance(filtration.begin(), prev)
|
|
1049
|
+
: std::distance(filtration.begin(), it);
|
|
1050
|
+
}
|
|
1051
|
+
Base::operator[](parameter) = coordinate ? static_cast<T>(idx) : static_cast<T>(filtration[idx]);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// FONCTIONNALITIES
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* @brief Computes the scalar product of the given filtration value with the given vector.
|
|
1059
|
+
*
|
|
1060
|
+
* @tparam U Arithmetic type of the result. Default value: `T`.
|
|
1061
|
+
* @param f Filtration value.
|
|
1062
|
+
* @param x Vector of coefficients.
|
|
1063
|
+
* @return Scalar product of @p f with @p x.
|
|
1064
|
+
*/
|
|
1065
|
+
template <typename U = T>
|
|
1066
|
+
friend U compute_linear_projection(const One_critical_filtration &f, const std::vector<U> &x) {
|
|
1067
|
+
U projection = 0;
|
|
1068
|
+
std::size_t size = std::min(x.size(), f.size());
|
|
1069
|
+
for (std::size_t i = 0u; i < size; i++) projection += x[i] * static_cast<U>(f[i]);
|
|
1070
|
+
return projection;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* @brief Computes the norm of the given filtration value.
|
|
1075
|
+
*
|
|
1076
|
+
* @param f Filtration value.
|
|
1077
|
+
* @return The norm of @p f.
|
|
1078
|
+
*/
|
|
1079
|
+
friend T compute_norm(const One_critical_filtration &f) {
|
|
1080
|
+
T out = 0;
|
|
1081
|
+
for (auto &val : f) out += (val * val);
|
|
1082
|
+
if constexpr (std::is_integral_v<T>) {
|
|
1083
|
+
// to avoid Windows issue which don't know how to cast integers for cmath methods
|
|
1084
|
+
return std::sqrt(static_cast<double>(out));
|
|
1085
|
+
} else {
|
|
1086
|
+
return std::sqrt(out);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* @brief Computes the euclidean distance from the first parameter to the second parameter.
|
|
1092
|
+
*
|
|
1093
|
+
* @param f Start filtration value.
|
|
1094
|
+
* @param other End filtration value.
|
|
1095
|
+
* @return Euclidean distance between @p f and @p other.
|
|
1096
|
+
*/
|
|
1097
|
+
friend T compute_euclidean_distance_to(const One_critical_filtration &f, const One_critical_filtration &other) {
|
|
1098
|
+
T out = 0;
|
|
1099
|
+
for (std::size_t i = 0u; i < other.size(); i++) {
|
|
1100
|
+
out += (f[i] - other[i]) * (f[i] - other[i]);
|
|
1101
|
+
}
|
|
1102
|
+
if constexpr (std::is_integral_v<T>) {
|
|
1103
|
+
// to avoid Windows issue which don't know how to cast integers for cmath methods
|
|
1104
|
+
return std::sqrt(static_cast<double>(out));
|
|
1105
|
+
} else {
|
|
1106
|
+
return std::sqrt(out);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* @brief Computes the coordinates in the given grid, corresponding to the nearest upper bounds of the entries
|
|
1112
|
+
* in the given filtration value.
|
|
1113
|
+
* The grid has to be represented as a vector of vectors of ordered values convertible into `out_type`. An index
|
|
1114
|
+
* \f$ i \f$ of the vector corresponds to the same parameter as the index \f$ i \f$ in the filtration value.
|
|
1115
|
+
* The inner vectors correspond to the possible values of the parameters, ordered by increasing value,
|
|
1116
|
+
* forming therefore all together a 2D grid.
|
|
1117
|
+
*
|
|
1118
|
+
* @tparam out_type Signed arithmetic type. Default value: std::int32_t.
|
|
1119
|
+
* @tparam U Type which is convertible into `out_type`.
|
|
1120
|
+
* @param f Filtration value to project.
|
|
1121
|
+
* @param grid Vector of vectors to project into.
|
|
1122
|
+
* @return Filtration value \f$ out \f$ whose entry correspond to the indices of the projected values. That is,
|
|
1123
|
+
* the projection of \f$ f[i] \f$ is \f$ grid[i][out[i]] \f$.
|
|
1124
|
+
*/
|
|
1125
|
+
template <typename out_type = std::int32_t, typename U = T>
|
|
1126
|
+
friend One_critical_filtration<out_type> compute_coordinates_in_grid(One_critical_filtration f,
|
|
1127
|
+
const std::vector<std::vector<U> > &grid) {
|
|
1128
|
+
// TODO: by replicating the code of "project_onto_grid", this could be done with just one copy
|
|
1129
|
+
// instead of two. But it is not clear if it is really worth it, i.e., how much the change in type is really
|
|
1130
|
+
// necessary in the use cases. To see later.
|
|
1131
|
+
f.project_onto_grid(grid);
|
|
1132
|
+
if constexpr (std::is_same_v<out_type, T>) {
|
|
1133
|
+
return f;
|
|
1134
|
+
} else {
|
|
1135
|
+
return f.as_type<out_type>();
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* @brief Computes the values in the given grid corresponding to the coordinates given by the given filtration
|
|
1141
|
+
* value. That is, if \f$ out \f$ is the result, \f$ out[i] = grid[i][f[i]] \f$. Assumes therefore, that the
|
|
1142
|
+
* values stored in the filtration value corresponds to indices existing in the given grid.
|
|
1143
|
+
*
|
|
1144
|
+
* @tparam U Signed arithmetic type.
|
|
1145
|
+
* @param f Filtration value storing coordinates compatible with `grid`.
|
|
1146
|
+
* @param grid Vector of vector.
|
|
1147
|
+
* @return Filtration value \f$ out \f$ whose entry correspond to \f$ out[i] = grid[i][f[i]] \f$.
|
|
1148
|
+
*/
|
|
1149
|
+
template <typename U>
|
|
1150
|
+
friend One_critical_filtration<U> evaluate_coordinates_in_grid(const One_critical_filtration &f,
|
|
1151
|
+
const std::vector<std::vector<U> > &grid) {
|
|
1152
|
+
One_critical_filtration<U> pushed_value(f.size());
|
|
1153
|
+
|
|
1154
|
+
GUDHI_CHECK(grid.size() == f.size(),
|
|
1155
|
+
"The size of the grid should correspond to the number of parameters in the filtration value.");
|
|
1156
|
+
|
|
1157
|
+
U grid_inf = One_critical_filtration<U>::T_inf;
|
|
1158
|
+
|
|
1159
|
+
for (std::size_t parameter = 0u; parameter < grid.size(); ++parameter) {
|
|
1160
|
+
const auto &filtration = grid[parameter];
|
|
1161
|
+
const auto &c = f[parameter];
|
|
1162
|
+
pushed_value[parameter] = c == f.T_inf ? grid_inf : filtration[c];
|
|
1163
|
+
}
|
|
1164
|
+
return pushed_value;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// UTILITIES
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* @brief Outstream operator.
|
|
1171
|
+
*/
|
|
1172
|
+
friend std::ostream &operator<<(std::ostream &stream, const One_critical_filtration &f) {
|
|
1173
|
+
if (f.is_plus_inf()) {
|
|
1174
|
+
stream << "[inf, ..., inf]";
|
|
1175
|
+
return stream;
|
|
1176
|
+
}
|
|
1177
|
+
if (f.is_minus_inf()) {
|
|
1178
|
+
stream << "[-inf, ..., -inf]";
|
|
1179
|
+
return stream;
|
|
1180
|
+
}
|
|
1181
|
+
if (f.is_nan()) {
|
|
1182
|
+
stream << "[NaN]";
|
|
1183
|
+
return stream;
|
|
1184
|
+
}
|
|
1185
|
+
if (f.empty()) {
|
|
1186
|
+
stream << "[]";
|
|
1187
|
+
return stream;
|
|
1188
|
+
}
|
|
1189
|
+
stream << "[";
|
|
1190
|
+
for (std::size_t i = 0; i < f.size() - 1; i++) {
|
|
1191
|
+
stream << f[i] << ", ";
|
|
1192
|
+
}
|
|
1193
|
+
stream << f.back();
|
|
1194
|
+
stream << "]";
|
|
1195
|
+
return stream;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
friend bool unify_lifetimes(One_critical_filtration &f1, const One_critical_filtration &f2) {
|
|
1199
|
+
// WARNING: costly check
|
|
1200
|
+
GUDHI_CHECK(f1 <= f2 || f2 <= f1, "When 1-critical, two non-comparable filtration values cannot be unified.");
|
|
1201
|
+
|
|
1202
|
+
return f1.pull_to_greatest_common_lower_bound(f2);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
friend bool intersect_lifetimes(One_critical_filtration &f1, const One_critical_filtration &f2) {
|
|
1206
|
+
return f1.push_to_least_common_upper_bound(f2);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
friend char *serialize_trivial(const One_critical_filtration &value, char *start) {
|
|
1210
|
+
const auto length = value.size();
|
|
1211
|
+
const std::size_t arg_size = sizeof(T) * length;
|
|
1212
|
+
const std::size_t type_size = sizeof(typename One_critical_filtration::Base::size_type);
|
|
1213
|
+
memcpy(start, &length, type_size);
|
|
1214
|
+
memcpy(start + type_size, value.data(), arg_size);
|
|
1215
|
+
return start + arg_size + type_size;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
friend const char *deserialize_trivial(One_critical_filtration &value, const char *start) {
|
|
1219
|
+
const std::size_t type_size = sizeof(typename One_critical_filtration::Base::size_type);
|
|
1220
|
+
typename One_critical_filtration::Base::size_type length;
|
|
1221
|
+
memcpy(&length, start, type_size);
|
|
1222
|
+
std::size_t arg_size = sizeof(T) * length;
|
|
1223
|
+
value.resize(length);
|
|
1224
|
+
memcpy(value.data(), start + type_size, arg_size);
|
|
1225
|
+
return start + arg_size + type_size;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
friend std::size_t get_serialization_size_of(const One_critical_filtration &value) {
|
|
1229
|
+
return sizeof(typename One_critical_filtration::Base::size_type) + sizeof(T) * value.size();
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* @brief Infinity value of an entry of the filtration value.
|
|
1234
|
+
*/
|
|
1235
|
+
constexpr static const T T_inf =
|
|
1236
|
+
std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : std::numeric_limits<T>::max();
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* @brief Indicates if the class manages multi-critical filtration values.
|
|
1240
|
+
*/
|
|
1241
|
+
constexpr static bool is_multi_critical = false;
|
|
1242
|
+
|
|
1243
|
+
private:
|
|
1244
|
+
static bool is_nan_(T val) {
|
|
1245
|
+
if constexpr (std::is_integral_v<T>) {
|
|
1246
|
+
// to avoid Windows issue which don't know how to cast integers for cmath methods
|
|
1247
|
+
return false;
|
|
1248
|
+
} else {
|
|
1249
|
+
return std::isnan(val);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
constexpr static bool subtract_(T &v1, T v2) { return add_(v1, -v2); }
|
|
1254
|
+
|
|
1255
|
+
constexpr static bool add_(T &v1, T v2) {
|
|
1256
|
+
if (is_nan_(v1) || is_nan_(v2) || (v1 == T_inf && v2 == -T_inf) || (v1 == -T_inf && v2 == T_inf)) {
|
|
1257
|
+
v1 = std::numeric_limits<T>::quiet_NaN();
|
|
1258
|
+
return false;
|
|
1259
|
+
}
|
|
1260
|
+
if (v1 == T_inf || v1 == -T_inf) {
|
|
1261
|
+
return true;
|
|
1262
|
+
}
|
|
1263
|
+
if (v2 == T_inf || v2 == -T_inf) {
|
|
1264
|
+
v1 = v2;
|
|
1265
|
+
return true;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
v1 += v2;
|
|
1269
|
+
return true;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
constexpr static bool multiply_(T &v1, T v2) {
|
|
1273
|
+
bool v1_is_infinite = v1 == T_inf || v1 == -T_inf;
|
|
1274
|
+
bool v2_is_infinite = v2 == T_inf || v2 == -T_inf;
|
|
1275
|
+
|
|
1276
|
+
if (is_nan_(v1) || is_nan_(v2) || (v1_is_infinite && v2 == 0) || (v1 == 0 && v2_is_infinite)) {
|
|
1277
|
+
v1 = std::numeric_limits<T>::quiet_NaN();
|
|
1278
|
+
return false;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
if ((v1 == T_inf && v2 > 0) || (v1 == -T_inf && v2 < 0) || (v1 < 0 && v2 == -T_inf) || (v1 > 0 && v2 == T_inf)) {
|
|
1282
|
+
v1 = T_inf;
|
|
1283
|
+
return true;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
if ((v1 == T_inf && v2 < 0) || (v1 == -T_inf && v2 > 0) || (v1 > 0 && v2 == -T_inf) || (v1 < 0 && v2 == T_inf)) {
|
|
1287
|
+
v1 = -T_inf;
|
|
1288
|
+
return true;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
v1 *= v2;
|
|
1292
|
+
return true;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
constexpr static bool divide_(T &v1, T v2) {
|
|
1296
|
+
bool v1_is_infinite = v1 == T_inf || v1 == -T_inf;
|
|
1297
|
+
bool v2_is_infinite = v2 == T_inf || v2 == -T_inf;
|
|
1298
|
+
|
|
1299
|
+
if (is_nan_(v1) || is_nan_(v2) || v2 == 0 || (v1_is_infinite && v2_is_infinite)) {
|
|
1300
|
+
v1 = std::numeric_limits<T>::quiet_NaN();
|
|
1301
|
+
return false;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
if (v1 == 0 || (v1_is_infinite && v2 > 0)) return true;
|
|
1305
|
+
|
|
1306
|
+
if (v1_is_infinite && v2 < 0) {
|
|
1307
|
+
v1 = -v1;
|
|
1308
|
+
return true;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
if (v2_is_infinite) {
|
|
1312
|
+
v1 = 0;
|
|
1313
|
+
return true;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
v1 /= v2;
|
|
1317
|
+
return true;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
constexpr static bool update_sign_(T toComp, int &sign) {
|
|
1321
|
+
if (toComp == T_inf) {
|
|
1322
|
+
if (sign == 0)
|
|
1323
|
+
sign = 1;
|
|
1324
|
+
else if (sign == -1)
|
|
1325
|
+
return false;
|
|
1326
|
+
} else if (toComp == -T_inf) {
|
|
1327
|
+
if (sign == 0)
|
|
1328
|
+
sign = -1;
|
|
1329
|
+
else if (sign == 1)
|
|
1330
|
+
return false;
|
|
1331
|
+
} else {
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
return true;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
template <typename F>
|
|
1339
|
+
static One_critical_filtration &apply_operation_with_finite_values_(One_critical_filtration &result,
|
|
1340
|
+
const One_critical_filtration &to_operate,
|
|
1341
|
+
F &&operate) {
|
|
1342
|
+
bool allSameInf = true;
|
|
1343
|
+
bool allNaN = true;
|
|
1344
|
+
int sign = 0;
|
|
1345
|
+
for (auto i = 0u; i < result.size(); ++i) {
|
|
1346
|
+
if (operate(result[i], to_operate[i])) {
|
|
1347
|
+
allNaN = false;
|
|
1348
|
+
} else {
|
|
1349
|
+
if constexpr (!std::numeric_limits<T>::has_quiet_NaN) {
|
|
1350
|
+
result = nan();
|
|
1351
|
+
return result;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
if (allSameInf) allSameInf = update_sign_(result[i], sign);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
if (allSameInf) result = (sign == 1 ? inf() : minus_inf());
|
|
1358
|
+
if (allNaN) result = nan();
|
|
1359
|
+
|
|
1360
|
+
return result;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
template <typename F>
|
|
1364
|
+
static One_critical_filtration &apply_scalar_operation_on_finite_value_(One_critical_filtration &result,
|
|
1365
|
+
const T &to_operate,
|
|
1366
|
+
F &&operate) {
|
|
1367
|
+
for (auto &val : result) {
|
|
1368
|
+
if constexpr (std::numeric_limits<T>::has_quiet_NaN) {
|
|
1369
|
+
operate(val, to_operate);
|
|
1370
|
+
} else {
|
|
1371
|
+
if (!operate(val, to_operate)) {
|
|
1372
|
+
result = nan();
|
|
1373
|
+
return result;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
return result;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
template <typename F>
|
|
1382
|
+
static One_critical_filtration &apply_scalar_operation_on_finite_value_with_all_nan_possible_(
|
|
1383
|
+
One_critical_filtration &result,
|
|
1384
|
+
const T &to_operate,
|
|
1385
|
+
F &&operate) {
|
|
1386
|
+
bool allNaN = true;
|
|
1387
|
+
|
|
1388
|
+
for (auto &val : result) {
|
|
1389
|
+
if (operate(val, to_operate)) {
|
|
1390
|
+
allNaN = false;
|
|
1391
|
+
} else {
|
|
1392
|
+
if constexpr (!std::numeric_limits<T>::has_quiet_NaN) {
|
|
1393
|
+
result = nan();
|
|
1394
|
+
return result;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
if (allNaN) result = nan();
|
|
1399
|
+
|
|
1400
|
+
return result;
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
|
|
1404
|
+
} // namespace multi_filtration
|
|
1405
|
+
} // namespace Gudhi
|
|
1406
|
+
|
|
1407
|
+
namespace std {
|
|
1408
|
+
|
|
1409
|
+
template <typename T>
|
|
1410
|
+
class numeric_limits<Gudhi::multi_filtration::One_critical_filtration<T> > {
|
|
1411
|
+
public:
|
|
1412
|
+
static constexpr bool has_infinity = true;
|
|
1413
|
+
|
|
1414
|
+
static constexpr Gudhi::multi_filtration::One_critical_filtration<T> infinity() noexcept {
|
|
1415
|
+
return Gudhi::multi_filtration::One_critical_filtration<T>::inf();
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1418
|
+
// non-standard
|
|
1419
|
+
static constexpr Gudhi::multi_filtration::One_critical_filtration<T> minus_infinity() noexcept {
|
|
1420
|
+
return Gudhi::multi_filtration::One_critical_filtration<T>::minus_inf();
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
static constexpr Gudhi::multi_filtration::One_critical_filtration<T> max() noexcept(false) {
|
|
1424
|
+
throw std::logic_error(
|
|
1425
|
+
"The maximal value cannot be represented with no finite numbers of parameters."
|
|
1426
|
+
"Use `max(number_of_parameters)` instead");
|
|
1427
|
+
};
|
|
1428
|
+
|
|
1429
|
+
// non-standard, so I don't want to define a default value.
|
|
1430
|
+
static constexpr Gudhi::multi_filtration::One_critical_filtration<T> max(unsigned int n) noexcept {
|
|
1431
|
+
return Gudhi::multi_filtration::One_critical_filtration<T>(n, std::numeric_limits<T>::max());
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
static constexpr Gudhi::multi_filtration::One_critical_filtration<T> quiet_NaN() noexcept {
|
|
1435
|
+
return Gudhi::multi_filtration::One_critical_filtration<T>::nan();
|
|
1436
|
+
};
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
} // namespace std
|
|
1440
|
+
|
|
1441
|
+
#endif // ONE_CRITICAL_FILTRATIONS_H_
|