HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
units.hpp
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../macros.hpp"
8#include "cast.hpp"
9#include <ratio>
10#include <concepts>
11#include <compare>
12
13hi_export_module(hikogui.utility.units);
14
15hi_export namespace hi { inline namespace v1 {
16
17template<typename Tag, typename T, typename Ratio = std::ratio<1>>
18class unit {
19public:
20 using value_type = T;
21 using ratio = Ratio;
22
23 constexpr unit(unit const&) noexcept = default;
24 constexpr unit(unit&&) noexcept = default;
25 constexpr unit& operator=(unit const&) noexcept = default;
26 constexpr unit& operator=(unit&&) noexcept = default;
27
28 constexpr explicit unit(value_type value) noexcept : _value(value) {}
29
30 template<typename OtherT, typename OtherRatio>
31 constexpr explicit unit(unit<Tag, OtherT, OtherRatio> const& other) noexcept
32 requires(not std::is_same_v<unit<Tag, OtherT, OtherRatio>, unit>)
33 {
35
37 tmp *= conversion::den;
38 tmp /= conversion::num;
39 _value = narrow_cast<T>(tmp);
40 }
41
42 template<typename OtherT, typename OtherRatio>
43 constexpr unit& operator=(unit<Tag, OtherT, OtherRatio> const& other) noexcept
44 requires(not std::is_same_v<unit<Tag, OtherT, OtherRatio>, unit>)
45 {
47
49 tmp *= conversion::den;
50 tmp /= conversion::num;
51 _value = narrow_cast<T>(tmp);
52 return *this;
53 }
54
55 [[nodiscard]] constexpr value_type count() const noexcept
56 {
57 return _value;
58 }
59
60 [[nodiscard]] constexpr unit operator*(value_type const& rhs) const noexcept
61 {
62 return unit{count() * rhs};
63 }
64
65 [[nodiscard]] constexpr unit operator/(value_type const& rhs) const noexcept
66 {
67 return unit{count() / rhs};
68 }
69
70 [[nodiscard]] constexpr unit& operator+=(unit const& rhs) noexcept
71 {
72 _value += rhs.count();
73 return *this;
74 }
75
76 [[nodiscard]] constexpr unit& operator-=(unit const& rhs) noexcept
77 {
78 _value -= rhs.count();
79 return *this;
80 }
81
82 [[nodiscard]] constexpr unit& operator*=(value_type const& rhs) noexcept
83 {
84 _value *= rhs;
85 return *this;
86 }
87
88 [[nodiscard]] constexpr unit& operator/=(value_type const& rhs) noexcept
89 {
90 _value /= rhs;
91 return *this;
92 }
93
94private:
95 value_type _value;
96};
97
98}} // namespace hi::v1
99
100template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
101struct std::common_type<hi::unit<Tag, T1, Ratio1>, hi::unit<Tag, T2, Ratio2>> {
102 // clang-format off
103 using type = hi::unit<
104 Tag,
105 std::common_type_t<T1, T2>,
106 std::conditional_t<std::ratio_less_v<Ratio1, Ratio2>, Ratio1, Ratio2>>;
107 // clang-format on
108};
109
110hi_export namespace hi { inline namespace v1 {
111
112template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
113[[nodiscard]] constexpr bool operator==(unit<Tag, T1, Ratio1> const& lhs, unit<Tag, T2, Ratio2> const& rhs) noexcept
114{
115 using common_type = std::common_type_t<unit<Tag, T1, Ratio1>, unit<Tag, T2, Ratio2>>;
116
117 auto const lhs_ = common_type{lhs};
118 auto const rhs_ = common_type{rhs};
119
120 return lhs_.count() == rhs_.count();
121}
122
123template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
124[[nodiscard]] constexpr auto operator<=>(unit<Tag, T1, Ratio1> const& lhs, unit<Tag, T2, Ratio2> const& rhs) noexcept
125{
126 using common_type = std::common_type_t<unit<Tag, T1, Ratio1>, unit<Tag, T2, Ratio2>>;
127
128 auto const lhs_ = common_type{lhs};
129 auto const rhs_ = common_type{rhs};
130
131 return lhs_.count() <=> rhs_.count();
132}
133
134template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
135[[nodiscard]] constexpr auto operator+(unit<Tag, T1, Ratio1> const& lhs, unit<Tag, T2, Ratio2> const& rhs) noexcept
136{
137 using common_type = std::common_type_t<unit<Tag, T1, Ratio1>, unit<Tag, T2, Ratio2>>;
138
139 auto const lhs_ = common_type{lhs};
140 auto const rhs_ = common_type{rhs};
141
142 return common_type{lhs_.count() + rhs_.count()};
143}
144
145template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
146[[nodiscard]] constexpr auto operator-(unit<Tag, T1, Ratio1> const& lhs, unit<Tag, T2, Ratio2> const& rhs) noexcept
147{
148 using common_type = std::common_type_t<unit<Tag, T1, Ratio1>, unit<Tag, T2, Ratio2>>;
149
150 auto const lhs_ = common_type{lhs};
151 auto const rhs_ = common_type{rhs};
152
153 return common_type{lhs_.count() - rhs_.count()};
154}
155
156template<typename Tag, typename T1, typename Ratio1, typename T2, typename Ratio2>
157[[nodiscard]] constexpr auto operator/(unit<Tag, T1, Ratio1> const& lhs, unit<Tag, T2, Ratio2> const& rhs) noexcept
158{
159 using common_type = std::common_type_t<unit<Tag, T1, Ratio1>, unit<Tag, T2, Ratio2>>;
160
161 auto const lhs_ = common_type{lhs};
162 auto const rhs_ = common_type{rhs};
163
164 return lhs_.count() / rhs_.count();
165}
166
167
171
177
180using points = unit<si_length_tag, double, std::ratio<254, 720'000>::type>;
181
184using inches = unit<si_length_tag, double, std::ratio<254, 10'000>::type>;
185using feet = unit<si_length_tag, double, std::ratio<3'048, 10'000>::type>;
186using yards = unit<si_length_tag, double, std::ratio<9'144, 10'000>::type>;
187using miles = unit<si_length_tag, double, std::ratio<16'093'440, 10'000>::type>;
188
191using dips = unit<si_length_tag, double, std::ratio<254, 960'000>::type>;
192
196
200
201}} // namespace hi::v1
Functions for casting values between types savely.
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
Definition units.hpp:18
Definition units.hpp:168
Definition units.hpp:169
Definition units.hpp:170