11#include <fmt/format.h>
13#include "units/base.h"
15using namespace units::literals;
20template <
typename... UnitTags>
23template <
typename OutputTagsTuple,
typename InputTagsTuple>
32template <std::
size_t Start, std::
size_t Length,
typename Tuple>
35 template <
typename Indices>
38 template <std::size_t... Is>
39 struct impl<
std::index_sequence<Is...>> {
40 using type = std::tuple<std::tuple_element_t<Start + Is, Tuple>...>;
45 using type =
typename impl<std::make_index_sequence<Length>>
::type;
53template <
typename Expected,
typename Received>
56 static constexpr bool value =
false;
65 static constexpr bool value =
true;
78 requires units::traits::is_dimensionless_unit<units::unit_t<U>>::value
80 using type = units::dimensionless::scalar;
84using Normalize =
typename NormalizeUnit<U>::type;
86template <
typename Tuple>
89template <
typename... Ts>
91 using type = std::tuple<Normalize<Ts>...>;
99template <
typename U1,
typename U2>
100using MultiplyResult = Normalize<typename units::unit_t<units::compound_unit<U1, U2>>::unit_type>;
107template <
typename U1,
typename U2>
108using DivideResult = Normalize<typename units::unit_t<units::compound_unit<U1, units::inverse<U2>>>::unit_type>;
117template <std::
size_t N,
typename T>
125template <
typename T,
typename Indices>
131template <
typename T, std::size_t... Is>
151 template <
typename ParseContext>
152 constexpr auto parse(ParseContext& ctx) {
153 auto it = ctx.begin();
154 if (it == ctx.end() || *it ==
'}')
162 if (it != ctx.end() && *it ==
'.') {
165 while (it != ctx.end() && *it >=
'0' && *it <=
'9')
169 if (it != ctx.end() && *it !=
'}')
170 throw fmt::format_error(
"UnitVector: unexpected format character");
182 return fmt::vformat(
"{:.{}f}", fmt::make_format_args(v,
precision));
183 return fmt::format(
"{}", v);
191template <
size_t N,
typename... Ts>
197template <
size_t N,
typename... Ts>
203template <
typename... Ts>
204concept AllSameUnits =
sizeof...(Ts) > 0 && (std::is_same_v<std::tuple_element_t<0, std::tuple<Ts...>>, Ts> && ...);
209template <
typename... Ts>
215template <
typename T1,
typename T2>
229 typename M::OutTuple;
231} && (std::tuple_size_v<typename M::OutTuple> == std::tuple_size_v<typename M::InTuple>);
238 typename M::OutTuple;
240} && std::is_same_v<typename M::OutTuple, typename M::InTuple>;
251template <
typename TL,
typename TR,
typename BL,
typename BR, std::
size_t TotalRows, std::
size_t TotalCols>
254 { TL::RowCount } -> std::convertible_to<std::size_t>;
255 { TL::ColCount } -> std::convertible_to<std::size_t>;
256 { TR::RowCount } -> std::convertible_to<std::size_t>;
257 { TR::ColCount } -> std::convertible_to<std::size_t>;
258 { BL::RowCount } -> std::convertible_to<std::size_t>;
259 { BL::ColCount } -> std::convertible_to<std::size_t>;
260 { BR::RowCount } -> std::convertible_to<std::size_t>;
261 { BR::ColCount } -> std::convertible_to<std::size_t>;
262 } && (TL::RowCount + BL::RowCount == TotalRows) && (TR::RowCount + BR::RowCount == TotalRows) &&
263 (TL::ColCount + TR::ColCount == TotalCols) && (BL::ColCount + BR::ColCount == TotalCols);
268template <
typename Vec,
typename ExpectedTuple>
269concept MatchingUnitTuple =
requires {
typename Vec::UnitTuple; } && std::is_same_v<typename Vec::UnitTuple, ExpectedTuple>;
274template <
typename OutTuple,
typename... ColVecs>
280template <
typename InTuple,
typename... RowVecs>
286template <std::
size_t I,
typename OutTuple,
typename InTuple>
287using MatrixElemUnit = DivideResult<std::tuple_element_t<I / std::tuple_size_v<InTuple>, OutTuple>,
288 std::tuple_element_t<I % std::tuple_size_v<InTuple>, InTuple>>;
293template <std::
size_t I,
typename OutTuple,
typename InTuple,
typename Arg>
294inline constexpr bool ValidElemArg = std::is_same_v<std::decay_t<Arg>, units::unit_t<MatrixElemUnit<I, OutTuple, InTuple>>>;
299template <
typename OutTuple,
typename InTuple,
typename ArgsTuple,
typename IS>
305template <
typename OutTuple,
typename InTuple,
typename ArgsTuple, std::size_t... Is>
308 static constexpr bool value = (ValidElemArg<Is, OutTuple, InTuple, std::tuple_element_t<Is, ArgsTuple>> && ...);
314template <
typename OutTuple,
typename InTuple,
typename... Args>
315concept ValidElemArgs = (
sizeof...(Args) == std::tuple_size_v<OutTuple> * std::tuple_size_v<InTuple>) &&
316 ValidElemArgsImpl<OutTuple, InTuple, std::tuple<Args...>, std::make_index_sequence<
sizeof...(Args)>>::value;
318template <std::
size_t N,
typename IS = std::make_index_sequence<N>>
321template <std::size_t N, std::size_t... Is>
323 using type = std::tuple<detail::substitution_helper<Is, units::dimensionless::scalar>...>;
326template <
typename OutTuple,
typename InTuple>
328 using NormalizedOut = OutTuple;
329 using NormalizedIn = InTuple;
332template <
typename... Ts>
A matrix wrapper representing a linear map between two UnitVectors.
Definition UnitMatrix.h:23
A vector wrapper that enforces units for each element.
Definition UnitVector.h:22
Concept verifying that all units in a pack are identical.
Definition Common.h:204
Checks that a pack of column vectors all match the output tuple.
Definition Common.h:275
Concept verifying that a UnitMatrix has uniform units for both inputs and outputs.
Definition Common.h:246
Concept verifying that a tuple contains only identical unit types.
Definition Common.h:222
Concept verifying that a UnitMatrix is square AND has matching units for rows and columns.
Definition Common.h:237
Checks that a UnitVector's UnitTuple matches the output tuple of a matrix.
Definition Common.h:269
Concept verifying that a UnitMatrix is square.
Definition Common.h:228
Concept verifying that a pack contains exactly three elements.
Definition Common.h:210
Concept verifying that two tuple-based unit types match exactly.
Definition Common.h:216
Checks that a UnitMatrix's block dimensions sum correctly for fromBlocks.
Definition Common.h:252
Concept verifying that a pack of arguments matches the required units for a UnitMatrix.
Definition Common.h:315
Concept verifying that index N is within the bounds of a pack.
Definition Common.h:192
Concept verifying that size N is within the bounds of a pack.
Definition Common.h:198
Template specializations for std::tuple_size and std::tuple_element to support UnitVector.
Definition Formatters.h:8
Internal utility templates for unit vector and matrix manipulation.
Definition Common.h:113
T substitution_helper
Identity helper for template pack substitution.
Definition Common.h:118
static constexpr bool value
True if units match.
Definition Common.h:65
Error trap for unit mismatch detection in concepts.
Definition Common.h:54
static constexpr bool value
False if units do not match.
Definition Common.h:56
Trait that detects if a unit type is dimensionless. Uses units library's is_dimensionless to check.
Definition Common.h:73
Slices a tuple type into a new tuple starting from Start index with Length.
Definition Common.h:33
typename impl< std::make_index_sequence< Length > >::type type
The resulting sliced tuple type.
Definition Common.h:45
static constexpr bool value
True if all arguments match their expected unit at each index.
Definition Common.h:308
Implementation details for checking variadic matrix element arguments.
Definition Common.h:300
UnitVector< substitution_helper< Is, T >... > type
The resulting UnitVector type.
Definition Common.h:134
Builder for N-dimensional UnitVectors with uniform units.
Definition Common.h:126