Valkyrie 2026
Loading...
Searching...
No Matches
Common.h
1#pragma once
2
3#include <concepts>
4#include <cstddef>
5#include <string>
6#include <tuple>
7#include <type_traits>
8#include <utility>
9
10#include <Eigen/Dense>
11#include <fmt/format.h>
12
13#include "units/base.h"
14
15using namespace units::literals;
16
17namespace valor {
18namespace EigenUnit {
19
20template <typename... UnitTags>
21class UnitVector;
22
23template <typename OutputTagsTuple, typename InputTagsTuple>
24class UnitMatrix;
25
32template <std::size_t Start, std::size_t Length, typename Tuple>
33struct SliceTuple {
34 private:
35 template <typename Indices>
36 struct impl;
37
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>...>;
41 };
42
43 public:
45 using type = typename impl<std::make_index_sequence<Length>>::type;
46};
47
53template <typename Expected, typename Received>
56 static constexpr bool value = false;
57};
58
62template <typename T>
65 static constexpr bool value = true;
66};
67
72template <typename U>
74 using type = U;
75};
76
77template <typename U>
78 requires units::traits::is_dimensionless_unit<units::unit_t<U>>::value
79struct NormalizeUnit<U> {
80 using type = units::dimensionless::scalar;
81};
82
83template <typename U>
84using Normalize = typename NormalizeUnit<U>::type;
85
86template <typename Tuple>
88
89template <typename... Ts>
90struct NormalizeTuple<std::tuple<Ts...>> {
91 using type = std::tuple<Normalize<Ts>...>;
92};
93
99template <typename U1, typename U2>
100using MultiplyResult = Normalize<typename units::unit_t<units::compound_unit<U1, U2>>::unit_type>;
101
107template <typename U1, typename U2>
108using DivideResult = Normalize<typename units::unit_t<units::compound_unit<U1, units::inverse<U2>>>::unit_type>;
109
113namespace detail {
117template <std::size_t N, typename T>
119
125template <typename T, typename Indices>
127
131template <typename T, std::size_t... Is>
132struct VectorN_Builder<T, std::index_sequence<Is...>> {
135};
136
142 int precision = -1;
144 bool values_only = false;
145
151 template <typename ParseContext>
152 constexpr auto parse(ParseContext& ctx) {
153 auto it = ctx.begin();
154 if (it == ctx.end() || *it == '}')
155 return it;
156
157 if (*it == 'v') {
158 values_only = true;
159 ++it;
160 }
161
162 if (it != ctx.end() && *it == '.') {
163 ++it;
164 precision = 0;
165 while (it != ctx.end() && *it >= '0' && *it <= '9')
166 precision = precision * 10 + (*it++ - '0');
167 }
168
169 if (it != ctx.end() && *it != '}')
170 throw fmt::format_error("UnitVector: unexpected format character");
171
172 return it;
173 }
174
180 std::string format_value(double v) const {
181 if (precision >= 0)
182 return fmt::vformat("{:.{}f}", fmt::make_format_args(v, precision));
183 return fmt::format("{}", v);
184 }
185};
186} // namespace detail
187
191template <size_t N, typename... Ts>
192concept ValidIndex = (N < sizeof...(Ts));
193
197template <size_t N, typename... Ts>
198concept ValidSize = (N <= sizeof...(Ts));
199
203template <typename... Ts>
204concept AllSameUnits = sizeof...(Ts) > 0 && (std::is_same_v<std::tuple_element_t<0, std::tuple<Ts...>>, Ts> && ...);
205
209template <typename... Ts>
210concept ThreeDimensionalVector = sizeof...(Ts) == 3;
211
215template <typename T1, typename T2>
217
221template <typename T>
222concept HomogeneousTuple = []<typename... Ts>(std::tuple<Ts...>) { return AllSameUnits<Ts...>; }(T{});
223
227template <typename M>
228concept SquareMatrix = requires {
229 typename M::OutTuple;
230 typename M::InTuple;
231} && (std::tuple_size_v<typename M::OutTuple> == std::tuple_size_v<typename M::InTuple>);
232
236template <typename M>
237concept MatchingSquareMatrix = requires {
238 typename M::OutTuple;
239 typename M::InTuple;
240} && std::is_same_v<typename M::OutTuple, typename M::InTuple>;
241
245template <typename M>
247
251template <typename TL, typename TR, typename BL, typename BR, std::size_t TotalRows, std::size_t TotalCols>
253 requires {
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);
264
268template <typename Vec, typename ExpectedTuple>
269concept MatchingUnitTuple = requires { typename Vec::UnitTuple; } && std::is_same_v<typename Vec::UnitTuple, ExpectedTuple>;
270
274template <typename OutTuple, typename... ColVecs>
276
280template <typename InTuple, typename... RowVecs>
282
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>>;
289
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>>>;
295
299template <typename OutTuple, typename InTuple, typename ArgsTuple, typename IS>
301
305template <typename OutTuple, typename InTuple, typename ArgsTuple, std::size_t... Is>
306struct ValidElemArgsImpl<OutTuple, InTuple, ArgsTuple, std::index_sequence<Is...>> {
308 static constexpr bool value = (ValidElemArg<Is, OutTuple, InTuple, std::tuple_element_t<Is, ArgsTuple>> && ...);
309};
310
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;
317
318template <std::size_t N, typename IS = std::make_index_sequence<N>>
320
321template <std::size_t N, std::size_t... Is>
322struct ScalarTuple_Builder<N, std::index_sequence<Is...>> {
323 using type = std::tuple<detail::substitution_helper<Is, units::dimensionless::scalar>...>;
324};
325
326template <typename OutTuple, typename InTuple>
328 using NormalizedOut = OutTuple;
329 using NormalizedIn = InTuple;
330};
331
332template <typename... Ts>
333struct NormalizeBlockTuples<std::tuple<Ts...>, std::tuple<Ts...>> {
334 using NormalizedOut = typename ScalarTuple_Builder<sizeof...(Ts)>::type;
335 using NormalizedIn = typename ScalarTuple_Builder<sizeof...(Ts)>::type;
336};
337
338} // namespace EigenUnit
339} // namespace valor
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
Checks that a pack of row vectors all match the input tuple.
Definition Common.h:281
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
Definition Common.h:87
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
Parses a shared format spec used by UnitVector, UnitMap, ConstUnitMap.
Definition Common.h:140
constexpr auto parse(ParseContext &ctx)
Parses the format specifier string.
Definition Common.h:152
int precision
Desired decimal precision. -1 for default.
Definition Common.h:142
std::string format_value(double v) const
Formats a single double value according to the spec.
Definition Common.h:180
bool values_only
If true, only values are printed (no unit abbreviations).
Definition Common.h:144
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