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
180 template<class Derived>
181 auto unit_norm(const Eigen::MatrixBase<Derived>& v)
182 {
183 using Unit = typename Derived::Scalar;
184 using Underlying = typename traits::unit_traits<Unit>::underlying_type;
185
186 Underlying accumulator = Underlying(0);
187 for (Eigen::Index i = 0; i < v.size(); ++i)
188 {
189 const Underlying raw = v(i).template to<Underlying>();
190 accumulator += raw * raw;
191 }
192 return Unit(std::sqrt(accumulator));
193 }
194
203 template<class Derived>
204 auto unit_normalized(const Eigen::MatrixBase<Derived>& v)
205 {
206 using Unit = typename Derived::Scalar;
207 using Underlying = typename traits::unit_traits<Unit>::underlying_type;
208
209 Underlying accumulator = Underlying(0);
210 for (Eigen::Index i = 0; i < v.size(); ++i)
211 {
212 const Underlying raw = v(i).template to<Underlying>();
213 accumulator += raw * raw;
214 }
215 const Underlying magnitude = std::sqrt(accumulator);
216
217 Eigen::Matrix<Underlying, Derived::RowsAtCompileTime, 1> direction;
218 for (Eigen::Index i = 0; i < v.size(); ++i)
219 direction(i) = v(i).template to<Underlying>() / magnitude;
220 return direction;
221 }
222
234 template<class DerivedA, class DerivedB>
235 auto unit_cross(const Eigen::MatrixBase<DerivedA>& lhs, const Eigen::MatrixBase<DerivedB>& rhs)
236 {
237 using UnitA = typename DerivedA::Scalar;
238 using UnitB = typename DerivedB::Scalar;
239 using Product = decltype(std::declval<UnitA>() * std::declval<UnitB>());
240
241 Eigen::Matrix<Product, 3, 1> result;
242 result(0) = lhs(1) * rhs(2) - lhs(2) * rhs(1);
243 result(1) = lhs(2) * rhs(0) - lhs(0) * rhs(2);
244 result(2) = lhs(0) * rhs(1) - lhs(1) * rhs(0);
245 return result;
246 }
247
261 template<class MatrixDerived, class VectorDerived>
262 auto unit_transform(const Eigen::MatrixBase<MatrixDerived>& matrix, const Eigen::MatrixBase<VectorDerived>& vector)
263 {
264 using Unit = typename VectorDerived::Scalar;
265 using Underlying = typename traits::unit_traits<Unit>::underlying_type;
266
267 Eigen::Matrix<Underlying, VectorDerived::RowsAtCompileTime, 1> raw;
268 for (Eigen::Index i = 0; i < vector.size(); ++i)
269 raw(i) = vector(i).template to<Underlying>();
270
271 const Eigen::Matrix<Underlying, MatrixDerived::RowsAtCompileTime, 1> product = matrix * raw;
272
273 Eigen::Matrix<Unit, MatrixDerived::RowsAtCompileTime, 1> result;
274 for (Eigen::Index i = 0; i < product.size(); ++i)
275 result(i) = Unit(product(i));
276 return result;
277 }
278} // namespace units
279
280#endif // __has_include(<Eigen/Core>)
281#endif // defined __has_include
282
283#endif // units_eigen_h_
unit, dimensional analysis, generic cmath functions, traits (not dimension-specific),...
Unit Conversion Library namespace.
Definition units.h:106