Unit Conversion and Dimensional Analysis Library 2.3.0
A compile-time c++14 unit conversion library
Loading...
Searching...
No Matches
units.h
Go to the documentation of this file.
1//--------------------------------------------------------------------------------------------------
2//
3// Units: A compile-time c++14 unit conversion library with no dependencies
4//
5//--------------------------------------------------------------------------------------------------
6//
7// The MIT License (MIT)
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10// and associated documentation files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use, copy, modify, merge, publish,
12// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
13// Software is furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in all copies or
16// substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
19// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23//
24//--------------------------------------------------------------------------------------------------
25//
26// Copyright (c) 2016 Nic Holthaus
27//
28//--------------------------------------------------------------------------------------------------
29//
30// ATTRIBUTION:
31// Parts of this work have been adapted from:
32// http://stackoverflow.com/questions/35069778/create-comparison-trait-for-template-classes-whose-parameters-are-in-a-different
33// http://stackoverflow.com/questions/28253399/check-traits-for-all-variadic-template-arguments/28253503
34// http://stackoverflow.com/questions/36321295/rational-approximation-of-square-root-of-stdratio-at-compile-time?noredirect=1#comment60266601_36321295
35//
36//--------------------------------------------------------------------------------------------------
37//
41//
42//--------------------------------------------------------------------------------------------------
43
44#pragma once
45
46#ifndef units_h__
47#define units_h__
48
49#ifdef _MSC_VER
50# pragma push_macro("pascal")
51# undef pascal
52# if _MSC_VER <= 1800
53# define _ALLOW_KEYWORD_MACROS
54# pragma warning(push)
55# pragma warning(disable : 4520)
56# pragma push_macro("constexpr")
57# define constexpr /*constexpr*/
58# pragma push_macro("noexcept")
59# define noexcept throw()
60# endif // _MSC_VER < 1800
61#endif // _MSC_VER
62
63#if defined(__MINGW64__) || defined(__MINGW32__)
64# pragma push_macro("pascal")
65# undef pascal
66#endif // __MINGW64__ or __MINGW32__
67
68#if !defined(_MSC_VER) || _MSC_VER > 1800
69# define UNIT_HAS_LITERAL_SUPPORT
70# define UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT
71#endif
72
73#ifndef UNIT_LIB_DEFAULT_TYPE
74# define UNIT_LIB_DEFAULT_TYPE double
75#endif
76
77//--------------------
78// INCLUDES
79//--------------------
80
81#include <chrono>
82#include <cstddef>
83#include <ratio>
84#include <type_traits>
85#include <cstdint>
86#include <cmath>
87#include <limits>
88
89#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
90 #include <iostream>
91 #include <string>
92 #include <locale>
93
94 //------------------------------
95 // STRING FORMATTER
96 //------------------------------
97
98 namespace units
99 {
100 namespace detail
101 {
102 template <typename T> std::string to_string(const T& t)
103 {
104 std::string str{ std::to_string(t) };
105 int offset{ 1 };
106
107 // remove trailing decimal points for integer value units. Locale aware!
108 struct lconv * lc;
109 lc = localeconv();
110 char decimalPoint = *lc->decimal_point;
111 if (str.find_last_not_of('0') == str.find(decimalPoint)) { offset = 0; }
112 str.erase(str.find_last_not_of('0') + offset, std::string::npos);
113 return str;
114 }
115 }
116 }
117#endif
118
119namespace units
120{
121 template<typename T> inline constexpr const char* name(const T&);
122 template<typename T> inline constexpr const char* name_plural(const T&);
123 template<typename T> inline constexpr const char* abbreviation(const T&);
124}
125
126//------------------------------
127// MACROS
128//------------------------------
129
146#define UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, /*definition*/...)\
147 namespace namespaceName\
148 {\
149 typedef __VA_ARGS__ namePlural; \
150 typedef namePlural nameSingular; \
151 typedef namePlural abbreviation; \
152 }
153
161#define UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
162 namespace namespaceName\
163 {\
164 typedef unit_t<nameSingular> nameSingular ## _t; \
165 }
166
175#define UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular, underlyingType)\
176 namespace namespaceName\
177 {\
178 typedef unit_t<nameSingular,underlyingType> nameSingular ## _t; \
179 }
180
190#if defined(UNIT_LIB_DISABLE_IOSTREAM)
191 #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)
192#else
193 #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)\
194 namespace namespaceName\
195 {\
196 inline std::ostream& operator<<(std::ostream& os, const nameSingular ## _t& obj) \
197 {\
198 os << obj() << " "#abbrev; return os; \
199 }\
200 inline std::string to_string(const nameSingular ## _t& obj)\
201 {\
202 return units::detail::to_string(obj()) + std::string(" "#abbrev);\
203 }\
204 }
205#endif
206
218#define UNIT_ADD_NAME(namespaceName, nameSingular, namePlural, abbrev)\
219template<> inline constexpr const char* name(const namespaceName::nameSingular ## _t&)\
220{\
221 return #nameSingular;\
222}\
223template<> inline constexpr const char* abbreviation(const namespaceName::nameSingular ## _t&)\
224{\
225 return #abbrev;\
226}\
227template<> inline constexpr const char* name_plural(const namespaceName::nameSingular ## _t&)\
228{\
229 return #namePlural;\
230}
231
243#if defined(UNIT_HAS_LITERAL_SUPPORT)
244 #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)\
245 namespace literals\
246 {\
247 inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation(long double d)\
248 {\
249 return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
250 }\
251 inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation (unsigned long long d)\
252 {\
253 return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
254 }\
255 }
256#else
257 #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)
258#endif
259
279#define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
280 UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
281 UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
282 UNIT_ADD_NAME(namespaceName,nameSingular,namePlural, abbreviation)\
283 UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
284 UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
285
306#define UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName, nameSingular, namePlural, abbreviation, underlyingType, /*definition*/...)\
307 UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
308 UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular,underlyingType)\
309 UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
310 UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
311
321#define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)\
322 namespace namespaceName\
323 {\
324 typedef unit_t<nameSingular, UNIT_LIB_DEFAULT_TYPE, units::decibel_scale> abbreviation ## _t; \
325 }\
326 UNIT_ADD_IO(namespaceName, abbreviation, abbreviation)\
327 UNIT_ADD_LITERALS(namespaceName, abbreviation, abbreviation)
328
337
338#define UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
339 namespace traits\
340 {\
341\
342 namespace detail\
343 {\
344 template<typename T> struct is_ ## unitCategory ## _unit_impl : std::false_type {};\
345 template<typename C, typename U, typename P, typename T>\
346 struct is_ ## unitCategory ## _unit_impl<units::unit<C, U, P, T>> : std::is_same<units::traits::base_unit_of<typename units::traits::unit_traits<units::unit<C, U, P, T>>::base_unit_type>, units::category::unitCategory ## _unit>::type {};\
347 template<typename U, typename S, template<typename> class N>\
348 struct is_ ## unitCategory ## _unit_impl<units::unit_t<U, S, N>> : std::is_same<units::traits::base_unit_of<typename units::traits::unit_t_traits<units::unit_t<U, S, N>>::unit_type>, units::category::unitCategory ## _unit>::type {};\
349 }\
350\
351 }
352
353#if defined(UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT)
354#define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
355 namespace traits\
356 {\
357 template<typename... T> struct is_ ## unitCategory ## _unit : std::integral_constant<bool, units::all_true<units::traits::detail::is_ ## unitCategory ## _unit_impl<std::decay_t<T>>::value...>::value> {};\
358 }
359#else
360#define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
361 namespace traits\
362 {\
363 template<typename T1, typename T2 = T1, typename T3 = T1>\
364 struct is_ ## unitCategory ## _unit : std::integral_constant<bool, units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T1>::type>::value &&\
365 units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T2>::type>::value &&\
366 units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T3>::type>::value>{};\
367 }
368#endif
369
370#define UNIT_ADD_CATEGORY_TRAIT(unitCategory)\
371 UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
372\
373\
374\
375\
376 UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)
377
396#define UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
397 UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
398 UNIT_ADD(namespaceName, femto ## nameSingular, femto ## namePlural, f ## abbreviation, femto<namePlural>)\
399 UNIT_ADD(namespaceName, pico ## nameSingular, pico ## namePlural, p ## abbreviation, pico<namePlural>)\
400 UNIT_ADD(namespaceName, nano ## nameSingular, nano ## namePlural, n ## abbreviation, nano<namePlural>)\
401 UNIT_ADD(namespaceName, micro ## nameSingular, micro ## namePlural, u ## abbreviation, micro<namePlural>)\
402 UNIT_ADD(namespaceName, milli ## nameSingular, milli ## namePlural, m ## abbreviation, milli<namePlural>)\
403 UNIT_ADD(namespaceName, centi ## nameSingular, centi ## namePlural, c ## abbreviation, centi<namePlural>)\
404 UNIT_ADD(namespaceName, deci ## nameSingular, deci ## namePlural, d ## abbreviation, deci<namePlural>)\
405 UNIT_ADD(namespaceName, deca ## nameSingular, deca ## namePlural, da ## abbreviation, deca<namePlural>)\
406 UNIT_ADD(namespaceName, hecto ## nameSingular, hecto ## namePlural, h ## abbreviation, hecto<namePlural>)\
407 UNIT_ADD(namespaceName, kilo ## nameSingular, kilo ## namePlural, k ## abbreviation, kilo<namePlural>)\
408 UNIT_ADD(namespaceName, mega ## nameSingular, mega ## namePlural, M ## abbreviation, mega<namePlural>)\
409 UNIT_ADD(namespaceName, giga ## nameSingular, giga ## namePlural, G ## abbreviation, giga<namePlural>)\
410 UNIT_ADD(namespaceName, tera ## nameSingular, tera ## namePlural, T ## abbreviation, tera<namePlural>)\
411 UNIT_ADD(namespaceName, peta ## nameSingular, peta ## namePlural, P ## abbreviation, peta<namePlural>)\
412
413
431#define UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
432 UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
433 UNIT_ADD(namespaceName, kibi ## nameSingular, kibi ## namePlural, Ki ## abbreviation, kibi<namePlural>)\
434 UNIT_ADD(namespaceName, mebi ## nameSingular, mebi ## namePlural, Mi ## abbreviation, mebi<namePlural>)\
435 UNIT_ADD(namespaceName, gibi ## nameSingular, gibi ## namePlural, Gi ## abbreviation, gibi<namePlural>)\
436 UNIT_ADD(namespaceName, tebi ## nameSingular, tebi ## namePlural, Ti ## abbreviation, tebi<namePlural>)\
437 UNIT_ADD(namespaceName, pebi ## nameSingular, pebi ## namePlural, Pi ## abbreviation, pebi<namePlural>)\
438 UNIT_ADD(namespaceName, exbi ## nameSingular, exbi ## namePlural, Ei ## abbreviation, exbi<namePlural>)
439
440//--------------------
441// UNITS NAMESPACE
442//--------------------
443
448namespace units
449{
450 //----------------------------------
451 // DOXYGEN
452 //----------------------------------
453
459
466
473
480
486
491
496
497 //------------------------------
498 // FORWARD DECLARATIONS
499 //------------------------------
500 // DOXYGEN IGNORE
502 namespace constants
503 {
504 namespace detail
505 {
506 static constexpr const UNIT_LIB_DEFAULT_TYPE PI_VAL = 3.14159265358979323846264338327950288419716939937510;
507 }
508 } // END DOXYGEN IGNORE
510
511 //------------------------------
512 // RATIO TRAITS
513 //------------------------------
514
519 // DOXYGEN IGNORE
521 namespace detail
522 {
524 template<class T>
525 struct has_num_impl
526 {
527 template<class U>
528 static constexpr auto test(U*)->std::is_integral<decltype(U::num)> {return std::is_integral<decltype(U::num)>{}; }
529 template<typename>
530 static constexpr std::false_type test(...) { return std::false_type{}; }
531
532 using type = decltype(test<T>(0));
533 };
534 }
535
541 template<class T>
542 struct has_num : units::detail::has_num_impl<T>::type {};
543
544 namespace detail
545 {
547 template<class T>
548 struct has_den_impl
549 {
550 template<class U>
551 static constexpr auto test(U*)->std::is_integral<decltype(U::den)> { return std::is_integral<decltype(U::den)>{}; }
552 template<typename>
553 static constexpr std::false_type test(...) { return std::false_type{}; }
554
555 using type = decltype(test<T>(0));
556 };
557 }
558
564 template<class T>
565 struct has_den : units::detail::has_den_impl<T>::type {};
566 // END DOXYGEN IGNORE
568
569 namespace traits
570 {
576 template<class T>
577 struct is_ratio : std::integral_constant<bool,
578 has_num<T>::value &&
579 has_den<T>::value>
580 {};
581 }
582
583 //------------------------------
584 // UNIT TRAITS
585 //------------------------------
586 // DOXYGEN IGNORE
592 template<class ...>
593 struct void_t { typedef void type; };
594
598 template<bool...> struct bool_pack {};
599
603 template<bool... Args>
604 struct all_true : std::is_same<units::bool_pack<true, Args...>, units::bool_pack<Args..., true>> {}; // DOXYGEN IGNORE
606
610 namespace traits
611 {
612#ifdef FOR_DOXYGEN_PURPOSES_ONLY
620 template<class T>
621 struct unit_traits
622 {
623 typedef typename T::base_unit_type base_unit_type;
624 typedef typename T::conversion_ratio conversion_ratio;
625 typedef typename T::pi_exponent_ratio pi_exponent_ratio;
626 typedef typename T::translation_ratio translation_ratio;
627 };
628#endif // DOXYGEN IGNORE
633 template<class T, typename = void>
634 struct unit_traits
635 {
636 typedef void base_unit_type;
637 typedef void conversion_ratio;
638 typedef void pi_exponent_ratio;
639 typedef void translation_ratio;
640 };
641
642 template<class T>
643 struct unit_traits
644 <T, typename void_t<
645 typename T::base_unit_type,
646 typename T::conversion_ratio,
647 typename T::pi_exponent_ratio,
648 typename T::translation_ratio>::type>
649 {
650 typedef typename T::base_unit_type base_unit_type;
651 typedef typename T::conversion_ratio conversion_ratio;
652 typedef typename T::pi_exponent_ratio pi_exponent_ratio;
653 typedef typename T::translation_ratio translation_ratio;
654 }; // END DOXYGEN IGNORE
656 }
657 // DOXYGEN IGNORE
659 namespace detail
660 {
665 struct _base_unit_t {};
666 } // END DOXYGEN IGNORE
668
669 namespace traits
670 {
677 template<class T>
678 struct is_base_unit : std::is_base_of<units::detail::_base_unit_t, T> {};
679 }
680 // DOXYGEN IGNORE
682 namespace detail
683 {
688 struct _unit {};
689
690 template<std::intmax_t Num, std::intmax_t Den = 1>
691 using meter_ratio = std::ratio<Num, Den>;
692 } // END DOXYGEN IGNORE
694
695 namespace traits
696 {
703 template<class T>
704 struct is_unit : std::is_base_of<units::detail::_unit, T>::type {};
705 }
706 // end of TypeTraits
708
709 //------------------------------
710 // BASE UNIT CLASS
711 //------------------------------
712
731 template<class Meter = detail::meter_ratio<0>,
732 class Kilogram = std::ratio<0>,
733 class Second = std::ratio<0>,
734 class Radian = std::ratio<0>,
735 class Ampere = std::ratio<0>,
736 class Kelvin = std::ratio<0>,
737 class Mole = std::ratio<0>,
738 class Candela = std::ratio<0>,
739 class Byte = std::ratio<0>>
740 struct base_unit : units::detail::_base_unit_t
741 {
742 static_assert(traits::is_ratio<Meter>::value, "Template parameter `Meter` must be a `std::ratio` representing the exponent of meters the unit has");
743 static_assert(traits::is_ratio<Kilogram>::value, "Template parameter `Kilogram` must be a `std::ratio` representing the exponent of kilograms the unit has");
744 static_assert(traits::is_ratio<Second>::value, "Template parameter `Second` must be a `std::ratio` representing the exponent of seconds the unit has");
745 static_assert(traits::is_ratio<Ampere>::value, "Template parameter `Ampere` must be a `std::ratio` representing the exponent of amperes the unit has");
746 static_assert(traits::is_ratio<Kelvin>::value, "Template parameter `Kelvin` must be a `std::ratio` representing the exponent of kelvin the unit has");
747 static_assert(traits::is_ratio<Candela>::value, "Template parameter `Candela` must be a `std::ratio` representing the exponent of candelas the unit has");
748 static_assert(traits::is_ratio<Mole>::value, "Template parameter `Mole` must be a `std::ratio` representing the exponent of moles the unit has");
749 static_assert(traits::is_ratio<Radian>::value, "Template parameter `Radian` must be a `std::ratio` representing the exponent of radians the unit has");
750 static_assert(traits::is_ratio<Byte>::value, "Template parameter `Byte` must be a `std::ratio` representing the exponent of bytes the unit has");
751
752 typedef Meter meter_ratio;
753 typedef Kilogram kilogram_ratio;
754 typedef Second second_ratio;
755 typedef Radian radian_ratio;
756 typedef Ampere ampere_ratio;
757 typedef Kelvin kelvin_ratio;
758 typedef Mole mole_ratio;
759 typedef Candela candela_ratio;
760 typedef Byte byte_ratio;
761 };
762
763 //------------------------------
764 // UNIT CATEGORIES
765 //------------------------------
766
771 namespace category
772 {
773 // SCALAR (DIMENSIONLESS) TYPES
776
777 // SI BASE UNIT TYPES
778 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
781 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>> time_unit;
782 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> angle_unit;
783 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> current_unit;
784 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> temperature_unit;
785 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> substance_unit;
786 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> luminous_intensity_unit;
787
788 // SI DERIVED UNIT TYPES
789 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
790 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>> solid_angle_unit;
791 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> frequency_unit;
792 typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-1>> velocity_unit;
793 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>, std::ratio<1>> angular_velocity_unit;
794 typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-2>> acceleration_unit;
795 typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-3>> jerk_unit;
796 typedef base_unit<detail::meter_ratio<1>, std::ratio<1>, std::ratio<-2>> force_unit;
797 typedef base_unit<detail::meter_ratio<-1>, std::ratio<1>, std::ratio<-2>> pressure_unit;
798 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<1>> charge_unit;
799 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> energy_unit;
800 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>> power_unit;
801 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-1>> voltage_unit;
802 typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<4>, std::ratio<0>, std::ratio<2>> capacitance_unit;
803 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-2>> impedance_unit;
804 typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<3>, std::ratio<0>, std::ratio<2>> conductance_unit;
805 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_flux_unit;
806 typedef base_unit<detail::meter_ratio<0>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_field_strength_unit;
807 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-2>> inductance_unit;
808 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> luminous_flux_unit;
809 typedef base_unit<detail::meter_ratio<-2>, std::ratio<0>, std::ratio<0>, std::ratio<2>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> illuminance_unit;
810 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> radioactivity_unit;
811
812 // OTHER UNIT TYPES
813 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
814 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> torque_unit;
817 typedef base_unit<detail::meter_ratio<-3>, std::ratio<1>> density_unit;
819 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> data_unit;
820 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> data_transfer_rate_unit;
821 }
822
823 //------------------------------
824 // UNIT CLASSES
825 //------------------------------
826 // DOXYGEN IGNORE
831 template <class, class, class, class> struct unit;
832 template<class Conversion, class... Exponents, class PiExponent, class Translation>
833 struct unit<Conversion, base_unit<Exponents...>, PiExponent, Translation> : units::detail::_unit
834 {
835 static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
836 static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
837 static_assert(traits::is_ratio<Translation>::value, "Template parameter `Translation` must be a `std::ratio` representing an additive translation required by the unit conversion.");
838
839 typedef typename units::base_unit<Exponents...> base_unit_type;
840 typedef Conversion conversion_ratio;
841 typedef Translation translation_ratio;
842 typedef PiExponent pi_exponent_ratio;
843 }; // END DOXYGEN IGNORE
845
865 template<class Conversion, class BaseUnit, class PiExponent = std::ratio<0>, class Translation = std::ratio<0>>
866 struct unit : units::detail::_unit
867 {
868 static_assert(traits::is_unit<BaseUnit>::value, "Template parameter `BaseUnit` must be a `unit` type.");
869 static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
870 static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
871
872 typedef typename units::traits::unit_traits<BaseUnit>::base_unit_type base_unit_type;
873 typedef typename std::ratio_multiply<typename BaseUnit::conversion_ratio, Conversion> conversion_ratio;
874 typedef typename std::ratio_add<typename BaseUnit::pi_exponent_ratio, PiExponent> pi_exponent_ratio;
875 typedef typename std::ratio_add<std::ratio_multiply<typename BaseUnit::conversion_ratio, Translation>, typename BaseUnit::translation_ratio> translation_ratio;
876 };
877
878 //------------------------------
879 // BASE UNIT MANIPULATORS
880 //------------------------------
881 // DOXYGEN IGNORE
883 namespace detail
884 {
890 template<class> struct base_unit_of_impl;
891 template<class Conversion, class BaseUnit, class PiExponent, class Translation>
892 struct base_unit_of_impl<unit<Conversion, BaseUnit, PiExponent, Translation>> : base_unit_of_impl<BaseUnit> {};
893 template<class... Exponents>
894 struct base_unit_of_impl<base_unit<Exponents...>>
895 {
896 typedef base_unit<Exponents...> type;
897 };
898 template<>
899 struct base_unit_of_impl<void>
900 {
901 typedef void type;
902 };
903 } // END DOXYGEN IGNORE
905
906 namespace traits
907 {
914 template<class U>
915 using base_unit_of = typename units::detail::base_unit_of_impl<U>::type;
916 }
917 // DOXYGEN IGNORE
919 namespace detail
920 {
926 template<class, class> struct base_unit_multiply_impl;
927 template<class... Exponents1, class... Exponents2>
928 struct base_unit_multiply_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
930 };
931
935 template<class U1, class U2>
936 using base_unit_multiply = typename base_unit_multiply_impl<U1, U2>::type;
937
943 template<class, class> struct base_unit_divide_impl;
944 template<class... Exponents1, class... Exponents2>
945 struct base_unit_divide_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
946 using type = base_unit<std::ratio_subtract<Exponents1, Exponents2>...>;
947 };
948
952 template<class U1, class U2>
953 using base_unit_divide = typename base_unit_divide_impl<U1, U2>::type;
954
960 template<class> struct inverse_base_impl;
961
962 template<class... Exponents>
963 struct inverse_base_impl<base_unit<Exponents...>> {
964 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<-1>>...>;
965 };
966
971 template<class U> using inverse_base = typename inverse_base_impl<U>::type;
972
978 template<class U> struct squared_base_impl;
979 template<class... Exponents>
980 struct squared_base_impl<base_unit<Exponents...>> {
981 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<2>>...>;
982 };
983
988 template<class U> using squared_base = typename squared_base_impl<U>::type;
989
995 template<class U> struct cubed_base_impl;
996 template<class... Exponents>
997 struct cubed_base_impl<base_unit<Exponents...>> {
998 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<3>>...>;
999 };
1000
1005 template<class U> using cubed_base = typename cubed_base_impl<U>::type;
1006
1012 template<class U> struct sqrt_base_impl;
1013 template<class... Exponents>
1014 struct sqrt_base_impl<base_unit<Exponents...>> {
1015 using type = base_unit<std::ratio_divide<Exponents, std::ratio<2>>...>;
1016 };
1017
1022 template<class U> using sqrt_base = typename sqrt_base_impl<U>::type;
1023
1029 template<class U> struct cbrt_base_impl;
1030 template<class... Exponents>
1031 struct cbrt_base_impl<base_unit<Exponents...>> {
1032 using type = base_unit<std::ratio_divide<Exponents, std::ratio<3>>...>;
1033 };
1034
1039 template<class U> using cbrt_base = typename cbrt_base_impl<U>::type;
1040 } // END DOXYGEN IGNORE
1042
1043 //------------------------------
1044 // UNIT MANIPULATORS
1045 //------------------------------
1046 // DOXYGEN IGNORE
1048 namespace detail
1049 {
1056 template<class Unit1, class Unit2>
1057 struct unit_multiply_impl
1058 {
1059 using type = unit < std::ratio_multiply<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1060 base_unit_multiply <traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1061 std::ratio_add<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1062 std::ratio < 0 >> ;
1063 };
1064
1069 template<class U1, class U2>
1070 using unit_multiply = typename unit_multiply_impl<U1, U2>::type;
1071
1078 template<class Unit1, class Unit2>
1079 struct unit_divide_impl
1080 {
1081 using type = unit < std::ratio_divide<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1082 base_unit_divide<traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1083 std::ratio_subtract<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1084 std::ratio < 0 >> ;
1085 };
1086
1091 template<class U1, class U2>
1092 using unit_divide = typename unit_divide_impl<U1, U2>::type;
1093
1100 template<class Unit>
1101 struct inverse_impl
1102 {
1103 using type = unit < std::ratio<Unit::conversion_ratio::den, Unit::conversion_ratio::num>,
1104 inverse_base<traits::base_unit_of<typename units::traits::unit_traits<Unit>::base_unit_type>>,
1105 std::ratio_multiply<typename units::traits::unit_traits<Unit>::pi_exponent_ratio, std::ratio<-1>>,
1106 std::ratio < 0 >> ; // inverses are rates or change, the translation factor goes away.
1107 };
1108 } // END DOXYGEN IGNORE
1110
1117 template<class U> using inverse = typename units::detail::inverse_impl<U>::type;
1118 // DOXYGEN IGNORE
1120 namespace detail
1121 {
1127 template<class Unit>
1128 struct squared_impl
1129 {
1130 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1131 using Conversion = typename Unit::conversion_ratio;
1132 using type = unit < std::ratio_multiply<Conversion, Conversion>,
1133 squared_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1134 std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1135 typename Unit::translation_ratio
1136 > ;
1137 };
1138 } // END DOXYGEN IGNORE
1140
1147 template<class U>
1148 using squared = typename units::detail::squared_impl<U>::type;
1149 // DOXYGEN IGNORE
1151 namespace detail
1152 {
1158 template<class Unit>
1159 struct cubed_impl
1160 {
1161 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1162 using Conversion = typename Unit::conversion_ratio;
1163 using type = unit < std::ratio_multiply<Conversion, std::ratio_multiply<Conversion, Conversion>>,
1164 cubed_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1165 std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<3>>,
1166 typename Unit::translation_ratio> ;
1167 };
1168 } // END DOXYGEN IGNORE
1170
1177 template<class U>
1178 using cubed = typename units::detail::cubed_impl<U>::type;
1179 // DOXYGEN IGNORE
1181 namespace detail
1182 {
1183 //----------------------------------
1184 // RATIO_SQRT IMPLEMENTATION
1185 //----------------------------------
1186
1187 using Zero = std::ratio<0>;
1188 using One = std::ratio<1>;
1189 template <typename R> using Square = std::ratio_multiply<R, R>;
1190
1191 // Find the largest std::integer N such that Predicate<N>::value is true.
1192 template <template <std::intmax_t N> class Predicate, typename enabled = void>
1193 struct BinarySearch {
1194 template <std::intmax_t N>
1195 struct SafeDouble_ {
1196 static constexpr const std::intmax_t value = 2 * N;
1197 static_assert(value > 0, "Overflows when computing 2 * N");
1198 };
1199
1200 template <intmax_t Lower, intmax_t Upper, typename Condition1 = void, typename Condition2 = void>
1201 struct DoubleSidedSearch_ : DoubleSidedSearch_<Lower, Upper,
1202 std::integral_constant<bool, (Upper - Lower == 1)>,
1203 std::integral_constant<bool, ((Upper - Lower>1 && Predicate<Lower + (Upper - Lower) / 2>::value))>> {};
1204
1205 template <intmax_t Lower, intmax_t Upper>
1206 struct DoubleSidedSearch_<Lower, Upper, std::false_type, std::false_type> : DoubleSidedSearch_<Lower, Lower + (Upper - Lower) / 2> {};
1207
1208 template <intmax_t Lower, intmax_t Upper, typename Condition2>
1209 struct DoubleSidedSearch_<Lower, Upper, std::true_type, Condition2> : std::integral_constant<intmax_t, Lower>{};
1210
1211 template <intmax_t Lower, intmax_t Upper, typename Condition1>
1212 struct DoubleSidedSearch_<Lower, Upper, Condition1, std::true_type> : DoubleSidedSearch_<Lower + (Upper - Lower) / 2, Upper>{};
1213
1214 template <std::intmax_t Lower, class enabled1 = void>
1215 struct SingleSidedSearch_ : SingleSidedSearch_<Lower, std::integral_constant<bool, Predicate<SafeDouble_<Lower>::value>::value>>{};
1216
1217 template <std::intmax_t Lower>
1218 struct SingleSidedSearch_<Lower, std::false_type> : DoubleSidedSearch_<Lower, SafeDouble_<Lower>::value> {};
1219
1220 template <std::intmax_t Lower>
1221 struct SingleSidedSearch_<Lower, std::true_type> : SingleSidedSearch_<SafeDouble_<Lower>::value>{};
1222
1223 static constexpr const std::intmax_t value = SingleSidedSearch_<1>::value;
1224 };
1225
1226 template <template <std::intmax_t N> class Predicate>
1227 struct BinarySearch<Predicate, std::enable_if_t<!Predicate<1>::value>> : std::integral_constant<std::intmax_t, 0>{};
1228
1229 // Find largest std::integer N such that N<=sqrt(R)
1230 template <typename R>
1231 struct Integer {
1232 template <std::intmax_t N> using Predicate_ = std::ratio_less_equal<std::ratio<N>, std::ratio_divide<R, std::ratio<N>>>;
1233 static constexpr const std::intmax_t value = BinarySearch<Predicate_>::value;
1234 };
1235
1236 template <typename R>
1237 struct IsPerfectSquare {
1238 static constexpr const std::intmax_t DenSqrt_ = Integer<std::ratio<R::den>>::value;
1239 static constexpr const std::intmax_t NumSqrt_ = Integer<std::ratio<R::num>>::value;
1240 static constexpr const bool value =( DenSqrt_ * DenSqrt_ == R::den && NumSqrt_ * NumSqrt_ == R::num);
1241 using Sqrt = std::ratio<NumSqrt_, DenSqrt_>;
1242 };
1243
1244 // Represents sqrt(P)-Q.
1245 template <typename Tp, typename Tq>
1246 struct Remainder {
1247 using P = Tp;
1248 using Q = Tq;
1249 };
1250
1251 // Represents 1/R = I + Rem where R is a Remainder.
1252 template <typename R>
1253 struct Reciprocal {
1254 using P_ = typename R::P;
1255 using Q_ = typename R::Q;
1256 using Den_ = std::ratio_subtract<P_, Square<Q_>>;
1257 using A_ = std::ratio_divide<Q_, Den_>;
1258 using B_ = std::ratio_divide<P_, Square<Den_>>;
1259 static constexpr const std::intmax_t I_ = (A_::num + Integer<std::ratio_multiply<B_, Square<std::ratio<A_::den>>>>::value) / A_::den;
1260 using I = std::ratio<I_>;
1261 using Rem = Remainder<B_, std::ratio_subtract<I, A_>>;
1262 };
1263
1264 // Expands sqrt(R) to continued fraction:
1265 // f(x)=C1+1/(C2+1/(C3+1/(...+1/(Cn+x)))) = (U*x+V)/(W*x+1) and sqrt(R)=f(Rem).
1266 // The error |f(Rem)-V| = |(U-W*V)x/(W*x+1)| <= |U-W*V|*Rem <= |U-W*V|/I' where
1267 // I' is the std::integer part of reciprocal of Rem.
1268 template <typename Tr, std::intmax_t N>
1269 struct ContinuedFraction {
1270 template <typename T>
1271 using Abs_ = std::conditional_t<std::ratio_less<T, Zero>::value, std::ratio_subtract<Zero, T>, T>;
1272
1273 using R = Tr;
1274 using Last_ = ContinuedFraction<R, N - 1>;
1275 using Reciprocal_ = Reciprocal<typename Last_::Rem>;
1276 using Rem = typename Reciprocal_::Rem;
1277 using I_ = typename Reciprocal_::I;
1278 using Den_ = std::ratio_add<typename Last_::W, I_>;
1279 using U = std::ratio_divide<typename Last_::V, Den_>;
1280 using V = std::ratio_divide<std::ratio_add<typename Last_::U, std::ratio_multiply<typename Last_::V, I_>>, Den_>;
1281 using W = std::ratio_divide<One, Den_>;
1282 using Error = Abs_<std::ratio_divide<std::ratio_subtract<U, std::ratio_multiply<V, W>>, typename Reciprocal<Rem>::I>>;
1283 };
1284
1285 template <typename Tr>
1286 struct ContinuedFraction<Tr, 1> {
1287 using R = Tr;
1288 using U = One;
1289 using V = std::ratio<Integer<R>::value>;
1290 using W = Zero;
1291 using Rem = Remainder<R, V>;
1292 using Error = std::ratio_divide<One, typename Reciprocal<Rem>::I>;
1293 };
1294
1295 template <typename R, typename Eps, std::intmax_t N = 1, typename enabled = void>
1296 struct Sqrt_ : Sqrt_<R, Eps, N + 1> {};
1297
1298 template <typename R, typename Eps, std::intmax_t N>
1299 struct Sqrt_<R, Eps, N, std::enable_if_t<std::ratio_less_equal<typename ContinuedFraction<R, N>::Error, Eps>::value>> {
1300 using type = typename ContinuedFraction<R, N>::V;
1301 };
1302
1303 template <typename R, typename Eps, typename enabled = void>
1304 struct Sqrt {
1305 static_assert(std::ratio_greater_equal<R, Zero>::value, "R can't be negative");
1306 };
1307
1308 template <typename R, typename Eps>
1309 struct Sqrt<R, Eps, std::enable_if_t<std::ratio_greater_equal<R, Zero>::value && IsPerfectSquare<R>::value>> {
1310 using type = typename IsPerfectSquare<R>::Sqrt;
1311 };
1312
1313 template <typename R, typename Eps>
1314 struct Sqrt<R, Eps, std::enable_if_t<(std::ratio_greater_equal<R, Zero>::value && !IsPerfectSquare<R>::value)>> : Sqrt_<R, Eps>{};
1315 } // END DOXYGEN IGNORE
1317
1338 template<typename Ratio, std::intmax_t Eps = 10000000000>
1339 using ratio_sqrt = typename units::detail::Sqrt<Ratio, std::ratio<1, Eps>>::type;
1340 // DOXYGEN IGNORE
1342 namespace detail
1343 {
1349 template<class Unit, std::intmax_t Eps>
1350 struct sqrt_impl
1351 {
1352 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1353 using Conversion = typename Unit::conversion_ratio;
1354 using type = unit <ratio_sqrt<Conversion, Eps>,
1355 sqrt_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1356 std::ratio_divide<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1357 typename Unit::translation_ratio>;
1358 };
1359 } // END DOXYGEN IGNORE
1361
1383 template<class U, std::intmax_t Eps = 10000000000>
1384 using square_root = typename units::detail::sqrt_impl<U, Eps>::type;
1385
1386 //------------------------------
1387 // COMPOUND UNITS
1388 //------------------------------
1389 // DOXYGEN IGNORE
1391 namespace detail
1392 {
1398 template<class U, class... Us> struct compound_impl;
1399 template<class U> struct compound_impl<U> { using type = U; };
1400 template<class U1, class U2, class...Us>
1401 struct compound_impl<U1, U2, Us...>
1402 : compound_impl<unit_multiply<U1, U2>, Us...> {};
1403 } // END DOXYGEN IGNORE
1405
1416 template<class U, class... Us>
1417 using compound_unit = typename units::detail::compound_impl<U, Us...>::type;
1418
1419 //------------------------------
1420 // PREFIXES
1421 //------------------------------
1422 // DOXYGEN IGNORE
1424 namespace detail
1425 {
1430 template<class Ratio, class Unit>
1431 struct prefix
1432 {
1433 static_assert(traits::is_ratio<Ratio>::value, "Template parameter `Ratio` must be a `std::ratio`.");
1434 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1435 typedef typename units::unit<Ratio, Unit> type;
1436 };
1437
1439 template <int N, class U>
1440 struct power_of_ratio
1441 {
1442 typedef std::ratio_multiply<U, typename power_of_ratio<N - 1, U>::type> type;
1443 };
1444
1446 template <class U>
1447 struct power_of_ratio<1, U>
1448 {
1449 typedef U type;
1450 };
1451 } // END DOXYGEN IGNORE
1453
1460 template<class U> using atto = typename units::detail::prefix<std::atto, U>::type;
1461 template<class U> using femto = typename units::detail::prefix<std::femto,U>::type;
1462 template<class U> using pico = typename units::detail::prefix<std::pico, U>::type;
1463 template<class U> using nano = typename units::detail::prefix<std::nano, U>::type;
1464 template<class U> using micro = typename units::detail::prefix<std::micro,U>::type;
1465 template<class U> using milli = typename units::detail::prefix<std::milli,U>::type;
1466 template<class U> using centi = typename units::detail::prefix<std::centi,U>::type;
1467 template<class U> using deci = typename units::detail::prefix<std::deci, U>::type;
1468 template<class U> using deca = typename units::detail::prefix<std::deca, U>::type;
1469 template<class U> using hecto = typename units::detail::prefix<std::hecto,U>::type;
1470 template<class U> using kilo = typename units::detail::prefix<std::kilo, U>::type;
1471 template<class U> using mega = typename units::detail::prefix<std::mega, U>::type;
1472 template<class U> using giga = typename units::detail::prefix<std::giga, U>::type;
1473 template<class U> using tera = typename units::detail::prefix<std::tera, U>::type;
1474 template<class U> using peta = typename units::detail::prefix<std::peta, U>::type;
1475 template<class U> using exa = typename units::detail::prefix<std::exa, U>::type;
1477
1484 template<class U> using kibi = typename units::detail::prefix<std::ratio<1024>, U>::type;
1485 template<class U> using mebi = typename units::detail::prefix<std::ratio<1048576>, U>::type;
1486 template<class U> using gibi = typename units::detail::prefix<std::ratio<1073741824>, U>::type;
1487 template<class U> using tebi = typename units::detail::prefix<std::ratio<1099511627776>, U>::type;
1488 template<class U> using pebi = typename units::detail::prefix<std::ratio<1125899906842624>, U>::type;
1489 template<class U> using exbi = typename units::detail::prefix<std::ratio<1152921504606846976>, U>::type;
1491
1492 //------------------------------
1493 // CONVERSION TRAITS
1494 //------------------------------
1495
1496 namespace traits
1497 {
1510 template<class U1, class U2>
1511 struct is_convertible_unit : std::is_same <traits::base_unit_of<typename units::traits::unit_traits<U1>::base_unit_type>,
1512 base_unit_of<typename units::traits::unit_traits<U2>::base_unit_type >> {};
1513 }
1514
1515 //------------------------------
1516 // CONVERSION FUNCTION
1517 //------------------------------
1518 // DOXYGEN IGNORE
1520 namespace detail
1521 {
1522 constexpr inline UNIT_LIB_DEFAULT_TYPE pow(UNIT_LIB_DEFAULT_TYPE x, unsigned long long y)
1523 {
1524 return y == 0 ? 1.0 : x * pow(x, y - 1);
1525 }
1526
1527 constexpr inline UNIT_LIB_DEFAULT_TYPE abs(UNIT_LIB_DEFAULT_TYPE x)
1528 {
1529 return x < 0 ? -x : x;
1530 }
1531
1533 template<class Ratio, class PiRatio, class Translation, bool piRequired, bool translationRequired, typename T>
1534 static inline constexpr T convert(const T& value, std::true_type, std::integral_constant<bool, piRequired>, std::integral_constant<bool, translationRequired>) noexcept
1535 {
1536 return value;
1537 }
1538
1539 template<std::intmax_t Ratio_num, std::intmax_t Ratio_den>
1540 struct normal_convert
1541 {
1542 template<typename T>
1543 inline constexpr T operator()(const T& value) const noexcept
1544 {
1545 return value * Ratio_num / Ratio_den;
1546 }
1547 };
1548
1549 template<std::intmax_t Ratio_num>
1550 struct normal_convert<Ratio_num, 1>
1551 {
1552 template<typename T>
1553 inline constexpr T operator()(const T& value) const noexcept
1554 {
1555 return value * Ratio_num;
1556 }
1557 };
1558
1559 template<std::intmax_t Ratio_den>
1560 struct normal_convert<1, Ratio_den>
1561 {
1562 template<typename T>
1563 inline constexpr T operator()(const T& value) const noexcept
1564 {
1565 return value / Ratio_den;
1566 }
1567 };
1568
1569 template<>
1570 struct normal_convert<1, 1>
1571 {
1572 template<typename T>
1573 inline constexpr T operator()(const T& value) const noexcept
1574 {
1575 return value;
1576 }
1577 };
1578
1580 template<class Ratio, class PiRatio, class Translation, typename T>
1581 static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::false_type) noexcept
1582 {
1583 return normal_convert<Ratio::num, Ratio::den>{}(value);
1584 }
1585
1587 // constepxr with PI in numerator
1588 template<class Ratio, class PiRatio, class Translation, typename T>
1589 static inline constexpr
1590 std::enable_if_t<(PiRatio::num / PiRatio::den >= 1 && PiRatio::num % PiRatio::den == 0), T>
1591 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1592 {
1593 return normal_convert<Ratio::num, Ratio::den>{}(value) * pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den);
1594 }
1595
1597 // constexpr with PI in denominator
1598 template<class Ratio, class PiRatio, class Translation, typename T>
1599 static inline constexpr
1600 std::enable_if_t<(PiRatio::num / PiRatio::den <= -1 && PiRatio::num % PiRatio::den == 0), T>
1601 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1602 {
1603 return normal_convert<Ratio::num, Ratio::den>{}(value) / pow(constants::detail::PI_VAL, -PiRatio::num / PiRatio::den);
1604 }
1605
1607 // Not constexpr - uses std::pow
1608 template<class Ratio, class PiRatio, class Translation, typename T>
1609 static inline // sorry, this can't be constexpr!
1610 std::enable_if_t<(PiRatio::num / PiRatio::den < 1 && PiRatio::num / PiRatio::den > -1), T>
1611 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1612 {
1613 return normal_convert<Ratio::num, Ratio::den>{}(value) * std::pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den);
1614 }
1615
1617 template<class Ratio, class PiRatio, class Translation, typename T>
1618 static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::true_type) noexcept
1619 {
1620 return normal_convert<Ratio::num, Ratio::den>{}(value) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1621 }
1622
1624 template<class Ratio, class PiRatio, class Translation, typename T>
1625 static inline constexpr T convert(const T& value, std::false_type isSame, std::true_type piRequired, std::true_type) noexcept
1626 {
1627 return convert<Ratio, PiRatio, Translation>(value, isSame, piRequired, std::false_type()) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1628 }
1629 } // END DOXYGEN IGNORE
1631
1647 template<class UnitFrom, class UnitTo, typename T = UNIT_LIB_DEFAULT_TYPE>
1648 static inline constexpr T convert(const T& value) noexcept
1649 {
1650 static_assert(traits::is_unit<UnitFrom>::value, "Template parameter `UnitFrom` must be a `unit` type.");
1651 static_assert(traits::is_unit<UnitTo>::value, "Template parameter `UnitTo` must be a `unit` type.");
1652 static_assert(traits::is_convertible_unit<UnitFrom, UnitTo>::value, "Units are not compatible.");
1653
1654 using Ratio = std::ratio_divide<typename UnitFrom::conversion_ratio, typename UnitTo::conversion_ratio>;
1655 using PiRatio = std::ratio_subtract<typename UnitFrom::pi_exponent_ratio, typename UnitTo::pi_exponent_ratio>;
1656 using Translation = std::ratio_divide<std::ratio_subtract<typename UnitFrom::translation_ratio, typename UnitTo::translation_ratio>, typename UnitTo::conversion_ratio>;
1657
1658 using isSame = typename std::is_same<std::decay_t<UnitFrom>, std::decay_t<UnitTo>>::type;
1659 using piRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, PiRatio>::value)>;
1660 using translationRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, Translation>::value)>;
1661
1662 return units::detail::convert<Ratio, PiRatio, Translation>
1663 (value, isSame{}, piRequired{}, translationRequired{});
1664 }
1665
1666 //----------------------------------
1667 // NON-LINEAR SCALE TRAITS
1668 //----------------------------------
1669 // DOXYGEN IGNORE
1671 namespace traits
1672 {
1673 namespace detail
1674 {
1679 template<class T, class Ret>
1680 struct has_operator_parenthesis_impl
1681 {
1682 template<class U>
1683 static constexpr auto test(U*) -> decltype(std::declval<U>()()) { return decltype(std::declval<U>()()){}; }
1684 template<typename>
1685 static constexpr std::false_type test(...) { return std::false_type{}; }
1686
1687 using type = typename std::is_same<Ret, decltype(test<T>(0))>::type;
1688 };
1689 }
1690
1695 template<class T, class Ret>
1696 struct has_operator_parenthesis : traits::detail::has_operator_parenthesis_impl<T, Ret>::type {};
1697 }
1698
1699 namespace traits
1700 {
1701 namespace detail
1702 {
1707 template<class T, class Ret>
1708 struct has_value_member_impl
1709 {
1710 template<class U>
1711 static constexpr auto test(U* p) -> decltype(p->m_value) { return p->m_value; }
1712 template<typename>
1713 static constexpr auto test(...)->std::false_type { return std::false_type{}; }
1714
1715 using type = typename std::is_same<std::decay_t<Ret>, std::decay_t<decltype(test<T>(0))>>::type;
1716 };
1717 }
1718
1723 template<class T, class Ret>
1724 struct has_value_member : traits::detail::has_value_member_impl<T, Ret>::type {};
1725 } // END DOXYGEN IGNORE
1727
1728 namespace traits
1729 {
1741 template<class T, class Ret>
1742 struct is_nonlinear_scale : std::integral_constant<bool,
1743 std::is_default_constructible<T>::value &&
1744 has_operator_parenthesis<T, Ret>::value &&
1745 has_value_member<T, Ret>::value &&
1746 std::is_trivial<T>::value>
1747 {};
1748 }
1749
1750 //------------------------------
1751 // UNIT_T TYPE TRAITS
1752 //------------------------------
1753
1754 namespace traits
1755 {
1756#ifdef FOR_DOXYGEN_PURPOSOES_ONLY
1763 template<typename T>
1764 struct unit_t_traits
1765 {
1766 typedef typename T::non_linear_scale_type non_linear_scale_type;
1767 typedef typename T::underlying_type underlying_type;
1768 typedef typename T::value_type value_type;
1769 typedef typename T::unit_type unit_type;
1770 };
1771#endif
1772 // DOXYGEN IGNORE
1778 template<typename T, typename = void>
1779 struct unit_t_traits
1780 {
1781 typedef void non_linear_scale_type;
1782 typedef void underlying_type;
1783 typedef void value_type;
1784 typedef void unit_type;
1785 };
1786
1792 template<typename T>
1793 struct unit_t_traits <T, typename void_t<
1794 typename T::non_linear_scale_type,
1795 typename T::underlying_type,
1796 typename T::value_type,
1797 typename T::unit_type>::type>
1798 {
1799 typedef typename T::non_linear_scale_type non_linear_scale_type;
1800 typedef typename T::underlying_type underlying_type;
1801 typedef typename T::value_type value_type;
1802 typedef typename T::unit_type unit_type;
1803 }; // END DOXYGEN IGNORE
1805 }
1806
1807 namespace traits
1808 {
1821 template<class U1, class U2>
1822 struct is_convertible_unit_t : std::integral_constant<bool,
1823 is_convertible_unit<typename units::traits::unit_t_traits<U1>::unit_type, typename units::traits::unit_t_traits<U2>::unit_type>::value>
1824 {};
1825 }
1826
1827 //----------------------------------
1828 // UNIT TYPE
1829 //----------------------------------
1830 // DOXYGEN IGNORE
1832 // forward declaration
1833 template<typename T> struct linear_scale;
1834 template<typename T> struct decibel_scale;
1835
1836 namespace detail
1837 {
1842 struct _unit_t {};
1843 } // END DOXYGEN IGNORE
1845
1846 namespace traits
1847 {
1848 // forward declaration
1849 #if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
1850 template<typename... T> struct is_dimensionless_unit;
1851 #else
1852 template<typename T1, typename T2 = T1, typename T3 = T1> struct is_dimensionless_unit;
1853 #endif
1854
1861 template<class T>
1862 struct is_unit_t : std::is_base_of<units::detail::_unit_t, T>::type {};
1863 }
1864
1921 template<class Units, typename T = UNIT_LIB_DEFAULT_TYPE, template<typename> class NonLinearScale = linear_scale>
1922 class unit_t : public NonLinearScale<T>, units::detail::_unit_t
1923 {
1924 static_assert(traits::is_unit<Units>::value, "Template parameter `Units` must be a unit tag. Check that you aren't using a unit type (_t).");
1925 static_assert(traits::is_nonlinear_scale<NonLinearScale<T>, T>::value, "Template parameter `NonLinearScale` does not conform to the `is_nonlinear_scale` concept.");
1926
1927 protected:
1928
1929 using nls = NonLinearScale<T>;
1930 using nls::m_value;
1931
1932 public:
1933
1934 typedef NonLinearScale<T> non_linear_scale_type;
1936 typedef T value_type;
1937 typedef Units unit_type;
1938
1943 constexpr unit_t() = default;
1944
1953 template<class... Args>
1954 inline explicit constexpr unit_t(const T value, const Args&... args) noexcept : nls(value, args...)
1955 {
1956
1957 }
1958
1964 template<class Ty, class = typename std::enable_if<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>::type>
1965 inline constexpr unit_t(const Ty value) noexcept : nls(value)
1966 {
1967
1968 }
1969
1975 template<class Rep, class Period, class = std::enable_if_t<std::is_arithmetic<Rep>::value && traits::is_ratio<Period>::value>>
1976 inline constexpr unit_t(const std::chrono::duration<Rep, Period>& value) noexcept :
1977 nls(units::convert<unit<std::ratio<1,1000000000>, category::time_unit>, Units>(static_cast<T>(std::chrono::duration_cast<std::chrono::nanoseconds>(value).count())))
1978 {
1979
1980 }
1981
1987 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1988 inline constexpr unit_t(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept :
1989 nls(units::convert<UnitsRhs, Units, T>(rhs.m_value), std::true_type() /*store linear value*/)
1990 {
1991
1992 }
1993
1999 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2000 inline unit_t& operator=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept
2001 {
2003 return *this;
2004 }
2005
2011 template<class Ty, class = std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>>
2012 inline unit_t& operator=(const Ty& rhs) noexcept
2013 {
2014 nls::m_value = rhs;
2015 return *this;
2016 }
2017
2024 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2025 inline constexpr bool operator<(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2026 {
2027 return (nls::m_value < units::convert<UnitsRhs, Units>(rhs.m_value));
2028 }
2029
2036 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2037 inline constexpr bool operator<=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2038 {
2039 return (nls::m_value <= units::convert<UnitsRhs, Units>(rhs.m_value));
2040 }
2041
2048 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2049 inline constexpr bool operator>(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2050 {
2051 return (nls::m_value > units::convert<UnitsRhs, Units>(rhs.m_value));
2052 }
2053
2060 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2061 inline constexpr bool operator>=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2062 {
2063 return (nls::m_value >= units::convert<UnitsRhs, Units>(rhs.m_value));
2064 }
2065
2073 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs, std::enable_if_t<std::is_floating_point<T>::value || std::is_floating_point<Ty>::value, int> = 0>
2074 inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2075 {
2076 return detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::epsilon() *
2077 detail::abs(nls::m_value + units::convert<UnitsRhs, Units>(rhs.m_value)) ||
2078 detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::min();
2079 }
2080
2081 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs, std::enable_if_t<std::is_integral<T>::value && std::is_integral<Ty>::value, int> = 0>
2082 inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2083 {
2084 return nls::m_value == units::convert<UnitsRhs, Units>(rhs.m_value);
2085 }
2086
2094 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2095 inline constexpr bool operator!=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2096 {
2097 return !(*this == rhs);
2098 }
2099
2104 inline constexpr underlying_type value() const noexcept
2105 {
2106 return static_cast<underlying_type>(*this);
2107 }
2108
2113 template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2114 inline constexpr Ty to() const noexcept
2115 {
2116 return static_cast<Ty>(*this);
2117 }
2118
2124 template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2125 inline constexpr Ty toLinearized() const noexcept
2126 {
2127 return static_cast<Ty>(m_value);
2128 }
2129
2139 template<class U>
2140 inline constexpr unit_t<U> convert() const noexcept
2141 {
2142 static_assert(traits::is_unit<U>::value, "Template parameter `U` must be a unit type.");
2143 return unit_t<U>(*this);
2144 }
2145
2150 template<class Ty, std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2151 inline constexpr operator Ty() const noexcept
2152 {
2153 // this conversion also resolves any PI exponents, by converting from a non-zero PI ratio to a zero-pi ratio.
2154 return static_cast<Ty>(units::convert<Units, unit<std::ratio<1>, units::category::scalar_unit>>((*this)()));
2155 }
2156
2161 template<class Ty, std::enable_if_t<!traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2162 inline constexpr explicit operator Ty() const noexcept
2163 {
2164 return static_cast<Ty>((*this)());
2165 }
2166
2171 template<typename U = Units, std::enable_if_t<units::traits::is_convertible_unit<U, unit<std::ratio<1>, category::time_unit>>::value, int> = 0>
2172 inline constexpr operator std::chrono::nanoseconds() const noexcept
2173 {
2174 return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double, std::nano>(units::convert<Units, unit<std::ratio<1,1000000000>, category::time_unit>>((*this)())));
2175 }
2176
2180 inline constexpr const char* name() const noexcept
2181 {
2182 return units::name(*this);
2183 }
2184
2188 inline constexpr const char* abbreviation() const noexcept
2189 {
2190 return units::abbreviation(*this);
2191 }
2192
2193 public:
2194
2195 template<class U, typename Ty, template<typename> class Nlt>
2196 friend class unit_t;
2197 };
2198
2199 //------------------------------
2200 // UNIT_T NON-MEMBER FUNCTIONS
2201 //------------------------------
2202
2213 template<class UnitType, typename T, class = std::enable_if_t<std::is_arithmetic<T>::value>>
2214 inline constexpr UnitType make_unit(const T value) noexcept
2215 {
2216 static_assert(traits::is_unit_t<UnitType>::value, "Template parameter `UnitType` must be a unit type (_t).");
2217
2218 return UnitType(value);
2219 }
2220
2221#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2222 template<class Units, typename T, template<typename> class NonLinearScale>
2223 inline std::ostream& operator<<(std::ostream& os, const unit_t<Units, T, NonLinearScale>& obj) noexcept
2224 {
2225 using BaseUnits = unit<std::ratio<1>, typename traits::unit_traits<Units>::base_unit_type>;
2226 os << convert<Units, BaseUnits>(obj());
2227
2228 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0) { os << " m"; }
2229 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0 &&
2230 traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::meter_ratio::num; }
2231 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::meter_ratio::den; }
2232
2233 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0) { os << " kg"; }
2234 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0 &&
2235 traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num; }
2236 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den; }
2237
2238 if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0) { os << " s"; }
2239 if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0 &&
2240 traits::unit_traits<Units>::base_unit_type::second_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::second_ratio::num; }
2241 if (traits::unit_traits<Units>::base_unit_type::second_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::second_ratio::den; }
2242
2243 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0) { os << " A"; }
2244 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0 &&
2245 traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::num; }
2246 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::den; }
2247
2248 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0) { os << " K"; }
2249 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0 &&
2250 traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num; }
2251 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den; }
2252
2253 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0) { os << " mol"; }
2254 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0 &&
2255 traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::mole_ratio::num; }
2256 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::mole_ratio::den; }
2257
2258 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0) { os << " cd"; }
2259 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0 &&
2260 traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::candela_ratio::num; }
2261 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::candela_ratio::den; }
2262
2263 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0) { os << " rad"; }
2264 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0 &&
2265 traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::radian_ratio::num; }
2266 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::radian_ratio::den; }
2267
2268 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0) { os << " b"; }
2269 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0 &&
2270 traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::byte_ratio::num; }
2271 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::byte_ratio::den; }
2272
2273 return os;
2274 }
2275#endif
2276
2277 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2278 inline constexpr unit_t<Units, T, NonLinearScale>& operator+=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2279 {
2281 (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2282 "parameters are not compatible units.");
2283
2284 lhs = lhs + rhs;
2285 return lhs;
2286 }
2287
2288 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2289 inline constexpr unit_t<Units, T, NonLinearScale>& operator-=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2290 {
2292 (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2293 "parameters are not compatible units.");
2294
2295 lhs = lhs - rhs;
2296 return lhs;
2297 }
2298
2299 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2300 inline constexpr unit_t<Units, T, NonLinearScale>& operator*=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2301 {
2302 static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2303 "right-hand side parameter must be dimensionless.");
2304
2305 lhs = lhs * rhs;
2306 return lhs;
2307 }
2308
2309 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2310 inline constexpr unit_t<Units, T, NonLinearScale>& operator/=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2311 {
2312 static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2313 "right-hand side parameter must be dimensionless.");
2314
2315 lhs = lhs / rhs;
2316 return lhs;
2317 }
2318
2319 //------------------------------
2320 // UNIT_T UNARY OPERATORS
2321 //------------------------------
2322
2323 // unary addition: +T
2324 template<class Units, typename T, template<typename> class NonLinearScale>
2325 inline constexpr unit_t<Units, T, NonLinearScale> operator+(const unit_t<Units, T, NonLinearScale>& u) noexcept
2326 {
2327 return u;
2328 }
2329
2330 // prefix increment: ++T
2331 template<class Units, typename T, template<typename> class NonLinearScale>
2332 inline constexpr unit_t<Units, T, NonLinearScale>& operator++(unit_t<Units, T, NonLinearScale>& u) noexcept
2333 {
2335 return u;
2336 }
2337
2338 // postfix increment: T++
2339 template<class Units, typename T, template<typename> class NonLinearScale>
2340 inline constexpr unit_t<Units, T, NonLinearScale> operator++(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2341 {
2342 auto ret = u;
2344 return ret;
2345 }
2346
2347 // unary addition: -T
2348 template<class Units, typename T, template<typename> class NonLinearScale>
2349 inline constexpr unit_t<Units, T, NonLinearScale> operator-(const unit_t<Units, T, NonLinearScale>& u) noexcept
2350 {
2352 }
2353
2354 // prefix increment: --T
2355 template<class Units, typename T, template<typename> class NonLinearScale>
2356 inline constexpr unit_t<Units, T, NonLinearScale>& operator--(unit_t<Units, T, NonLinearScale>& u) noexcept
2357 {
2359 return u;
2360 }
2361
2362 // postfix increment: T--
2363 template<class Units, typename T, template<typename> class NonLinearScale>
2364 inline constexpr unit_t<Units, T, NonLinearScale> operator--(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2365 {
2366 auto ret = u;
2368 return ret;
2369 }
2370
2371 //------------------------------
2372 // UNIT_CAST
2373 //------------------------------
2374
2388 template<typename T, typename Units, class = std::enable_if_t<std::is_arithmetic<T>::value && traits::is_unit_t<Units>::value>>
2389 inline constexpr T unit_cast(const Units& value) noexcept
2390 {
2391 return static_cast<T>(value);
2392 }
2393
2394 //------------------------------
2395 // NON-LINEAR SCALE TRAITS
2396 //------------------------------
2397
2398 // forward declaration
2399 template<typename T> struct decibel_scale;
2400
2401 namespace traits
2402 {
2410#if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2411 template<typename... T>
2412 struct has_linear_scale : std::integral_constant<bool, units::all_true<std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T>::underlying_type>, T>::value...>::value > {};
2413#else
2414 template<typename T1, typename T2 = T1, typename T3 = T1>
2415 struct has_linear_scale : std::integral_constant<bool,
2416 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2417 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2418 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T3>::underlying_type>, T3>::value> {};
2419#endif
2420
2428#if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2429 template<typename... T>
2430 struct has_decibel_scale : std::integral_constant<bool, units::all_true<std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T>::underlying_type>, T>::value...>::value> {};
2431#else
2432 template<typename T1, typename T2 = T1, typename T3 = T1>
2433 struct has_decibel_scale : std::integral_constant<bool,
2434 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2435 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2436 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T3>::value> {};
2437#endif
2438
2447 template<typename T1, typename T2>
2448 struct is_same_scale : std::integral_constant<bool,
2449 std::is_same<typename units::traits::unit_t_traits<T1>::non_linear_scale_type, typename units::traits::unit_t_traits<T2>::non_linear_scale_type>::value>
2450 {};
2451 }
2452
2453 //----------------------------------
2454 // NON-LINEAR SCALES
2455 //----------------------------------
2456
2457 // Non-linear transforms are used to pre and post scale units which are defined in terms of non-
2458 // linear functions of their current value. A good example of a non-linear scale would be a
2459 // logarithmic or decibel scale
2460
2461 //------------------------------
2462 // LINEAR SCALE
2463 //------------------------------
2464
2472 template<typename T>
2474 {
2475 inline constexpr linear_scale() = default;
2476 inline constexpr linear_scale(const linear_scale&) = default;
2477 inline ~linear_scale() = default;
2478 inline linear_scale& operator=(const linear_scale&) = default;
2479#if defined(_MSC_VER) && (_MSC_VER > 1800)
2480 inline constexpr linear_scale(linear_scale&&) = default;
2481 inline linear_scale& operator=(linear_scale&&) = default;
2482#endif
2483 template<class... Args>
2484 inline constexpr linear_scale(const T& value, Args&&...) noexcept : m_value(value) {}
2485 inline constexpr T operator()() const noexcept { return m_value; }
2486
2488 };
2489
2490 //----------------------------------
2491 // SCALAR (LINEAR) UNITS
2492 //----------------------------------
2493
2494 // Scalar units are the *ONLY* units implicitly convertible to/from built-in types.
2495 namespace dimensionless
2496 {
2499
2500 typedef unit_t<scalar> scalar_t;
2501 typedef scalar_t dimensionless_t;
2502 }
2503
2504// ignore the redeclaration of the default template parameters
2505#if defined(_MSC_VER)
2506# pragma warning(push)
2507# pragma warning(disable : 4348)
2508#endif
2511#if defined(_MSC_VER)
2512# pragma warning(pop)
2513#endif
2514
2515 //------------------------------
2516 // LINEAR ARITHMETIC
2517 //------------------------------
2518
2519 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<!traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2520 constexpr inline int operator+(const UnitTypeLhs& /* lhs */, const UnitTypeRhs& /* rhs */) noexcept
2521 {
2522 static_assert(traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, "Cannot add units with different linear/non-linear scales.");
2523 return 0;
2524 }
2525
2527 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2528 inline constexpr UnitTypeLhs operator+(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2529 {
2530 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2531 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2532 return UnitTypeLhs(lhs() + convert<UnitsRhs, UnitsLhs>(rhs()));
2533 }
2534
2536 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2537 inline constexpr dimensionless::scalar_t operator+(const dimensionless::scalar_t& lhs, T rhs) noexcept
2538 {
2539 return dimensionless::scalar_t(lhs() + rhs);
2540 }
2541
2543 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2544 inline constexpr dimensionless::scalar_t operator+(T lhs, const dimensionless::scalar_t& rhs) noexcept
2545 {
2546 return dimensionless::scalar_t(lhs + rhs());
2547 }
2548
2550 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2551 inline constexpr UnitTypeLhs operator-(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2552 {
2553 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2554 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2555 return UnitTypeLhs(lhs() - convert<UnitsRhs, UnitsLhs>(rhs()));
2556 }
2557
2559 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2560 inline constexpr dimensionless::scalar_t operator-(const dimensionless::scalar_t& lhs, T rhs) noexcept
2561 {
2562 return dimensionless::scalar_t(lhs() - rhs);
2563 }
2564
2566 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2567 inline constexpr dimensionless::scalar_t operator-(T lhs, const dimensionless::scalar_t& rhs) noexcept
2568 {
2569 return dimensionless::scalar_t(lhs - rhs());
2570 }
2571
2573 template<class UnitTypeLhs, class UnitTypeRhs,
2574 std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2575 inline constexpr auto operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<compound_unit<squared<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>>>
2576 {
2577 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2578 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2580 (lhs() * convert<UnitsRhs, UnitsLhs>(rhs()));
2581 }
2582
2584 template<class UnitTypeLhs, class UnitTypeRhs,
2585 std::enable_if_t<!traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2586 inline constexpr auto operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<compound_unit<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type, typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2587 {
2588 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2589 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2590 return unit_t<compound_unit<UnitsLhs, UnitsRhs>>
2591 (lhs() * rhs());
2592 }
2593
2595 template<class UnitTypeLhs, typename UnitTypeRhs,
2596 std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value && traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2597 inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2598 {
2599 // the cast makes sure factors of PI are handled as expected
2600 return UnitTypeLhs(lhs() * static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2601 }
2602
2604 template<class UnitTypeLhs, typename UnitTypeRhs,
2605 std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && traits::is_dimensionless_unit<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2606 inline constexpr UnitTypeRhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2607 {
2608 // the cast makes sure factors of PI are handled as expected
2609 return UnitTypeRhs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) * rhs());
2610 }
2611
2613 template<class UnitTypeLhs, typename T,
2614 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2615 inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, T rhs) noexcept
2616 {
2617 return UnitTypeLhs(lhs() * rhs);
2618 }
2619
2621 template<class UnitTypeRhs, typename T,
2622 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2623 inline constexpr UnitTypeRhs operator*(T lhs, const UnitTypeRhs& rhs) noexcept
2624 {
2625 return UnitTypeRhs(lhs * rhs());
2626 }
2627
2629 template<class UnitTypeLhs, class UnitTypeRhs,
2630 std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2631 inline constexpr dimensionless::scalar_t operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2632 {
2633 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2634 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2635 return dimensionless::scalar_t(lhs() / convert<UnitsRhs, UnitsLhs>(rhs()));
2636 }
2637
2639 template<class UnitTypeLhs, class UnitTypeRhs,
2640 std::enable_if_t<!traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2642 {
2643 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2644 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2646 (lhs() / rhs());
2647 }
2648
2650 template<class UnitTypeLhs, class UnitTypeRhs,
2651 std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value && traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2652 inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2653 {
2654 return UnitTypeLhs(lhs() / static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2655 }
2656
2658 template<class UnitTypeLhs, class UnitTypeRhs,
2659 std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value && traits::is_dimensionless_unit<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2660 inline constexpr auto operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2661 {
2662 return unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2663 (static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) / rhs());
2664 }
2665
2667 template<class UnitTypeLhs, typename T,
2668 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2669 inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, T rhs) noexcept
2670 {
2671 return UnitTypeLhs(lhs() / rhs);
2672 }
2673
2675 template<class UnitTypeRhs, typename T,
2676 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2677 inline constexpr auto operator/(T lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2678 {
2679 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2681 (lhs / rhs());
2682 }
2683
2684 //----------------------------------
2685 // SCALAR COMPARISONS
2686 //----------------------------------
2687
2688 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2689 constexpr bool operator==(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2690 {
2691 return detail::abs(lhs - static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs)) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::epsilon() * detail::abs(lhs + static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs)) ||
2692 detail::abs(lhs - static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs)) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2693 }
2694
2695 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2696 constexpr bool operator==(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2697 {
2698 return detail::abs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) - rhs) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::epsilon() * detail::abs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) + rhs) ||
2699 detail::abs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) - rhs) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2700 }
2701
2702 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2703 constexpr bool operator!=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2704 {
2705 return!(lhs == static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2706 }
2707
2708 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2709 constexpr bool operator!=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2710 {
2711 return !(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) == rhs);
2712 }
2713
2714 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2715 constexpr bool operator>=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2716 {
2717 return std::isgreaterequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2718 }
2719
2720 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2721 constexpr bool operator>=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2722 {
2723 return std::isgreaterequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2724 }
2725
2726 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2727 constexpr bool operator>(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2728 {
2729 return lhs > static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2730 }
2731
2732 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2733 constexpr bool operator>(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2734 {
2735 return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) > rhs;
2736 }
2737
2738 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2739 constexpr bool operator<=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2740 {
2741 return std::islessequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2742 }
2743
2744 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2745 constexpr bool operator<=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2746 {
2747 return std::islessequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2748 }
2749
2750 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2751 constexpr bool operator<(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2752 {
2753 return lhs < static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2754 }
2755
2756 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2757 constexpr bool operator<(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2758 {
2759 return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) < rhs;
2760 }
2761
2762 //----------------------------------
2763 // POW
2764 //----------------------------------
2765 // DOXYGEN IGNORE
2767 namespace detail
2768 {
2770 template <int N, class U> struct power_of_unit
2771 {
2772 template<bool isPos, int V> struct power_of_unit_impl;
2773
2774 template<int V> struct power_of_unit_impl<true, V>
2775 {
2776 typedef units::detail::unit_multiply<U, typename power_of_unit<N - 1, U>::type> type;
2777 };
2778
2779 template<int V> struct power_of_unit_impl<false, V>
2780 {
2781 typedef units::inverse<typename power_of_unit<-N, U>::type> type;
2782 };
2783
2784 typedef typename power_of_unit_impl<(N > 0), N>::type type;
2785 };
2786
2788 template <class U> struct power_of_unit<1, U>
2789 {
2790 typedef U type;
2791 };
2792 template <class U> struct power_of_unit<0, U>
2793 {
2794 typedef units::dimensionless::dimensionless type;
2795 };
2796 } // END DOXYGEN IGNORE
2798
2799 namespace math
2800 {
2808 template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2809 inline auto pow(const UnitType& value) noexcept -> unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
2810 {
2811 return unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
2812 (std::pow(value(), power));
2813 }
2814
2823 template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2824 inline constexpr auto cpow(const UnitType& value) noexcept -> unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
2825 {
2826 static_assert(power >= 0, "cpow cannot accept negative numbers. Try units::math::pow instead.");
2827 return unit_t<typename units::detail::power_of_unit<power, typename units::traits::unit_t_traits<UnitType>::unit_type>::type, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
2828 (detail::pow(value(), power));
2829 }
2830 }
2831
2832 //------------------------------
2833 // DECIBEL SCALE
2834 //------------------------------
2835
2842 template<typename T>
2843 struct decibel_scale
2844 {
2845 inline constexpr decibel_scale() = default;
2846 inline constexpr decibel_scale(const decibel_scale&) = default;
2847 inline ~decibel_scale() = default;
2848 inline decibel_scale& operator=(const decibel_scale&) = default;
2849#if defined(_MSC_VER) && (_MSC_VER > 1800)
2850 inline constexpr decibel_scale(decibel_scale&&) = default;
2851 inline decibel_scale& operator=(decibel_scale&&) = default;
2852#endif
2853 inline constexpr decibel_scale(const T value) noexcept : m_value(std::pow(10, value / 10)) {}
2854 template<class... Args>
2855 inline constexpr decibel_scale(const T value, std::true_type, Args&&...) noexcept : m_value(value) {}
2856 inline constexpr T operator()() const noexcept { return 10 * std::log10(m_value); }
2857
2859 };
2860
2861 //------------------------------
2862 // SCALAR (DECIBEL) UNITS
2863 //------------------------------
2864
2869 namespace dimensionless
2870 {
2872#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2873 inline std::ostream& operator<<(std::ostream& os, const dB_t& obj) { os << obj() << " dB"; return os; }
2874#endif
2875 typedef dB_t dBi_t;
2876 }
2877
2878 //------------------------------
2879 // DECIBEL ARITHMETIC
2880 //------------------------------
2881
2883 template<class UnitTypeLhs, class UnitTypeRhs,
2884 std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2885 constexpr inline auto operator+(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<compound_unit<squared<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>>, typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type, decibel_scale>
2886 {
2887 using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2888 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2889 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2890
2891 return unit_t<compound_unit<squared<LhsUnits>>, underlying_type, decibel_scale>
2892 (lhs.template toLinearized<underlying_type>() * convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2893 }
2894
2896 template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2897 constexpr inline UnitTypeLhs operator+(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2898 {
2899 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2900 return UnitTypeLhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2901 }
2902
2904 template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2905 constexpr inline UnitTypeRhs operator+(const dimensionless::dB_t& lhs, const UnitTypeRhs& rhs) noexcept
2906 {
2907 using underlying_type = typename units::traits::unit_t_traits<UnitTypeRhs>::underlying_type;
2908 return UnitTypeRhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2909 }
2910
2912 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2913 constexpr inline auto operator-(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<compound_unit<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type, inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>, typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type, decibel_scale>
2914 {
2915 using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2916 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2917 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2918
2920 (lhs.template toLinearized<underlying_type>() / convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2921 }
2922
2924 template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2925 constexpr inline UnitTypeLhs operator-(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2926 {
2927 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2928 return UnitTypeLhs(lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2929 }
2930
2932 template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2933 constexpr inline auto operator-(const dimensionless::dB_t& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>, typename units::traits::unit_t_traits<UnitTypeRhs>::underlying_type, decibel_scale>
2934 {
2935 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2936 using underlying_type = typename units::traits::unit_t_traits<RhsUnits>::underlying_type;
2937
2938 return unit_t<inverse<RhsUnits>, underlying_type, decibel_scale>
2939 (lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2940 }
2941
2942 //----------------------------------
2943 // UNIT RATIO CLASS
2944 //----------------------------------
2945 // DOXYGEN IGNORE
2947 namespace detail
2948 {
2949 template<class Units>
2950 struct _unit_value_t {};
2951 } // END DOXYGEN IGNORE
2953
2954 namespace traits
2955 {
2956#ifdef FOR_DOXYGEN_PURPOSES_ONLY
2964 template<typename T>
2965 struct unit_value_t_traits
2966 {
2967 typedef typename T::unit_type unit_type;
2968 typedef typename T::ratio ratio;
2969 };
2970#endif
2971 // DOXYGEN IGNORE
2977 template<typename T, typename = void>
2978 struct unit_value_t_traits
2979 {
2980 typedef void unit_type;
2981 typedef void ratio;
2982 };
2983
2989 template<typename T>
2990 struct unit_value_t_traits <T, typename void_t<
2991 typename T::unit_type,
2992 typename T::ratio>::type>
2993 {
2994 typedef typename T::unit_type unit_type;
2995 typedef typename T::ratio ratio;
2996 }; // END DOXYGEN IGNORE
2998 }
2999
3000 //------------------------------------------------------------------------------
3001 // COMPILE-TIME UNIT VALUES AND ARITHMETIC
3002 //------------------------------------------------------------------------------
3003
3017 template<typename Units, std::uintmax_t Num, std::uintmax_t Denom = 1>
3018 struct unit_value_t : units::detail::_unit_value_t<Units>
3019 {
3020 typedef Units unit_type;
3021 typedef std::ratio<Num, Denom> ratio;
3022
3023 static_assert(traits::is_unit<Units>::value, "Template parameter `Units` must be a unit type.");
3024 static constexpr const unit_t<Units> value() { return unit_t<Units>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den); }
3025 };
3026
3027 namespace traits
3028 {
3037 template<typename T, typename Units = typename traits::unit_value_t_traits<T>::unit_type>
3038 struct is_unit_value_t : std::integral_constant<bool,
3039 std::is_base_of<units::detail::_unit_value_t<Units>, T>::value>
3040 {};
3041
3047 template<typename Category, typename T>
3048 struct is_unit_value_t_category : std::integral_constant<bool,
3049 std::is_same<units::traits::base_unit_of<typename traits::unit_value_t_traits<T>::unit_type>, Category>::value>
3050 {
3051 static_assert(is_base_unit<Category>::value, "Template parameter `Category` must be a `base_unit` type.");
3052 };
3053 }
3054 // DOXYGEN IGNORE
3056 namespace detail
3057 {
3058 // base class for common arithmetic
3059 template<class U1, class U2>
3060 struct unit_value_arithmetic
3061 {
3062 static_assert(traits::is_unit_value_t<U1>::value, "Template parameter `U1` must be a `unit_value_t` type.");
3063 static_assert(traits::is_unit_value_t<U2>::value, "Template parameter `U2` must be a `unit_value_t` type.");
3064
3065 using _UNIT1 = typename traits::unit_value_t_traits<U1>::unit_type;
3066 using _UNIT2 = typename traits::unit_value_t_traits<U2>::unit_type;
3067 using _CONV1 = typename units::traits::unit_traits<_UNIT1>::conversion_ratio;
3068 using _CONV2 = typename units::traits::unit_traits<_UNIT2>::conversion_ratio;
3069 using _RATIO1 = typename traits::unit_value_t_traits<U1>::ratio;
3070 using _RATIO2 = typename traits::unit_value_t_traits<U2>::ratio;
3071 using _RATIO2CONV = typename std::ratio_divide<std::ratio_multiply<_RATIO2, _CONV2>, _CONV1>;
3072 using _PI_EXP = std::ratio_subtract<typename units::traits::unit_traits<_UNIT2>::pi_exponent_ratio, typename units::traits::unit_traits<_UNIT1>::pi_exponent_ratio>;
3073 };
3074 } // END DOXYGEN IGNORE
3076
3087 template<class U1, class U2>
3088 struct unit_value_add : units::detail::unit_value_arithmetic<U1, U2>, units::detail::_unit_value_t<typename traits::unit_value_t_traits<U1>::unit_type>
3089 { // DOXYGEN IGNORE
3091 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3092 typedef typename Base::_UNIT1 unit_type;
3093 using ratio = std::ratio_add<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3094
3095 static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3097
3104 static constexpr const unit_t<unit_type> value() noexcept
3105 {
3106 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3107 return value(UsePi());
3108 }
3109 // DOXYGEN IGNORE
3111 // value if PI isn't involved
3112 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3113 {
3114 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3115 }
3116
3117 // value if PI *is* involved
3118 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3119 {
3120 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO1::num / Base::_RATIO1::den) +
3121 ((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO2CONV::num / Base::_RATIO2CONV::den) * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3122 } // END DOXYGEN IGNORE
3124 };
3125
3136 template<class U1, class U2>
3137 struct unit_value_subtract : units::detail::unit_value_arithmetic<U1, U2>, units::detail::_unit_value_t<typename traits::unit_value_t_traits<U1>::unit_type>
3138 { // DOXYGEN IGNORE
3140 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3141
3142 typedef typename Base::_UNIT1 unit_type;
3143 using ratio = std::ratio_subtract<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3144
3145 static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3147
3154 static constexpr const unit_t<unit_type> value() noexcept
3155 {
3156 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3157 return value(UsePi());
3158 }
3159 // DOXYGEN IGNORE
3161 // value if PI isn't involved
3162 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3163 {
3164 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3165 }
3166
3167 // value if PI *is* involved
3168 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3169 {
3170 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO1::num / Base::_RATIO1::den) - ((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO2CONV::num / Base::_RATIO2CONV::den)
3171 * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3172 } // END DOXYGEN IGNORE };
3174 };
3175
3186 template<class U1, class U2>
3187 struct unit_value_multiply : units::detail::unit_value_arithmetic<U1, U2>,
3188 units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3189 typename traits::unit_value_t_traits<U2>::unit_type>::value, compound_unit<squared<typename traits::unit_value_t_traits<U1>::unit_type>>,
3190 compound_unit<typename traits::unit_value_t_traits<U1>::unit_type, typename traits::unit_value_t_traits<U2>::unit_type>>::type>
3191 { // DOXYGEN IGNORE
3193 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3194
3195 using unit_type = std::conditional_t<traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, compound_unit<squared<typename Base::_UNIT1>>, compound_unit<typename Base::_UNIT1, typename Base::_UNIT2>>;
3196 using ratio = std::conditional_t<traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, std::ratio_multiply<typename Base::_RATIO1, typename Base::_RATIO2CONV>, std::ratio_multiply<typename Base::_RATIO1, typename Base::_RATIO2>>; // END DOXYGEN IGNORE
3198
3205 static constexpr const unit_t<unit_type> value() noexcept
3206 {
3207 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3208 return value(UsePi());
3209 }
3210 // DOXYGEN IGNORE
3212 // value if PI isn't involved
3213 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3214 {
3215 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3216 }
3217
3218 // value if PI *is* involved
3219 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3220 {
3221 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den) * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3222 } // END DOXYGEN IGNORE
3224 };
3225
3236 template<class U1, class U2>
3237 struct unit_value_divide : units::detail::unit_value_arithmetic<U1, U2>,
3238 units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3239 typename traits::unit_value_t_traits<U2>::unit_type>::value, dimensionless::scalar, compound_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3240 inverse<typename traits::unit_value_t_traits<U2>::unit_type>>>::type>
3241 { // DOXYGEN IGNORE
3243 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3244
3245 using unit_type = std::conditional_t<traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, dimensionless::scalar, compound_unit<typename Base::_UNIT1, inverse<typename Base::_UNIT2>>>;
3246 using ratio = std::conditional_t<traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, std::ratio_divide<typename Base::_RATIO1, typename Base::_RATIO2CONV>, std::ratio_divide<typename Base::_RATIO1, typename Base::_RATIO2>>; // END DOXYGEN IGNORE
3248
3255 static constexpr const unit_t<unit_type> value() noexcept
3256 {
3257 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3258 return value(UsePi());
3259 }
3260 // DOXYGEN IGNORE
3262 // value if PI isn't involved
3263 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3264 {
3265 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3266 }
3267
3268 // value if PI *is* involved
3269 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3270 {
3271 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den) * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3272 } // END DOXYGEN IGNORE
3274 };
3275
3285 template<class U1, int power>
3286 struct unit_value_power : units::detail::unit_value_arithmetic<U1, U1>, units::detail::_unit_value_t<typename units::detail::power_of_unit<power, typename traits::unit_value_t_traits<U1>::unit_type>::type>
3287 { // DOXYGEN IGNORE
3289 using Base = units::detail::unit_value_arithmetic<U1, U1>;
3290
3291 using unit_type = typename units::detail::power_of_unit<power, typename Base::_UNIT1>::type;
3292 using ratio = typename units::detail::power_of_ratio<power, typename Base::_RATIO1>::type;
3293 using pi_exponent = std::ratio_multiply<std::ratio<power>, typename Base::_UNIT1::pi_exponent_ratio>; // END DOXYGEN IGNORE
3295
3302 static constexpr const unit_t<unit_type> value() noexcept
3303 {
3304 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3305 return value(UsePi());
3306 }
3307 // DOXYGEN IGNORE
3309 // value if PI isn't involved
3310 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3311 {
3312 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3313 }
3314
3315 // value if PI *is* involved
3316 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3317 {
3318 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den) * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)pi_exponent::num / pi_exponent::den)));
3319 } // END DOXYGEN IGNORE };
3321 };
3322
3332 template<class U1, std::intmax_t Eps = 10000000000>
3333 struct unit_value_sqrt : units::detail::unit_value_arithmetic<U1, U1>, units::detail::_unit_value_t<square_root<typename traits::unit_value_t_traits<U1>::unit_type, Eps>>
3334 { // DOXYGEN IGNORE
3336 using Base = units::detail::unit_value_arithmetic<U1, U1>;
3337
3340 using pi_exponent = ratio_sqrt<typename Base::_UNIT1::pi_exponent_ratio, Eps>; // END DOXYGEN IGNORE
3342
3349 static constexpr const unit_t<unit_type> value() noexcept
3350 {
3351 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3352 return value(UsePi());
3353 }
3354 // DOXYGEN IGNORE
3356 // value if PI isn't involved
3357 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3358 {
3359 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3360 }
3361
3362 // value if PI *is* involved
3363 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3364 {
3365 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den) * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)pi_exponent::num / pi_exponent::den)));
3366 } // END DOXYGEN IGNORE
3368 };
3369
3370 //------------------------------
3371 // LITERALS
3372 //------------------------------
3373
3384
3385 //------------------------------
3386 // LENGTH UNITS
3387 //------------------------------
3388
3397#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LENGTH_UNITS)
3398 UNIT_ADD_WITH_METRIC_PREFIXES(length, meter, meters, m, unit<std::ratio<1>, units::category::length_unit>)
3399 UNIT_ADD(length, foot, feet, ft, unit<std::ratio<381, 1250>, meters>)
3400 UNIT_ADD(length, inch, inches, in, unit<std::ratio<1, 12>, feet>)
3401 UNIT_ADD(length, mil, mils, mil, unit<std::ratio<1000>, inches>)
3402 UNIT_ADD(length, mile, miles, mi, unit<std::ratio<5280>, feet>)
3403 UNIT_ADD(length, nauticalMile, nauticalMiles, nmi, unit<std::ratio<1852>, meters>)
3404 UNIT_ADD(length, astronicalUnit, astronicalUnits, au, unit<std::ratio<149597870700>, meters>)
3405 UNIT_ADD(length, lightyear, lightyears, ly, unit<std::ratio<9460730472580800>, meters>)
3406 UNIT_ADD(length, parsec, parsecs, pc, unit<std::ratio<648000>, astronicalUnits, std::ratio<-1>>)
3407 UNIT_ADD(length, angstrom, angstroms, angstrom, unit<std::ratio<1, 10>, nanometers>)
3408 UNIT_ADD(length, cubit, cubits, cbt, unit<std::ratio<18>, inches>)
3409 UNIT_ADD(length, fathom, fathoms, ftm, unit<std::ratio<6>, feet>)
3410 UNIT_ADD(length, chain, chains, ch, unit<std::ratio<66>, feet>)
3411 UNIT_ADD(length, furlong, furlongs, fur, unit<std::ratio<10>, chains>)
3412 UNIT_ADD(length, hand, hands, hand, unit<std::ratio<4>, inches>)
3413 UNIT_ADD(length, league, leagues, lea, unit<std::ratio<3>, miles>)
3414 UNIT_ADD(length, nauticalLeague, nauticalLeagues, nl, unit<std::ratio<3>, nauticalMiles>)
3415 UNIT_ADD(length, yard, yards, yd, unit<std::ratio<3>, feet>)
3416
3418#endif
3419
3420 //------------------------------
3421 // MASS UNITS
3422 //------------------------------
3423
3432#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MASS_UNITS)
3433 UNIT_ADD_WITH_METRIC_PREFIXES(mass, gram, grams, g, unit<std::ratio<1, 1000>, units::category::mass_unit>)
3434 UNIT_ADD(mass, metric_ton, metric_tons, t, unit<std::ratio<1000>, kilograms>)
3435 UNIT_ADD(mass, pound, pounds, lb, unit<std::ratio<45359237, 100000000>, kilograms>)
3436 UNIT_ADD(mass, long_ton, long_tons, ln_t, unit<std::ratio<2240>, pounds>)
3437 UNIT_ADD(mass, short_ton, short_tons, sh_t, unit<std::ratio<2000>, pounds>)
3438 UNIT_ADD(mass, stone, stone, st, unit<std::ratio<14>, pounds>)
3439 UNIT_ADD(mass, ounce, ounces, oz, unit<std::ratio<1, 16>, pounds>)
3440 UNIT_ADD(mass, carat, carats, ct, unit<std::ratio<200>, milligrams>)
3441 UNIT_ADD(mass, slug, slugs, slug, unit<std::ratio<145939029, 10000000>, kilograms>)
3442
3444#endif
3445
3446 //------------------------------
3447 // TIME UNITS
3448 //------------------------------
3449
3458#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TIME_UNITS)
3459 UNIT_ADD_WITH_METRIC_PREFIXES(time, second, seconds, s, unit<std::ratio<1>, units::category::time_unit>)
3460 UNIT_ADD(time, minute, minutes, min, unit<std::ratio<60>, seconds>)
3461 UNIT_ADD(time, hour, hours, hr, unit<std::ratio<60>, minutes>)
3462 UNIT_ADD(time, day, days, d, unit<std::ratio<24>, hours>)
3463 UNIT_ADD(time, week, weeks, wk, unit<std::ratio<7>, days>)
3464 UNIT_ADD(time, year, years, yr, unit<std::ratio<365>, days>)
3465 UNIT_ADD(time, julian_year, julian_years, a_j, unit<std::ratio<31557600>, seconds>)
3466 UNIT_ADD(time, gregorian_year, gregorian_years, a_g, unit<std::ratio<31556952>, seconds>)
3467
3469#endif
3470
3471 //------------------------------
3472 // ANGLE UNITS
3473 //------------------------------
3474
3483#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
3484 UNIT_ADD_WITH_METRIC_PREFIXES(angle, radian, radians, rad, unit<std::ratio<1>, units::category::angle_unit>)
3485 UNIT_ADD(angle, degree, degrees, deg, unit<std::ratio<1, 180>, radians, std::ratio<1>>)
3486 UNIT_ADD(angle, arcminute, arcminutes, arcmin, unit<std::ratio<1, 60>, degrees>)
3487 UNIT_ADD(angle, arcsecond, arcseconds, arcsec, unit<std::ratio<1, 60>, arcminutes>)
3488 UNIT_ADD(angle, milliarcsecond, milliarcseconds, mas, milli<arcseconds>)
3489 UNIT_ADD(angle, turn, turns, tr, unit<std::ratio<2>, radians, std::ratio<1>>)
3490 UNIT_ADD(angle, gradian, gradians, gon, unit<std::ratio<1, 400>, turns>)
3491
3493#endif
3494
3495 //------------------------------
3496 // UNITS OF CURRENT
3497 //------------------------------
3506#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CURRENT_UNITS)
3507 UNIT_ADD_WITH_METRIC_PREFIXES(current, ampere, amperes, A, unit<std::ratio<1>, units::category::current_unit>)
3508
3510#endif
3511
3512 //------------------------------
3513 // UNITS OF TEMPERATURE
3514 //------------------------------
3515
3516 // NOTE: temperature units have special conversion overloads, since they
3517 // require translations and aren't a reversible transform.
3518
3527#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TEMPERATURE_UNITS)
3528 UNIT_ADD(temperature, kelvin, kelvin, K, unit<std::ratio<1>, units::category::temperature_unit>)
3529 UNIT_ADD(temperature, celsius, celsius, degC, unit<std::ratio<1>, kelvin, std::ratio<0>, std::ratio<27315, 100>>)
3530 UNIT_ADD(temperature, fahrenheit, fahrenheit, degF, unit<std::ratio<5, 9>, celsius, std::ratio<0>, std::ratio<-160, 9>>)
3531 UNIT_ADD(temperature, reaumur, reaumur, Re, unit<std::ratio<10, 8>, celsius>)
3532 UNIT_ADD(temperature, rankine, rankine, Ra, unit<std::ratio<5, 9>, kelvin>)
3533
3535#endif
3536
3537 //------------------------------
3538 // UNITS OF AMOUNT OF SUBSTANCE
3539 //------------------------------
3540
3549#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SUBSTANCE_UNITS)
3550 UNIT_ADD(substance, mole, moles, mol, unit<std::ratio<1>, units::category::substance_unit>)
3551
3553#endif
3554
3555 //------------------------------
3556 // UNITS OF LUMINOUS INTENSITY
3557 //------------------------------
3558
3567#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS)
3569
3571#endif
3572
3573 //------------------------------
3574 // UNITS OF SOLID ANGLE
3575 //------------------------------
3576
3585#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS)
3586 UNIT_ADD_WITH_METRIC_PREFIXES(solid_angle, steradian, steradians, sr, unit<std::ratio<1>, units::category::solid_angle_unit>)
3587 UNIT_ADD(solid_angle, degree_squared, degrees_squared, sq_deg, squared<angle::degrees>)
3588 UNIT_ADD(solid_angle, spat, spats, sp, unit<std::ratio<4>, steradians, std::ratio<1>>)
3589
3591#endif
3592
3593 //------------------------------
3594 // FREQUENCY UNITS
3595 //------------------------------
3596
3605#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FREQUENCY_UNITS)
3607
3609#endif
3610
3611 //------------------------------
3612 // VELOCITY UNITS
3613 //------------------------------
3614
3623#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VELOCITY_UNITS)
3624 UNIT_ADD(velocity, meters_per_second, meters_per_second, mps, unit<std::ratio<1>, units::category::velocity_unit>)
3625 UNIT_ADD(velocity, feet_per_second, feet_per_second, fps, compound_unit<length::feet, inverse<time::seconds>>)
3626 UNIT_ADD(velocity, miles_per_hour, miles_per_hour, mph, compound_unit<length::miles, inverse<time::hour>>)
3627 UNIT_ADD(velocity, kilometers_per_hour, kilometers_per_hour, kph, compound_unit<length::kilometers, inverse<time::hour>>)
3628 UNIT_ADD(velocity, knot, knots, kts, compound_unit<length::nauticalMiles, inverse<time::hour>>)
3629
3631#endif
3632
3633 //------------------------------
3634 // ANGULAR VELOCITY UNITS
3635 //------------------------------
3636
3645#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS)
3646 UNIT_ADD(angular_velocity, radians_per_second, radians_per_second, rad_per_s, unit<std::ratio<1>, units::category::angular_velocity_unit>)
3647 UNIT_ADD(angular_velocity, degrees_per_second, degrees_per_second, deg_per_s, compound_unit<angle::degrees, inverse<time::seconds>>)
3648 UNIT_ADD(angular_velocity, revolutions_per_minute, revolutions_per_minute, rpm, unit<std::ratio<2, 60>, radians_per_second, std::ratio<1>>)
3649 UNIT_ADD(angular_velocity, revolutions_per_second, revolutions_per_second, rps, unit<std::ratio<2, 1>, radians_per_second, std::ratio<1>>)
3650 UNIT_ADD(angular_velocity, milliarcseconds_per_year, milliarcseconds_per_year, mas_per_yr, compound_unit<angle::milliarcseconds, inverse<time::year>>)
3651
3653#endif
3654
3655 //------------------------------
3656 // UNITS OF ACCELERATION
3657 //------------------------------
3658
3667#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ACCELERATION_UNITS)
3668 UNIT_ADD(acceleration, meters_per_second_squared, meters_per_second_squared, mps_sq, unit<std::ratio<1>, units::category::acceleration_unit>)
3669 UNIT_ADD(acceleration, feet_per_second_squared, feet_per_second_squared, fps_sq, compound_unit<length::feet, inverse<squared<time::seconds>>>)
3670 UNIT_ADD(acceleration, standard_gravity, standard_gravity, SG, unit<std::ratio<980665, 100000>, meters_per_second_squared>)
3671
3673#endif
3674
3675 //------------------------------
3676 // UNITS OF JERK
3677 //------------------------------
3678
3687#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_JERK_UNITS)
3688 UNIT_ADD(jerk, meters_per_second_cubed, meters_per_second_cubed, mps_cb, unit<std::ratio<1>, units::category::jerk_unit>)
3689 UNIT_ADD(jerk, feet_per_second_cubed, feet_per_second_cubed, fps_cb, compound_unit<length::feet, inverse<cubed<time::seconds>>>)
3690
3692#endif
3693
3694 //------------------------------
3695 // UNITS OF FORCE
3696 //------------------------------
3697
3706#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FORCE_UNITS)
3707 UNIT_ADD_WITH_METRIC_PREFIXES(force, newton, newtons, N, unit<std::ratio<1>, units::category::force_unit>)
3708 UNIT_ADD(force, pound, pounds, lbf, compound_unit<mass::slug, length::foot, inverse<squared<time::seconds>>>)
3709 UNIT_ADD(force, dyne, dynes, dyn, unit<std::ratio<1, 100000>, newtons>)
3710 UNIT_ADD(force, kilopond, kiloponds, kp, compound_unit<acceleration::standard_gravity, mass::kilograms>)
3711 UNIT_ADD(force, poundal, poundals, pdl, compound_unit<mass::pound, length::foot, inverse<squared<time::seconds>>>)
3712
3714#endif
3715
3716 //------------------------------
3717 // UNITS OF PRESSURE
3718 //------------------------------
3719
3728#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_PRESSURE_UNITS)
3729 UNIT_ADD_WITH_METRIC_PREFIXES(pressure, pascal, pascals, Pa, unit<std::ratio<1>, units::category::pressure_unit>)
3730 UNIT_ADD(pressure, bar, bars, bar, unit<std::ratio<100>, kilo<pascals>>)
3731 UNIT_ADD(pressure, mbar, mbars, mbar, unit<std::ratio<1>, milli<bar>>)
3732 UNIT_ADD(pressure, atmosphere, atmospheres, atm, unit<std::ratio<101325>, pascals>)
3733 UNIT_ADD(pressure, pounds_per_square_inch, pounds_per_square_inch, psi, compound_unit<force::pounds, inverse<squared<length::inch>>>)
3734 UNIT_ADD(pressure, torr, torrs, torr, unit<std::ratio<1, 760>, atmospheres>)
3735 UNIT_ADD(pressure, millimeter_of_mercury, millimeters_of_mercury, mmHg, unit<std::ratio<26664477483LL, 200000000LL>, pascals>)
3736 UNIT_ADD(pressure, inch_of_mercury, inches_of_mercury, inHg, unit<std::ratio<254, 10>, millimeters_of_mercury>)
3737
3739#endif
3740
3741 //------------------------------
3742 // UNITS OF CHARGE
3743 //------------------------------
3744
3753#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CHARGE_UNITS)
3754 UNIT_ADD_WITH_METRIC_PREFIXES(charge, coulomb, coulombs, C, unit<std::ratio<1>, units::category::charge_unit>)
3755 UNIT_ADD_WITH_METRIC_PREFIXES(charge, ampere_hour, ampere_hours, Ah, compound_unit<current::ampere, time::hours>)
3756
3758#endif
3759
3760 //------------------------------
3761 // UNITS OF ENERGY
3762 //------------------------------
3763
3772#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ENERGY_UNITS)
3773 UNIT_ADD_WITH_METRIC_PREFIXES(energy, joule, joules, J, unit<std::ratio<1>, units::category::energy_unit>)
3774 UNIT_ADD_WITH_METRIC_PREFIXES(energy, calorie, calories, cal, unit<std::ratio<4184, 1000>, joules>)
3775 UNIT_ADD(energy, kilowatt_hour, kilowatt_hours, kWh, unit<std::ratio<36, 10>, megajoules>)
3776 UNIT_ADD(energy, watt_hour, watt_hours, Wh, unit<std::ratio<1, 1000>, kilowatt_hours>)
3777 UNIT_ADD(energy, british_thermal_unit, british_thermal_units, BTU, unit<std::ratio<105505585262, 100000000>, joules>)
3778 UNIT_ADD(energy, british_thermal_unit_iso, british_thermal_units_iso, BTU_iso, unit<std::ratio<1055056, 1000>, joules>)
3779 UNIT_ADD(energy, british_thermal_unit_59, british_thermal_units_59, BTU59, unit<std::ratio<1054804, 1000>, joules>)
3780 UNIT_ADD(energy, therm, therms, thm, unit<std::ratio<100000>, british_thermal_units_59>)
3781 UNIT_ADD(energy, foot_pound, foot_pounds, ftlbf, unit<std::ratio<13558179483314004, 10000000000000000>, joules>)
3782
3784#endif
3785
3786 //------------------------------
3787 // UNITS OF POWER
3788 //------------------------------
3789
3798#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_POWER_UNITS)
3800 UNIT_ADD(power, horsepower, horsepower, hp, unit<std::ratio<7457, 10>, watts>)
3801 UNIT_ADD_DECIBEL(power, watt, dBW)
3802 UNIT_ADD_DECIBEL(power, milliwatt, dBm)
3803
3805#endif
3806
3807 //------------------------------
3808 // UNITS OF VOLTAGE
3809 //------------------------------
3810
3819#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLTAGE_UNITS)
3821 UNIT_ADD(voltage, statvolt, statvolts, statV, unit<std::ratio<1000000, 299792458>, volts>)
3822 UNIT_ADD(voltage, abvolt, abvolts, abV, unit<std::ratio<1, 100000000>, volts>)
3823
3825#endif
3826
3827 //------------------------------
3828 // UNITS OF CAPACITANCE
3829 //------------------------------
3830
3839#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CAPACITANCE_UNITS)
3841
3843#endif
3844
3845 //------------------------------
3846 // UNITS OF IMPEDANCE
3847 //------------------------------
3848
3857#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_IMPEDANCE_UNITS)
3859
3861#endif
3862
3863 //------------------------------
3864 // UNITS OF CONDUCTANCE
3865 //------------------------------
3866
3875#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONDUCTANCE_UNITS)
3877
3879#endif
3880
3881 //------------------------------
3882 // UNITS OF MAGNETIC FLUX
3883 //------------------------------
3884
3893#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS)
3895 UNIT_ADD(magnetic_flux, maxwell, maxwells, Mx, unit<std::ratio<1, 100000000>, webers>)
3896
3898#endif
3899
3900 //----------------------------------------
3901 // UNITS OF MAGNETIC FIELD STRENGTH
3902 //----------------------------------------
3903
3912 // Unfortunately `_T` is a WINAPI macro, so we have to use `_Te` as the tesla abbreviation.
3913#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS)
3915 UNIT_ADD(magnetic_field_strength, gauss, gauss, G, compound_unit<magnetic_flux::maxwell, inverse<squared<length::centimeter>>>)
3916
3918#endif
3919
3920 //------------------------------
3921 // UNITS OF INDUCTANCE
3922 //------------------------------
3923
3932#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_INDUCTANCE_UNITS)
3934
3936#endif
3937
3938 //------------------------------
3939 // UNITS OF LUMINOUS FLUX
3940 //------------------------------
3941
3950#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS)
3952
3954#endif
3955
3956 //------------------------------
3957 // UNITS OF ILLUMINANCE
3958 //------------------------------
3959
3968#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ILLUMINANCE_UNITS)
3970 UNIT_ADD(illuminance, footcandle, footcandles, fc, compound_unit<luminous_flux::lumen, inverse<squared<length::foot>>>)
3971 UNIT_ADD(illuminance, lumens_per_square_inch, lumens_per_square_inch, lm_per_in_sq, compound_unit<luminous_flux::lumen, inverse<squared<length::inch>>>)
3972 UNIT_ADD(illuminance, phot, phots, ph, compound_unit<luminous_flux::lumens, inverse<squared<length::centimeter>>>)
3973
3975#endif
3976
3977 //------------------------------
3978 // UNITS OF RADIATION
3979 //------------------------------
3980
3991#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_RADIATION_UNITS)
3992 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, becquerel, becquerels, Bq, unit<std::ratio<1>, units::frequency::hertz>)
3993 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, gray, grays, Gy, compound_unit<energy::joules, inverse<mass::kilogram>>)
3994 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, sievert, sieverts, Sv, unit<std::ratio<1>, grays>)
3995 UNIT_ADD(radiation, curie, curies, Ci, unit<std::ratio<37>, gigabecquerels>)
3996 UNIT_ADD(radiation, rutherford, rutherfords, rd, unit<std::ratio<1>, megabecquerels>)
3997 UNIT_ADD(radiation, rad, rads, rads, unit<std::ratio<1>, centigrays>)
3998
4000#endif
4001
4002 //------------------------------
4003 // UNITS OF TORQUE
4004 //------------------------------
4005
4014#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TORQUE_UNITS)
4015 UNIT_ADD(torque, newton_meter, newton_meters, Nm, unit<std::ratio<1>, units::energy::joule>)
4016 UNIT_ADD(torque, foot_pound, foot_pounds, ftlb, compound_unit<length::foot, force::pounds>)
4017 UNIT_ADD(torque, foot_poundal, foot_poundals, ftpdl, compound_unit<length::foot, force::poundal>)
4018 UNIT_ADD(torque, inch_pound, inch_pounds, inlb, compound_unit<length::inch, force::pounds>)
4019 UNIT_ADD(torque, meter_kilogram, meter_kilograms, mkgf, compound_unit<length::meter, force::kiloponds>)
4020
4022#endif
4023
4024 //------------------------------
4025 // AREA UNITS
4026 //------------------------------
4027
4036#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_AREA_UNITS)
4037 UNIT_ADD(area, square_meter, square_meters, sq_m, unit<std::ratio<1>, units::category::area_unit>)
4038 UNIT_ADD(area, square_foot, square_feet, sq_ft, squared<length::feet>)
4039 UNIT_ADD(area, square_inch, square_inches, sq_in, squared<length::inch>)
4040 UNIT_ADD(area, square_mile, square_miles, sq_mi, squared<length::miles>)
4041 UNIT_ADD(area, square_kilometer, square_kilometers, sq_km, squared<length::kilometers>)
4042 UNIT_ADD(area, hectare, hectares, ha, unit<std::ratio<10000>, square_meters>)
4043 UNIT_ADD(area, acre, acres, acre, unit<std::ratio<43560>, square_feet>)
4044
4046#endif
4047
4048 //------------------------------
4049 // UNITS OF VOLUME
4050 //------------------------------
4051
4060#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLUME_UNITS)
4061 UNIT_ADD(volume, cubic_meter, cubic_meters, cu_m, unit<std::ratio<1>, units::category::volume_unit>)
4062 UNIT_ADD(volume, cubic_millimeter, cubic_millimeters, cu_mm, cubed<length::millimeter>)
4063 UNIT_ADD(volume, cubic_kilometer, cubic_kilometers, cu_km, cubed<length::kilometer>)
4064 UNIT_ADD_WITH_METRIC_PREFIXES(volume, liter, liters, L, cubed<deci<length::meter>>)
4065 UNIT_ADD(volume, cubic_inch, cubic_inches, cu_in, cubed<length::inches>)
4066 UNIT_ADD(volume, cubic_foot, cubic_feet, cu_ft, cubed<length::feet>)
4067 UNIT_ADD(volume, cubic_yard, cubic_yards, cu_yd, cubed<length::yards>)
4068 UNIT_ADD(volume, cubic_mile, cubic_miles, cu_mi, cubed<length::miles>)
4069 UNIT_ADD(volume, gallon, gallons, gal, unit<std::ratio<231>, cubic_inches>)
4070 UNIT_ADD(volume, quart, quarts, qt, unit<std::ratio<1, 4>, gallons>)
4071 UNIT_ADD(volume, pint, pints, pt, unit<std::ratio<1, 2>, quarts>)
4072 UNIT_ADD(volume, cup, cups, c, unit<std::ratio<1, 2>, pints>)
4073 UNIT_ADD(volume, fluid_ounce, fluid_ounces, fl_oz, unit<std::ratio<1, 8>, cups>)
4074 UNIT_ADD(volume, barrel, barrels, bl, unit<std::ratio<42>, gallons>)
4075 UNIT_ADD(volume, bushel, bushels, bu, unit<std::ratio<215042, 100>, cubic_inches>)
4076 UNIT_ADD(volume, cord, cords, cord, unit<std::ratio<128>, cubic_feet>)
4077 UNIT_ADD(volume, cubic_fathom, cubic_fathoms, cu_fm, cubed<length::fathom>)
4078 UNIT_ADD(volume, tablespoon, tablespoons, tbsp, unit<std::ratio<1, 2>, fluid_ounces>)
4079 UNIT_ADD(volume, teaspoon, teaspoons, tsp, unit<std::ratio<1, 6>, fluid_ounces>)
4080 UNIT_ADD(volume, pinch, pinches, pinch, unit<std::ratio<1, 8>, teaspoons>)
4081 UNIT_ADD(volume, dash, dashes, dash, unit<std::ratio<1, 2>, pinches>)
4082 UNIT_ADD(volume, drop, drops, drop, unit<std::ratio<1, 360>, fluid_ounces>)
4083 UNIT_ADD(volume, fifth, fifths, fifth, unit<std::ratio<1, 5>, gallons>)
4084 UNIT_ADD(volume, dram, drams, dr, unit<std::ratio<1, 8>, fluid_ounces>)
4085 UNIT_ADD(volume, gill, gills, gi, unit<std::ratio<4>, fluid_ounces>)
4086 UNIT_ADD(volume, peck, pecks, pk, unit<std::ratio<1, 4>, bushels>)
4087 UNIT_ADD(volume, sack, sacks, sacks, unit<std::ratio<3>, bushels>)
4088 UNIT_ADD(volume, shot, shots, shots, unit<std::ratio<3, 2>, fluid_ounces>)
4089 UNIT_ADD(volume, strike, strikes, strikes, unit<std::ratio<2>, bushels>)
4090
4092#endif
4093
4094 //------------------------------
4095 // UNITS OF DENSITY
4096 //------------------------------
4097
4106#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DENSITY_UNITS)
4107 UNIT_ADD(density, kilograms_per_cubic_meter, kilograms_per_cubic_meter, kg_per_cu_m, unit<std::ratio<1>, units::category::density_unit>)
4108 UNIT_ADD(density, grams_per_milliliter, grams_per_milliliter, g_per_mL, compound_unit<mass::grams, inverse<volume::milliliter>>)
4109 UNIT_ADD(density, kilograms_per_liter, kilograms_per_liter, kg_per_L, unit<std::ratio<1>, compound_unit<mass::grams, inverse<volume::milliliter>>>)
4110 UNIT_ADD(density, ounces_per_cubic_foot, ounces_per_cubic_foot, oz_per_cu_ft, compound_unit<mass::ounces, inverse<volume::cubic_foot>>)
4111 UNIT_ADD(density, ounces_per_cubic_inch, ounces_per_cubic_inch, oz_per_cu_in, compound_unit<mass::ounces, inverse<volume::cubic_inch>>)
4112 UNIT_ADD(density, ounces_per_gallon, ounces_per_gallon, oz_per_gal, compound_unit<mass::ounces, inverse<volume::gallon>>)
4113 UNIT_ADD(density, pounds_per_cubic_foot, pounds_per_cubic_foot, lb_per_cu_ft, compound_unit<mass::pounds, inverse<volume::cubic_foot>>)
4114 UNIT_ADD(density, pounds_per_cubic_inch, pounds_per_cubic_inch, lb_per_cu_in, compound_unit<mass::pounds, inverse<volume::cubic_inch>>)
4115 UNIT_ADD(density, pounds_per_gallon, pounds_per_gallon, lb_per_gal, compound_unit<mass::pounds, inverse<volume::gallon>>)
4116 UNIT_ADD(density, slugs_per_cubic_foot, slugs_per_cubic_foot, slug_per_cu_ft, compound_unit<mass::slugs, inverse<volume::cubic_foot>>)
4117
4119#endif
4120
4121 //------------------------------
4122 // UNITS OF CONCENTRATION
4123 //------------------------------
4124
4133#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONCENTRATION_UNITS)
4134 UNIT_ADD(concentration, ppm, parts_per_million, ppm, unit<std::ratio<1, 1000000>, units::category::scalar_unit>)
4135 UNIT_ADD(concentration, ppb, parts_per_billion, ppb, unit<std::ratio<1, 1000>, parts_per_million>)
4136 UNIT_ADD(concentration, ppt, parts_per_trillion, ppt, unit<std::ratio<1, 1000>, parts_per_billion>)
4137 UNIT_ADD(concentration, percent, percent, pct, unit<std::ratio<1, 100>, units::category::scalar_unit>)
4138
4140#endif
4141
4142 //------------------------------
4143 // UNITS OF DATA
4144 //------------------------------
4145
4154#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_UNITS)
4156 UNIT_ADD(data, exabyte, exabytes, EB, unit<std::ratio<1000>, petabytes>)
4157 UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data, bit, bits, b, unit<std::ratio<1, 8>, byte>)
4158 UNIT_ADD(data, exabit, exabits, Eb, unit<std::ratio<1000>, petabits>)
4159
4161#endif
4162
4163 //------------------------------
4164 // UNITS OF DATA TRANSFER
4165 //------------------------------
4166
4175#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS)
4176 UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data_transfer_rate, bytes_per_second, bytes_per_second, Bps, unit<std::ratio<1>, units::category::data_transfer_rate_unit>)
4177 UNIT_ADD(data_transfer_rate, exabytes_per_second, exabytes_per_second, EBps, unit<std::ratio<1000>, petabytes_per_second>)
4178 UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data_transfer_rate, bits_per_second, bits_per_second, bps, unit<std::ratio<1, 8>, bytes_per_second>)
4179 UNIT_ADD(data_transfer_rate, exabits_per_second, exabits_per_second, Ebps, unit<std::ratio<1000>, petabits_per_second>)
4180
4182#endif
4183
4184 //------------------------------
4185 // CONSTANTS
4186 //------------------------------
4187
4192#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONSTANTS_UNITS)
4193 namespace constants
4194 {
4200 #undef PI
4201 using PI = unit<std::ratio<1>, dimensionless::scalar, std::ratio<1>>;
4202
4203 static constexpr const unit_t<PI> pi(1);
4204 static constexpr const velocity::meters_per_second_t c(299792458.0);
4206 static constexpr const unit_t<compound_unit<energy::joule, time::seconds>> h(6.626070040e-34);
4207 static constexpr const unit_t<compound_unit<force::newtons, inverse<squared<current::ampere>>>> mu0(pi * 4.0e-7 * force::newton_t(1) / units::math::cpow<2>(current::ampere_t(1)));
4209 static constexpr const impedance::ohm_t Z0(mu0 * c);
4211 static constexpr const charge::coulomb_t e(1.6021766208e-19);
4212 static constexpr const mass::kilogram_t m_e(9.10938356e-31);
4213 static constexpr const mass::kilogram_t m_p(1.672621898e-27);
4215 static constexpr const unit_t<inverse<substance::mol>> N_A(6.022140857e23);
4221 }
4222#endif
4223
4224 //----------------------------------
4225 // UNIT-ENABLED CMATH FUNCTIONS
4226 //----------------------------------
4227
4233 namespace math
4234 {
4235
4236 //----------------------------------
4237 // MIN/MAX FUNCTIONS
4238 //----------------------------------
4239
4240 template<class UnitTypeLhs, class UnitTypeRhs>
4241 UnitTypeLhs min(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4242 {
4243 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4244 UnitTypeLhs r(rhs);
4245 return (lhs < r ? lhs : r);
4246 }
4247
4248 template<class UnitTypeLhs, class UnitTypeRhs>
4249 UnitTypeLhs max(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4250 {
4251 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4252 UnitTypeLhs r(rhs);
4253 return (lhs > r ? lhs : r);
4254 }
4255
4256 //----------------------------------
4257 // TRIGONOMETRIC FUNCTIONS
4258 //----------------------------------
4259
4268#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4269 template<class AngleUnit>
4270 dimensionless::scalar_t cos(const AngleUnit angle) noexcept
4271 {
4272 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4273 return dimensionless::scalar_t(std::cos(angle.template convert<angle::radian>()()));
4274 }
4275#endif
4276
4285#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4286 template<class AngleUnit>
4287 dimensionless::scalar_t sin(const AngleUnit angle) noexcept
4288 {
4289 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4290 return dimensionless::scalar_t(std::sin(angle.template convert<angle::radian>()()));
4291 }
4292#endif
4301#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4302 template<class AngleUnit>
4303 dimensionless::scalar_t tan(const AngleUnit angle) noexcept
4304 {
4305 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4306 return dimensionless::scalar_t(std::tan(angle.template convert<angle::radian>()()));
4307 }
4308#endif
4309
4317#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4318 template<class ScalarUnit>
4319 angle::radian_t acos(const ScalarUnit x) noexcept
4320 {
4321 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4322 return angle::radian_t(std::acos(x.value()));
4323 }
4324#endif
4325
4333#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4334 template<class ScalarUnit>
4335 angle::radian_t asin(const ScalarUnit x) noexcept
4336 {
4337 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4338 return angle::radian_t(std::asin(x.value()));
4339 }
4340#endif
4341
4353#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4354 template<class ScalarUnit>
4355 angle::radian_t atan(const ScalarUnit x) noexcept
4356 {
4357 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4358 return angle::radian_t(std::atan(x.value()));
4359 }
4360#endif
4361
4370#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4371 template<class Y, class X>
4372 angle::radian_t atan2(const Y y, const X x) noexcept
4373 {
4374 static_assert(traits::is_dimensionless_unit<decltype(y/x)>::value, "The quantity y/x must yield a dimensionless ratio.");
4375
4376 // X and Y could be different length units, so normalize them
4377 return angle::radian_t(std::atan2(y.template convert<typename units::traits::unit_t_traits<X>::unit_type>()(), x()));
4378 }
4379#endif
4380
4381 //----------------------------------
4382 // HYPERBOLIC TRIG FUNCTIONS
4383 //----------------------------------
4384
4393#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4394 template<class AngleUnit>
4395 dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
4396 {
4397 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4398 return dimensionless::scalar_t(std::cosh(angle.template convert<angle::radian>()()));
4399 }
4400#endif
4401
4410#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4411 template<class AngleUnit>
4412 dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
4413 {
4414 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4415 return dimensionless::scalar_t(std::sinh(angle.template convert<angle::radian>()()));
4416 }
4417#endif
4418
4427#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4428 template<class AngleUnit>
4429 dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
4430 {
4431 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4432 return dimensionless::scalar_t(std::tanh(angle.template convert<angle::radian>()()));
4433 }
4434#endif
4435
4444#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4445 template<class ScalarUnit>
4446 angle::radian_t acosh(const ScalarUnit x) noexcept
4447 {
4448 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4449 return angle::radian_t(std::acosh(x.value()));
4450 }
4451#endif
4452
4460#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4461 template<class ScalarUnit>
4462 angle::radian_t asinh(const ScalarUnit x) noexcept
4463 {
4464 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4465 return angle::radian_t(std::asinh(x.value()));
4466 }
4467#endif
4468
4478#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4479 template<class ScalarUnit>
4480 angle::radian_t atanh(const ScalarUnit x) noexcept
4481 {
4482 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4483 return angle::radian_t(std::atanh(x.value()));
4484 }
4485#endif
4486
4487 //----------------------------------
4488 // TRANSCENDENTAL FUNCTIONS
4489 //----------------------------------
4490
4491 // it makes NO SENSE to put dimensioned units into a transcendental function, and if you think it does you are
4492 // demonstrably wrong. https://en.wikipedia.org/wiki/Transcendental_function#Dimensional_analysis
4493
4503 template<class ScalarUnit>
4504 dimensionless::scalar_t exp(const ScalarUnit x) noexcept
4505 {
4506 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4507 return dimensionless::scalar_t(std::exp(x.value()));
4508 }
4509
4519 template<class ScalarUnit>
4520 dimensionless::scalar_t log(const ScalarUnit x) noexcept
4521 {
4522 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4523 return dimensionless::scalar_t(std::log(x.value()));
4524 }
4525
4534 template<class ScalarUnit>
4535 dimensionless::scalar_t log10(const ScalarUnit x) noexcept
4536 {
4537 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4538 return dimensionless::scalar_t(std::log10(x.value()));
4539 }
4540
4552 template<class ScalarUnit>
4553 dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit* intpart) noexcept
4554 {
4555 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4556
4557 UNIT_LIB_DEFAULT_TYPE intp;
4558 dimensionless::scalar_t fracpart = dimensionless::scalar_t(std::modf(x.value(), &intp));
4559 *intpart = intp;
4560 return fracpart;
4561 }
4562
4570 template<class ScalarUnit>
4571 dimensionless::scalar_t exp2(const ScalarUnit x) noexcept
4572 {
4573 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4574 return dimensionless::scalar_t(std::exp2(x.value()));
4575 }
4576
4585 template<class ScalarUnit>
4586 dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
4587 {
4588 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4589 return dimensionless::scalar_t(std::expm1(x.value()));
4590 }
4591
4601 template<class ScalarUnit>
4602 dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
4603 {
4604 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4605 return dimensionless::scalar_t(std::log1p(x.value()));
4606 }
4607
4616 template<class ScalarUnit>
4617 dimensionless::scalar_t log2(const ScalarUnit x) noexcept
4618 {
4619 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4620 return dimensionless::scalar_t(std::log2(x.value()));
4621 }
4622
4623 //----------------------------------
4624 // POWER FUNCTIONS
4625 //----------------------------------
4626
4627 /* pow is implemented earlier in the library since a lot of the unit definitions depend on it */
4628
4641 template<class UnitType, std::enable_if_t<units::traits::has_linear_scale<UnitType>::value, int> = 0>
4642 inline auto sqrt(const UnitType& value) noexcept -> unit_t<square_root<typename units::traits::unit_t_traits<UnitType>::unit_type>, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
4643 {
4644 return unit_t<square_root<typename units::traits::unit_t_traits<UnitType>::unit_type>, typename units::traits::unit_t_traits<UnitType>::underlying_type, linear_scale>
4645 (std::sqrt(value()));
4646 }
4647
4657 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<units::traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
4658 inline UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y)
4659 {
4660 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of hypot() function are not compatible units.");
4661 return UnitTypeLhs(std::hypot(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4662 }
4663
4664 //----------------------------------
4665 // ROUNDING FUNCTIONS
4666 //----------------------------------
4667
4675 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4676 UnitType ceil(const UnitType x) noexcept
4677 {
4678 return UnitType(std::ceil(x()));
4679 }
4680
4688 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4689 UnitType floor(const UnitType x) noexcept
4690 {
4691 return UnitType(std::floor(x()));
4692 }
4693
4702 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4703 UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
4704 {
4705 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmod() function are not compatible units.");
4706 return UnitTypeLhs(std::fmod(numer(), denom.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4707 }
4708
4717 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4718 UnitType trunc(const UnitType x) noexcept
4719 {
4720 return UnitType(std::trunc(x()));
4721 }
4722
4723
4732 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4733 UnitType round(const UnitType x) noexcept
4734 {
4735 return UnitType(std::round(x()));
4736 }
4737
4738 //----------------------------------
4739 // FLOATING POINT MANIPULATION
4740 //----------------------------------
4741
4751 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4752 UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4753 {
4754 return UnitTypeLhs(std::copysign(x(), y())); // no need for conversion to get the correct sign.
4755 }
4756
4758 template<class UnitTypeLhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value>>
4759 UnitTypeLhs copysign(const UnitTypeLhs x, const UNIT_LIB_DEFAULT_TYPE y) noexcept
4760 {
4761 return UnitTypeLhs(std::copysign(x(), y));
4762 }
4763
4764 //----------------------------------
4765 // MIN / MAX / DIFFERENCE
4766 //----------------------------------
4767
4778 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4779 UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4780 {
4781 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fdim() function are not compatible units.");
4782 return UnitTypeLhs(std::fdim(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4783 }
4784
4795 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4796 UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4797 {
4798 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmax() function are not compatible units.");
4799 return UnitTypeLhs(std::fmax(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4800 }
4801
4813 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4814 UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4815 {
4816 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmin() function are not compatible units.");
4817 return UnitTypeLhs(std::fmin(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4818 }
4819
4820 //----------------------------------
4821 // OTHER FUNCTIONS
4822 //----------------------------------
4823
4831 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4832 UnitType fabs(const UnitType x) noexcept
4833 {
4834 return UnitType(std::fabs(x()));
4835 }
4836
4844 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4845 UnitType abs(const UnitType x) noexcept
4846 {
4847 return UnitType(std::fabs(x()));
4848 }
4849
4860 template<class UnitTypeLhs, class UnitMultiply, class UnitAdd, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitMultiply>::value && traits::is_unit_t<UnitAdd>::value>>
4861 auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x * y)
4862 {
4863 using resultType = decltype(x * y);
4864 static_assert(traits::is_convertible_unit_t<compound_unit<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type, typename units::traits::unit_t_traits<UnitMultiply>::unit_type>, typename units::traits::unit_t_traits<UnitAdd>::unit_type>::value, "Unit types are not compatible.");
4865 return resultType(std::fma(x(), y(), resultType(z)()));
4866 }
4867
4868 } // end namespace math
4869} // end namespace units
4870
4871//------------------------------
4872// std::numeric_limits
4873//------------------------------
4874
4875namespace std
4876{
4877 template<class Units, typename T, template<typename> class NonLinearScale>
4878 class numeric_limits<units::unit_t<Units, T, NonLinearScale>>
4879 {
4880 public:
4881 static constexpr units::unit_t<Units, T, NonLinearScale> min()
4882 {
4883 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::min());
4884 }
4885 static constexpr units::unit_t<Units, T, NonLinearScale> denorm_min() noexcept
4886 {
4887 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::denorm_min());
4888 }
4889 static constexpr units::unit_t<Units, T, NonLinearScale> max()
4890 {
4891 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::max());
4892 }
4893 static constexpr units::unit_t<Units, T, NonLinearScale> lowest()
4894 {
4895 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::lowest());
4896 }
4897 static constexpr units::unit_t<Units, T, NonLinearScale> epsilon()
4898 {
4899 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::epsilon());
4900 }
4901 static constexpr units::unit_t<Units, T, NonLinearScale> round_error()
4902 {
4903 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::round_error());
4904 }
4905 static constexpr units::unit_t<Units, T, NonLinearScale> infinity()
4906 {
4907 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::infinity());
4908 }
4909 static constexpr units::unit_t<Units, T, NonLinearScale> quiet_NaN()
4910 {
4911 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::quiet_NaN());
4912 }
4913 static constexpr units::unit_t<Units, T, NonLinearScale> signaling_NaN()
4914 {
4915 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::signaling_NaN());
4916 }
4917 static constexpr bool is_specialized = std::numeric_limits<T>::is_specialized;
4918 static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
4919 static constexpr bool is_integer = std::numeric_limits<T>::is_integer;
4920 static constexpr bool is_exact = std::numeric_limits<T>::is_exact;
4921 static constexpr bool has_infinity = std::numeric_limits<T>::has_infinity;
4922 static constexpr bool has_quiet_NaN = std::numeric_limits<T>::has_quiet_NaN;
4923 static constexpr bool has_signaling_NaN = std::numeric_limits<T>::has_signaling_NaN;
4924 };
4925
4926 template<class Units, typename T, template<typename> class NonLinearScale>
4927 bool isnan(const units::unit_t<Units, T, NonLinearScale>& x)
4928 {
4929 return std::isnan(x());
4930 }
4931
4932 template<class Units, typename T, template<typename> class NonLinearScale>
4933 bool isinf(const units::unit_t<Units, T, NonLinearScale>& x)
4934 {
4935 return std::isinf(x());
4936 }
4937
4938 template<class Units, typename T, template<typename> class NonLinearScale>
4939 bool signbit(const units::unit_t<Units, T, NonLinearScale>& x)
4940 {
4941 return std::signbit(x());
4942 }
4943}
4944
4945#ifdef _MSC_VER
4946# if _MSC_VER <= 1800
4947# pragma warning(pop)
4948# undef constexpr
4949# pragma pop_macro("constexpr")
4950# undef noexcept
4951# pragma pop_macro("noexcept")
4952# undef _ALLOW_KEYWORD_MACROS
4953# endif // _MSC_VER < 1800
4954# pragma pop_macro("pascal")
4955#endif // _MSC_VER
4956
4957#if defined(__MINGW64__) || defined(__MINGW32__)
4958# pragma pop_macro("pascal")
4959#endif // __MINGW64__ or __MINGW32__
4960
4961#endif // units_h__
4962
4963// For Emacs
4964// Local Variables:
4965// Mode: C++
4966// c-basic-offset: 2
4967// fill-column: 116
4968// tab-width: 4
4969// End:
Container for values which represent quantities of a given unit.
Definition units.h:1923
constexpr bool operator<(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than
Definition units.h:2025
constexpr bool operator<=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than or equal
Definition units.h:2037
constexpr unit_t< U > convert() const noexcept
conversion
Definition units.h:2140
unit_t & operator=(const Ty &rhs) noexcept
assignment
Definition units.h:2012
constexpr unit_t(const std::chrono::duration< Rep, Period > &value) noexcept
chrono constructor
Definition units.h:1976
constexpr underlying_type value() const noexcept
unit value
Definition units.h:2104
constexpr unit_t(const Ty value) noexcept
constructor
Definition units.h:1965
constexpr unit_t(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
copy constructor (converting)
Definition units.h:1988
constexpr const char * name() const noexcept
returns the unit name
Definition units.h:2180
constexpr Ty toLinearized() const noexcept
linearized unit value
Definition units.h:2125
constexpr Ty to() const noexcept
unit value
Definition units.h:2114
constexpr bool operator!=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
inequality
Definition units.h:2095
Units unit_type
Type of unit the unit_t represents (e.g. meters)
Definition units.h:1937
constexpr bool operator>(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than
Definition units.h:2049
T value_type
Synonym for underlying type. May be removed in future versions. Prefer underlying_type.
Definition units.h:1936
constexpr bool operator==(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
equality
Definition units.h:2074
constexpr unit_t(const T value, const Args &... args) noexcept
constructor
Definition units.h:1954
constexpr const char * abbreviation() const noexcept
returns the unit abbreviation
Definition units.h:2188
NonLinearScale< T > non_linear_scale_type
Type of the non-linear scale of the unit_t (e.g. linear_scale)
Definition units.h:1934
constexpr bool operator>=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than or equal
Definition units.h:2061
constexpr unit_t()=default
default constructor.
unit_t & operator=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
assignment
Definition units.h:2000
T underlying_type
Type of the underlying storage of the unit_t (e.g. double)
Definition units.h:1935
constexpr T unit_cast(const Units &value) noexcept
Casts a unit container to an arithmetic type.
Definition units.h:2389
static constexpr T convert(const T &value) noexcept
converts a value from one type to another.
Definition units.h:1648
typename units::detail::Sqrt< Ratio, std::ratio< 1, Eps > >::type ratio_sqrt
Calculate square root of a ratio at compile-time.
Definition units.h:1339
constexpr UnitType make_unit(const T value) noexcept
Constructs a unit container from an arithmetic type.
Definition units.h:2214
typename units::detail::inverse_impl< U >::type inverse
represents the inverse unit type of class U.
Definition units.h:1117
typename units::detail::prefix< std::exa, U >::type exa
Represents the type of class U with the metric 'exa' prefix appended.
Definition units.h:1475
typename units::detail::prefix< std::deca, U >::type deca
Represents the type of class U with the metric 'deca' prefix appended.
Definition units.h:1468
typename units::detail::squared_impl< U >::type squared
represents the unit type of class U squared
Definition units.h:1148
typename units::detail::cubed_impl< U >::type cubed
represents the type of class U cubed.
Definition units.h:1178
typename units::detail::prefix< std::milli, U >::type milli
Represents the type of class U with the metric 'milli' prefix appended.
Definition units.h:1465
typename units::detail::prefix< std::peta, U >::type peta
Represents the type of class U with the metric 'peta' prefix appended.
Definition units.h:1474
typename units::detail::prefix< std::kilo, U >::type kilo
Represents the type of class U with the metric 'kilo' prefix appended.
Definition units.h:1470
typename units::detail::prefix< std::micro, U >::type micro
Represents the type of class U with the metric 'micro' prefix appended.
Definition units.h:1464
typename units::detail::prefix< std::deci, U >::type deci
Represents the type of class U with the metric 'deci' prefix appended.
Definition units.h:1467
typename units::detail::prefix< std::ratio< 1073741824 >, U >::type gibi
Represents the type of class U with the binary 'gibi' prefix appended.
Definition units.h:1486
typename units::detail::prefix< std::giga, U >::type giga
Represents the type of class U with the metric 'giga' prefix appended.
Definition units.h:1472
typename units::detail::prefix< std::ratio< 1048576 >, U >::type mebi
Represents the type of class U with the binary 'mibi' prefix appended.
Definition units.h:1485
typename units::detail::prefix< std::ratio< 1125899906842624 >, U >::type pebi
Represents the type of class U with the binary 'pebi' prefix appended.
Definition units.h:1488
typename units::detail::prefix< std::ratio< 1152921504606846976 >, U >::type exbi
Represents the type of class U with the binary 'exbi' prefix appended.
Definition units.h:1489
typename units::detail::prefix< std::pico, U >::type pico
Represents the type of class U with the metric 'pico' prefix appended.
Definition units.h:1462
typename units::detail::prefix< std::atto, U >::type atto
Represents the type of class U with the metric 'atto' prefix appended.
Definition units.h:1460
typename units::detail::prefix< std::tera, U >::type tera
Represents the type of class U with the metric 'tera' prefix appended.
Definition units.h:1473
typename units::detail::prefix< std::mega, U >::type mega
Represents the type of class U with the metric 'mega' prefix appended.
Definition units.h:1471
typename units::detail::prefix< std::hecto, U >::type hecto
Represents the type of class U with the metric 'hecto' prefix appended.
Definition units.h:1469
typename units::detail::prefix< std::nano, U >::type nano
Represents the type of class U with the metric 'nano' prefix appended.
Definition units.h:1463
typename units::detail::prefix< std::ratio< 1099511627776 >, U >::type tebi
Represents the type of class U with the binary 'tebi' prefix appended.
Definition units.h:1487
typename units::detail::prefix< std::centi, U >::type centi
Represents the type of class U with the metric 'centi' prefix appended.
Definition units.h:1466
typename units::detail::prefix< std::femto, U >::type femto
Represents the type of class U with the metric 'femto' prefix appended.
Definition units.h:1461
typename units::detail::prefix< std::ratio< 1024 >, U >::type kibi
Represents the type of class U with the binary 'kibi' prefix appended.
Definition units.h:1484
typename units::detail::sqrt_impl< U, Eps >::type square_root
represents the square root of type class U.
Definition units.h:1384
UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Maximum value.
Definition units.h:4796
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition units.h:4845
angle::radian_t acosh(const ScalarUnit x) noexcept
Compute arc hyperbolic cosine.
Definition units.h:4446
UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Minimum value.
Definition units.h:4814
UnitTypeLhs hypot(const UnitTypeLhs &x, const UnitTypeRhs &y)
Computes the square root of the sum-of-squares of x and y.
Definition units.h:4658
dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition units.h:4504
dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
Compute hyperbolic sine.
Definition units.h:4412
UnitType round(const UnitType x) noexcept
Round to nearest.
Definition units.h:4733
dimensionless::scalar_t tan(const AngleUnit angle) noexcept
Compute tangent.
Definition units.h:4303
UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
Compute remainder of division.
Definition units.h:4703
angle::radian_t asin(const ScalarUnit x) noexcept
Compute arc sine.
Definition units.h:4335
auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x *y)
Multiply-add.
Definition units.h:4861
UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Positive difference.
Definition units.h:4779
angle::radian_t atanh(const ScalarUnit x) noexcept
Compute arc hyperbolic tangent.
Definition units.h:4480
angle::radian_t acos(const ScalarUnit x) noexcept
Compute arc cosine.
Definition units.h:4319
angle::radian_t atan2(const Y y, const X x) noexcept
Compute arc tangent with two parameters.
Definition units.h:4372
dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit *intpart) noexcept
Break into fractional and integral parts.
Definition units.h:4553
dimensionless::scalar_t exp2(const ScalarUnit x) noexcept
Compute binary exponential function.
Definition units.h:4571
dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
Compute exponential minus one.
Definition units.h:4586
UnitType fabs(const UnitType x) noexcept
Compute absolute value.
Definition units.h:4832
dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
Compute hyperbolic cosine.
Definition units.h:4395
angle::radian_t atan(const ScalarUnit x) noexcept
Compute arc tangent.
Definition units.h:4355
dimensionless::scalar_t log2(const ScalarUnit x) noexcept
Compute binary logarithm.
Definition units.h:4617
dimensionless::scalar_t cos(const AngleUnit angle) noexcept
Compute cosine.
Definition units.h:4270
dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
Compute hyperbolic tangent.
Definition units.h:4429
UnitType floor(const UnitType x) noexcept
Round down value.
Definition units.h:4689
UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Copy sign.
Definition units.h:4752
UnitType trunc(const UnitType x) noexcept
Truncate value.
Definition units.h:4718
auto sqrt(const UnitType &value) noexcept -> unit_t< square_root< typename units::traits::unit_t_traits< UnitType >::unit_type >, typename units::traits::unit_t_traits< UnitType >::underlying_type, linear_scale >
computes the square root of value
Definition units.h:4642
dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition units.h:4520
dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
Compute logarithm plus one.
Definition units.h:4602
dimensionless::scalar_t log10(const ScalarUnit x) noexcept
Compute common logarithm.
Definition units.h:4535
dimensionless::scalar_t sin(const AngleUnit angle) noexcept
Compute sine.
Definition units.h:4287
UnitType ceil(const UnitType x) noexcept
Round up value.
Definition units.h:4676
angle::radian_t asinh(const ScalarUnit x) noexcept
Compute arc hyperbolic sine.
Definition units.h:4462
typename units::detail::compound_impl< U, Us... >::type compound_unit
Represents a unit type made up from other units.
Definition units.h:1417
STL namespace.
namespace for unit types and containers representing acceleration values
namespace for unit types and containers representing angle values
namespace for unit types and containers representing angular velocity values
namespace for unit types and containers representing area values
namespace for unit types and containers representing capacitance values
namespace representing the implemented base and derived unit types.
Definition units.h:772
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > time_unit
Represents an SI base unit of time.
Definition units.h:781
base_unit< detail::meter_ratio< 0 >, std::ratio< 1 > > mass_unit
Represents an SI base unit of mass.
Definition units.h:780
base_unit< detail::meter_ratio<-3 >, std::ratio< 1 > > density_unit
Represents an SI derived unit of density.
Definition units.h:817
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 >, std::ratio< 0 >, std::ratio<-1 > > magnetic_flux_unit
Represents an SI derived unit of magnetic flux.
Definition units.h:805
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 >, std::ratio< 1 > > angular_velocity_unit
Represents an SI derived unit of angular velocity.
Definition units.h:793
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-3 >, std::ratio< 0 >, std::ratio<-2 > > impedance_unit
Represents an SI derived unit of impedance.
Definition units.h:803
base_unit< detail::meter_ratio< 1 > > length_unit
Represents an SI base unit of length.
Definition units.h:779
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > luminous_intensity_unit
Represents an SI base unit of luminous intensity.
Definition units.h:786
base_unit concentration_unit
Represents a unit of concentration.
Definition units.h:818
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > energy_unit
Represents an SI derived unit of energy.
Definition units.h:799
base_unit< detail::meter_ratio< 3 > > volume_unit
Represents an SI derived unit of volume.
Definition units.h:816
base_unit< detail::meter_ratio<-2 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 2 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > illuminance_unit
Represents an SI derived unit of illuminance.
Definition units.h:809
base_unit dimensionless_unit
Represents a quantity with no dimension.
Definition units.h:775
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > data_unit
Represents a unit of data size.
Definition units.h:819
base_unit< detail::meter_ratio<-1 >, std::ratio< 1 >, std::ratio<-2 > > pressure_unit
Represents an SI derived unit of pressure.
Definition units.h:797
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-2 > > acceleration_unit
Represents an SI derived unit of acceleration.
Definition units.h:794
base_unit scalar_unit
Represents a quantity with no dimension.
Definition units.h:774
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-3 > > power_unit
Represents an SI derived unit of power.
Definition units.h:800
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > frequency_unit
Represents an SI derived unit of frequency.
Definition units.h:791
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > angle_unit
Represents an SI base unit of angle.
Definition units.h:782
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > current_unit
Represents an SI base unit of current.
Definition units.h:783
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 1 >, std::ratio< 0 >, std::ratio< 1 > > charge_unit
Represents an SI derived unit of charge.
Definition units.h:798
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 2 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 > > solid_angle_unit
Represents an SI derived unit of solid angle.
Definition units.h:790
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > substance_unit
Represents an SI base unit of amount of substance.
Definition units.h:785
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-3 > > jerk_unit
Represents an SI derived unit of jerk.
Definition units.h:795
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-3 >, std::ratio< 0 >, std::ratio<-1 > > voltage_unit
Represents an SI derived unit of voltage.
Definition units.h:801
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > radioactivity_unit
Represents an SI derived unit of radioactivity.
Definition units.h:810
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 2 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > luminous_flux_unit
Represents an SI derived unit of luminous flux.
Definition units.h:808
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > torque_unit
Represents an SI derived unit of torque.
Definition units.h:814
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 >, std::ratio< 0 >, std::ratio<-2 > > inductance_unit
Represents an SI derived unit of inductance.
Definition units.h:807
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-1 > > velocity_unit
Represents an SI derived unit of velocity.
Definition units.h:792
base_unit< detail::meter_ratio< 1 >, std::ratio< 1 >, std::ratio<-2 > > force_unit
Represents an SI derived unit of force.
Definition units.h:796
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > data_transfer_rate_unit
Represents a unit of data transfer rate.
Definition units.h:820
base_unit< detail::meter_ratio<-2 >, std::ratio<-1 >, std::ratio< 4 >, std::ratio< 0 >, std::ratio< 2 > > capacitance_unit
Represents an SI derived unit of capacitance.
Definition units.h:802
base_unit< detail::meter_ratio<-2 >, std::ratio<-1 >, std::ratio< 3 >, std::ratio< 0 >, std::ratio< 2 > > conductance_unit
Represents an SI derived unit of conductance.
Definition units.h:804
base_unit< detail::meter_ratio< 0 >, std::ratio< 1 >, std::ratio<-2 >, std::ratio< 0 >, std::ratio<-1 > > magnetic_field_strength_unit
Represents an SI derived unit of magnetic field strength.
Definition units.h:806
base_unit< detail::meter_ratio< 2 > > area_unit
Represents an SI derived unit of area.
Definition units.h:815
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > temperature_unit
Represents an SI base unit of temperature.
Definition units.h:784
namespace for unit types and containers representing charge values
namespace for unit types and containers representing concentration values
namespace for unit types and containers representing conductance values
namespace for physical constants like PI and Avogadro's Number.
Definition units.h:4194
static constexpr const unit_t< compound_unit< cubed< length::meters >, inverse< mass::kilogram >, inverse< squared< time::seconds > > > > G(6.67408e-11)
Newtonian constant of gravitation.
static constexpr const unit_t< compound_unit< capacitance::farad, inverse< length::meter > > > epsilon0(1.0/(mu0 *math::cpow< 2 >(c)))
vacuum permitivity.
static constexpr const mass::kilogram_t m_e(9.10938356e-31)
electron mass.
static constexpr const unit_t< compound_unit< energy::joules, inverse< temperature::kelvin > > > k_B(R/N_A)
Boltzmann constant.
static constexpr const unit_t< compound_unit< power::watts, inverse< area::square_meters >, inverse< squared< squared< temperature::kelvin > > > > > sigma((2 *math::cpow< 5 >(pi) *math::cpow< 4 >(R))/(15 *math::cpow< 3 >(h) *math::cpow< 2 >(c) *math::cpow< 4 >(N_A)))
Stefan-Boltzmann constant.
static constexpr const unit_t< compound_unit< energy::joules, inverse< temperature::kelvin >, inverse< substance::moles > > > R(8.3144598)
Gas constant.
static constexpr const unit_t< inverse< substance::mol > > N_A(6.022140857e23)
Avagadro's Number.
static constexpr const unit_t< compound_unit< force::newtons, area::square_meter, inverse< squared< charge::coulomb > > > > k_e(1.0/(4 *pi *epsilon0))
Coulomb's constant.
static constexpr const unit_t< compound_unit< force::newtons, inverse< squared< current::ampere > > > > mu0(pi *4.0e-7 *force::newton_t(1)/units::math::cpow< 2 >(current::ampere_t(1)))
vacuum permeability.
static constexpr const unit_t< compound_unit< energy::joules, inverse< magnetic_field_strength::tesla > > > mu_B(e *h/(4 *pi *m_e))
Bohr magneton.
static constexpr const unit_t< compound_unit< energy::joule, time::seconds > > h(6.626070040e-34)
Planck constant.
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
static constexpr const unit_t< PI > pi(1)
Ratio of a circle's circumference to its diameter.
static constexpr const impedance::ohm_t Z0(mu0 *c)
characteristic impedance of vacuum.
static constexpr const mass::kilogram_t m_p(1.672621898e-27)
proton mass.
static constexpr const charge::coulomb_t e(1.6021766208e-19)
elementary charge.
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
namespace for unit types and containers representing current values
namespace for unit types and containers representing data values
namespace for unit types and containers representing data values
namespace for unit types and containers representing density values
namespace for unit types and containers for units that have no dimension (scalar units)
Definition units.h:2496
namespace for unit types and containers representing energy values
namespace for unit types and containers representing force values
namespace for unit types and containers representing frequency values
namespace for unit types and containers representing illuminance values
namespace for unit types and containers representing impedance values
namespace for unit types and containers representing inductance values
namespace for unit types and containers representing jerk values
namespace for unit types and containers representing length values
namespace for unit types and containers representing luminous_flux values
namespace for unit types and containers representing luminous_intensity values
namespace for unit types and containers representing magnetic_field_strength values
namespace for unit types and containers representing magnetic_flux values
namespace for unit types and containers representing mass values
namespace for unit-enabled versions of the <cmath> library
Definition units.h:2800
constexpr auto cpow(const UnitType &value) noexcept -> unit_t< typename units::detail::power_of_unit< power, typename units::traits::unit_t_traits< UnitType >::unit_type >::type, typename units::traits::unit_t_traits< UnitType >::underlying_type, linear_scale >
computes the value of value raised to the power as a constexpr
Definition units.h:2824
auto pow(const UnitType &value) noexcept -> unit_t< typename units::detail::power_of_unit< power, typename units::traits::unit_t_traits< UnitType >::unit_type >::type, typename units::traits::unit_t_traits< UnitType >::underlying_type, linear_scale >
computes the value of value raised to the power
Definition units.h:2809
namespace for unit types and containers representing power values
namespace for unit types and containers representing pressure values
namespace for unit types and containers representing radiation values
namespace for unit types and containers representing solid_angle values
namespace for unit types and containers representing substance values
namespace for unit types and containers representing temperature values
namespace for unit types and containers representing time values
namespace for unit types and containers representing torque values
namespace representing type traits which can access the properties of types provided by the units lib...
Definition units.h:570
typename units::detail::base_unit_of_impl< U >::type base_unit_of
Trait which returns the base_unit type that a unit is originally derived from.
Definition units.h:915
namespace for unit types and containers representing velocity values
namespace for unit types and containers representing voltage values
namespace for unit types and containers representing volume values
Unit Conversion Library namespace.
Definition units.h:99
constexpr dimensionless::scalar_t operator/(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs) noexcept
Division for convertible unit_t types with a linear scale.
Definition units.h:2631
constexpr auto operator*(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs) noexcept -> unit_t< compound_unit< squared< typename units::traits::unit_t_traits< UnitTypeLhs >::unit_type > > >
Multiplication type for convertible unit_t types with a linear scale.
Definition units.h:2575
Class representing SI base unit types.
Definition units.h:741
unit_t scale for representing decibel values.
Definition units.h:2844
T m_value
linearized value
Definition units.h:2858
unit_t scale which is linear
Definition units.h:2474
constexpr T operator()() const noexcept
returns value.
Definition units.h:2485
double m_value
Definition units.h:2487
constexpr linear_scale()=default
default constructor.
constexpr linear_scale(const T &value, Args &&...) noexcept
constructor.
Definition units.h:2484
Trait which tests whether a type is inherited from a decibel scale.
Definition units.h:2430
Trait which tests whether a type is inherited from a linear scale.
Definition units.h:2412
Definition units.h:3492
Trait which tests if a class is a base_unit type.
Definition units.h:678
Trait which tests whether two container types derived from unit_t are convertible to each other.
Definition units.h:1824
Trait which checks whether two units can be converted to each other.
Definition units.h:1512
Trait which tests that class T meets the requirements for a non-linear scale.
Definition units.h:1747
Trait that tests whether a type represents a std::ratio.
Definition units.h:580
Trait which tests whether two types has the same non-linear scale.
Definition units.h:2450
Traits which tests if a class is a unit
Definition units.h:1862
Trait which tests whether type T is a unit_value_t with a unit type in the given category.
Definition units.h:3050
Trait which tests whether a type is a unit_value_t representing the given unit type.
Definition units.h:3040
Traits which tests if a class is a unit
Definition units.h:704
adds two unit_value_t types at compile-time
Definition units.h:3089
static constexpr const unit_t< unit_type > value() noexcept
Value of sum.
Definition units.h:3104
divides two unit_value_t types at compile-time
Definition units.h:3241
static constexpr const unit_t< unit_type > value() noexcept
Value of quotient.
Definition units.h:3255
multiplies two unit_value_t types at compile-time
Definition units.h:3191
static constexpr const unit_t< unit_type > value() noexcept
Value of product.
Definition units.h:3205
raises unit_value_to a power at compile-time
Definition units.h:3287
static constexpr const unit_t< unit_type > value() noexcept
Value of exponentiation.
Definition units.h:3302
calculates square root of unit_value_t at compile-time
Definition units.h:3334
static constexpr const unit_t< unit_type > value() noexcept
Value of square root.
Definition units.h:3349
subtracts two unit_value_t types at compile-time
Definition units.h:3138
static constexpr const unit_t< unit_type > value() noexcept
Value of difference.
Definition units.h:3154
Stores a rational unit value as a compile-time constant.
Definition units.h:3019
Type representing an arbitrary unit.
Definition units.h:867
#define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation,...)
Macro for generating the boiler-plate code needed for a new unit.
Definition units.h:279
#define UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation,...)
Macro for generating the boiler-plate code needed for a new unit, including its metric prefixes from ...
Definition units.h:431
#define UNIT_ADD_CATEGORY_TRAIT(unitCategory)
Macro to create the is_category_unit type trait.
Definition units.h:370
#define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)
Macro to create decibel container and literals for an existing unit type.
Definition units.h:321
#define UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation,...)
Macro for generating the boiler-plate code needed for a new unit, including its metric prefixes from ...
Definition units.h:396