Forked from
Air Shower Physics / corsika
3464 commits behind the upstream repository.
-
Maximilian Reininghaus authoredMaximilian Reininghaus authored
quantity.hpp 32.83 KiB
/**
* \file quantity.hpp
*
* \brief Zero-overhead dimensional analysis and unit/quantity manipulation and
* conversion. \author Michael S. Kenniston, Martin Moene \date 7 September 2013
* \since 0.4
*
* Copyright 2013 Universiteit Leiden. All rights reserved.
*
* Copyright (c) 2001 by Michael S. Kenniston. For the most
* recent version check www.xnet.com/~msk/quantity. Permission is granted
* to use this code without restriction so long as this copyright
* notice appears in all source files.
*
* This code is provided as-is, with no warrantee of correctness.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Unless otherwise specified, the definitions of all units in this
* file are from NIST Special Publication 811, found online at
* http://physics.nist.gov/Document/sp811.pdf
* Other sources: OED = Oxford English Dictionary
*/
#ifndef PHYS_UNITS_QUANTITY_HPP_INCLUDED
#define PHYS_UNITS_QUANTITY_HPP_INCLUDED
#include <cmath>
#include <cstdlib>
#include <utility> // std::declval
/// namespace phys.
namespace phys {
/// namespace units.
namespace units {
#ifdef PHYS_UNITS_REP_TYPE
using Rep = PHYS_UNITS_REP_TYPE;
#else
using Rep = double;
#endif
/*
* declare now, define later.
*/
template <typename Dims, typename T = Rep>
class quantity;
/**
* We could drag dimensions around individually, but it's much more convenient to
* package them.
*/
template <int D1, int D2, int D3, int D4 = 0, int D5 = 0, int D6 = 0, int D7 = 0,
int D8 = 0>
struct dimensions {
enum {
dim1 = D1,
dim2 = D2,
dim3 = D3,
dim4 = D4,
dim5 = D5,
dim6 = D6,
dim7 = D7,
dim8 = D8,
is_all_zero = D1 == 0 && D2 == 0 && D3 == 0 && D4 == 0 && D5 == 0 && D6 == 0 &&
D7 == 0 && D8 == 0,
is_base = 1 == (D1 != 0) + (D2 != 0) + (D3 != 0) + (D4 != 0) + (D5 != 0) +
(D6 != 0) + (D7 != 0) + (D8 != 0) &&
1 == D1 + D2 + D3 + D4 + D5 + D6 + D7 + D8,
};
template <int R1, int R2, int R3, int R4, int R5, int R6, int R7, int R8>
constexpr bool operator==(dimensions<R1, R2, R3, R4, R5, R6, R7, R8> const&) const {
return D1 == R1 && D2 == R2 && D3 == R3 && D4 == R4 && D5 == R5 && D6 == R6 &&
D7 == R7 && D8 == R8;
}
template <int R1, int R2, int R3, int R4, int R5, int R6, int R7, int R8>
constexpr bool operator!=(
dimensions<R1, R2, R3, R4, R5, R6, R7, R8> const& rhs) const {
return !(*this == rhs);
}
};
/// demensionless 'dimension'.
typedef dimensions<0, 0, 0> dimensionless_d;
/// namespace detail.
namespace detail {
/**
* \brief The "collapse" template is used to avoid quantity< dimensions< 0, 0, 0 >
* >, i.e. to make dimensionless results come out as type "Rep".
*/
template <typename D, typename T>
struct collapse {
typedef quantity<D, T> type;
};
template <typename T>
struct collapse<dimensionless_d, T> {
typedef T type;
};
template <typename D, typename T>
using Collapse = typename collapse<D, T>::type;
// promote types of expression to result type.
template <typename X, typename Y>
using PromoteAdd = decltype(std::declval<X>() + std::declval<Y>());
template <typename X, typename Y>
using PromoteMul = decltype(std::declval<X>() * std::declval<Y>());
/*
* The following batch of structs are type generators to calculate
* the correct type of the result of various operations.
*/
/**
* product type generator.
*/
template <typename DX, typename DY, typename T>
struct product {
enum {
d1 = DX::dim1 + DY::dim1,
d2 = DX::dim2 + DY::dim2,
d3 = DX::dim3 + DY::dim3,
d4 = DX::dim4 + DY::dim4,
d5 = DX::dim5 + DY::dim5,
d6 = DX::dim6 + DY::dim6,
d7 = DX::dim7 + DY::dim7,
d8 = DX::dim8 + DY::dim8
};
typedef dimensions<d1, d2, d3, d4, d5, d6, d7, d8> dim;
typedef Collapse<dim, T> type;
};
/**
* convenience type for product dimension
*/
template <typename DX, typename DY>
using product_d = typename product<DX, DY, Rep>::dim;
template <typename DX, typename DY, typename X, typename Y>
using Product = typename product<DX, DY, PromoteMul<X, Y>>::type;
/**
* quotient type generator.
*/
template <typename DX, typename DY, typename T>
struct quotient {
enum {
d1 = DX::dim1 - DY::dim1,
d2 = DX::dim2 - DY::dim2,
d3 = DX::dim3 - DY::dim3,
d4 = DX::dim4 - DY::dim4,
d5 = DX::dim5 - DY::dim5,
d6 = DX::dim6 - DY::dim6,
d7 = DX::dim7 - DY::dim7,
d8 = DX::dim8 - DY::dim8
};
typedef dimensions<d1, d2, d3, d4, d5, d6, d7, d8> dim;
typedef Collapse<dim, T> type;
};
/**
* convenience type for quotient dimension
*/
template <typename DX, typename DY>
using quotient_d = typename quotient<DX, DY, Rep>::dim;
template <typename DX, typename DY, typename X, typename Y>
using Quotient = typename quotient<DX, DY, PromoteMul<X, Y>>::type;
/**
* reciprocal type generator.
*/
template <typename D, typename T>
struct reciprocal {
enum {
d1 = -D::dim1,
d2 = -D::dim2,
d3 = -D::dim3,
d4 = -D::dim4,
d5 = -D::dim5,
d6 = -D::dim6,
d7 = -D::dim7,
d8 = -D::dim8
};
typedef dimensions<d1, d2, d3, d4, d5, d6, d7, d8> dim;
typedef Collapse<dim, T> type;
};
/**
* convenience type for reciprocal dimension
*/
template <typename DX, typename DY>
using reciprocal_d = typename reciprocal<DX, Rep>::dim;
template <typename D, typename X, typename Y>
using Reciprocal = typename reciprocal<D, PromoteMul<X, Y>>::type;
/**
* power type generator.
*/
template <typename D, int N, typename T>
struct power {
enum {
d1 = N * D::dim1,
d2 = N * D::dim2,
d3 = N * D::dim3,
d4 = N * D::dim4,
d5 = N * D::dim5,
d6 = N * D::dim6,
d7 = N * D::dim7,
d8 = N * D::dim8
};
typedef dimensions<d1, d2, d3, d4, d5, d6, d7, d8> dim;
typedef Collapse<dim, T> type;
};
/**
* convenience type for power dimension
*/
template <typename DX, int N>
using power_d = typename power<DX, N, Rep>::dim;
template <typename D, int N, typename T>
using Power = typename power<D, N, T>::type;
/**
* root type generator.
*/
template <typename D, int N, typename T>
struct root {
enum {
all_even_multiples = D::dim1 % N == 0 && D::dim2 % N == 0 && D::dim3 % N == 0 &&
D::dim4 % N == 0 && D::dim5 % N == 0 && D::dim6 % N == 0 &&
D::dim7 % N == 0 && D::dim8 % N == 0
};
enum {
d1 = D::dim1 / N,
d2 = D::dim2 / N,
d3 = D::dim3 / N,
d4 = D::dim4 / N,
d5 = D::dim5 / N,
d6 = D::dim6 / N,
d7 = D::dim7 / N,
d8 = D::dim8 / N
};
typedef dimensions<d1, d2, d3, d4, d5, d6, d7, d8> dim;
typedef Collapse<dim, T> type;
};
/**
* convenience type for root dimension
*/
template <typename D, int N>
using root_d = typename root<D, N, Rep>::dim;
template <typename D, int N, typename T>
using Root = typename detail::root<D, N, T>::type;
/**
* tag to construct a quantity from a magnitude.
*/
constexpr struct magnitude_tag_t { } magnitude_tag{}; } // namespace detail
/**
* \brief class "quantity" is the heart of the library. It associates
* dimensions with a single "Rep" data member and protects it from
* dimensionally inconsistent use.
*/
template <typename Dims, typename T /*= Rep */>
class quantity {
public:
typedef Dims dimension_type;
typedef T value_type;
typedef quantity<Dims, T> this_type;
constexpr quantity()
: m_value{} {}
/**
* public converting initializing constructor;
* requires magnitude_tag to prevent constructing a quantity from a raw magnitude.
*/
template <typename X>
constexpr explicit quantity(detail::magnitude_tag_t, X x)
: m_value(x) {}
/**
* converting copy-assignment constructor.
*/
template <typename X>
constexpr quantity(quantity<Dims, X> const& x)
: m_value(x.magnitude()) {}
// /**
// * convert to compatible unit, for example: (3._dm).to(meter) gives 0.3;
// */
// constexpr value_type to( quantity const & x ) const { return *this / x; }
/**
* convert to given unit, for example: (3._dm).to(meter) gives 0.3;
*/
template <typename DX, typename X>
constexpr auto to(quantity<DX, X> const& x) const
-> detail::Quotient<Dims, DX, T, X> {
return *this / x;
}
/**
* the quantity's magnitude.
*/
constexpr value_type magnitude() const { return m_value; }
/**
* the quantity's dimensions.
*/
constexpr dimension_type dimension() const { return dimension_type{}; }
/**
* We need a "zero" of each type -- for comparisons, to initialize running
* totals, etc. Note: 0 m != 0 kg, since they are of different dimensionality.
* zero is really just defined for convenience, since
* quantity< length_d >::zero == 0 * meter, etc.
*/
static constexpr quantity zero() { return quantity{value_type(0.0)}; }
// static constexpr quantity zero = quantity{ value_type( 0.0 ) };
private:
/**
* private initializing constructor.
*/
constexpr explicit quantity(value_type x)
: m_value{x} {}
private:
value_type m_value;
enum { has_dimension = !Dims::is_all_zero };
// static_assert( has_dimension, "quantity dimensions must not all be zero" ); //
// MR: removed
private:
// friends:
// arithmetic
template <typename D, typename X, typename Y>
friend constexpr quantity<D, X>& operator+=(quantity<D, X>& x,
quantity<D, Y> const& y);
template <typename D, typename X>
friend constexpr quantity<D, X> operator+(quantity<D, X> const& x);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, detail::PromoteAdd<X, Y>> operator+(
quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, X>& operator-=(quantity<D, X>& x,
quantity<D, Y> const& y);
template <typename D, typename X>
friend constexpr quantity<D, X> operator-(quantity<D, X> const& x);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, detail::PromoteAdd<X, Y>> operator-(
quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, X>& operator*=(quantity<D, X>& x, const Y& y);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(
quantity<D, X> const& x, const Y& y);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(
const X& x, quantity<D, Y> const& y);
template <typename DX, typename DY, typename X, typename Y>
friend constexpr detail::Product<DX, DY, X, Y> operator*(
quantity<DX, X> const& lhs, quantity<DY, Y> const& rhs);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, X>& operator/=(quantity<D, X>& x, const Y& y);
template <typename D, typename X, typename Y>
friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator/(
quantity<D, X> const& x, const Y& y);
template <typename D, typename X, typename Y>
friend constexpr detail::Reciprocal<D, X, Y> operator/(const X& x,
quantity<D, Y> const& y);
template <typename DX, typename DY, typename X, typename Y>
friend constexpr detail::Quotient<DX, DY, X, Y> operator/(quantity<DX, X> const& x,
quantity<DY, Y> const& y);
// absolute value.
template <typename D, typename X>
friend constexpr quantity<D, X> abs(quantity<D, X> const& x);
// powers and roots
template <int N, typename D, typename X>
friend detail::Power<D, N, X> nth_power(quantity<D, X> const& x);
template <typename D, typename X>
friend constexpr detail::Power<D, 2, X> square(quantity<D, X> const& x);
template <typename D, typename X>
friend constexpr detail::Power<D, 3, X> cube(quantity<D, X> const& x);
template <int N, typename D, typename X>
friend detail::Root<D, N, X> nth_root(quantity<D, X> const& x);
template <typename D, typename X>
friend detail::Root<D, 2, X> sqrt(quantity<D, X> const& x);
// comparison
template <typename D, typename X, typename Y>
friend constexpr bool operator==(quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr bool operator!=(quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr bool operator<(quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr bool operator<=(quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr bool operator>(quantity<D, X> const& x, quantity<D, Y> const& y);
template <typename D, typename X, typename Y>
friend constexpr bool operator>=(quantity<D, X> const& x, quantity<D, Y> const& y);
};
// Give names to the seven fundamental dimensions of physical reality.
typedef dimensions<1, 0, 0, 0, 0, 0, 0, 0> length_d;
typedef dimensions<0, 1, 0, 0, 0, 0, 0, 0> mass_d;
typedef dimensions<0, 0, 1, 0, 0, 0, 0, 0> time_interval_d;
typedef dimensions<0, 0, 0, 1, 0, 0, 0, 0> electric_current_d;
typedef dimensions<0, 0, 0, 0, 1, 0, 0, 0> thermodynamic_temperature_d;
typedef dimensions<0, 0, 0, 0, 0, 1, 0, 0> amount_of_substance_d;
typedef dimensions<0, 0, 0, 0, 0, 0, 1, 0> luminous_intensity_d;
typedef dimensions<0, 0, 0, 0, 0, 0, 0, 1> hepenergy_d; // this is not an SI unit !
// Addition operators
/// quan += quan
template <typename D, typename X, typename Y>
constexpr quantity<D, X>& operator+=(quantity<D, X>& x, quantity<D, Y> const& y) {
return x.m_value += y.m_value, x;
}
/// + quan
template <typename D, typename X>
constexpr quantity<D, X> operator+(quantity<D, X> const& x) {
return quantity<D, X>(+x.m_value);
}
/// quan + quan
template <typename D, typename X, typename Y>
constexpr quantity<D, detail::PromoteAdd<X, Y>> operator+(quantity<D, X> const& x,
quantity<D, Y> const& y) {
return quantity<D, detail::PromoteAdd<X, Y>>(x.m_value + y.m_value);
}
// Subtraction operators
/// quan -= quan
template <typename D, typename X, typename Y>
constexpr quantity<D, X>& operator-=(quantity<D, X>& x, quantity<D, Y> const& y) {
return x.m_value -= y.m_value, x;
}
/// - quan
template <typename D, typename X>
constexpr quantity<D, X> operator-(quantity<D, X> const& x) {
return quantity<D, X>(-x.m_value);
}
/// quan - quan
template <typename D, typename X, typename Y>
constexpr quantity<D, detail::PromoteAdd<X, Y>> operator-(quantity<D, X> const& x,
quantity<D, Y> const& y) {
return quantity<D, detail::PromoteAdd<X, Y>>(x.m_value - y.m_value);
}
// Multiplication operators
/// quan *= num
template <typename D, typename X, typename Y>
constexpr quantity<D, X>& operator*=(quantity<D, X>& x, const Y& y) {
return x.m_value *= y, x;
}
/// quan * num
template <typename D, typename X, typename Y>
constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(quantity<D, X> const& x,
const Y& y) {
return quantity<D, detail::PromoteMul<X, Y>>(x.m_value * y);
}
/// num * quan
template <typename D, typename X, typename Y>
constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(const X& x,
quantity<D, Y> const& y) {
return quantity<D, detail::PromoteMul<X, Y>>(x * y.m_value);
}
/// quan * quan:
template <typename DX, typename DY, typename X, typename Y>
constexpr detail::Product<DX, DY, X, Y> operator*(quantity<DX, X> const& lhs,
quantity<DY, Y> const& rhs) {
return detail::Product<DX, DY, X, Y>(lhs.m_value * rhs.m_value);
}
// Division operators
/// quan /= num
template <typename D, typename X, typename Y>
constexpr quantity<D, X>& operator/=(quantity<D, X>& x, const Y& y) {
return x.m_value /= y, x;
}
/// quan / num
template <typename D, typename X, typename Y>
constexpr quantity<D, detail::PromoteMul<X, Y>> operator/(quantity<D, X> const& x,
const Y& y) {
return quantity<D, detail::PromoteMul<X, Y>>(x.m_value / y);
}
/// num / quan
template <typename D, typename X, typename Y>
constexpr detail::Reciprocal<D, X, Y> operator/(const X& x, quantity<D, Y> const& y) {
return detail::Reciprocal<D, X, Y>(x / y.m_value);
}
/// quan / quan:
template <typename DX, typename DY, typename X, typename Y>
constexpr detail::Quotient<DX, DY, X, Y> operator/(quantity<DX, X> const& x,
quantity<DY, Y> const& y) {
return detail::Quotient<DX, DY, X, Y>(x.m_value / y.m_value);
}
/// absolute value.
template <typename D, typename X>
constexpr quantity<D, X> abs(quantity<D, X> const& x) {
return quantity<D, X>(std::abs(x.m_value));
}
// General powers
/// N-th power.
template <int N, typename D, typename X>
detail::Power<D, N, X> nth_power(quantity<D, X> const& x) {
return detail::Power<D, N, X>(std::pow(x.m_value, X(N)));
}
// Low powers defined separately for efficiency.
/// square.
template <typename D, typename X>
constexpr detail::Power<D, 2, X> square(quantity<D, X> const& x) {
return x * x;
}
/// cube.
template <typename D, typename X>
constexpr detail::Power<D, 3, X> cube(quantity<D, X> const& x) {
return x * x * x;
}
// General root
/// n-th root.
template <int N, typename D, typename X>
detail::Root<D, N, X> nth_root(quantity<D, X> const& x) {
static_assert(detail::root<D, N, X>::all_even_multiples,
"root result dimensions must be integral");
return detail::Root<D, N, X>(std::pow(x.m_value, X(1.0) / N));
}
// Low roots defined separately for convenience.
/// square root.
template <typename D, typename X>
detail::Root<D, 2, X> sqrt(quantity<D, X> const& x) {
static_assert(detail::root<D, 2, X>::all_even_multiples,
"root result dimensions must be integral");
return detail::Root<D, 2, X>(std::pow(x.m_value, X(1.0) / 2));
}
// Comparison operators
/// equality.
template <typename D, typename X, typename Y>
constexpr bool operator==(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value == y.m_value;
}
/// inequality.
template <typename D, typename X, typename Y>
constexpr bool operator!=(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value != y.m_value;
}
/// less-than.
template <typename D, typename X, typename Y>
constexpr bool operator<(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value < y.m_value;
}
/// less-equal.
template <typename D, typename X, typename Y>
constexpr bool operator<=(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value <= y.m_value;
}
/// greater-than.
template <typename D, typename X, typename Y>
constexpr bool operator>(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value > y.m_value;
}
/// greater-equal.
template <typename D, typename X, typename Y>
constexpr bool operator>=(quantity<D, X> const& x, quantity<D, Y> const& y) {
return x.m_value >= y.m_value;
}
/// quantity's dimension.
template <typename DX, typename X>
inline constexpr DX dimension(quantity<DX, X> const& q) {
return q.dimension();
}
/// quantity's magnitude.
template <typename DX, typename X>
inline constexpr X magnitude(quantity<DX, X> const& q) {
return q.magnitude();
}
// The seven SI base units. These tie our numbers to the real world.
constexpr quantity<length_d> meter{detail::magnitude_tag, 1.0};
constexpr quantity<mass_d> kilogram{detail::magnitude_tag, 1.0};
constexpr quantity<time_interval_d> second{detail::magnitude_tag, 1.0};
constexpr quantity<electric_current_d> ampere{detail::magnitude_tag, 1.0};
constexpr quantity<thermodynamic_temperature_d> kelvin{detail::magnitude_tag, 1.0};
constexpr quantity<amount_of_substance_d> mole{detail::magnitude_tag, 1.0};
constexpr quantity<luminous_intensity_d> candela{detail::magnitude_tag, 1.0};
constexpr quantity<hepenergy_d> electronvolt{detail::magnitude_tag, 1.0};
// The standard SI prefixes.
constexpr long double yotta = 1e+24L;
constexpr long double zetta = 1e+21L;
constexpr long double exa = 1e+18L;
constexpr long double peta = 1e+15L;
constexpr long double tera = 1e+12L;
constexpr long double giga = 1e+9L;
constexpr long double mega = 1e+6L;
constexpr long double kilo = 1e+3L;
constexpr long double hecto = 1e+2L;
constexpr long double deka = 1e+1L;
constexpr long double deci = 1e-1L;
constexpr long double centi = 1e-2L;
constexpr long double milli = 1e-3L;
constexpr long double micro = 1e-6L;
constexpr long double nano = 1e-9L;
constexpr long double pico = 1e-12L;
constexpr long double femto = 1e-15L;
constexpr long double atto = 1e-18L;
constexpr long double zepto = 1e-21L;
constexpr long double yocto = 1e-24L;
// Binary prefixes, pending adoption.
constexpr long double kibi = 1024;
constexpr long double mebi = 1024 * kibi;
constexpr long double gibi = 1024 * mebi;
constexpr long double tebi = 1024 * gibi;
constexpr long double pebi = 1024 * tebi;
constexpr long double exbi = 1024 * pebi;
constexpr long double zebi = 1024 * exbi;
constexpr long double yobi = 1024 * zebi;
// The rest of the standard dimensional types, as specified in SP811.
using absorbed_dose_d = dimensions<2, 0, -2>;
using absorbed_dose_rate_d = dimensions<2, 0, -3>;
using acceleration_d = dimensions<1, 0, -2>;
using activity_of_a_nuclide_d = dimensions<0, 0, -1>;
using angular_velocity_d = dimensions<0, 0, -1>;
using angular_acceleration_d = dimensions<0, 0, -2>;
using area_d = dimensions<2, 0, 0>;
using capacitance_d = dimensions<-2, -1, 4, 2>;
using concentration_d = dimensions<-3, 0, 0, 0, 0, 1>;
using current_density_d = dimensions<-2, 0, 0, 1>;
using dose_equivalent_d = dimensions<2, 0, -2>;
using dynamic_viscosity_d = dimensions<-1, 1, -1>;
using electric_charge_d = dimensions<0, 0, 1, 1>;
using electric_charge_density_d = dimensions<-3, 0, 1, 1>;
using electric_conductance_d = dimensions<-2, -1, 3, 2>;
using electric_field_strenth_d = dimensions<1, 1, -3, -1>;
using electric_flux_density_d = dimensions<-2, 0, 1, 1>;
using electric_potential_d = dimensions<2, 1, -3, -1>;
using electric_resistance_d = dimensions<2, 1, -3, -2>;
using energy_d = dimensions<2, 1, -2>;
using energy_density_d = dimensions<-1, 1, -2>;
using exposure_d = dimensions<0, -1, 1, 1>;
using force_d = dimensions<1, 1, -2>;
using frequency_d = dimensions<0, 0, -1>;
using heat_capacity_d = dimensions<2, 1, -2, 0, -1>;
using heat_density_d = dimensions<0, 1, -2>;
using heat_density_flow_rate_d = dimensions<0, 1, -3>;
using heat_flow_rate_d = dimensions<2, 1, -3>;
using heat_flux_density_d = dimensions<0, 1, -3>;
using heat_transfer_coefficient_d = dimensions<0, 1, -3, 0, -1>;
using illuminance_d = dimensions<-2, 0, 0, 0, 0, 0, 1>;
using inductance_d = dimensions<2, 1, -2, -2>;
using irradiance_d = dimensions<0, 1, -3>;
using kinematic_viscosity_d = dimensions<2, 0, -1>;
using luminance_d = dimensions<-2, 0, 0, 0, 0, 0, 1>;
using luminous_flux_d = dimensions<0, 0, 0, 0, 0, 0, 1>;
using magnetic_field_strength_d = dimensions<-1, 0, 0, 1>;
using magnetic_flux_d = dimensions<2, 1, -2, -1>;
using magnetic_flux_density_d = dimensions<0, 1, -2, -1>;
using magnetic_permeability_d = dimensions<1, 1, -2, -2>;
using mass_density_d = dimensions<-3, 1, 0>;
using mass_flow_rate_d = dimensions<0, 1, -1>;
using molar_energy_d = dimensions<2, 1, -2, 0, 0, -1>;
using molar_entropy_d = dimensions<2, 1, -2, -1, 0, -1>;
using moment_of_force_d = dimensions<2, 1, -2>;
using permittivity_d = dimensions<-3, -1, 4, 2>;
using power_d = dimensions<2, 1, -3>;
using pressure_d = dimensions<-1, 1, -2>;
using radiance_d = dimensions<0, 1, -3>;
using radiant_intensity_d = dimensions<2, 1, -3>;
using speed_d = dimensions<1, 0, -1>;
using specific_energy_d = dimensions<2, 0, -2>;
using specific_heat_capacity_d = dimensions<2, 0, -2, 0, -1>;
using specific_volume_d = dimensions<3, -1, 0>;
using substance_permeability_d = dimensions<-1, 0, 1>;
using surface_tension_d = dimensions<0, 1, -2>;
using thermal_conductivity_d = dimensions<1, 1, -3, 0, -1>;
using thermal_diffusivity_d = dimensions<2, 0, -1>;
using thermal_insulance_d = dimensions<0, -1, 3, 0, 1>;
using thermal_resistance_d = dimensions<-2, -1, 3, 0, 1>;
using thermal_resistivity_d = dimensions<-1, -1, 3, 0, 1>;
using torque_d = dimensions<2, 1, -2>;
using volume_d = dimensions<3, 0, 0>;
using volume_flow_rate_d = dimensions<3, 0, -1>;
using wave_number_d = dimensions<-1, 0, 0>;
// Handy values.
constexpr Rep pi{Rep(3.141592653589793238462L)};
constexpr Rep percent{Rep(1) / 100};
//// Not approved for use alone, but needed for use with prefixes.
constexpr quantity<mass_d> gram{kilogram / 1000};
// The derived SI units, as specified in SP811.
constexpr Rep radian{Rep(1)};
constexpr Rep steradian{Rep(1)};
constexpr quantity<force_d> newton{meter * kilogram / square(second)};
constexpr quantity<pressure_d> pascal{newton / square(meter)};
constexpr quantity<energy_d> joule{newton * meter};
constexpr quantity<power_d> watt{joule / second};
constexpr quantity<electric_charge_d> coulomb{second * ampere};
constexpr quantity<electric_potential_d> volt{watt / ampere};
constexpr quantity<capacitance_d> farad{coulomb / volt};
constexpr quantity<electric_resistance_d> ohm{volt / ampere};
constexpr quantity<electric_conductance_d> siemens{ampere / volt};
constexpr quantity<magnetic_flux_d> weber{volt * second};
constexpr quantity<magnetic_flux_density_d> tesla{weber / square(meter)};
constexpr quantity<inductance_d> henry{weber / ampere};
constexpr quantity<thermodynamic_temperature_d> degree_celsius{kelvin};
constexpr quantity<luminous_flux_d> lumen{candela * steradian};
constexpr quantity<illuminance_d> lux{lumen / meter / meter};
constexpr quantity<activity_of_a_nuclide_d> becquerel{1 / second};
constexpr quantity<absorbed_dose_d> gray{joule / kilogram};
constexpr quantity<dose_equivalent_d> sievert{joule / kilogram};
constexpr quantity<frequency_d> hertz{1 / second};
// The rest of the units approved for use with SI, as specified in SP811.
// (However, use of these units is generally discouraged.)
constexpr quantity<length_d> angstrom{Rep(1e-10L) * meter};
constexpr quantity<area_d> are{Rep(1e+2L) * square(meter)};
constexpr quantity<pressure_d> bar{Rep(1e+5L) * pascal};
constexpr quantity<area_d> barn{Rep(1e-28L) * square(meter)};
constexpr quantity<activity_of_a_nuclide_d> curie{Rep(3.7e+10L) * becquerel};
constexpr quantity<time_interval_d> day{Rep(86400L) * second};
constexpr Rep degree_angle{pi / 180};
constexpr quantity<acceleration_d> gal{Rep(1e-2L) * meter / square(second)};
constexpr quantity<area_d> hectare{Rep(1e+4L) * square(meter)};
constexpr quantity<time_interval_d> hour{Rep(3600) * second};
constexpr quantity<speed_d> knot{Rep(1852) / 3600 * meter / second};
constexpr quantity<volume_d> liter{Rep(1e-3L) * cube(meter)};
constexpr quantity<time_interval_d> minute{Rep(60) * second};
constexpr Rep minute_angle{pi / 10800};
constexpr quantity<length_d> mile_nautical{Rep(1852) * meter};
constexpr quantity<absorbed_dose_d> rad{Rep(1e-2L) * gray};
constexpr quantity<dose_equivalent_d> rem{Rep(1e-2L) * sievert};
constexpr quantity<exposure_d> roentgen{Rep(2.58e-4L) * coulomb / kilogram};
constexpr Rep second_angle{pi / 648000L};
constexpr quantity<mass_d> ton_metric{Rep(1e+3L) * kilogram};
// Alternate (non-US) spellings:
constexpr quantity<length_d> metre{meter};
constexpr quantity<volume_d> litre{liter};
constexpr Rep deca{deka};
constexpr quantity<mass_d> tonne{ton_metric};
// cooked literals for base units;
// these could also have been created with a script.
#define QUANTITY_DEFINE_SCALING_LITERAL(sfx, dim, factor) \
constexpr quantity<dim, double> operator"" _##sfx(unsigned long long x) { \
return quantity<dim, double>(detail::magnitude_tag, factor * x); \
} \
constexpr quantity<dim, double> operator"" _##sfx(long double x) { \
return quantity<dim, double>(detail::magnitude_tag, factor * x); \
}
#define QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, fact) \
QUANTITY_DEFINE_SCALING_LITERAL(Y##pfx, dim, fact* yotta) \
QUANTITY_DEFINE_SCALING_LITERAL(Z##pfx, dim, fact* zetta) \
QUANTITY_DEFINE_SCALING_LITERAL(E##pfx, dim, fact* exa) \
QUANTITY_DEFINE_SCALING_LITERAL(P##pfx, dim, fact* peta) \
QUANTITY_DEFINE_SCALING_LITERAL(T##pfx, dim, fact* tera) \
QUANTITY_DEFINE_SCALING_LITERAL(G##pfx, dim, fact* giga) \
QUANTITY_DEFINE_SCALING_LITERAL(M##pfx, dim, fact* mega) \
QUANTITY_DEFINE_SCALING_LITERAL(k##pfx, dim, fact* kilo) \
QUANTITY_DEFINE_SCALING_LITERAL(h##pfx, dim, fact* hecto) \
QUANTITY_DEFINE_SCALING_LITERAL(da##pfx, dim, fact* deka) \
QUANTITY_DEFINE_SCALING_LITERAL(pfx, dim, fact * 1) \
QUANTITY_DEFINE_SCALING_LITERAL(d##pfx, dim, fact* deci) \
QUANTITY_DEFINE_SCALING_LITERAL(c##pfx, dim, fact* centi) \
QUANTITY_DEFINE_SCALING_LITERAL(m##pfx, dim, fact* milli) \
QUANTITY_DEFINE_SCALING_LITERAL(u##pfx, dim, fact* micro) \
QUANTITY_DEFINE_SCALING_LITERAL(n##pfx, dim, fact* nano) \
QUANTITY_DEFINE_SCALING_LITERAL(p##pfx, dim, fact* pico) \
QUANTITY_DEFINE_SCALING_LITERAL(f##pfx, dim, fact* femto) \
QUANTITY_DEFINE_SCALING_LITERAL(a##pfx, dim, fact* atto) \
QUANTITY_DEFINE_SCALING_LITERAL(z##pfx, dim, fact* zepto) \
QUANTITY_DEFINE_SCALING_LITERAL(y##pfx, dim, fact* yocto)
#define QUANTITY_DEFINE_LITERALS(pfx, dim) QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, 1)
/// literals
namespace literals {
QUANTITY_DEFINE_SCALING_LITERALS(g, mass_d, 1e-3)
QUANTITY_DEFINE_LITERALS(m, length_d)
QUANTITY_DEFINE_LITERALS(s, time_interval_d)
QUANTITY_DEFINE_LITERALS(A, electric_current_d)
QUANTITY_DEFINE_LITERALS(K, thermodynamic_temperature_d)
QUANTITY_DEFINE_LITERALS(mol, amount_of_substance_d)
QUANTITY_DEFINE_LITERALS(cd, luminous_intensity_d)
} // namespace literals
} // namespace units
} // namespace phys
#endif // PHYS_UNITS_QUANTITY_HPP_INCLUDED
/*
* end of file
*/