More refactoring

- unknown_unit and unknown_dimension added
- the support for remaining SI units added
This commit is contained in:
Mateusz Pusz
2019-12-07 16:30:40 +01:00
parent 33f14f39f3
commit 22eda11bea
40 changed files with 1094 additions and 953 deletions

View File

@ -229,6 +229,9 @@ using make_dimension = dim_consolidate<type_list_sort<typename extract<Es...>::t
* base and derived dimensions. This is called a "recipe" of the dimension and among others is used to print
* unnamed coherent units of this dimension.
*
* Coherent unit is a unit that, for a given system of quantities and for a chosen set of base units, is a product
* of powers of base units with no other proportionality factor than one.
*
* The implementation is responsible for unpacking all of the dimensions into a list containing only base dimensions
* and their factors and putting them to the other (private) units::derived_dimension class template partial
* specialization.
@ -246,30 +249,6 @@ struct derived_dimension<Child, U, E, ERest...> : downcast_child<Child, typename
using coherent_unit = U;
};
// unknown_unit
struct unknown_unit {};
namespace detail {
template<typename T>
concept PredefinedDimension = Dimension<T> && requires { typename T::coherent_unit; };
template<Dimension D, Ratio R>
auto unit_for_dimension_impl()
{
if constexpr(PredefinedDimension<D>) {
return downcast<scaled_unit<typename D::coherent_unit::reference, R>>{};
}
else {
return scaled_unit<unknown_unit, R>{};
}
}
template<Dimension D, Ratio R>
using unit_for_dimension = decltype(unit_for_dimension_impl<D, R>());
}
// same_dim
template<Dimension D1, Dimension D2>
inline constexpr bool same_dim = false;
@ -280,157 +259,4 @@ inline constexpr bool same_dim<D1, D2> = std::is_same_v<D1, D2>;
template<DerivedDimension D1, DerivedDimension D2>
inline constexpr bool same_dim<D1, D2> = std::is_same_v<typename D1::downcast_base_type, typename D2::downcast_base_type>;
// dim_invert
namespace detail {
template<Dimension D>
struct dim_invert_impl;
template<BaseDimension D>
struct dim_invert_impl<D> {
using type = downcast<derived_dimension<exp<D, -1>>>;
};
template<BaseDimension D>
struct dim_invert_impl<derived_dimension<exp<D, -1>>> {
using type = D;
};
template<typename... Es>
struct dim_invert_impl<derived_dimension<Es...>> {
using type = downcast<derived_dimension<exp_invert<Es>...>>;
};
template<DerivedDimension D>
struct dim_invert_impl<D> : dim_invert_impl<downcast_base_t<D>> {
};
} // namespace detail
template<Dimension D>
using dim_invert = detail::dim_invert_impl<D>::type;
// dimension_multiply
namespace detail {
template<Dimension D>
struct dim_unpack {
using type = D;
};
template<BaseDimension D>
struct dim_unpack<derived_dimension<exp<D, 1>>> {
using type = D;
};
/**
* @brief Merges 2 sorted derived dimensions into one units::derived_dimension
*
* A result of a dimensional calculation may result with many exponents of the same base dimension orginated
* from different parts of the equation. As the exponents lists of both operands it is enough to merge them
* into one list and consolidate duplicates. Also it is possible that final exponents list will contain only
* one element being a base dimension with exponent 1. In such a case the final dimension should be the base
* dimension itself.
*/
template<Dimension D1, Dimension D2>
using merge_dimension = dim_unpack<typename dim_consolidate<type_list_merge_sorted<D1, D2, exp_less>>::type>::type;
template<Dimension D1, Dimension D2>
struct dimension_multiply_impl;
template<BaseDimension D1, BaseDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast<merge_dimension<derived_dimension<exp<D1, 1>>, derived_dimension<exp<D2, 1>>>>;
};
template<BaseDimension D1, DerivedDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast<merge_dimension<derived_dimension<exp<D1, 1>>, typename D2::downcast_base_type>>;
};
template<DerivedDimension D1, BaseDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = dimension_multiply_impl<D2, D1>::type;
};
template<DerivedDimension D1, DerivedDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast<merge_dimension<typename D1::downcast_base_type, typename D2::downcast_base_type>>;
};
} // namespace detail
template<Dimension D1, Dimension D2>
using dimension_multiply = detail::dimension_multiply_impl<D1, D2>::type;
template<Dimension D1, Dimension D2>
using dimension_divide = detail::dimension_multiply_impl<D1, dim_invert<D2>>::type;
// dimension_sqrt
namespace detail {
template<Dimension D>
struct dimension_sqrt_impl;
template<BaseDimension D>
struct dimension_sqrt_impl<D> {
using type = derived_dimension<exp<D, 1, 2>>;
};
template<BaseDimension D>
struct dimension_sqrt_impl<derived_dimension<exp<D, 2>>> {
using type = D;
};
template<DerivedDimension D>
struct dimension_sqrt_impl<D> {
using type = dimension_sqrt_impl<typename D::downcast_base_type>;
};
template<typename... Es>
struct dimension_sqrt_impl<derived_dimension<Es...>> {
using type = downcast<derived_dimension<exp_multiply<Es, 1, 2>...>>;
};
} // namespace detail
template<Dimension D>
using dimension_sqrt = detail::dimension_sqrt_impl<typename D::downcast_base_type>::type;
// dimension_pow
namespace detail {
template<Dimension D, std::size_t N>
struct dimension_pow_impl;
template<BaseDimension D, std::size_t N>
struct dimension_pow_impl<D, N> {
using type = downcast<derived_dimension<exp<D, N>>>;
};
template<BaseDimension D>
struct dimension_pow_impl<D, 1> {
using type = D;
};
template<BaseDimension D, std::size_t N>
struct dimension_pow_impl<derived_dimension<exp<D, 1, N>>, N> {
using type = D;
};
template<DerivedDimension D, std::size_t N>
struct dimension_pow_impl<D, N> {
using type = dimension_pow_impl<downcast_base<D>, N>;
};
template<typename... Es, std::size_t N>
struct dimension_pow_impl<derived_dimension<Es...>, N> {
using type = downcast<derived_dimension<exp_multiply<Es, N, 1>...>>;
};
} // namespace detail
template<Dimension D, std::size_t N>
using dimension_pow = detail::dimension_pow_impl<D, N>::type;
} // namespace units

View File

@ -0,0 +1,215 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/derived_dimension.h>
#include <units/unit.h>
namespace units {
/**
* @brief Unknown dimension
*
* Sometimes a temporary partial result of a complex calculation may not result in a predefined
* dimension. In such a case an `unknown_dimension` is created with a coherent unit of `unknown_unit`
* and ratio<1>.
*
* @tparam Es zero or more exponents of a derived dimension
*/
template<Exponent... Es>
struct unknown_dimension : derived_dimension<unknown_dimension<Es...>, scaled_unit<unknown_unit, ratio<1>>, Es...> {
using coherent_unit = scaled_unit<unknown_unit, ratio<1>>;
};
namespace detail {
template<Dimension D>
struct downcast_dimension_impl {
using type = D;
};
// downcast did not find user predefined type
template<typename... Es>
struct downcast_dimension_impl<derived_dimension<Es...>> {
using type = unknown_dimension<Es...>;
};
} // namespace detail
template<Dimension D>
using downcast_dimension = detail::downcast_dimension_impl<downcast<D>>::type;
// dim_invert
namespace detail {
template<Dimension D>
struct dim_invert_impl;
template<BaseDimension D>
struct dim_invert_impl<D> {
using type = downcast_dimension<derived_dimension<exp<D, -1>>>;
};
template<BaseDimension D>
struct dim_invert_impl<derived_dimension<exp<D, -1>>> {
using type = D;
};
template<typename... Es>
struct dim_invert_impl<derived_dimension<Es...>> {
using type = downcast_dimension<derived_dimension<exp_invert<Es>...>>;
};
template<DerivedDimension D>
struct dim_invert_impl<D> : dim_invert_impl<downcast_base_t<D>> {
};
} // namespace detail
template<Dimension D>
using dim_invert = detail::dim_invert_impl<D>::type;
// dimension_multiply
namespace detail {
template<Dimension D>
struct dim_unpack {
using type = D;
};
template<BaseDimension D>
struct dim_unpack<derived_dimension<exp<D, 1>>> {
using type = D;
};
/**
* @brief Merges 2 sorted derived dimensions into one units::derived_dimension
*
* A result of a dimensional calculation may result with many exponents of the same base dimension orginated
* from different parts of the equation. As the exponents lists of both operands it is enough to merge them
* into one list and consolidate duplicates. Also it is possible that final exponents list will contain only
* one element being a base dimension with exponent 1. In such a case the final dimension should be the base
* dimension itself.
*/
template<Dimension D1, Dimension D2>
using merge_dimension = dim_unpack<typename dim_consolidate<type_list_merge_sorted<D1, D2, exp_less>>::type>::type;
template<Dimension D1, Dimension D2>
struct dimension_multiply_impl;
template<BaseDimension D1, BaseDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast_dimension<merge_dimension<derived_dimension<exp<D1, 1>>, derived_dimension<exp<D2, 1>>>>;
};
template<BaseDimension D1, DerivedDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast_dimension<merge_dimension<derived_dimension<exp<D1, 1>>, typename D2::downcast_base_type>>;
};
template<DerivedDimension D1, BaseDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = dimension_multiply_impl<D2, D1>::type;
};
template<DerivedDimension D1, DerivedDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = downcast_dimension<merge_dimension<typename D1::downcast_base_type, typename D2::downcast_base_type>>;
};
} // namespace detail
template<Dimension D1, Dimension D2>
using dimension_multiply = detail::dimension_multiply_impl<D1, D2>::type;
template<Dimension D1, Dimension D2>
using dimension_divide = detail::dimension_multiply_impl<D1, dim_invert<D2>>::type;
// dimension_sqrt
namespace detail {
template<Dimension D>
struct dimension_sqrt_impl;
template<BaseDimension D>
struct dimension_sqrt_impl<D> {
using type = derived_dimension<exp<D, 1, 2>>;
};
template<BaseDimension D>
struct dimension_sqrt_impl<derived_dimension<exp<D, 2>>> {
using type = D;
};
template<DerivedDimension D>
struct dimension_sqrt_impl<D> {
using type = dimension_sqrt_impl<typename D::downcast_base_type>;
};
template<typename... Es>
struct dimension_sqrt_impl<derived_dimension<Es...>> {
using type = downcast_dimension<derived_dimension<exp_multiply<Es, 1, 2>...>>;
};
} // namespace detail
template<Dimension D>
using dimension_sqrt = detail::dimension_sqrt_impl<typename D::downcast_base_type>::type;
// dimension_pow
namespace detail {
template<Dimension D, std::size_t N>
struct dimension_pow_impl;
template<BaseDimension D, std::size_t N>
struct dimension_pow_impl<D, N> {
using type = downcast_dimension<derived_dimension<exp<D, N>>>;
};
template<BaseDimension D>
struct dimension_pow_impl<D, 1> {
using type = D;
};
template<BaseDimension D, std::size_t N>
struct dimension_pow_impl<derived_dimension<exp<D, 1, N>>, N> {
using type = D;
};
template<DerivedDimension D, std::size_t N>
struct dimension_pow_impl<D, N> {
using type = dimension_pow_impl<downcast_base<D>, N>;
};
template<typename... Es, std::size_t N>
struct dimension_pow_impl<derived_dimension<Es...>, N> {
using type = downcast_dimension<derived_dimension<exp_multiply<Es, N, 1>...>>;
};
} // namespace detail
template<Dimension D, std::size_t N>
using dimension_pow = detail::dimension_pow_impl<D, N>::type;
} // namespace units

View File

@ -1,46 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/electric_charge.h>
#include <units/dimensions/voltage.h>
namespace units {
struct capacitance : derived_dimension<capacitance, exp<electric_charge, 1>, exp<voltage, -1>> {};
template<typename T>
concept Capacitance = QuantityOf<T, capacitance>;
struct farad : named_coherent_derived_unit<farad, capacitance, "F", si_prefix> {};
inline namespace literals {
// F
constexpr auto operator""F(unsigned long long l) { return quantity<farad, std::int64_t>(l); }
constexpr auto operator""_F(long double l) { return quantity<farad, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,67 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/si_prefixes.h>
#include <units/dimensions/force.h>
#include <units/dimensions/pressure.h>
namespace units {
struct energy : derived_dimension<energy, exp<force, 1>, exp<length, 1>> {};
template<typename T>
concept Energy = QuantityOf<T, energy>;
struct joule : named_coherent_derived_unit<joule, energy, "J", si_prefix> {};
struct millijoule : prefixed_derived_unit<millijoule, milli, joule> {};
struct kilojoule : prefixed_derived_unit<kilojoule, kilo, joule> {};
struct megajoule : prefixed_derived_unit<megajoule, mega, joule> {};
struct gigajoule : prefixed_derived_unit<gigajoule, giga, joule> {};
inline namespace literals {
// J
constexpr auto operator""_J(unsigned long long l) { return quantity<joule, std::int64_t>(l); }
constexpr auto operator""_J(long double l) { return quantity<joule, long double>(l); }
// mJ
constexpr auto operator""mJ(unsigned long long l) { return quantity<millijoule, std::int64_t>(l); }
constexpr auto operator""mJ(long double l) { return quantity<millijoule, long double>(l); }
// kJ
constexpr auto operator""kJ(unsigned long long l) { return quantity<kilojoule, std::int64_t>(l); }
constexpr auto operator""kJ(long double l) { return quantity<kilojoule, long double>(l); }
// MJ
constexpr auto operator""MJ(unsigned long long l) { return quantity<megajoule, std::int64_t>(l); }
constexpr auto operator""MJ(long double l) { return quantity<megajoule, long double>(l); }
// GJ
constexpr auto operator""GJ(unsigned long long l) { return quantity<gigajoule, std::int64_t>(l); }
constexpr auto operator""GJ(long double l) { return quantity<gigajoule, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,46 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/mass.h>
#include <units/dimensions/acceleration.h>
namespace units {
struct force : derived_dimension<force, exp<mass, 1>, exp<acceleration, 1>> {};
template<typename T>
concept Force = QuantityOf<T, force>;
struct newton : named_coherent_derived_unit<newton, force, "N", si_prefix> {};
inline namespace literals {
// N
constexpr auto operator""N(unsigned long long l) { return quantity<newton, std::int64_t>(l); }
constexpr auto operator""N(long double l) { return quantity<newton, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,50 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/quantity.h>
namespace units {
struct mass : derived_dimension<mass, exp<base_dim_mass, 1>> {};
template<typename T>
concept Mass = QuantityOf<T, mass>;
struct gram : named_scaled_derived_unit<gram, mass, "g", ratio<1, 1000>, si_prefix> {};
struct kilogram : prefixed_derived_unit<kilogram, kilo, gram> {};
inline namespace literals {
// g
constexpr auto operator""g(unsigned long long l) { return quantity<gram, std::int64_t>(l); }
constexpr auto operator""g(long double l) { return quantity<gram, long double>(l); }
// kg
constexpr auto operator""kg(unsigned long long l) { return quantity<kilogram, std::int64_t>(l); }
constexpr auto operator""kg(long double l) { return quantity<kilogram, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,124 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/si_prefixes.h>
namespace units {
// base dimension
template<basic_fixed_string Name>
struct base_dimension {
static constexpr auto name = Name;
};
template<typename T>
concept BaseDimension = true;
// base dimension
template<basic_fixed_string Symbol, BaseDimension Dim, PrefixType PT, Ratio R = ratio<1>>
struct base_unit {
static constexpr auto symbol = Symbol;
using dimension = Dim;
using prefix_type = PT;
using ratio = R;
};
template<typename T>
concept BaseUnit = true;
template<typename T, typename Dim>
concept BaseUnitOf = BaseUnit<T> && BaseDimension<Dim> && std::same_as<typename T::dimension, Dim>;
namespace physical {
// base dimensions
struct base_dim_length : base_dimension<"length"> {};
struct base_dim_mass : base_dimension<"mass"> {};
struct base_dim_time : base_dimension<"time"> {};
struct base_dim_current : base_dimension<"current"> {};
struct base_dim_temperature : base_dimension<"temperature"> {};
struct base_dim_substance : base_dimension<"substance"> {};
struct base_dim_luminous_intensity : base_dimension<"luminous intensity"> {};
// dimensions
template<UnitOf<base_dim_length> L>
struct length : derived_dimension<length, exp<L, 1>> {};
template<UnitOf<base_dim_mass> M>
struct mass : derived_dimension<mass, exp<M, 1>> {};
template<UnitOf<base_dim_time> T>
struct time : derived_dimension<time, exp<T, 1>> {};
template<UnitOf<base_dim_length> L, UnitOf<base_dim_time> T>
struct velocity : derived_dimension<velocity, exp<L, 1>, exp<T, -1>> {};
template<UnitOf<base_dim_length> L, UnitOf<base_dim_time> T>
struct acceleration : derived_dimension<acceleration, exp<L, 1>, exp<T, -2>> {};
template<UnitOf<base_dim_mass> M, UnitOf<acceleration> A>
struct force : derived_dimension<force, exp<M, 1>, exp<A, 1>> {};
} // physical
// SI
namespace si {
struct si_prefix;
// length
struct metre : base_unit<"m", base_dim_length, si_prefix> {};
struct length : physical::length<metre> {};
// mass
struct kilogram : base_unit<"kg", base_dim_mass, si_prefix> {};
struct mass : physical::mass<kilogram> {};
// time
struct second : base_unit<"s", base_dim_time, si_prefix> {};
struct time : physical::time<second> {};
struct nanosecond : prefixed_derived_unit<nanosecond, nano, second> {};
struct microsecond : prefixed_derived_unit<microsecond, micro, second> {};
struct millisecond : prefixed_derived_unit<millisecond, milli, second> {};
struct minute : named_derived_unit<minute, time, "min", ratio<60>> {};
struct hour : named_derived_unit<hour, time, "h", ratio<3600>> {};
// velocity
struct velocity : physical::velocity<metre, second>;
// acceleration
struct acceleration : physical::acceleration<metre, second>;
// acceleration
struct acceleration : physical::acceleration<metre, second>;
}
} // namespace units

View File

@ -1,66 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/si_prefixes.h>
#include <units/dimensions/energy.h>
namespace units {
struct power : derived_dimension<power, exp<energy, 1>, exp<time, -1>> {};
template<typename T>
concept Power = QuantityOf<T, power>;
struct watt : named_coherent_derived_unit<watt, power, "W", si_prefix> {};
struct milliwatt : prefixed_derived_unit<milliwatt, milli, watt> {};
struct kilowatt : prefixed_derived_unit<kilowatt, kilo, watt> {};
struct megawatt : prefixed_derived_unit<megawatt, mega, watt> {};
struct gigawatt : prefixed_derived_unit<gigawatt, giga, watt> {};
inline namespace literals {
// W
constexpr auto operator""W(unsigned long long l) { return quantity<watt, std::int64_t>(l); }
constexpr auto operator""_W(long double l) { return quantity<watt, long double>(l); }
// mW
constexpr auto operator""mW(unsigned long long l) { return quantity<milliwatt, std::int64_t>(l); }
constexpr auto operator""mW(long double l) { return quantity<milliwatt, long double>(l); }
// kW
constexpr auto operator""kW(unsigned long long l) { return quantity<kilowatt, std::int64_t>(l); }
constexpr auto operator""kW(long double l) { return quantity<kilowatt, long double>(l); }
// MW
constexpr auto operator""MW(unsigned long long l) { return quantity<megawatt, std::int64_t>(l); }
constexpr auto operator""MW(long double l) { return quantity<megawatt, long double>(l); }
// GW
constexpr auto operator""GW(unsigned long long l) { return quantity<gigawatt, std::int64_t>(l); }
constexpr auto operator""GW(long double l) { return quantity<gigawatt, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,46 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/force.h>
#include <units/dimensions/area.h>
namespace units {
struct pressure : derived_dimension<pressure, exp<force, 1>, exp<area, -1>> {};
template<typename T>
concept Pressure = QuantityOf<T, pressure>;
struct pascal : named_coherent_derived_unit<pascal, pressure, "Pa", si_prefix> {};
inline namespace literals {
// Pa
constexpr auto operator""Pa(unsigned long long l) { return quantity<pascal, std::int64_t>(l); }
constexpr auto operator""Pa(long double l) { return quantity<pascal, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,45 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/force.h>
namespace units {
struct surface_tension : derived_dimension<surface_tension, exp<force, 1>, exp<length, -1>> {};
template<typename T>
concept SurfaceTension = QuantityOf<T, surface_tension>;
struct newton_per_metre : coherent_derived_unit<newton_per_metre, surface_tension> {};
inline namespace literals {
// Nm
constexpr auto operator""Npm(unsigned long long l) { return quantity<newton_per_metre, std::int64_t>(l); }
constexpr auto operator""Npm(long double l) { return quantity<newton_per_metre, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,48 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/power.h>
#include <units/dimensions/current.h>
#include <units/dimensions/energy.h>
#include <units/dimensions/electric_charge.h>
namespace units {
struct voltage : derived_dimension<voltage, exp<power, 1>, exp<current, -1>> {};
template<typename T>
concept Voltage = QuantityOf<T, voltage>;
struct volt : named_coherent_derived_unit<volt, voltage, "V", si_prefix> {};
inline namespace literals {
// V
constexpr auto operator""V(unsigned long long l) { return quantity<volt, std::int64_t>(l); }
constexpr auto operator""V(long double l) { return quantity<volt, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -1,64 +0,0 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/dimensions/length.h>
namespace units {
struct volume : derived_dimension<volume, exp<length, 3>> {};
template<typename T>
concept Volume = QuantityOf<T, volume>;
struct cubic_metre : coherent_derived_unit<cubic_metre, volume> {};
struct cubic_millimetre : deduced_derived_unit<cubic_millimetre, volume, millimetre> {};
struct cubic_centimetre : deduced_derived_unit<cubic_centimetre, volume, centimetre> {};
struct cubic_kilometre : deduced_derived_unit<cubic_kilometre, volume, kilometre> {};
struct cubic_foot : deduced_derived_unit<cubic_foot, volume, foot> {};
inline namespace literals {
// cub_mm
constexpr auto operator""cub_mm(unsigned long long l) { return quantity<cubic_millimetre, std::int64_t>(l); }
constexpr auto operator""cub_mm(long double l) { return quantity<cubic_millimetre, long double>(l); }
// cub_cm
constexpr auto operator""cub_cm(unsigned long long l) { return quantity<cubic_centimetre, std::int64_t>(l); }
constexpr auto operator""cub_cm(long double l) { return quantity<cubic_centimetre, long double>(l); }
// cub_m
constexpr auto operator""cub_m(unsigned long long l) { return quantity<cubic_metre, std::int64_t>(l); }
constexpr auto operator""cub_m(long double l) { return quantity<cubic_metre, long double>(l); }
// cub_km
constexpr auto operator""cub_km(unsigned long long l) { return quantity<cubic_kilometre, std::int64_t>(l); }
constexpr auto operator""cub_km(long double l) { return quantity<cubic_kilometre, long double>(l); }
// cub_ft
constexpr auto operator""cub_ft(unsigned long long l) { return quantity<cubic_foot, std::int64_t>(l); }
constexpr auto operator""cub_ft(long double l) { return quantity<cubic_foot, long double>(l); }
} // namespace literals
} // namespace units

View File

@ -39,7 +39,7 @@ namespace units {
{
using dim = dimension_pow<D, N>;
using ratio = ratio_pow<typename U::ratio, N>;
using unit = detail::unit_for_dimension<dim, ratio>;
using unit = downcast_unit<dim, ratio>;
return quantity<dim, unit, Rep>(static_cast<Rep>(std::pow(q.count(), N)));
}
@ -48,7 +48,7 @@ namespace units {
{
using dim = dimension_sqrt<D>;
using ratio = ratio_sqrt<typename U::ratio>;
using unit = detail::unit_for_dimension<dim, ratio>;
using unit = downcast_unit<dim, ratio>;
return quantity<dim, unit, Rep>(static_cast<Rep>(std::sqrt(q.count())));
}

View File

@ -104,6 +104,13 @@ struct dim_area : derived_dimension<Child, U, exp<L, 2>> {};
template<typename T>
concept Area = QuantityOf<T, dim_area>;
// volume
template<typename Child, Unit U, DimensionOf<dim_length> L>
struct dim_volume : derived_dimension<Child, U, exp<L, 3>> {};
template<typename T>
concept Volume = QuantityOf<T, dim_volume>;
// velocity
template<typename Child, Unit U, DimensionOf<dim_length> L, DimensionOf<dim_time> T>
struct dim_velocity : derived_dimension<Child, U, exp<L, 1>, exp<T, -1>> {};
@ -139,6 +146,34 @@ struct dim_power : derived_dimension<Child, U, exp<E, 1>, exp<T, -1>> {};
template<typename T>
concept Power = QuantityOf<T, dim_power>;
// voltage
template<typename Child, Unit U, DimensionOf<dim_power> P, DimensionOf<dim_current> C>
struct dim_voltage : derived_dimension<Child, U, exp<P, 1>, exp<C, -1>> {};
template<typename T>
concept Voltage = QuantityOf<T, dim_voltage>;
// electric charge
template<typename Child, Unit U, DimensionOf<dim_time> T, DimensionOf<dim_current> C>
struct dim_electric_charge : derived_dimension<Child, U, exp<T, 1>, exp<C, 1>> {};
template<typename T>
concept ElectricCharge = QuantityOf<T, dim_electric_charge>;
// capacitance
template<typename Child, Unit U, DimensionOf<dim_electric_charge> C, DimensionOf<dim_voltage> V>
struct dim_capacitance : derived_dimension<Child, U, exp<C, 1>, exp<V, -1>> {};
template<typename T>
concept Capacitance = QuantityOf<T, dim_capacitance>;
// surface tension
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_length> L>
struct dim_surface_tension : derived_dimension<Child, U, exp<F, 1>, exp<L, -1>> {};
template<typename T>
concept SurfaceTension = QuantityOf<T, dim_surface_tension>;
// pressure
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_area> A>
struct dim_pressure : derived_dimension<Child, U, exp<F, 1>, exp<A, -1>> {};

View File

@ -24,6 +24,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/velocity.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -24,6 +24,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/length.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -0,0 +1,48 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/electric_charge.h>
#include <units/physical/si/voltage.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {
struct farad : named_unit<farad, "F", prefix> {};
struct dim_capacitance : physical::dim_capacitance<dim_capacitance, farad, dim_electric_charge, dim_voltage> {};
template<Unit U, Scalar Rep = double>
using capacitance = quantity<dim_capacitance, U, Rep>;
inline namespace literals {
// F
constexpr auto operator""F(unsigned long long l) { return capacitance<farad, std::int64_t>(l); }
constexpr auto operator""_F(long double l) { return capacitance<farad, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -22,24 +22,25 @@
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units {
namespace units::si {
struct current : derived_dimension<current, exp<base_dim_current, 1>> {};
struct ampere : named_unit<ampere, "m", prefix> {};
template<typename T>
concept Current = QuantityOf<T, current>;
struct dim_current : physical::dim_current<ampere> {};
struct ampere : named_coherent_derived_unit<ampere, current, "A", si_prefix> {};
template<Unit U, Scalar Rep = double>
using current = quantity<dim_current, U, Rep>;
inline namespace literals {
inline namespace literals {
// A
constexpr auto operator""A(unsigned long long l) { return quantity<ampere, std::int64_t>(l); }
constexpr auto operator""A(long double l) { return quantity<ampere, long double>(l); }
// A
constexpr auto operator""A(unsigned long long l) { return current<ampere, std::int64_t>(l); }
constexpr auto operator""A(long double l) { return current<ampere, long double>(l); }
}
} // namespace literals
} // namespace units
} // namespace units::si

View File

@ -0,0 +1,47 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/current.h>
#include <units/physical/si/time.h>
#include <units/quantity.h>
namespace units::si {
struct coulomb : named_unit<coulomb, "C", prefix> {};
struct dim_electric_charge : physical::dim_electric_charge<dim_electric_charge, coulomb, dim_time, dim_current> {};
template<Unit U, Scalar Rep = double>
using electric_charge = quantity<dim_electric_charge, U, Rep>;
inline namespace literals {
// C
constexpr auto operator""C(unsigned long long l) { return electric_charge<coulomb, std::int64_t>(l); }
constexpr auto operator""C(long double l) { return electric_charge<coulomb, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -0,0 +1,67 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/force.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {
struct joule : named_unit<joule, "J", prefix> {};
struct millijoule : prefixed_unit<millijoule, milli, joule> {};
struct kilojoule : prefixed_unit<kilojoule, kilo, joule> {};
struct megajoule : prefixed_unit<megajoule, mega, joule> {};
struct gigajoule : prefixed_unit<gigajoule, giga, joule> {};
struct dim_energy : physical::dim_energy<dim_energy, joule, dim_force, dim_length> {};
template<Unit U, Scalar Rep = double>
using energy = quantity<dim_energy, U, Rep>;
inline namespace literals {
// J
constexpr auto operator""_J(unsigned long long l) { return energy<joule, std::int64_t>(l); }
constexpr auto operator""_J(long double l) { return energy<joule, long double>(l); }
// mJ
constexpr auto operator""mJ(unsigned long long l) { return energy<millijoule, std::int64_t>(l); }
constexpr auto operator""mJ(long double l) { return energy<millijoule, long double>(l); }
// kJ
constexpr auto operator""kJ(unsigned long long l) { return energy<kilojoule, std::int64_t>(l); }
constexpr auto operator""kJ(long double l) { return energy<kilojoule, long double>(l); }
// MJ
constexpr auto operator""MJ(unsigned long long l) { return energy<megajoule, std::int64_t>(l); }
constexpr auto operator""MJ(long double l) { return energy<megajoule, long double>(l); }
// GJ
constexpr auto operator""GJ(unsigned long long l) { return energy<gigajoule, std::int64_t>(l); }
constexpr auto operator""GJ(long double l) { return energy<gigajoule, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -0,0 +1,48 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/acceleration.h>
#include <units/physical/si/mass.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {
struct newton : named_unit<newton, "N", prefix> {};
struct dim_force : physical::dim_force<dim_force, newton, dim_mass, dim_acceleration> {};
template<Unit U, Scalar Rep = double>
using force = quantity<dim_force, U, Rep>;
inline namespace literals {
// N
constexpr auto operator""N(unsigned long long l) { return force<newton, std::int64_t>(l); }
constexpr auto operator""N(long double l) { return force<newton, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -24,6 +24,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/time.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -24,6 +24,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -22,24 +22,25 @@
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units {
namespace units::si {
struct luminous_intensity : derived_dimension<luminous_intensity, exp<base_dim_luminous_intensity, 1>> {};
struct candela : named_unit<candela, "cd", prefix> {};
template<typename T>
concept LuminousIntensity = QuantityOf<T, luminous_intensity>;
struct dim_luminous_intensity : physical::dim_luminous_intensity<candela> {};
struct candela : named_coherent_derived_unit<candela, luminous_intensity, "cd", si_prefix> {};
template<Unit U, Scalar Rep = double>
using luminous_intensity = quantity<dim_luminous_intensity, U, Rep>;
inline namespace literals {
inline namespace literals {
// cd
constexpr auto operator""cd(unsigned long long l) { return quantity<candela, std::int64_t>(l); }
constexpr auto operator""cd(long double l) { return quantity<candela, long double>(l); }
// cd
constexpr auto operator""cd(unsigned long long l) { return luminous_intensity<candela, std::int64_t>(l); }
constexpr auto operator""cd(long double l) { return luminous_intensity<candela, long double>(l); }
} // namespace literals
} // namespace literals
} // namespace units
} // namespace units::si

View File

@ -22,25 +22,29 @@
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/dimensions/time.h>
#include <units/dimensions/current.h>
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
namespace units {
namespace units::si {
struct electric_charge : derived_dimension<electric_charge, exp<time, 1>, exp<current, 1>> {};
struct gram : named_unit<gram, "g", prefix> {};
struct kilogram : prefixed_unit<kilogram, kilo, gram> {};
template<typename T>
concept ElectricCharge = QuantityOf<T, electric_charge>;
struct dim_mass : physical::dim_mass<kilogram> {};
struct coulomb : named_coherent_derived_unit<coulomb, electric_charge, "C", si_prefix> {};
template<Unit U, Scalar Rep = double>
using mass = quantity<dim_mass, U, Rep>;
inline namespace literals {
inline namespace literals {
// C
constexpr auto operator""C(unsigned long long l) { return quantity<coulomb, std::int64_t>(l); }
constexpr auto operator""C(long double l) { return quantity<coulomb, long double>(l); }
// g
constexpr auto operator""g(unsigned long long l) { return mass<gram, std::int64_t>(l); }
constexpr auto operator""g(long double l) { return mass<gram, long double>(l); }
} // namespace literals
// kg
constexpr auto operator""kg(unsigned long long l) { return mass<kilogram, std::int64_t>(l); }
constexpr auto operator""kg(long double l) { return mass<kilogram, long double>(l); }
} // namespace units
} // namespace literals
} // namespace units::si

View File

@ -0,0 +1,67 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/energy.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {
struct watt : named_unit<watt, "W", prefix> {};
struct milliwatt : prefixed_unit<milliwatt, milli, watt> {};
struct kilowatt : prefixed_unit<kilowatt, kilo, watt> {};
struct megawatt : prefixed_unit<megawatt, mega, watt> {};
struct gigawatt : prefixed_unit<gigawatt, giga, watt> {};
struct dim_power : physical::dim_power<dim_power, watt, dim_energy, dim_time> {};
template<Unit U, Scalar Rep = double>
using power = quantity<dim_power, U, Rep>;
inline namespace literals {
// W
constexpr auto operator""W(unsigned long long l) { return power<watt, std::int64_t>(l); }
constexpr auto operator""_W(long double l) { return power<watt, long double>(l); }
// mW
constexpr auto operator""mW(unsigned long long l) { return power<milliwatt, std::int64_t>(l); }
constexpr auto operator""mW(long double l) { return power<milliwatt, long double>(l); }
// kW
constexpr auto operator""kW(unsigned long long l) { return power<kilowatt, std::int64_t>(l); }
constexpr auto operator""kW(long double l) { return power<kilowatt, long double>(l); }
// MW
constexpr auto operator""MW(unsigned long long l) { return power<megawatt, std::int64_t>(l); }
constexpr auto operator""MW(long double l) { return power<megawatt, long double>(l); }
// GW
constexpr auto operator""GW(unsigned long long l) { return power<gigawatt, std::int64_t>(l); }
constexpr auto operator""GW(long double l) { return power<gigawatt, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -0,0 +1,48 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/area.h>
#include <units/physical/si/force.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {
struct pascal : named_unit<pascal, "Pa", prefix> {};
struct dim_pressure : physical::dim_pressure<dim_pressure, pascal, dim_force, dim_area> {};
template<Unit U, Scalar Rep = double>
using pressure = quantity<dim_pressure, U, Rep>;
inline namespace literals {
// Pa
constexpr auto operator""Pa(unsigned long long l) { return pressure<pascal, std::int64_t>(l); }
constexpr auto operator""Pa(long double l) { return pressure<pascal, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -22,24 +22,25 @@
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units {
namespace units::si {
struct substance : derived_dimension<substance, exp<base_dim_substance, 1>> {};
struct mole : named_unit<metre, "mol", prefix> {};
template<typename T>
concept Substance = QuantityOf<T, substance>;
struct dim_substance : physical::dim_substance<mole> {};
struct mole : named_coherent_derived_unit<mole, substance, "mol", si_prefix> {};
template<Unit U, Scalar Rep = double>
using substance = quantity<dim_substance, U, Rep>;
inline namespace literals {
inline namespace literals {
// mol
constexpr auto operator""mol(unsigned long long l) { return quantity<mole, std::int64_t>(l); }
constexpr auto operator""mol(long double l) { return quantity<mole, long double>(l); }
// mol
constexpr auto operator"" mol(unsigned long long l) { return substance<mole, std::int64_t>(l); }
constexpr auto operator"" mol(long double l) { return substance<mole, long double>(l); }
} // namespace literals
} // namespace literals
} // namespace units
} // namespace units::si

View File

@ -0,0 +1,46 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/force.h>
#include <units/quantity.h>
namespace units::si {
struct newton_per_metre : unit<newton_per_metre> {};
struct dim_surface_tension : physical::dim_surface_tension<dim_surface_tension, newton_per_metre, dim_force, dim_length> {};
template<Unit U, Scalar Rep = double>
using surface_tension = quantity<dim_surface_tension, U, Rep>;
inline namespace literals {
// Nm
constexpr auto operator""Npm(unsigned long long l) { return surface_tension<newton_per_metre, std::int64_t>(l); }
constexpr auto operator""Npm(long double l) { return surface_tension<newton_per_metre, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -22,16 +22,24 @@
#pragma once
#include <units/dimension.h>
#include <units/physical/dimensions.h>
#include <units/quantity.h>
namespace units {
namespace units::si {
struct base_dim_length : base_dimension<"length", "m"> {};
struct base_dim_mass : base_dimension<"mass", "kg"> {};
struct base_dim_time : base_dimension<"time", "s"> {};
struct base_dim_current : base_dimension<"current", "A"> {};
struct base_dim_temperature : base_dimension<"temperature", "K"> {};
struct base_dim_substance : base_dimension<"substance", "mol"> {};
struct base_dim_luminous_intensity : base_dimension<"luminous intensity", "cd"> {};
struct kelvin : named_unit<kelvin, "K", no_prefix> {};
} // namespace units
struct dim_temperature : physical::dim_temperature<kelvin> {};
template<Unit U, Scalar Rep = double>
using temperature = quantity<dim_temperature, U, Rep>;
inline namespace literals {
// K
constexpr auto operator""K(unsigned long long l) { return temperature<kelvin, std::int64_t>(l); }
constexpr auto operator""_K(long double l) { return temperature<kelvin, long double>(l); } // TODO: conflicts with gcc GNU extension
} // namespace literals
} // namespace units::si

View File

@ -24,6 +24,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -25,6 +25,7 @@
#include <units/physical/dimensions.h>
#include <units/physical/si/length.h>
#include <units/physical/si/time.h>
#include <units/quantity.h>
namespace units::si {

View File

@ -22,24 +22,27 @@
#pragma once
#include <units/dimensions/si_base_dimensions.h>
#include <units/physical/dimensions.h>
#include <units/physical/si/current.h>
#include <units/physical/si/power.h>
#include <units/physical/si/prefixes.h>
#include <units/quantity.h>
namespace units {
namespace units::si {
struct temperature : derived_dimension<temperature, exp<base_dim_temperature, 1>> {};
struct volt : named_unit<volt, "V", prefix> {};
template<typename T>
concept ThermodynamicTemperature = QuantityOf<T, temperature>;
struct dim_voltage : physical::dim_voltage<dim_voltage, volt, dim_power, dim_current> {};
struct kelvin : named_coherent_derived_unit<kelvin, temperature, "K", no_prefix> {};
template<Unit U, Scalar Rep = double>
using voltage = quantity<dim_voltage, U, Rep>;
inline namespace literals {
inline namespace literals {
// K
constexpr auto operator""K(unsigned long long l) { return quantity<kelvin, std::int64_t>(l); }
constexpr auto operator""_K(long double l) { return quantity<kelvin, long double>(l); } // TODO: conflicts with gcc GNU extension
// V
constexpr auto operator""V(unsigned long long l) { return voltage<volt, std::int64_t>(l); }
constexpr auto operator""V(long double l) { return voltage<volt, long double>(l); }
} // namespace literals
} // namespace literals
} // namespace units
} // namespace units::si

View File

@ -0,0 +1,66 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <units/physical/dimensions.h>
#include <units/physical/si/length.h>
#include <units/quantity.h>
namespace units::si {
struct cubic_metre : unit<cubic_metre> {};
struct dim_volume : physical::dim_volume<dim_volume, cubic_metre, dim_length> {};
struct cubic_millimetre : deduced_unit<cubic_millimetre, dim_volume, millimetre> {};
struct cubic_centimetre : deduced_unit<cubic_centimetre, dim_volume, centimetre> {};
struct cubic_kilometre : deduced_unit<cubic_kilometre, dim_volume, kilometre> {};
struct cubic_foot : deduced_unit<cubic_foot, dim_volume, foot> {};
template<Unit U, Scalar Rep = double>
using volume = quantity<dim_volume, U, Rep>;
inline namespace literals {
// cub_mm
constexpr auto operator""cub_mm(unsigned long long l) { return volume<cubic_millimetre, std::int64_t>(l); }
constexpr auto operator""cub_mm(long double l) { return volume<cubic_millimetre, long double>(l); }
// cub_cm
constexpr auto operator""cub_cm(unsigned long long l) { return volume<cubic_centimetre, std::int64_t>(l); }
constexpr auto operator""cub_cm(long double l) { return volume<cubic_centimetre, long double>(l); }
// cub_m
constexpr auto operator""cub_m(unsigned long long l) { return volume<cubic_metre, std::int64_t>(l); }
constexpr auto operator""cub_m(long double l) { return volume<cubic_metre, long double>(l); }
// cub_km
constexpr auto operator""cub_km(unsigned long long l) { return volume<cubic_kilometre, std::int64_t>(l); }
constexpr auto operator""cub_km(long double l) { return volume<cubic_kilometre, long double>(l); }
// cub_ft
constexpr auto operator""cub_ft(unsigned long long l) { return volume<cubic_foot, std::int64_t>(l); }
constexpr auto operator""cub_ft(long double l) { return volume<cubic_foot, long double>(l); }
} // namespace literals
} // namespace units::si

View File

@ -23,7 +23,7 @@
#pragma once
#include <units/concepts.h>
#include <units/unit.h>
#include <units/dimension_op.h>
#include <limits>
#include <ostream>
@ -73,9 +73,7 @@ struct common_quantity_impl<quantity<D, U, Rep1>, quantity<D, U, Rep2>, Rep> {
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2, typename Rep>
struct common_quantity_impl<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, Rep> {
using type = quantity<
D, downcast<scaled_unit<typename U1::reference, common_ratio<typename U1::ratio, typename U2::ratio>>>,
Rep>;
using type = quantity<D, downcast_unit<D, common_ratio<typename U1::ratio, typename U2::ratio>>, Rep>;
};
} // namespace detail
@ -154,7 +152,7 @@ template<Quantity To, typename D, typename U, typename Rep>
{
using c_ratio = ratio_divide<typename U::ratio, typename To::unit::ratio>;
using c_rep = std::common_type_t<typename To::rep, Rep, intmax_t>;
using ret_unit = downcast<scaled_unit<typename U::reference, typename To::unit::ratio>>;
using ret_unit = downcast_unit<D, typename To::unit::ratio>;
using ret = quantity<D, ret_unit, typename To::rep>;
using cast = detail::quantity_cast_impl<ret, c_ratio, c_rep, c_ratio::num == 1, c_ratio::den == 1>;
return cast::cast(q);
@ -465,8 +463,10 @@ template<typename D1, typename U1, typename Rep1, typename D2, typename U2, type
detail::basic_arithmetic<Rep1, Rep2>
{
using dim = dimension_multiply<D1, D2>;
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
using unit = detail::unit_for_dimension<dim, ratio>;
using ratio1 = ratio_divide<typename U1::ratio, typename D1::coherent_unit::ratio>;
using ratio2 = ratio_divide<typename U2::ratio, typename D2::coherent_unit::ratio>;
using ratio = ratio_multiply<ratio1, ratio2>;
using unit = downcast_unit<dim, ratio>;
using common_rep = decltype(lhs.count() * rhs.count());
using ret = quantity<dim, unit, common_rep>;
return ret(lhs.count() * rhs.count());
@ -480,7 +480,7 @@ template<typename D, Scalar Value, typename U, typename Rep>
using dim = dim_invert<D>;
using ratio = ratio<U::ratio::den, U::ratio::num>;
using unit = detail::unit_for_dimension<dim, ratio>;
using unit = downcast_unit<dim, ratio>;
using common_rep = decltype(v / q.count());
using ret = quantity<dim, unit, common_rep>;
return ret(v / q.count());
@ -518,8 +518,10 @@ template<typename D1, typename U1, typename Rep1, typename D2, typename U2, type
using common_rep = decltype(lhs.count() / rhs.count());
using dim = dimension_divide<D1, D2>;
using ratio = ratio_divide<typename U1::ratio, typename U2::ratio>;
using unit = detail::unit_for_dimension<dim, ratio>;
using ratio1 = ratio_divide<typename U1::ratio, typename D1::coherent_unit::ratio>;
using ratio2 = ratio_divide<typename U2::ratio, typename D2::coherent_unit::ratio>;
using ratio = ratio_divide<ratio1, ratio2>;
using unit = downcast_unit<dim, ratio>;
using ret = quantity<dim, unit, common_rep>;
return ret(lhs.count() / rhs.count());
}

View File

@ -32,86 +32,35 @@
namespace units {
// scaled_unit
/**
* @brief A common point for a hierarchy of units
*
* A unit is an entity defined and adopted by convention, with which any other quantity of
* the same kind can be compared to express the ratio of the second quantity to the first
* one as a number.
*
* All units of the same dimension can be convereted between each other. To allow this all of
* them are expressed as different ratios of the same one proprietary chosen reference unit
* (i.e. all length units are expressed in terms of meter, all mass units are expressed in
* terms of gram, ...)
*
* @tparam U a unit to use as a reference for this dimension
* @tparam R a ratio of a reference unit
*/
template<typename U, UnitRatio R>
struct scaled_unit : downcast_base<scaled_unit<U, R>> {
using reference = U;
using ratio = R;
};
// UnitOf
namespace detail {
template<typename U, typename D>
concept SameReference = std::same_as<typename U::reference, typename D::coherent_unit::reference>;
}
template<typename U, typename D>
concept UnitOf =
Unit<U> &&
Dimension<D> &&
(std::same_as<typename U::reference, unknown_unit> || detail::SameReference<U, D>);
namespace detail {
// same_scaled_units
template<DerivedDimension D, Unit... Us>
inline constexpr bool same_scaled_units = false;
template<typename... Es, Unit... Us>
inline constexpr bool same_scaled_units<derived_dimension<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
// deduced_unit
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
struct ratio_op;
template<typename Result, int UnitExpDen, typename UnitRatio>
struct ratio_op<Result, 0, UnitExpDen, UnitRatio> {
using ratio = Result;
};
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
struct ratio_op {
using calc_ratio =
conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply<Result, UnitRatio>, ratio_divide<Result, UnitRatio>>;
static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen);
using ratio = ratio_op<calc_ratio, value, UnitExpDen, UnitRatio>::ratio;
};
template<DerivedDimension D, Unit... Us>
struct derived_ratio;
template<Unit... Us>
struct derived_ratio<derived_dimension<>, Us...> {
using ratio = ::units::ratio<1>;
};
template<typename E, typename... ERest, Unit U, Unit... URest>
struct derived_ratio<derived_dimension<E, ERest...>, U, URest...> {
using rest_ratio = derived_ratio<derived_dimension<ERest...>, URest...>::ratio;
using ratio = ratio_op<rest_ratio, E::num, E::den, typename U::ratio>::ratio;
};
template<DerivedDimension D, Unit... Us>
using deduced_unit =
scaled_unit<typename D::coherent_unit::reference, typename detail::derived_ratio<typename D::recipe, Us...>::ratio>;
} // namespace detail
template<Dimension D, UnitRatio R>
using downcast_unit = downcast<scaled_unit<typename D::coherent_unit::reference, R>>;
/**
* @brief A starting point for a new hierarchy of units
*
* A unit is an entity defined and adopted by convention, with which any other quantity of
* the same kind can be compared to express the ratio of the second quantity to the first
* one as a number.
*
* Coherent unit is a unit that, for a given system of quantities and for a chosen set of
* base units, is a product of powers of base units with no other proportionality factor
* than one.
*
* This class allows definition of a new unnamed (in most cases coherent) derived unit of
* a specific derived dimension and it should be passed in this dimension's definition.
* Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension
* and it should be passed in this dimension's definition.
*
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
*/
@ -121,6 +70,13 @@ struct unit : downcast_child<Child, scaled_unit<Child, ratio<1>>> {
using prefix_type = no_prefix;
};
/**
* @brief Unknown unit
*
* Used as a reference unit of an unknown dimension.
*/
struct unknown_unit : unit<unknown_unit> {};
/**
* @brief A named unit
*
@ -185,6 +141,59 @@ struct prefixed_unit :
using prefix_type = P::prefix_type;
};
// UnitOf
template<typename U, typename D>
concept UnitOf =
Unit<U> &&
Dimension<D> &&
std::same_as<typename U::reference, typename D::coherent_unit::reference>;
namespace detail {
// same_scaled_units
template<DerivedDimension D, Unit... Us>
inline constexpr bool same_scaled_units = false;
template<typename... Es, Unit... Us>
inline constexpr bool same_scaled_units<derived_dimension<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
// deduced_unit
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
struct ratio_op;
template<typename Result, int UnitExpDen, typename UnitRatio>
struct ratio_op<Result, 0, UnitExpDen, UnitRatio> {
using ratio = Result;
};
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
struct ratio_op {
using calc_ratio =
conditional<(UnitExpNum * UnitExpDen > 0), ratio_multiply<Result, UnitRatio>, ratio_divide<Result, UnitRatio>>;
static constexpr int value = (UnitExpNum * UnitExpDen > 0) ? (UnitExpNum - UnitExpDen) : (UnitExpNum + UnitExpDen);
using ratio = ratio_op<calc_ratio, value, UnitExpDen, UnitRatio>::ratio;
};
template<DerivedDimension D, Unit... Us>
struct derived_ratio;
template<Unit... Us>
struct derived_ratio<derived_dimension<>, Us...> {
using ratio = ::units::ratio<1>;
};
template<typename E, typename... ERest, Unit U, Unit... URest>
struct derived_ratio<derived_dimension<E, ERest...>, U, URest...> {
using rest_ratio = derived_ratio<derived_dimension<ERest...>, URest...>::ratio;
using ratio = ratio_op<rest_ratio, E::num, E::den, typename U::ratio>::ratio;
};
template<DerivedDimension D, Unit... Us>
using deduced_unit =
scaled_unit<typename D::coherent_unit::reference, typename detail::derived_ratio<typename D::recipe, Us...>::ratio>;
} // namespace detail
/**
* @brief A unit with a deduced ratio and symbol
*
@ -202,7 +211,7 @@ template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
(U::is_named && (URest::is_named && ... && true))
struct deduced_unit : downcast_child<Child, detail::deduced_unit<Dim, U, URest...>> {
static constexpr bool is_named = false;
static constexpr auto symbol = basic_fixed_string{""}; // detail::deduced_symbol_text<Dim, U, Us...>();
static constexpr auto symbol = basic_fixed_string{""}; // detail::deduced_symbol_text<Dim, U, Us...>(); // TODO implement this
using prefix_type = no_prefix;
};

View File

@ -23,13 +23,12 @@
add_library(unit_tests_static
# cgs_test.cpp
# custom_unit_test.cpp
dimension_test.cpp
dimension_op_test.cpp
# fixed_string_test.cpp
math_test.cpp
# new_design.cpp
quantity_test.cpp
ratio_test.cpp
# si_test.cpp
si_test.cpp
type_list_test.cpp
unit_test.cpp
)

View File

@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "units/derived_dimension.h"
#include "units/dimension_op.h"
#include "units/unit.h"
#include <utility>
@ -63,9 +63,9 @@ static_assert(std::is_same_v<extract<exp<dim2, -2>, exp<d0, 1>, exp<d1, 2>>,
// dim_invert
static_assert(std::is_same_v<dim_invert<derived_dimension<exp<d0, -1>>>, d0>);
static_assert(std::is_same_v<dim_invert<derived_dimension<exp<d0, -2>>>, derived_dimension<exp<d0, 2>>>);
static_assert(std::is_same_v<dim_invert<derived_dimension<exp<d0, -2>>>, unknown_dimension<exp<d0, 2>>>);
static_assert(
std::is_same_v<dim_invert<derived_dimension<exp<d0, 2>, exp<d1, -1>>>, derived_dimension<exp<d0, -2>, exp<d1, 1>>>);
std::is_same_v<dim_invert<derived_dimension<exp<d0, 2>, exp<d1, -1>>>, unknown_dimension<exp<d0, -2>, exp<d1, 1>>>);
// make_dimension
@ -94,33 +94,33 @@ static_assert(std::is_same_v<make_dimension<exp<d0, 1>, exp<d1, 1>, exp<d0, -1>,
// dimension_multiply
static_assert(std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 1>>, derived_dimension<exp<d1, 1>>>,
derived_dimension<exp<d0, 1>, exp<d1, 1>>>);
unknown_dimension<exp<d0, 1>, exp<d1, 1>>>);
static_assert(
std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 1>>, d1>, derived_dimension<exp<d0, 1>, exp<d1, 1>>>);
std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 1>>, d1>, unknown_dimension<exp<d0, 1>, exp<d1, 1>>>);
static_assert(
std::is_same_v<dimension_multiply<d0, derived_dimension<exp<d1, 1>>>, derived_dimension<exp<d0, 1>, exp<d1, 1>>>);
static_assert(std::is_same_v<dimension_multiply<d0, d1>, derived_dimension<exp<d0, 1>, exp<d1, 1>>>);
std::is_same_v<dimension_multiply<d0, derived_dimension<exp<d1, 1>>>, unknown_dimension<exp<d0, 1>, exp<d1, 1>>>);
static_assert(std::is_same_v<dimension_multiply<d0, d1>, unknown_dimension<exp<d0, 1>, exp<d1, 1>>>);
static_assert(std::is_same_v<
dimension_multiply<derived_dimension<exp<d0, 1>, exp<d1, 1>, exp<d2, 1>>, derived_dimension<exp<d3, 1>>>,
derived_dimension<exp<d0, 1>, exp<d1, 1>, exp<d2, 1>, exp<d3, 1>>>);
unknown_dimension<exp<d0, 1>, exp<d1, 1>, exp<d2, 1>, exp<d3, 1>>>);
static_assert(std::is_same_v<
dimension_multiply<derived_dimension<exp<d0, 1>, exp<d1, 1>, exp<d2, 1>>, derived_dimension<exp<d1, 1>>>,
derived_dimension<exp<d0, 1>, exp<d1, 2>, exp<d2, 1>>>);
unknown_dimension<exp<d0, 1>, exp<d1, 2>, exp<d2, 1>>>);
static_assert(std::is_same_v<
dimension_multiply<derived_dimension<exp<d0, 1>, exp<d1, 1>, exp<d2, 1>>, derived_dimension<exp<d1, -1>>>,
derived_dimension<exp<d0, 1>, exp<d2, 1>>>);
unknown_dimension<exp<d0, 1>, exp<d2, 1>>>);
static_assert(std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 1>>, derived_dimension<exp<d0, -1>>>,
derived_dimension<>>);
static_assert(std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 2>>, derived_dimension<exp<d0, -1>>>, d0>);
unknown_dimension<>>);
static_assert(std::is_same_v<dimension_multiply<derived_dimension<exp<d0, 2>>, unknown_dimension<exp<d0, -1>>>, d0>);
// dimension_divide
static_assert(std::is_same_v<dimension_divide<derived_dimension<exp<d0, 1>>, derived_dimension<exp<d1, 1>>>,
derived_dimension<exp<d0, 1>, exp<d1, -1>>>);
unknown_dimension<exp<d0, 1>, exp<d1, -1>>>);
static_assert(std::is_same_v<dimension_divide<derived_dimension<exp<d0, 1>>, derived_dimension<exp<d0, 1>>>,
derived_dimension<>>);
unknown_dimension<>>);
static_assert(std::is_same_v<dimension_divide<derived_dimension<exp<d0, 1>>, derived_dimension<exp<d0, 1>>>,
derived_dimension<>>);
static_assert(std::is_same_v<dimension_divide<derived_dimension<exp<d0, 2>>, derived_dimension<exp<d0, 1>>>, d0>);
unknown_dimension<>>);
static_assert(std::is_same_v<dimension_divide<derived_dimension<exp<d0, 2>>, unknown_dimension<exp<d0, 1>>>, d0>);
} // namespace

View File

@ -0,0 +1,193 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Mateusz Pusz
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <units/physical/si/acceleration.h>
#include <units/physical/si/area.h>
#include <units/physical/si/capacitance.h>
#include <units/physical/si/current.h>
#include <units/physical/si/electric_charge.h>
#include <units/physical/si/energy.h>
#include <units/physical/si/force.h>
#include <units/physical/si/frequency.h>
#include <units/physical/si/length.h>
#include <units/physical/si/luminous_intensity.h>
#include <units/physical/si/mass.h>
#include <units/physical/si/power.h>
#include <units/physical/si/pressure.h>
#include <units/physical/si/substance.h>
#include <units/physical/si/surface_tension.h>
#include <units/physical/si/temperature.h>
#include <units/physical/si/time.h>
#include <units/physical/si/velocity.h>
#include <units/physical/si/voltage.h>
#include <units/physical/si/volume.h>
#include <utility>
namespace {
using namespace units;
using namespace units::si;
/* ************** BASE DIMENSIONS **************** */
// length
static_assert(1km == 1000m);
static_assert(1m == 100cm);
static_assert(1m == 1000mm);
static_assert(1km + 1m == 1001m);
static_assert(10km / 5km == 2);
static_assert(100mm / 5cm == 2);
static_assert(10km / 2 == 5km);
static_assert(1yd == 0.9144m);
static_assert(1yd == 3ft);
static_assert(1ft == 12in);
static_assert(1mi == 1760yd);
static_assert(5in + 8cm == 207mm);
static_assert(millimetre::symbol == "mm");
static_assert(centimetre::symbol == "cm");
static_assert(kilometre::symbol == "km");
// mass
static_assert(1kg == 1000g);
static_assert(kilogram::symbol == "kg");
// time
static_assert(1h == 3600s);
static_assert(nanosecond::symbol == "ns");
static_assert(microsecond::symbol == "µs");
static_assert(millisecond::symbol == "ms");
// current
// temperature
// substance
// luminous intensity
/* ************** DERIVED DIMENSIONS WITH NAMED UNITS **************** */
// frequency
static_assert(2 / 1s == 2Hz);
static_assert(120 / 1min == 2Hz);
static_assert(1000 / 1s == 1kHz);
static_assert(1 / 1ms == 1kHz);
static_assert(3.2GHz == 3'200'000'000Hz);
static_assert(10Hz * 1min == 600);
static_assert(2 / 1Hz == 2s);
static_assert(millihertz::symbol == "mHz");
static_assert(kilohertz::symbol == "kHz");
static_assert(megahertz::symbol == "MHz");
static_assert(gigahertz::symbol == "GHz");
static_assert(terahertz::symbol == "THz");
// force
static_assert(10kg * 10mps_sq == 100N);
// pressure
static_assert(10N / 10sq_m == 1Pa);
// energy
static_assert(10N * 10m == 100_J);
static_assert(10Pa * 10cub_m == 100_J);
// power
static_assert(10_J / 10s == 1W);
// electric charge
static_assert(10A * 10s == 100C);
// voltage
static_assert(10W / 10A == 1V);
static_assert(10_J / 10C == 1V);
// capacitance
static_assert(10C / 10V == 1F);
/* ************** DERIVED DIMENSIONS IN TERMS OF BASE UNITS **************** */
// velocity
static_assert(std::is_same_v<decltype(1km / 1s), quantity<si::dim_velocity, scaled_unit<metre_per_second, ratio<1000>>, std::int64_t>>);
static_assert(10m / 5s == 2mps);
static_assert(10 / 5s * 1m == 2mps);
static_assert(1km / 1s == 1000mps);
// static_assert(1km / 1h == 1kmph); // should not compile
static_assert(1.0km / 1h == 1kmph);
static_assert(1000.0m / 3600.0s == 1kmph);
static_assert(10.0mi / 2h == 5mph);
static_assert(2kmph * 2h == 4km);
// static_assert(2kmph * 15min == 500m); // should not compile
static_assert(2kmph * 15.0min == 500m);
static_assert(2.0kmph * 15min == 500m);
static_assert(2km / 2kmph == 1h);
// static_assert(2000m / 2kmph == 1h); // should not compile
static_assert(quantity_cast<quantity<si::dim_length, kilometre, int>>(2000m) / 2kmph == 1h);
// static_assert(metre_per_second::symbol == basic_fixed_string("m/s"));
// static_assert(kilometre_per_hour::symbol == basic_fixed_string("km/h"));
// acceleration
static_assert(10mps / 10s == 1mps_sq);
// area
static_assert(1m * 1m == 1sq_m);
static_assert(10km * 10km == 100sq_km);
static_assert(1sq_m == 10'000sq_cm);
// volume
static_assert(1m * 1m * 1m == 1cub_m);
static_assert(10sq_m * 10m == 100cub_m);
static_assert(10km * 10km * 10km == 1000cub_km);
static_assert(1cub_m == 1'000'000cub_cm);
/* ************** DERIVED DIMENSIONS IN TERMS OF OTHER UNITS **************** */
static_assert(10N / 2m == 5Npm);
} // namespace

View File

@ -38,6 +38,9 @@ struct second : named_unit<second, "s", si::prefix> {};
struct hour : named_scaled_unit<hour, "h", no_prefix, ratio<3600>, second> {};
struct dim_time : base_dimension<"time", second> {};
struct kelvin : named_unit<kelvin, "K", no_prefix> {};
// struct kilokelvin : prefixed_unit<kilokelvin, si::kilo, kelvin> {}; // should not compile (prefix not allowed for this reference unit)
struct metre_per_second : unit<metre_per_second> {};
struct dim_velocity : derived_dimension<dim_velocity, metre_per_second, exp<dim_length, 1>, exp<dim_time, -1>> {};
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_velocity, kilometre, hour> {};