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(_MSC_VER) || _MSC_VER > 1800
64# define UNIT_HAS_LITERAL_SUPPORT
65# define UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT
66#endif
67
68#ifndef UNIT_LIB_DEFAULT_TYPE
69# define UNIT_LIB_DEFAULT_TYPE double
70#endif
71
72//--------------------
73// INCLUDES
74//--------------------
75
76#include <chrono>
77#include <cstddef>
78#include <ratio>
79#include <type_traits>
80#include <cstdint>
81#include <cmath>
82#include <limits>
83
84#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
85 #include <iostream>
86 #include <string>
87 #include <locale>
88
89 //------------------------------
90 // STRING FORMATTER
91 //------------------------------
92
93 namespace units
94 {
95 namespace detail
96 {
97 template <typename T> std::string to_string(const T& t)
98 {
99 std::string str{ std::to_string(t) };
100 int offset{ 1 };
101
102 // remove trailing decimal points for integer value units. Locale aware!
103 struct lconv * lc;
104 lc = localeconv();
105 char decimalPoint = *lc->decimal_point;
106 if (str.find_last_not_of('0') == str.find(decimalPoint)) { offset = 0; }
107 str.erase(str.find_last_not_of('0') + offset, std::string::npos);
108 return str;
109 }
110 }
111 }
112#endif
113
114namespace units
115{
116 template<typename T> inline constexpr const char* name(const T&);
117 template<typename T> inline constexpr const char* abbreviation(const T&);
118}
119
120//------------------------------
121// MACROS
122//------------------------------
123
140#define UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, /*definition*/...)\
141 namespace namespaceName\
142 {\
143 typedef __VA_ARGS__ namePlural; \
144 typedef namePlural nameSingular; \
145 typedef namePlural abbreviation; \
146 }
147
155#define UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
156 namespace namespaceName\
157 {\
158 typedef unit_t<nameSingular> nameSingular ## _t; \
159 }
160
169#define UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular, underlyingType)\
170 namespace namespaceName\
171 {\
172 typedef unit_t<nameSingular,underlyingType> nameSingular ## _t; \
173 }
184#if defined(UNIT_LIB_DISABLE_IOSTREAM)
185 #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)
186#else
187 #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)\
188 namespace namespaceName\
189 {\
190 inline std::ostream& operator<<(std::ostream& os, const nameSingular ## _t& obj) \
191 {\
192 os << obj() << " "#abbrev; return os; \
193 }\
194 inline std::string to_string(const nameSingular ## _t& obj)\
195 {\
196 return units::detail::to_string(obj()) + std::string(" "#abbrev);\
197 }\
198 }
199#endif
200
211#define UNIT_ADD_NAME(namespaceName, nameSingular, abbrev)\
212template<> inline constexpr const char* name(const namespaceName::nameSingular ## _t&)\
213{\
214 return #nameSingular;\
215}\
216template<> inline constexpr const char* abbreviation(const namespaceName::nameSingular ## _t&)\
217{\
218 return #abbrev;\
219}
220
232#if defined(UNIT_HAS_LITERAL_SUPPORT)
233 #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)\
234 namespace literals\
235 {\
236 inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation(long double d)\
237 {\
238 return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
239 }\
240 inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation (unsigned long long d)\
241 {\
242 return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
243 }\
244 }
245#else
246 #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)
247#endif
248
268#define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
269 UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
270 UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
271 UNIT_ADD_NAME(namespaceName,nameSingular, abbreviation)\
272 UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
273 UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
274
295#define UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName, nameSingular, namePlural, abbreviation, underlyingType, /*definition*/...)\
296 UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
297 UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular,underlyingType)\
298 UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
299 UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
300
310#define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)\
311 namespace namespaceName\
312 {\
313 typedef unit_t<nameSingular, UNIT_LIB_DEFAULT_TYPE, units::decibel_scale> abbreviation ## _t; \
314 }\
315 UNIT_ADD_IO(namespaceName, abbreviation, abbreviation)\
316 UNIT_ADD_LITERALS(namespaceName, abbreviation, abbreviation)
317
327#define UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
328 namespace traits\
329 {\
330\
331 namespace detail\
332 {\
333 template<typename T> struct is_ ## unitCategory ## _unit_impl : std::false_type {};\
334 template<typename C, typename U, typename P, typename T>\
335 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 {};\
336 template<typename U, typename S, template<typename> class N>\
337 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 {};\
338 }\
339\
340 }
341
342#if defined(UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT)
343#define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
344 namespace traits\
345 {\
346 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> {};\
347 }
348#else
349#define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
350 namespace traits\
351 {\
352 template<typename T1, typename T2 = T1, typename T3 = T1>\
353 struct is_ ## unitCategory ## _unit : std::integral_constant<bool, units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T1>::type>::value &&\
354 units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T2>::type>::value &&\
355 units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T3>::type>::value>{};\
356 }
357#endif
358
359#define UNIT_ADD_CATEGORY_TRAIT(unitCategory)\
360 UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
361\
362\
363\
364\
365 UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)
366
385#define UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
386 UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
387 UNIT_ADD(namespaceName, femto ## nameSingular, femto ## namePlural, f ## abbreviation, femto<namePlural>)\
388 UNIT_ADD(namespaceName, pico ## nameSingular, pico ## namePlural, p ## abbreviation, pico<namePlural>)\
389 UNIT_ADD(namespaceName, nano ## nameSingular, nano ## namePlural, n ## abbreviation, nano<namePlural>)\
390 UNIT_ADD(namespaceName, micro ## nameSingular, micro ## namePlural, u ## abbreviation, micro<namePlural>)\
391 UNIT_ADD(namespaceName, milli ## nameSingular, milli ## namePlural, m ## abbreviation, milli<namePlural>)\
392 UNIT_ADD(namespaceName, centi ## nameSingular, centi ## namePlural, c ## abbreviation, centi<namePlural>)\
393 UNIT_ADD(namespaceName, deci ## nameSingular, deci ## namePlural, d ## abbreviation, deci<namePlural>)\
394 UNIT_ADD(namespaceName, deca ## nameSingular, deca ## namePlural, da ## abbreviation, deca<namePlural>)\
395 UNIT_ADD(namespaceName, hecto ## nameSingular, hecto ## namePlural, h ## abbreviation, hecto<namePlural>)\
396 UNIT_ADD(namespaceName, kilo ## nameSingular, kilo ## namePlural, k ## abbreviation, kilo<namePlural>)\
397 UNIT_ADD(namespaceName, mega ## nameSingular, mega ## namePlural, M ## abbreviation, mega<namePlural>)\
398 UNIT_ADD(namespaceName, giga ## nameSingular, giga ## namePlural, G ## abbreviation, giga<namePlural>)\
399 UNIT_ADD(namespaceName, tera ## nameSingular, tera ## namePlural, T ## abbreviation, tera<namePlural>)\
400 UNIT_ADD(namespaceName, peta ## nameSingular, peta ## namePlural, P ## abbreviation, peta<namePlural>)\
401
420#define UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
421 UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
422 UNIT_ADD(namespaceName, kibi ## nameSingular, kibi ## namePlural, Ki ## abbreviation, kibi<namePlural>)\
423 UNIT_ADD(namespaceName, mebi ## nameSingular, mebi ## namePlural, Mi ## abbreviation, mebi<namePlural>)\
424 UNIT_ADD(namespaceName, gibi ## nameSingular, gibi ## namePlural, Gi ## abbreviation, gibi<namePlural>)\
425 UNIT_ADD(namespaceName, tebi ## nameSingular, tebi ## namePlural, Ti ## abbreviation, tebi<namePlural>)\
426 UNIT_ADD(namespaceName, pebi ## nameSingular, pebi ## namePlural, Pi ## abbreviation, pebi<namePlural>)\
427 UNIT_ADD(namespaceName, exbi ## nameSingular, exbi ## namePlural, Ei ## abbreviation, exbi<namePlural>)
428
429//--------------------
430// UNITS NAMESPACE
431//--------------------
432
437namespace units
438{
439 //----------------------------------
440 // DOXYGEN
441 //----------------------------------
442
486 //------------------------------
487 // FORWARD DECLARATIONS
488 //------------------------------
489 // DOXYGEN IGNORE
491 namespace constants
492 {
493 namespace detail
494 {
495 static constexpr const UNIT_LIB_DEFAULT_TYPE PI_VAL = 3.14159265358979323846264338327950288419716939937510;
496 }
497 } // END DOXYGEN IGNORE
499
500 //------------------------------
501 // RATIO TRAITS
502 //------------------------------
503 // DOXYGEN IGNORE
510 namespace detail
511 {
513 template<class T>
514 struct has_num_impl
515 {
516 template<class U>
517 static constexpr auto test(U*)->std::is_integral<decltype(U::num)> {return std::is_integral<decltype(U::num)>{}; }
518 template<typename>
519 static constexpr std::false_type test(...) { return std::false_type{}; }
520
521 using type = decltype(test<T>(0));
522 };
523 }
524
530 template<class T>
531 struct has_num : units::detail::has_num_impl<T>::type {};
532
533 namespace detail
534 {
536 template<class T>
537 struct has_den_impl
538 {
539 template<class U>
540 static constexpr auto test(U*)->std::is_integral<decltype(U::den)> { return std::is_integral<decltype(U::den)>{}; }
541 template<typename>
542 static constexpr std::false_type test(...) { return std::false_type{}; }
543
544 using type = decltype(test<T>(0));
545 };
546 }
547
553 template<class T>
554 struct has_den : units::detail::has_den_impl<T>::type {};
555 // END DOXYGEN IGNORE
557
558 namespace traits
559 {
565 template<class T>
566 struct is_ratio : std::integral_constant<bool,
567 has_num<T>::value &&
568 has_den<T>::value>
569 {};
570 }
571
572 //------------------------------
573 // UNIT TRAITS
574 //------------------------------
575 // DOXYGEN IGNORE
581 template<class ...>
582 struct void_t { typedef void type; };
583
587 template<bool...> struct bool_pack {};
588
592 template<bool... Args>
593 struct all_true : std::is_same<units::bool_pack<true, Args...>, units::bool_pack<Args..., true>> {}; // DOXYGEN IGNORE
595
599 namespace traits
600 {
601#ifdef FOR_DOXYGEN_PURPOSES_ONLY
609 template<class T>
610 struct unit_traits
611 {
612 typedef typename T::base_unit_type base_unit_type;
613 typedef typename T::conversion_ratio conversion_ratio;
614 typedef typename T::pi_exponent_ratio pi_exponent_ratio;
615 typedef typename T::translation_ratio translation_ratio;
616 };
617#endif // DOXYGEN IGNORE
622 template<class T, typename = void>
623 struct unit_traits
624 {
625 typedef void base_unit_type;
626 typedef void conversion_ratio;
627 typedef void pi_exponent_ratio;
628 typedef void translation_ratio;
629 };
630
631 template<class T>
632 struct unit_traits
633 <T, typename void_t<
634 typename T::base_unit_type,
635 typename T::conversion_ratio,
636 typename T::pi_exponent_ratio,
637 typename T::translation_ratio>::type>
638 {
639 typedef typename T::base_unit_type base_unit_type;
640 typedef typename T::conversion_ratio conversion_ratio;
641 typedef typename T::pi_exponent_ratio pi_exponent_ratio;
642 typedef typename T::translation_ratio translation_ratio;
643 }; // END DOXYGEN IGNORE
645 }
646 // DOXYGEN IGNORE
648 namespace detail
649 {
654 struct _base_unit_t {};
655 } // END DOXYGEN IGNORE
657
658 namespace traits
659 {
666 template<class T>
667 struct is_base_unit : std::is_base_of<units::detail::_base_unit_t, T> {};
668 }
669 // DOXYGEN IGNORE
671 namespace detail
672 {
677 struct _unit {};
678
679 template<std::intmax_t Num, std::intmax_t Den = 1>
680 using meter_ratio = std::ratio<Num, Den>;
681 } // END DOXYGEN IGNORE
683
684 namespace traits
685 {
692 template<class T>
693 struct is_unit : std::is_base_of<units::detail::_unit, T>::type {};
694 }
695 // end of TypeTraits
697
698 //------------------------------
699 // BASE UNIT CLASS
700 //------------------------------
701
720 template<class Meter = detail::meter_ratio<0>,
721 class Kilogram = std::ratio<0>,
722 class Second = std::ratio<0>,
723 class Radian = std::ratio<0>,
724 class Ampere = std::ratio<0>,
725 class Kelvin = std::ratio<0>,
726 class Mole = std::ratio<0>,
727 class Candela = std::ratio<0>,
728 class Byte = std::ratio<0>>
729 struct base_unit : units::detail::_base_unit_t
730 {
731 static_assert(traits::is_ratio<Meter>::value, "Template parameter `Meter` must be a `std::ratio` representing the exponent of meters the unit has");
732 static_assert(traits::is_ratio<Kilogram>::value, "Template parameter `Kilogram` must be a `std::ratio` representing the exponent of kilograms the unit has");
733 static_assert(traits::is_ratio<Second>::value, "Template parameter `Second` must be a `std::ratio` representing the exponent of seconds the unit has");
734 static_assert(traits::is_ratio<Ampere>::value, "Template parameter `Ampere` must be a `std::ratio` representing the exponent of amperes the unit has");
735 static_assert(traits::is_ratio<Kelvin>::value, "Template parameter `Kelvin` must be a `std::ratio` representing the exponent of kelvin the unit has");
736 static_assert(traits::is_ratio<Candela>::value, "Template parameter `Candela` must be a `std::ratio` representing the exponent of candelas the unit has");
737 static_assert(traits::is_ratio<Mole>::value, "Template parameter `Mole` must be a `std::ratio` representing the exponent of moles the unit has");
738 static_assert(traits::is_ratio<Radian>::value, "Template parameter `Radian` must be a `std::ratio` representing the exponent of radians the unit has");
739 static_assert(traits::is_ratio<Byte>::value, "Template parameter `Byte` must be a `std::ratio` representing the exponent of bytes the unit has");
740
741 typedef Meter meter_ratio;
742 typedef Kilogram kilogram_ratio;
743 typedef Second second_ratio;
744 typedef Radian radian_ratio;
745 typedef Ampere ampere_ratio;
746 typedef Kelvin kelvin_ratio;
747 typedef Mole mole_ratio;
748 typedef Candela candela_ratio;
749 typedef Byte byte_ratio;
750 };
751
752 //------------------------------
753 // UNIT CATEGORIES
754 //------------------------------
755
760 namespace category
761 {
762 // SCALAR (DIMENSIONLESS) TYPES
765
766 // SI BASE UNIT TYPES
767 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
770 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>> time_unit;
771 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> angle_unit;
772 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> current_unit;
773 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> temperature_unit;
774 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;
775 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;
776
777 // SI DERIVED UNIT TYPES
778 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
779 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;
780 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> frequency_unit;
781 typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-1>> velocity_unit;
782 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>, std::ratio<1>> angular_velocity_unit;
783 typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-2>> acceleration_unit;
784 typedef base_unit<detail::meter_ratio<1>, std::ratio<1>, std::ratio<-2>> force_unit;
785 typedef base_unit<detail::meter_ratio<-1>, std::ratio<1>, std::ratio<-2>> pressure_unit;
786 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<1>> charge_unit;
787 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> energy_unit;
788 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>> power_unit;
789 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-1>> voltage_unit;
790 typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<4>, std::ratio<0>, std::ratio<2>> capacitance_unit;
791 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-2>> impedance_unit;
792 typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<3>, std::ratio<0>, std::ratio<2>> conductance_unit;
793 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_flux_unit;
794 typedef base_unit<detail::meter_ratio<0>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_field_strength_unit;
795 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-2>> inductance_unit;
796 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;
797 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;
798 typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> radioactivity_unit;
799
800 // OTHER UNIT TYPES
801 // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
802 typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> torque_unit;
805 typedef base_unit<detail::meter_ratio<-3>, std::ratio<1>> density_unit;
807 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;
808 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;
809 }
810
811 //------------------------------
812 // UNIT CLASSES
813 //------------------------------
814 // DOXYGEN IGNORE
819 template <class, class, class, class> struct unit;
820 template<class Conversion, class... Exponents, class PiExponent, class Translation>
821 struct unit<Conversion, base_unit<Exponents...>, PiExponent, Translation> : units::detail::_unit
822 {
823 static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
824 static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
825 static_assert(traits::is_ratio<Translation>::value, "Template parameter `Translation` must be a `std::ratio` representing an additive translation required by the unit conversion.");
826
827 typedef typename units::base_unit<Exponents...> base_unit_type;
828 typedef Conversion conversion_ratio;
829 typedef Translation translation_ratio;
830 typedef PiExponent pi_exponent_ratio;
831 }; // END DOXYGEN IGNORE
833
853 template<class Conversion, class BaseUnit, class PiExponent = std::ratio<0>, class Translation = std::ratio<0>>
854 struct unit : units::detail::_unit
855 {
856 static_assert(traits::is_unit<BaseUnit>::value, "Template parameter `BaseUnit` must be a `unit` type.");
857 static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
858 static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
859
860 typedef typename units::traits::unit_traits<BaseUnit>::base_unit_type base_unit_type;
861 typedef typename std::ratio_multiply<typename BaseUnit::conversion_ratio, Conversion> conversion_ratio;
862 typedef typename std::ratio_add<typename BaseUnit::pi_exponent_ratio, PiExponent> pi_exponent_ratio;
863 typedef typename std::ratio_add<std::ratio_multiply<typename BaseUnit::conversion_ratio, Translation>, typename BaseUnit::translation_ratio> translation_ratio;
864 };
865
866 //------------------------------
867 // BASE UNIT MANIPULATORS
868 //------------------------------
869 // DOXYGEN IGNORE
871 namespace detail
872 {
878 template<class> struct base_unit_of_impl;
879 template<class Conversion, class BaseUnit, class PiExponent, class Translation>
880 struct base_unit_of_impl<unit<Conversion, BaseUnit, PiExponent, Translation>> : base_unit_of_impl<BaseUnit> {};
881 template<class... Exponents>
882 struct base_unit_of_impl<base_unit<Exponents...>>
883 {
884 typedef base_unit<Exponents...> type;
885 };
886 template<>
887 struct base_unit_of_impl<void>
888 {
889 typedef void type;
890 };
891 } // END DOXYGEN IGNORE
893
894 namespace traits
895 {
902 template<class U>
903 using base_unit_of = typename units::detail::base_unit_of_impl<U>::type;
904 }
905 // DOXYGEN IGNORE
907 namespace detail
908 {
914 template<class, class> struct base_unit_multiply_impl;
915 template<class... Exponents1, class... Exponents2>
916 struct base_unit_multiply_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
918 };
919
923 template<class U1, class U2>
924 using base_unit_multiply = typename base_unit_multiply_impl<U1, U2>::type;
925
931 template<class, class> struct base_unit_divide_impl;
932 template<class... Exponents1, class... Exponents2>
933 struct base_unit_divide_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
934 using type = base_unit<std::ratio_subtract<Exponents1, Exponents2>...>;
935 };
936
940 template<class U1, class U2>
941 using base_unit_divide = typename base_unit_divide_impl<U1, U2>::type;
942
948 template<class> struct inverse_base_impl;
949
950 template<class... Exponents>
951 struct inverse_base_impl<base_unit<Exponents...>> {
952 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<-1>>...>;
953 };
954
959 template<class U> using inverse_base = typename inverse_base_impl<U>::type;
960
966 template<class U> struct squared_base_impl;
967 template<class... Exponents>
968 struct squared_base_impl<base_unit<Exponents...>> {
969 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<2>>...>;
970 };
971
976 template<class U> using squared_base = typename squared_base_impl<U>::type;
977
983 template<class U> struct cubed_base_impl;
984 template<class... Exponents>
985 struct cubed_base_impl<base_unit<Exponents...>> {
986 using type = base_unit<std::ratio_multiply<Exponents, std::ratio<3>>...>;
987 };
988
993 template<class U> using cubed_base = typename cubed_base_impl<U>::type;
994
1000 template<class U> struct sqrt_base_impl;
1001 template<class... Exponents>
1002 struct sqrt_base_impl<base_unit<Exponents...>> {
1003 using type = base_unit<std::ratio_divide<Exponents, std::ratio<2>>...>;
1004 };
1005
1010 template<class U> using sqrt_base = typename sqrt_base_impl<U>::type;
1011
1017 template<class U> struct cbrt_base_impl;
1018 template<class... Exponents>
1019 struct cbrt_base_impl<base_unit<Exponents...>> {
1020 using type = base_unit<std::ratio_divide<Exponents, std::ratio<3>>...>;
1021 };
1022
1027 template<class U> using cbrt_base = typename cbrt_base_impl<U>::type;
1028 } // END DOXYGEN IGNORE
1030
1031 //------------------------------
1032 // UNIT MANIPULATORS
1033 //------------------------------
1034 // DOXYGEN IGNORE
1036 namespace detail
1037 {
1044 template<class Unit1, class Unit2>
1045 struct unit_multiply_impl
1046 {
1047 using type = unit < std::ratio_multiply<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1048 base_unit_multiply <traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1049 std::ratio_add<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1050 std::ratio < 0 >> ;
1051 };
1052
1057 template<class U1, class U2>
1058 using unit_multiply = typename unit_multiply_impl<U1, U2>::type;
1059
1066 template<class Unit1, class Unit2>
1067 struct unit_divide_impl
1068 {
1069 using type = unit < std::ratio_divide<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1070 base_unit_divide<traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1071 std::ratio_subtract<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1072 std::ratio < 0 >> ;
1073 };
1074
1079 template<class U1, class U2>
1080 using unit_divide = typename unit_divide_impl<U1, U2>::type;
1081
1088 template<class Unit>
1089 struct inverse_impl
1090 {
1091 using type = unit < std::ratio<Unit::conversion_ratio::den, Unit::conversion_ratio::num>,
1092 inverse_base<traits::base_unit_of<typename units::traits::unit_traits<Unit>::base_unit_type>>,
1093 std::ratio_multiply<typename units::traits::unit_traits<Unit>::pi_exponent_ratio, std::ratio<-1>>,
1094 std::ratio < 0 >> ; // inverses are rates or change, the translation factor goes away.
1095 };
1096 } // END DOXYGEN IGNORE
1098
1105 template<class U> using inverse = typename units::detail::inverse_impl<U>::type;
1106 // DOXYGEN IGNORE
1108 namespace detail
1109 {
1115 template<class Unit>
1116 struct squared_impl
1117 {
1118 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1119 using Conversion = typename Unit::conversion_ratio;
1120 using type = unit < std::ratio_multiply<Conversion, Conversion>,
1121 squared_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1122 std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1123 typename Unit::translation_ratio
1124 > ;
1125 };
1126 } // END DOXYGEN IGNORE
1128
1135 template<class U>
1136 using squared = typename units::detail::squared_impl<U>::type;
1137 // DOXYGEN IGNORE
1139 namespace detail
1140 {
1146 template<class Unit>
1147 struct cubed_impl
1148 {
1149 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1150 using Conversion = typename Unit::conversion_ratio;
1151 using type = unit < std::ratio_multiply<Conversion, std::ratio_multiply<Conversion, Conversion>>,
1152 cubed_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1153 std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<3>>,
1154 typename Unit::translation_ratio> ;
1155 };
1156 } // END DOXYGEN IGNORE
1158
1165 template<class U>
1166 using cubed = typename units::detail::cubed_impl<U>::type;
1167 // DOXYGEN IGNORE
1169 namespace detail
1170 {
1171 //----------------------------------
1172 // RATIO_SQRT IMPLEMENTATION
1173 //----------------------------------
1174
1175 using Zero = std::ratio<0>;
1176 using One = std::ratio<1>;
1177 template <typename R> using Square = std::ratio_multiply<R, R>;
1178
1179 // Find the largest std::integer N such that Predicate<N>::value is true.
1180 template <template <std::intmax_t N> class Predicate, typename enabled = void>
1181 struct BinarySearch {
1182 template <std::intmax_t N>
1183 struct SafeDouble_ {
1184 static constexpr const std::intmax_t value = 2 * N;
1185 static_assert(value > 0, "Overflows when computing 2 * N");
1186 };
1187
1188 template <intmax_t Lower, intmax_t Upper, typename Condition1 = void, typename Condition2 = void>
1189 struct DoubleSidedSearch_ : DoubleSidedSearch_<Lower, Upper,
1190 std::integral_constant<bool, (Upper - Lower == 1)>,
1191 std::integral_constant<bool, ((Upper - Lower>1 && Predicate<Lower + (Upper - Lower) / 2>::value))>> {};
1192
1193 template <intmax_t Lower, intmax_t Upper>
1194 struct DoubleSidedSearch_<Lower, Upper, std::false_type, std::false_type> : DoubleSidedSearch_<Lower, Lower + (Upper - Lower) / 2> {};
1195
1196 template <intmax_t Lower, intmax_t Upper, typename Condition2>
1197 struct DoubleSidedSearch_<Lower, Upper, std::true_type, Condition2> : std::integral_constant<intmax_t, Lower>{};
1198
1199 template <intmax_t Lower, intmax_t Upper, typename Condition1>
1200 struct DoubleSidedSearch_<Lower, Upper, Condition1, std::true_type> : DoubleSidedSearch_<Lower + (Upper - Lower) / 2, Upper>{};
1201
1202 template <std::intmax_t Lower, class enabled1 = void>
1203 struct SingleSidedSearch_ : SingleSidedSearch_<Lower, std::integral_constant<bool, Predicate<SafeDouble_<Lower>::value>::value>>{};
1204
1205 template <std::intmax_t Lower>
1206 struct SingleSidedSearch_<Lower, std::false_type> : DoubleSidedSearch_<Lower, SafeDouble_<Lower>::value> {};
1207
1208 template <std::intmax_t Lower>
1209 struct SingleSidedSearch_<Lower, std::true_type> : SingleSidedSearch_<SafeDouble_<Lower>::value>{};
1210
1211 static constexpr const std::intmax_t value = SingleSidedSearch_<1>::value;
1212 };
1213
1214 template <template <std::intmax_t N> class Predicate>
1215 struct BinarySearch<Predicate, std::enable_if_t<!Predicate<1>::value>> : std::integral_constant<std::intmax_t, 0>{};
1216
1217 // Find largest std::integer N such that N<=sqrt(R)
1218 template <typename R>
1219 struct Integer {
1220 template <std::intmax_t N> using Predicate_ = std::ratio_less_equal<std::ratio<N>, std::ratio_divide<R, std::ratio<N>>>;
1221 static constexpr const std::intmax_t value = BinarySearch<Predicate_>::value;
1222 };
1223
1224 template <typename R>
1225 struct IsPerfectSquare {
1226 static constexpr const std::intmax_t DenSqrt_ = Integer<std::ratio<R::den>>::value;
1227 static constexpr const std::intmax_t NumSqrt_ = Integer<std::ratio<R::num>>::value;
1228 static constexpr const bool value =( DenSqrt_ * DenSqrt_ == R::den && NumSqrt_ * NumSqrt_ == R::num);
1229 using Sqrt = std::ratio<NumSqrt_, DenSqrt_>;
1230 };
1231
1232 // Represents sqrt(P)-Q.
1233 template <typename Tp, typename Tq>
1234 struct Remainder {
1235 using P = Tp;
1236 using Q = Tq;
1237 };
1238
1239 // Represents 1/R = I + Rem where R is a Remainder.
1240 template <typename R>
1241 struct Reciprocal {
1242 using P_ = typename R::P;
1243 using Q_ = typename R::Q;
1244 using Den_ = std::ratio_subtract<P_, Square<Q_>>;
1245 using A_ = std::ratio_divide<Q_, Den_>;
1246 using B_ = std::ratio_divide<P_, Square<Den_>>;
1247 static constexpr const std::intmax_t I_ = (A_::num + Integer<std::ratio_multiply<B_, Square<std::ratio<A_::den>>>>::value) / A_::den;
1248 using I = std::ratio<I_>;
1249 using Rem = Remainder<B_, std::ratio_subtract<I, A_>>;
1250 };
1251
1252 // Expands sqrt(R) to continued fraction:
1253 // f(x)=C1+1/(C2+1/(C3+1/(...+1/(Cn+x)))) = (U*x+V)/(W*x+1) and sqrt(R)=f(Rem).
1254 // The error |f(Rem)-V| = |(U-W*V)x/(W*x+1)| <= |U-W*V|*Rem <= |U-W*V|/I' where
1255 // I' is the std::integer part of reciprocal of Rem.
1256 template <typename Tr, std::intmax_t N>
1257 struct ContinuedFraction {
1258 template <typename T>
1259 using Abs_ = std::conditional_t<std::ratio_less<T, Zero>::value, std::ratio_subtract<Zero, T>, T>;
1260
1261 using R = Tr;
1262 using Last_ = ContinuedFraction<R, N - 1>;
1263 using Reciprocal_ = Reciprocal<typename Last_::Rem>;
1264 using Rem = typename Reciprocal_::Rem;
1265 using I_ = typename Reciprocal_::I;
1266 using Den_ = std::ratio_add<typename Last_::W, I_>;
1267 using U = std::ratio_divide<typename Last_::V, Den_>;
1268 using V = std::ratio_divide<std::ratio_add<typename Last_::U, std::ratio_multiply<typename Last_::V, I_>>, Den_>;
1269 using W = std::ratio_divide<One, Den_>;
1270 using Error = Abs_<std::ratio_divide<std::ratio_subtract<U, std::ratio_multiply<V, W>>, typename Reciprocal<Rem>::I>>;
1271 };
1272
1273 template <typename Tr>
1274 struct ContinuedFraction<Tr, 1> {
1275 using R = Tr;
1276 using U = One;
1277 using V = std::ratio<Integer<R>::value>;
1278 using W = Zero;
1279 using Rem = Remainder<R, V>;
1280 using Error = std::ratio_divide<One, typename Reciprocal<Rem>::I>;
1281 };
1282
1283 template <typename R, typename Eps, std::intmax_t N = 1, typename enabled = void>
1284 struct Sqrt_ : Sqrt_<R, Eps, N + 1> {};
1285
1286 template <typename R, typename Eps, std::intmax_t N>
1287 struct Sqrt_<R, Eps, N, std::enable_if_t<std::ratio_less_equal<typename ContinuedFraction<R, N>::Error, Eps>::value>> {
1288 using type = typename ContinuedFraction<R, N>::V;
1289 };
1290
1291 template <typename R, typename Eps, typename enabled = void>
1292 struct Sqrt {
1293 static_assert(std::ratio_greater_equal<R, Zero>::value, "R can't be negative");
1294 };
1295
1296 template <typename R, typename Eps>
1297 struct Sqrt<R, Eps, std::enable_if_t<std::ratio_greater_equal<R, Zero>::value && IsPerfectSquare<R>::value>> {
1298 using type = typename IsPerfectSquare<R>::Sqrt;
1299 };
1300
1301 template <typename R, typename Eps>
1302 struct Sqrt<R, Eps, std::enable_if_t<(std::ratio_greater_equal<R, Zero>::value && !IsPerfectSquare<R>::value)>> : Sqrt_<R, Eps>{};
1303 } // END DOXYGEN IGNORE
1305
1326 template<typename Ratio, std::intmax_t Eps = 10000000000>
1327 using ratio_sqrt = typename units::detail::Sqrt<Ratio, std::ratio<1, Eps>>::type;
1328 // DOXYGEN IGNORE
1330 namespace detail
1331 {
1337 template<class Unit, std::intmax_t Eps>
1338 struct sqrt_impl
1339 {
1340 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1341 using Conversion = typename Unit::conversion_ratio;
1342 using type = unit <ratio_sqrt<Conversion, Eps>,
1343 sqrt_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1344 std::ratio_divide<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1345 typename Unit::translation_ratio>;
1346 };
1347 } // END DOXYGEN IGNORE
1349
1371 template<class U, std::intmax_t Eps = 10000000000>
1372 using square_root = typename units::detail::sqrt_impl<U, Eps>::type;
1373
1374 //------------------------------
1375 // COMPOUND UNITS
1376 //------------------------------
1377 // DOXYGEN IGNORE
1379 namespace detail
1380 {
1386 template<class U, class... Us> struct compound_impl;
1387 template<class U> struct compound_impl<U> { using type = U; };
1388 template<class U1, class U2, class...Us>
1389 struct compound_impl<U1, U2, Us...>
1390 : compound_impl<unit_multiply<U1, U2>, Us...> {};
1391 } // END DOXYGEN IGNORE
1393
1404 template<class U, class... Us>
1405 using compound_unit = typename units::detail::compound_impl<U, Us...>::type;
1406
1407 //------------------------------
1408 // PREFIXES
1409 //------------------------------
1410 // DOXYGEN IGNORE
1412 namespace detail
1413 {
1418 template<class Ratio, class Unit>
1419 struct prefix
1420 {
1421 static_assert(traits::is_ratio<Ratio>::value, "Template parameter `Ratio` must be a `std::ratio`.");
1422 static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1423 typedef typename units::unit<Ratio, Unit> type;
1424 };
1425
1427 template <int N, class U>
1428 struct power_of_ratio
1429 {
1430 typedef std::ratio_multiply<U, typename power_of_ratio<N - 1, U>::type> type;
1431 };
1432
1434 template <class U>
1435 struct power_of_ratio<1, U>
1436 {
1437 typedef U type;
1438 };
1439 } // END DOXYGEN IGNORE
1441
1448 template<class U> using atto = typename units::detail::prefix<std::atto, U>::type;
1449 template<class U> using femto = typename units::detail::prefix<std::femto,U>::type;
1450 template<class U> using pico = typename units::detail::prefix<std::pico, U>::type;
1451 template<class U> using nano = typename units::detail::prefix<std::nano, U>::type;
1452 template<class U> using micro = typename units::detail::prefix<std::micro,U>::type;
1453 template<class U> using milli = typename units::detail::prefix<std::milli,U>::type;
1454 template<class U> using centi = typename units::detail::prefix<std::centi,U>::type;
1455 template<class U> using deci = typename units::detail::prefix<std::deci, U>::type;
1456 template<class U> using deca = typename units::detail::prefix<std::deca, U>::type;
1457 template<class U> using hecto = typename units::detail::prefix<std::hecto,U>::type;
1458 template<class U> using kilo = typename units::detail::prefix<std::kilo, U>::type;
1459 template<class U> using mega = typename units::detail::prefix<std::mega, U>::type;
1460 template<class U> using giga = typename units::detail::prefix<std::giga, U>::type;
1461 template<class U> using tera = typename units::detail::prefix<std::tera, U>::type;
1462 template<class U> using peta = typename units::detail::prefix<std::peta, U>::type;
1463 template<class U> using exa = typename units::detail::prefix<std::exa, U>::type;
1472 template<class U> using kibi = typename units::detail::prefix<std::ratio<1024>, U>::type;
1473 template<class U> using mebi = typename units::detail::prefix<std::ratio<1048576>, U>::type;
1474 template<class U> using gibi = typename units::detail::prefix<std::ratio<1073741824>, U>::type;
1475 template<class U> using tebi = typename units::detail::prefix<std::ratio<1099511627776>, U>::type;
1476 template<class U> using pebi = typename units::detail::prefix<std::ratio<1125899906842624>, U>::type;
1477 template<class U> using exbi = typename units::detail::prefix<std::ratio<1152921504606846976>, U>::type;
1480 //------------------------------
1481 // CONVERSION TRAITS
1482 //------------------------------
1483
1484 namespace traits
1485 {
1498 template<class U1, class U2>
1499 struct is_convertible_unit : std::is_same <traits::base_unit_of<typename units::traits::unit_traits<U1>::base_unit_type>,
1500 base_unit_of<typename units::traits::unit_traits<U2>::base_unit_type >> {};
1501 }
1502
1503 //------------------------------
1504 // CONVERSION FUNCTION
1505 //------------------------------
1506 // DOXYGEN IGNORE
1508 namespace detail
1509 {
1510 constexpr inline UNIT_LIB_DEFAULT_TYPE pow(UNIT_LIB_DEFAULT_TYPE x, unsigned long long y)
1511 {
1512 return y == 0 ? 1.0 : x * pow(x, y - 1);
1513 }
1514
1515 constexpr inline UNIT_LIB_DEFAULT_TYPE abs(UNIT_LIB_DEFAULT_TYPE x)
1516 {
1517 return x < 0 ? -x : x;
1518 }
1519
1521 template<class Ratio, class PiRatio, class Translation, bool piRequired, bool translationRequired, typename T>
1522 static inline constexpr T convert(const T& value, std::true_type, std::integral_constant<bool, piRequired>, std::integral_constant<bool, translationRequired>) noexcept
1523 {
1524 return value;
1525 }
1526
1527 template<std::size_t Ratio_num, std::size_t Ratio_den>
1528 struct normal_convert
1529 {
1530 template<typename T>
1531 inline constexpr T operator()(const T& value) const noexcept
1532 {
1533 return value * Ratio_num / Ratio_den;
1534 }
1535 };
1536
1537 template<std::size_t Ratio_num>
1538 struct normal_convert<Ratio_num, 1>
1539 {
1540 template<typename T>
1541 inline constexpr T operator()(const T& value) const noexcept
1542 {
1543 return value * Ratio_num;
1544 }
1545 };
1546
1547 template<std::size_t Ratio_den>
1548 struct normal_convert<1, Ratio_den>
1549 {
1550 template<typename T>
1551 inline constexpr T operator()(const T& value) const noexcept
1552 {
1553 return value / Ratio_den;
1554 }
1555 };
1556
1557 template<>
1558 struct normal_convert<1, 1>
1559 {
1560 template<typename T>
1561 inline constexpr T operator()(const T& value) const noexcept
1562 {
1563 return value;
1564 }
1565 };
1566
1568 template<class Ratio, class PiRatio, class Translation, typename T>
1569 static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::false_type) noexcept
1570 {
1571 return normal_convert<Ratio::num, Ratio::den>{}(value);
1572 }
1573
1575 // constepxr with PI in numerator
1576 template<class Ratio, class PiRatio, class Translation, typename T>
1577 static inline constexpr
1578 std::enable_if_t<(PiRatio::num / PiRatio::den >= 1 && PiRatio::num % PiRatio::den == 0), T>
1579 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1580 {
1581 return normal_convert<Ratio::num, Ratio::den>{}(value) * pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den);
1582 }
1583
1585 // constexpr with PI in denominator
1586 template<class Ratio, class PiRatio, class Translation, typename T>
1587 static inline constexpr
1588 std::enable_if_t<(PiRatio::num / PiRatio::den <= -1 && PiRatio::num % PiRatio::den == 0), T>
1589 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1590 {
1591 return normal_convert<Ratio::num, Ratio::den>{}(value) / pow(constants::detail::PI_VAL, -PiRatio::num / PiRatio::den);
1592 }
1593
1595 // Not constexpr - uses std::pow
1596 template<class Ratio, class PiRatio, class Translation, typename T>
1597 static inline // sorry, this can't be constexpr!
1598 std::enable_if_t<(PiRatio::num / PiRatio::den < 1 && PiRatio::num / PiRatio::den > -1), T>
1599 convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1600 {
1601 return normal_convert<Ratio::num, Ratio::den>{}(value) * std::pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den);
1602 }
1603
1605 template<class Ratio, class PiRatio, class Translation, typename T>
1606 static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::true_type) noexcept
1607 {
1608 return normal_convert<Ratio::num, Ratio::den>{}(value) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1609 }
1610
1612 template<class Ratio, class PiRatio, class Translation, typename T>
1613 static inline constexpr T convert(const T& value, std::false_type isSame, std::true_type piRequired, std::true_type) noexcept
1614 {
1615 return convert<Ratio, PiRatio, Translation>(value, isSame, piRequired, std::false_type()) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1616 }
1617 } // END DOXYGEN IGNORE
1619
1635 template<class UnitFrom, class UnitTo, typename T = UNIT_LIB_DEFAULT_TYPE>
1636 static inline constexpr T convert(const T& value) noexcept
1637 {
1638 static_assert(traits::is_unit<UnitFrom>::value, "Template parameter `UnitFrom` must be a `unit` type.");
1639 static_assert(traits::is_unit<UnitTo>::value, "Template parameter `UnitTo` must be a `unit` type.");
1640 static_assert(traits::is_convertible_unit<UnitFrom, UnitTo>::value, "Units are not compatible.");
1641
1642 using Ratio = std::ratio_divide<typename UnitFrom::conversion_ratio, typename UnitTo::conversion_ratio>;
1643 using PiRatio = std::ratio_subtract<typename UnitFrom::pi_exponent_ratio, typename UnitTo::pi_exponent_ratio>;
1644 using Translation = std::ratio_divide<std::ratio_subtract<typename UnitFrom::translation_ratio, typename UnitTo::translation_ratio>, typename UnitTo::conversion_ratio>;
1645
1646 using isSame = typename std::is_same<std::decay_t<UnitFrom>, std::decay_t<UnitTo>>::type;
1647 using piRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, PiRatio>::value)>;
1648 using translationRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, Translation>::value)>;
1649
1650 return units::detail::convert<Ratio, PiRatio, Translation>
1651 (value, isSame{}, piRequired{}, translationRequired{});
1652 }
1653
1654 //----------------------------------
1655 // NON-LINEAR SCALE TRAITS
1656 //----------------------------------
1657 // DOXYGEN IGNORE
1659 namespace traits
1660 {
1661 namespace detail
1662 {
1667 template<class T, class Ret>
1668 struct has_operator_parenthesis_impl
1669 {
1670 template<class U>
1671 static constexpr auto test(U*) -> decltype(std::declval<U>()()) { return decltype(std::declval<U>()()){}; }
1672 template<typename>
1673 static constexpr std::false_type test(...) { return std::false_type{}; }
1674
1675 using type = typename std::is_same<Ret, decltype(test<T>(0))>::type;
1676 };
1677 }
1678
1683 template<class T, class Ret>
1684 struct has_operator_parenthesis : traits::detail::has_operator_parenthesis_impl<T, Ret>::type {};
1685 }
1686
1687 namespace traits
1688 {
1689 namespace detail
1690 {
1695 template<class T, class Ret>
1696 struct has_value_member_impl
1697 {
1698 template<class U>
1699 static constexpr auto test(U* p) -> decltype(p->m_value) { return p->m_value; }
1700 template<typename>
1701 static constexpr auto test(...)->std::false_type { return std::false_type{}; }
1702
1703 using type = typename std::is_same<std::decay_t<Ret>, std::decay_t<decltype(test<T>(0))>>::type;
1704 };
1705 }
1706
1711 template<class T, class Ret>
1712 struct has_value_member : traits::detail::has_value_member_impl<T, Ret>::type {};
1713 } // END DOXYGEN IGNORE
1715
1716 namespace traits
1717 {
1729 template<class T, class Ret>
1730 struct is_nonlinear_scale : std::integral_constant<bool,
1731 std::is_default_constructible<T>::value &&
1732 has_operator_parenthesis<T, Ret>::value &&
1733 has_value_member<T, Ret>::value &&
1734 std::is_trivial<T>::value>
1735 {};
1736 }
1737
1738 //------------------------------
1739 // UNIT_T TYPE TRAITS
1740 //------------------------------
1741
1742 namespace traits
1743 {
1744#ifdef FOR_DOXYGEN_PURPOSOES_ONLY
1751 template<typename T>
1752 struct unit_t_traits
1753 {
1754 typedef typename T::non_linear_scale_type non_linear_scale_type;
1755 typedef typename T::underlying_type underlying_type;
1756 typedef typename T::value_type value_type;
1757 typedef typename T::unit_type unit_type;
1758 };
1759#endif
1760 // DOXYGEN IGNORE
1766 template<typename T, typename = void>
1767 struct unit_t_traits
1768 {
1769 typedef void non_linear_scale_type;
1770 typedef void underlying_type;
1771 typedef void value_type;
1772 typedef void unit_type;
1773 };
1774
1780 template<typename T>
1781 struct unit_t_traits <T, typename void_t<
1782 typename T::non_linear_scale_type,
1783 typename T::underlying_type,
1784 typename T::value_type,
1785 typename T::unit_type>::type>
1786 {
1787 typedef typename T::non_linear_scale_type non_linear_scale_type;
1788 typedef typename T::underlying_type underlying_type;
1789 typedef typename T::value_type value_type;
1790 typedef typename T::unit_type unit_type;
1791 }; // END DOXYGEN IGNORE
1793 }
1794
1795 namespace traits
1796 {
1809 template<class U1, class U2>
1810 struct is_convertible_unit_t : std::integral_constant<bool,
1811 is_convertible_unit<typename units::traits::unit_t_traits<U1>::unit_type, typename units::traits::unit_t_traits<U2>::unit_type>::value>
1812 {};
1813 }
1814
1815 //----------------------------------
1816 // UNIT TYPE
1817 //----------------------------------
1818 // DOXYGEN IGNORE
1820 // forward declaration
1821 template<typename T> struct linear_scale;
1822 template<typename T> struct decibel_scale;
1823
1824 namespace detail
1825 {
1830 struct _unit_t {};
1831 } // END DOXYGEN IGNORE
1833
1834 namespace traits
1835 {
1836 // forward declaration
1837 #if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
1838 template<typename... T> struct is_dimensionless_unit;
1839 #else
1840 template<typename T1, typename T2 = T1, typename T3 = T1> struct is_dimensionless_unit;
1841 #endif
1842
1849 template<class T>
1850 struct is_unit_t : std::is_base_of<units::detail::_unit_t, T>::type {};
1851 }
1852
1908 template<class Units, typename T = UNIT_LIB_DEFAULT_TYPE, template<typename> class NonLinearScale = linear_scale>
1909 class unit_t : public NonLinearScale<T>, units::detail::_unit_t
1910 {
1911 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).");
1912 static_assert(traits::is_nonlinear_scale<NonLinearScale<T>, T>::value, "Template parameter `NonLinearScale` does not conform to the `is_nonlinear_scale` concept.");
1913
1914 protected:
1915
1916 using nls = NonLinearScale<T>;
1917 using nls::m_value;
1918
1919 public:
1920
1921 typedef NonLinearScale<T> non_linear_scale_type;
1923 typedef T value_type;
1924 typedef Units unit_type;
1925
1930 constexpr unit_t() = default;
1931
1940 template<class... Args>
1941 inline explicit constexpr unit_t(const T value, const Args&... args) noexcept : nls(value, args...)
1942 {
1943
1944 }
1945
1951 template<class Ty, class = typename std::enable_if<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>::type>
1952 inline constexpr unit_t(const Ty value) noexcept : nls(value)
1953 {
1954
1955 }
1956
1962 template<class Rep, class Period, class = std::enable_if_t<std::is_arithmetic<Rep>::value && traits::is_ratio<Period>::value>>
1963 inline constexpr unit_t(const std::chrono::duration<Rep, Period>& value) noexcept :
1964 nls(units::convert<unit<std::ratio<1,1000000000>, category::time_unit>, Units>(static_cast<T>(std::chrono::duration_cast<std::chrono::nanoseconds>(value).count())))
1965 {
1966
1967 }
1968
1974 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1975 inline constexpr unit_t(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept :
1976 nls(units::convert<UnitsRhs, Units, T>(rhs.m_value), std::true_type() /*store linear value*/)
1977 {
1978
1979 }
1980
1986 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1987 inline unit_t& operator=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept
1988 {
1989 nls::m_value = units::convert<UnitsRhs, Units, T>(rhs.m_value);
1990 return *this;
1991 }
1992
1998 template<class Ty, class = std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>>
1999 inline unit_t& operator=(const Ty& rhs) noexcept
2000 {
2001 nls::m_value = rhs;
2002 return *this;
2003 }
2004
2011 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2012 inline constexpr bool operator<(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2013 {
2014 return (nls::m_value < units::convert<UnitsRhs, Units>(rhs.m_value));
2015 }
2016
2023 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2024 inline constexpr bool operator<=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2025 {
2026 return (nls::m_value <= units::convert<UnitsRhs, Units>(rhs.m_value));
2027 }
2028
2035 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2036 inline constexpr bool operator>(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2037 {
2038 return (nls::m_value > units::convert<UnitsRhs, Units>(rhs.m_value));
2039 }
2040
2047 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2048 inline constexpr bool operator>=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2049 {
2050 return (nls::m_value >= units::convert<UnitsRhs, Units>(rhs.m_value));
2051 }
2052
2060 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>
2061 inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2062 {
2063 return detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::epsilon() *
2064 detail::abs(nls::m_value + units::convert<UnitsRhs, Units>(rhs.m_value)) ||
2065 detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::min();
2066 }
2067
2068 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>
2069 inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2070 {
2071 return nls::m_value == units::convert<UnitsRhs, Units>(rhs.m_value);
2072 }
2073
2081 template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2082 inline constexpr bool operator!=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2083 {
2084 return !(*this == rhs);
2085 }
2086
2091 inline constexpr underlying_type value() const noexcept
2092 {
2093 return static_cast<underlying_type>(*this);
2094 }
2095
2100 template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2101 inline constexpr Ty to() const noexcept
2102 {
2103 return static_cast<Ty>(*this);
2104 }
2105
2111 template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2112 inline constexpr Ty toLinearized() const noexcept
2113 {
2114 return static_cast<Ty>(m_value);
2115 }
2116
2126 template<class U>
2127 inline constexpr unit_t<U> convert() const noexcept
2128 {
2129 static_assert(traits::is_unit<U>::value, "Template parameter `U` must be a unit type.");
2130 return unit_t<U>(*this);
2131 }
2132
2137 template<class Ty, std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2138 inline constexpr operator Ty() const noexcept
2139 {
2140 // this conversion also resolves any PI exponents, by converting from a non-zero PI ratio to a zero-pi ratio.
2141 return static_cast<Ty>(units::convert<Units, unit<std::ratio<1>, units::category::scalar_unit>>((*this)()));
2142 }
2143
2148 template<class Ty, std::enable_if_t<!traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2149 inline constexpr explicit operator Ty() const noexcept
2150 {
2151 return static_cast<Ty>((*this)());
2152 }
2153
2158 template<typename U = Units, std::enable_if_t<units::traits::is_convertible_unit<U, unit<std::ratio<1>, category::time_unit>>::value, int> = 0>
2159 inline constexpr operator std::chrono::nanoseconds() const noexcept
2160 {
2161 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)())));
2162 }
2163
2167 inline constexpr const char* name() const noexcept
2168 {
2169 return units::name(*this);
2170 }
2171
2175 inline constexpr const char* abbreviation() const noexcept
2176 {
2177 return units::abbreviation(*this);
2178 }
2179
2180 public:
2181
2182 template<class U, typename Ty, template<typename> class Nlt>
2183 friend class unit_t;
2184 };
2185
2186 //------------------------------
2187 // UNIT_T NON-MEMBER FUNCTIONS
2188 //------------------------------
2189
2200 template<class UnitType, typename T, class = std::enable_if_t<std::is_arithmetic<T>::value>>
2201 inline constexpr UnitType make_unit(const T value) noexcept
2202 {
2203 static_assert(traits::is_unit_t<UnitType>::value, "Template parameter `UnitType` must be a unit type (_t).");
2204
2205 return UnitType(value);
2206 }
2207
2208#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2209 template<class Units, typename T, template<typename> class NonLinearScale>
2210 inline std::ostream& operator<<(std::ostream& os, const unit_t<Units, T, NonLinearScale>& obj) noexcept
2211 {
2212 using BaseUnits = unit<std::ratio<1>, typename traits::unit_traits<Units>::base_unit_type>;
2213 os << convert<Units, BaseUnits>(obj());
2214
2215 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0) { os << " m"; }
2216 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0 &&
2217 traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::meter_ratio::num; }
2218 if (traits::unit_traits<Units>::base_unit_type::meter_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::meter_ratio::den; }
2219
2220 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0) { os << " kg"; }
2221 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0 &&
2222 traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num; }
2223 if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den; }
2224
2225 if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0) { os << " s"; }
2226 if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0 &&
2227 traits::unit_traits<Units>::base_unit_type::second_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::second_ratio::num; }
2228 if (traits::unit_traits<Units>::base_unit_type::second_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::second_ratio::den; }
2229
2230 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0) { os << " A"; }
2231 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0 &&
2232 traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::num; }
2233 if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::den; }
2234
2235 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0) { os << " K"; }
2236 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0 &&
2237 traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num; }
2238 if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den; }
2239
2240 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0) { os << " mol"; }
2241 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0 &&
2242 traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::mole_ratio::num; }
2243 if (traits::unit_traits<Units>::base_unit_type::mole_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::mole_ratio::den; }
2244
2245 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0) { os << " cd"; }
2246 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0 &&
2247 traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::candela_ratio::num; }
2248 if (traits::unit_traits<Units>::base_unit_type::candela_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::candela_ratio::den; }
2249
2250 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0) { os << " rad"; }
2251 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0 &&
2252 traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::radian_ratio::num; }
2253 if (traits::unit_traits<Units>::base_unit_type::radian_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::radian_ratio::den; }
2254
2255 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0) { os << " b"; }
2256 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0 &&
2257 traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::byte_ratio::num; }
2258 if (traits::unit_traits<Units>::base_unit_type::byte_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::byte_ratio::den; }
2259
2260 return os;
2261 }
2262#endif
2263
2264 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2265 inline constexpr unit_t<Units, T, NonLinearScale>& operator+=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2266 {
2267 static_assert(traits::is_convertible_unit_t<unit_t<Units, T, NonLinearScale>, RhsType>::value ||
2268 (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2269 "parameters are not compatible units.");
2270
2271 lhs = lhs + rhs;
2272 return lhs;
2273 }
2274
2275 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2276 inline constexpr unit_t<Units, T, NonLinearScale>& operator-=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2277 {
2278 static_assert(traits::is_convertible_unit_t<unit_t<Units, T, NonLinearScale>, RhsType>::value ||
2279 (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2280 "parameters are not compatible units.");
2281
2282 lhs = lhs - rhs;
2283 return lhs;
2284 }
2285
2286 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2287 inline constexpr unit_t<Units, T, NonLinearScale>& operator*=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2288 {
2289 static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2290 "right-hand side parameter must be dimensionless.");
2291
2292 lhs = lhs * rhs;
2293 return lhs;
2294 }
2295
2296 template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2297 inline constexpr unit_t<Units, T, NonLinearScale>& operator/=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2298 {
2299 static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2300 "right-hand side parameter must be dimensionless.");
2301
2302 lhs = lhs / rhs;
2303 return lhs;
2304 }
2305
2306 //------------------------------
2307 // UNIT_T UNARY OPERATORS
2308 //------------------------------
2309
2310 // unary addition: +T
2311 template<class Units, typename T, template<typename> class NonLinearScale>
2312 inline constexpr unit_t<Units, T, NonLinearScale> operator+(const unit_t<Units, T, NonLinearScale>& u) noexcept
2313 {
2314 return u;
2315 }
2316
2317 // prefix increment: ++T
2318 template<class Units, typename T, template<typename> class NonLinearScale>
2319 inline constexpr unit_t<Units, T, NonLinearScale>& operator++(unit_t<Units, T, NonLinearScale>& u) noexcept
2320 {
2321 u = unit_t<Units, T, NonLinearScale>(u() + 1);
2322 return u;
2323 }
2324
2325 // postfix increment: T++
2326 template<class Units, typename T, template<typename> class NonLinearScale>
2327 inline constexpr unit_t<Units, T, NonLinearScale> operator++(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2328 {
2329 auto ret = u;
2330 u = unit_t<Units, T, NonLinearScale>(u() + 1);
2331 return ret;
2332 }
2333
2334 // unary addition: -T
2335 template<class Units, typename T, template<typename> class NonLinearScale>
2336 inline constexpr unit_t<Units, T, NonLinearScale> operator-(const unit_t<Units, T, NonLinearScale>& u) noexcept
2337 {
2338 return unit_t<Units, T, NonLinearScale>(-u());
2339 }
2340
2341 // prefix increment: --T
2342 template<class Units, typename T, template<typename> class NonLinearScale>
2343 inline constexpr unit_t<Units, T, NonLinearScale>& operator--(unit_t<Units, T, NonLinearScale>& u) noexcept
2344 {
2345 u = unit_t<Units, T, NonLinearScale>(u() - 1);
2346 return u;
2347 }
2348
2349 // postfix increment: T--
2350 template<class Units, typename T, template<typename> class NonLinearScale>
2351 inline constexpr unit_t<Units, T, NonLinearScale> operator--(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2352 {
2353 auto ret = u;
2354 u = unit_t<Units, T, NonLinearScale>(u() - 1);
2355 return ret;
2356 }
2357
2358 //------------------------------
2359 // UNIT_CAST
2360 //------------------------------
2361
2375 template<typename T, typename Units, class = std::enable_if_t<std::is_arithmetic<T>::value && traits::is_unit_t<Units>::value>>
2376 inline constexpr T unit_cast(const Units& value) noexcept
2377 {
2378 return static_cast<T>(value);
2379 }
2380
2381 //------------------------------
2382 // NON-LINEAR SCALE TRAITS
2383 //------------------------------
2384
2385 // forward declaration
2386 template<typename T> struct decibel_scale;
2387
2388 namespace traits
2389 {
2397#if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2398 template<typename... T>
2399 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 > {};
2400#else
2401 template<typename T1, typename T2 = T1, typename T3 = T1>
2402 struct has_linear_scale : std::integral_constant<bool,
2403 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2404 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2405 std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T3>::underlying_type>, T3>::value> {};
2406#endif
2407
2415#if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2416 template<typename... T>
2417 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> {};
2418#else
2419 template<typename T1, typename T2 = T1, typename T3 = T1>
2420 struct has_decibel_scale : std::integral_constant<bool,
2421 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2422 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2423 std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T3>::value> {};
2424#endif
2425
2434 template<typename T1, typename T2>
2435 struct is_same_scale : std::integral_constant<bool,
2436 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>
2437 {};
2438 }
2439
2440 //----------------------------------
2441 // NON-LINEAR SCALES
2442 //----------------------------------
2443
2444 // Non-linear transforms are used to pre and post scale units which are defined in terms of non-
2445 // linear functions of their current value. A good example of a non-linear scale would be a
2446 // logarithmic or decibel scale
2447
2448 //------------------------------
2449 // LINEAR SCALE
2450 //------------------------------
2451
2459 template<typename T>
2461 {
2462 inline constexpr linear_scale() = default;
2463 inline constexpr linear_scale(const linear_scale&) = default;
2464 inline ~linear_scale() = default;
2465 inline linear_scale& operator=(const linear_scale&) = default;
2466#if defined(_MSC_VER) && (_MSC_VER > 1800)
2467 inline constexpr linear_scale(linear_scale&&) = default;
2468 inline linear_scale& operator=(linear_scale&&) = default;
2469#endif
2470 template<class... Args>
2471 inline constexpr linear_scale(const T& value, Args&&...) noexcept : m_value(value) {}
2472 inline constexpr T operator()() const noexcept { return m_value; }
2473
2475 };
2476
2477 //----------------------------------
2478 // SCALAR (LINEAR) UNITS
2479 //----------------------------------
2480
2481 // Scalar units are the *ONLY* units implicitly convertible to/from built-in types.
2483 {
2486
2487 typedef unit_t<scalar> scalar_t;
2488 typedef scalar_t dimensionless_t;
2489 }
2490
2491// ignore the redeclaration of the default template parameters
2492#if defined(_MSC_VER)
2493# pragma warning(push)
2494# pragma warning(disable : 4348)
2495#endif
2498#if defined(_MSC_VER)
2499# pragma warning(pop)
2500#endif
2501
2502 //------------------------------
2503 // LINEAR ARITHMETIC
2504 //------------------------------
2505
2506 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<!traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2507 constexpr inline int operator+(const UnitTypeLhs& /* lhs */, const UnitTypeRhs& /* rhs */) noexcept
2508 {
2509 static_assert(traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, "Cannot add units with different linear/non-linear scales.");
2510 return 0;
2511 }
2512
2514 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2515 inline constexpr UnitTypeLhs operator+(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2516 {
2517 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2518 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2519 return UnitTypeLhs(lhs() + convert<UnitsRhs, UnitsLhs>(rhs()));
2520 }
2521
2523 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2524 inline constexpr dimensionless::scalar_t operator+(const dimensionless::scalar_t& lhs, T rhs) noexcept
2525 {
2526 return dimensionless::scalar_t(lhs() + rhs);
2527 }
2528
2530 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2531 inline constexpr dimensionless::scalar_t operator+(T lhs, const dimensionless::scalar_t& rhs) noexcept
2532 {
2533 return dimensionless::scalar_t(lhs + rhs());
2534 }
2535
2537 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2538 inline constexpr UnitTypeLhs operator-(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2539 {
2540 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2541 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2542 return UnitTypeLhs(lhs() - convert<UnitsRhs, UnitsLhs>(rhs()));
2543 }
2544
2546 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2547 inline constexpr dimensionless::scalar_t operator-(const dimensionless::scalar_t& lhs, T rhs) noexcept
2548 {
2549 return dimensionless::scalar_t(lhs() - rhs);
2550 }
2551
2553 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2554 inline constexpr dimensionless::scalar_t operator-(T lhs, const dimensionless::scalar_t& rhs) noexcept
2555 {
2556 return dimensionless::scalar_t(lhs - rhs());
2557 }
2558
2560 template<class UnitTypeLhs, class UnitTypeRhs,
2561 std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2562 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>>>
2563 {
2564 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2565 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2567 (lhs() * convert<UnitsRhs, UnitsLhs>(rhs()));
2568 }
2569
2571 template<class UnitTypeLhs, class UnitTypeRhs,
2572 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>
2573 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>>
2574 {
2575 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2576 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2577 return unit_t<compound_unit<UnitsLhs, UnitsRhs>>
2578 (lhs() * rhs());
2579 }
2580
2582 template<class UnitTypeLhs, typename UnitTypeRhs,
2583 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>
2584 inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2585 {
2586 // the cast makes sure factors of PI are handled as expected
2587 return UnitTypeLhs(lhs() * static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2588 }
2589
2591 template<class UnitTypeLhs, typename UnitTypeRhs,
2592 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>
2593 inline constexpr UnitTypeRhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2594 {
2595 // the cast makes sure factors of PI are handled as expected
2596 return UnitTypeRhs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) * rhs());
2597 }
2598
2600 template<class UnitTypeLhs, typename T,
2601 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2602 inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, T rhs) noexcept
2603 {
2604 return UnitTypeLhs(lhs() * rhs);
2605 }
2606
2608 template<class UnitTypeRhs, typename T,
2609 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2610 inline constexpr UnitTypeRhs operator*(T lhs, const UnitTypeRhs& rhs) noexcept
2611 {
2612 return UnitTypeRhs(lhs * rhs());
2613 }
2614
2616 template<class UnitTypeLhs, class UnitTypeRhs,
2617 std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2618 inline constexpr dimensionless::scalar_t operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2619 {
2620 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2621 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2622 return dimensionless::scalar_t(lhs() / convert<UnitsRhs, UnitsLhs>(rhs()));
2623 }
2624
2626 template<class UnitTypeLhs, class UnitTypeRhs,
2627 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>
2629 {
2630 using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2631 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2633 (lhs() / rhs());
2634 }
2635
2637 template<class UnitTypeLhs, class UnitTypeRhs,
2638 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>
2639 inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2640 {
2641 return UnitTypeLhs(lhs() / static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2642 }
2643
2645 template<class UnitTypeLhs, class UnitTypeRhs,
2646 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>
2647 inline constexpr auto operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2648 {
2649 return unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2650 (static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) / rhs());
2651 }
2652
2654 template<class UnitTypeLhs, typename T,
2655 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2656 inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, T rhs) noexcept
2657 {
2658 return UnitTypeLhs(lhs() / rhs);
2659 }
2660
2662 template<class UnitTypeRhs, typename T,
2663 std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2664 inline constexpr auto operator/(T lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2665 {
2666 using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2668 (lhs / rhs());
2669 }
2670
2671 //----------------------------------
2672 // SCALAR COMPARISONS
2673 //----------------------------------
2674
2675 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2676 constexpr bool operator==(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2677 {
2678 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)) ||
2679 detail::abs(lhs - static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs)) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2680 }
2681
2682 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2683 constexpr bool operator==(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2684 {
2685 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) ||
2686 detail::abs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) - rhs) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2687 }
2688
2689 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2690 constexpr bool operator!=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2691 {
2692 return!(lhs == static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
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 !(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) == rhs);
2699 }
2700
2701 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2702 constexpr bool operator>=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2703 {
2704 return std::isgreaterequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2705 }
2706
2707 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2708 constexpr bool operator>=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2709 {
2710 return std::isgreaterequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2711 }
2712
2713 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2714 constexpr bool operator>(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2715 {
2716 return lhs > static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2717 }
2718
2719 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2720 constexpr bool operator>(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2721 {
2722 return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) > rhs;
2723 }
2724
2725 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2726 constexpr bool operator<=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2727 {
2728 return std::islessequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2729 }
2730
2731 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2732 constexpr bool operator<=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2733 {
2734 return std::islessequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2735 }
2736
2737 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2738 constexpr bool operator<(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2739 {
2740 return lhs < static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2741 }
2742
2743 template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2744 constexpr bool operator<(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2745 {
2746 return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) < rhs;
2747 }
2748
2749 //----------------------------------
2750 // POW
2751 //----------------------------------
2752 // DOXYGEN IGNORE
2754 namespace detail
2755 {
2757 template <int N, class U> struct power_of_unit
2758 {
2759 template<bool isPos, int V> struct power_of_unit_impl;
2760
2761 template<int V> struct power_of_unit_impl<true, V>
2762 {
2763 typedef units::detail::unit_multiply<U, typename power_of_unit<N - 1, U>::type> type;
2764 };
2765
2766 template<int V> struct power_of_unit_impl<false, V>
2767 {
2768 typedef units::inverse<typename power_of_unit<-N, U>::type> type;
2769 };
2770
2771 typedef typename power_of_unit_impl<(N > 0), N>::type type;
2772 };
2773
2775 template <class U> struct power_of_unit<1, U>
2776 {
2777 typedef U type;
2778 };
2779 template <class U> struct power_of_unit<0, U>
2780 {
2782 };
2783 } // END DOXYGEN IGNORE
2785
2786 namespace math
2787 {
2795 template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2796 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>
2797 {
2798 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>
2799 (std::pow(value(), power));
2800 }
2801
2810 template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2811 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>
2812 {
2813 static_assert(power >= 0, "cpow cannot accept negative numbers. Try units::math::pow instead.");
2814 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>
2815 (detail::pow(value(), power));
2816 }
2817 }
2818
2819 //------------------------------
2820 // DECIBEL SCALE
2821 //------------------------------
2822
2829 template<typename T>
2831 {
2832 inline constexpr decibel_scale() = default;
2833 inline constexpr decibel_scale(const decibel_scale&) = default;
2834 inline ~decibel_scale() = default;
2835 inline decibel_scale& operator=(const decibel_scale&) = default;
2836#if defined(_MSC_VER) && (_MSC_VER > 1800)
2837 inline constexpr decibel_scale(decibel_scale&&) = default;
2838 inline decibel_scale& operator=(decibel_scale&&) = default;
2839#endif
2840 inline constexpr decibel_scale(const T value) noexcept : m_value(std::pow(10, value / 10)) {}
2841 template<class... Args>
2842 inline constexpr decibel_scale(const T value, std::true_type, Args&&...) noexcept : m_value(value) {}
2843 inline constexpr T operator()() const noexcept { return 10 * std::log10(m_value); }
2844
2846 };
2847
2848 //------------------------------
2849 // SCALAR (DECIBEL) UNITS
2850 //------------------------------
2851
2856 namespace dimensionless
2857 {
2859#if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2860 inline std::ostream& operator<<(std::ostream& os, const dB_t& obj) { os << obj() << " dB"; return os; }
2861#endif
2862 typedef dB_t dBi_t;
2863 }
2864
2865 //------------------------------
2866 // DECIBEL ARITHMETIC
2867 //------------------------------
2868
2870 template<class UnitTypeLhs, class UnitTypeRhs,
2871 std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2872 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>
2873 {
2874 using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2875 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2876 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2877
2878 return unit_t<compound_unit<squared<LhsUnits>>, underlying_type, decibel_scale>
2879 (lhs.template toLinearized<underlying_type>() * convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2880 }
2881
2883 template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2884 constexpr inline UnitTypeLhs operator+(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2885 {
2886 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2887 return UnitTypeLhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2888 }
2889
2891 template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2892 constexpr inline UnitTypeRhs operator+(const dimensionless::dB_t& lhs, const UnitTypeRhs& rhs) noexcept
2893 {
2894 using underlying_type = typename units::traits::unit_t_traits<UnitTypeRhs>::underlying_type;
2895 return UnitTypeRhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2896 }
2897
2899 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2900 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>
2901 {
2902 using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2903 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2904 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2905
2907 (lhs.template toLinearized<underlying_type>() / convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2908 }
2909
2911 template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2912 constexpr inline UnitTypeLhs operator-(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2913 {
2914 using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2915 return UnitTypeLhs(lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2916 }
2917
2919 template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2920 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>
2921 {
2922 using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2923 using underlying_type = typename units::traits::unit_t_traits<RhsUnits>::underlying_type;
2924
2925 return unit_t<inverse<RhsUnits>, underlying_type, decibel_scale>
2926 (lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2927 }
2928
2929 //----------------------------------
2930 // UNIT RATIO CLASS
2931 //----------------------------------
2932 // DOXYGEN IGNORE
2934 namespace detail
2935 {
2936 template<class Units>
2937 struct _unit_value_t {};
2938 } // END DOXYGEN IGNORE
2940
2941 namespace traits
2942 {
2943#ifdef FOR_DOXYGEN_PURPOSES_ONLY
2951 template<typename T>
2952 struct unit_value_t_traits
2953 {
2954 typedef typename T::unit_type unit_type;
2955 typedef typename T::ratio ratio;
2956 };
2957#endif
2958 // DOXYGEN IGNORE
2964 template<typename T, typename = void>
2965 struct unit_value_t_traits
2966 {
2967 typedef void unit_type;
2968 typedef void ratio;
2969 };
2970
2976 template<typename T>
2977 struct unit_value_t_traits <T, typename void_t<
2978 typename T::unit_type,
2979 typename T::ratio>::type>
2980 {
2981 typedef typename T::unit_type unit_type;
2982 typedef typename T::ratio ratio;
2983 }; // END DOXYGEN IGNORE
2985 }
2986
2987 //------------------------------------------------------------------------------
2988 // COMPILE-TIME UNIT VALUES AND ARITHMETIC
2989 //------------------------------------------------------------------------------
2990
3004 template<typename Units, std::uintmax_t Num, std::uintmax_t Denom = 1>
3005 struct unit_value_t : units::detail::_unit_value_t<Units>
3006 {
3007 typedef Units unit_type;
3008 typedef std::ratio<Num, Denom> ratio;
3009
3010 static_assert(traits::is_unit<Units>::value, "Template parameter `Units` must be a unit type.");
3011 static constexpr const unit_t<Units> value() { return unit_t<Units>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den); }
3012 };
3013
3014 namespace traits
3015 {
3024 template<typename T, typename Units = typename traits::unit_value_t_traits<T>::unit_type>
3025 struct is_unit_value_t : std::integral_constant<bool,
3026 std::is_base_of<units::detail::_unit_value_t<Units>, T>::value>
3027 {};
3028
3034 template<typename Category, typename T>
3035 struct is_unit_value_t_category : std::integral_constant<bool,
3036 std::is_same<units::traits::base_unit_of<typename traits::unit_value_t_traits<T>::unit_type>, Category>::value>
3037 {
3038 static_assert(is_base_unit<Category>::value, "Template parameter `Category` must be a `base_unit` type.");
3039 };
3040 }
3041 // DOXYGEN IGNORE
3043 namespace detail
3044 {
3045 // base class for common arithmetic
3046 template<class U1, class U2>
3047 struct unit_value_arithmetic
3048 {
3049 static_assert(traits::is_unit_value_t<U1>::value, "Template parameter `U1` must be a `unit_value_t` type.");
3050 static_assert(traits::is_unit_value_t<U2>::value, "Template parameter `U2` must be a `unit_value_t` type.");
3051
3052 using _UNIT1 = typename traits::unit_value_t_traits<U1>::unit_type;
3053 using _UNIT2 = typename traits::unit_value_t_traits<U2>::unit_type;
3054 using _CONV1 = typename units::traits::unit_traits<_UNIT1>::conversion_ratio;
3055 using _CONV2 = typename units::traits::unit_traits<_UNIT2>::conversion_ratio;
3056 using _RATIO1 = typename traits::unit_value_t_traits<U1>::ratio;
3057 using _RATIO2 = typename traits::unit_value_t_traits<U2>::ratio;
3058 using _RATIO2CONV = typename std::ratio_divide<std::ratio_multiply<_RATIO2, _CONV2>, _CONV1>;
3059 using _PI_EXP = std::ratio_subtract<typename units::traits::unit_traits<_UNIT2>::pi_exponent_ratio, typename units::traits::unit_traits<_UNIT1>::pi_exponent_ratio>;
3060 };
3061 } // END DOXYGEN IGNORE
3063
3074 template<class U1, class U2>
3075 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>
3076 { // DOXYGEN IGNORE
3078 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3079 typedef typename Base::_UNIT1 unit_type;
3080 using ratio = std::ratio_add<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3081
3082 static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3084
3091 static constexpr const unit_t<unit_type> value() noexcept
3092 {
3093 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3094 return value(UsePi());
3095 }
3096 // DOXYGEN IGNORE
3098 // value if PI isn't involved
3099 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3100 {
3101 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3102 }
3103
3104 // value if PI *is* involved
3105 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3106 {
3107 return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO1::num / Base::_RATIO1::den) +
3108 ((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)));
3109 } // END DOXYGEN IGNORE
3111 };
3112
3123 template<class U1, class U2>
3124 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>
3125 { // DOXYGEN IGNORE
3127 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3128
3129 typedef typename Base::_UNIT1 unit_type;
3130 using ratio = std::ratio_subtract<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3131
3132 static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3134
3141 static constexpr const unit_t<unit_type> value() noexcept
3142 {
3143 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3144 return value(UsePi());
3145 }
3146 // DOXYGEN IGNORE
3148 // value if PI isn't involved
3149 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3150 {
3151 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3152 }
3153
3154 // value if PI *is* involved
3155 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3156 {
3157 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)
3158 * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3159 } // END DOXYGEN IGNORE };
3161 };
3162
3173 template<class U1, class U2>
3174 struct unit_value_multiply : units::detail::unit_value_arithmetic<U1, U2>,
3175 units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3176 typename traits::unit_value_t_traits<U2>::unit_type>::value, compound_unit<squared<typename traits::unit_value_t_traits<U1>::unit_type>>,
3177 compound_unit<typename traits::unit_value_t_traits<U1>::unit_type, typename traits::unit_value_t_traits<U2>::unit_type>>::type>
3178 { // DOXYGEN IGNORE
3180 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3181
3182 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>>;
3183 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
3185
3192 static constexpr const unit_t<unit_type> value() noexcept
3193 {
3194 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3195 return value(UsePi());
3196 }
3197 // DOXYGEN IGNORE
3199 // value if PI isn't involved
3200 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3201 {
3202 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3203 }
3204
3205 // value if PI *is* involved
3206 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3207 {
3208 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)));
3209 } // END DOXYGEN IGNORE
3211 };
3212
3223 template<class U1, class U2>
3224 struct unit_value_divide : units::detail::unit_value_arithmetic<U1, U2>,
3225 units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3226 typename traits::unit_value_t_traits<U2>::unit_type>::value, dimensionless::scalar, compound_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3227 inverse<typename traits::unit_value_t_traits<U2>::unit_type>>>::type>
3228 { // DOXYGEN IGNORE
3230 using Base = units::detail::unit_value_arithmetic<U1, U2>;
3231
3232 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>>>;
3233 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
3235
3242 static constexpr const unit_t<unit_type> value() noexcept
3243 {
3244 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3245 return value(UsePi());
3246 }
3247 // DOXYGEN IGNORE
3249 // value if PI isn't involved
3250 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3251 {
3252 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3253 }
3254
3255 // value if PI *is* involved
3256 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3257 {
3258 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)));
3259 } // END DOXYGEN IGNORE
3261 };
3262
3272 template<class U1, int power>
3273 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>
3274 { // DOXYGEN IGNORE
3276 using Base = units::detail::unit_value_arithmetic<U1, U1>;
3277
3278 using unit_type = typename units::detail::power_of_unit<power, typename Base::_UNIT1>::type;
3279 using ratio = typename units::detail::power_of_ratio<power, typename Base::_RATIO1>::type;
3280 using pi_exponent = std::ratio_multiply<std::ratio<power>, typename Base::_UNIT1::pi_exponent_ratio>; // END DOXYGEN IGNORE
3282
3289 static constexpr const unit_t<unit_type> value() noexcept
3290 {
3291 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3292 return value(UsePi());
3293 }
3294 // DOXYGEN IGNORE
3296 // value if PI isn't involved
3297 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3298 {
3299 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3300 }
3301
3302 // value if PI *is* involved
3303 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3304 {
3305 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)));
3306 } // END DOXYGEN IGNORE };
3308 };
3309
3319 template<class U1, std::intmax_t Eps = 10000000000>
3320 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>>
3321 { // DOXYGEN IGNORE
3323 using Base = units::detail::unit_value_arithmetic<U1, U1>;
3324
3327 using pi_exponent = ratio_sqrt<typename Base::_UNIT1::pi_exponent_ratio, Eps>; // END DOXYGEN IGNORE
3329
3336 static constexpr const unit_t<unit_type> value() noexcept
3337 {
3338 using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3339 return value(UsePi());
3340 }
3341 // DOXYGEN IGNORE
3343 // value if PI isn't involved
3344 static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3345 {
3346 return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3347 }
3348
3349 // value if PI *is* involved
3350 static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3351 {
3352 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)));
3353 } // END DOXYGEN IGNORE
3355 };
3356
3357 //------------------------------
3358 // LITERALS
3359 //------------------------------
3360
3372 //------------------------------
3373 // LENGTH UNITS
3374 //------------------------------
3375
3384#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LENGTH_UNITS)
3385 UNIT_ADD_WITH_METRIC_PREFIXES(length, meter, meters, m, unit<std::ratio<1>, units::category::length_unit>)
3386 UNIT_ADD(length, foot, feet, ft, unit<std::ratio<381, 1250>, meters>)
3387 UNIT_ADD(length, inch, inches, in, unit<std::ratio<1, 12>, feet>)
3388 UNIT_ADD(length, mil, mils, mil, unit<std::ratio<1000>, inches>)
3389 UNIT_ADD(length, mile, miles, mi, unit<std::ratio<5280>, feet>)
3390 UNIT_ADD(length, nauticalMile, nauticalMiles, nmi, unit<std::ratio<1852>, meters>)
3391 UNIT_ADD(length, astronicalUnit, astronicalUnits, au, unit<std::ratio<149597870700>, meters>)
3392 UNIT_ADD(length, lightyear, lightyears, ly, unit<std::ratio<9460730472580800>, meters>)
3393 UNIT_ADD(length, parsec, parsecs, pc, unit<std::ratio<648000>, astronicalUnits, std::ratio<-1>>)
3394 UNIT_ADD(length, angstrom, angstroms, angstrom, unit<std::ratio<1, 10>, nanometers>)
3395 UNIT_ADD(length, cubit, cubits, cbt, unit<std::ratio<18>, inches>)
3396 UNIT_ADD(length, fathom, fathoms, ftm, unit<std::ratio<6>, feet>)
3397 UNIT_ADD(length, chain, chains, ch, unit<std::ratio<66>, feet>)
3398 UNIT_ADD(length, furlong, furlongs, fur, unit<std::ratio<10>, chains>)
3399 UNIT_ADD(length, hand, hands, hand, unit<std::ratio<4>, inches>)
3400 UNIT_ADD(length, league, leagues, lea, unit<std::ratio<3>, miles>)
3401 UNIT_ADD(length, nauticalLeague, nauticalLeagues, nl, unit<std::ratio<3>, nauticalMiles>)
3402 UNIT_ADD(length, yard, yards, yd, unit<std::ratio<3>, feet>)
3403
3405#endif
3406
3407 //------------------------------
3408 // MASS UNITS
3409 //------------------------------
3410
3419#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MASS_UNITS)
3420 UNIT_ADD_WITH_METRIC_PREFIXES(mass, gram, grams, g, unit<std::ratio<1, 1000>, units::category::mass_unit>)
3421 UNIT_ADD(mass, metric_ton, metric_tons, t, unit<std::ratio<1000>, kilograms>)
3422 UNIT_ADD(mass, pound, pounds, lb, unit<std::ratio<45359237, 100000000>, kilograms>)
3423 UNIT_ADD(mass, long_ton, long_tons, ln_t, unit<std::ratio<2240>, pounds>)
3424 UNIT_ADD(mass, short_ton, short_tons, sh_t, unit<std::ratio<2000>, pounds>)
3425 UNIT_ADD(mass, stone, stone, st, unit<std::ratio<14>, pounds>)
3426 UNIT_ADD(mass, ounce, ounces, oz, unit<std::ratio<1, 16>, pounds>)
3427 UNIT_ADD(mass, carat, carats, ct, unit<std::ratio<200>, milligrams>)
3428 UNIT_ADD(mass, slug, slugs, slug, unit<std::ratio<145939029, 10000000>, kilograms>)
3429
3431#endif
3432
3433 //------------------------------
3434 // TIME UNITS
3435 //------------------------------
3436
3445#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TIME_UNITS)
3446 UNIT_ADD_WITH_METRIC_PREFIXES(time, second, seconds, s, unit<std::ratio<1>, units::category::time_unit>)
3447 UNIT_ADD(time, minute, minutes, min, unit<std::ratio<60>, seconds>)
3448 UNIT_ADD(time, hour, hours, hr, unit<std::ratio<60>, minutes>)
3449 UNIT_ADD(time, day, days, d, unit<std::ratio<24>, hours>)
3450 UNIT_ADD(time, week, weeks, wk, unit<std::ratio<7>, days>)
3451 UNIT_ADD(time, year, years, yr, unit<std::ratio<365>, days>)
3452 UNIT_ADD(time, julian_year, julian_years, a_j, unit<std::ratio<31557600>, seconds>)
3453 UNIT_ADD(time, gregorian_year, gregorian_years, a_g, unit<std::ratio<31556952>, seconds>)
3454
3456#endif
3457
3458 //------------------------------
3459 // ANGLE UNITS
3460 //------------------------------
3461
3470#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
3471 UNIT_ADD_WITH_METRIC_PREFIXES(angle, radian, radians, rad, unit<std::ratio<1>, units::category::angle_unit>)
3472 UNIT_ADD(angle, degree, degrees, deg, unit<std::ratio<1, 180>, radians, std::ratio<1>>)
3473 UNIT_ADD(angle, arcminute, arcminutes, arcmin, unit<std::ratio<1, 60>, degrees>)
3474 UNIT_ADD(angle, arcsecond, arcseconds, arcsec, unit<std::ratio<1, 60>, arcminutes>)
3475 UNIT_ADD(angle, milliarcsecond, milliarcseconds, mas, milli<arcseconds>)
3476 UNIT_ADD(angle, turn, turns, tr, unit<std::ratio<2>, radians, std::ratio<1>>)
3477 UNIT_ADD(angle, gradian, gradians, gon, unit<std::ratio<1, 400>, turns>)
3478
3480#endif
3481
3482 //------------------------------
3483 // UNITS OF CURRENT
3484 //------------------------------
3493#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CURRENT_UNITS)
3494 UNIT_ADD_WITH_METRIC_PREFIXES(current, ampere, amperes, A, unit<std::ratio<1>, units::category::current_unit>)
3495
3497#endif
3498
3499 //------------------------------
3500 // UNITS OF TEMPERATURE
3501 //------------------------------
3502
3503 // NOTE: temperature units have special conversion overloads, since they
3504 // require translations and aren't a reversible transform.
3505
3514#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TEMPERATURE_UNITS)
3515 UNIT_ADD(temperature, kelvin, kelvin, K, unit<std::ratio<1>, units::category::temperature_unit>)
3516 UNIT_ADD(temperature, celsius, celsius, degC, unit<std::ratio<1>, kelvin, std::ratio<0>, std::ratio<27315, 100>>)
3517 UNIT_ADD(temperature, fahrenheit, fahrenheit, degF, unit<std::ratio<5, 9>, celsius, std::ratio<0>, std::ratio<-160, 9>>)
3518 UNIT_ADD(temperature, reaumur, reaumur, Re, unit<std::ratio<10, 8>, celsius>)
3519 UNIT_ADD(temperature, rankine, rankine, Ra, unit<std::ratio<5, 9>, kelvin>)
3520
3522#endif
3523
3524 //------------------------------
3525 // UNITS OF AMOUNT OF SUBSTANCE
3526 //------------------------------
3527
3536#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SUBSTANCE_UNITS)
3537 UNIT_ADD(substance, mole, moles, mol, unit<std::ratio<1>, units::category::substance_unit>)
3538
3540#endif
3541
3542 //------------------------------
3543 // UNITS OF LUMINOUS INTENSITY
3544 //------------------------------
3545
3554#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS)
3555 UNIT_ADD_WITH_METRIC_PREFIXES(luminous_intensity, candela, candelas, cd, unit<std::ratio<1>, units::category::luminous_intensity_unit>)
3556
3557 UNIT_ADD_CATEGORY_TRAIT(luminous_intensity)
3558#endif
3559
3560 //------------------------------
3561 // UNITS OF SOLID ANGLE
3562 //------------------------------
3563
3572#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS)
3573 UNIT_ADD_WITH_METRIC_PREFIXES(solid_angle, steradian, steradians, sr, unit<std::ratio<1>, units::category::solid_angle_unit>)
3574 UNIT_ADD(solid_angle, degree_squared, degrees_squared, sq_deg, squared<angle::degrees>)
3575 UNIT_ADD(solid_angle, spat, spats, sp, unit<std::ratio<4>, steradians, std::ratio<1>>)
3576
3578#endif
3579
3580 //------------------------------
3581 // FREQUENCY UNITS
3582 //------------------------------
3583
3592#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FREQUENCY_UNITS)
3593 UNIT_ADD_WITH_METRIC_PREFIXES(frequency, hertz, hertz, Hz, unit<std::ratio<1>, units::category::frequency_unit>)
3594
3596#endif
3597
3598 //------------------------------
3599 // VELOCITY UNITS
3600 //------------------------------
3601
3610#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VELOCITY_UNITS)
3611 UNIT_ADD(velocity, meters_per_second, meters_per_second, mps, unit<std::ratio<1>, units::category::velocity_unit>)
3612 UNIT_ADD(velocity, feet_per_second, feet_per_second, fps, compound_unit<length::feet, inverse<time::seconds>>)
3613 UNIT_ADD(velocity, miles_per_hour, miles_per_hour, mph, compound_unit<length::miles, inverse<time::hour>>)
3614 UNIT_ADD(velocity, kilometers_per_hour, kilometers_per_hour, kph, compound_unit<length::kilometers, inverse<time::hour>>)
3615 UNIT_ADD(velocity, knot, knots, kts, compound_unit<length::nauticalMiles, inverse<time::hour>>)
3616
3618#endif
3619
3620 //------------------------------
3621 // ANGULAR VELOCITY UNITS
3622 //------------------------------
3623
3632#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS)
3633 UNIT_ADD(angular_velocity, radians_per_second, radians_per_second, rad_per_s, unit<std::ratio<1>, units::category::angular_velocity_unit>)
3634 UNIT_ADD(angular_velocity, degrees_per_second, degrees_per_second, deg_per_s, compound_unit<angle::degrees, inverse<time::seconds>>)
3635 UNIT_ADD(angular_velocity, revolutions_per_minute, revolutions_per_minute, rpm, unit<std::ratio<2, 60>, radians_per_second, std::ratio<1>>)
3636 UNIT_ADD(angular_velocity, milliarcseconds_per_year, milliarcseconds_per_year, mas_per_yr, compound_unit<angle::milliarcseconds, inverse<time::year>>)
3637
3638 UNIT_ADD_CATEGORY_TRAIT(angular_velocity)
3639#endif
3640
3641 //------------------------------
3642 // UNITS OF ACCELERATION
3643 //------------------------------
3644
3653#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ACCELERATION_UNITS)
3654 UNIT_ADD(acceleration, meters_per_second_squared, meters_per_second_squared, mps_sq, unit<std::ratio<1>, units::category::acceleration_unit>)
3655 UNIT_ADD(acceleration, feet_per_second_squared, feet_per_second_squared, fps_sq, compound_unit<length::feet, inverse<squared<time::seconds>>>)
3656 UNIT_ADD(acceleration, standard_gravity, standard_gravity, SG, unit<std::ratio<980665, 100000>, meters_per_second_squared>)
3657
3659#endif
3660
3661 //------------------------------
3662 // UNITS OF FORCE
3663 //------------------------------
3664
3673#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FORCE_UNITS)
3674 UNIT_ADD_WITH_METRIC_PREFIXES(force, newton, newtons, N, unit<std::ratio<1>, units::category::force_unit>)
3675 UNIT_ADD(force, pound, pounds, lbf, compound_unit<mass::slug, length::foot, inverse<squared<time::seconds>>>)
3676 UNIT_ADD(force, dyne, dynes, dyn, unit<std::ratio<1, 100000>, newtons>)
3677 UNIT_ADD(force, kilopond, kiloponds, kp, compound_unit<acceleration::standard_gravity, mass::kilograms>)
3678 UNIT_ADD(force, poundal, poundals, pdl, compound_unit<mass::pound, length::foot, inverse<squared<time::seconds>>>)
3679
3681#endif
3682
3683 //------------------------------
3684 // UNITS OF PRESSURE
3685 //------------------------------
3686
3695#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_PRESSURE_UNITS)
3696 UNIT_ADD_WITH_METRIC_PREFIXES(pressure, pascal, pascals, Pa, unit<std::ratio<1>, units::category::pressure_unit>)
3697 UNIT_ADD(pressure, bar, bars, bar, unit<std::ratio<100>, kilo<pascals>>)
3698 UNIT_ADD(pressure, mbar, mbars, mbar, unit<std::ratio<1>, milli<bar>>)
3699 UNIT_ADD(pressure, atmosphere, atmospheres, atm, unit<std::ratio<101325>, pascals>)
3700 UNIT_ADD(pressure, pounds_per_square_inch, pounds_per_square_inch, psi, compound_unit<force::pounds, inverse<squared<length::inch>>>)
3701 UNIT_ADD(pressure, torr, torrs, torr, unit<std::ratio<1, 760>, atmospheres>)
3702
3704#endif
3705
3706 //------------------------------
3707 // UNITS OF CHARGE
3708 //------------------------------
3709
3718#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CHARGE_UNITS)
3719 UNIT_ADD_WITH_METRIC_PREFIXES(charge, coulomb, coulombs, C, unit<std::ratio<1>, units::category::charge_unit>)
3720 UNIT_ADD_WITH_METRIC_PREFIXES(charge, ampere_hour, ampere_hours, Ah, compound_unit<current::ampere, time::hours>)
3721
3723#endif
3724
3725 //------------------------------
3726 // UNITS OF ENERGY
3727 //------------------------------
3728
3737#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ENERGY_UNITS)
3738 UNIT_ADD_WITH_METRIC_PREFIXES(energy, joule, joules, J, unit<std::ratio<1>, units::category::energy_unit>)
3739 UNIT_ADD_WITH_METRIC_PREFIXES(energy, calorie, calories, cal, unit<std::ratio<4184, 1000>, joules>)
3740 UNIT_ADD(energy, kilowatt_hour, kilowatt_hours, kWh, unit<std::ratio<36, 10>, megajoules>)
3741 UNIT_ADD(energy, watt_hour, watt_hours, Wh, unit<std::ratio<1, 1000>, kilowatt_hours>)
3742 UNIT_ADD(energy, british_thermal_unit, british_thermal_units, BTU, unit<std::ratio<105505585262, 100000000>, joules>)
3743 UNIT_ADD(energy, british_thermal_unit_iso, british_thermal_units_iso, BTU_iso, unit<std::ratio<1055056, 1000>, joules>)
3744 UNIT_ADD(energy, british_thermal_unit_59, british_thermal_units_59, BTU59, unit<std::ratio<1054804, 1000>, joules>)
3745 UNIT_ADD(energy, therm, therms, thm, unit<std::ratio<100000>, british_thermal_units_59>)
3746 UNIT_ADD(energy, foot_pound, foot_pounds, ftlbf, unit<std::ratio<13558179483314004, 10000000000000000>, joules>)
3747
3749#endif
3750
3751 //------------------------------
3752 // UNITS OF POWER
3753 //------------------------------
3754
3763#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_POWER_UNITS)
3764 UNIT_ADD_WITH_METRIC_PREFIXES(power, watt, watts, W, unit<std::ratio<1>, units::category::power_unit>)
3765 UNIT_ADD(power, horsepower, horsepower, hp, unit<std::ratio<7457, 10>, watts>)
3766 UNIT_ADD_DECIBEL(power, watt, dBW)
3767 UNIT_ADD_DECIBEL(power, milliwatt, dBm)
3768
3770#endif
3771
3772 //------------------------------
3773 // UNITS OF VOLTAGE
3774 //------------------------------
3775
3784#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLTAGE_UNITS)
3785 UNIT_ADD_WITH_METRIC_PREFIXES(voltage, volt, volts, V, unit<std::ratio<1>, units::category::voltage_unit>)
3786 UNIT_ADD(voltage, statvolt, statvolts, statV, unit<std::ratio<1000000, 299792458>, volts>)
3787 UNIT_ADD(voltage, abvolt, abvolts, abV, unit<std::ratio<1, 100000000>, volts>)
3788
3790#endif
3791
3792 //------------------------------
3793 // UNITS OF CAPACITANCE
3794 //------------------------------
3795
3804#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CAPACITANCE_UNITS)
3805 UNIT_ADD_WITH_METRIC_PREFIXES(capacitance, farad, farads, F, unit<std::ratio<1>, units::category::capacitance_unit>)
3806
3808#endif
3809
3810 //------------------------------
3811 // UNITS OF IMPEDANCE
3812 //------------------------------
3813
3822#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_IMPEDANCE_UNITS)
3823 UNIT_ADD_WITH_METRIC_PREFIXES(impedance, ohm, ohms, Ohm, unit<std::ratio<1>, units::category::impedance_unit>)
3824
3826#endif
3827
3828 //------------------------------
3829 // UNITS OF CONDUCTANCE
3830 //------------------------------
3831
3840#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONDUCTANCE_UNITS)
3841 UNIT_ADD_WITH_METRIC_PREFIXES(conductance, siemens, siemens, S, unit<std::ratio<1>, units::category::conductance_unit>)
3842
3844#endif
3845
3846 //------------------------------
3847 // UNITS OF MAGNETIC FLUX
3848 //------------------------------
3849
3858#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS)
3859 UNIT_ADD_WITH_METRIC_PREFIXES(magnetic_flux, weber, webers, Wb, unit<std::ratio<1>, units::category::magnetic_flux_unit>)
3860 UNIT_ADD(magnetic_flux, maxwell, maxwells, Mx, unit<std::ratio<1, 100000000>, webers>)
3861
3863#endif
3864
3865 //----------------------------------------
3866 // UNITS OF MAGNETIC FIELD STRENGTH
3867 //----------------------------------------
3868
3877 // Unfortunately `_T` is a WINAPI macro, so we have to use `_Te` as the tesla abbreviation.
3878#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS)
3879 UNIT_ADD_WITH_METRIC_PREFIXES(magnetic_field_strength, tesla, teslas, Te, unit<std::ratio<1>, units::category::magnetic_field_strength_unit>)
3880 UNIT_ADD(magnetic_field_strength, gauss, gauss, G, compound_unit<magnetic_flux::maxwell, inverse<squared<length::centimeter>>>)
3881
3882 UNIT_ADD_CATEGORY_TRAIT(magnetic_field_strength)
3883#endif
3884
3885 //------------------------------
3886 // UNITS OF INDUCTANCE
3887 //------------------------------
3888
3897#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_INDUCTANCE_UNITS)
3898 UNIT_ADD_WITH_METRIC_PREFIXES(inductance, henry, henries, H, unit<std::ratio<1>, units::category::inductance_unit>)
3899
3901#endif
3902
3903 //------------------------------
3904 // UNITS OF LUMINOUS FLUX
3905 //------------------------------
3906
3915#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS)
3916 UNIT_ADD_WITH_METRIC_PREFIXES(luminous_flux, lumen, lumens, lm, unit<std::ratio<1>, units::category::luminous_flux_unit>)
3917
3919#endif
3920
3921 //------------------------------
3922 // UNITS OF ILLUMINANCE
3923 //------------------------------
3924
3933#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ILLUMINANCE_UNITS)
3934 UNIT_ADD_WITH_METRIC_PREFIXES(illuminance, lux, luxes, lx, unit<std::ratio<1>, units::category::illuminance_unit>)
3935 UNIT_ADD(illuminance, footcandle, footcandles, fc, compound_unit<luminous_flux::lumen, inverse<squared<length::foot>>>)
3936 UNIT_ADD(illuminance, lumens_per_square_inch, lumens_per_square_inch, lm_per_in_sq, compound_unit<luminous_flux::lumen, inverse<squared<length::inch>>>)
3937 UNIT_ADD(illuminance, phot, phots, ph, compound_unit<luminous_flux::lumens, inverse<squared<length::centimeter>>>)
3938
3940#endif
3941
3942 //------------------------------
3943 // UNITS OF RADIATION
3944 //------------------------------
3945
3956#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_RADIATION_UNITS)
3957 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, becquerel, becquerels, Bq, unit<std::ratio<1>, units::frequency::hertz>)
3958 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, gray, grays, Gy, compound_unit<energy::joules, inverse<mass::kilogram>>)
3959 UNIT_ADD_WITH_METRIC_PREFIXES(radiation, sievert, sieverts, Sv, unit<std::ratio<1>, grays>)
3960 UNIT_ADD(radiation, curie, curies, Ci, unit<std::ratio<37>, gigabecquerels>)
3961 UNIT_ADD(radiation, rutherford, rutherfords, rd, unit<std::ratio<1>, megabecquerels>)
3962 UNIT_ADD(radiation, rad, rads, rads, unit<std::ratio<1>, centigrays>)
3963
3965#endif
3966
3967 //------------------------------
3968 // UNITS OF TORQUE
3969 //------------------------------
3970
3979#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TORQUE_UNITS)
3980 UNIT_ADD(torque, newton_meter, newton_meters, Nm, unit<std::ratio<1>, units::energy::joule>)
3981 UNIT_ADD(torque, foot_pound, foot_pounds, ftlb, compound_unit<length::foot, force::pounds>)
3982 UNIT_ADD(torque, foot_poundal, foot_poundals, ftpdl, compound_unit<length::foot, force::poundal>)
3983 UNIT_ADD(torque, inch_pound, inch_pounds, inlb, compound_unit<length::inch, force::pounds>)
3984 UNIT_ADD(torque, meter_kilogram, meter_kilograms, mkgf, compound_unit<length::meter, force::kiloponds>)
3985
3987#endif
3988
3989 //------------------------------
3990 // AREA UNITS
3991 //------------------------------
3992
4001#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_AREA_UNITS)
4002 UNIT_ADD(area, square_meter, square_meters, sq_m, unit<std::ratio<1>, units::category::area_unit>)
4003 UNIT_ADD(area, square_foot, square_feet, sq_ft, squared<length::feet>)
4004 UNIT_ADD(area, square_inch, square_inches, sq_in, squared<length::inch>)
4005 UNIT_ADD(area, square_mile, square_miles, sq_mi, squared<length::miles>)
4006 UNIT_ADD(area, square_kilometer, square_kilometers, sq_km, squared<length::kilometers>)
4007 UNIT_ADD(area, hectare, hectares, ha, unit<std::ratio<10000>, square_meters>)
4008 UNIT_ADD(area, acre, acres, acre, unit<std::ratio<43560>, square_feet>)
4009
4011#endif
4012
4013 //------------------------------
4014 // UNITS OF VOLUME
4015 //------------------------------
4016
4025#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLUME_UNITS)
4026 UNIT_ADD(volume, cubic_meter, cubic_meters, cu_m, unit<std::ratio<1>, units::category::volume_unit>)
4027 UNIT_ADD(volume, cubic_millimeter, cubic_millimeters, cu_mm, cubed<length::millimeter>)
4028 UNIT_ADD(volume, cubic_kilometer, cubic_kilometers, cu_km, cubed<length::kilometer>)
4029 UNIT_ADD_WITH_METRIC_PREFIXES(volume, liter, liters, L, cubed<deci<length::meter>>)
4030 UNIT_ADD(volume, cubic_inch, cubic_inches, cu_in, cubed<length::inches>)
4031 UNIT_ADD(volume, cubic_foot, cubic_feet, cu_ft, cubed<length::feet>)
4032 UNIT_ADD(volume, cubic_yard, cubic_yards, cu_yd, cubed<length::yards>)
4033 UNIT_ADD(volume, cubic_mile, cubic_miles, cu_mi, cubed<length::miles>)
4034 UNIT_ADD(volume, gallon, gallons, gal, unit<std::ratio<231>, cubic_inches>)
4035 UNIT_ADD(volume, quart, quarts, qt, unit<std::ratio<1, 4>, gallons>)
4036 UNIT_ADD(volume, pint, pints, pt, unit<std::ratio<1, 2>, quarts>)
4037 UNIT_ADD(volume, cup, cups, c, unit<std::ratio<1, 2>, pints>)
4038 UNIT_ADD(volume, fluid_ounce, fluid_ounces, fl_oz, unit<std::ratio<1, 8>, cups>)
4039 UNIT_ADD(volume, barrel, barrels, bl, unit<std::ratio<42>, gallons>)
4040 UNIT_ADD(volume, bushel, bushels, bu, unit<std::ratio<215042, 100>, cubic_inches>)
4041 UNIT_ADD(volume, cord, cords, cord, unit<std::ratio<128>, cubic_feet>)
4042 UNIT_ADD(volume, cubic_fathom, cubic_fathoms, cu_fm, cubed<length::fathom>)
4043 UNIT_ADD(volume, tablespoon, tablespoons, tbsp, unit<std::ratio<1, 2>, fluid_ounces>)
4044 UNIT_ADD(volume, teaspoon, teaspoons, tsp, unit<std::ratio<1, 6>, fluid_ounces>)
4045 UNIT_ADD(volume, pinch, pinches, pinch, unit<std::ratio<1, 8>, teaspoons>)
4046 UNIT_ADD(volume, dash, dashes, dash, unit<std::ratio<1, 2>, pinches>)
4047 UNIT_ADD(volume, drop, drops, drop, unit<std::ratio<1, 360>, fluid_ounces>)
4048 UNIT_ADD(volume, fifth, fifths, fifth, unit<std::ratio<1, 5>, gallons>)
4049 UNIT_ADD(volume, dram, drams, dr, unit<std::ratio<1, 8>, fluid_ounces>)
4050 UNIT_ADD(volume, gill, gills, gi, unit<std::ratio<4>, fluid_ounces>)
4051 UNIT_ADD(volume, peck, pecks, pk, unit<std::ratio<1, 4>, bushels>)
4052 UNIT_ADD(volume, sack, sacks, sacks, unit<std::ratio<3>, bushels>)
4053 UNIT_ADD(volume, shot, shots, shots, unit<std::ratio<3, 2>, fluid_ounces>)
4054 UNIT_ADD(volume, strike, strikes, strikes, unit<std::ratio<2>, bushels>)
4055
4057#endif
4058
4059 //------------------------------
4060 // UNITS OF DENSITY
4061 //------------------------------
4062
4071#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DENSITY_UNITS)
4072 UNIT_ADD(density, kilograms_per_cubic_meter, kilograms_per_cubic_meter, kg_per_cu_m, unit<std::ratio<1>, units::category::density_unit>)
4073 UNIT_ADD(density, grams_per_milliliter, grams_per_milliliter, g_per_mL, compound_unit<mass::grams, inverse<volume::milliliter>>)
4074 UNIT_ADD(density, kilograms_per_liter, kilograms_per_liter, kg_per_L, unit<std::ratio<1>, compound_unit<mass::grams, inverse<volume::milliliter>>>)
4075 UNIT_ADD(density, ounces_per_cubic_foot, ounces_per_cubic_foot, oz_per_cu_ft, compound_unit<mass::ounces, inverse<volume::cubic_foot>>)
4076 UNIT_ADD(density, ounces_per_cubic_inch, ounces_per_cubic_inch, oz_per_cu_in, compound_unit<mass::ounces, inverse<volume::cubic_inch>>)
4077 UNIT_ADD(density, ounces_per_gallon, ounces_per_gallon, oz_per_gal, compound_unit<mass::ounces, inverse<volume::gallon>>)
4078 UNIT_ADD(density, pounds_per_cubic_foot, pounds_per_cubic_foot, lb_per_cu_ft, compound_unit<mass::pounds, inverse<volume::cubic_foot>>)
4079 UNIT_ADD(density, pounds_per_cubic_inch, pounds_per_cubic_inch, lb_per_cu_in, compound_unit<mass::pounds, inverse<volume::cubic_inch>>)
4080 UNIT_ADD(density, pounds_per_gallon, pounds_per_gallon, lb_per_gal, compound_unit<mass::pounds, inverse<volume::gallon>>)
4081 UNIT_ADD(density, slugs_per_cubic_foot, slugs_per_cubic_foot, slug_per_cu_ft, compound_unit<mass::slugs, inverse<volume::cubic_foot>>)
4082
4084#endif
4085
4086 //------------------------------
4087 // UNITS OF CONCENTRATION
4088 //------------------------------
4089
4098#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONCENTRATION_UNITS)
4099 UNIT_ADD(concentration, ppm, parts_per_million, ppm, unit<std::ratio<1, 1000000>, units::category::scalar_unit>)
4100 UNIT_ADD(concentration, ppb, parts_per_billion, ppb, unit<std::ratio<1, 1000>, parts_per_million>)
4101 UNIT_ADD(concentration, ppt, parts_per_trillion, ppt, unit<std::ratio<1, 1000>, parts_per_billion>)
4102 UNIT_ADD(concentration, percent, percent, pct, unit<std::ratio<1, 100>, units::category::scalar_unit>)
4103
4105#endif
4106
4107 //------------------------------
4108 // UNITS OF DATA
4109 //------------------------------
4110
4119#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_UNITS)
4120 UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data, byte, bytes, B, unit<std::ratio<1>, units::category::data_unit>)
4121 UNIT_ADD(data, exabyte, exabytes, EB, unit<std::ratio<1000>, petabytes>)
4122 UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data, bit, bits, b, unit<std::ratio<1, 8>, byte>)
4123 UNIT_ADD(data, exabit, exabits, Eb, unit<std::ratio<1000>, petabits>)
4124
4126#endif
4127
4128 //------------------------------
4129 // UNITS OF DATA TRANSFER
4130 //------------------------------
4131
4140#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS)
4141 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>)
4142 UNIT_ADD(data_transfer_rate, exabytes_per_second, exabytes_per_second, EBps, unit<std::ratio<1000>, petabytes_per_second>)
4143 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>)
4144 UNIT_ADD(data_transfer_rate, exabits_per_second, exabits_per_second, Ebps, unit<std::ratio<1000>, petabits_per_second>)
4145
4146 UNIT_ADD_CATEGORY_TRAIT(data_transfer_rate)
4147#endif
4148
4149 //------------------------------
4150 // CONSTANTS
4151 //------------------------------
4152
4157#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONSTANTS_UNITS)
4158 namespace constants
4159 {
4165 using PI = unit<std::ratio<1>, dimensionless::scalar, std::ratio<1>>;
4166
4167 static constexpr const unit_t<PI> pi(1);
4168 static constexpr const velocity::meters_per_second_t c(299792458.0);
4170 static constexpr const unit_t<compound_unit<energy::joule, time::seconds>> h(6.626070040e-34);
4171 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)));
4172 static constexpr const unit_t<compound_unit<capacitance::farad, inverse<length::meter>>> epsilon0(1.0 / (mu0 * math::cpow<2>(c)));
4173 static constexpr const impedance::ohm_t Z0(mu0 * c);
4175 static constexpr const charge::coulomb_t e(1.6021766208e-19);
4176 static constexpr const mass::kilogram_t m_e(9.10938356e-31);
4177 static constexpr const mass::kilogram_t m_p(1.672621898e-27);
4179 static constexpr const unit_t<inverse<substance::mol>> N_A(6.022140857e23);
4183 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)));
4185 }
4186#endif
4187
4188 //----------------------------------
4189 // UNIT-ENABLED CMATH FUNCTIONS
4190 //----------------------------------
4191
4197 namespace math
4198 {
4199
4200 //----------------------------------
4201 // MIN/MAX FUNCTIONS
4202 //----------------------------------
4203
4204 template<class UnitTypeLhs, class UnitTypeRhs>
4205 UnitTypeLhs min(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4206 {
4207 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4208 UnitTypeLhs r(rhs);
4209 return (lhs < r ? lhs : r);
4210 }
4211
4212 template<class UnitTypeLhs, class UnitTypeRhs>
4213 UnitTypeLhs max(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4214 {
4215 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4216 UnitTypeLhs r(rhs);
4217 return (lhs > r ? lhs : r);
4218 }
4219
4220 //----------------------------------
4221 // TRIGONOMETRIC FUNCTIONS
4222 //----------------------------------
4223
4232#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4233 template<class AngleUnit>
4234 dimensionless::scalar_t cos(const AngleUnit angle) noexcept
4235 {
4236 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4237 return dimensionless::scalar_t(std::cos(angle.template convert<angle::radian>()()));
4238 }
4239#endif
4240
4249#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4250 template<class AngleUnit>
4251 dimensionless::scalar_t sin(const AngleUnit angle) noexcept
4252 {
4253 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4254 return dimensionless::scalar_t(std::sin(angle.template convert<angle::radian>()()));
4255 }
4256#endif
4265#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4266 template<class AngleUnit>
4267 dimensionless::scalar_t tan(const AngleUnit angle) noexcept
4268 {
4269 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4270 return dimensionless::scalar_t(std::tan(angle.template convert<angle::radian>()()));
4271 }
4272#endif
4273
4281#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4282 template<class ScalarUnit>
4283 angle::radian_t acos(const ScalarUnit x) noexcept
4284 {
4285 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4286 return angle::radian_t(std::acos(x.value()));
4287 }
4288#endif
4289
4297#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4298 template<class ScalarUnit>
4299 angle::radian_t asin(const ScalarUnit x) noexcept
4300 {
4301 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4302 return angle::radian_t(std::asin(x.value()));
4303 }
4304#endif
4305
4317#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4318 template<class ScalarUnit>
4319 angle::radian_t atan(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::atan(x.value()));
4323 }
4324#endif
4325
4334#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4335 template<class Y, class X>
4336 angle::radian_t atan2(const Y y, const X x) noexcept
4337 {
4338 static_assert(traits::is_dimensionless_unit<decltype(y/x)>::value, "The quantity y/x must yield a dimensionless ratio.");
4339
4340 // X and Y could be different length units, so normalize them
4341 return angle::radian_t(std::atan2(y.template convert<typename units::traits::unit_t_traits<X>::unit_type>()(), x()));
4342 }
4343#endif
4344
4345 //----------------------------------
4346 // HYPERBOLIC TRIG FUNCTIONS
4347 //----------------------------------
4348
4357#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4358 template<class AngleUnit>
4359 dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
4360 {
4361 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4362 return dimensionless::scalar_t(std::cosh(angle.template convert<angle::radian>()()));
4363 }
4364#endif
4365
4374#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4375 template<class AngleUnit>
4376 dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
4377 {
4378 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4379 return dimensionless::scalar_t(std::sinh(angle.template convert<angle::radian>()()));
4380 }
4381#endif
4382
4391#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4392 template<class AngleUnit>
4393 dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
4394 {
4395 static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4396 return dimensionless::scalar_t(std::tanh(angle.template convert<angle::radian>()()));
4397 }
4398#endif
4399
4408#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4409 template<class ScalarUnit>
4410 angle::radian_t acosh(const ScalarUnit x) noexcept
4411 {
4412 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4413 return angle::radian_t(std::acosh(x.value()));
4414 }
4415#endif
4416
4424#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4425 template<class ScalarUnit>
4426 angle::radian_t asinh(const ScalarUnit x) noexcept
4427 {
4428 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4429 return angle::radian_t(std::asinh(x.value()));
4430 }
4431#endif
4432
4442#if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4443 template<class ScalarUnit>
4444 angle::radian_t atanh(const ScalarUnit x) noexcept
4445 {
4446 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4447 return angle::radian_t(std::atanh(x.value()));
4448 }
4449#endif
4450
4451 //----------------------------------
4452 // TRANSCENDENTAL FUNCTIONS
4453 //----------------------------------
4454
4455 // it makes NO SENSE to put dimensioned units into a transcendental function, and if you think it does you are
4456 // demonstrably wrong. https://en.wikipedia.org/wiki/Transcendental_function#Dimensional_analysis
4457
4467 template<class ScalarUnit>
4468 dimensionless::scalar_t exp(const ScalarUnit x) noexcept
4469 {
4470 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4471 return dimensionless::scalar_t(std::exp(x.value()));
4472 }
4473
4483 template<class ScalarUnit>
4484 dimensionless::scalar_t log(const ScalarUnit x) noexcept
4485 {
4486 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4487 return dimensionless::scalar_t(std::log(x.value()));
4488 }
4489
4498 template<class ScalarUnit>
4499 dimensionless::scalar_t log10(const ScalarUnit x) noexcept
4500 {
4501 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4502 return dimensionless::scalar_t(std::log10(x.value()));
4503 }
4504
4516 template<class ScalarUnit>
4517 dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit* intpart) noexcept
4518 {
4519 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4520
4521 UNIT_LIB_DEFAULT_TYPE intp;
4522 dimensionless::scalar_t fracpart = dimensionless::scalar_t(std::modf(x.value(), &intp));
4523 *intpart = intp;
4524 return fracpart;
4525 }
4526
4534 template<class ScalarUnit>
4535 dimensionless::scalar_t exp2(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::exp2(x.value()));
4539 }
4540
4549 template<class ScalarUnit>
4550 dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
4551 {
4552 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4553 return dimensionless::scalar_t(std::expm1(x.value()));
4554 }
4555
4565 template<class ScalarUnit>
4566 dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
4567 {
4568 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4569 return dimensionless::scalar_t(std::log1p(x.value()));
4570 }
4571
4580 template<class ScalarUnit>
4581 dimensionless::scalar_t log2(const ScalarUnit x) noexcept
4582 {
4583 static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4584 return dimensionless::scalar_t(std::log2(x.value()));
4585 }
4586
4587 //----------------------------------
4588 // POWER FUNCTIONS
4589 //----------------------------------
4590
4591 /* pow is implemented earlier in the library since a lot of the unit definitions depend on it */
4592
4605 template<class UnitType, std::enable_if_t<units::traits::has_linear_scale<UnitType>::value, int> = 0>
4606 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>
4607 {
4608 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>
4609 (std::sqrt(value()));
4610 }
4611
4621 template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<units::traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
4622 inline UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y)
4623 {
4624 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of hypot() function are not compatible units.");
4625 return UnitTypeLhs(std::hypot(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4626 }
4627
4628 //----------------------------------
4629 // ROUNDING FUNCTIONS
4630 //----------------------------------
4631
4639 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4640 UnitType ceil(const UnitType x) noexcept
4641 {
4642 return UnitType(std::ceil(x()));
4643 }
4644
4652 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4653 UnitType floor(const UnitType x) noexcept
4654 {
4655 return UnitType(std::floor(x()));
4656 }
4657
4666 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4667 UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
4668 {
4669 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmod() function are not compatible units.");
4670 return UnitTypeLhs(std::fmod(numer(), denom.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4671 }
4672
4681 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4682 UnitType trunc(const UnitType x) noexcept
4683 {
4684 return UnitType(std::trunc(x()));
4685 }
4686
4687
4696 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4697 UnitType round(const UnitType x) noexcept
4698 {
4699 return UnitType(std::round(x()));
4700 }
4701
4702 //----------------------------------
4703 // FLOATING POINT MANIPULATION
4704 //----------------------------------
4705
4715 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4716 UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4717 {
4718 return UnitTypeLhs(std::copysign(x(), y())); // no need for conversion to get the correct sign.
4719 }
4720
4722 template<class UnitTypeLhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value>>
4723 UnitTypeLhs copysign(const UnitTypeLhs x, const UNIT_LIB_DEFAULT_TYPE y) noexcept
4724 {
4725 return UnitTypeLhs(std::copysign(x(), y));
4726 }
4727
4728 //----------------------------------
4729 // MIN / MAX / DIFFERENCE
4730 //----------------------------------
4731
4742 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4743 UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4744 {
4745 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fdim() function are not compatible units.");
4746 return UnitTypeLhs(std::fdim(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4747 }
4748
4759 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4760 UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4761 {
4762 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmax() function are not compatible units.");
4763 return UnitTypeLhs(std::fmax(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4764 }
4765
4777 template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4778 UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4779 {
4780 static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmin() function are not compatible units.");
4781 return UnitTypeLhs(std::fmin(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4782 }
4783
4784 //----------------------------------
4785 // OTHER FUNCTIONS
4786 //----------------------------------
4787
4795 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4796 UnitType fabs(const UnitType x) noexcept
4797 {
4798 return UnitType(std::fabs(x()));
4799 }
4800
4808 template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4809 UnitType abs(const UnitType x) noexcept
4810 {
4811 return UnitType(std::fabs(x()));
4812 }
4813
4824 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>>
4825 auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x * y)
4826 {
4827 using resultType = decltype(x * y);
4828 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.");
4829 return resultType(std::fma(x(), y(), resultType(z)()));
4830 }
4831
4832 } // end namespace math
4833} // end namespace units
4834
4835//------------------------------
4836// std::numeric_limits
4837//------------------------------
4838
4839namespace std
4840{
4841 template<class Units, typename T, template<typename> class NonLinearScale>
4842 class numeric_limits<units::unit_t<Units, T, NonLinearScale>>
4843 {
4844 public:
4845 static constexpr units::unit_t<Units, T, NonLinearScale> min()
4846 {
4847 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::min());
4848 }
4849 static constexpr units::unit_t<Units, T, NonLinearScale> max()
4850 {
4851 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::max());
4852 }
4853 static constexpr units::unit_t<Units, T, NonLinearScale> lowest()
4854 {
4855 return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::lowest());
4856 }
4857 static constexpr bool is_integer = std::numeric_limits<T>::is_integer;
4858 static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
4859 };
4860}
4861
4862#ifdef _MSC_VER
4863# if _MSC_VER <= 1800
4864# pragma warning(pop)
4865# undef constexpr
4866# pragma pop_macro("constexpr")
4867# undef noexcept
4868# pragma pop_macro("noexcept")
4869# undef _ALLOW_KEYWORD_MACROS
4870# endif // _MSC_VER < 1800
4871# pragma pop_macro("pascal")
4872#endif // _MSC_VER
4873
4874#endif // units_h__
4875
4876// For Emacs
4877// Local Variables:
4878// Mode: C++
4879// c-basic-offset: 2
4880// fill-column: 116
4881// tab-width: 4
4882// End:
Container for values which represent quantities of a given unit.
Definition: units.h:1910
constexpr bool operator<(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than
Definition: units.h:2012
constexpr bool operator<=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than or equal
Definition: units.h:2024
constexpr unit_t< U > convert() const noexcept
conversion
Definition: units.h:2127
unit_t & operator=(const Ty &rhs) noexcept
assignment
Definition: units.h:1999
constexpr unit_t(const std::chrono::duration< Rep, Period > &value) noexcept
chrono constructor
Definition: units.h:1963
constexpr underlying_type value() const noexcept
unit value
Definition: units.h:2091
constexpr unit_t(const Ty value) noexcept
constructor
Definition: units.h:1952
constexpr unit_t(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
copy constructor (converting)
Definition: units.h:1975
constexpr const char * name() const noexcept
returns the unit name
Definition: units.h:2167
constexpr Ty toLinearized() const noexcept
linearized unit value
Definition: units.h:2112
constexpr Ty to() const noexcept
unit value
Definition: units.h:2101
constexpr bool operator!=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
inequality
Definition: units.h:2082
Units unit_type
Type of unit the unit_t represents (e.g. meters)
Definition: units.h:1924
constexpr bool operator>(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than
Definition: units.h:2036
T value_type
Synonym for underlying type. May be removed in future versions. Prefer underlying_type.
Definition: units.h:1923
constexpr bool operator==(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
equality
Definition: units.h:2061
constexpr unit_t(const T value, const Args &... args) noexcept
constructor
Definition: units.h:1941
constexpr const char * abbreviation() const noexcept
returns the unit abbreviation
Definition: units.h:2175
NonLinearScale< T > non_linear_scale_type
Type of the non-linear scale of the unit_t (e.g. linear_scale)
Definition: units.h:1921
constexpr bool operator>=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than or equal
Definition: units.h:2048
constexpr unit_t()=default
default constructor.
unit_t & operator=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
assignment
Definition: units.h:1987
T underlying_type
Type of the underlying storage of the unit_t (e.g. double)
Definition: units.h:1922
constexpr T unit_cast(const Units &value) noexcept
Casts a unit container to an arithmetic type.
Definition: units.h:2376
static constexpr T convert(const T &value) noexcept
converts a value from one type to another.
Definition: units.h:1636
typename units::detail::Sqrt< Ratio, std::ratio< 1, Eps > >::type ratio_sqrt
Calculate square root of a ratio at compile-time.
Definition: units.h:1327
constexpr UnitType make_unit(const T value) noexcept
Constructs a unit container from an arithmetic type.
Definition: units.h:2201
typename units::detail::prefix< std::peta, U >::type peta
Represents the type of class U with the metric 'peta' prefix appended.
Definition: units.h:1462
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:1475
typename units::detail::prefix< std::milli, U >::type milli
Represents the type of class U with the metric 'milli' prefix appended.
Definition: units.h:1453
typename units::detail::inverse_impl< U >::type inverse
represents the inverse unit type of class U.
Definition: units.h:1105
typename units::detail::prefix< std::micro, U >::type micro
Represents the type of class U with the metric 'micro' prefix appended.
Definition: units.h:1452
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:1473
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:1477
typename units::detail::prefix< std::giga, U >::type giga
Represents the type of class U with the metric 'giga' prefix appended.
Definition: units.h:1460
typename units::detail::squared_impl< U >::type squared
represents the unit type of class U squared
Definition: units.h:1136
typename units::detail::prefix< std::deca, U >::type deca
Represents the type of class U with the metric 'deca' prefix appended.
Definition: units.h:1456
typename units::detail::prefix< std::deci, U >::type deci
Represents the type of class U with the metric 'deci' prefix appended.
Definition: units.h:1455
typename units::detail::cubed_impl< U >::type cubed
represents the type of class U cubed.
Definition: units.h:1166
typename units::detail::prefix< std::femto, U >::type femto
Represents the type of class U with the metric 'femto' prefix appended.
Definition: units.h:1449
typename units::detail::prefix< std::pico, U >::type pico
Represents the type of class U with the metric 'pico' prefix appended.
Definition: units.h:1450
typename units::detail::prefix< std::tera, U >::type tera
Represents the type of class U with the metric 'tera' prefix appended.
Definition: units.h:1461
typename units::detail::prefix< std::hecto, U >::type hecto
Represents the type of class U with the metric 'hecto' prefix appended.
Definition: units.h:1457
typename units::detail::prefix< std::atto, U >::type atto
Represents the type of class U with the metric 'atto' prefix appended.
Definition: units.h:1448
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:1474
typename units::detail::prefix< std::exa, U >::type exa
Represents the type of class U with the metric 'exa' prefix appended.
Definition: units.h:1463
typename units::detail::sqrt_impl< U, Eps >::type square_root
represents the square root of type class U.
Definition: units.h:1372
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:1476
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:1472
typename units::detail::prefix< std::centi, U >::type centi
Represents the type of class U with the metric 'centi' prefix appended.
Definition: units.h:1454
typename units::detail::prefix< std::nano, U >::type nano
Represents the type of class U with the metric 'nano' prefix appended.
Definition: units.h:1451
typename units::detail::prefix< std::mega, U >::type mega
Represents the type of class U with the metric 'mega' prefix appended.
Definition: units.h:1459
typename units::detail::prefix< std::kilo, U >::type kilo
Represents the type of class U with the metric 'kilo' prefix appended.
Definition: units.h:1458
UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Maximum value.
Definition: units.h:4760
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: units.h:4809
angle::radian_t acosh(const ScalarUnit x) noexcept
Compute arc hyperbolic cosine.
Definition: units.h:4410
UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Minimum value.
Definition: units.h:4778
UnitTypeLhs hypot(const UnitTypeLhs &x, const UnitTypeRhs &y)
Computes the square root of the sum-of-squares of x and y.
Definition: units.h:4622
dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition: units.h:4468
dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
Compute hyperbolic sine.
Definition: units.h:4376
UnitType round(const UnitType x) noexcept
Round to nearest.
Definition: units.h:4697
dimensionless::scalar_t tan(const AngleUnit angle) noexcept
Compute tangent.
Definition: units.h:4267
UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
Compute remainder of division.
Definition: units.h:4667
angle::radian_t asin(const ScalarUnit x) noexcept
Compute arc sine.
Definition: units.h:4299
auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x *y)
Multiply-add.
Definition: units.h:4825
UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Positive difference.
Definition: units.h:4743
angle::radian_t atanh(const ScalarUnit x) noexcept
Compute arc hyperbolic tangent.
Definition: units.h:4444
angle::radian_t acos(const ScalarUnit x) noexcept
Compute arc cosine.
Definition: units.h:4283
angle::radian_t atan2(const Y y, const X x) noexcept
Compute arc tangent with two parameters.
Definition: units.h:4336
dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit *intpart) noexcept
Break into fractional and integral parts.
Definition: units.h:4517
dimensionless::scalar_t exp2(const ScalarUnit x) noexcept
Compute binary exponential function.
Definition: units.h:4535
dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
Compute exponential minus one.
Definition: units.h:4550
UnitType fabs(const UnitType x) noexcept
Compute absolute value.
Definition: units.h:4796
dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
Compute hyperbolic cosine.
Definition: units.h:4359
angle::radian_t atan(const ScalarUnit x) noexcept
Compute arc tangent.
Definition: units.h:4319
dimensionless::scalar_t log2(const ScalarUnit x) noexcept
Compute binary logarithm.
Definition: units.h:4581
dimensionless::scalar_t cos(const AngleUnit angle) noexcept
Compute cosine.
Definition: units.h:4234
dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
Compute hyperbolic tangent.
Definition: units.h:4393
UnitType floor(const UnitType x) noexcept
Round down value.
Definition: units.h:4653
UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Copy sign.
Definition: units.h:4716
UnitType trunc(const UnitType x) noexcept
Truncate value.
Definition: units.h:4682
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:4606
dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition: units.h:4484
dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
Compute logarithm plus one.
Definition: units.h:4566
dimensionless::scalar_t log10(const ScalarUnit x) noexcept
Compute common logarithm.
Definition: units.h:4499
dimensionless::scalar_t sin(const AngleUnit angle) noexcept
Compute sine.
Definition: units.h:4251
UnitType ceil(const UnitType x) noexcept
Round up value.
Definition: units.h:4640
angle::radian_t asinh(const ScalarUnit x) noexcept
Compute arc hyperbolic sine.
Definition: units.h:4426
typename units::detail::compound_impl< U, Us... >::type compound_unit
Represents a unit type made up from other units.
Definition: units.h:1405
STL namespace.
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > time_unit
Represents an SI base unit of time.
Definition: units.h:770
base_unit< detail::meter_ratio< 0 >, std::ratio< 1 > > mass_unit
Represents an SI base unit of mass.
Definition: units.h:769
base_unit< detail::meter_ratio<-3 >, std::ratio< 1 > > density_unit
Represents an SI derived unit of density.
Definition: units.h:805
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:793
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:782
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:791
base_unit< detail::meter_ratio< 1 > > length_unit
Represents an SI base unit of length.
Definition: units.h:768
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:775
base_unit concentration_unit
Represents a unit of concentration.
Definition: units.h:806
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > energy_unit
Represents an SI derived unit of energy.
Definition: units.h:787
base_unit< detail::meter_ratio< 3 > > volume_unit
Represents an SI derived unit of volume.
Definition: units.h:804
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:797
base_unit dimensionless_unit
Represents a quantity with no dimension.
Definition: units.h:764
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:807
base_unit< detail::meter_ratio<-1 >, std::ratio< 1 >, std::ratio<-2 > > pressure_unit
Represents an SI derived unit of pressure.
Definition: units.h:785
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-2 > > acceleration_unit
Represents an SI derived unit of acceleration.
Definition: units.h:783
base_unit scalar_unit
Represents a quantity with no dimension.
Definition: units.h:763
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-3 > > power_unit
Represents an SI derived unit of power.
Definition: units.h:788
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > frequency_unit
Represents an SI derived unit of frequency.
Definition: units.h:780
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:771
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:772
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:786
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:779
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:774
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:789
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > radioactivity_unit
Represents an SI derived unit of radioactivity.
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< 1 > > luminous_flux_unit
Represents an SI derived unit of luminous flux.
Definition: units.h:796
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > torque_unit
Represents an SI derived unit of torque.
Definition: units.h:802
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:795
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-1 > > velocity_unit
Represents an SI derived unit of velocity.
Definition: units.h:781
base_unit< detail::meter_ratio< 1 >, std::ratio< 1 >, std::ratio<-2 > > force_unit
Represents an SI derived unit of force.
Definition: units.h:784
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:808
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:790
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:792
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:794
base_unit< detail::meter_ratio< 2 > > area_unit
Represents an SI derived unit of area.
Definition: units.h:803
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:773
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.
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:2811
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:2796
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:903
Unit Conversion Library namespace.
Definition: units.h:94
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:2618
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:2562
Class representing SI base unit types.
Definition: units.h:730
unit_t scale for representing decibel values.
Definition: units.h:2831
T m_value
linearized value
Definition: units.h:2845
unit_t scale which is linear
Definition: units.h:2461
constexpr T operator()() const noexcept
returns value.
Definition: units.h:2472
T m_value
linearized value.
Definition: units.h:2474
constexpr linear_scale()=default
default constructor.
constexpr linear_scale(const T &value, Args &&...) noexcept
constructor.
Definition: units.h:2471
Trait which tests whether a type is inherited from a decibel scale.
Definition: units.h:2417
Trait which tests whether a type is inherited from a linear scale.
Definition: units.h:2399
Definition: units.h:3479
Trait which tests if a class is a base_unit type.
Definition: units.h:667
Trait which tests whether two container types derived from unit_t are convertible to each other.
Definition: units.h:1812
Trait which checks whether two units can be converted to each other.
Definition: units.h:1500
Definition: units.h:2497
Trait which tests that class T meets the requirements for a non-linear scale.
Definition: units.h:1735
Trait that tests whether a type represents a std::ratio.
Definition: units.h:569
Trait which tests whether two types has the same non-linear scale.
Definition: units.h:2437
Traits which tests if a class is a unit
Definition: units.h:1850
Trait which tests whether type T is a unit_value_t with a unit type in the given category.
Definition: units.h:3037
Trait which tests whether a type is a unit_value_t representing the given unit type.
Definition: units.h:3027
Traits which tests if a class is a unit
Definition: units.h:693
adds two unit_value_t types at compile-time
Definition: units.h:3076
static constexpr const unit_t< unit_type > value() noexcept
Value of sum.
Definition: units.h:3091
divides two unit_value_t types at compile-time
Definition: units.h:3228
static constexpr const unit_t< unit_type > value() noexcept
Value of quotient.
Definition: units.h:3242
multiplies two unit_value_t types at compile-time
Definition: units.h:3178
static constexpr const unit_t< unit_type > value() noexcept
Value of product.
Definition: units.h:3192
raises unit_value_to a power at compile-time
Definition: units.h:3274
static constexpr const unit_t< unit_type > value() noexcept
Value of exponentiation.
Definition: units.h:3289
calculates square root of unit_value_t at compile-time
Definition: units.h:3321
static constexpr const unit_t< unit_type > value() noexcept
Value of square root.
Definition: units.h:3336
subtracts two unit_value_t types at compile-time
Definition: units.h:3125
static constexpr const unit_t< unit_type > value() noexcept
Value of difference.
Definition: units.h:3141
Stores a rational unit value as a compile-time constant.
Definition: units.h:3006
Type representing an arbitrary unit.
Definition: units.h:855
#define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation,...)
Macro for generating the boiler-plate code needed for a new unit.
Definition: units.h:268
#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:420
#define UNIT_ADD_CATEGORY_TRAIT(unitCategory)
Macro to create the is_category_unit type trait.
Definition: units.h:359
#define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)
Macro to create decibel container and literals for an existing unit type.
Definition: units.h:310
#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:385