Unit Conversion and Dimensional Analysis Library 3.6.1
A compile-time, header-only C++23 dimensional-analysis library
Loading...
Searching...
No Matches
eigen.h
Go to the documentation of this file.
1//--------------------------------------------------------------------------------------------------
2//
3// UnitConversion: A compile-time c++23 unit conversion library with no dependencies
4//
5//--------------------------------------------------------------------------------------------------
6//
7// The MIT License (MIT)
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10// and associated documentation files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use, copy, modify, merge, publish,
12// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
13// Software is furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in all copies or
16// substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
19// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23//
24//--------------------------------------------------------------------------------------------------
25//
26// Copyright (c) 2016 Nic Holthaus
27//
28//--------------------------------------------------------------------------------------------------
29//
43//
44//--------------------------------------------------------------------------------------------------
45
46#pragma once
47
48#ifndef units_eigen_h_
49#define units_eigen_h_
50
51#include <units/core.h>
52
53#if defined __has_include
54#if __has_include(<Eigen/Core>)
55#include <Eigen/Core>
56
57#include <cmath>
58
59namespace Eigen
60{
70 template<units::UnitType U>
71 struct NumTraits<U> : NumTraits<typename units::traits::unit_traits<U>::underlying_type>
72 {
73 using T = typename units::traits::unit_traits<U>::underlying_type;
74 using Real = U;
75 using NonInteger = U;
76 using Nested = U;
77 using Literal = T;
78
79 enum
80 {
81 IsComplex = 0,
82 IsInteger = NumTraits<T>::IsInteger,
83 IsSigned = NumTraits<T>::IsSigned,
84 RequireInitialization = 1,
85 ReadCost = 1,
86 AddCost = 1,
87 MulCost = 1
88 };
89 };
90
98 template<units::UnitType U, class X>
99 struct ScalarBinaryOpTraits<U, X, internal::scalar_product_op<U, X>>
100 {
101 using ReturnType = U;
102 };
103
109 template<class X, units::UnitType U>
110 struct ScalarBinaryOpTraits<X, U, internal::scalar_product_op<X, U>>
111 {
112 using ReturnType = U;
113 };
114
124 template<units::UnitType U, class X>
125 struct ScalarBinaryOpTraits<U, X, internal::scalar_quotient_op<U, X>>
126 {
127 using ReturnType = U;
128 };
129} // namespace Eigen
130
131namespace units
132{
144 template<class DerivedA, class DerivedB>
145 auto unit_dot(const Eigen::MatrixBase<DerivedA>& lhs, const Eigen::MatrixBase<DerivedB>& rhs)
146 {
147 using UnitA = typename DerivedA::Scalar;
148 using UnitB = typename DerivedB::Scalar;
149 using Product = decltype(std::declval<UnitA>() * std::declval<UnitB>());
150
151 Product accumulator = Product(0);
152 for (Eigen::Index i = 0; i < lhs.size(); ++i)
153 accumulator += lhs(i) * rhs(i);
154 return accumulator;
155 }
156
164 template<class Derived>
165 auto unit_squared_norm(const Eigen::MatrixBase<Derived>& v)
166 {
167 return unit_dot(v, v);
168 }
169
182 template<class Derived>
183 auto unit_norm(const Eigen::MatrixBase<Derived>& v)
184 {
185 return units::sqrt(unit_squared_norm(v));
186 }
187
200 template<class Derived>
201 auto unit_normalized(const Eigen::MatrixBase<Derived>& v)
202 {
203 using Unit = typename Derived::Scalar;
204 using Underlying = detail::floating_point_promotion_t<typename traits::unit_traits<Unit>::underlying_type>;
205
206 const auto magnitude = unit_norm(v);
207
208 Eigen::Matrix<Underlying, Derived::RowsAtCompileTime, 1> direction(v.size());
209 for (Eigen::Index i = 0; i < v.size(); ++i)
210 direction(i) = (v(i) / magnitude).template to<Underlying>();
211 return direction;
212 }
213
225 template<class DerivedA, class DerivedB>
226 auto unit_cross(const Eigen::MatrixBase<DerivedA>& lhs, const Eigen::MatrixBase<DerivedB>& rhs)
227 {
228 using UnitA = typename DerivedA::Scalar;
229 using UnitB = typename DerivedB::Scalar;
230 using Product = decltype(std::declval<UnitA>() * std::declval<UnitB>());
231
232 Eigen::Matrix<Product, 3, 1> result;
233 result(0) = lhs(1) * rhs(2) - lhs(2) * rhs(1);
234 result(1) = lhs(2) * rhs(0) - lhs(0) * rhs(2);
235 result(2) = lhs(0) * rhs(1) - lhs(1) * rhs(0);
236 return result;
237 }
238
252 template<class MatrixDerived, class VectorDerived>
253 auto unit_transform(const Eigen::MatrixBase<MatrixDerived>& matrix, const Eigen::MatrixBase<VectorDerived>& vector)
254 {
255 using Unit = typename VectorDerived::Scalar;
256 using Underlying = typename traits::unit_traits<Unit>::underlying_type;
257
258 // Operate on each component's own-scale value (raw), so a ratio-scaled dimensionless input transforms in the
259 // scale the caller sees and the result reconstructs on that same scale. Every intermediate is sized to its
260 // runtime length so a dynamically-sized transform does not index a zero-length matrix.
261 Eigen::Matrix<Underlying, VectorDerived::RowsAtCompileTime, 1> raw(vector.size());
262 for (Eigen::Index i = 0; i < vector.size(); ++i)
263 raw(i) = vector(i).raw();
264
265 const Eigen::Matrix<Underlying, MatrixDerived::RowsAtCompileTime, 1> product = matrix * raw;
266
267 Eigen::Matrix<Unit, MatrixDerived::RowsAtCompileTime, 1> result(product.size());
268 for (Eigen::Index i = 0; i < product.size(); ++i)
269 result(i) = Unit(product(i));
270 return result;
271 }
272} // namespace units
273
274#endif // __has_include(<Eigen/Core>)
275#endif // defined __has_include
276
277#endif // units_eigen_h_
unit, dimensional analysis, generic cmath functions, traits (not dimension-specific),...
Unit Conversion Library namespace.
Definition units.h:108