Unit Conversion and Dimensional Analysis Library  2.3.0
A compile-time c++14 unit conversion library
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 <ratio>
78 #include <type_traits>
79 #include <cstdint>
80 #include <cmath>
81 #include <limits>
82 
83 #if !defined(UNIT_LIB_DISABLE_IOSTREAM)
84  #include <iostream>
85  #include <string>
86  #include <locale>
87 
88  //------------------------------
89  // STRING FORMATTER
90  //------------------------------
91 
92  namespace units
93  {
94  namespace detail
95  {
96  template <typename T> std::string to_string(const T& t)
97  {
98  std::string str{ std::to_string(t) };
99  int offset{ 1 };
100 
101  // remove trailing decimal points for integer value units. Locale aware!
102  struct lconv * lc;
103  lc = localeconv();
104  char decimalPoint = *lc->decimal_point;
105  if (str.find_last_not_of('0') == str.find(decimalPoint)) { offset = 0; }
106  str.erase(str.find_last_not_of('0') + offset, std::string::npos);
107  return str;
108  }
109  }
110  }
111 #endif
112 
113 namespace units
114 {
115  template<typename T> inline constexpr const char* name(const T&);
116  template<typename T> inline constexpr const char* abbreviation(const T&);
117 }
118 
119 //------------------------------
120 // MACROS
121 //------------------------------
122 
139 #define UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, /*definition*/...)\
140  namespace namespaceName\
141  {\
142  typedef __VA_ARGS__ namePlural; \
143  typedef namePlural nameSingular; \
144  typedef namePlural abbreviation; \
145  }
146 
154 #define UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
155  namespace namespaceName\
156  {\
157  typedef unit_t<nameSingular> nameSingular ## _t; \
158  }
159 
168 #define UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular, underlyingType)\
169  namespace namespaceName\
170  {\
171  typedef unit_t<nameSingular,underlyingType> nameSingular ## _t; \
172  }
173 
183 #if defined(UNIT_LIB_DISABLE_IOSTREAM)
184  #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)
185 #else
186  #define UNIT_ADD_IO(namespaceName, nameSingular, abbrev)\
187  namespace namespaceName\
188  {\
189  inline std::ostream& operator<<(std::ostream& os, const nameSingular ## _t& obj) \
190  {\
191  os << obj() << " "#abbrev; return os; \
192  }\
193  inline std::string to_string(const nameSingular ## _t& obj)\
194  {\
195  return units::detail::to_string(obj()) + std::string(" "#abbrev);\
196  }\
197  }
198 #endif
199 
210 #define UNIT_ADD_NAME(namespaceName, nameSingular, abbrev)\
211 template<> inline constexpr const char* name(const namespaceName::nameSingular ## _t&)\
212 {\
213  return #nameSingular;\
214 }\
215 template<> inline constexpr const char* abbreviation(const namespaceName::nameSingular ## _t&)\
216 {\
217  return #abbrev;\
218 }
219 
231 #if defined(UNIT_HAS_LITERAL_SUPPORT)
232  #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)\
233  namespace literals\
234  {\
235  inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation(long double d)\
236  {\
237  return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
238  }\
239  inline constexpr namespaceName::nameSingular ## _t operator""_ ## abbreviation (unsigned long long d)\
240  {\
241  return namespaceName::nameSingular ## _t(static_cast<namespaceName::nameSingular ## _t::underlying_type>(d));\
242  }\
243  }
244 #else
245  #define UNIT_ADD_LITERALS(namespaceName, nameSingular, abbreviation)
246 #endif
247 
267 #define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
268  UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
269  UNIT_ADD_UNIT_DEFINITION(namespaceName,nameSingular)\
270  UNIT_ADD_NAME(namespaceName,nameSingular, abbreviation)\
271  UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
272  UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
273 
294 #define UNIT_ADD_WITH_CUSTOM_TYPE(namespaceName, nameSingular, namePlural, abbreviation, underlyingType, /*definition*/...)\
295  UNIT_ADD_UNIT_TAGS(namespaceName,nameSingular, namePlural, abbreviation, __VA_ARGS__)\
296  UNIT_ADD_CUSTOM_TYPE_UNIT_DEFINITION(namespaceName,nameSingular,underlyingType)\
297  UNIT_ADD_IO(namespaceName,nameSingular, abbreviation)\
298  UNIT_ADD_LITERALS(namespaceName,nameSingular, abbreviation)
299 
309 #define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)\
310  namespace namespaceName\
311  {\
312  typedef unit_t<nameSingular, UNIT_LIB_DEFAULT_TYPE, units::decibel_scale> abbreviation ## _t; \
313  }\
314  UNIT_ADD_IO(namespaceName, abbreviation, abbreviation)\
315  UNIT_ADD_LITERALS(namespaceName, abbreviation, abbreviation)
316 
326 #define UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
327  namespace traits\
328  {\
329 \
330  namespace detail\
331  {\
332  template<typename T> struct is_ ## unitCategory ## _unit_impl : std::false_type {};\
333  template<typename C, typename U, typename P, typename T>\
334  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 {};\
335  template<typename U, typename S, template<typename> class N>\
336  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 {};\
337  }\
338 \
339  }
340 
341 #if defined(UNIT_HAS_VARIADIC_TEMPLATE_SUPPORT)
342 #define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
343  namespace traits\
344  {\
345  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> {};\
346  }
347 #else
348 #define UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)\
349  namespace traits\
350  {\
351  template<typename T1, typename T2 = T1, typename T3 = T1>\
352  struct is_ ## unitCategory ## _unit : std::integral_constant<bool, units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T1>::type>::value &&\
353  units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T2>::type>::value &&\
354  units::traits::detail::is_ ## unitCategory ## _unit_impl<typename std::decay<T3>::type>::value>{};\
355  }
356 #endif
357 
358 #define UNIT_ADD_CATEGORY_TRAIT(unitCategory)\
359  UNIT_ADD_CATEGORY_TRAIT_DETAIL(unitCategory)\
360 \
361 \
362 \
363 \
364  UNIT_ADD_IS_UNIT_CATEGORY_TRAIT(unitCategory)
365 
384 #define UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
385  UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
386  UNIT_ADD(namespaceName, femto ## nameSingular, femto ## namePlural, f ## abbreviation, femto<namePlural>)\
387  UNIT_ADD(namespaceName, pico ## nameSingular, pico ## namePlural, p ## abbreviation, pico<namePlural>)\
388  UNIT_ADD(namespaceName, nano ## nameSingular, nano ## namePlural, n ## abbreviation, nano<namePlural>)\
389  UNIT_ADD(namespaceName, micro ## nameSingular, micro ## namePlural, u ## abbreviation, micro<namePlural>)\
390  UNIT_ADD(namespaceName, milli ## nameSingular, milli ## namePlural, m ## abbreviation, milli<namePlural>)\
391  UNIT_ADD(namespaceName, centi ## nameSingular, centi ## namePlural, c ## abbreviation, centi<namePlural>)\
392  UNIT_ADD(namespaceName, deci ## nameSingular, deci ## namePlural, d ## abbreviation, deci<namePlural>)\
393  UNIT_ADD(namespaceName, deca ## nameSingular, deca ## namePlural, da ## abbreviation, deca<namePlural>)\
394  UNIT_ADD(namespaceName, hecto ## nameSingular, hecto ## namePlural, h ## abbreviation, hecto<namePlural>)\
395  UNIT_ADD(namespaceName, kilo ## nameSingular, kilo ## namePlural, k ## abbreviation, kilo<namePlural>)\
396  UNIT_ADD(namespaceName, mega ## nameSingular, mega ## namePlural, M ## abbreviation, mega<namePlural>)\
397  UNIT_ADD(namespaceName, giga ## nameSingular, giga ## namePlural, G ## abbreviation, giga<namePlural>)\
398  UNIT_ADD(namespaceName, tera ## nameSingular, tera ## namePlural, T ## abbreviation, tera<namePlural>)\
399  UNIT_ADD(namespaceName, peta ## nameSingular, peta ## namePlural, P ## abbreviation, peta<namePlural>)\
400 
401 
419 #define UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, /*definition*/...)\
420  UNIT_ADD_WITH_METRIC_PREFIXES(namespaceName, nameSingular, namePlural, abbreviation, __VA_ARGS__)\
421  UNIT_ADD(namespaceName, kibi ## nameSingular, kibi ## namePlural, Ki ## abbreviation, kibi<namePlural>)\
422  UNIT_ADD(namespaceName, mebi ## nameSingular, mebi ## namePlural, Mi ## abbreviation, mebi<namePlural>)\
423  UNIT_ADD(namespaceName, gibi ## nameSingular, gibi ## namePlural, Gi ## abbreviation, gibi<namePlural>)\
424  UNIT_ADD(namespaceName, tebi ## nameSingular, tebi ## namePlural, Ti ## abbreviation, tebi<namePlural>)\
425  UNIT_ADD(namespaceName, pebi ## nameSingular, pebi ## namePlural, Pi ## abbreviation, pebi<namePlural>)\
426  UNIT_ADD(namespaceName, exbi ## nameSingular, exbi ## namePlural, Ei ## abbreviation, exbi<namePlural>)
427 
428 //--------------------
429 // UNITS NAMESPACE
430 //--------------------
431 
436 namespace units
437 {
438  //----------------------------------
439  // DOXYGEN
440  //----------------------------------
441 
485  //------------------------------
486  // FORWARD DECLARATIONS
487  //------------------------------
488  // DOXYGEN IGNORE
490  namespace constants
491  {
492  namespace detail
493  {
494  static constexpr const UNIT_LIB_DEFAULT_TYPE PI_VAL = 3.14159265358979323846264338327950288419716939937510;
495  }
496  } // END DOXYGEN IGNORE
498 
499  //------------------------------
500  // RATIO TRAITS
501  //------------------------------
502  // DOXYGEN IGNORE
509  namespace detail
510  {
512  template<class T>
513  struct has_num_impl
514  {
515  template<class U>
516  static constexpr auto test(U*)->std::is_integral<decltype(U::num)> {return std::is_integral<decltype(U::num)>{}; }
517  template<typename>
518  static constexpr std::false_type test(...) { return std::false_type{}; }
519 
520  using type = decltype(test<T>(0));
521  };
522  }
523 
529  template<class T>
530  struct has_num : units::detail::has_num_impl<T>::type {};
531 
532  namespace detail
533  {
535  template<class T>
536  struct has_den_impl
537  {
538  template<class U>
539  static constexpr auto test(U*)->std::is_integral<decltype(U::den)> { return std::is_integral<decltype(U::den)>{}; }
540  template<typename>
541  static constexpr std::false_type test(...) { return std::false_type{}; }
542 
543  using type = decltype(test<T>(0));
544  };
545  }
546 
552  template<class T>
553  struct has_den : units::detail::has_den_impl<T>::type {};
554  // END DOXYGEN IGNORE
556 
557  namespace traits
558  {
564  template<class T>
565  struct is_ratio : std::integral_constant<bool,
566  has_num<T>::value &&
567  has_den<T>::value>
568  {};
569  }
570 
571  //------------------------------
572  // UNIT TRAITS
573  //------------------------------
574  // DOXYGEN IGNORE
580  template<class ...>
581  struct void_t { typedef void type; };
582 
586  template<bool...> struct bool_pack {};
587 
591  template<bool... Args>
592  struct all_true : std::is_same<units::bool_pack<true, Args...>, units::bool_pack<Args..., true>> {}; // DOXYGEN IGNORE
594 
598  namespace traits
599  {
600 #ifdef FOR_DOXYGEN_PURPOSES_ONLY
601 
608  template<class T>
609  struct unit_traits
610  {
611  typedef typename T::base_unit_type base_unit_type;
612  typedef typename T::conversion_ratio conversion_ratio;
613  typedef typename T::pi_exponent_ratio pi_exponent_ratio;
614  typedef typename T::translation_ratio translation_ratio;
615  };
616 #endif
617  // DOXYGEN IGNORE
621  template<class T, typename = void>
622  struct unit_traits
623  {
624  typedef void base_unit_type;
625  typedef void conversion_ratio;
626  typedef void pi_exponent_ratio;
627  typedef void translation_ratio;
628  };
629 
630  template<class T>
631  struct unit_traits
632  <T, typename void_t<
633  typename T::base_unit_type,
634  typename T::conversion_ratio,
635  typename T::pi_exponent_ratio,
636  typename T::translation_ratio>::type>
637  {
638  typedef typename T::base_unit_type base_unit_type;
639  typedef typename T::conversion_ratio conversion_ratio;
640  typedef typename T::pi_exponent_ratio pi_exponent_ratio;
641  typedef typename T::translation_ratio translation_ratio;
642  }; // END DOXYGEN IGNORE
644  }
645  // DOXYGEN IGNORE
647  namespace detail
648  {
653  struct _base_unit_t {};
654  } // END DOXYGEN IGNORE
656 
657  namespace traits
658  {
665  template<class T>
666  struct is_base_unit : std::is_base_of<units::detail::_base_unit_t, T> {};
667  }
668  // DOXYGEN IGNORE
670  namespace detail
671  {
676  struct _unit {};
677 
678  template<std::intmax_t Num, std::intmax_t Den = 1>
679  using meter_ratio = std::ratio<Num, Den>;
680  } // END DOXYGEN IGNORE
682 
683  namespace traits
684  {
691  template<class T>
692  struct is_unit : std::is_base_of<units::detail::_unit, T>::type {};
693  }
694  // end of TypeTraits
696 
697  //------------------------------
698  // BASE UNIT CLASS
699  //------------------------------
700 
719  template<class Meter = detail::meter_ratio<0>,
720  class Kilogram = std::ratio<0>,
721  class Second = std::ratio<0>,
722  class Radian = std::ratio<0>,
723  class Ampere = std::ratio<0>,
724  class Kelvin = std::ratio<0>,
725  class Mole = std::ratio<0>,
726  class Candela = std::ratio<0>,
727  class Byte = std::ratio<0>>
728  struct base_unit : units::detail::_base_unit_t
729  {
730  static_assert(traits::is_ratio<Meter>::value, "Template parameter `Meter` must be a `std::ratio` representing the exponent of meters the unit has");
731  static_assert(traits::is_ratio<Kilogram>::value, "Template parameter `Kilogram` must be a `std::ratio` representing the exponent of kilograms the unit has");
732  static_assert(traits::is_ratio<Second>::value, "Template parameter `Second` must be a `std::ratio` representing the exponent of seconds the unit has");
733  static_assert(traits::is_ratio<Ampere>::value, "Template parameter `Ampere` must be a `std::ratio` representing the exponent of amperes the unit has");
734  static_assert(traits::is_ratio<Kelvin>::value, "Template parameter `Kelvin` must be a `std::ratio` representing the exponent of kelvin the unit has");
735  static_assert(traits::is_ratio<Candela>::value, "Template parameter `Candela` must be a `std::ratio` representing the exponent of candelas the unit has");
736  static_assert(traits::is_ratio<Mole>::value, "Template parameter `Mole` must be a `std::ratio` representing the exponent of moles the unit has");
737  static_assert(traits::is_ratio<Radian>::value, "Template parameter `Radian` must be a `std::ratio` representing the exponent of radians the unit has");
738  static_assert(traits::is_ratio<Byte>::value, "Template parameter `Byte` must be a `std::ratio` representing the exponent of bytes the unit has");
739 
740  typedef Meter meter_ratio;
741  typedef Kilogram kilogram_ratio;
742  typedef Second second_ratio;
743  typedef Radian radian_ratio;
744  typedef Ampere ampere_ratio;
745  typedef Kelvin kelvin_ratio;
746  typedef Mole mole_ratio;
747  typedef Candela candela_ratio;
748  typedef Byte byte_ratio;
749  };
750 
751  //------------------------------
752  // UNIT CATEGORIES
753  //------------------------------
754 
759  namespace category
760  {
761  // SCALAR (DIMENSIONLESS) TYPES
764 
765  // SI BASE UNIT TYPES
766  // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
768  typedef base_unit<detail::meter_ratio<0>, std::ratio<1>> mass_unit;
769  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>> time_unit;
770  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> angle_unit;
771  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> current_unit;
772  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>> temperature_unit;
773  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;
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<0>, std::ratio<1>> luminous_intensity_unit;
775 
776  // SI DERIVED UNIT TYPES
777  // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
778  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;
779  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> frequency_unit;
780  typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-1>> velocity_unit;
781  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>, std::ratio<1>> angular_velocity_unit;
782  typedef base_unit<detail::meter_ratio<1>, std::ratio<0>, std::ratio<-2>> acceleration_unit;
783  typedef base_unit<detail::meter_ratio<1>, std::ratio<1>, std::ratio<-2>> force_unit;
784  typedef base_unit<detail::meter_ratio<-1>, std::ratio<1>, std::ratio<-2>> pressure_unit;
785  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<1>> charge_unit;
786  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> energy_unit;
787  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>> power_unit;
788  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-1>> voltage_unit;
789  typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<4>, std::ratio<0>, std::ratio<2>> capacitance_unit;
790  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-3>, std::ratio<0>, std::ratio<-2>> impedance_unit;
791  typedef base_unit<detail::meter_ratio<-2>, std::ratio<-1>, std::ratio<3>, std::ratio<0>, std::ratio<2>> conductance_unit;
792  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_flux_unit;
793  typedef base_unit<detail::meter_ratio<0>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-1>> magnetic_field_strength_unit;
794  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>, std::ratio<0>, std::ratio<-2>> inductance_unit;
795  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;
796  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;
797  typedef base_unit<detail::meter_ratio<0>, std::ratio<0>, std::ratio<-1>> radioactivity_unit;
798 
799  // OTHER UNIT TYPES
800  // METERS KILOGRAMS SECONDS RADIANS AMPERES KELVIN MOLE CANDELA BYTE --- CATEGORY
801  typedef base_unit<detail::meter_ratio<2>, std::ratio<1>, std::ratio<-2>> torque_unit;
804  typedef base_unit<detail::meter_ratio<-3>, std::ratio<1>> density_unit;
806  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;
807  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;
808  }
809 
810  //------------------------------
811  // UNIT CLASSES
812  //------------------------------
813  // DOXYGEN IGNORE
818  template <class, class, class, class> struct unit;
819  template<class Conversion, class... Exponents, class PiExponent, class Translation>
820  struct unit<Conversion, base_unit<Exponents...>, PiExponent, Translation> : units::detail::_unit
821  {
822  static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
823  static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
824  static_assert(traits::is_ratio<Translation>::value, "Template parameter `Translation` must be a `std::ratio` representing an additive translation required by the unit conversion.");
825 
826  typedef typename units::base_unit<Exponents...> base_unit_type;
827  typedef Conversion conversion_ratio;
828  typedef Translation translation_ratio;
829  typedef PiExponent pi_exponent_ratio;
830  }; // END DOXYGEN IGNORE
832 
852  template<class Conversion, class BaseUnit, class PiExponent = std::ratio<0>, class Translation = std::ratio<0>>
853  struct unit : units::detail::_unit
854  {
855  static_assert(traits::is_unit<BaseUnit>::value, "Template parameter `BaseUnit` must be a `unit` type.");
856  static_assert(traits::is_ratio<Conversion>::value, "Template parameter `Conversion` must be a `std::ratio` representing the conversion factor to `BaseUnit`.");
857  static_assert(traits::is_ratio<PiExponent>::value, "Template parameter `PiExponent` must be a `std::ratio` representing the exponents of Pi the unit has.");
858 
859  typedef typename units::traits::unit_traits<BaseUnit>::base_unit_type base_unit_type;
860  typedef typename std::ratio_multiply<typename BaseUnit::conversion_ratio, Conversion> conversion_ratio;
861  typedef typename std::ratio_add<typename BaseUnit::pi_exponent_ratio, PiExponent> pi_exponent_ratio;
862  typedef typename std::ratio_add<std::ratio_multiply<typename BaseUnit::conversion_ratio, Translation>, typename BaseUnit::translation_ratio> translation_ratio;
863  };
864 
865  //------------------------------
866  // BASE UNIT MANIPULATORS
867  //------------------------------
868  // DOXYGEN IGNORE
870  namespace detail
871  {
877  template<class> struct base_unit_of_impl;
878  template<class Conversion, class BaseUnit, class PiExponent, class Translation>
879  struct base_unit_of_impl<unit<Conversion, BaseUnit, PiExponent, Translation>> : base_unit_of_impl<BaseUnit> {};
880  template<class... Exponents>
881  struct base_unit_of_impl<base_unit<Exponents...>>
882  {
883  typedef base_unit<Exponents...> type;
884  };
885  template<>
886  struct base_unit_of_impl<void>
887  {
888  typedef void type;
889  };
890  } // END DOXYGEN IGNORE
892 
893  namespace traits
894  {
901  template<class U>
902  using base_unit_of = typename units::detail::base_unit_of_impl<U>::type;
903  }
904  // DOXYGEN IGNORE
906  namespace detail
907  {
913  template<class, class> struct base_unit_multiply_impl;
914  template<class... Exponents1, class... Exponents2>
915  struct base_unit_multiply_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
917  };
918 
922  template<class U1, class U2>
923  using base_unit_multiply = typename base_unit_multiply_impl<U1, U2>::type;
924 
930  template<class, class> struct base_unit_divide_impl;
931  template<class... Exponents1, class... Exponents2>
932  struct base_unit_divide_impl<base_unit<Exponents1...>, base_unit<Exponents2...>> {
933  using type = base_unit<std::ratio_subtract<Exponents1, Exponents2>...>;
934  };
935 
939  template<class U1, class U2>
940  using base_unit_divide = typename base_unit_divide_impl<U1, U2>::type;
941 
947  template<class> struct inverse_base_impl;
948 
949  template<class... Exponents>
950  struct inverse_base_impl<base_unit<Exponents...>> {
951  using type = base_unit<std::ratio_multiply<Exponents, std::ratio<-1>>...>;
952  };
953 
958  template<class U> using inverse_base = typename inverse_base_impl<U>::type;
959 
965  template<class U> struct squared_base_impl;
966  template<class... Exponents>
967  struct squared_base_impl<base_unit<Exponents...>> {
968  using type = base_unit<std::ratio_multiply<Exponents, std::ratio<2>>...>;
969  };
970 
975  template<class U> using squared_base = typename squared_base_impl<U>::type;
976 
982  template<class U> struct cubed_base_impl;
983  template<class... Exponents>
984  struct cubed_base_impl<base_unit<Exponents...>> {
985  using type = base_unit<std::ratio_multiply<Exponents, std::ratio<3>>...>;
986  };
987 
992  template<class U> using cubed_base = typename cubed_base_impl<U>::type;
993 
999  template<class U> struct sqrt_base_impl;
1000  template<class... Exponents>
1001  struct sqrt_base_impl<base_unit<Exponents...>> {
1002  using type = base_unit<std::ratio_divide<Exponents, std::ratio<2>>...>;
1003  };
1004 
1009  template<class U> using sqrt_base = typename sqrt_base_impl<U>::type;
1010 
1016  template<class U> struct cbrt_base_impl;
1017  template<class... Exponents>
1018  struct cbrt_base_impl<base_unit<Exponents...>> {
1019  using type = base_unit<std::ratio_divide<Exponents, std::ratio<3>>...>;
1020  };
1021 
1026  template<class U> using cbrt_base = typename cbrt_base_impl<U>::type;
1027  } // END DOXYGEN IGNORE
1029 
1030  //------------------------------
1031  // UNIT MANIPULATORS
1032  //------------------------------
1033  // DOXYGEN IGNORE
1035  namespace detail
1036  {
1043  template<class Unit1, class Unit2>
1044  struct unit_multiply_impl
1045  {
1046  using type = unit < std::ratio_multiply<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1047  base_unit_multiply <traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1048  std::ratio_add<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1049  std::ratio < 0 >> ;
1050  };
1051 
1056  template<class U1, class U2>
1057  using unit_multiply = typename unit_multiply_impl<U1, U2>::type;
1058 
1065  template<class Unit1, class Unit2>
1066  struct unit_divide_impl
1067  {
1068  using type = unit < std::ratio_divide<typename Unit1::conversion_ratio, typename Unit2::conversion_ratio>,
1069  base_unit_divide<traits::base_unit_of<typename Unit1::base_unit_type>, traits::base_unit_of<typename Unit2::base_unit_type>>,
1070  std::ratio_subtract<typename Unit1::pi_exponent_ratio, typename Unit2::pi_exponent_ratio>,
1071  std::ratio < 0 >> ;
1072  };
1073 
1078  template<class U1, class U2>
1079  using unit_divide = typename unit_divide_impl<U1, U2>::type;
1080 
1087  template<class Unit>
1088  struct inverse_impl
1089  {
1090  using type = unit < std::ratio<Unit::conversion_ratio::den, Unit::conversion_ratio::num>,
1091  inverse_base<traits::base_unit_of<typename units::traits::unit_traits<Unit>::base_unit_type>>,
1092  std::ratio_multiply<typename units::traits::unit_traits<Unit>::pi_exponent_ratio, std::ratio<-1>>,
1093  std::ratio < 0 >> ; // inverses are rates or change, the translation factor goes away.
1094  };
1095  } // END DOXYGEN IGNORE
1097 
1104  template<class U> using inverse = typename units::detail::inverse_impl<U>::type;
1105  // DOXYGEN IGNORE
1107  namespace detail
1108  {
1114  template<class Unit>
1115  struct squared_impl
1116  {
1117  static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1118  using Conversion = typename Unit::conversion_ratio;
1120  squared_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1121  std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1122  typename Unit::translation_ratio
1123  > ;
1124  };
1125  } // END DOXYGEN IGNORE
1127 
1134  template<class U>
1135  using squared = typename units::detail::squared_impl<U>::type;
1136  // DOXYGEN IGNORE
1138  namespace detail
1139  {
1145  template<class Unit>
1146  struct cubed_impl
1147  {
1148  static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1149  using Conversion = typename Unit::conversion_ratio;
1151  cubed_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1152  std::ratio_multiply<typename Unit::pi_exponent_ratio, std::ratio<3>>,
1153  typename Unit::translation_ratio> ;
1154  };
1155  } // END DOXYGEN IGNORE
1157 
1164  template<class U>
1165  using cubed = typename units::detail::cubed_impl<U>::type;
1166  // DOXYGEN IGNORE
1168  namespace detail
1169  {
1170  //----------------------------------
1171  // RATIO_SQRT IMPLEMENTATION
1172  //----------------------------------
1173 
1174  using Zero = std::ratio<0>;
1175  using One = std::ratio<1>;
1176  template <typename R> using Square = std::ratio_multiply<R, R>;
1177 
1178  // Find the largest std::integer N such that Predicate<N>::value is true.
1179  template <template <std::intmax_t N> class Predicate, typename enabled = void>
1180  struct BinarySearch {
1181  template <std::intmax_t N>
1182  struct SafeDouble_ {
1183  static constexpr const std::intmax_t value = 2 * N;
1184  static_assert(value > 0, "Overflows when computing 2 * N");
1185  };
1186 
1187  template <intmax_t Lower, intmax_t Upper, typename Condition1 = void, typename Condition2 = void>
1188  struct DoubleSidedSearch_ : DoubleSidedSearch_<Lower, Upper,
1189  std::integral_constant<bool, (Upper - Lower == 1)>,
1190  std::integral_constant<bool, ((Upper - Lower>1 && Predicate<Lower + (Upper - Lower) / 2>::value))>> {};
1191 
1192  template <intmax_t Lower, intmax_t Upper>
1193  struct DoubleSidedSearch_<Lower, Upper, std::false_type, std::false_type> : DoubleSidedSearch_<Lower, Lower + (Upper - Lower) / 2> {};
1194 
1195  template <intmax_t Lower, intmax_t Upper, typename Condition2>
1196  struct DoubleSidedSearch_<Lower, Upper, std::true_type, Condition2> : std::integral_constant<intmax_t, Lower>{};
1197 
1198  template <intmax_t Lower, intmax_t Upper, typename Condition1>
1199  struct DoubleSidedSearch_<Lower, Upper, Condition1, std::true_type> : DoubleSidedSearch_<Lower + (Upper - Lower) / 2, Upper>{};
1200 
1201  template <std::intmax_t Lower, class enabled1 = void>
1202  struct SingleSidedSearch_ : SingleSidedSearch_<Lower, std::integral_constant<bool, Predicate<SafeDouble_<Lower>::value>::value>>{};
1203 
1204  template <std::intmax_t Lower>
1205  struct SingleSidedSearch_<Lower, std::false_type> : DoubleSidedSearch_<Lower, SafeDouble_<Lower>::value> {};
1206 
1207  template <std::intmax_t Lower>
1208  struct SingleSidedSearch_<Lower, std::true_type> : SingleSidedSearch_<SafeDouble_<Lower>::value>{};
1209 
1210  static constexpr const std::intmax_t value = SingleSidedSearch_<1>::value;
1211  };
1212 
1213  template <template <std::intmax_t N> class Predicate>
1214  struct BinarySearch<Predicate, std::enable_if_t<!Predicate<1>::value>> : std::integral_constant<std::intmax_t, 0>{};
1215 
1216  // Find largest std::integer N such that N<=sqrt(R)
1217  template <typename R>
1218  struct Integer {
1219  template <std::intmax_t N> using Predicate_ = std::ratio_less_equal<std::ratio<N>, std::ratio_divide<R, std::ratio<N>>>;
1220  static constexpr const std::intmax_t value = BinarySearch<Predicate_>::value;
1221  };
1222 
1223  template <typename R>
1224  struct IsPerfectSquare {
1225  static constexpr const std::intmax_t DenSqrt_ = Integer<std::ratio<R::den>>::value;
1226  static constexpr const std::intmax_t NumSqrt_ = Integer<std::ratio<R::num>>::value;
1227  static constexpr const bool value =( DenSqrt_ * DenSqrt_ == R::den && NumSqrt_ * NumSqrt_ == R::num);
1228  using Sqrt = std::ratio<NumSqrt_, DenSqrt_>;
1229  };
1230 
1231  // Represents sqrt(P)-Q.
1232  template <typename Tp, typename Tq>
1233  struct Remainder {
1234  using P = Tp;
1235  using Q = Tq;
1236  };
1237 
1238  // Represents 1/R = I + Rem where R is a Remainder.
1239  template <typename R>
1240  struct Reciprocal {
1241  using P_ = typename R::P;
1242  using Q_ = typename R::Q;
1243  using Den_ = std::ratio_subtract<P_, Square<Q_>>;
1244  using A_ = std::ratio_divide<Q_, Den_>;
1245  using B_ = std::ratio_divide<P_, Square<Den_>>;
1246  static constexpr const std::intmax_t I_ = (A_::num + Integer<std::ratio_multiply<B_, Square<std::ratio<A_::den>>>>::value) / A_::den;
1247  using I = std::ratio<I_>;
1248  using Rem = Remainder<B_, std::ratio_subtract<I, A_>>;
1249  };
1250 
1251  // Expands sqrt(R) to continued fraction:
1252  // f(x)=C1+1/(C2+1/(C3+1/(...+1/(Cn+x)))) = (U*x+V)/(W*x+1) and sqrt(R)=f(Rem).
1253  // The error |f(Rem)-V| = |(U-W*V)x/(W*x+1)| <= |U-W*V|*Rem <= |U-W*V|/I' where
1254  // I' is the std::integer part of reciprocal of Rem.
1255  template <typename Tr, std::intmax_t N>
1256  struct ContinuedFraction {
1257  template <typename T>
1258  using Abs_ = std::conditional_t<std::ratio_less<T, Zero>::value, std::ratio_subtract<Zero, T>, T>;
1259 
1260  using R = Tr;
1261  using Last_ = ContinuedFraction<R, N - 1>;
1262  using Reciprocal_ = Reciprocal<typename Last_::Rem>;
1263  using Rem = typename Reciprocal_::Rem;
1264  using I_ = typename Reciprocal_::I;
1265  using Den_ = std::ratio_add<typename Last_::W, I_>;
1266  using U = std::ratio_divide<typename Last_::V, Den_>;
1267  using V = std::ratio_divide<std::ratio_add<typename Last_::U, std::ratio_multiply<typename Last_::V, I_>>, Den_>;
1268  using W = std::ratio_divide<One, Den_>;
1269  using Error = Abs_<std::ratio_divide<std::ratio_subtract<U, std::ratio_multiply<V, W>>, typename Reciprocal<Rem>::I>>;
1270  };
1271 
1272  template <typename Tr>
1273  struct ContinuedFraction<Tr, 1> {
1274  using R = Tr;
1275  using U = One;
1276  using V = std::ratio<Integer<R>::value>;
1277  using W = Zero;
1278  using Rem = Remainder<R, V>;
1279  using Error = std::ratio_divide<One, typename Reciprocal<Rem>::I>;
1280  };
1281 
1282  template <typename R, typename Eps, std::intmax_t N = 1, typename enabled = void>
1283  struct Sqrt_ : Sqrt_<R, Eps, N + 1> {};
1284 
1285  template <typename R, typename Eps, std::intmax_t N>
1286  struct Sqrt_<R, Eps, N, std::enable_if_t<std::ratio_less_equal<typename ContinuedFraction<R, N>::Error, Eps>::value>> {
1287  using type = typename ContinuedFraction<R, N>::V;
1288  };
1289 
1290  template <typename R, typename Eps, typename enabled = void>
1291  struct Sqrt {
1292  static_assert(std::ratio_greater_equal<R, Zero>::value, "R can't be negative");
1293  };
1294 
1295  template <typename R, typename Eps>
1296  struct Sqrt<R, Eps, std::enable_if_t<std::ratio_greater_equal<R, Zero>::value && IsPerfectSquare<R>::value>> {
1297  using type = typename IsPerfectSquare<R>::Sqrt;
1298  };
1299 
1300  template <typename R, typename Eps>
1301  struct Sqrt<R, Eps, std::enable_if_t<(std::ratio_greater_equal<R, Zero>::value && !IsPerfectSquare<R>::value)>> : Sqrt_<R, Eps>{};
1302  } // END DOXYGEN IGNORE
1304 
1325  template<typename Ratio, std::intmax_t Eps = 10000000000>
1326  using ratio_sqrt = typename units::detail::Sqrt<Ratio, std::ratio<1, Eps>>::type;
1327  // DOXYGEN IGNORE
1329  namespace detail
1330  {
1336  template<class Unit, std::intmax_t Eps>
1337  struct sqrt_impl
1338  {
1339  static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1340  using Conversion = typename Unit::conversion_ratio;
1341  using type = unit <ratio_sqrt<Conversion, Eps>,
1342  sqrt_base<traits::base_unit_of<typename Unit::base_unit_type>>,
1343  std::ratio_divide<typename Unit::pi_exponent_ratio, std::ratio<2>>,
1344  typename Unit::translation_ratio>;
1345  };
1346  } // END DOXYGEN IGNORE
1348 
1370  template<class U, std::intmax_t Eps = 10000000000>
1371  using square_root = typename units::detail::sqrt_impl<U, Eps>::type;
1372 
1373  //------------------------------
1374  // COMPOUND UNITS
1375  //------------------------------
1376  // DOXYGEN IGNORE
1378  namespace detail
1379  {
1385  template<class U, class... Us> struct compound_impl;
1386  template<class U> struct compound_impl<U> { using type = U; };
1387  template<class U1, class U2, class...Us>
1388  struct compound_impl<U1, U2, Us...>
1389  : compound_impl<unit_multiply<U1, U2>, Us...> {};
1390  } // END DOXYGEN IGNORE
1392 
1403  template<class U, class... Us>
1404  using compound_unit = typename units::detail::compound_impl<U, Us...>::type;
1405 
1406  //------------------------------
1407  // PREFIXES
1408  //------------------------------
1409  // DOXYGEN IGNORE
1411  namespace detail
1412  {
1417  template<class Ratio, class Unit>
1418  struct prefix
1419  {
1420  static_assert(traits::is_ratio<Ratio>::value, "Template parameter `Ratio` must be a `std::ratio`.");
1421  static_assert(traits::is_unit<Unit>::value, "Template parameter `Unit` must be a `unit` type.");
1422  typedef typename units::unit<Ratio, Unit> type;
1423  };
1424 
1426  template <int N, class U>
1427  struct power_of_ratio
1428  {
1429  typedef std::ratio_multiply<U, typename power_of_ratio<N - 1, U>::type> type;
1430  };
1431 
1433  template <class U>
1434  struct power_of_ratio<1, U>
1435  {
1436  typedef U type;
1437  };
1438  } // END DOXYGEN IGNORE
1440 
1447  template<class U> using atto = typename units::detail::prefix<std::atto, U>::type;
1448  template<class U> using femto = typename units::detail::prefix<std::femto,U>::type;
1449  template<class U> using pico = typename units::detail::prefix<std::pico, U>::type;
1450  template<class U> using nano = typename units::detail::prefix<std::nano, U>::type;
1451  template<class U> using micro = typename units::detail::prefix<std::micro,U>::type;
1452  template<class U> using milli = typename units::detail::prefix<std::milli,U>::type;
1453  template<class U> using centi = typename units::detail::prefix<std::centi,U>::type;
1454  template<class U> using deci = typename units::detail::prefix<std::deci, U>::type;
1455  template<class U> using deca = typename units::detail::prefix<std::deca, U>::type;
1456  template<class U> using hecto = typename units::detail::prefix<std::hecto,U>::type;
1457  template<class U> using kilo = typename units::detail::prefix<std::kilo, U>::type;
1458  template<class U> using mega = typename units::detail::prefix<std::mega, U>::type;
1459  template<class U> using giga = typename units::detail::prefix<std::giga, U>::type;
1460  template<class U> using tera = typename units::detail::prefix<std::tera, U>::type;
1461  template<class U> using peta = typename units::detail::prefix<std::peta, U>::type;
1462  template<class U> using exa = typename units::detail::prefix<std::exa, U>::type;
1463 
1471  template<class U> using kibi = typename units::detail::prefix<std::ratio<1024>, U>::type;
1472  template<class U> using mebi = typename units::detail::prefix<std::ratio<1048576>, U>::type;
1473  template<class U> using gibi = typename units::detail::prefix<std::ratio<1073741824>, U>::type;
1474  template<class U> using tebi = typename units::detail::prefix<std::ratio<1099511627776>, U>::type;
1475  template<class U> using pebi = typename units::detail::prefix<std::ratio<1125899906842624>, U>::type;
1476  template<class U> using exbi = typename units::detail::prefix<std::ratio<1152921504606846976>, U>::type;
1477 
1479  //------------------------------
1480  // CONVERSION TRAITS
1481  //------------------------------
1482 
1483  namespace traits
1484  {
1497  template<class U1, class U2>
1498  struct is_convertible_unit : std::is_same <traits::base_unit_of<typename units::traits::unit_traits<U1>::base_unit_type>,
1499  base_unit_of<typename units::traits::unit_traits<U2>::base_unit_type >> {};
1500  }
1501 
1502  //------------------------------
1503  // CONVERSION FUNCTION
1504  //------------------------------
1505  // DOXYGEN IGNORE
1507  namespace detail
1508  {
1509  constexpr inline UNIT_LIB_DEFAULT_TYPE pow(UNIT_LIB_DEFAULT_TYPE x, unsigned long long y)
1510  {
1511  return y == 0 ? 1.0 : x * pow(x, y - 1);
1512  }
1513 
1514  constexpr inline UNIT_LIB_DEFAULT_TYPE abs(UNIT_LIB_DEFAULT_TYPE x)
1515  {
1516  return x < 0 ? -x : x;
1517  }
1518 
1520  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1521  static inline constexpr T convert(const T& value, std::true_type, std::false_type, std::false_type) noexcept
1522  {
1523  return value;
1524  }
1525 
1527  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1528  static inline constexpr T convert(const T& value, std::true_type, std::false_type, std::true_type) noexcept
1529  {
1530  return value;
1531  }
1532 
1534  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1535  static inline constexpr T convert(const T& value, std::true_type, std::true_type, std::false_type) noexcept
1536  {
1537  return value;
1538  }
1539 
1541  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1542  static inline constexpr T convert(const T& value, std::true_type, std::true_type, std::true_type) noexcept
1543  {
1544  return value;
1545  }
1546 
1548  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1549  static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::false_type) noexcept
1550  {
1551  return ((value * Ratio::num) / Ratio::den);
1552  }
1553 
1555  // constepxr with PI in numerator
1556  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1557  static inline constexpr
1558  std::enable_if_t<(PiRatio::num / PiRatio::den >= 1 && PiRatio::num % PiRatio::den == 0), T>
1559  convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1560  {
1561  return ((value * pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den) * Ratio::num) / Ratio::den);
1562  }
1563 
1565  // constexpr with PI in denominator
1566  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1567  static inline constexpr
1568  std::enable_if_t<(PiRatio::num / PiRatio::den <= -1 && PiRatio::num % PiRatio::den == 0), T>
1569  convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1570  {
1571  return (value * Ratio::num) / (Ratio::den * pow(constants::detail::PI_VAL, -PiRatio::num / PiRatio::den));
1572  }
1573 
1575  // Not constexpr - uses std::pow
1576  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1577  static inline // sorry, this can't be constexpr!
1578  std::enable_if_t<(PiRatio::num / PiRatio::den < 1 && PiRatio::num / PiRatio::den > -1), T>
1579  convert(const T& value, std::false_type, std::true_type, std::false_type) noexcept
1580  {
1581  return ((value * std::pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den) * Ratio::num) / Ratio::den);
1582  }
1583 
1585  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1586  static inline constexpr T convert(const T& value, std::false_type, std::false_type, std::true_type) noexcept
1587  {
1588  return ((value * Ratio::num) / Ratio::den) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1589  }
1590 
1592  template<class UnitFrom, class UnitTo, class Ratio, class PiRatio, class Translation, typename T>
1593  static inline constexpr T convert(const T& value, const std::false_type, const std::true_type, const std::true_type) noexcept
1594  {
1595  return ((value * std::pow(constants::detail::PI_VAL, PiRatio::num / PiRatio::den) * Ratio::num) / Ratio::den) + (static_cast<UNIT_LIB_DEFAULT_TYPE>(Translation::num) / Translation::den);
1596  }
1597  } // END DOXYGEN IGNORE
1599 
1615  template<class UnitFrom, class UnitTo, typename T = UNIT_LIB_DEFAULT_TYPE>
1616  static inline constexpr T convert(const T& value) noexcept
1617  {
1618  static_assert(traits::is_unit<UnitFrom>::value, "Template parameter `UnitFrom` must be a `unit` type.");
1619  static_assert(traits::is_unit<UnitTo>::value, "Template parameter `UnitTo` must be a `unit` type.");
1620  static_assert(traits::is_convertible_unit<UnitFrom, UnitTo>::value, "Units are not compatible.");
1621 
1622  using Ratio = std::ratio_divide<typename UnitFrom::conversion_ratio, typename UnitTo::conversion_ratio>;
1623  using PiRatio = std::ratio_subtract<typename UnitFrom::pi_exponent_ratio, typename UnitTo::pi_exponent_ratio>;
1624  using Translation = std::ratio_divide<std::ratio_subtract<typename UnitFrom::translation_ratio, typename UnitTo::translation_ratio>, typename UnitTo::conversion_ratio>;
1625 
1626  using isSame = typename std::is_same<std::decay_t<UnitFrom>, std::decay_t<UnitTo>>::type;
1627  using piRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, PiRatio>::value)>;
1628  using translationRequired = std::integral_constant<bool, !(std::is_same<std::ratio<0>, Translation>::value)>;
1629 
1630  return units::detail::convert<UnitFrom, UnitTo, Ratio, PiRatio, Translation, T>
1631  (value, isSame{}, piRequired{}, translationRequired{});
1632  }
1633 
1634  //----------------------------------
1635  // NON-LINEAR SCALE TRAITS
1636  //----------------------------------
1637  // DOXYGEN IGNORE
1639  namespace traits
1640  {
1641  namespace detail
1642  {
1647  template<class T, class Ret>
1648  struct has_operator_parenthesis_impl
1649  {
1650  template<class U>
1651  static constexpr auto test(U*) -> decltype(std::declval<U>()()) { return decltype(std::declval<U>()()){}; }
1652  template<typename>
1653  static constexpr std::false_type test(...) { return std::false_type{}; }
1654 
1655  using type = typename std::is_same<Ret, decltype(test<T>(0))>::type;
1656  };
1657  }
1658 
1663  template<class T, class Ret>
1664  struct has_operator_parenthesis : traits::detail::has_operator_parenthesis_impl<T, Ret>::type {};
1665  }
1666 
1667  namespace traits
1668  {
1669  namespace detail
1670  {
1675  template<class T, class Ret>
1676  struct has_value_member_impl
1677  {
1678  template<class U>
1679  static constexpr auto test(U* p) -> decltype(p->m_value) { return p->m_value; }
1680  template<typename>
1681  static constexpr auto test(...)->std::false_type { return std::false_type{}; }
1682 
1683  using type = typename std::is_same<std::decay_t<Ret>, std::decay_t<decltype(test<T>(0))>>::type;
1684  };
1685  }
1686 
1691  template<class T, class Ret>
1692  struct has_value_member : traits::detail::has_value_member_impl<T, Ret>::type {};
1693  } // END DOXYGEN IGNORE
1695 
1696  namespace traits
1697  {
1709  template<class T, class Ret>
1710  struct is_nonlinear_scale : std::integral_constant<bool,
1711  std::is_default_constructible<T>::value &&
1712  has_operator_parenthesis<T, Ret>::value &&
1713  has_value_member<T, Ret>::value &&
1714  std::is_trivial<T>::value>
1715  {};
1716  }
1717 
1718  //------------------------------
1719  // UNIT_T TYPE TRAITS
1720  //------------------------------
1721 
1722  namespace traits
1723  {
1724 #ifdef FOR_DOXYGEN_PURPOSOES_ONLY
1725 
1731  template<typename T>
1732  struct unit_t_traits
1733  {
1734  typedef typename T::non_linear_scale_type non_linear_scale_type;
1735  typedef typename T::underlying_type underlying_type;
1736  typedef typename T::value_type value_type;
1737  typedef typename T::unit_type unit_type;
1738  };
1739 #endif
1740  // DOXYGEN IGNORE
1746  template<typename T, typename = void>
1747  struct unit_t_traits
1748  {
1749  typedef void non_linear_scale_type;
1750  typedef void underlying_type;
1751  typedef void value_type;
1752  typedef void unit_type;
1753  };
1754 
1760  template<typename T>
1761  struct unit_t_traits <T, typename void_t<
1762  typename T::non_linear_scale_type,
1763  typename T::underlying_type,
1764  typename T::value_type,
1765  typename T::unit_type>::type>
1766  {
1767  typedef typename T::non_linear_scale_type non_linear_scale_type;
1768  typedef typename T::underlying_type underlying_type;
1769  typedef typename T::value_type value_type;
1770  typedef typename T::unit_type unit_type;
1771  }; // END DOXYGEN IGNORE
1773  }
1774 
1775  namespace traits
1776  {
1789  template<class U1, class U2>
1790  struct is_convertible_unit_t : std::integral_constant<bool,
1791  is_convertible_unit<typename units::traits::unit_t_traits<U1>::unit_type, typename units::traits::unit_t_traits<U2>::unit_type>::value>
1792  {};
1793  }
1794 
1795  //----------------------------------
1796  // UNIT TYPE
1797  //----------------------------------
1798  // DOXYGEN IGNORE
1800  // forward declaration
1801  template<typename T> struct linear_scale;
1802  template<typename T> struct decibel_scale;
1803 
1804  namespace detail
1805  {
1810  struct _unit_t {};
1811  } // END DOXYGEN IGNORE
1813 
1814  namespace traits
1815  {
1816  // forward declaration
1817  #if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
1818  template<typename... T> struct is_dimensionless_unit;
1819  #else
1820  template<typename T1, typename T2 = T1, typename T3 = T1> struct is_dimensionless_unit;
1821  #endif
1822 
1829  template<class T>
1830  struct is_unit_t : std::is_base_of<units::detail::_unit_t, T>::type {};
1831  }
1832 
1888  template<class Units, typename T = UNIT_LIB_DEFAULT_TYPE, template<typename> class NonLinearScale = linear_scale>
1889  class unit_t : public NonLinearScale<T>, units::detail::_unit_t
1890  {
1891  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).");
1892  static_assert(traits::is_nonlinear_scale<NonLinearScale<T>, T>::value, "Template parameter `NonLinearScale` does not conform to the `is_nonlinear_scale` concept.");
1893 
1894  protected:
1895 
1896  using nls = NonLinearScale<T>;
1897  using nls::m_value;
1898 
1899  public:
1900 
1901  typedef NonLinearScale<T> non_linear_scale_type;
1902  typedef T underlying_type;
1903  typedef T value_type;
1904  typedef Units unit_type;
1905 
1910  constexpr unit_t() = default;
1911 
1920  template<class... Args>
1921  inline explicit constexpr unit_t(const T value, const Args&... args) noexcept : nls(value, args...)
1922  {
1923 
1924  }
1925 
1931  template<class Ty, class = typename std::enable_if<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>::type>
1932  inline constexpr unit_t(const Ty value) noexcept : nls(value)
1933  {
1934 
1935  }
1936 
1942  template<class Rep, class Period, class = std::enable_if_t<std::is_arithmetic<Rep>::value && traits::is_ratio<Period>::value>>
1943  inline constexpr unit_t(const std::chrono::duration<Rep, Period>& value) noexcept :
1944  nls(units::convert<unit<std::ratio<1,1000000000>, category::time_unit>, Units>(static_cast<T>(std::chrono::duration_cast<std::chrono::nanoseconds>(value).count())))
1945  {
1946 
1947  }
1948 
1954  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1955  inline constexpr unit_t(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept :
1956  nls(units::convert<UnitsRhs, Units, T>(rhs.m_value), std::true_type() /*store linear value*/)
1957  {
1958 
1959  }
1960 
1966  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1967  inline unit_t& operator=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) noexcept
1968  {
1969  nls::m_value = units::convert<UnitsRhs, Units, T>(rhs.m_value);
1970  return *this;
1971  }
1972 
1978  template<class Ty, class = std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value>>
1979  inline unit_t& operator=(const Ty& rhs) noexcept
1980  {
1981  nls::m_value = rhs;
1982  return *this;
1983  }
1984 
1991  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
1992  inline constexpr bool operator<(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
1993  {
1994  return (nls::m_value < units::convert<UnitsRhs, Units>(rhs.m_value));
1995  }
1996 
2003  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2004  inline constexpr bool operator<=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2005  {
2006  return (nls::m_value <= units::convert<UnitsRhs, Units>(rhs.m_value));
2007  }
2008 
2015  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2016  inline constexpr bool operator>(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2017  {
2018  return (nls::m_value > units::convert<UnitsRhs, Units>(rhs.m_value));
2019  }
2020 
2027  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2028  inline constexpr bool operator>=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2029  {
2030  return (nls::m_value >= units::convert<UnitsRhs, Units>(rhs.m_value));
2031  }
2032 
2040  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>
2041  inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2042  {
2043  return detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::epsilon() *
2044  detail::abs(nls::m_value + units::convert<UnitsRhs, Units>(rhs.m_value)) ||
2045  detail::abs(nls::m_value - units::convert<UnitsRhs, Units>(rhs.m_value)) < std::numeric_limits<T>::min();
2046  }
2047 
2048  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>
2049  inline constexpr bool operator==(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2050  {
2051  return nls::m_value == units::convert<UnitsRhs, Units>(rhs.m_value);
2052  }
2053 
2061  template<class UnitsRhs, typename Ty, template<typename> class NlsRhs>
2062  inline constexpr bool operator!=(const unit_t<UnitsRhs, Ty, NlsRhs>& rhs) const noexcept
2063  {
2064  return !(*this == rhs);
2065  }
2066 
2071  inline constexpr underlying_type value() const noexcept
2072  {
2073  return static_cast<underlying_type>(*this);
2074  }
2075 
2080  template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2081  inline constexpr Ty to() const noexcept
2082  {
2083  return static_cast<Ty>(*this);
2084  }
2085 
2091  template<typename Ty, class = std::enable_if_t<std::is_arithmetic<Ty>::value>>
2092  inline constexpr Ty toLinearized() const noexcept
2093  {
2094  return static_cast<Ty>(m_value);
2095  }
2096 
2106  template<class U>
2107  inline constexpr unit_t<U> convert() const noexcept
2108  {
2109  static_assert(traits::is_unit<U>::value, "Template parameter `U` must be a unit type.");
2110  return unit_t<U>(*this);
2111  }
2112 
2117  template<class Ty, std::enable_if_t<traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2118  inline constexpr operator Ty() const noexcept
2119  {
2120  // this conversion also resolves any PI exponents, by converting from a non-zero PI ratio to a zero-pi ratio.
2121  return static_cast<Ty>(units::convert<Units, unit<std::ratio<1>, units::category::scalar_unit>>((*this)()));
2122  }
2123 
2128  template<class Ty, std::enable_if_t<!traits::is_dimensionless_unit<Units>::value && std::is_arithmetic<Ty>::value, int> = 0>
2129  inline constexpr explicit operator Ty() const noexcept
2130  {
2131  return static_cast<Ty>((*this)());
2132  }
2133 
2138  template<typename U = Units, std::enable_if_t<units::traits::is_convertible_unit<U, unit<std::ratio<1>, category::time_unit>>::value, int> = 0>
2139  inline constexpr operator std::chrono::nanoseconds() const noexcept
2140  {
2141  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)())));
2142  }
2143 
2147  inline constexpr const char* name() const noexcept
2148  {
2149  return units::name(*this);
2150  }
2151 
2155  inline constexpr const char* abbreviation() const noexcept
2156  {
2157  return units::abbreviation(*this);
2158  }
2159 
2160  public:
2161 
2162  template<class U, typename Ty, template<typename> class Nlt>
2163  friend class unit_t;
2164  };
2165 
2166  //------------------------------
2167  // UNIT_T NON-MEMBER FUNCTIONS
2168  //------------------------------
2169 
2180  template<class UnitType, typename T, class = std::enable_if_t<std::is_arithmetic<T>::value>>
2181  inline constexpr UnitType make_unit(const T value) noexcept
2182  {
2183  static_assert(traits::is_unit_t<UnitType>::value, "Template parameter `UnitType` must be a unit type (_t).");
2184 
2185  return UnitType(value);
2186  }
2187 
2188 #if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2189  template<class Units, typename T, template<typename> class NonLinearScale>
2190  inline std::ostream& operator<<(std::ostream& os, const unit_t<Units, T, NonLinearScale>& obj) noexcept
2191  {
2192  using BaseUnits = unit<std::ratio<1>, typename traits::unit_traits<Units>::base_unit_type>;
2193  os << convert<Units, BaseUnits>(obj());
2194 
2195  if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0) { os << " m"; }
2196  if (traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 0 &&
2197  traits::unit_traits<Units>::base_unit_type::meter_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::meter_ratio::num; }
2198  if (traits::unit_traits<Units>::base_unit_type::meter_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::meter_ratio::den; }
2199 
2200  if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0) { os << " kg"; }
2201  if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 0 &&
2202  traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::num; }
2203  if (traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kilogram_ratio::den; }
2204 
2205  if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0) { os << " s"; }
2206  if (traits::unit_traits<Units>::base_unit_type::second_ratio::num != 0 &&
2207  traits::unit_traits<Units>::base_unit_type::second_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::second_ratio::num; }
2208  if (traits::unit_traits<Units>::base_unit_type::second_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::second_ratio::den; }
2209 
2210  if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0) { os << " A"; }
2211  if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 0 &&
2212  traits::unit_traits<Units>::base_unit_type::ampere_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::num; }
2213  if (traits::unit_traits<Units>::base_unit_type::ampere_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::ampere_ratio::den; }
2214 
2215  if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0) { os << " K"; }
2216  if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 0 &&
2217  traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num; }
2218  if (traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den; }
2219 
2220  if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0) { os << " mol"; }
2221  if (traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 0 &&
2222  traits::unit_traits<Units>::base_unit_type::mole_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::mole_ratio::num; }
2223  if (traits::unit_traits<Units>::base_unit_type::mole_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::mole_ratio::den; }
2224 
2225  if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0) { os << " cd"; }
2226  if (traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 0 &&
2227  traits::unit_traits<Units>::base_unit_type::candela_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::candela_ratio::num; }
2228  if (traits::unit_traits<Units>::base_unit_type::candela_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::candela_ratio::den; }
2229 
2230  if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0) { os << " rad"; }
2231  if (traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 0 &&
2232  traits::unit_traits<Units>::base_unit_type::radian_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::radian_ratio::num; }
2233  if (traits::unit_traits<Units>::base_unit_type::radian_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::radian_ratio::den; }
2234 
2235  if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0) { os << " b"; }
2236  if (traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 0 &&
2237  traits::unit_traits<Units>::base_unit_type::byte_ratio::num != 1) { os << "^" << traits::unit_traits<Units>::base_unit_type::byte_ratio::num; }
2238  if (traits::unit_traits<Units>::base_unit_type::byte_ratio::den != 1) { os << "/" << traits::unit_traits<Units>::base_unit_type::byte_ratio::den; }
2239 
2240  return os;
2241  }
2242 #endif
2243 
2244  template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2245  inline unit_t<Units, T, NonLinearScale>& operator+=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2246  {
2247  static_assert(traits::is_convertible_unit_t<unit_t<Units, T, NonLinearScale>, RhsType>::value ||
2248  (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2249  "parameters are not compatible units.");
2250 
2251  lhs = lhs + rhs;
2252  return lhs;
2253  }
2254 
2255  template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2256  inline unit_t<Units, T, NonLinearScale>& operator-=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2257  {
2258  static_assert(traits::is_convertible_unit_t<unit_t<Units, T, NonLinearScale>, RhsType>::value ||
2259  (traits::is_dimensionless_unit<decltype(lhs)>::value && std::is_arithmetic<RhsType>::value),
2260  "parameters are not compatible units.");
2261 
2262  lhs = lhs - rhs;
2263  return lhs;
2264  }
2265 
2266  template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2267  inline unit_t<Units, T, NonLinearScale>& operator*=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2268  {
2269  static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2270  "right-hand side parameter must be dimensionless.");
2271 
2272  lhs = lhs * rhs;
2273  return lhs;
2274  }
2275 
2276  template<class Units, typename T, template<typename> class NonLinearScale, typename RhsType>
2277  inline unit_t<Units, T, NonLinearScale>& operator/=(unit_t<Units, T, NonLinearScale>& lhs, const RhsType& rhs) noexcept
2278  {
2279  static_assert((traits::is_dimensionless_unit<RhsType>::value || std::is_arithmetic<RhsType>::value),
2280  "right-hand side parameter must be dimensionless.");
2281 
2282  lhs = lhs / rhs;
2283  return lhs;
2284  }
2285 
2286  //------------------------------
2287  // UNIT_T UNARY OPERATORS
2288  //------------------------------
2289 
2290  // unary addition: +T
2291  template<class Units, typename T, template<typename> class NonLinearScale>
2292  inline unit_t<Units, T, NonLinearScale> operator+(const unit_t<Units, T, NonLinearScale>& u) noexcept
2293  {
2294  return u;
2295  }
2296 
2297  // prefix increment: ++T
2298  template<class Units, typename T, template<typename> class NonLinearScale>
2299  inline unit_t<Units, T, NonLinearScale>& operator++(unit_t<Units, T, NonLinearScale>& u) noexcept
2300  {
2301  u = unit_t<Units, T, NonLinearScale>(u() + 1);
2302  return u;
2303  }
2304 
2305  // postfix increment: T++
2306  template<class Units, typename T, template<typename> class NonLinearScale>
2307  inline unit_t<Units, T, NonLinearScale> operator++(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2308  {
2309  auto ret = u;
2310  u = unit_t<Units, T, NonLinearScale>(u() + 1);
2311  return ret;
2312  }
2313 
2314  // unary addition: -T
2315  template<class Units, typename T, template<typename> class NonLinearScale>
2316  inline unit_t<Units, T, NonLinearScale> operator-(const unit_t<Units, T, NonLinearScale>& u) noexcept
2317  {
2318  return unit_t<Units, T, NonLinearScale>(-u());
2319  }
2320 
2321  // prefix increment: --T
2322  template<class Units, typename T, template<typename> class NonLinearScale>
2323  inline unit_t<Units, T, NonLinearScale>& operator--(unit_t<Units, T, NonLinearScale>& u) noexcept
2324  {
2325  u = unit_t<Units, T, NonLinearScale>(u() - 1);
2326  return u;
2327  }
2328 
2329  // postfix increment: T--
2330  template<class Units, typename T, template<typename> class NonLinearScale>
2331  inline unit_t<Units, T, NonLinearScale> operator--(unit_t<Units, T, NonLinearScale>& u, int) noexcept
2332  {
2333  auto ret = u;
2334  u = unit_t<Units, T, NonLinearScale>(u() - 1);
2335  return ret;
2336  }
2337 
2338  //------------------------------
2339  // UNIT_CAST
2340  //------------------------------
2341 
2355  template<typename T, typename Units, class = std::enable_if_t<std::is_arithmetic<T>::value && traits::is_unit_t<Units>::value>>
2356  inline constexpr T unit_cast(const Units& value) noexcept
2357  {
2358  return static_cast<T>(value);
2359  }
2360 
2361  //------------------------------
2362  // NON-LINEAR SCALE TRAITS
2363  //------------------------------
2364 
2365  // forward declaration
2366  template<typename T> struct decibel_scale;
2367 
2368  namespace traits
2369  {
2377 #if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2378  template<typename... T>
2379  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 > {};
2380 #else
2381  template<typename T1, typename T2 = T1, typename T3 = T1>
2382  struct has_linear_scale : std::integral_constant<bool,
2383  std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2384  std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2385  std::is_base_of<units::linear_scale<typename units::traits::unit_t_traits<T3>::underlying_type>, T3>::value> {};
2386 #endif
2387 
2395 #if !defined(_MSC_VER) || _MSC_VER > 1800 // bug in VS2013 prevents this from working
2396  template<typename... T>
2397  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> {};
2398 #else
2399  template<typename T1, typename T2 = T1, typename T3 = T1>
2400  struct has_decibel_scale : std::integral_constant<bool,
2401  std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T1>::underlying_type>, T1>::value &&
2402  std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T2>::value &&
2403  std::is_base_of<units::decibel_scale<typename units::traits::unit_t_traits<T2>::underlying_type>, T3>::value> {};
2404 #endif
2405 
2414  template<typename T1, typename T2>
2415  struct is_same_scale : std::integral_constant<bool,
2416  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>
2417  {};
2418  }
2419 
2420  //----------------------------------
2421  // NON-LINEAR SCALES
2422  //----------------------------------
2423 
2424  // Non-linear transforms are used to pre and post scale units which are defined in terms of non-
2425  // linear functions of their current value. A good example of a non-linear scale would be a
2426  // logarithmic or decibel scale
2427 
2428  //------------------------------
2429  // LINEAR SCALE
2430  //------------------------------
2431 
2439  template<typename T>
2441  {
2442  inline constexpr linear_scale() = default;
2443  inline constexpr linear_scale(const linear_scale&) = default;
2444  inline ~linear_scale() = default;
2445  inline linear_scale& operator=(const linear_scale&) = default;
2446 #if defined(_MSC_VER) && (_MSC_VER > 1800)
2447  inline constexpr linear_scale(linear_scale&&) = default;
2448  inline linear_scale& operator=(linear_scale&&) = default;
2449 #endif
2450  template<class... Args>
2451  inline constexpr linear_scale(const T& value, Args&&...) noexcept : m_value(value) {}
2452  inline constexpr T operator()() const noexcept { return m_value; }
2453 
2455  };
2456 
2457  //----------------------------------
2458  // SCALAR (LINEAR) UNITS
2459  //----------------------------------
2460 
2461  // Scalar units are the *ONLY* units implicitly convertible to/from built-in types.
2462  namespace dimensionless
2463  {
2466 
2467  typedef unit_t<scalar> scalar_t;
2468  typedef scalar_t dimensionless_t;
2469  }
2470 
2471 // ignore the redeclaration of the default template parameters
2472 #if defined(_MSC_VER)
2473 # pragma warning(push)
2474 # pragma warning(disable : 4348)
2475 #endif
2477  UNIT_ADD_CATEGORY_TRAIT(dimensionless)
2478 #if defined(_MSC_VER)
2479 # pragma warning(pop)
2480 #endif
2481 
2482  //------------------------------
2483  // LINEAR ARITHMETIC
2484  //------------------------------
2485 
2486  template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<!traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2487  constexpr inline int operator+(const UnitTypeLhs& /* lhs */, const UnitTypeRhs& /* rhs */) noexcept
2488  {
2489  static_assert(traits::is_same_scale<UnitTypeLhs, UnitTypeRhs>::value, "Cannot add units with different linear/non-linear scales.");
2490  return 0;
2491  }
2492 
2494  template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2495  inline constexpr UnitTypeLhs operator+(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2496  {
2497  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2498  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2499  return UnitTypeLhs(lhs() + convert<UnitsRhs, UnitsLhs>(rhs()));
2500  }
2501 
2503  template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2504  inline constexpr dimensionless::scalar_t operator+(const dimensionless::scalar_t& lhs, T rhs) noexcept
2505  {
2506  return dimensionless::scalar_t(lhs() + rhs);
2507  }
2508 
2510  template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2511  inline constexpr dimensionless::scalar_t operator+(T lhs, const dimensionless::scalar_t& rhs) noexcept
2512  {
2513  return dimensionless::scalar_t(lhs + rhs());
2514  }
2515 
2517  template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2518  inline constexpr UnitTypeLhs operator-(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2519  {
2520  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2521  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2522  return UnitTypeLhs(lhs() - convert<UnitsRhs, UnitsLhs>(rhs()));
2523  }
2524 
2526  template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2527  inline constexpr dimensionless::scalar_t operator-(const dimensionless::scalar_t& lhs, T rhs) noexcept
2528  {
2529  return dimensionless::scalar_t(lhs() - rhs);
2530  }
2531 
2533  template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
2534  inline constexpr dimensionless::scalar_t operator-(T lhs, const dimensionless::scalar_t& rhs) noexcept
2535  {
2536  return dimensionless::scalar_t(lhs - rhs());
2537  }
2538 
2540  template<class UnitTypeLhs, class UnitTypeRhs,
2541  std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2542  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>>>
2543  {
2544  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2545  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2547  (lhs() * convert<UnitsRhs, UnitsLhs>(rhs()));
2548  }
2549 
2551  template<class UnitTypeLhs, class UnitTypeRhs,
2552  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>
2553  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>>
2554  {
2555  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2556  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2557  return unit_t<compound_unit<UnitsLhs, UnitsRhs>>
2558  (lhs() * rhs());
2559  }
2560 
2562  template<class UnitTypeLhs, typename UnitTypeRhs,
2563  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>
2564  inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2565  {
2566  // the cast makes sure factors of PI are handled as expected
2567  return UnitTypeLhs(lhs() * static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2568  }
2569 
2571  template<class UnitTypeLhs, typename UnitTypeRhs,
2572  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>
2573  inline constexpr UnitTypeRhs operator*(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2574  {
2575  // the cast makes sure factors of PI are handled as expected
2576  return UnitTypeRhs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) * rhs());
2577  }
2578 
2580  template<class UnitTypeLhs, typename T,
2581  std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2582  inline constexpr UnitTypeLhs operator*(const UnitTypeLhs& lhs, T rhs) noexcept
2583  {
2584  return UnitTypeLhs(lhs() * rhs);
2585  }
2586 
2588  template<class UnitTypeRhs, typename T,
2589  std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2590  inline constexpr UnitTypeRhs operator*(T lhs, const UnitTypeRhs& rhs) noexcept
2591  {
2592  return UnitTypeRhs(lhs * rhs());
2593  }
2594 
2596  template<class UnitTypeLhs, class UnitTypeRhs,
2597  std::enable_if_t<traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value && traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2598  inline constexpr dimensionless::scalar_t operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2599  {
2600  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2601  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2602  return dimensionless::scalar_t(lhs() / convert<UnitsRhs, UnitsLhs>(rhs()));
2603  }
2604 
2606  template<class UnitTypeLhs, class UnitTypeRhs,
2607  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>
2609  {
2610  using UnitsLhs = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2611  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2613  (lhs() / rhs());
2614  }
2615 
2617  template<class UnitTypeLhs, class UnitTypeRhs,
2618  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>
2619  inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept
2620  {
2621  return UnitTypeLhs(lhs() / static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2622  }
2623 
2625  template<class UnitTypeLhs, class UnitTypeRhs,
2626  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>
2627  inline constexpr auto operator/(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2628  {
2630  (static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) / rhs());
2631  }
2632 
2634  template<class UnitTypeLhs, typename T,
2635  std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeLhs>::value, int> = 0>
2636  inline constexpr UnitTypeLhs operator/(const UnitTypeLhs& lhs, T rhs) noexcept
2637  {
2638  return UnitTypeLhs(lhs() / rhs);
2639  }
2640 
2642  template<class UnitTypeRhs, typename T,
2643  std::enable_if_t<std::is_arithmetic<T>::value && traits::has_linear_scale<UnitTypeRhs>::value, int> = 0>
2644  inline constexpr auto operator/(T lhs, const UnitTypeRhs& rhs) noexcept -> unit_t<inverse<typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type>>
2645  {
2646  using UnitsRhs = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2647  return unit_t<inverse<UnitsRhs>>
2648  (lhs / rhs());
2649  }
2650 
2651  //----------------------------------
2652  // SCALAR COMPARISONS
2653  //----------------------------------
2654 
2655  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2656  constexpr bool operator==(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2657  {
2658  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)) ||
2659  detail::abs(lhs - static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs)) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2660  }
2661 
2662  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2663  constexpr bool operator==(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2664  {
2665  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) ||
2666  detail::abs(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) - rhs) < std::numeric_limits<UNIT_LIB_DEFAULT_TYPE>::min();
2667  }
2668 
2669  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2670  constexpr bool operator!=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2671  {
2672  return!(lhs == static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2673  }
2674 
2675  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2676  constexpr bool operator!=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2677  {
2678  return !(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) == rhs);
2679  }
2680 
2681  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2682  constexpr bool operator>=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2683  {
2684  return std::isgreaterequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2685  }
2686 
2687  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2688  constexpr bool operator>=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2689  {
2690  return std::isgreaterequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2691  }
2692 
2693  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2694  constexpr bool operator>(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2695  {
2696  return lhs > static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2697  }
2698 
2699  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2700  constexpr bool operator>(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2701  {
2702  return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) > rhs;
2703  }
2704 
2705  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2706  constexpr bool operator<=(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2707  {
2708  return std::islessequal(lhs, static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs));
2709  }
2710 
2711  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2712  constexpr bool operator<=(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2713  {
2714  return std::islessequal(static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs), rhs);
2715  }
2716 
2717  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2718  constexpr bool operator<(const UNIT_LIB_DEFAULT_TYPE lhs, const Units& rhs) noexcept
2719  {
2720  return lhs < static_cast<UNIT_LIB_DEFAULT_TYPE>(rhs);
2721  }
2722 
2723  template<typename Units, class = std::enable_if_t<units::traits::is_dimensionless_unit<Units>::value>>
2724  constexpr bool operator<(const Units& lhs, const UNIT_LIB_DEFAULT_TYPE rhs) noexcept
2725  {
2726  return static_cast<UNIT_LIB_DEFAULT_TYPE>(lhs) < rhs;
2727  }
2728 
2729  //----------------------------------
2730  // POW
2731  //----------------------------------
2732  // DOXYGEN IGNORE
2734  namespace detail
2735  {
2737  template <int N, class U> struct power_of_unit
2738  {
2739  typedef typename units::detail::unit_multiply<U, typename power_of_unit<N - 1, U>::type> type;
2740  };
2741 
2743  template <class U> struct power_of_unit<1, U>
2744  {
2745  typedef U type;
2746  };
2747  } // END DOXYGEN IGNORE
2749 
2750  namespace math
2751  {
2759  template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2760  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>
2761  {
2762  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>
2763  (std::pow(value(), power));
2764  }
2765 
2774  template<int power, class UnitType, class = typename std::enable_if<traits::has_linear_scale<UnitType>::value, int>>
2775  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>
2776  {
2777  static_assert(power >= 0, "cpow cannot accept negative numbers. Try units::math::pow instead.");
2778  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>
2779  (detail::pow(value(), power));
2780  }
2781  }
2782 
2783  //------------------------------
2784  // DECIBEL SCALE
2785  //------------------------------
2786 
2793  template<typename T>
2794  struct decibel_scale
2795  {
2796  inline constexpr decibel_scale() = default;
2797  inline constexpr decibel_scale(const decibel_scale&) = default;
2798  inline ~decibel_scale() = default;
2799  inline decibel_scale& operator=(const decibel_scale&) = default;
2800 #if defined(_MSC_VER) && (_MSC_VER > 1800)
2801  inline constexpr decibel_scale(decibel_scale&&) = default;
2802  inline decibel_scale& operator=(decibel_scale&&) = default;
2803 #endif
2804  inline constexpr decibel_scale(const T value) noexcept : m_value(std::pow(10, value / 10)) {}
2805  template<class... Args>
2806  inline constexpr decibel_scale(const T value, std::true_type, Args&&...) noexcept : m_value(value) {}
2807  inline constexpr T operator()() const noexcept { return 10 * std::log10(m_value); }
2808 
2810  };
2811 
2812  //------------------------------
2813  // SCALAR (DECIBEL) UNITS
2814  //------------------------------
2815 
2820  namespace dimensionless
2821  {
2823 #if !defined(UNIT_LIB_DISABLE_IOSTREAM)
2824  inline std::ostream& operator<<(std::ostream& os, const dB_t& obj) { os << obj() << " dB"; return os; }
2825 #endif
2826  typedef dB_t dBi_t;
2827  }
2828 
2829  //------------------------------
2830  // DECIBEL ARITHMETIC
2831  //------------------------------
2832 
2834  template<class UnitTypeLhs, class UnitTypeRhs,
2835  std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2836  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>
2837  {
2838  using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2839  using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2840  using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2841 
2842  return unit_t<compound_unit<squared<LhsUnits>>, underlying_type, decibel_scale>
2843  (lhs.template toLinearized<underlying_type>() * convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2844  }
2845 
2847  template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2848  constexpr inline UnitTypeLhs operator+(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2849  {
2850  using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2851  return UnitTypeLhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2852  }
2853 
2855  template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2856  constexpr inline UnitTypeRhs operator+(const dimensionless::dB_t& lhs, const UnitTypeRhs& rhs) noexcept
2857  {
2858  using underlying_type = typename units::traits::unit_t_traits<UnitTypeRhs>::underlying_type;
2859  return UnitTypeRhs(lhs.template toLinearized<underlying_type>() * rhs.template toLinearized<underlying_type>(), std::true_type());
2860  }
2861 
2863  template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
2864  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>
2865  {
2866  using LhsUnits = typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type;
2867  using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2868  using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2869 
2871  (lhs.template toLinearized<underlying_type>() / convert<RhsUnits, LhsUnits>(rhs.template toLinearized<underlying_type>()), std::true_type());
2872  }
2873 
2875  template<class UnitTypeLhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeLhs>::value && !traits::is_dimensionless_unit<UnitTypeLhs>::value, int> = 0>
2876  constexpr inline UnitTypeLhs operator-(const UnitTypeLhs& lhs, const dimensionless::dB_t& rhs) noexcept
2877  {
2878  using underlying_type = typename units::traits::unit_t_traits<UnitTypeLhs>::underlying_type;
2879  return UnitTypeLhs(lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2880  }
2881 
2883  template<class UnitTypeRhs, std::enable_if_t<traits::has_decibel_scale<UnitTypeRhs>::value && !traits::is_dimensionless_unit<UnitTypeRhs>::value, int> = 0>
2884  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>
2885  {
2886  using RhsUnits = typename units::traits::unit_t_traits<UnitTypeRhs>::unit_type;
2887  using underlying_type = typename units::traits::unit_t_traits<RhsUnits>::underlying_type;
2888 
2889  return unit_t<inverse<RhsUnits>, underlying_type, decibel_scale>
2890  (lhs.template toLinearized<underlying_type>() / rhs.template toLinearized<underlying_type>(), std::true_type());
2891  }
2892 
2893  //----------------------------------
2894  // UNIT RATIO CLASS
2895  //----------------------------------
2896  // DOXYGEN IGNORE
2898  namespace detail
2899  {
2900  template<class Units>
2901  struct _unit_value_t {};
2902  } // END DOXYGEN IGNORE
2904 
2905  namespace traits
2906  {
2907 #ifdef FOR_DOXYGEN_PURPOSES_ONLY
2908 
2915  template<typename T>
2916  struct unit_value_t_traits
2917  {
2918  typedef typename T::unit_type unit_type;
2919  typedef typename T::ratio ratio;
2920  };
2921 #endif
2922  // DOXYGEN IGNORE
2928  template<typename T, typename = void>
2929  struct unit_value_t_traits
2930  {
2931  typedef void unit_type;
2932  typedef void ratio;
2933  };
2934 
2940  template<typename T>
2941  struct unit_value_t_traits <T, typename void_t<
2942  typename T::unit_type,
2943  typename T::ratio>::type>
2944  {
2945  typedef typename T::unit_type unit_type;
2946  typedef typename T::ratio ratio;
2947  }; // END DOXYGEN IGNORE
2949  }
2950 
2951  //------------------------------------------------------------------------------
2952  // COMPILE-TIME UNIT VALUES AND ARITHMETIC
2953  //------------------------------------------------------------------------------
2954 
2968  template<typename Units, std::uintmax_t Num, std::uintmax_t Denom = 1>
2969  struct unit_value_t : units::detail::_unit_value_t<Units>
2970  {
2971  typedef Units unit_type;
2972  typedef std::ratio<Num, Denom> ratio;
2973 
2974  static_assert(traits::is_unit<Units>::value, "Template parameter `Units` must be a unit type.");
2975  static constexpr const unit_t<Units> value() { return unit_t<Units>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den); }
2976  };
2977 
2978  namespace traits
2979  {
2988  template<typename T, typename Units = typename traits::unit_value_t_traits<T>::unit_type>
2989  struct is_unit_value_t : std::integral_constant<bool,
2990  std::is_base_of<units::detail::_unit_value_t<Units>, T>::value>
2991  {};
2992 
2998  template<typename Category, typename T>
2999  struct is_unit_value_t_category : std::integral_constant<bool,
3000  std::is_same<units::traits::base_unit_of<typename traits::unit_value_t_traits<T>::unit_type>, Category>::value>
3001  {
3002  static_assert(is_base_unit<Category>::value, "Template parameter `Category` must be a `base_unit` type.");
3003  };
3004  }
3005  // DOXYGEN IGNORE
3007  namespace detail
3008  {
3009  // base class for common arithmetic
3010  template<class U1, class U2>
3011  struct unit_value_arithmetic
3012  {
3013  static_assert(traits::is_unit_value_t<U1>::value, "Template parameter `U1` must be a `unit_value_t` type.");
3014  static_assert(traits::is_unit_value_t<U2>::value, "Template parameter `U2` must be a `unit_value_t` type.");
3015 
3016  using _UNIT1 = typename traits::unit_value_t_traits<U1>::unit_type;
3017  using _UNIT2 = typename traits::unit_value_t_traits<U2>::unit_type;
3018  using _CONV1 = typename units::traits::unit_traits<_UNIT1>::conversion_ratio;
3019  using _CONV2 = typename units::traits::unit_traits<_UNIT2>::conversion_ratio;
3020  using _RATIO1 = typename traits::unit_value_t_traits<U1>::ratio;
3021  using _RATIO2 = typename traits::unit_value_t_traits<U2>::ratio;
3022  using _RATIO2CONV = typename std::ratio_divide<std::ratio_multiply<_RATIO2, _CONV2>, _CONV1>;
3023  using _PI_EXP = std::ratio_subtract<typename units::traits::unit_traits<_UNIT2>::pi_exponent_ratio, typename units::traits::unit_traits<_UNIT1>::pi_exponent_ratio>;
3024  };
3025  } // END DOXYGEN IGNORE
3027 
3038  template<class U1, class U2>
3039  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>
3040  { // DOXYGEN IGNORE
3042  using Base = units::detail::unit_value_arithmetic<U1, U2>;
3043  typedef typename Base::_UNIT1 unit_type;
3044  using ratio = std::ratio_add<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3045 
3046  static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3048 
3055  static constexpr const unit_t<unit_type> value() noexcept
3056  {
3057  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3058  return value(UsePi());
3059  }
3060  // DOXYGEN IGNORE
3062  // value if PI isn't involved
3063  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3064  {
3065  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3066  }
3067 
3068  // value if PI *is* involved
3069  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3070  {
3071  return unit_t<unit_type>(((UNIT_LIB_DEFAULT_TYPE)Base::_RATIO1::num / Base::_RATIO1::den) +
3072  ((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)));
3073  } // END DOXYGEN IGNORE
3075  };
3076 
3087  template<class U1, class U2>
3088  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>
3089  { // DOXYGEN IGNORE
3091  using Base = units::detail::unit_value_arithmetic<U1, U2>;
3092 
3093  typedef typename Base::_UNIT1 unit_type;
3094  using ratio = std::ratio_subtract<typename Base::_RATIO1, typename Base::_RATIO2CONV>;
3095 
3096  static_assert(traits::is_convertible_unit<typename Base::_UNIT1, typename Base::_UNIT2>::value, "Unit types are not compatible."); // END DOXYGEN IGNORE
3098 
3105  static constexpr const unit_t<unit_type> value() noexcept
3106  {
3107  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3108  return value(UsePi());
3109  }
3110  // DOXYGEN IGNORE
3112  // value if PI isn't involved
3113  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3114  {
3115  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3116  }
3117 
3118  // value if PI *is* involved
3119  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3120  {
3121  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)
3122  * std::pow(units::constants::detail::PI_VAL, ((UNIT_LIB_DEFAULT_TYPE)Base::_PI_EXP::num / Base::_PI_EXP::den)));
3123  } // END DOXYGEN IGNORE };
3125  };
3126 
3137  template<class U1, class U2>
3138  struct unit_value_multiply : units::detail::unit_value_arithmetic<U1, U2>,
3139  units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3140  typename traits::unit_value_t_traits<U2>::unit_type>::value, compound_unit<squared<typename traits::unit_value_t_traits<U1>::unit_type>>,
3141  compound_unit<typename traits::unit_value_t_traits<U1>::unit_type, typename traits::unit_value_t_traits<U2>::unit_type>>::type>
3142  { // DOXYGEN IGNORE
3144  using Base = units::detail::unit_value_arithmetic<U1, U2>;
3145 
3146  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>>;
3147  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
3149 
3156  static constexpr const unit_t<unit_type> value() noexcept
3157  {
3158  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3159  return value(UsePi());
3160  }
3161  // DOXYGEN IGNORE
3163  // value if PI isn't involved
3164  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3165  {
3166  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3167  }
3168 
3169  // value if PI *is* involved
3170  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3171  {
3172  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)));
3173  } // END DOXYGEN IGNORE
3175  };
3176 
3187  template<class U1, class U2>
3188  struct unit_value_divide : units::detail::unit_value_arithmetic<U1, U2>,
3189  units::detail::_unit_value_t<typename std::conditional<traits::is_convertible_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3190  typename traits::unit_value_t_traits<U2>::unit_type>::value, dimensionless::scalar, compound_unit<typename traits::unit_value_t_traits<U1>::unit_type,
3191  inverse<typename traits::unit_value_t_traits<U2>::unit_type>>>::type>
3192  { // DOXYGEN IGNORE
3194  using Base = units::detail::unit_value_arithmetic<U1, U2>;
3195 
3196  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>>>;
3197  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
3199 
3206  static constexpr const unit_t<unit_type> value() noexcept
3207  {
3208  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3209  return value(UsePi());
3210  }
3211  // DOXYGEN IGNORE
3213  // value if PI isn't involved
3214  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3215  {
3216  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3217  }
3218 
3219  // value if PI *is* involved
3220  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3221  {
3222  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)));
3223  } // END DOXYGEN IGNORE
3225  };
3226 
3236  template<class U1, int power>
3237  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>
3238  { // DOXYGEN IGNORE
3240  using Base = units::detail::unit_value_arithmetic<U1, U1>;
3241 
3242  using unit_type = typename units::detail::power_of_unit<power, typename Base::_UNIT1>::type;
3243  using ratio = typename units::detail::power_of_ratio<power, typename Base::_RATIO1>::type;
3244  using pi_exponent = std::ratio_multiply<std::ratio<power>, typename Base::_UNIT1::pi_exponent_ratio>; // END DOXYGEN IGNORE
3246 
3253  static constexpr const unit_t<unit_type> value() noexcept
3254  {
3255  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3256  return value(UsePi());
3257  }
3258  // DOXYGEN IGNORE
3260  // value if PI isn't involved
3261  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3262  {
3263  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3264  }
3265 
3266  // value if PI *is* involved
3267  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3268  {
3269  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)));
3270  } // END DOXYGEN IGNORE };
3272  };
3273 
3283  template<class U1, std::intmax_t Eps = 10000000000>
3284  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>>
3285  { // DOXYGEN IGNORE
3287  using Base = units::detail::unit_value_arithmetic<U1, U1>;
3288 
3289  using unit_type = square_root<typename Base::_UNIT1, Eps>;
3291  using pi_exponent = ratio_sqrt<typename Base::_UNIT1::pi_exponent_ratio, Eps>; // END DOXYGEN IGNORE
3293 
3300  static constexpr const unit_t<unit_type> value() noexcept
3301  {
3302  using UsePi = std::integral_constant<bool, Base::_PI_EXP::num != 0>;
3303  return value(UsePi());
3304  }
3305  // DOXYGEN IGNORE
3307  // value if PI isn't involved
3308  static constexpr const unit_t<unit_type> value(std::false_type) noexcept
3309  {
3310  return unit_t<unit_type>((UNIT_LIB_DEFAULT_TYPE)ratio::num / ratio::den);
3311  }
3312 
3313  // value if PI *is* involved
3314  static constexpr const unit_t<unit_type> value(std::true_type) noexcept
3315  {
3316  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)));
3317  } // END DOXYGEN IGNORE
3319  };
3320 
3321  //------------------------------
3322  // LITERALS
3323  //------------------------------
3324 
3336  //------------------------------
3337  // LENGTH UNITS
3338  //------------------------------
3339 
3348 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LENGTH_UNITS)
3349  UNIT_ADD_WITH_METRIC_PREFIXES(length, meter, meters, m, unit<std::ratio<1>, units::category::length_unit>)
3350  UNIT_ADD(length, foot, feet, ft, unit<std::ratio<381, 1250>, meters>)
3351  UNIT_ADD(length, mil, mils, mil, unit<std::ratio<1000>, feet>)
3352  UNIT_ADD(length, inch, inches, in, unit<std::ratio<1, 12>, feet>)
3353  UNIT_ADD(length, mile, miles, mi, unit<std::ratio<5280>, feet>)
3354  UNIT_ADD(length, nauticalMile, nauticalMiles, nmi, unit<std::ratio<1852>, meters>)
3355  UNIT_ADD(length, astronicalUnit, astronicalUnits, au, unit<std::ratio<149597870700>, meters>)
3356  UNIT_ADD(length, lightyear, lightyears, ly, unit<std::ratio<9460730472580800>, meters>)
3357  UNIT_ADD(length, parsec, parsecs, pc, unit<std::ratio<648000>, astronicalUnits, std::ratio<-1>>)
3358  UNIT_ADD(length, angstrom, angstroms, angstrom, unit<std::ratio<1, 10>, nanometers>)
3359  UNIT_ADD(length, cubit, cubits, cbt, unit<std::ratio<18>, inches>)
3360  UNIT_ADD(length, fathom, fathoms, ftm, unit<std::ratio<6>, feet>)
3361  UNIT_ADD(length, chain, chains, ch, unit<std::ratio<66>, feet>)
3362  UNIT_ADD(length, furlong, furlongs, fur, unit<std::ratio<10>, chains>)
3363  UNIT_ADD(length, hand, hands, hand, unit<std::ratio<4>, inches>)
3364  UNIT_ADD(length, league, leagues, lea, unit<std::ratio<3>, miles>)
3365  UNIT_ADD(length, nauticalLeague, nauticalLeagues, nl, unit<std::ratio<3>, nauticalMiles>)
3366  UNIT_ADD(length, yard, yards, yd, unit<std::ratio<3>, feet>)
3367 
3369 #endif
3370 
3371  //------------------------------
3372  // MASS UNITS
3373  //------------------------------
3374 
3383 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MASS_UNITS)
3384  UNIT_ADD_WITH_METRIC_PREFIXES(mass, gram, grams, g, unit<std::ratio<1, 1000>, units::category::mass_unit>)
3385  UNIT_ADD(mass, metric_ton, metric_tons, t, unit<std::ratio<1000>, kilograms>)
3386  UNIT_ADD(mass, pound, pounds, lb, unit<std::ratio<45359237, 100000000>, kilograms>)
3387  UNIT_ADD(mass, long_ton, long_tons, ln_t, unit<std::ratio<2240>, pounds>)
3388  UNIT_ADD(mass, short_ton, short_tons, sh_t, unit<std::ratio<2000>, pounds>)
3389  UNIT_ADD(mass, stone, stone, st, unit<std::ratio<14>, pounds>)
3390  UNIT_ADD(mass, ounce, ounces, oz, unit<std::ratio<1, 16>, pounds>)
3391  UNIT_ADD(mass, carat, carats, ct, unit<std::ratio<200>, milligrams>)
3392  UNIT_ADD(mass, slug, slugs, slug, unit<std::ratio<145939029, 10000000>, kilograms>)
3393 
3395 #endif
3396 
3397  //------------------------------
3398  // TIME UNITS
3399  //------------------------------
3400 
3409 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TIME_UNITS)
3410  UNIT_ADD_WITH_METRIC_PREFIXES(time, second, seconds, s, unit<std::ratio<1>, units::category::time_unit>)
3411  UNIT_ADD(time, minute, minutes, min, unit<std::ratio<60>, seconds>)
3412  UNIT_ADD(time, hour, hours, hr, unit<std::ratio<60>, minutes>)
3413  UNIT_ADD(time, day, days, d, unit<std::ratio<24>, hours>)
3414  UNIT_ADD(time, week, weeks, wk, unit<std::ratio<7>, days>)
3415  UNIT_ADD(time, year, years, yr, unit<std::ratio<365>, days>)
3416  UNIT_ADD(time, julian_year, julian_years, a_j, unit<std::ratio<31557600>, seconds>)
3417  UNIT_ADD(time, gregorian_year, gregorian_years, a_g, unit<std::ratio<31556952>, seconds>)
3418 
3420 #endif
3421 
3422  //------------------------------
3423  // ANGLE UNITS
3424  //------------------------------
3425 
3434 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
3435  UNIT_ADD_WITH_METRIC_PREFIXES(angle, radian, radians, rad, unit<std::ratio<1>, units::category::angle_unit>)
3436  UNIT_ADD(angle, degree, degrees, deg, unit<std::ratio<1, 180>, radians, std::ratio<1>>)
3437  UNIT_ADD(angle, arcminute, arcminutes, arcmin, unit<std::ratio<1, 60>, degrees>)
3438  UNIT_ADD(angle, arcsecond, arcseconds, arcsec, unit<std::ratio<1, 60>, arcminutes>)
3439  UNIT_ADD(angle, milliarcsecond, milliarcseconds, mas, milli<arcseconds>)
3440  UNIT_ADD(angle, turn, turns, tr, unit<std::ratio<2>, radians, std::ratio<1>>)
3441  UNIT_ADD(angle, gradian, gradians, gon, unit<std::ratio<1, 400>, turns>)
3442 
3444 #endif
3445 
3446  //------------------------------
3447  // UNITS OF CURRENT
3448  //------------------------------
3457 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CURRENT_UNITS)
3458  UNIT_ADD_WITH_METRIC_PREFIXES(current, ampere, amperes, A, unit<std::ratio<1>, units::category::current_unit>)
3459 
3461 #endif
3462 
3463  //------------------------------
3464  // UNITS OF TEMPERATURE
3465  //------------------------------
3466 
3467  // NOTE: temperature units have special conversion overloads, since they
3468  // require translations and aren't a reversible transform.
3469 
3478 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TEMPERATURE_UNITS)
3479  UNIT_ADD(temperature, kelvin, kelvin, K, unit<std::ratio<1>, units::category::temperature_unit>)
3480  UNIT_ADD(temperature, celsius, celsius, degC, unit<std::ratio<1>, kelvin, std::ratio<0>, std::ratio<27315, 100>>)
3481  UNIT_ADD(temperature, fahrenheit, fahrenheit, degF, unit<std::ratio<5, 9>, celsius, std::ratio<0>, std::ratio<-160, 9>>)
3482  UNIT_ADD(temperature, reaumur, reaumur, Re, unit<std::ratio<10, 8>, celsius>)
3483  UNIT_ADD(temperature, rankine, rankine, Ra, unit<std::ratio<5, 9>, kelvin>)
3484 
3486 #endif
3487 
3488  //------------------------------
3489  // UNITS OF AMOUNT OF SUBSTANCE
3490  //------------------------------
3491 
3500 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SUBSTANCE_UNITS)
3501  UNIT_ADD(substance, mole, moles, mol, unit<std::ratio<1>, units::category::substance_unit>)
3502 
3504 #endif
3505 
3506  //------------------------------
3507  // UNITS OF LUMINOUS INTENSITY
3508  //------------------------------
3509 
3518 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_INTENSITY_UNITS)
3519  UNIT_ADD_WITH_METRIC_PREFIXES(luminous_intensity, candela, candelas, cd, unit<std::ratio<1>, units::category::luminous_intensity_unit>)
3520 
3521  UNIT_ADD_CATEGORY_TRAIT(luminous_intensity)
3522 #endif
3523 
3524  //------------------------------
3525  // UNITS OF SOLID ANGLE
3526  //------------------------------
3527 
3536 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_SOLID_ANGLE_UNITS)
3537  UNIT_ADD_WITH_METRIC_PREFIXES(solid_angle, steradian, steradians, sr, unit<std::ratio<1>, units::category::solid_angle_unit>)
3538  UNIT_ADD(solid_angle, degree_squared, degrees_squared, sq_deg, squared<angle::degrees>)
3539  UNIT_ADD(solid_angle, spat, spats, sp, unit<std::ratio<4>, steradians, std::ratio<1>>)
3540 
3542 #endif
3543 
3544  //------------------------------
3545  // FREQUENCY UNITS
3546  //------------------------------
3547 
3556 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FREQUENCY_UNITS)
3557  UNIT_ADD_WITH_METRIC_PREFIXES(frequency, hertz, hertz, Hz, unit<std::ratio<1>, units::category::frequency_unit>)
3558 
3560 #endif
3561 
3562  //------------------------------
3563  // VELOCITY UNITS
3564  //------------------------------
3565 
3574 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VELOCITY_UNITS)
3575  UNIT_ADD(velocity, meters_per_second, meters_per_second, mps, unit<std::ratio<1>, units::category::velocity_unit>)
3576  UNIT_ADD(velocity, feet_per_second, feet_per_second, fps, compound_unit<length::feet, inverse<time::seconds>>)
3577  UNIT_ADD(velocity, miles_per_hour, miles_per_hour, mph, compound_unit<length::miles, inverse<time::hour>>)
3578  UNIT_ADD(velocity, kilometers_per_hour, kilometers_per_hour, kph, compound_unit<length::kilometers, inverse<time::hour>>)
3579  UNIT_ADD(velocity, knot, knots, kts, compound_unit<length::nauticalMiles, inverse<time::hour>>)
3580 
3582 #endif
3583 
3584  //------------------------------
3585  // ANGULAR VELOCITY UNITS
3586  //------------------------------
3587 
3596 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGULAR_VELOCITY_UNITS)
3597  UNIT_ADD(angular_velocity, radians_per_second, radians_per_second, rad_per_s, unit<std::ratio<1>, units::category::angular_velocity_unit>)
3598  UNIT_ADD(angular_velocity, degrees_per_second, degrees_per_second, deg_per_s, compound_unit<angle::degrees, inverse<time::seconds>>)
3599  UNIT_ADD(angular_velocity, revolutions_per_minute, revolutions_per_minute, rpm, unit<std::ratio<2, 60>, radians_per_second, std::ratio<1>>)
3600  UNIT_ADD(angular_velocity, milliarcseconds_per_year, milliarcseconds_per_year, mas_per_yr, compound_unit<angle::milliarcseconds, inverse<time::year>>)
3601 
3602  UNIT_ADD_CATEGORY_TRAIT(angular_velocity)
3603 #endif
3604 
3605  //------------------------------
3606  // UNITS OF ACCELERATION
3607  //------------------------------
3608 
3617 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ACCELERATION_UNITS)
3618  UNIT_ADD(acceleration, meters_per_second_squared, meters_per_second_squared, mps_sq, unit<std::ratio<1>, units::category::acceleration_unit>)
3619  UNIT_ADD(acceleration, feet_per_second_squared, feet_per_second_squared, fps_sq, compound_unit<length::feet, inverse<squared<time::seconds>>>)
3620  UNIT_ADD(acceleration, standard_gravity, standard_gravity, SG, unit<std::ratio<980665, 100000>, meters_per_second_squared>)
3621 
3623 #endif
3624 
3625  //------------------------------
3626  // UNITS OF FORCE
3627  //------------------------------
3628 
3637 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_FORCE_UNITS)
3638  UNIT_ADD_WITH_METRIC_PREFIXES(force, newton, newtons, N, unit<std::ratio<1>, units::category::force_unit>)
3639  UNIT_ADD(force, pound, pounds, lbf, compound_unit<mass::slug, length::foot, inverse<squared<time::seconds>>>)
3640  UNIT_ADD(force, dyne, dynes, dyn, unit<std::ratio<1, 100000>, newtons>)
3641  UNIT_ADD(force, kilopond, kiloponds, kp, compound_unit<acceleration::standard_gravity, mass::kilograms>)
3642  UNIT_ADD(force, poundal, poundals, pdl, compound_unit<mass::pound, length::foot, inverse<squared<time::seconds>>>)
3643 
3645 #endif
3646 
3647  //------------------------------
3648  // UNITS OF PRESSURE
3649  //------------------------------
3650 
3659 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_PRESSURE_UNITS)
3660  UNIT_ADD_WITH_METRIC_PREFIXES(pressure, pascal, pascals, Pa, unit<std::ratio<1>, units::category::pressure_unit>)
3661  UNIT_ADD(pressure, bar, bars, bar, unit<std::ratio<100>, kilo<pascals>>)
3662  UNIT_ADD(pressure, mbar, mbars, mbar, unit<std::ratio<1>, milli<bar>>)
3663  UNIT_ADD(pressure, atmosphere, atmospheres, atm, unit<std::ratio<101325>, pascals>)
3664  UNIT_ADD(pressure, pounds_per_square_inch, pounds_per_square_inch, psi, compound_unit<force::pounds, inverse<squared<length::inch>>>)
3665  UNIT_ADD(pressure, torr, torrs, torr, unit<std::ratio<1, 760>, atmospheres>)
3666 
3668 #endif
3669 
3670  //------------------------------
3671  // UNITS OF CHARGE
3672  //------------------------------
3673 
3682 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CHARGE_UNITS)
3683  UNIT_ADD_WITH_METRIC_PREFIXES(charge, coulomb, coulombs, C, unit<std::ratio<1>, units::category::charge_unit>)
3684  UNIT_ADD_WITH_METRIC_PREFIXES(charge, ampere_hour, ampere_hours, Ah, compound_unit<current::ampere, time::hours>)
3685 
3687 #endif
3688 
3689  //------------------------------
3690  // UNITS OF ENERGY
3691  //------------------------------
3692 
3701 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ENERGY_UNITS)
3702  UNIT_ADD_WITH_METRIC_PREFIXES(energy, joule, joules, J, unit<std::ratio<1>, units::category::energy_unit>)
3703  UNIT_ADD_WITH_METRIC_PREFIXES(energy, calorie, calories, cal, unit<std::ratio<4184, 1000>, joules>)
3704  UNIT_ADD(energy, kilowatt_hour, kilowatt_hours, kWh, unit<std::ratio<36, 10>, megajoules>)
3705  UNIT_ADD(energy, watt_hour, watt_hours, Wh, unit<std::ratio<1, 1000>, kilowatt_hours>)
3706  UNIT_ADD(energy, british_thermal_unit, british_thermal_units, BTU, unit<std::ratio<105505585262, 100000000>, joules>)
3707  UNIT_ADD(energy, british_thermal_unit_iso, british_thermal_units_iso, BTU_iso, unit<std::ratio<1055056, 1000>, joules>)
3708  UNIT_ADD(energy, british_thermal_unit_59, british_thermal_units_59, BTU59, unit<std::ratio<1054804, 1000>, joules>)
3709  UNIT_ADD(energy, therm, therms, thm, unit<std::ratio<100000>, british_thermal_units_59>)
3710  UNIT_ADD(energy, foot_pound, foot_pounds, ftlbf, unit<std::ratio<13558179483314004, 10000000000000000>, joules>)
3711 
3713 #endif
3714 
3715  //------------------------------
3716  // UNITS OF POWER
3717  //------------------------------
3718 
3727 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_POWER_UNITS)
3728  UNIT_ADD_WITH_METRIC_PREFIXES(power, watt, watts, W, unit<std::ratio<1>, units::category::power_unit>)
3729  UNIT_ADD(power, horsepower, horsepower, hp, unit<std::ratio<7457, 10>, watts>)
3730  UNIT_ADD_DECIBEL(power, watt, dBW)
3731  UNIT_ADD_DECIBEL(power, milliwatt, dBm)
3732 
3734 #endif
3735 
3736  //------------------------------
3737  // UNITS OF VOLTAGE
3738  //------------------------------
3739 
3748 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLTAGE_UNITS)
3749  UNIT_ADD_WITH_METRIC_PREFIXES(voltage, volt, volts, V, unit<std::ratio<1>, units::category::voltage_unit>)
3750  UNIT_ADD(voltage, statvolt, statvolts, statV, unit<std::ratio<1000000, 299792458>, volts>)
3751  UNIT_ADD(voltage, abvolt, abvolts, abV, unit<std::ratio<1, 100000000>, volts>)
3752 
3754 #endif
3755 
3756  //------------------------------
3757  // UNITS OF CAPACITANCE
3758  //------------------------------
3759 
3768 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CAPACITANCE_UNITS)
3769  UNIT_ADD_WITH_METRIC_PREFIXES(capacitance, farad, farads, F, unit<std::ratio<1>, units::category::capacitance_unit>)
3770 
3772 #endif
3773 
3774  //------------------------------
3775  // UNITS OF IMPEDANCE
3776  //------------------------------
3777 
3786 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_IMPEDANCE_UNITS)
3787  UNIT_ADD_WITH_METRIC_PREFIXES(impedance, ohm, ohms, Ohm, unit<std::ratio<1>, units::category::impedance_unit>)
3788 
3790 #endif
3791 
3792  //------------------------------
3793  // UNITS OF CONDUCTANCE
3794  //------------------------------
3795 
3804 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONDUCTANCE_UNITS)
3805  UNIT_ADD_WITH_METRIC_PREFIXES(conductance, siemens, siemens, S, unit<std::ratio<1>, units::category::conductance_unit>)
3806 
3808 #endif
3809 
3810  //------------------------------
3811  // UNITS OF MAGNETIC FLUX
3812  //------------------------------
3813 
3822 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FLUX_UNITS)
3823  UNIT_ADD_WITH_METRIC_PREFIXES(magnetic_flux, weber, webers, Wb, unit<std::ratio<1>, units::category::magnetic_flux_unit>)
3824  UNIT_ADD(magnetic_flux, maxwell, maxwells, Mx, unit<std::ratio<1, 100000000>, webers>)
3825 
3827 #endif
3828 
3829  //----------------------------------------
3830  // UNITS OF MAGNETIC FIELD STRENGTH
3831  //----------------------------------------
3832 
3841  // Unfortunately `_T` is a WINAPI macro, so we have to use `_Te` as the tesla abbreviation.
3842 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_MAGNETIC_FIELD_STRENGTH_UNITS)
3843  UNIT_ADD_WITH_METRIC_PREFIXES(magnetic_field_strength, tesla, teslas, Te, unit<std::ratio<1>, units::category::magnetic_field_strength_unit>)
3844  UNIT_ADD(magnetic_field_strength, gauss, gauss, G, compound_unit<magnetic_flux::maxwell, inverse<squared<length::centimeter>>>)
3845 
3846  UNIT_ADD_CATEGORY_TRAIT(magnetic_field_strength)
3847 #endif
3848 
3849  //------------------------------
3850  // UNITS OF INDUCTANCE
3851  //------------------------------
3852 
3861 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_INDUCTANCE_UNITS)
3862  UNIT_ADD_WITH_METRIC_PREFIXES(inductance, henry, henries, H, unit<std::ratio<1>, units::category::inductance_unit>)
3863 
3865 #endif
3866 
3867  //------------------------------
3868  // UNITS OF LUMINOUS FLUX
3869  //------------------------------
3870 
3879 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_LUMINOUS_FLUX_UNITS)
3880  UNIT_ADD_WITH_METRIC_PREFIXES(luminous_flux, lumen, lumens, lm, unit<std::ratio<1>, units::category::luminous_flux_unit>)
3881 
3883 #endif
3884 
3885  //------------------------------
3886  // UNITS OF ILLUMINANCE
3887  //------------------------------
3888 
3897 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ILLUMINANCE_UNITS)
3898  UNIT_ADD_WITH_METRIC_PREFIXES(illuminance, lux, luxes, lx, unit<std::ratio<1>, units::category::illuminance_unit>)
3899  UNIT_ADD(illuminance, footcandle, footcandles, fc, compound_unit<luminous_flux::lumen, inverse<squared<length::foot>>>)
3900  UNIT_ADD(illuminance, lumens_per_square_inch, lumens_per_square_inch, lm_per_in_sq, compound_unit<luminous_flux::lumen, inverse<squared<length::inch>>>)
3901  UNIT_ADD(illuminance, phot, phots, ph, compound_unit<luminous_flux::lumens, inverse<squared<length::centimeter>>>)
3902 
3904 #endif
3905 
3906  //------------------------------
3907  // UNITS OF RADIATION
3908  //------------------------------
3909 
3920 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_RADIATION_UNITS)
3921  UNIT_ADD_WITH_METRIC_PREFIXES(radiation, becquerel, becquerels, Bq, unit<std::ratio<1>, units::frequency::hertz>)
3922  UNIT_ADD_WITH_METRIC_PREFIXES(radiation, gray, grays, Gy, compound_unit<energy::joules, inverse<mass::kilogram>>)
3923  UNIT_ADD_WITH_METRIC_PREFIXES(radiation, sievert, sieverts, Sv, unit<std::ratio<1>, grays>)
3924  UNIT_ADD(radiation, curie, curies, Ci, unit<std::ratio<37>, gigabecquerels>)
3925  UNIT_ADD(radiation, rutherford, rutherfords, rd, unit<std::ratio<1>, megabecquerels>)
3926  UNIT_ADD(radiation, rad, rads, rads, unit<std::ratio<1>, centigrays>)
3927 
3929 #endif
3930 
3931  //------------------------------
3932  // UNITS OF TORQUE
3933  //------------------------------
3934 
3943 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_TORQUE_UNITS)
3944  UNIT_ADD(torque, newton_meter, newton_meters, Nm, unit<std::ratio<1>, units::energy::joule>)
3945  UNIT_ADD(torque, foot_pound, foot_pounds, ftlb, compound_unit<length::foot, force::pounds>)
3946  UNIT_ADD(torque, foot_poundal, foot_poundals, ftpdl, compound_unit<length::foot, force::poundal>)
3947  UNIT_ADD(torque, inch_pound, inch_pounds, inlb, compound_unit<length::inch, force::pounds>)
3948  UNIT_ADD(torque, meter_kilogram, meter_kilograms, mkgf, compound_unit<length::meter, force::kiloponds>)
3949 
3951 #endif
3952 
3953  //------------------------------
3954  // AREA UNITS
3955  //------------------------------
3956 
3965 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_AREA_UNITS)
3966  UNIT_ADD(area, square_meter, square_meters, sq_m, unit<std::ratio<1>, units::category::area_unit>)
3967  UNIT_ADD(area, square_foot, square_feet, sq_ft, squared<length::feet>)
3968  UNIT_ADD(area, square_inch, square_inches, sq_in, squared<length::inch>)
3969  UNIT_ADD(area, square_mile, square_miles, sq_mi, squared<length::miles>)
3970  UNIT_ADD(area, square_kilometer, square_kilometers, sq_km, squared<length::kilometers>)
3971  UNIT_ADD(area, hectare, hectares, ha, unit<std::ratio<10000>, square_meters>)
3972  UNIT_ADD(area, acre, acres, acre, unit<std::ratio<43560>, square_feet>)
3973 
3975 #endif
3976 
3977  //------------------------------
3978  // UNITS OF VOLUME
3979  //------------------------------
3980 
3989 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_VOLUME_UNITS)
3990  UNIT_ADD(volume, cubic_meter, cubic_meters, cu_m, unit<std::ratio<1>, units::category::volume_unit>)
3991  UNIT_ADD(volume, cubic_millimeter, cubic_millimeters, cu_mm, cubed<length::millimeter>)
3992  UNIT_ADD(volume, cubic_kilometer, cubic_kilometers, cu_km, cubed<length::kilometer>)
3993  UNIT_ADD_WITH_METRIC_PREFIXES(volume, liter, liters, L, cubed<deci<length::meter>>)
3994  UNIT_ADD(volume, cubic_inch, cubic_inches, cu_in, cubed<length::inches>)
3995  UNIT_ADD(volume, cubic_foot, cubic_feet, cu_ft, cubed<length::feet>)
3996  UNIT_ADD(volume, cubic_yard, cubic_yards, cu_yd, cubed<length::yards>)
3997  UNIT_ADD(volume, cubic_mile, cubic_miles, cu_mi, cubed<length::miles>)
3998  UNIT_ADD(volume, gallon, gallons, gal, unit<std::ratio<231>, cubic_inches>)
3999  UNIT_ADD(volume, quart, quarts, qt, unit<std::ratio<1, 4>, gallons>)
4000  UNIT_ADD(volume, pint, pints, pt, unit<std::ratio<1, 2>, quarts>)
4001  UNIT_ADD(volume, cup, cups, c, unit<std::ratio<1, 2>, pints>)
4002  UNIT_ADD(volume, fluid_ounce, fluid_ounces, fl_oz, unit<std::ratio<1, 8>, cups>)
4003  UNIT_ADD(volume, barrel, barrels, bl, unit<std::ratio<42>, gallons>)
4004  UNIT_ADD(volume, bushel, bushels, bu, unit<std::ratio<215042, 100>, cubic_inches>)
4005  UNIT_ADD(volume, cord, cords, cord, unit<std::ratio<128>, cubic_feet>)
4006  UNIT_ADD(volume, cubic_fathom, cubic_fathoms, cu_fm, cubed<length::fathom>)
4007  UNIT_ADD(volume, tablespoon, tablespoons, tbsp, unit<std::ratio<1, 2>, fluid_ounces>)
4008  UNIT_ADD(volume, teaspoon, teaspoons, tsp, unit<std::ratio<1, 6>, fluid_ounces>)
4009  UNIT_ADD(volume, pinch, pinches, pinch, unit<std::ratio<1, 8>, teaspoons>)
4010  UNIT_ADD(volume, dash, dashes, dash, unit<std::ratio<1, 2>, pinches>)
4011  UNIT_ADD(volume, drop, drops, drop, unit<std::ratio<1, 360>, fluid_ounces>)
4012  UNIT_ADD(volume, fifth, fifths, fifth, unit<std::ratio<1, 5>, gallons>)
4013  UNIT_ADD(volume, dram, drams, dr, unit<std::ratio<1, 8>, fluid_ounces>)
4014  UNIT_ADD(volume, gill, gills, gi, unit<std::ratio<4>, fluid_ounces>)
4015  UNIT_ADD(volume, peck, pecks, pk, unit<std::ratio<1, 4>, bushels>)
4016  UNIT_ADD(volume, sack, sacks, sacks, unit<std::ratio<3>, bushels>)
4017  UNIT_ADD(volume, shot, shots, shots, unit<std::ratio<3, 2>, fluid_ounces>)
4018  UNIT_ADD(volume, strike, strikes, strikes, unit<std::ratio<2>, bushels>)
4019 
4021 #endif
4022 
4023  //------------------------------
4024  // UNITS OF DENSITY
4025  //------------------------------
4026 
4035 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DENSITY_UNITS)
4036  UNIT_ADD(density, kilograms_per_cubic_meter, kilograms_per_cubic_meter, kg_per_cu_m, unit<std::ratio<1>, units::category::density_unit>)
4037  UNIT_ADD(density, grams_per_milliliter, grams_per_milliliter, g_per_mL, compound_unit<mass::grams, inverse<volume::milliliter>>)
4038  UNIT_ADD(density, kilograms_per_liter, kilograms_per_liter, kg_per_L, unit<std::ratio<1>, compound_unit<mass::grams, inverse<volume::milliliter>>>)
4039  UNIT_ADD(density, ounces_per_cubic_foot, ounces_per_cubic_foot, oz_per_cu_ft, compound_unit<mass::ounces, inverse<volume::cubic_foot>>)
4040  UNIT_ADD(density, ounces_per_cubic_inch, ounces_per_cubic_inch, oz_per_cu_in, compound_unit<mass::ounces, inverse<volume::cubic_inch>>)
4041  UNIT_ADD(density, ounces_per_gallon, ounces_per_gallon, oz_per_gal, compound_unit<mass::ounces, inverse<volume::gallon>>)
4042  UNIT_ADD(density, pounds_per_cubic_foot, pounds_per_cubic_foot, lb_per_cu_ft, compound_unit<mass::pounds, inverse<volume::cubic_foot>>)
4043  UNIT_ADD(density, pounds_per_cubic_inch, pounds_per_cubic_inch, lb_per_cu_in, compound_unit<mass::pounds, inverse<volume::cubic_inch>>)
4044  UNIT_ADD(density, pounds_per_gallon, pounds_per_gallon, lb_per_gal, compound_unit<mass::pounds, inverse<volume::gallon>>)
4045  UNIT_ADD(density, slugs_per_cubic_foot, slugs_per_cubic_foot, slug_per_cu_ft, compound_unit<mass::slugs, inverse<volume::cubic_foot>>)
4046 
4048 #endif
4049 
4050  //------------------------------
4051  // UNITS OF CONCENTRATION
4052  //------------------------------
4053 
4062 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_CONCENTRATION_UNITS)
4063  UNIT_ADD(concentration, ppm, parts_per_million, ppm, unit<std::ratio<1, 1000000>, units::category::scalar_unit>)
4064  UNIT_ADD(concentration, ppb, parts_per_billion, ppb, unit<std::ratio<1, 1000>, parts_per_million>)
4065  UNIT_ADD(concentration, ppt, parts_per_trillion, ppt, unit<std::ratio<1, 1000>, parts_per_billion>)
4066  UNIT_ADD(concentration, percent, percent, pct, unit<std::ratio<1, 100>, units::category::scalar_unit>)
4067 
4069 #endif
4070 
4071  //------------------------------
4072  // UNITS OF DATA
4073  //------------------------------
4074 
4083 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_UNITS)
4084  UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data, byte, bytes, B, unit<std::ratio<1>, units::category::data_unit>)
4085  UNIT_ADD(data, exabyte, exabytes, EB, unit<std::ratio<1000>, petabytes>)
4086  UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES(data, bit, bits, b, unit<std::ratio<1, 8>, byte>)
4087  UNIT_ADD(data, exabit, exabits, Eb, unit<std::ratio<1000>, petabits>)
4088 
4090 #endif
4091 
4092  //------------------------------
4093  // UNITS OF DATA TRANSFER
4094  //------------------------------
4095 
4104 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_DATA_TRANSFER_RATE_UNITS)
4105  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>)
4106  UNIT_ADD(data_transfer_rate, exabytes_per_second, exabytes_per_second, EBps, unit<std::ratio<1000>, petabytes_per_second>)
4107  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>)
4108  UNIT_ADD(data_transfer_rate, exabits_per_second, exabits_per_second, Ebps, unit<std::ratio<1000>, petabits_per_second>)
4109 
4110  UNIT_ADD_CATEGORY_TRAIT(data_transfer_rate)
4111 #endif
4112 
4113  //------------------------------
4114  // CONSTANTS
4115  //------------------------------
4116 
4121 #if !defined(DISABLE_PREDEFINED_UNITS)
4122  namespace constants
4123  {
4129  using PI = unit<std::ratio<1>, dimensionless::scalar, std::ratio<1>>;
4130 
4131  static constexpr const unit_t<PI> pi(1);
4132  static constexpr const velocity::meters_per_second_t c(299792458.0);
4134  static constexpr const unit_t<compound_unit<energy::joule, time::seconds>> h(6.626070040e-34);
4135  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)));
4136  static constexpr const unit_t<compound_unit<capacitance::farad, inverse<length::meter>>> epsilon0(1.0 / (mu0 * math::cpow<2>(c)));
4137  static constexpr const impedance::ohm_t Z0(mu0 * c);
4139  static constexpr const charge::coulomb_t e(1.6021766208e-19);
4140  static constexpr const mass::kilogram_t m_e(9.10938356e-31);
4141  static constexpr const mass::kilogram_t m_p(1.672621898e-27);
4143  static constexpr const unit_t<inverse<substance::mol>> N_A(6.022140857e23);
4147  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)));
4148 
4149  }
4150 #endif
4151 
4152  //----------------------------------
4153  // UNIT-ENABLED CMATH FUNCTIONS
4154  //----------------------------------
4155 
4161  namespace math
4162  {
4163 
4164  //----------------------------------
4165  // MIN/MAX FUNCTIONS
4166  //----------------------------------
4167 
4168  template<class UnitTypeLhs, class UnitTypeRhs>
4169  UnitTypeLhs min(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4170  {
4171  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4172  UnitTypeLhs r(rhs);
4173  return (lhs < r ? lhs : r);
4174  }
4175 
4176  template<class UnitTypeLhs, class UnitTypeRhs>
4177  UnitTypeLhs max(const UnitTypeLhs& lhs, const UnitTypeRhs& rhs)
4178  {
4179  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Unit types are not compatible.");
4180  UnitTypeLhs r(rhs);
4181  return (lhs > r ? lhs : r);
4182  }
4183 
4184  //----------------------------------
4185  // TRIGONOMETRIC FUNCTIONS
4186  //----------------------------------
4187 
4196 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4197  template<class AngleUnit>
4198  dimensionless::scalar_t cos(const AngleUnit angle) noexcept
4199  {
4200  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4201  return dimensionless::scalar_t(std::cos(angle.template convert<angle::radian>()()));
4202  }
4203 #endif
4204 
4213 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4214  template<class AngleUnit>
4215  dimensionless::scalar_t sin(const AngleUnit angle) noexcept
4216  {
4217  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4218  return dimensionless::scalar_t(std::sin(angle.template convert<angle::radian>()()));
4219  }
4220 #endif
4221 
4229 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4230  template<class AngleUnit>
4231  dimensionless::scalar_t tan(const AngleUnit angle) noexcept
4232  {
4233  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4234  return dimensionless::scalar_t(std::tan(angle.template convert<angle::radian>()()));
4235  }
4236 #endif
4237 
4245 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4246  template<class ScalarUnit>
4247  angle::radian_t acos(const ScalarUnit x) noexcept
4248  {
4249  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4250  return angle::radian_t(std::acos(x()));
4251  }
4252 #endif
4253 
4261 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4262  template<class ScalarUnit>
4263  angle::radian_t asin(const ScalarUnit x) noexcept
4264  {
4265  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4266  return angle::radian_t(std::asin(x()));
4267  }
4268 #endif
4269 
4281 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4282  template<class ScalarUnit>
4283  angle::radian_t atan(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::atan(x()));
4287  }
4288 #endif
4289 
4298 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4299  template<class Y, class X>
4300  angle::radian_t atan2(const Y y, const X x) noexcept
4301  {
4302  static_assert(traits::is_dimensionless_unit<decltype(y/x)>::value, "The quantity y/x must yield a dimensionless ratio.");
4303 
4304  // X and Y could be different length units, so normalize them
4305  return angle::radian_t(std::atan2(y.template convert<typename units::traits::unit_t_traits<X>::unit_type>()(), x()));
4306  }
4307 #endif
4308 
4309  //----------------------------------
4310  // HYPERBOLIC TRIG FUNCTIONS
4311  //----------------------------------
4312 
4321 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4322  template<class AngleUnit>
4323  dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
4324  {
4325  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4326  return dimensionless::scalar_t(std::cosh(angle.template convert<angle::radian>()()));
4327  }
4328 #endif
4329 
4338 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4339  template<class AngleUnit>
4340  dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
4341  {
4342  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4343  return dimensionless::scalar_t(std::sinh(angle.template convert<angle::radian>()()));
4344  }
4345 #endif
4346 
4355 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4356  template<class AngleUnit>
4357  dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
4358  {
4359  static_assert(traits::is_angle_unit<AngleUnit>::value, "Type `AngleUnit` must be a unit of angle derived from `unit_t`.");
4360  return dimensionless::scalar_t(std::tanh(angle.template convert<angle::radian>()()));
4361  }
4362 #endif
4363 
4372 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4373  template<class ScalarUnit>
4374  angle::radian_t acosh(const ScalarUnit x) noexcept
4375  {
4376  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4377  return angle::radian_t(std::acosh(x()));
4378  }
4379 #endif
4380 
4388 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4389  template<class ScalarUnit>
4390  angle::radian_t asinh(const ScalarUnit x) noexcept
4391  {
4392  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4393  return angle::radian_t(std::asinh(x()));
4394  }
4395 #endif
4396 
4406 #if !defined(DISABLE_PREDEFINED_UNITS) || defined(ENABLE_PREDEFINED_ANGLE_UNITS)
4407  template<class ScalarUnit>
4408  angle::radian_t atanh(const ScalarUnit x) noexcept
4409  {
4410  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4411  return angle::radian_t(std::atanh(x()));
4412  }
4413 #endif
4414 
4415  //----------------------------------
4416  // TRANSCENDENTAL FUNCTIONS
4417  //----------------------------------
4418 
4419  // it makes NO SENSE to put dimensioned units into a transcendental function, and if you think it does you are
4420  // demonstrably wrong. https://en.wikipedia.org/wiki/Transcendental_function#Dimensional_analysis
4421 
4431  template<class ScalarUnit>
4432  dimensionless::scalar_t exp(const ScalarUnit x) noexcept
4433  {
4434  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4435  return dimensionless::scalar_t(std::exp(x()));
4436  }
4437 
4447  template<class ScalarUnit>
4448  dimensionless::scalar_t log(const ScalarUnit x) noexcept
4449  {
4450  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4451  return dimensionless::scalar_t(std::log(x()));
4452  }
4453 
4462  template<class ScalarUnit>
4463  dimensionless::scalar_t log10(const ScalarUnit x) noexcept
4464  {
4465  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4466  return dimensionless::scalar_t(std::log10(x()));
4467  }
4468 
4480  template<class ScalarUnit>
4481  dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit* intpart) noexcept
4482  {
4483  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4484 
4485  UNIT_LIB_DEFAULT_TYPE intp;
4487  *intpart = intp;
4488  return fracpart;
4489  }
4490 
4498  template<class ScalarUnit>
4499  dimensionless::scalar_t exp2(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::exp2(x()));
4503  }
4504 
4513  template<class ScalarUnit>
4514  dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
4515  {
4516  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4517  return dimensionless::scalar_t(std::expm1(x()));
4518  }
4519 
4529  template<class ScalarUnit>
4530  dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
4531  {
4532  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4533  return dimensionless::scalar_t(std::log1p(x()));
4534  }
4535 
4544  template<class ScalarUnit>
4545  dimensionless::scalar_t log2(const ScalarUnit x) noexcept
4546  {
4547  static_assert(traits::is_dimensionless_unit<ScalarUnit>::value, "Type `ScalarUnit` must be a dimensionless unit derived from `unit_t`.");
4548  return dimensionless::scalar_t(std::log2(x()));
4549  }
4550 
4551  //----------------------------------
4552  // POWER FUNCTIONS
4553  //----------------------------------
4554 
4555  /* pow is implemented earlier in the library since a lot of the unit definitions depend on it */
4556 
4569  template<class UnitType, std::enable_if_t<units::traits::has_linear_scale<UnitType>::value, int> = 0>
4570  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>
4571  {
4572  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>
4573  (std::sqrt(value()));
4574  }
4575 
4585  template<class UnitTypeLhs, class UnitTypeRhs, std::enable_if_t<units::traits::has_linear_scale<UnitTypeLhs, UnitTypeRhs>::value, int> = 0>
4586  inline UnitTypeLhs hypot(const UnitTypeLhs& x, const UnitTypeRhs& y)
4587  {
4588  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of hypot() function are not compatible units.");
4589  return UnitTypeLhs(std::hypot(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4590  }
4591 
4592  //----------------------------------
4593  // ROUNDING FUNCTIONS
4594  //----------------------------------
4595 
4603  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4604  UnitType ceil(const UnitType x) noexcept
4605  {
4606  return UnitType(std::ceil(x()));
4607  }
4608 
4616  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4617  UnitType floor(const UnitType x) noexcept
4618  {
4619  return UnitType(std::floor(x()));
4620  }
4621 
4630  template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4631  UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
4632  {
4633  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmod() function are not compatible units.");
4634  return UnitTypeLhs(std::fmod(numer(), denom.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4635  }
4636 
4645  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4646  UnitType trunc(const UnitType x) noexcept
4647  {
4648  return UnitType(std::trunc(x()));
4649  }
4650 
4651 
4660  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4661  UnitType round(const UnitType x) noexcept
4662  {
4663  return UnitType(std::round(x()));
4664  }
4665 
4666  //----------------------------------
4667  // FLOATING POINT MANIPULATION
4668  //----------------------------------
4669 
4679  template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4680  UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4681  {
4682  return UnitTypeLhs(std::copysign(x(), y())); // no need for conversion to get the correct sign.
4683  }
4684 
4686  template<class UnitTypeLhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value>>
4687  UnitTypeLhs copysign(const UnitTypeLhs x, const UNIT_LIB_DEFAULT_TYPE y) noexcept
4688  {
4689  return UnitTypeLhs(std::copysign(x(), y));
4690  }
4691 
4692  //----------------------------------
4693  // MIN / MAX / DIFFERENCE
4694  //----------------------------------
4695 
4706  template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4707  UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4708  {
4709  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fdim() function are not compatible units.");
4710  return UnitTypeLhs(std::fdim(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4711  }
4712 
4723  template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4724  UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4725  {
4726  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmax() function are not compatible units.");
4727  return UnitTypeLhs(std::fmax(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4728  }
4729 
4741  template<class UnitTypeLhs, class UnitTypeRhs, class = std::enable_if_t<traits::is_unit_t<UnitTypeLhs>::value && traits::is_unit_t<UnitTypeRhs>::value>>
4742  UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
4743  {
4744  static_assert(traits::is_convertible_unit_t<UnitTypeLhs, UnitTypeRhs>::value, "Parameters of fmin() function are not compatible units.");
4745  return UnitTypeLhs(std::fmin(x(), y.template convert<typename units::traits::unit_t_traits<UnitTypeLhs>::unit_type>()()));
4746  }
4747 
4748  //----------------------------------
4749  // OTHER FUNCTIONS
4750  //----------------------------------
4751 
4759  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4760  UnitType fabs(const UnitType x) noexcept
4761  {
4762  return UnitType(std::fabs(x()));
4763  }
4764 
4772  template<class UnitType, class = std::enable_if_t<traits::is_unit_t<UnitType>::value>>
4773  UnitType abs(const UnitType x) noexcept
4774  {
4775  return UnitType(std::fabs(x()));
4776  }
4777 
4788  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>>
4789  auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x * y)
4790  {
4791  using resultType = decltype(x * y);
4792  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.");
4793  return resultType(std::fma(x(), y(), resultType(z)()));
4794  }
4795 
4796  } // end namespace math
4797 } // end namespace units
4798 
4799 //------------------------------
4800 // std::numeric_limits
4801 //------------------------------
4802 
4803 namespace std
4804 {
4805  template<class Units, typename T, template<typename> class NonLinearScale>
4806  class numeric_limits<units::unit_t<Units, T, NonLinearScale>>
4807  {
4808  public:
4809  static constexpr units::unit_t<Units, T, NonLinearScale> min()
4810  {
4811  return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::min());
4812  }
4813  static constexpr units::unit_t<Units, T, NonLinearScale> max()
4814  {
4815  return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::max());
4816  }
4817  static constexpr units::unit_t<Units, T, NonLinearScale> lowest()
4818  {
4819  return units::unit_t<Units, T, NonLinearScale>(std::numeric_limits<T>::lowest());
4820  }
4821  };
4822 }
4823 
4824 #ifdef _MSC_VER
4825 # if _MSC_VER <= 1800
4826 # pragma warning(pop)
4827 # undef constexpr
4828 # pragma pop_macro("constexpr")
4829 # undef noexcept
4830 # pragma pop_macro("noexcept")
4831 # undef _ALLOW_KEYWORD_MACROS
4832 # endif // _MSC_VER < 1800
4833 # pragma pop_macro("pascal")
4834 #endif // _MSC_VER
4835 
4836 #endif // units_h__
4837 
4838 // For Emacs
4839 // Local Variables:
4840 // Mode: C++
4841 // c-basic-offset: 2
4842 // fill-column: 116
4843 // tab-width: 4
4844 // End:
units::traits::is_angle_unit
Definition: units.h:3443
units::unit_t::to
constexpr Ty to() const noexcept
unit value
Definition: units.h:2081
units::category::frequency_unit
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > frequency_unit
Represents an SI derived unit of frequency.
Definition: units.h:779
units::math::asin
angle::radian_t asin(const ScalarUnit x) noexcept
Compute arc sine.
Definition: units.h:4263
units::linear_scale
unit_t scale which is linear
Definition: units.h:2440
units::constants::e
static constexpr const charge::coulomb_t e(1.6021766208e-19)
elementary charge.
units::category::data_unit
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:806
UNIT_ADD_CATEGORY_TRAIT
#define UNIT_ADD_CATEGORY_TRAIT(unitCategory)
Macro to create the is_category_unit type trait.
Definition: units.h:358
units::math::trunc
UnitType trunc(const UnitType x) noexcept
Truncate value.
Definition: units.h:4646
units::ratio_sqrt
typename units::detail::Sqrt< Ratio, std::ratio< 1, Eps > >::type ratio_sqrt
Calculate square root of a ratio at compile-time.
Definition: units.h:1326
units::exbi
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:1476
units::category::magnetic_flux_unit
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:792
units::tebi
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:1474
units::compound_unit
typename units::detail::compound_impl< U, Us... >::type compound_unit
Represents a unit type made up from other units.
Definition: units.h:1404
units::traits::has_decibel_scale
Trait which tests whether a type is inherited from a decibel scale.
Definition: units.h:2397
units::exa
typename units::detail::prefix< std::exa, U >::type exa
Represents the type of class U with the metric 'exa' prefix appended.
Definition: units.h:1462
units::category::pressure_unit
base_unit< detail::meter_ratio<-1 >, std::ratio< 1 >, std::ratio<-2 > > pressure_unit
Represents an SI derived unit of pressure.
Definition: units.h:784
units::unit_value_subtract::value
static constexpr const unit_t< unit_type > value() noexcept
Value of difference.
Definition: units.h:3105
units::constants::mu0
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.
units::constants::Z0
static constexpr const impedance::ohm_t Z0(mu0 *c)
characteristic impedance of vacuum.
units::category::area_unit
base_unit< detail::meter_ratio< 2 > > area_unit
Represents an SI derived unit of area.
Definition: units.h:802
units::math::abs
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: units.h:4773
units::math::log
dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition: units.h:4448
units::unit_t::operator=
unit_t & operator=(const Ty &rhs) noexcept
assignment
Definition: units.h:1979
units::category::angle_unit
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:770
units::math::tanh
dimensionless::scalar_t tanh(const AngleUnit angle) noexcept
Compute hyperbolic tangent.
Definition: units.h:4357
units::hecto
typename units::detail::prefix< std::hecto, U >::type hecto
Represents the type of class U with the metric 'hecto' prefix appended.
Definition: units.h:1456
units::unit_t::value_type
T value_type
Synonym for underlying type. May be removed in future versions. Prefer underlying_type.
Definition: units.h:1903
units::giga
typename units::detail::prefix< std::giga, U >::type giga
Represents the type of class U with the metric 'giga' prefix appended.
Definition: units.h:1459
units::traits::is_same_scale
Trait which tests whether two types has the same non-linear scale.
Definition: units.h:2415
units::category::charge_unit
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:785
units::operator+
constexpr UnitTypeRhs operator+(const dimensionless::dB_t &lhs, const UnitTypeRhs &rhs) noexcept
Addition between unit_t types with a decibel_scale and dimensionless dB units.
Definition: units.h:2856
units::operator/
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:2598
units::unit_t::unit_t
constexpr unit_t(const Ty value) noexcept
constructor
Definition: units.h:1932
units::kilo
typename units::detail::prefix< std::kilo, U >::type kilo
Represents the type of class U with the metric 'kilo' prefix appended.
Definition: units.h:1457
units::math::atanh
angle::radian_t atanh(const ScalarUnit x) noexcept
Compute arc hyperbolic tangent.
Definition: units.h:4408
units::math::exp
dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition: units.h:4432
units::pebi
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:1475
units::category::time_unit
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio< 1 > > time_unit
Represents an SI base unit of time.
Definition: units.h:769
units::traits::is_base_unit
Trait which tests if a class is a base_unit type.
Definition: units.h:666
UNIT_ADD_DECIBEL
#define UNIT_ADD_DECIBEL(namespaceName, nameSingular, abbreviation)
Macro to create decibel container and literals for an existing unit type.
Definition: units.h:309
units::deci
typename units::detail::prefix< std::deci, U >::type deci
Represents the type of class U with the metric 'deci' prefix appended.
Definition: units.h:1454
units::unit_t::operator!=
constexpr bool operator!=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
inequality
Definition: units.h:2062
units::unit_t::operator==
constexpr bool operator==(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
equality
Definition: units.h:2041
units::convert
static constexpr T convert(const T &value) noexcept
converts a value from one type to another.
Definition: units.h:1616
units::constants::F
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
units::peta
typename units::detail::prefix< std::peta, U >::type peta
Represents the type of class U with the metric 'peta' prefix appended.
Definition: units.h:1461
units::unit_t::unit_type
Units unit_type
Type of unit the unit_t represents (e.g. meters)
Definition: units.h:1904
units::math::pow
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:2760
units::category::concentration_unit
base_unit concentration_unit
Represents a unit of concentration.
Definition: units.h:805
units::constants::sigma
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.
units::unit_t::operator=
unit_t & operator=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
assignment
Definition: units.h:1967
units::math::sinh
dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
Compute hyperbolic sine.
Definition: units.h:4340
units::unit_t::unit_t
constexpr unit_t(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) noexcept
copy constructor (converting)
Definition: units.h:1955
units::unit_t
Container for values which represent quantities of a given unit.
Definition: units.h:1889
units::math::log10
dimensionless::scalar_t log10(const ScalarUnit x) noexcept
Compute common logarithm.
Definition: units.h:4463
units::category::luminous_intensity_unit
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:774
units::math::fmod
UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
Compute remainder of division.
Definition: units.h:4631
units::unit_value_multiply::value
static constexpr const unit_t< unit_type > value() noexcept
Value of product.
Definition: units.h:3156
units::unit_t::operator>
constexpr bool operator>(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than
Definition: units.h:2016
units::category::luminous_flux_unit
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:795
units::math::hypot
UnitTypeLhs hypot(const UnitTypeLhs &x, const UnitTypeRhs &y)
Computes the square root of the sum-of-squares of x and y.
Definition: units.h:4586
units::math::asinh
angle::radian_t asinh(const ScalarUnit x) noexcept
Compute arc hyperbolic sine.
Definition: units.h:4390
units::math::log2
dimensionless::scalar_t log2(const ScalarUnit x) noexcept
Compute binary logarithm.
Definition: units.h:4545
units::math::copysign
UnitTypeLhs copysign(const UnitTypeLhs x, const double y) noexcept
Overload to copy the sign from a raw double.
Definition: units.h:4687
units::unit_value_add
adds two unit_value_t types at compile-time
Definition: units.h:3039
units::inverse
typename units::detail::inverse_impl< U >::type inverse
represents the inverse unit type of class U.
Definition: units.h:1104
units::math::round
UnitType round(const UnitType x) noexcept
Round to nearest.
Definition: units.h:4661
units::unit_t::value
constexpr underlying_type value() const noexcept
unit value
Definition: units.h:2071
units::math::fmax
UnitTypeLhs fmax(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Maximum value.
Definition: units.h:4724
units::math::modf
dimensionless::scalar_t modf(const ScalarUnit x, ScalarUnit *intpart) noexcept
Break into fractional and integral parts.
Definition: units.h:4481
units::math::exp2
dimensionless::scalar_t exp2(const ScalarUnit x) noexcept
Compute binary exponential function.
Definition: units.h:4499
units::category::inductance_unit
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:794
units::operator*
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:2542
units::category::dimensionless_unit
base_unit dimensionless_unit
Represents a quantity with no dimension.
Definition: units.h:763
units::traits::base_unit_of
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:902
units::category::magnetic_field_strength_unit
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:793
units::constants::epsilon0
static constexpr const unit_t< compound_unit< capacitance::farad, inverse< length::meter > > > epsilon0(1.0/(mu0 *math::cpow< 2 >(c)))
vacuum permitivity.
units::traits::is_unit_value_t
Trait which tests whether a type is a unit_value_t representing the given unit type.
Definition: units.h:2989
units::atto
typename units::detail::prefix< std::atto, U >::type atto
Represents the type of class U with the metric 'atto' prefix appended.
Definition: units.h:1447
units::category::impedance_unit
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:790
units::math::atan2
angle::radian_t atan2(const Y y, const X x) noexcept
Compute arc tangent with two parameters.
Definition: units.h:4300
UNIT_ADD
#define UNIT_ADD(namespaceName, nameSingular, namePlural, abbreviation,...)
Macro for generating the boiler-plate code needed for a new unit.
Definition: units.h:267
units::unit_t::underlying_type
T underlying_type
Type of the underlying storage of the unit_t (e.g. double)
Definition: units.h:1902
units::constants::m_p
static constexpr const mass::kilogram_t m_p(1.672621898e-27)
proton mass.
units::centi
typename units::detail::prefix< std::centi, U >::type centi
Represents the type of class U with the metric 'centi' prefix appended.
Definition: units.h:1453
units::unit_t::operator>=
constexpr bool operator>=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
greater-than or equal
Definition: units.h:2028
units::constants::G
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.
units::unit_t::operator<
constexpr bool operator<(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than
Definition: units.h:1992
units::math::copysign
UnitTypeLhs copysign(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Copy sign.
Definition: units.h:4680
units::math::fdim
UnitTypeLhs fdim(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Positive difference.
Definition: units.h:4707
units::constants::c
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
units::constants::N_A
static constexpr const unit_t< inverse< substance::mol > > N_A(6.022140857e23)
Avagadro's Number.
units::category::radioactivity_unit
base_unit< detail::meter_ratio< 0 >, std::ratio< 0 >, std::ratio<-1 > > radioactivity_unit
Represents an SI derived unit of radioactivity.
Definition: units.h:797
units::math::sin
dimensionless::scalar_t sin(const AngleUnit angle) noexcept
Compute sine.
Definition: units.h:4215
UNIT_ADD_WITH_METRIC_PREFIXES
#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:384
units::math::expm1
dimensionless::scalar_t expm1(const ScalarUnit x) noexcept
Compute exponential minus one.
Definition: units.h:4514
units::category::solid_angle_unit
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:778
units::category::voltage_unit
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:788
units::unit_value_subtract
subtracts two unit_value_t types at compile-time
Definition: units.h:3088
units::category::data_transfer_rate_unit
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:807
units::category::temperature_unit
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:772
units::math::cpow
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:2775
units::category::torque_unit
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > torque_unit
Represents an SI derived unit of torque.
Definition: units.h:801
units::nano
typename units::detail::prefix< std::nano, U >::type nano
Represents the type of class U with the metric 'nano' prefix appended.
Definition: units.h:1450
units::category::illuminance_unit
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:796
units::constants::R
static constexpr const unit_t< compound_unit< energy::joules, inverse< temperature::kelvin >, inverse< substance::moles > > > R(8.3144598)
Gas constant.
units::math::acos
angle::radian_t acos(const ScalarUnit x) noexcept
Compute arc cosine.
Definition: units.h:4247
units::category::volume_unit
base_unit< detail::meter_ratio< 3 > > volume_unit
Represents an SI derived unit of volume.
Definition: units.h:803
units::math::tan
dimensionless::scalar_t tan(const AngleUnit angle) noexcept
Compute tangent.
Definition: units.h:4231
units::category::energy_unit
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-2 > > energy_unit
Represents an SI derived unit of energy.
Definition: units.h:786
units::unit_t::unit_t
constexpr unit_t(const std::chrono::duration< Rep, Period > &value) noexcept
chrono constructor
Definition: units.h:1943
units::mebi
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:1472
units::math::floor
UnitType floor(const UnitType x) noexcept
Round down value.
Definition: units.h:4617
units::math::sqrt
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:4570
UNIT_ADD_WITH_METRIC_AND_BINARY_PREFIXES
#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:419
units::math::fmin
UnitTypeLhs fmin(const UnitTypeLhs x, const UnitTypeRhs y) noexcept
Minimum value.
Definition: units.h:4742
units::squared
typename units::detail::squared_impl< U >::type squared
represents the unit type of class U squared
Definition: units.h:1135
units::gibi
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:1473
units::math::cos
dimensionless::scalar_t cos(const AngleUnit angle) noexcept
Compute cosine.
Definition: units.h:4198
units::math::cosh
dimensionless::scalar_t cosh(const AngleUnit angle) noexcept
Compute hyperbolic cosine.
Definition: units.h:4323
units::category::angular_velocity_unit
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:781
units::femto
typename units::detail::prefix< std::femto, U >::type femto
Represents the type of class U with the metric 'femto' prefix appended.
Definition: units.h:1448
units::unit_t::operator<=
constexpr bool operator<=(const unit_t< UnitsRhs, Ty, NlsRhs > &rhs) const noexcept
less-than or equal
Definition: units.h:2004
units::constants::k_e
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.
units::unit_cast
constexpr T unit_cast(const Units &value) noexcept
Casts a unit container to an arithmetic type.
Definition: units.h:2356
units::math::acosh
angle::radian_t acosh(const ScalarUnit x) noexcept
Compute arc hyperbolic cosine.
Definition: units.h:4374
units::constants::k_B
static constexpr const unit_t< compound_unit< energy::joules, inverse< temperature::kelvin > > > k_B(R/N_A)
Boltzmann constant.
units::decibel_scale::m_value
T m_value
linearized value
Definition: units.h:2809
units::mega
typename units::detail::prefix< std::mega, U >::type mega
Represents the type of class U with the metric 'mega' prefix appended.
Definition: units.h:1458
units::constants::m_e
static constexpr const mass::kilogram_t m_e(9.10938356e-31)
electron mass.
units::category::capacitance_unit
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:789
units::square_root
typename units::detail::sqrt_impl< U, Eps >::type square_root
represents the square root of type class U.
Definition: units.h:1371
units::base_unit
Class representing SI base unit types.
Definition: units.h:728
units::category::conductance_unit
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:791
units::unit_value_sqrt::value
static constexpr const unit_t< unit_type > value() noexcept
Value of square root.
Definition: units.h:3300
units::decibel_scale
unit_t scale for representing decibel values.
Definition: units.h:2366
units::traits::is_unit_t
Traits which tests if a class is a unit
Definition: units.h:1830
units::category::velocity_unit
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-1 > > velocity_unit
Represents an SI derived unit of velocity.
Definition: units.h:780
units::unit_value_divide::value
static constexpr const unit_t< unit_type > value() noexcept
Value of quotient.
Definition: units.h:3206
units::operator-
constexpr 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 >
Subtraction between unit_t types with a decibel_scale and dimensionless dB units.
Definition: units.h:2884
units::constants::mu_B
static constexpr const unit_t< compound_unit< energy::joules, inverse< magnetic_field_strength::tesla > > > mu_B(e *h/(4 *pi *m_e))
Bohr magneton.
units::traits::is_nonlinear_scale
Trait which tests that class T meets the requirements for a non-linear scale.
Definition: units.h:1710
units::unit_value_divide
divides two unit_value_t types at compile-time
Definition: units.h:3188
units
Unit Conversion Library namespace.
Definition: units.h:92
units::traits::is_unit_value_t_category
Trait which tests whether type T is a unit_value_t with a unit type in the given category.
Definition: units.h:2999
units::category::substance_unit
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:773
units::category::density_unit
base_unit< detail::meter_ratio<-3 >, std::ratio< 1 > > density_unit
Represents an SI derived unit of density.
Definition: units.h:804
units::traits::is_convertible_unit_t
Trait which tests whether two container types derived from unit_t are convertible to each other.
Definition: units.h:1790
units::micro
typename units::detail::prefix< std::micro, U >::type micro
Represents the type of class U with the metric 'micro' prefix appended.
Definition: units.h:1451
units::pico
typename units::detail::prefix< std::pico, U >::type pico
Represents the type of class U with the metric 'pico' prefix appended.
Definition: units.h:1449
units::math::atan
angle::radian_t atan(const ScalarUnit x) noexcept
Compute arc tangent.
Definition: units.h:4283
units::math::fma
auto fma(const UnitTypeLhs x, const UnitMultiply y, const UnitAdd z) noexcept -> decltype(x *y)
Multiply-add.
Definition: units.h:4789
units::linear_scale::linear_scale
constexpr linear_scale()=default
default constructor.
units::category::scalar_unit
base_unit scalar_unit
Represents a quantity with no dimension.
Definition: units.h:762
units::cubed
typename units::detail::cubed_impl< U >::type cubed
represents the type of class U cubed.
Definition: units.h:1165
units::deca
typename units::detail::prefix< std::deca, U >::type deca
Represents the type of class U with the metric 'deca' prefix appended.
Definition: units.h:1455
units::linear_scale< double >::m_value
double m_value
linearized value.
Definition: units.h:2454
units::kibi
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:1471
units::category::current_unit
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:771
units::unit_value_sqrt
calculates square root of unit_value_t at compile-time
Definition: units.h:3284
units::traits::is_unit
Traits which tests if a class is a unit
Definition: units.h:692
units::unit_value_t
Stores a rational unit value as a compile-time constant.
Definition: units.h:2969
units::unit_value_add::value
static constexpr const unit_t< unit_type > value() noexcept
Value of sum.
Definition: units.h:3055
units::unit_value_power::value
static constexpr const unit_t< unit_type > value() noexcept
Value of exponentiation.
Definition: units.h:3253
units::traits::is_ratio
Trait that tests whether a type represents a std::ratio.
Definition: units.h:565
units::constants::h
static constexpr const unit_t< compound_unit< energy::joule, time::seconds > > h(6.626070040e-34)
Planck constant.
units::traits::is_convertible_unit
Trait which checks whether two units can be converted to each other.
Definition: units.h:1498
units::unit
Type representing an arbitrary unit.
Definition: units.h:853
units::category::force_unit
base_unit< detail::meter_ratio< 1 >, std::ratio< 1 >, std::ratio<-2 > > force_unit
Represents an SI derived unit of force.
Definition: units.h:783
units::unit_t::toLinearized
constexpr Ty toLinearized() const noexcept
linearized unit value
Definition: units.h:2092
units::unit_value_multiply
multiplies two unit_value_t types at compile-time
Definition: units.h:3138
units::traits::has_linear_scale
Trait which tests whether a type is inherited from a linear scale.
Definition: units.h:2379
units::unit_t::non_linear_scale_type
NonLinearScale< T > non_linear_scale_type
Type of the non-linear scale of the unit_t (e.g. linear_scale)
Definition: units.h:1901
units::math::ceil
UnitType ceil(const UnitType x) noexcept
Round up value.
Definition: units.h:4604
units::category::acceleration_unit
base_unit< detail::meter_ratio< 1 >, std::ratio< 0 >, std::ratio<-2 > > acceleration_unit
Represents an SI derived unit of acceleration.
Definition: units.h:782
units::math::fabs
UnitType fabs(const UnitType x) noexcept
Compute absolute value.
Definition: units.h:4760
units::unit_t::abbreviation
constexpr const char * abbreviation() const noexcept
returns the unit abbreviation
Definition: units.h:2155
units::unit_t::name
constexpr const char * name() const noexcept
returns the unit name
Definition: units.h:2147
units::category::power_unit
base_unit< detail::meter_ratio< 2 >, std::ratio< 1 >, std::ratio<-3 > > power_unit
Represents an SI derived unit of power.
Definition: units.h:787
units::constants::pi
static constexpr const unit_t< PI > pi(1)
Ratio of a circle's circumference to its diameter.
units::tera
typename units::detail::prefix< std::tera, U >::type tera
Represents the type of class U with the metric 'tera' prefix appended.
Definition: units.h:1460
units::unit_t::convert
constexpr unit_t< U > convert() const noexcept
conversion
Definition: units.h:2107
units::category::length_unit
base_unit< detail::meter_ratio< 1 > > length_unit
Represents an SI base unit of length.
Definition: units.h:767
units::unit_t::unit_t
constexpr unit_t(const T value, const Args &... args) noexcept
constructor
Definition: units.h:1921
units::unit_value_power
raises unit_value_to a power at compile-time
Definition: units.h:3237
units::milli
typename units::detail::prefix< std::milli, U >::type milli
Represents the type of class U with the metric 'milli' prefix appended.
Definition: units.h:1452
units::traits::is_dimensionless_unit
Definition: units.h:1818
units::category::mass_unit
base_unit< detail::meter_ratio< 0 >, std::ratio< 1 > > mass_unit
Represents an SI base unit of mass.
Definition: units.h:768
units::make_unit
constexpr UnitType make_unit(const T value) noexcept
Constructs a unit container from an arithmetic type.
Definition: units.h:2181
units::math::log1p
dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
Compute logarithm plus one.
Definition: units.h:4530