Eigen  5.0.1
 
Loading...
Searching...
No Matches
Homogeneous.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_HOMOGENEOUS_H
12#define EIGEN_HOMOGENEOUS_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
33
34namespace internal {
35
36template <typename MatrixType, int Direction>
37struct traits<Homogeneous<MatrixType, Direction> > : traits<MatrixType> {
38 using StorageKind = typename traits<MatrixType>::StorageKind;
39 using MatrixTypeNested = typename ref_selector<MatrixType>::type;
40 using MatrixTypeNested_ = std::remove_reference_t<MatrixTypeNested>;
41 enum {
42 RowsPlusOne = (MatrixType::RowsAtCompileTime != Dynamic) ? int(MatrixType::RowsAtCompileTime) + 1 : Dynamic,
43 ColsPlusOne = (MatrixType::ColsAtCompileTime != Dynamic) ? int(MatrixType::ColsAtCompileTime) + 1 : Dynamic,
44 RowsAtCompileTime = Direction == Vertical ? RowsPlusOne : MatrixType::RowsAtCompileTime,
45 ColsAtCompileTime = Direction == Horizontal ? ColsPlusOne : MatrixType::ColsAtCompileTime,
46 MaxRowsAtCompileTime = RowsAtCompileTime,
47 MaxColsAtCompileTime = ColsAtCompileTime,
48 TmpFlags = MatrixTypeNested_::Flags & HereditaryBits,
49 Flags = ColsAtCompileTime == 1 ? (TmpFlags & ~RowMajorBit)
50 : RowsAtCompileTime == 1 ? (TmpFlags | RowMajorBit)
51 : TmpFlags
52 };
53};
54
55template <typename MatrixType, typename Lhs>
56struct homogeneous_left_product_impl;
57template <typename MatrixType, typename Rhs>
58struct homogeneous_right_product_impl;
59
60} // end namespace internal
61
62template <typename MatrixType, int Direction_>
63class Homogeneous : public MatrixBase<Homogeneous<MatrixType, Direction_> >, internal::no_assignment_operator {
64 public:
65 using NestedExpression = MatrixType;
66 enum { Direction = Direction_ };
67
68 using Base = MatrixBase<Homogeneous>;
69 EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
70
71 EIGEN_DEVICE_FUNC explicit inline Homogeneous(const MatrixType& matrix) : m_matrix(matrix) {}
72
73 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept {
74 return m_matrix.rows() + (int(Direction) == Vertical ? 1 : 0);
75 }
76 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept {
77 return m_matrix.cols() + (int(Direction) == Horizontal ? 1 : 0);
78 }
79
80 EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
81
82 template <typename Rhs>
83 EIGEN_DEVICE_FUNC inline const Product<Homogeneous, Rhs> operator*(const MatrixBase<Rhs>& rhs) const {
84 return Product<Homogeneous, Rhs>(*this, rhs.derived());
85 }
86
87 template <typename Lhs>
88 friend EIGEN_DEVICE_FUNC inline const Product<Lhs, Homogeneous> operator*(const MatrixBase<Lhs>& lhs,
89 const Homogeneous& rhs) {
90 return Product<Lhs, Homogeneous>(lhs.derived(), rhs);
91 }
92
93 template <typename Scalar, int Dim, int Mode, int Options>
94 friend EIGEN_DEVICE_FUNC inline const Product<Transform<Scalar, Dim, Mode, Options>, Homogeneous> operator*(
95 const Transform<Scalar, Dim, Mode, Options>& lhs, const Homogeneous& rhs) {
96 eigen_assert(int(Direction) == Vertical);
97 return Product<Transform<Scalar, Dim, Mode, Options>, Homogeneous>(lhs, rhs);
98 }
99
100 template <typename Func>
101 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::result_of<Func(Scalar, Scalar)>::type redux(
102 const Func& func) const {
103 return func(m_matrix.redux(func), Scalar(1));
104 }
105
106 protected:
107 typename MatrixType::Nested m_matrix;
108};
109
124template <typename Derived>
125EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::HomogeneousReturnType MatrixBase<Derived>::homogeneous() const {
126 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
127 return HomogeneousReturnType(derived());
128}
129
141template <typename ExpressionType, int Direction>
143 const {
144 return HomogeneousReturnType(_expression());
145}
146
164template <typename Derived>
165EIGEN_DEVICE_FUNC inline const typename MatrixBase<Derived>::HNormalizedReturnType MatrixBase<Derived>::hnormalized()
166 const {
167 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
168 return ConstStartMinusOne(derived(), 0, 0, ColsAtCompileTime == 1 ? size() - 1 : 1,
169 ColsAtCompileTime == 1 ? 1 : size() - 1) /
170 coeff(size() - 1);
171}
172
188template <typename ExpressionType, int Direction>
189EIGEN_DEVICE_FUNC inline const typename VectorwiseOp<ExpressionType, Direction>::HNormalizedReturnType
191 return HNormalized_Block(_expression(), 0, 0, Direction == Vertical ? _expression().rows() - 1 : _expression().rows(),
192 Direction == Horizontal ? _expression().cols() - 1 : _expression().cols())
193 .cwiseQuotient(Replicate < HNormalized_Factors, Direction == Vertical ? HNormalized_SizeMinusOne : 1,
194 Direction == Horizontal
195 ? HNormalized_SizeMinusOne
196 : 1 > (HNormalized_Factors(_expression(), Direction == Vertical ? _expression().rows() - 1 : 0,
197 Direction == Horizontal ? _expression().cols() - 1 : 0,
198 Direction == Vertical ? 1 : _expression().rows(),
199 Direction == Horizontal ? 1 : _expression().cols()),
200 Direction == Vertical ? _expression().rows() - 1 : 1,
201 Direction == Horizontal ? _expression().cols() - 1 : 1));
202}
203
204namespace internal {
205
206template <typename MatrixOrTransformType>
207struct take_matrix_for_product {
208 using type = MatrixOrTransformType;
209 EIGEN_DEVICE_FUNC static const type& run(const type& x) { return x; }
210};
211
212template <typename Scalar, int Dim, int Mode, int Options>
213struct take_matrix_for_product<Transform<Scalar, Dim, Mode, Options> > {
214 using TransformType = Transform<Scalar, Dim, Mode, Options>;
215 using type = std::add_const_t<typename TransformType::ConstAffinePart>;
216 EIGEN_DEVICE_FUNC static type run(const TransformType& x) { return x.affine(); }
217};
218
219template <typename Scalar, int Dim, int Options>
220struct take_matrix_for_product<Transform<Scalar, Dim, Projective, Options> > {
221 using TransformType = Transform<Scalar, Dim, Projective, Options>;
222 using type = typename TransformType::MatrixType;
223 EIGEN_DEVICE_FUNC static const type& run(const TransformType& x) { return x.matrix(); }
224};
225
226template <typename MatrixType, typename Lhs>
227struct traits<homogeneous_left_product_impl<Homogeneous<MatrixType, Vertical>, Lhs> > {
228 using LhsMatrixType = typename take_matrix_for_product<Lhs>::type;
229 using MatrixTypeCleaned = remove_all_t<MatrixType>;
230 using LhsMatrixTypeCleaned = remove_all_t<LhsMatrixType>;
231 using ReturnType = typename make_proper_matrix_type<
232 typename traits<MatrixTypeCleaned>::Scalar, LhsMatrixTypeCleaned::RowsAtCompileTime,
233 MatrixTypeCleaned::ColsAtCompileTime, MatrixTypeCleaned::PlainObject::Options,
234 LhsMatrixTypeCleaned::MaxRowsAtCompileTime, MatrixTypeCleaned::MaxColsAtCompileTime>::type;
235};
236
237template <typename MatrixType, typename Lhs>
238struct homogeneous_left_product_impl<Homogeneous<MatrixType, Vertical>, Lhs>
239 : public ReturnByValue<homogeneous_left_product_impl<Homogeneous<MatrixType, Vertical>, Lhs> > {
240 using LhsMatrixType = typename traits<homogeneous_left_product_impl>::LhsMatrixType;
241 using LhsMatrixTypeCleaned = remove_all_t<LhsMatrixType>;
242 using LhsMatrixTypeNested = remove_all_t<typename LhsMatrixTypeCleaned::Nested>;
243 EIGEN_DEVICE_FUNC homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
244 : m_lhs(take_matrix_for_product<Lhs>::run(lhs)), m_rhs(rhs) {}
245
246 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_lhs.rows(); }
247 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_rhs.cols(); }
248
249 template <typename Dest>
250 EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const {
251 // FIXME: investigate how to allow lazy evaluation of this product when possible.
252 dst = Block < const LhsMatrixTypeNested, LhsMatrixTypeNested::RowsAtCompileTime,
253 LhsMatrixTypeNested::ColsAtCompileTime == Dynamic
254 ? Dynamic
255 : LhsMatrixTypeNested::ColsAtCompileTime - 1 > (m_lhs, 0, 0, m_lhs.rows(), m_lhs.cols() - 1) * m_rhs;
256 dst += m_lhs.col(m_lhs.cols() - 1).rowwise().template replicate<MatrixType::ColsAtCompileTime>(m_rhs.cols());
257 }
258
259 typename LhsMatrixTypeCleaned::Nested m_lhs;
260 typename MatrixType::Nested m_rhs;
261};
262
263template <typename MatrixType, typename Rhs>
264struct traits<homogeneous_right_product_impl<Homogeneous<MatrixType, Horizontal>, Rhs> > {
265 using ReturnType =
266 typename make_proper_matrix_type<typename traits<MatrixType>::Scalar, MatrixType::RowsAtCompileTime,
267 Rhs::ColsAtCompileTime, MatrixType::PlainObject::Options,
268 MatrixType::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime>::type;
269};
270
271template <typename MatrixType, typename Rhs>
272struct homogeneous_right_product_impl<Homogeneous<MatrixType, Horizontal>, Rhs>
273 : public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType, Horizontal>, Rhs> > {
274 using RhsNested = remove_all_t<typename Rhs::Nested>;
275 EIGEN_DEVICE_FUNC homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) {}
276
277 EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_lhs.rows(); }
278 EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_rhs.cols(); }
279
280 template <typename Dest>
281 EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const {
282 // FIXME: investigate how to allow lazy evaluation of this product when possible.
283 dst = m_lhs * Block < const RhsNested,
284 RhsNested::RowsAtCompileTime == Dynamic ? Dynamic : RhsNested::RowsAtCompileTime - 1,
285 RhsNested::ColsAtCompileTime > (m_rhs, 0, 0, m_rhs.rows() - 1, m_rhs.cols());
286 dst += m_rhs.row(m_rhs.rows() - 1).colwise().template replicate<MatrixType::RowsAtCompileTime>(m_lhs.rows());
287 }
288
289 typename MatrixType::Nested m_lhs;
290 typename Rhs::Nested m_rhs;
291};
292
293template <typename ArgType, int Direction>
294struct evaluator_traits<Homogeneous<ArgType, Direction> > {
295 using Kind = typename storage_kind_to_evaluator_kind<typename ArgType::StorageKind>::Kind;
296 using Shape = HomogeneousShape;
297};
298
299template <>
300struct AssignmentKind<DenseShape, HomogeneousShape> {
301 using Kind = Dense2Dense;
302};
303
304template <typename ArgType, int Direction>
305struct unary_evaluator<Homogeneous<ArgType, Direction>, IndexBased>
306 : evaluator<typename Homogeneous<ArgType, Direction>::PlainObject> {
307 using XprType = Homogeneous<ArgType, Direction>;
308 using PlainObject = typename XprType::PlainObject;
309 using Base = evaluator<PlainObject>;
310
311 EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op) : Base(), m_temp(op) {
312 internal::construct_at<Base>(this, m_temp);
313 }
314
315 protected:
316 PlainObject m_temp;
317};
318
319// dense = homogeneous
320template <typename DstXprType, typename ArgType, typename Scalar>
321struct Assignment<DstXprType, Homogeneous<ArgType, Vertical>, internal::assign_op<Scalar, typename ArgType::Scalar>,
322 Dense2Dense> {
323 using SrcXprType = Homogeneous<ArgType, Vertical>;
324 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src,
325 const internal::assign_op<Scalar, typename ArgType::Scalar>&) {
326 Index dstRows = src.rows();
327 Index dstCols = src.cols();
328 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
329
330 dst.template topRows<ArgType::RowsAtCompileTime>(src.nestedExpression().rows()) = src.nestedExpression();
331 dst.row(dst.rows() - 1).setOnes();
332 }
333};
334
335// dense = homogeneous
336template <typename DstXprType, typename ArgType, typename Scalar>
337struct Assignment<DstXprType, Homogeneous<ArgType, Horizontal>, internal::assign_op<Scalar, typename ArgType::Scalar>,
338 Dense2Dense> {
339 using SrcXprType = Homogeneous<ArgType, Horizontal>;
340 EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src,
341 const internal::assign_op<Scalar, typename ArgType::Scalar>&) {
342 Index dstRows = src.rows();
343 Index dstCols = src.cols();
344 if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
345
346 dst.template leftCols<ArgType::ColsAtCompileTime>(src.nestedExpression().cols()) = src.nestedExpression();
347 dst.col(dst.cols() - 1).setOnes();
348 }
349};
350
351template <typename LhsArg, typename Rhs, int ProductTag>
352struct generic_product_impl<Homogeneous<LhsArg, Horizontal>, Rhs, HomogeneousShape, DenseShape, ProductTag> {
353 template <typename Dest>
354 EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Homogeneous<LhsArg, Horizontal>& lhs, const Rhs& rhs) {
355 homogeneous_right_product_impl<Homogeneous<LhsArg, Horizontal>, Rhs>(lhs.nestedExpression(), rhs).evalTo(dst);
356 }
357};
358
359template <typename Lhs, typename Rhs>
360struct homogeneous_right_product_refactoring_helper {
361 enum { Dim = Lhs::ColsAtCompileTime, Rows = Lhs::RowsAtCompileTime };
362 using LinearBlockConst = typename Rhs::template ConstNRowsBlockXpr<Dim>::Type;
363 using LinearBlock = std::remove_const_t<LinearBlockConst>;
364 using ConstantColumn = typename Rhs::ConstRowXpr;
365 using ConstantBlock = Replicate<const ConstantColumn, Rows, 1>;
366 using LinearProduct = Product<Lhs, LinearBlock, LazyProduct>;
367 using Xpr = CwiseBinaryOp<internal::scalar_sum_op<typename Lhs::Scalar, typename Rhs::Scalar>, const LinearProduct,
368 const ConstantBlock>;
369};
370
371template <typename Lhs, typename Rhs, int ProductTag>
372struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, HomogeneousShape, DenseShape>
373 : public evaluator<
374 typename homogeneous_right_product_refactoring_helper<typename Lhs::NestedExpression, Rhs>::Xpr> {
375 using XprType = Product<Lhs, Rhs, LazyProduct>;
376 using helper = homogeneous_right_product_refactoring_helper<typename Lhs::NestedExpression, Rhs>;
377 using ConstantBlock = typename helper::ConstantBlock;
378 using RefactoredXpr = typename helper::Xpr;
379 using Base = evaluator<RefactoredXpr>;
380
381 EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
382 : Base(xpr.lhs().nestedExpression().lazyProduct(
383 xpr.rhs().template topRows<helper::Dim>(xpr.lhs().nestedExpression().cols())) +
384 ConstantBlock(xpr.rhs().row(xpr.rhs().rows() - 1), xpr.lhs().rows(), 1)) {}
385};
386
387template <typename Lhs, typename RhsArg, int ProductTag>
388struct generic_product_impl<Lhs, Homogeneous<RhsArg, Vertical>, DenseShape, HomogeneousShape, ProductTag> {
389 template <typename Dest>
390 EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg, Vertical>& rhs) {
391 homogeneous_left_product_impl<Homogeneous<RhsArg, Vertical>, Lhs>(lhs, rhs.nestedExpression()).evalTo(dst);
392 }
393};
394
395template <typename Lhs, typename RhsArg, int ProductTag>
396struct generic_product_impl<Lhs, Homogeneous<RhsArg, Vertical>, TriangularShape, HomogeneousShape, ProductTag> {
397 template <typename Dest>
398 static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg, Vertical>& rhs) {
399 dst.noalias() = lhs * rhs.eval();
400 }
401};
402
403template <typename Lhs, typename Rhs>
404struct homogeneous_left_product_refactoring_helper {
405 enum { Dim = Rhs::RowsAtCompileTime, Cols = Rhs::ColsAtCompileTime };
406 using LinearBlockConst = typename Lhs::template ConstNColsBlockXpr<Dim>::Type;
407 using LinearBlock = std::remove_const_t<LinearBlockConst>;
408 using ConstantColumn = typename Lhs::ConstColXpr;
409 using ConstantBlock = Replicate<const ConstantColumn, 1, Cols>;
410 using LinearProduct = Product<LinearBlock, Rhs, LazyProduct>;
411 using Xpr = CwiseBinaryOp<internal::scalar_sum_op<typename Lhs::Scalar, typename Rhs::Scalar>, const LinearProduct,
412 const ConstantBlock>;
413};
414
415template <typename Lhs, typename Rhs, int ProductTag>
416struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape, HomogeneousShape>
417 : public evaluator<typename homogeneous_left_product_refactoring_helper<Lhs, typename Rhs::NestedExpression>::Xpr> {
418 using XprType = Product<Lhs, Rhs, LazyProduct>;
419 using helper = homogeneous_left_product_refactoring_helper<Lhs, typename Rhs::NestedExpression>;
420 using ConstantBlock = typename helper::ConstantBlock;
421 using RefactoredXpr = typename helper::Xpr;
422 using Base = evaluator<RefactoredXpr>;
423
424 EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
425 : Base(xpr.lhs()
426 .template leftCols<helper::Dim>(xpr.rhs().nestedExpression().rows())
427 .lazyProduct(xpr.rhs().nestedExpression()) +
428 ConstantBlock(xpr.lhs().col(xpr.lhs().cols() - 1), 1, xpr.rhs().cols())) {}
429};
430
431template <typename Scalar, int Dim, int Mode, int Options, typename RhsArg, int ProductTag>
432struct generic_product_impl<Transform<Scalar, Dim, Mode, Options>, Homogeneous<RhsArg, Vertical>, DenseShape,
433 HomogeneousShape, ProductTag> {
435 template <typename Dest>
436 EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const TransformType& lhs, const Homogeneous<RhsArg, Vertical>& rhs) {
437 homogeneous_left_product_impl<Homogeneous<RhsArg, Vertical>, TransformType>(lhs, rhs.nestedExpression())
438 .evalTo(dst);
439 }
440};
441
442template <typename ExpressionType, int Side, bool Transposed>
443struct permutation_matrix_product<ExpressionType, Side, Transposed, HomogeneousShape>
444 : public permutation_matrix_product<ExpressionType, Side, Transposed, DenseShape> {};
445
446} // end namespace internal
447
448} // end namespace Eigen
449
450#endif // EIGEN_HOMOGENEOUS_H
constexpr ColXpr col(Index i)
Definition DenseBase.h:1081
@ ColsAtCompileTime
Definition DenseBase.h:103
typename internal::traits< Homogeneous< MatrixType, Direction_ > >::Scalar Scalar
Definition DenseBase.h:63
Expression of one (or a set of) homogeneous vector(s)
Definition Homogeneous.h:63
const Product< MatrixWrapper< ExpressionType >, OtherDerived, LazyProduct > lazyProduct(const MatrixBase< OtherDerived > &other) const
Expression of the product of two arbitrary matrices or vectors.
Definition Product.h:203
Expression of the multiple replication of a matrix or vector.
Definition Replicate.h:65
Represents an homogeneous transformation in a N dimensional space.
Definition Transform.h:222
const HNormalizedReturnType hnormalized() const
column or row-wise homogeneous normalization
Definition Homogeneous.h:190
const HNormalizedReturnType hnormalized() const
homogeneous normalization
Definition Homogeneous.h:165
HomogeneousReturnType homogeneous() const
Definition Homogeneous.h:125
HomogeneousReturnType homogeneous() const
Definition Homogeneous.h:142
@ Horizontal
Definition Constants.h:270
@ Vertical
Definition Constants.h:267
@ Projective
Definition Constants.h:479
constexpr unsigned int RowMajorBit
Definition Constants.h:71