1+ /*
2+ * Copyright (c) 2022, Thomas Sommer
3+ *
4+ * This file is part of the modm project.
5+ *
6+ * This Source Code Form is subject to the terms of the Mozilla Public
7+ * License, v. 2.0. If a copy of the MPL was not distributed with this
8+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+ */
10+ // ----------------------------------------------------------------------------
11+ #pragma once
12+
13+ #include < algorithm>
14+ #include < concepts>
15+
16+ #include < modm/math/utils/integer_traits.hpp>
17+ #include < modm/architecture/interface/assert.hpp>
18+
19+ namespace modm {
20+
21+ /* *
22+ * @brief Unsigned integer with arbitrary number of digits.
23+ * Artihmetic over- and underflows wrap by default, just like builtin integral types.
24+ *
25+ * @tparam Bits Resolution of the unsigned integer
26+ *
27+ * @author Thomas Sommer
28+ * @ingroup modm_math
29+ */
30+ template <int Bits>
31+ requires (Bits > 0 )
32+ class uintn_t {
33+ public:
34+ static constexpr int digits = Bits;
35+
36+ using T = uint_t <Bits>::least;
37+ static constexpr T bitmask = ::modm::bitmask<Bits>();
38+
39+ static constexpr T min = 0 ;
40+ static constexpr T max = bitmask;
41+
42+ // / constructors
43+ constexpr uintn_t () = default;
44+
45+ constexpr uintn_t (T value) {
46+ #ifdef MODM_DEBUG_BUILD
47+ if (not modm_assert_continue_ignore_debug (value <= max, " uintn_t.ctor" , " value exceeded max" , max)) {
48+ value_ = std::min (max, value);
49+ return ;
50+ }
51+ #endif
52+
53+ value_ = value;
54+ }
55+
56+ #if 0
57+ template <int E>
58+ requires (Bits <= E)
59+ constexpr uintn_t(const uintn_t<E>& other)
60+ : value_(other.value_ >> (E - Bits))
61+ {}
62+
63+ template <int E>
64+ requires (Bits > E)
65+ constexpr uintn_t(const uintn_t<E>& other)
66+ : value_(other.value_ * max / other.max)
67+ {}
68+ #endif
69+
70+ // / assignment operators
71+ void operator =(T value) {
72+ #ifdef MODM_DEBUG_BUILD
73+ if (not modm_assert_continue_ignore_debug (value <= max, " uintn_t.assign" , " value exceeded max" , max)) {
74+ value_ = std::min (max, value);
75+ return ;
76+ }
77+ #endif
78+
79+ value_ = value;
80+ }
81+
82+ #if 0
83+ template <int E>
84+ requires (Bits <= E)
85+ constexpr void operator=(const uintn_t<E>& other) {
86+ value_ = other.value_ >> (E - Bits);
87+ }
88+
89+ template <int E>
90+ requires (Bits > E)
91+ constexpr void operator=(const uintn_t<E>& other) {
92+ value_ = other.value_ * max / other.max;
93+ }
94+ #endif
95+
96+ constexpr T value () const { return value_; }
97+ constexpr T& value () { return value_; }
98+
99+ bool operator <=>(const uintn_t & other) const = default ;
100+
101+ // / operator +, -, *, /
102+ template <std::integral U>
103+ uintn_t
104+ operator +(U value)
105+ {
106+ return {T (value_ + value) & uintn_t ::max};
107+ }
108+
109+ template <std::integral U>
110+ uintn_t
111+ operator -(U value)
112+ {
113+ return {T (value_ - value) & uintn_t ::max};
114+ }
115+
116+ template <std::integral U>
117+ uintn_t
118+ operator *(U value)
119+ {
120+ return {T (value_ * value) & uintn_t ::max};
121+ }
122+
123+ template <std::integral U>
124+ uintn_t
125+ operator /(U value)
126+ {
127+ return {T (value_ / value) & uintn_t ::max};
128+ }
129+
130+ // / operator +=, -=, *=, /=
131+ template <std::integral U>
132+ uintn_t &
133+ operator +=(U value)
134+ {
135+ value_ = T (value_ + value) & uintn_t ::max;
136+ return *this ;
137+ }
138+
139+ template <std::integral U>
140+ uintn_t &
141+ operator -=(U value)
142+ {
143+ value_ = T (value_ - value) & uintn_t ::max;
144+ return *this ;
145+ }
146+
147+ template <std::integral U>
148+ uintn_t &
149+ operator *(U value)
150+ {
151+ value_ = T (value_ * value) & uintn_t ::max;
152+ return *this ;
153+ }
154+
155+ template <std::integral U>
156+ uintn_t &
157+ operator /(U value)
158+ {
159+ value_ = T (value_ / value) & uintn_t ::max;
160+ return this ;
161+ }
162+
163+ protected:
164+ T value_{0 };
165+
166+ private:
167+ template <int >
168+ friend class uintn_t ;
169+ };
170+
171+ }
0 commit comments