libsemigroups  v3.0.0
C++ library for semigroups and monoids
Loading...
Searching...
No Matches
constants.hpp
1//
2// libsemigroups - C++ library for semigroups and monoids
3// Copyright (C) 2019-2025 James D. Mitchell
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17//
18//
19// This file contains functionality for various constant values used in
20// libsemigroups.
21
22// TODO(later)
23// 1. NegativeInfinity could be comparable with unsigned integers (always <).
24// 2. specialisation of operator<< for ostringstream for better printing. I
25// couldn't immediately get this to work.
26
27#ifndef LIBSEMIGROUPS_CONSTANTS_HPP_
28#define LIBSEMIGROUPS_CONSTANTS_HPP_
29
30#include <cinttypes> // for int64_t
31#include <limits> // for numeric_limits
32#include <type_traits> // for is_integral
33
34namespace libsemigroups {
35 namespace detail {
36
37 struct Min {
38 template <typename T>
39 constexpr T operator()() const noexcept {
40 static_assert(std::is_integral_v<T>,
41 "can only call Min with an integral type");
43 }
44 };
45
46 struct Max {
47 template <typename T>
48 constexpr T operator()() const noexcept {
49 static_assert(std::is_integral_v<T>,
50 "can only call Max with an integral type");
52 }
53 };
54
55 template <int64_t TOffset, typename TMaxOrMin>
56 struct Constant {
57 static_assert(std::is_same_v<TMaxOrMin, Max>
58 || std::is_same_v<TMaxOrMin, Min>,
59 "template parameter TMaxOrMin must be Max or Min");
60
61 Constant() = default;
62 Constant(Constant const&) = default;
63 Constant(Constant&&) = default;
64 Constant& operator=(Constant const&) = default;
65 Constant& operator=(Constant&&) = default;
66 ~Constant() = default;
67
68 template <typename T, typename = std::enable_if_t<!std::is_enum_v<T>, T>>
69 constexpr operator T() const noexcept {
70 static_assert(
71 std::is_integral_v<T>
72 && (std::is_signed_v<T> || std::is_same_v<TMaxOrMin, Max>),
73 "the template parameter T must be an integral type, and either "
74 "unsigned or the template parameter TMaxOrMin must be Max.");
75 return TMaxOrMin().template operator()<T>() + TOffset;
76 }
77 };
78 } // namespace detail
79
81 // Constant values
83
92
97 using Undefined = detail::Constant<0, detail::Max>;
98
103 using PositiveInfinity = detail::Constant<-1, detail::Max>;
104
109 using LimitMax = detail::Constant<-2, detail::Max>;
110
115 using NegativeInfinity = detail::Constant<0, detail::Min>;
116
124 extern Undefined const UNDEFINED;
125
135
144 extern LimitMax const LIMIT_MAX;
145
155
157 // Operators for all constants
159
160 // Note that for some reason Catch requires that the comparison functions are
161 // in the namespace detail.
162
163#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
164 namespace detail {
165
166 // operator==
167 // No SFINAE required, since the functions delegated to don't exist.
168 template <int64_t R, typename S, typename T>
169 constexpr bool operator==(Constant<R, S> const& lhs,
170 T const& rhs) noexcept {
171 return lhs.operator T() == rhs;
172 }
173
174 template <int64_t R, typename S, typename T>
175 constexpr bool operator==(T const& lhs,
176 Constant<R, S> const& rhs) noexcept {
177 return rhs.operator T() == lhs;
178 }
179
180 template <int64_t R1, typename S1, int64_t R2, typename S2>
181 constexpr bool operator==(Constant<R1, S1> const&,
182 Constant<R2, S2> const&) noexcept {
183 return std::is_same_v<S1, S2> && R1 == R2;
184 }
185
186 // operator!=
187 // No SFINAE required, since the functions delegated to don't exist.
188 template <int64_t R, typename S, typename T>
189 constexpr bool operator!=(Constant<R, S> const& lhs,
190 T const& rhs) noexcept {
191 return !(lhs == rhs);
192 }
193
194 template <int64_t R, typename S, typename T>
195 constexpr bool operator!=(T const& lhs,
196 Constant<R, S> const& rhs) noexcept {
197 return !(lhs == rhs);
198 }
199
200 template <int64_t R1, typename S1, int64_t R2, typename S2>
201 constexpr bool operator!=(Constant<R1, S1> const& lhs,
202 Constant<R2, S2> const& rhs) noexcept {
203 return !(lhs == rhs);
204 }
205
206 // operator>
207 // No SFINAE required, since the functions delegated to don't exist.
208 template <int64_t R, typename S, typename T>
209 constexpr bool operator>(Constant<R, S> const& lhs, T const& rhs) noexcept {
210 return rhs < lhs;
211 }
212
213 template <int64_t R, typename S, typename T>
214 constexpr bool operator>(T const& lhs, Constant<R, S> const& rhs) noexcept {
215 return rhs < lhs;
216 }
217
218 template <int64_t R, typename S>
219 constexpr bool operator>(Constant<R, S> const&,
220 Constant<R, S> const&) noexcept {
221 return false;
222 }
223
224 template <int64_t R, typename S>
225 constexpr bool operator<(Constant<R, S> const&,
226 Constant<R, S> const&) noexcept {
227 return false;
228 }
229
230 // No further operator< for Constant and Constant unless given explicitly
231
233 // Operators for specific constants
235
236 // PositiveInfinity is not less than any integral value, or
237 // NegativeInfinity.
238 template <typename T, typename SFINAE = bool>
239 constexpr auto operator<(PositiveInfinity const&, T const&) noexcept
240 -> std::enable_if_t<std::is_integral_v<T>
241 || std::is_same_v<NegativeInfinity, T>,
242 SFINAE> {
243 return false;
244 }
245
246 // Every integral value, and negative infinity, is less than
247 // PositiveInfinity.
248 template <typename T, typename SFINAE = bool>
249 constexpr auto operator<(T const&, PositiveInfinity const&) noexcept
250 -> std::enable_if_t<std::is_integral_v<T>
251 || std::is_same_v<NegativeInfinity, T>,
252 SFINAE> {
253 return true;
254 }
255
256 // NegativeInfinity is less than every integral value.
257 template <typename T, typename SFINAE = bool>
258 constexpr auto operator<(NegativeInfinity const&, T const&) noexcept
259 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
260 return true;
261 }
262
263 // No integral value is less than NegativeInfinity.
264 template <typename T, typename SFINAE = bool>
265 constexpr auto operator<(T const&, NegativeInfinity const&) noexcept
266 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
267 return false;
268 }
269
270 // LimitMax is compared by implicit conversion with any integral value.
271 template <typename T, typename SFINAE = bool>
272 constexpr auto operator<(LimitMax const& lhs, T const& rhs) noexcept
273 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
274 return lhs.operator T() < rhs;
275 }
276
277 // LimitMax is compared by implicit conversion with any integral value.
278 template <typename T, typename SFINAE = bool>
279 constexpr auto operator<(T const& lhs, LimitMax const& rhs) noexcept
280 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
281 return lhs < rhs.operator T();
282 }
283
284 template <typename T, typename SFINAE = T>
285 constexpr auto operator-(LimitMax const& lhs, T const& rhs) noexcept
286 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
287 return lhs.operator T() - rhs;
288 }
289
290 template <typename T, typename SFINAE = T>
291 constexpr auto operator-(T const& lhs, LimitMax const& rhs) noexcept
292 -> std::enable_if_t<std::is_integral_v<T>, SFINAE> {
293 return lhs - rhs.operator T();
294 }
295 } // namespace detail
296#endif // LIBSEMIGROUPS_PARSED_BY_DOXYGEN
297} // namespace libsemigroups
298#endif // LIBSEMIGROUPS_CONSTANTS_HPP_
bool operator>(Bipartition const &x, Bipartition const &y)
Compare bipartitions.
Definition bipart.hpp:1658
bool operator!=(Bipartition const &x, Bipartition const &y)
Check bipartitions for inequality.
Definition bipart.hpp:1637
detail::Constant< 0, detail::Max > Undefined
Type for undefined values.
Definition constants.hpp:97
NegativeInfinity const NEGATIVE_INFINITY
Value for negative infinity.
detail::Constant<-1, detail::Max > PositiveInfinity
Type for positive infinity.
Definition constants.hpp:103
Undefined const UNDEFINED
Value for something undefined.
detail::Constant< 0, detail::Min > NegativeInfinity
Type for negative infinity.
Definition constants.hpp:115
PositiveInfinity const POSITIVE_INFINITY
Value for positive infinity.
LimitMax const LIMIT_MAX
Value for the maximum of something.
detail::Constant<-2, detail::Max > LimitMax
Type for the maximum value of something.
Definition constants.hpp:109
bool operator==(Presentation< Word > const &lhop, Presentation< Word > const &rhop)
Compare for equality.
Definition presentation.hpp:2346
T max(T... args)
T min(T... args)
Namespace for everything in the libsemigroups library.
Definition action.hpp:44