1+ /*
2+ * Copyright (c) 2021, 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+
12+ #pragma once
13+
14+ #include < algorithm>
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 digits and scaling value on conversion
23+ * between instances with different digits.
24+ *
25+ * @tparam D Digits
26+ *
27+ * @author Thomas Sommer
28+ */
29+ template <int D>
30+ class ScalingUnsigned {
31+ public:
32+ static constexpr int Digits = D;
33+ using ValueType = uint_t <D>::least;
34+
35+ static constexpr ValueType min = 0 ;
36+ static constexpr ValueType max = bitmask<D>();
37+
38+ constexpr ScalingUnsigned () = default;
39+
40+ // FIXME want both:
41+ // COMPTIME: static_assert(value <= max, "value out of range")
42+ // RUNTIME: std::min(value, max) or modm_assert(value <= max, ...)
43+ constexpr ScalingUnsigned (ValueType value) : value(std::min(value, max)) {
44+ // TODO disable via lbuild option
45+ // modm_assert_continue_fail_debug(value <= max, "ScalingUnsigned", "constructor", "value out of range");
46+ }
47+
48+ // Construct from bigger or equal ColorGray
49+ template <int E, std::enable_if_t <(D <= E), void *> = nullptr >
50+ constexpr ScalingUnsigned (const ScalingUnsigned<E>& other)
51+ : value(other.value >> (E - D)) {}
52+
53+ template <int E, std::enable_if_t <(D <= E), void *> = nullptr >
54+ constexpr ScalingUnsigned (ScalingUnsigned<E> &&other)
55+ : value(other.value >> (E - D)) {}
56+
57+ // Construct from smaller ColorGray
58+ template <int E, std::enable_if_t <(D > E), void *> = nullptr >
59+ constexpr ScalingUnsigned (const ScalingUnsigned<E>& other)
60+ : value(other.value * max / other.max)
61+ {}
62+
63+ template <int E, std::enable_if_t <(D > E), void *> = nullptr >
64+ constexpr ScalingUnsigned (ScalingUnsigned<E> &&other)
65+ : value(other.value * max / other.max)
66+ {}
67+
68+ /* // Faster construction from from single digit
69+ constexpr ScalingUnsigned(const ScalingUnsigned<1> &other) : value(other.value ? bitmask<D>() : 0){}
70+
71+ // constexpr ScalingUnsigned(ScalingUnsigned<1> &&other) : value(other.value ? bitmask<D>() : 0){}
72+ constexpr ScalingUnsigned& operator=(const ScalingUnsigned<1> &other) {
73+ value = other.value ? bitmask<D>() : 0;
74+ return *this;
75+ } */
76+
77+ // Assign ScalingUnsigned with more or equal Depth
78+ template <int E, std::enable_if_t <(D <= E), void *> = nullptr >
79+ void operator =(const ScalingUnsigned<E>& other) {
80+ value = other.value >> (E - D);
81+ }
82+
83+ // Assign ScalingUnsigned with less Depth
84+ template <int E, std::enable_if_t <(D > E), void *> = nullptr >
85+ void operator =(const ScalingUnsigned<E>& other) {
86+ value = other.value * max / other.max ;
87+ }
88+
89+ // FIXME want both:
90+ // COMPTIME: static_assert(value <= max, "value out of range")
91+ // RUNTIME: std::min(value, max) or modm_assert(value <= max, ...)
92+ void setValue (ValueType value) {
93+ this ->value = std::min (value, max);
94+ // TODO disable via lbuild option
95+ // modm_assert_continue_fail_debug(value <= max, "modm::ScalingUnsigned", "setValue()", "value out of range");
96+ }
97+
98+ ValueType getValue () const { return value; }
99+
100+ bool isSaturated () const {
101+ return value == max;
102+ }
103+
104+ constexpr auto operator <=>(const ScalingUnsigned<D> &) const = default ;
105+
106+ protected:
107+ ValueType value = 0 ;
108+
109+ inline void max_cutoff () { value = std::min (value, max); }
110+ private:
111+ template <int >
112+ friend class ScalingUnsigned ;
113+ };
114+
115+ }
0 commit comments