Maipa's Standard Library Extension 1.5.6
mstd
Loading...
Searching...
No Matches
overflow_operations.hpp
1/*
2 * mstd - Maipa's Standard Library
3 *
4 * Licensed under the BSD 3-Clause License with Attribution Requirement.
5 * See the LICENSE file for details: https://github.com/MAIPA01/mstd/blob/main/LICENSE
6 *
7 * Copyright (c) 2025, Patryk Antosik (MAIPA01)
8 */
9
10#pragma once
11#ifndef _MSTD_OVERFLOW_OPERATIONS_HPP_
12 #define _MSTD_OVERFLOW_OPERATIONS_HPP_
13
14 #include <mstd/config.hpp>
15
17_MSTD_WARNING("this is only available for c++17 and greater!");
18 #else
19
20 #include <mstd/arithmetic_types.hpp>
21 #include <mstd/types.hpp>
22
23namespace mstd {
26 #else
27 template<class N, class Na, class Nb, std::enable_if_t<are_arithmetic_v<N, Na, Nb>, bool> = true>
28 #endif
29 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool add_overflow(const Na& a, const Nb& b, N& out) {
30 using limits = std::numeric_limits<N>;
31
33 if (a > limits::max() - b) { return true; }
34 }
35 else {
36 if (b >= 0 && a > limits::max() - b) { return true; }
37
38 if (b <= 0 && a < limits::min() - b) { return true; }
39 }
40
41 out = static_cast<N>(a + b);
42 return false;
43 }
44
47 #else
48 template<class N, class Na, class Nb, std::enable_if_t<are_arithmetic_v<N, Na, Nb>, bool> = true>
49 #endif
50 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool sub_overflow(const Na& a, const Nb& b, N& out) {
51 using limits = std::numeric_limits<N>;
52
54 if (a < limits::min() + b) { return true; }
55 }
56 else {
57 if (b <= 0 && a > limits::max() + b) { return true; }
58
59 if (b >= 0 && a < limits::min() + b) { return true; }
60 }
61
62 out = static_cast<N>(a - b);
63 return false;
64 }
65
68 #else
69 template<class N, class Na, class Nb, std::enable_if_t<are_arithmetic_v<N, Na, Nb>, bool> = true>
70 #endif
71 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool mul_overflow(const Na& a, const Nb& b, N& out) {
72 using limits = std::numeric_limits<N>;
73
75 if (a != 0 && b != 0 && a > limits::max() / b) { return true; }
76 }
77 else {
78 if (a != 0 && b != 0) {
79 if (a == -1 && b == static_cast<Nb>(limits::min())) { return true; }
80
81 if (a == limits::min() && b == static_cast<Nb>(-1)) { return true; }
82
83 if (a > static_cast<Na>(limits::max() / b)) { return true; }
84
85 if (a < static_cast<Na>(limits::min() / b)) { return true; }
86 }
87 }
88
89 out = static_cast<N>(a * b);
90 return false;
91 }
92
95 #else
96 template<class N, class Na, class Nb, std::enable_if_t<are_arithmetic_v<N, Na, Nb>, bool> = true>
97 #endif
98 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool div_overflow(const Na& a, const Nb& b, N& out) {
99 using limits = std::numeric_limits<N>;
100
101 if _MSTD_CONSTEXPR17 (are_unsigned_v<N, Na, Nb>) { out = static_cast<N>(b == 0 ? limits::max() : a / b); }
102 else {
103 if (a == limits::min() && b == -1) { return true; }
104
105 N badValue = a < 0 ? limits::min() : limits::max();
106 out = static_cast<N>(b == 0 ? badValue : a / b);
107 }
108 return false;
109 }
110} // namespace mstd
111 #endif
112#endif
#define _MSTD_HAS_CXX17
Definition config.hpp:45
#define _MSTD_CONSTEXPR17
Definition config.hpp:76
#define _MSTD_HAS_CXX20
Definition config.hpp:52
#define _MSTD_INLINE17
Definition config.hpp:83
#define _MSTD_CONSTEXPR20
Definition config.hpp:84
Definition arithmetic_types.hpp:23
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool add_overflow(const Na &a, const Nb &b, N &out)
Definition overflow_operations.hpp:29
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool mul_overflow(const Na &a, const Nb &b, N &out)
Definition overflow_operations.hpp:71
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool sub_overflow(const Na &a, const Nb &b, N &out)
Definition overflow_operations.hpp:50
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool div_overflow(const Na &a, const Nb &b, N &out)
Definition overflow_operations.hpp:98