Quantify
An extensible C++ units library
Loading...
Searching...
No Matches
unit_macros.h
Go to the documentation of this file.
1// Copyright (c) 2024-2025, Víctor Castillo Agüero.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
18#define UNIT_SYMBOL(...) \
19 static constexpr inline std::string symbol() noexcept { \
20 return (__VA_ARGS__); \
21 }
22
23#define SCALE(NAME) \
24 namespace NAME { \
25 struct scale { \
26 UNIT_SYMBOL(#NAME) \
27 }; \
28 template <typename Q> \
29 concept quantity = quantify::Quantity<Q, scale>; \
30 } \
31 namespace NAME
32
33#define DERIVED_SCALE(NAME, ...) \
34 namespace NAME { \
35 using scale = typename reduce_scale<__VA_ARGS__>::type; \
36 template <typename Q> \
37 concept quantity = quantify::Quantity<Q, scale>; \
38 } \
39 namespace NAME
40
41#define UNIT(NAME, SYMBOL, FACTOR_NUM, FACTOR_DEN) \
42 struct NAME { \
43 using scale = scale; \
44 template <typename T> \
45 using factor = quantify::ratio<T, FACTOR_NUM, FACTOR_DEN>; \
46 using reduce = NAME; \
47 UNIT_SYMBOL(SYMBOL) \
48 }
49
50#define UNIT_IN_SCALE(SCALE, NAME, SYMBOL, FACTOR_NUM, FACTOR_DEN) \
51 struct NAME { \
52 using scale = SCALE; \
53 template <typename T> \
54 using factor = quantify::ratio<T, FACTOR_NUM, FACTOR_DEN>; \
55 using reduce = NAME; \
56 UNIT_SYMBOL(SYMBOL) \
57 }
58
59#define METRIC_UNIT(UNIT_NAME, SYMBOL, FACTOR_NUM, FACTOR_DEN) \
60 UNIT(nano##UNIT_NAME, "n" SYMBOL, 1UL * (FACTOR_NUM), 1000000000UL * (FACTOR_DEN)); \
61 UNIT(micro##UNIT_NAME, "u" SYMBOL, 1UL * (FACTOR_NUM), 1000000UL * (FACTOR_DEN)); \
62 UNIT(milli##UNIT_NAME, "m" SYMBOL, 1UL * (FACTOR_NUM), 1000UL * (FACTOR_DEN)); \
63 UNIT(centi##UNIT_NAME, "c" SYMBOL, 1UL * (FACTOR_NUM), 100UL * (FACTOR_DEN)); \
64 UNIT(deci##UNIT_NAME, "d" SYMBOL, 1UL * (FACTOR_NUM), 10UL * (FACTOR_DEN)); \
65 UNIT(UNIT_NAME, SYMBOL, 1UL * (FACTOR_NUM), 1UL * (FACTOR_DEN)); \
66 UNIT(deca##UNIT_NAME, "D" SYMBOL, 10UL * (FACTOR_NUM), 1UL * (FACTOR_DEN)); \
67 UNIT(hecto##UNIT_NAME, "h" SYMBOL, 100UL * (FACTOR_NUM), 1UL * (FACTOR_DEN)); \
68 UNIT(kilo##UNIT_NAME, "k" SYMBOL, 1000UL * (FACTOR_NUM), 1UL * (FACTOR_DEN)); \
69 UNIT(mega##UNIT_NAME, "M" SYMBOL, 1000000UL * (FACTOR_NUM), 1UL * (FACTOR_DEN))
70
71
72#define SCALE_CONVERSION(FROM, TO) \
73 template <> \
74 struct quantify::scale_conversion_t<FROM, TO> { \
75 using from_scale = FROM; \
76 using to_scale = TO;
77
78#define SCALE_FORWARD_CONVERSION(...) \
79 template <typename U_FROM, typename U_TO, typename T> \
80 requires quantify::CompareScales<from_scale, typename U_FROM::scale> && \
81 quantify::CompareScales<to_scale, typename U_TO::scale> \
82 static quantity<U_TO, T> forward(const quantity<U_FROM, T>& _quantity) { \
83 quantity<U_TO, T> result{ \
84 _quantity.value * U_FROM::template factor<T>::numerator / \
85 U_FROM::template factor<T>::denominator \
86 }; \
87 auto it = result.value; \
88 result.value = __VA_ARGS__; \
89 result.value = \
90 result.value * U_TO::template factor<T>::denominator / U_TO::template factor<T>::numerator; \
91 return result; \
92 }
93
94#define SCALE_BACKWARD_CONVERSION(...) \
95 template <typename U_FROM, typename U_TO, typename T> \
96 requires quantify::CompareScales<to_scale, typename U_FROM::scale> && \
97 quantify::CompareScales<from_scale, typename U_TO::scale> \
98 static quantity<U_TO, T> backward(const quantity<U_FROM, T>& _quantity) { \
99 quantity<U_TO, T> result{ \
100 _quantity.value * U_FROM::template factor<T>::numerator / \
101 U_FROM::template factor<T>::denominator \
102 }; \
103 auto it = result.value; \
104 result.value = __VA_ARGS__; \
105 result.value = \
106 result.value * U_TO::template factor<T>::denominator / U_TO::template factor<T>::numerator; \
107 return result; \
108 } \
109 } \
110 ;
111