Line data Source code
1 : /** @file basis_unit.hpp **/
2 :
3 : #pragma once
4 :
5 : #include "native_unit.hpp"
6 : #include "basis_unit_abbrev.hpp"
7 : #include "xo/ratio/ratio.hpp"
8 :
9 : namespace xo {
10 : namespace qty {
11 : /** @class basis_unit2
12 : * @brief A dimensionless multiple of a single natively-specified basis dimension
13 : *
14 : * For example "3600 minutes" or "1e-6 grams"
15 : **/
16 : struct basis_unit {
17 : public:
18 : constexpr basis_unit() = default;
19 77 : constexpr basis_unit(dim native_dim, const scalefactor_ratio_type & scalefactor)
20 77 : : native_dim_{native_dim},
21 50 : scalefactor_{scalefactor}
22 : {}
23 :
24 107 : constexpr dim native_dim() const { return native_dim_; }
25 146 : constexpr const scalefactor_ratio_type & scalefactor() const { return scalefactor_; }
26 :
27 36 : constexpr basis_unit2_abbrev_type abbrev() const {
28 36 : return abbrev::basis_unit2_abbrev(native_dim_,
29 : scalefactor_);
30 : }
31 :
32 : constexpr basis_unit & operator=(const basis_unit & x) = default;
33 :
34 : /** @brief identifies a native unit, e.g. time (in seconds) **/
35 : dim native_dim_ = dim::invalid;
36 : /** @brief this unit defined as multiple scalefactor times native unit **/
37 : scalefactor_ratio_type scalefactor_;
38 : };
39 :
40 : namespace bu {
41 : // ----- mass -----
42 :
43 : constexpr basis_unit picogram = basis_unit(dim::mass, scalefactor_ratio_type( 1, 1000000000000));
44 : constexpr basis_unit nanogram = basis_unit(dim::mass, scalefactor_ratio_type( 1, 1000000000));
45 : constexpr basis_unit microgram = basis_unit(dim::mass, scalefactor_ratio_type( 1, 1000000));
46 : constexpr basis_unit milligram = basis_unit(dim::mass, scalefactor_ratio_type( 1, 1000));
47 : constexpr basis_unit gram = basis_unit(dim::mass, scalefactor_ratio_type( 1, 1));
48 : constexpr basis_unit kilogram = basis_unit(dim::mass, scalefactor_ratio_type( 1000, 1));
49 : constexpr basis_unit tonne = basis_unit(dim::mass, scalefactor_ratio_type( 1000000, 1));
50 : constexpr basis_unit kilotonne = basis_unit(dim::mass, scalefactor_ratio_type( 1000000000, 1));
51 : constexpr basis_unit megatonne = basis_unit(dim::mass, scalefactor_ratio_type(1000000000000, 1));
52 :
53 : // ----- distance -----
54 :
55 : /* International spelling */
56 : constexpr basis_unit picometre = basis_unit(dim::distance, scalefactor_ratio_type( 1, 1000000000000));
57 : constexpr basis_unit nanometre = basis_unit(dim::distance, scalefactor_ratio_type( 1, 1000000000));
58 : constexpr basis_unit micrometre = basis_unit(dim::distance, scalefactor_ratio_type( 1, 1000000));
59 : constexpr basis_unit millimetre = basis_unit(dim::distance, scalefactor_ratio_type( 1, 1000));
60 : constexpr basis_unit metre = basis_unit(dim::distance, scalefactor_ratio_type( 1, 1));
61 : constexpr basis_unit kilometre = basis_unit(dim::distance, scalefactor_ratio_type( 1000, 1));
62 : constexpr basis_unit megametre = basis_unit(dim::distance, scalefactor_ratio_type( 1000000, 1));
63 : constexpr basis_unit gigametre = basis_unit(dim::distance, scalefactor_ratio_type( 1000000000, 1));
64 :
65 : constexpr basis_unit lightsecond = basis_unit(dim::distance, scalefactor_ratio_type( 299792458, 1));
66 : constexpr basis_unit astronomicalunit = basis_unit(dim::distance, scalefactor_ratio_type( 149597870700, 1));
67 :
68 : /* US spelling */
69 : constexpr basis_unit picometer = picometre;
70 : constexpr basis_unit nanometer = nanometre;
71 : constexpr basis_unit micrometer = micrometre;
72 : constexpr basis_unit millimeter = millimetre;
73 : constexpr basis_unit meter = metre;
74 : constexpr basis_unit kilometer = kilometre;
75 :
76 : // ----- time -----
77 :
78 : constexpr basis_unit picosecond = basis_unit(dim::time, scalefactor_ratio_type( 1, 1000000000000));
79 : constexpr basis_unit nanosecond = basis_unit(dim::time, scalefactor_ratio_type( 1, 1000000000));
80 : constexpr basis_unit microsecond = basis_unit(dim::time, scalefactor_ratio_type( 1, 1000000));
81 : constexpr basis_unit millisecond = basis_unit(dim::time, scalefactor_ratio_type( 1, 1000));
82 : constexpr basis_unit second = basis_unit(dim::time, scalefactor_ratio_type( 1, 1));
83 : constexpr basis_unit minute = basis_unit(dim::time, scalefactor_ratio_type( 60, 1));
84 : constexpr basis_unit hour = basis_unit(dim::time, scalefactor_ratio_type( 3600, 1));
85 : constexpr basis_unit day = basis_unit(dim::time, scalefactor_ratio_type( 24*3600, 1));
86 : constexpr basis_unit week = basis_unit(dim::time, scalefactor_ratio_type( 7*24*3600, 1));
87 : constexpr basis_unit month = basis_unit(dim::time, scalefactor_ratio_type( 30*24*3600, 1));
88 : constexpr basis_unit year = basis_unit(dim::time, scalefactor_ratio_type((365*24+6)*3600, 1));
89 :
90 : /* alt conventions used in finance */
91 : constexpr basis_unit year365 = basis_unit(dim::time, scalefactor_ratio_type( 365*24*3600, 1));
92 : constexpr basis_unit year360 = basis_unit(dim::time, scalefactor_ratio_type( 360*24*3600, 1));
93 : /* 250 = approx number of trading days in a calendar year */
94 : constexpr basis_unit year250 = basis_unit(dim::time, scalefactor_ratio_type( 250*24*3600, 1));
95 :
96 : // ----- currency -----
97 :
98 : /* pseudounit -- placeholder for any actual currency amount */
99 : constexpr basis_unit currency = basis_unit(dim::currency, scalefactor_ratio_type( 1, 1));
100 :
101 : // ----- price -----
102 :
103 : /* psuedounit -- context-dependent interpretation */
104 : constexpr basis_unit price = basis_unit(dim::price, scalefactor_ratio_type( 1, 1));
105 : }
106 :
107 : namespace units {
108 : /** for runtime work, would like to be able to promptly find special abbreviation
109 : * keyed by (native_dim, scalefactor).
110 : *
111 : * Also want to support compile-time-only unit computation.
112 : * Since constexpr unordered containers aren't obviously feasible (as of c++23).
113 : *
114 : * Solution adopted here is to support introduction of scaled native units
115 : * only at compile time, at least for now
116 : **/
117 :
118 : // ----- scaled_native_unit_abbrev_helper -----
119 :
120 : /* Require: InnerScale is ratio type; InnerScale >= 1
121 : *
122 : * NOTE: clang 18 doesn't accept that scalefactor_ratio_type is a 'structural type'
123 : */
124 : template <dim BasisDim, std::int64_t InnerScaleNum = 1, std::int64_t InnerScaleDen = 1>
125 : struct scaled_native_unit2_abbrev;
126 :
127 : template <dim BasisDim>
128 : struct scaled_native_unit2_abbrev<BasisDim, 1, 1> {
129 : static constexpr const basis_unit2_abbrev_type value
130 : = (basis_unit2_abbrev_type::from_flatstring
131 : (native_unit2_v[static_cast<uint32_t>(BasisDim)]
132 : .abbrev_str()));
133 : };
134 :
135 : inline
136 : constexpr basis_unit2_abbrev_type
137 0 : bu_fallback_abbrev(dim basis_dim,
138 : const scalefactor_ratio_type & scalefactor)
139 : {
140 0 : return (basis_unit2_abbrev_type::from_flatstring
141 0 : (flatstring_concat
142 0 : (scalefactor.to_str<basis_unit2_abbrev_type::fixed_capacity>(),
143 0 : native_unit2_v[static_cast<std::uint32_t>(basis_dim)].abbrev_str())));
144 : }
145 :
146 : #ifdef NOT_USING
147 : template <dim BasisDim,
148 : std::int64_t InnerScaleNum,
149 : std::int64_t InnerScaleDen>
150 : struct scaled_native_unit2_abbrev {
151 : /* e.g. unit of '1000 grams' will have abbrev '1000g' in absence
152 : * of a specialization for scaled_native_unit_abbrev
153 : */
154 : static constexpr const basis_unit2_abbrev_type value
155 : = (basis_unit2_abbrev_type::from_flatstring
156 : (flatstring_concat
157 : (xo::ratio::ratio<std::int64_t>(InnerScaleNum,
158 : InnerScaleDen)
159 : .to_str<basis_unit2_abbrev_type::fixed_capacity>(),
160 : native_unit2_v[static_cast<std::uint32_t>(BasisDim)].abbrev_str())));
161 :
162 : // = bu_fallback_abbrev(BasisDim,
163 : // xo::ratio::ratio<std::int64_t>(InnerScaleNum, InnerScaleDen));
164 : };
165 :
166 : template <>
167 : struct scaled_native_unit2_abbrev<dim::mass, bu::nanogram.scalefactor().num(), bu::nanogram.scalefactor().den()> {
168 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("ng");
169 : };
170 :
171 : template <>
172 : struct scaled_native_unit2_abbrev<dim::mass, bu::microgram.scalefactor().num(), bu::microgram.scalefactor().den()> {
173 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("ug");
174 : };
175 :
176 : template <>
177 : struct scaled_native_unit2_abbrev<dim::mass, bu::milligram.scalefactor().num(), bu::milligram.scalefactor().den()> {
178 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("mg");
179 : };
180 :
181 : template <>
182 : struct scaled_native_unit2_abbrev<dim::mass, 1000, 1> {
183 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("kg");
184 : };
185 :
186 : template <>
187 : struct scaled_native_unit2_abbrev<dim::mass, 1000000, 1> {
188 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("t");
189 : };
190 :
191 : template <>
192 : struct scaled_native_unit2_abbrev<dim::mass, 1000000000, 1> {
193 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("kt");
194 : };
195 :
196 : // ----- units for dim::distance -----
197 :
198 : template <>
199 : struct scaled_native_unit2_abbrev<dim::distance, 1, 1000000000> {
200 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("nm");
201 : };
202 :
203 : template <>
204 : struct scaled_native_unit2_abbrev<dim::distance, 1, 1000000> {
205 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("um");
206 : };
207 :
208 : template <>
209 : struct scaled_native_unit2_abbrev<dim::distance, 1, 1000> {
210 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("mm");
211 : };
212 :
213 : template <>
214 : struct scaled_native_unit2_abbrev<dim::distance, 1000, 1> {
215 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("km");
216 : };
217 :
218 : // ----- units for dim::time -----
219 :
220 : template <>
221 : struct scaled_native_unit2_abbrev<dim::time, 1, 1000000000> {
222 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("ns");
223 : };
224 :
225 : template <>
226 : struct scaled_native_unit2_abbrev<dim::time, 1, 1000000> {
227 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("us");
228 : };
229 :
230 : template <>
231 : struct scaled_native_unit2_abbrev<dim::time, 1, 1000> {
232 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("ms");
233 : };
234 :
235 : template <>
236 : struct scaled_native_unit2_abbrev<dim::time, 60, 1> {
237 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("min");
238 : };
239 :
240 : template <>
241 : struct scaled_native_unit2_abbrev<dim::time, 3600, 1> {
242 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("hr");
243 : };
244 :
245 : template <>
246 : struct scaled_native_unit2_abbrev<dim::time, 24*3600, 1> {
247 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("dy");
248 : };
249 :
250 : template <>
251 : struct scaled_native_unit2_abbrev<dim::time, 250*24*3600, 1> {
252 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("yr250");
253 : };
254 :
255 : template <>
256 : struct scaled_native_unit2_abbrev<dim::time, 360*24*3600, 1> {
257 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("yr360");
258 : };
259 :
260 : template <>
261 : struct scaled_native_unit2_abbrev<dim::time, 365*24*3600, 1> {
262 : static constexpr const basis_unit2_abbrev_type value = basis_unit2_abbrev_type::from_chars("yr365");
263 : };
264 :
265 : // ----- native unit abbrev api -----
266 :
267 : template <dim BasisDim, std::int64_t InnerScaleNum = 1, std::int64_t InnerScaleDen = 1>
268 : constexpr auto scaled_native_unit2_abbrev_v = scaled_native_unit2_abbrev<BasisDim, InnerScaleNum, InnerScaleDen>::value;
269 : #endif
270 : }
271 :
272 :
273 : } /*namespace qty*/
274 : } /*namespace xo*/
275 :
276 : /** end basis_unit.hpp **/
|