Bluenet  5.7.0
Bluenet, firmware for nRF52 smart home devices
Loading...
Searching...
No Matches
cs_Math.h
Go to the documentation of this file.
1/*
2 * Author: Crownstone Team
3 * Copyright: Crownstone (https://crownstone.rocks)
4 * Date: Okt 18, 2019
5 * License: LGPLv3+, Apache License 2.0, and/or MIT (triple-licensed)
6 */
7#pragma once
8
9#include <algorithm>
10
11#ifdef HOST_TARGET
12#include <limits>
13#endif
14
15namespace CsMath {
16
21template <class T, class U>
22constexpr inline T SafeAdd(T lhs, U rhs) {
23 T min = std::numeric_limits<T>::lowest();
24 T max = std::numeric_limits<T>::max();
25
26 if (rhs > 0) {
27 return (lhs > max - rhs) ? max : T(lhs + rhs);
28 }
29 if (rhs < 0) {
30 return (lhs < min - rhs) ? min : T(lhs + rhs);
31 }
32 return lhs;
33}
34
38template <class T, class U = int>
39constexpr inline T& Increase(T& obj, U diff = 1) {
40 obj = SafeAdd(obj, diff);
41 return obj;
42}
43
47template <class T, class U = int>
48constexpr inline T& Decrease(T& obj, U diff = 1) {
49 obj = SafeAdd(obj, -diff);
50 return obj;
51}
52
60template <class T, class M, class U = int>
61constexpr inline decltype(auto) DecreaseMember(T& obj, M member, U diff = 1) {
62 obj.*member = SafeAdd(obj.*member, -diff);
63 return obj.*member;
64}
65
76template <class T, class S>
77auto mod(T v, S m) -> decltype(v % m) {
78 if (m == 0) {
79 return v;
80 }
81 if (m < 0) {
82 // flip [m] doesn't change the value.
83 return mod(v, -m);
84 }
85 if (v < 0) {
86 // flip [v] twice won't change it either, but be careful not to return
87 // [m] instead of 0 when val is a multiple of m.
88 if (auto neg_v = mod(-v, m)) {
89 // hidden recursion in if clause will only go one level deep ;)
90 return m - neg_v;
91 }
92 else {
93 return 0;
94 }
95 }
96 // m positive, v non-negative, yay C++ actually works in that case.
97 return v % m;
98}
99
100template <class T, class S>
101auto min(T l, S r) {
102 return l < r ? l : r;
103}
104
105template <class T, class S>
106auto max(T l, S r) {
107 return l > r ? l : r;
108}
109
116template <class V, class L, class U>
117auto clamp(V value, L lower, U upper) {
118 return min(max(value, lower), upper);
119}
120
126template <class T, class S = T>
127class Interval {
128private:
130 bool invert;
131
132public:
133 Interval(T base, S diff, bool inv = false) : low(base), high(base + (inv ? -diff : diff)), invert(inv) {
134 // notes:
135 // - addition base+diff is allowed to overflow/underflow.
136 // - having a different type S for diff allows negative
137 // values without conflicting type resolutions.
138 if ((diff < 0) ^ invert) {
139 std::swap(low, high);
140 }
141 }
142
143 T lowerbound() { return low; }
144 T upperbound() { return high; }
145
146 // E.g.
147 // Interval<uint8_t> i(200,100)
148 // i.contains(0) == true.
149 // considers this interval as half open (lower closed) so that the return value is
150 // true if [val] is enclosed in the interval or equal to the lower boundary.
151 bool contains(T val) {
152 return low < high // reversed interval?
153 ? (low <= val && val < high) // nope, both must hold
154 : (low <= val || val < high); // yup, only one can hold
155 }
156
157 // considers this interval as open ended so that the return value is
158 // true if [val] is enclosed in the interval or on the boundary.
159 bool ClosureContains(T val) {
160 return low < high // reversed interval?
161 ? (low <= val && val <= high) // nope, both must hold
162 : (low <= val || val <= high); // yup, only one can hold
163 }
164
165 // considers this interval as open ended so that the return value is
166 // true if [val] is strictly enclosed in the interval.
167 bool InteriorContains(T val) {
168 return low < high // reversed interval?
169 ? (low < val && val < high) // nope, both must hold
170 : (low < val || val < high); // yup, only one can hold
171 }
172};
173
177template <class T>
178T round(float val) {
179 // since numeric types are implicitly converted from float by flooring them,
180 // adding 0.5 results in conventional rounding.
181 return T(val + 0.5);
182}
183} // namespace CsMath
Represents an interval by two unsigned integers [base, base + diff].
Definition: cs_Math.h:127
bool contains(T val)
Definition: cs_Math.h:151
bool invert
Definition: cs_Math.h:130
bool ClosureContains(T val)
Definition: cs_Math.h:159
bool InteriorContains(T val)
Definition: cs_Math.h:167
T lowerbound()
Definition: cs_Math.h:143
T low
Definition: cs_Math.h:129
Interval(T base, S diff, bool inv=false)
Definition: cs_Math.h:133
T high
Definition: cs_Math.h:129
T upperbound()
Definition: cs_Math.h:144
Definition: cs_Math.h:15
constexpr decltype(auto) DecreaseMember(T &obj, M member, U diff=1)
Identical to the other decrease function.
Definition: cs_Math.h:61
constexpr T & Increase(T &obj, U diff=1)
roll over safe variant of ++some_value;
Definition: cs_Math.h:39
constexpr T & Decrease(T &obj, U diff=1)
roll over safe variant of –some_value;
Definition: cs_Math.h:48
auto min(T l, S r)
Definition: cs_Math.h:101
constexpr T SafeAdd(T lhs, U rhs)
returns lhs+rhs, clamping return values that would roll over to the min/max values of lhs.
Definition: cs_Math.h:22
auto clamp(V value, L lower, U upper)
Returns:
Definition: cs_Math.h:117
auto max(T l, S r)
Definition: cs_Math.h:106
auto mod(T v, S m) -> decltype(v % m)
Returns the canonical representation of [v] considered as element of Z/mZ, regardless of any silly fe...
Definition: cs_Math.h:77
T round(float val)
Rounds a numeric value.
Definition: cs_Math.h:178