Physical Quantities  v1.0.0
C++ library of physical quantities, physical models, and units of measure for scientific computing. https://github.com/acodcha/phq
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 
37 namespace 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.
49 class Dimensions {
50 public:
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.
57  constexpr 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 
308 private:
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 
331 inline 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 
339 inline 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 
347 inline 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 
369 inline 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 
391 inline constexpr bool operator<=(const Dimensions& left, const Dimensions& right) noexcept {
392  return !(left > right);
393 }
394 
395 inline constexpr bool operator>=(const Dimensions& left, const Dimensions& right) noexcept {
396  return !(left < right);
397 }
398 
399 inline 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.
406 inline constexpr Dimensions Dimensionless;
407 
408 } // namespace PhQ
409 
410 namespace std {
411 
412 template <>
413 struct 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 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...
Definition: Temperature.hpp:40
constexpr int8_t Value() const noexcept
Value of this base physical dimension.
Definition: Temperature.hpp:69
static std::string_view Label() noexcept
Label of this base physical dimension.
Definition: Temperature.hpp:79
std::string Print() const noexcept
Prints this base physical dimension as a string.
Definition: Temperature.hpp:84
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...
Definition: Dimensions.hpp:49
constexpr const Dimension::Temperature & Temperature() const noexcept
Base physical dimension of temperature of this physical dimension set.
Definition: Dimensions.hpp:104
std::string Print() const
Prints this physical dimension set as a string.
Definition: Dimensions.hpp:119
Dimension::Time time
Base physical dimension of time of this physical dimension set.
Definition: Dimensions.hpp:310
Dimension::LuminousIntensity luminous_intensity
Base physical dimension of luminous intensity of this physical dimension set.
Definition: Dimensions.hpp:328
constexpr const Dimension::ElectricCurrent & ElectricCurrent() const noexcept
Base physical dimension of electric current of this physical dimension set.
Definition: Dimensions.hpp:99
std::string YAML() const
Serializes this physical dimension set as a YAML message.
Definition: Dimensions.hpp:260
Dimension::Temperature temperature
Base physical dimension of temperature of this physical dimension set.
Definition: Dimensions.hpp:322
Dimension::Length length
Base physical dimension of length of this physical dimension set.
Definition: Dimensions.hpp:313
Dimension::Mass mass
Base physical dimension of mass of this physical dimension set.
Definition: Dimensions.hpp:316
Dimension::ElectricCurrent electric_current
Base physical dimension of electric current of this physical dimension set.
Definition: Dimensions.hpp:319
std::string JSON() const
Serializes this physical dimension set as a JSON message.
Definition: Dimensions.hpp:171
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.
Definition: Dimensions.hpp:57
constexpr const Dimension::SubstanceAmount & SubstanceAmount() const noexcept
Base physical dimension of amount of substance of this physical dimension set.
Definition: Dimensions.hpp:109
~Dimensions() noexcept=default
Destructor. Destroys this physical dimension set.
constexpr const Dimension::Length & Length() const noexcept
Base physical dimension of length of this physical dimension set.
Definition: Dimensions.hpp:89
constexpr const Dimension::Mass & Mass() const noexcept
Base physical dimension of mass of this physical dimension set.
Definition: Dimensions.hpp:94
constexpr const Dimension::Time & Time() const noexcept
Base physical dimension of time of this physical dimension set.
Definition: Dimensions.hpp:84
Dimension::SubstanceAmount substance_amount
Base physical dimension of amount of substance of this physical dimension set.
Definition: Dimensions.hpp:325
constexpr const Dimension::LuminousIntensity & LuminousIntensity() const noexcept
Base physical dimension of luminous intensity of this physical dimension set.
Definition: Dimensions.hpp:114
std::string XML() const
Serializes this physical dimension set as an XML message.
Definition: Dimensions.hpp:223
constexpr Dimensions()=default
Default constructor. Constructs a dimensionless physical dimension set where all base physical dimens...
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.
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....
Definition: Dimensions.hpp:406
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
std::ostream & operator<<(std::ostream &stream, const Acceleration< NumericType > &acceleration)