Physical Quantities  v1.0.0
C++ library of physical quantities, physical models, and units of measure for scientific computing. https://github.com/acodcha/phq
Loading...
Searching...
No Matches
Dimensions.hpp
Go to the documentation of this file.
1// Copyright © 2020-2024 Alexandre Coderre-Chabot
2//
3// This file is part of Physical Quantities (PhQ), a C++ library of physical quantities, physical
4// models, and units of measure for scientific computing.
5//
6// Physical Quantities is hosted at:
7// https://github.com/acodcha/phq
8//
9// Physical Quantities is licensed under the MIT License:
10// https://mit-license.org
11//
12// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
13// associated documentation files (the "Software"), to deal in the Software without restriction,
14// including without limitation the rights to use, copy, modify, merge, publish, distribute,
15// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
16// furnished to do so, subject to the following conditions:
17// - The above copyright notice and this permission notice shall be included in all copies or
18// substantial portions of the Software.
19// - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
20// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
23// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25#ifndef PHQ_DIMENSIONS_HPP
26#define PHQ_DIMENSIONS_HPP
27
28#include "Base.hpp"
30#include "Dimension/Length.hpp"
32#include "Dimension/Mass.hpp"
35#include "Dimension/Time.hpp"
36
37namespace PhQ {
38
39/// \brief Physical dimension set of a unit of measure or physical quantity. Composed of the seven
40/// independent base physical dimensions: time (T), length (L), mass (M), electric current (I),
41/// temperature (Θ), amount of substance (N), and luminous intensity (J). Units of measure that
42/// share the same physical dimension set are of the same type and can be converted between one
43/// another. For example, the metre per second and the mile per hour are both units of measure that
44/// have the same physical dimension set of T^(-1)·L, which is the physical dimension set of speed,
45/// so these two units of measure can be converted between one another. On the other hand, the
46/// kilogram per cubic metre is a unit of measure with physical dimension set L^(-3)·M, which is the
47/// physical dimension set of mass density, so this unit of measure cannot be converted to either
48/// the metre per second or the mile per hour, which have a different physical dimension set.
50public:
51 /// \brief Default constructor. Constructs a dimensionless physical dimension set where all base
52 /// physical dimensions are zero.
53 constexpr Dimensions() = default;
54
55 /// \brief Constructor. Constructs a physical dimension set from the given base physical
56 /// dimensions.
65
66 /// \brief Destructor. Destroys this physical dimension set.
67 ~Dimensions() noexcept = default;
68
69 /// \brief Copy constructor. Constructs a physical dimension set by copying another one.
70 constexpr Dimensions(const Dimensions& other) = default;
71
72 /// \brief Move constructor. Constructs a physical dimension set by moving another one.
73 constexpr Dimensions(Dimensions&& other) noexcept = default;
74
75 /// \brief Copy assignment operator. Assigns the base physical dimensions of this physical
76 /// dimension set by copying from another one.
77 constexpr Dimensions& operator=(const Dimensions& other) = default;
78
79 /// \brief Move assignment operator. Assigns the base physical dimensions of this physical
80 /// dimension set by moving another one.
81 constexpr Dimensions& operator=(Dimensions&& other) noexcept = default;
82
83 /// \brief Base physical dimension of time of this physical dimension set.
84 [[nodiscard]] constexpr const Dimension::Time& Time() const noexcept {
85 return time;
86 }
87
88 /// \brief Base physical dimension of length of this physical dimension set.
89 [[nodiscard]] constexpr const Dimension::Length& Length() const noexcept {
90 return length;
91 }
92
93 /// \brief Base physical dimension of mass of this physical dimension set.
94 [[nodiscard]] constexpr const Dimension::Mass& Mass() const noexcept {
95 return mass;
96 }
97
98 /// \brief Base physical dimension of electric current of this physical dimension set.
99 [[nodiscard]] constexpr const Dimension::ElectricCurrent& ElectricCurrent() const noexcept {
100 return electric_current;
101 }
102
103 /// \brief Base physical dimension of temperature of this physical dimension set.
104 [[nodiscard]] constexpr const Dimension::Temperature& Temperature() const noexcept {
105 return temperature;
106 }
107
108 /// \brief Base physical dimension of amount of substance of this physical dimension set.
109 [[nodiscard]] constexpr const Dimension::SubstanceAmount& SubstanceAmount() const noexcept {
110 return substance_amount;
111 }
112
113 /// \brief Base physical dimension of luminous intensity of this physical dimension set.
114 [[nodiscard]] constexpr const Dimension::LuminousIntensity& LuminousIntensity() const noexcept {
115 return luminous_intensity;
116 }
117
118 /// \brief Prints this physical dimension set as a string.
119 [[nodiscard]] std::string Print() const {
120 std::string string;
121 string.append(time.Print());
122 const std::string length_string{length.Print()};
123 if (!length_string.empty()) {
124 if (!string.empty()) {
125 string.append("·");
126 }
127 string.append(length_string);
128 }
129 const std::string mass_string{mass.Print()};
130 if (!mass_string.empty()) {
131 if (!string.empty()) {
132 string.append("·");
133 }
134 string.append(mass_string);
135 }
136 const std::string electric_current_string{electric_current.Print()};
137 if (!electric_current_string.empty()) {
138 if (!string.empty()) {
139 string.append("·");
140 }
141 string.append(electric_current_string);
142 }
143 const std::string temperature_string{temperature.Print()};
144 if (!temperature_string.empty()) {
145 if (!string.empty()) {
146 string.append("·");
147 }
148 string.append(temperature_string);
149 }
150 const std::string substance_amount_string{substance_amount.Print()};
151 if (!substance_amount_string.empty()) {
152 if (!string.empty()) {
153 string.append("·");
154 }
155 string.append(substance_amount_string);
156 }
157 const std::string luminous_intensity_string{luminous_intensity.Print()};
158 if (!luminous_intensity_string.empty()) {
159 if (!string.empty()) {
160 string.append("·");
161 }
162 string.append(luminous_intensity_string);
163 }
164 if (string.empty()) {
165 return "1";
166 }
167 return string;
168 }
169
170 /// \brief Serializes this physical dimension set as a JSON message.
171 [[nodiscard]] std::string JSON() const {
172 std::string message;
173 if (time.Value() != 0) {
174 message.append(
175 "\"" + SnakeCase(Dimension::Time::Label()) + "\":" + std::to_string(time.Value()));
176 }
177 if (length.Value() != 0) {
178 if (!message.empty()) {
179 message.append(",");
180 }
181 message.append(
182 "\"" + SnakeCase(Dimension::Length::Label()) + "\":" + std::to_string(length.Value()));
183 }
184 if (mass.Value() != 0) {
185 if (!message.empty()) {
186 message.append(",");
187 }
188 message.append(
189 "\"" + SnakeCase(Dimension::Mass::Label()) + "\":" + std::to_string(mass.Value()));
190 }
191 if (electric_current.Value() != 0) {
192 if (!message.empty()) {
193 message.append(",");
194 }
195 message.append("\"" + SnakeCase(Dimension::ElectricCurrent::Label())
196 + "\":" + std::to_string(electric_current.Value()));
197 }
198 if (temperature.Value() != 0) {
199 if (!message.empty()) {
200 message.append(",");
201 }
202 message.append("\"" + SnakeCase(Dimension::Temperature::Label())
203 + "\":" + std::to_string(temperature.Value()));
204 }
205 if (substance_amount.Value() != 0) {
206 if (!message.empty()) {
207 message.append(",");
208 }
209 message.append("\"" + SnakeCase(Dimension::SubstanceAmount::Label())
210 + "\":" + std::to_string(substance_amount.Value()));
211 }
212 if (luminous_intensity.Value() != 0) {
213 if (!message.empty()) {
214 message.append(",");
215 }
216 message.append("\"" + SnakeCase(Dimension::LuminousIntensity::Label())
217 + "\":" + std::to_string(luminous_intensity.Value()));
218 }
219 return "{" + message + "}";
220 }
221
222 /// \brief Serializes this physical dimension set as an XML message.
223 [[nodiscard]] std::string XML() const {
224 std::string message;
225 if (time.Value() != 0) {
226 const std::string label{SnakeCase(Dimension::Time::Label())};
227 message.append("<" + label + ">" + std::to_string(time.Value()) + "</" + label + ">");
228 }
229 if (length.Value() != 0) {
230 const std::string label{SnakeCase(Dimension::Length::Label())};
231 message.append("<" + label + ">" + std::to_string(length.Value()) + "</" + label + ">");
232 }
233 if (mass.Value() != 0) {
234 const std::string label{SnakeCase(Dimension::Mass::Label())};
235 message.append("<" + label + ">" + std::to_string(mass.Value()) + "</" + label + ">");
236 }
237 if (electric_current.Value() != 0) {
238 const std::string label{SnakeCase(Dimension::ElectricCurrent::Label())};
239 message.append(
240 "<" + label + ">" + std::to_string(electric_current.Value()) + "</" + label + ">");
241 }
242 if (temperature.Value() != 0) {
243 const std::string label{SnakeCase(Dimension::Temperature::Label())};
244 message.append("<" + label + ">" + std::to_string(temperature.Value()) + "</" + label + ">");
245 }
246 if (substance_amount.Value() != 0) {
247 const std::string label{SnakeCase(Dimension::SubstanceAmount::Label())};
248 message.append(
249 "<" + label + ">" + std::to_string(substance_amount.Value()) + "</" + label + ">");
250 }
251 if (luminous_intensity.Value() != 0) {
252 const std::string label{SnakeCase(Dimension::LuminousIntensity::Label())};
253 message.append(
254 "<" + label + ">" + std::to_string(luminous_intensity.Value()) + "</" + label + ">");
255 }
256 return message;
257 }
258
259 /// \brief Serializes this physical dimension set as a YAML message.
260 [[nodiscard]] std::string YAML() const {
261 std::string message;
262 if (time.Value() != 0) {
263 message.append(SnakeCase(Dimension::Time::Label()) + ":" + std::to_string(time.Value()));
264 }
265 if (length.Value() != 0) {
266 if (!message.empty()) {
267 message.append(",");
268 }
269 message.append(SnakeCase(Dimension::Length::Label()) + ":" + std::to_string(length.Value()));
270 }
271 if (mass.Value() != 0) {
272 if (!message.empty()) {
273 message.append(",");
274 }
275 message.append(SnakeCase(Dimension::Mass::Label()) + ":" + std::to_string(mass.Value()));
276 }
277 if (electric_current.Value() != 0) {
278 if (!message.empty()) {
279 message.append(",");
280 }
281 message.append(SnakeCase(Dimension::ElectricCurrent::Label()) + ":"
282 + std::to_string(electric_current.Value()));
283 }
284 if (temperature.Value() != 0) {
285 if (!message.empty()) {
286 message.append(",");
287 }
288 message.append(
289 SnakeCase(Dimension::Temperature::Label()) + ":" + std::to_string(temperature.Value()));
290 }
291 if (substance_amount.Value() != 0) {
292 if (!message.empty()) {
293 message.append(",");
294 }
295 message.append(SnakeCase(Dimension::SubstanceAmount::Label()) + ":"
296 + std::to_string(substance_amount.Value()));
297 }
298 if (luminous_intensity.Value() != 0) {
299 if (!message.empty()) {
300 message.append(",");
301 }
302 message.append(SnakeCase(Dimension::LuminousIntensity::Label()) + ":"
303 + std::to_string(luminous_intensity.Value()));
304 }
305 return "{" + message + "}";
306 }
307
308private:
309 /// \brief Base physical dimension of time of this physical dimension set.
311
312 /// \brief Base physical dimension of length of this physical dimension set.
314
315 /// \brief Base physical dimension of mass of this physical dimension set.
317
318 /// \brief Base physical dimension of electric current of this physical dimension set.
320
321 /// \brief Base physical dimension of temperature of this physical dimension set.
323
324 /// \brief Base physical dimension of amount of substance of this physical dimension set.
326
327 /// \brief Base physical dimension of luminous intensity of this physical dimension set.
329};
330
331inline constexpr bool operator==(const Dimensions& left, const Dimensions& right) noexcept {
332 return left.Time() == right.Time() && left.Length() == right.Length()
333 && left.Mass() == right.Mass() && left.ElectricCurrent() == right.ElectricCurrent()
334 && left.Temperature() == right.Temperature()
335 && left.SubstanceAmount() == right.SubstanceAmount()
336 && left.LuminousIntensity() == right.LuminousIntensity();
337}
338
339inline constexpr bool operator!=(const Dimensions& left, const Dimensions& right) noexcept {
340 return left.Time() != right.Time() || left.Length() != right.Length()
341 || left.Mass() != right.Mass() || left.ElectricCurrent() != right.ElectricCurrent()
342 || left.Temperature() != right.Temperature()
343 || left.SubstanceAmount() != right.SubstanceAmount()
344 || left.LuminousIntensity() != right.LuminousIntensity();
345}
346
347inline constexpr bool operator<(const Dimensions& left, const Dimensions& right) noexcept {
348 if (left.Time() != right.Time()) {
349 return left.Time() < right.Time();
350 }
351 if (left.Length() != right.Length()) {
352 return left.Length() < right.Length();
353 }
354 if (left.Mass() != right.Mass()) {
355 return left.Mass() < right.Mass();
356 }
357 if (left.ElectricCurrent() != right.ElectricCurrent()) {
358 return left.ElectricCurrent() < right.ElectricCurrent();
359 }
360 if (left.Temperature() != right.Temperature()) {
361 return left.Temperature() < right.Temperature();
362 }
363 if (left.SubstanceAmount() != right.SubstanceAmount()) {
364 return left.SubstanceAmount() < right.SubstanceAmount();
365 }
366 return left.LuminousIntensity() < right.LuminousIntensity();
367}
368
369inline constexpr bool operator>(const Dimensions& left, const Dimensions& right) noexcept {
370 if (left.Time() != right.Time()) {
371 return left.Time() > right.Time();
372 }
373 if (left.Length() != right.Length()) {
374 return left.Length() > right.Length();
375 }
376 if (left.Mass() != right.Mass()) {
377 return left.Mass() > right.Mass();
378 }
379 if (left.ElectricCurrent() != right.ElectricCurrent()) {
380 return left.ElectricCurrent() > right.ElectricCurrent();
381 }
382 if (left.Temperature() != right.Temperature()) {
383 return left.Temperature() > right.Temperature();
384 }
385 if (left.SubstanceAmount() != right.SubstanceAmount()) {
386 return left.SubstanceAmount() > right.SubstanceAmount();
387 }
388 return left.LuminousIntensity() > right.LuminousIntensity();
389}
390
391inline constexpr bool operator<=(const Dimensions& left, const Dimensions& right) noexcept {
392 return !(left > right);
393}
394
395inline constexpr bool operator>=(const Dimensions& left, const Dimensions& right) noexcept {
396 return !(left < right);
397}
398
399inline std::ostream& operator<<(std::ostream& stream, const Dimensions& dimensions) {
400 stream << dimensions.Print();
401 return stream;
402}
403
404/// \brief Dimensionless physical dimension set. This dimension set has all base dimensions of zero.
405/// Applies to all dimensionless units of measure and dimensionless physical quantities.
406inline constexpr Dimensions Dimensionless;
407
408} // namespace PhQ
409
410namespace std {
411
412template <>
413struct hash<PhQ::Dimensions> {
414 inline size_t operator()(const PhQ::Dimensions& dimensions) const {
415 size_t result{17};
416 result = static_cast<size_t>(31) * result + dimensions.Time().Value();
417 result = static_cast<size_t>(31) * result + dimensions.Length().Value();
418 result = static_cast<size_t>(31) * result + dimensions.Mass().Value();
419 result = static_cast<size_t>(31) * result + dimensions.ElectricCurrent().Value();
420 result = static_cast<size_t>(31) * result + dimensions.Temperature().Value();
421 result = static_cast<size_t>(31) * result + dimensions.SubstanceAmount().Value();
422 result = static_cast<size_t>(31) * result + dimensions.LuminousIntensity().Value();
423 return result;
424 }
425};
426
427} // namespace std
428
429#endif // PHQ_DIMENSIONS_HPP
Base physical dimension of electric current. Typically denoted "I". One of seven independent base phy...
static std::string_view Label() noexcept
Label of this base physical dimension.
std::string Print() const noexcept
Prints this base physical dimension as a string.
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
Base physical dimension of length. Typically denoted "L". One of seven independent base physical dime...
Definition Length.hpp:40
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
Definition Length.hpp:68
static std::string_view Label() noexcept
Label of this base physical dimension.
Definition Length.hpp:78
std::string Print() const noexcept
Prints this base physical dimension as a string.
Definition Length.hpp:83
Base physical dimension of luminous intensity. Typically denoted "J". One of seven independent base p...
static std::string_view Label() noexcept
Label of this base physical dimension.
constexpr LuminousIntensity()=default
Default constructor. Constructs a base physical dimension of luminous intensity with a value of zero.
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
std::string Print() const noexcept
Prints this base physical dimension as a string.
Base physical dimension of mass. Typically denoted "M". One of seven independent base physical dimens...
Definition Mass.hpp:40
static std::string_view Label() noexcept
Label of this base physical dimension.
Definition Mass.hpp:76
std::string Print() const noexcept
Prints this base physical dimension as a string.
Definition Mass.hpp:81
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
Definition Mass.hpp:66
Base physical dimension of amount of substance. Typically denoted "N". One of seven independent base ...
std::string Print() const noexcept
Prints this base physical dimension as a string.
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
static std::string_view Label() noexcept
Label of this base physical dimension.
Base physical dimension of temperature. Typically denoted "Θ". One of seven independent base physical...
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
static std::string_view Label() noexcept
Label of this base physical dimension.
std::string Print() const noexcept
Prints this base physical dimension as a string.
Base physical dimension of time. Typically denoted "T". One of seven independent base physical dimens...
Definition Time.hpp:40
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
Definition Time.hpp:66
static std::string_view Label() noexcept
Label of this base physical dimension.
Definition Time.hpp:76
std::string Print() const noexcept
Prints this base physical dimension as a string.
Definition Time.hpp:81
Physical dimension set of a unit of measure or physical quantity. Composed of the seven independent b...
std::string Print() const
Prints this physical dimension set as a string.
Dimension::Time time
Base physical dimension of time of this physical dimension set.
constexpr const Dimension::Mass & Mass() const noexcept
Base physical dimension of mass of this physical dimension set.
constexpr const Dimension::LuminousIntensity & LuminousIntensity() const noexcept
Base physical dimension of luminous intensity of this physical dimension set.
Dimension::LuminousIntensity luminous_intensity
Base physical dimension of luminous intensity of this physical dimension set.
std::string YAML() const
Serializes this physical dimension set as a YAML message.
constexpr const Dimension::Time & Time() const noexcept
Base physical dimension of time of this physical dimension set.
constexpr const Dimension::SubstanceAmount & SubstanceAmount() const noexcept
Base physical dimension of amount of substance of this physical dimension set.
constexpr const Dimension::ElectricCurrent & ElectricCurrent() const noexcept
Base physical dimension of electric current of this physical dimension set.
Dimension::Temperature temperature
Base physical dimension of temperature of this physical dimension set.
Dimension::Length length
Base physical dimension of length of this physical dimension set.
Dimension::Mass mass
Base physical dimension of mass of this physical dimension set.
Dimension::ElectricCurrent electric_current
Base physical dimension of electric current of this physical dimension set.
std::string JSON() const
Serializes this physical dimension set as a JSON message.
constexpr Dimensions(const Dimension::Time &time, const Dimension::Length &length, const Dimension::Mass &mass, const Dimension::ElectricCurrent &electric_current, const Dimension::Temperature &temperature, const Dimension::SubstanceAmount &substance_amount, const Dimension::LuminousIntensity &luminous_intensity)
Constructor. Constructs a physical dimension set from the given base physical dimensions.
~Dimensions() noexcept=default
Destructor. Destroys this physical dimension set.
constexpr const Dimension::Temperature & Temperature() const noexcept
Base physical dimension of temperature of this physical dimension set.
Dimension::SubstanceAmount substance_amount
Base physical dimension of amount of substance of this physical dimension set.
std::string XML() const
Serializes this physical dimension set as an XML message.
constexpr Dimensions()=default
Default constructor. Constructs a dimensionless physical dimension set where all base physical dimens...
constexpr const Dimension::Length & Length() const noexcept
Base physical dimension of length of this physical dimension set.
Time. Can represent either a point in time, a time duration, or a period. For the inverse of time,...
Definition Time.hpp:172
Namespace that encompasses all of the Physical Quantities library's content.
std::ostream & operator<<(std::ostream &stream, const Acceleration< NumericType > &acceleration)
constexpr bool operator<(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Dimensions Dimensionless
Dimensionless physical dimension set. This dimension set has all base dimensions of zero....
constexpr bool operator<=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator>(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator==(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator>=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
std::string SnakeCase(const std::string_view string)
Returns a copy of the given string in snake case: all characters are lowercase and all spaces are rep...
Definition Base.hpp:263
constexpr bool operator!=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept