Eigen  5.0.1
 
Loading...
Searching...
No Matches
Dot.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2006-2008, 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
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_DOT_H
12#define EIGEN_DOT_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21// Accumulate low-precision norms in float without changing the public result type.
22template <typename RealScalar>
23struct stable_norm_accumulator {
24 using type = RealScalar;
25};
26
27template <>
28struct stable_norm_accumulator<half> {
29 using type = float;
30};
31
32template <>
33struct stable_norm_accumulator<bfloat16> {
34 using type = float;
35};
36
37template <typename RealScalar, typename Accumulator>
38struct stable_normalization_normal_min {
39 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() {
40 return static_cast<Accumulator>((numext::numeric_limits<RealScalar>::min)());
41 }
42};
43
44// The half and bfloat16 numeric_limits functions are not device functions.
45template <typename Accumulator>
46struct stable_normalization_normal_min<half, Accumulator> {
47 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() { return Accumulator(1) / Accumulator(16384); }
48};
49
50template <typename Accumulator>
51struct stable_normalization_normal_min<bfloat16, Accumulator> {
52 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator run() {
53 return static_cast<Accumulator>((numext::numeric_limits<float>::min)());
54 }
55};
56
57template <typename RealScalar, typename Accumulator>
58EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool stable_normalization_inv_scale(const Accumulator& value,
59 Accumulator& invScale) {
60 safe_scaling_factors<Accumulator> factors;
61 const Accumulator normalMin = stable_normalization_normal_min<RealScalar, Accumulator>::run();
62 if (!safe_scaling<Accumulator>::try_compute_ceiling_factors_with_normal_reciprocal(value, normalMin, factors))
63 return false;
64 invScale = factors.invScale;
65 return true;
66}
67
68template <typename Accumulator>
69EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool stable_normalization_combined_factor(const Accumulator& invScale,
70 const Accumulator& sqrtNorm,
71 Accumulator& factor) {
72 // Check before dividing: an overflowing reciprocal can raise FE_OVERFLOW even if the two-step fallback is used.
73 if (sqrtNorm < Accumulator(1) && invScale > Accumulator(NumTraits<Accumulator>::highest()) * sqrtNorm) return false;
74 Accumulator localSqrtNorm = sqrtNorm;
75 EIGEN_OPTIMIZATION_BARRIER(localSqrtNorm)
76 factor = invScale / localSqrtNorm;
77 return factor >= stable_normalization_normal_min<Accumulator, Accumulator>::run();
78}
79
80template <typename VectorType, typename Accumulator,
81 bool = bool(traits<VectorType>::Flags & DirectAccessBit) &&
82 (int(inner_stride_at_compile_time<VectorType>::value) != 1)>
83struct stable_normalization_dispatch {
84 using Scalar = typename traits<VectorType>::Scalar;
85 using RealScalar = typename NumTraits<Scalar>::Real;
86 // Only complex_array_access scalars have a writable component view.
87 using HasWritableRealView = bool_constant<!NumTraits<Scalar>::IsComplex || complex_array_access<Scalar>::value>;
88
89 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator max_abs(const VectorType& vec) {
90 return vec.realView().template cast<Accumulator>().cwiseAbs().template maxCoeff<PropagateNaN>();
91 }
92
93 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator scaled_squared_norm(const VectorType& vec,
94 const Accumulator& factor) {
95 return (vec.realView().template cast<Accumulator>() * factor).squaredNorm();
96 }
97
98 template <typename ResultType>
99 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled(ResultType& result, const VectorType& vec,
100 const Accumulator& factor) {
101 assign_scaled_impl(result, vec, factor, HasWritableRealView());
102 }
103
104 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place(VectorType& vec, const Accumulator& factor) {
105 assign_scaled_impl(vec, vec, factor, HasWritableRealView());
106 }
107
108 private:
109 template <typename ResultType>
110 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled_impl(ResultType& result, const VectorType& vec,
111 const Accumulator& factor, std::true_type) {
112 result.realView() = (vec.realView().template cast<Accumulator>() * factor).template cast<RealScalar>();
113 }
114
115 template <typename ResultType>
116 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled_impl(ResultType& result, const VectorType& vec,
117 const Accumulator& factor, std::false_type) {
118 result = vec * static_cast<RealScalar>(factor);
119 }
120};
121
122// Runtime-contiguous expressions can still use packet traversal.
123template <typename VectorType, typename Accumulator>
124struct stable_normalization_dispatch<VectorType, Accumulator, true> {
125 using Scalar = typename traits<VectorType>::Scalar;
126 using RealScalar = typename NumTraits<Scalar>::Real;
127 // A dynamic map avoids over-unrolling fixed-size normalization paths.
128 using PlainVector = Matrix<Scalar, Dynamic, 1>;
129 using ConstContiguousMap = Map<const PlainVector, evaluator<VectorType>::Alignment>;
130 using ContiguousMap = Map<PlainVector, evaluator<VectorType>::Alignment>;
131
132 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE bool is_contiguous(const VectorType& vec) {
133 return vec.innerStride() == 1 && (vec.outerSize() == 1 || vec.outerStride() == vec.innerSize());
134 }
135
136 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator max_abs(const VectorType& vec) {
137 if (is_contiguous(vec)) {
138 const ConstContiguousMap contiguous(vec.data(), vec.size());
139 return stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::max_abs(contiguous);
140 }
141 return stable_normalization_dispatch<VectorType, Accumulator, false>::max_abs(vec);
142 }
143
144 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Accumulator scaled_squared_norm(const VectorType& vec,
145 const Accumulator& factor) {
146 if (is_contiguous(vec)) {
147 const ConstContiguousMap contiguous(vec.data(), vec.size());
148 return stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::scaled_squared_norm(contiguous,
149 factor);
150 }
151 return stable_normalization_dispatch<VectorType, Accumulator, false>::scaled_squared_norm(vec, factor);
152 }
153
154 template <typename ResultType>
155 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void assign_scaled(ResultType& result, const VectorType& vec,
156 const Accumulator& factor) {
157 if (is_contiguous(vec)) {
158 const ConstContiguousMap contiguous(vec.data(), vec.size());
159 Map<PlainVector> output(result.data(), result.size());
160 stable_normalization_dispatch<ConstContiguousMap, Accumulator, false>::assign_scaled(output, contiguous, factor);
161 return;
162 }
163 stable_normalization_dispatch<VectorType, Accumulator, false>::assign_scaled(result, vec, factor);
164 }
165
166 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void scale_in_place(VectorType& vec, const Accumulator& factor) {
167 if (is_contiguous(vec)) {
168 ContiguousMap contiguous(vec.data(), vec.size());
169 stable_normalization_dispatch<ContiguousMap, Accumulator, false>::scale_in_place(contiguous, factor);
170 return;
171 }
172 stable_normalization_dispatch<VectorType, Accumulator, false>::scale_in_place(vec, factor);
173 }
174};
175
176// Prevent fast-math from merging normal scale factors into a subnormal factor.
177template <typename VectorType, typename Accumulator>
178EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void stable_normalization_scale_in_place(VectorType& vec,
179 const Accumulator& factor) {
180 stable_normalization_dispatch<VectorType, Accumulator>::scale_in_place(vec, factor);
181}
182
183template <typename VectorType, typename Divisor>
184EIGEN_DEVICE_FUNC EIGEN_DONT_INLINE void stable_normalization_divide_in_place(VectorType& vec, const Divisor& divisor) {
185 vec /= divisor;
186}
188template <typename VectorType, typename Accumulator>
189EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void stable_normalization_with_division(VectorType& vec,
190 const Accumulator& maxCoeff) {
191 using RealScalar = typename NumTraits<typename traits<VectorType>::Scalar>::Real;
192 // Two normal divisors avoid an exceptional reciprocal and fast-math
193 // reassociation into multiplication by 1 / maxCoeff.
194 const Accumulator sqrtMax = numext::sqrt(maxCoeff);
195 const RealScalar scale1 = static_cast<RealScalar>(sqrtMax);
196 const RealScalar scale2 = static_cast<RealScalar>(maxCoeff / sqrtMax);
197 stable_normalization_divide_in_place(vec, scale1);
198 stable_normalization_divide_in_place(vec, scale2);
199 const Accumulator z = vec.realView().template cast<Accumulator>().squaredNorm();
200 if (z > Accumulator(0)) {
201 stable_normalization_scale_in_place(vec, Accumulator(1) / numext::sqrt(z));
202 }
203}
204
205template <typename VectorType, typename Accumulator,
206 bool = use_subnormal_preserving_scaling<Accumulator, typename traits<VectorType>::Scalar>::value>
207struct stable_normalization_subnormal_recovery {
208 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(VectorType&) {}
209};
210
211template <typename VectorType, typename Accumulator>
212struct stable_normalization_subnormal_recovery<VectorType, Accumulator, true> {
213 using RealScalar = typename NumTraits<typename traits<VectorType>::Scalar>::Real;
214
215 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(VectorType& vec) {
216 using Binary = binary_floating_point_traits<RealScalar>;
217 using Bits = typename Binary::Bits;
218 decltype(auto) components = vec.realView();
219 Bits maxBits = 0;
220 for (Index col = 0; col < components.cols(); ++col) {
221 for (Index row = 0; row < components.rows(); ++row) {
222 const Bits bits = Binary::magnitude(components.coeff(row, col));
223 if (bits > maxBits) maxBits = bits;
224 }
225 }
226 if (maxBits == 0 || maxBits >= Binary::kExponentUnit) return;
227
228 const Accumulator maxAbs = numext::bit_cast<RealScalar>(maxBits);
229 const auto factors = safe_scaling<Accumulator>::compute_ceiling_factors(maxAbs);
230 safe_scaling<Accumulator>::scale_in_place(vec, maxAbs, factors);
231 const Accumulator squaredNorm = components.template cast<Accumulator>().squaredNorm();
232 if (squaredNorm > Accumulator(0)) {
233 stable_normalization_divide_in_place(vec, numext::sqrt(squaredNorm));
234 }
235 }
236};
237
238// squaredNorm() reduces realView().cwiseAbs2(), a cwise expression with no direct access, so when
239// the underlying expression has an inner stride that is not statically 1 (a dynamic-inner-stride
240// Map/Ref, a row of a 1xN matrix, ...) the reduction falls back to a scalar traversal even though
241// the data is frequently contiguous at runtime. This trait flags the cases where a runtime
242// contiguity check is worthwhile; it mirrors the reduction fast path in Redux.h (redux_dispatch).
243// bool is excluded: its squared norm is any(), handled by a dedicated specialization below.
244template <typename Xpr>
245struct squared_norm_runtime_unit_stride {
246 using Scalar = typename traits<Xpr>::Scalar;
247 static constexpr bool value =
248 bool(traits<Xpr>::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::Vectorizable) &&
249 !bool(internal::is_same<Scalar, bool>::value) && (int(inner_stride_at_compile_time<Xpr>::value) != 1);
250};
251
252template <typename Derived, typename Scalar = typename traits<Derived>::Scalar, typename Enable = void>
253struct squared_norm_impl {
254 using Real = typename NumTraits<Scalar>::Real;
255 static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Real run(const Derived& a) {
256 return a.realView().cwiseAbs2().sum();
257 }
258};
259
260template <typename Derived>
261struct squared_norm_impl<Derived, bool, void> {
262 static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE bool run(const Derived& a) { return a.any(); }
263};
264
265// Runtime contiguity fast path: when the data is contiguous at runtime (inner stride 1, and a
266// single inner panel or no gap between inner panels), reduce the underlying buffer as a contiguous
267// vector, recovering vectorization of the abs2 reduction.
268template <typename Derived, typename Scalar>
269struct squared_norm_impl<Derived, Scalar, std::enable_if_t<squared_norm_runtime_unit_stride<Derived>::value>> {
270 using Real = typename NumTraits<Scalar>::Real;
271 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Real run(const Derived& a) {
272 if (a.innerStride() == 1 && (a.outerSize() == 1 || a.outerStride() == a.innerSize())) {
273 using PlainVector = Matrix<Scalar, Dynamic, 1>;
274 Map<const PlainVector, evaluator<Derived>::Alignment> contiguous(a.data(), a.size());
275 return contiguous.realView().cwiseAbs2().sum();
276 }
277 return a.realView().cwiseAbs2().sum();
278 }
279};
280
281} // end namespace internal
282
294template <typename Derived>
295template <typename OtherDerived>
296EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE
298 typename internal::traits<OtherDerived>::Scalar>::ReturnType
299 MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const {
300 return internal::inner_product_dispatch<Derived, OtherDerived, true>::run(derived(), other.derived());
301}
302
303//---------- implementation of L2 norm and related functions ----------
304
311template <typename Derived>
312EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
314 return internal::squared_norm_impl<Derived>::run(derived());
315}
316
323template <typename Derived>
324EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
326 return numext::sqrt(squaredNorm());
327}
328
338template <typename Derived>
339EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject MatrixBase<Derived>::normalized()
340 const {
341 using Nested_ = typename internal::nested_eval<Derived, 2>::type;
342 Nested_ n(derived());
343 RealScalar z = n.squaredNorm();
344 // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
345 if (z > RealScalar(0))
346 return n / numext::sqrt(z);
347 else
348 return n;
349}
350
359template <typename Derived>
360EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::normalize() {
361 RealScalar z = squaredNorm();
362 // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
363 if (z > RealScalar(0)) derived() /= numext::sqrt(z);
364}
365
378template <typename Derived>
379EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
381 using Nested_ = typename internal::nested_eval<Derived, 3>::type;
382 using NestedClean = internal::remove_all_t<Nested_>;
383 using Accumulator = typename internal::stable_norm_accumulator<RealScalar>::type;
384 using Dispatch = internal::stable_normalization_dispatch<NestedClean, Accumulator>;
385 Nested_ vec(derived());
386 if (EIGEN_PREDICT_FALSE(vec.size() == 0)) return vec;
387
388 // Component-wise scaling stays finite when a finite complex value has an
389 // overflowing magnitude, and avoids a hypot per coefficient.
390 const Accumulator w = Dispatch::max_abs(vec);
391 const Accumulator highest = static_cast<Accumulator>(NumTraits<RealScalar>::highest());
392 if (EIGEN_PREDICT_FALSE(!(w > Accumulator(0)))) {
393 PlainObject normalized(vec);
394 internal::stable_normalization_subnormal_recovery<PlainObject, Accumulator>::run(normalized);
395 return normalized;
396 }
397 if (EIGEN_PREDICT_FALSE(!(w <= highest))) return vec;
398
399 Accumulator invScale;
400 if (EIGEN_PREDICT_TRUE((internal::stable_normalization_inv_scale<RealScalar>(w, invScale)))) {
401 const Accumulator z = Dispatch::scaled_squared_norm(vec, invScale);
402 if (z > Accumulator(0)) {
403 const Accumulator sqrt_z = numext::sqrt(z);
404 Accumulator factor;
405 PlainObject normalized(rows(), cols());
406 if (EIGEN_PREDICT_TRUE(internal::stable_normalization_combined_factor(invScale, sqrt_z, factor))) {
407 Dispatch::assign_scaled(normalized, vec, factor);
408 } else {
409 // invScale and sqrt_z are normal even though their quotient is not.
410 Dispatch::assign_scaled(normalized, vec, invScale);
411 internal::stable_normalization_divide_in_place(normalized, static_cast<RealScalar>(sqrt_z));
412 }
413 return normalized;
414 }
415 // Packet arithmetic may flush subnormal inputs even when the maximum reduction preserves them (ARMv7 NEON).
416 PlainObject normalized(vec);
417 internal::stable_normalization_subnormal_recovery<PlainObject, Accumulator>::run(normalized);
418 return normalized;
419 }
420
421 PlainObject normalized = vec;
422 internal::stable_normalization_with_division(normalized, w);
423 return normalized;
424}
425
437template <typename Derived>
438EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::stableNormalize() {
439 using Accumulator = typename internal::stable_norm_accumulator<RealScalar>::type;
440 using Dispatch = internal::stable_normalization_dispatch<Derived, Accumulator>;
441 if (EIGEN_PREDICT_FALSE(size() == 0)) return;
442
443 const Accumulator w = Dispatch::max_abs(derived());
444 const Accumulator highest = static_cast<Accumulator>(NumTraits<RealScalar>::highest());
445 if (EIGEN_PREDICT_FALSE(!(w > Accumulator(0)))) {
446 internal::stable_normalization_subnormal_recovery<Derived, Accumulator>::run(derived());
447 return;
448 }
449 if (EIGEN_PREDICT_FALSE(!(w <= highest))) return;
450
451 Accumulator invScale;
452 if (EIGEN_PREDICT_TRUE((internal::stable_normalization_inv_scale<RealScalar>(w, invScale)))) {
453 const Accumulator z = Dispatch::scaled_squared_norm(derived(), invScale);
454 if (z > Accumulator(0)) {
455 const Accumulator sqrt_z = numext::sqrt(z);
456 Accumulator factor;
457 if (EIGEN_PREDICT_TRUE(internal::stable_normalization_combined_factor(invScale, sqrt_z, factor))) {
458 Dispatch::scale_in_place(derived(), factor);
459 } else {
460 internal::stable_normalization_scale_in_place(derived(), invScale);
461 internal::stable_normalization_divide_in_place(derived(), static_cast<RealScalar>(sqrt_z));
462 }
463 } else {
464 internal::stable_normalization_subnormal_recovery<Derived, Accumulator>::run(derived());
465 }
466 return;
467 }
468
469 internal::stable_normalization_with_division(derived(), w);
470}
471
472//---------- implementation of other norms ----------
473
474namespace internal {
475
476template <typename Derived, int p>
477struct lpNorm_selector {
478 using RealScalar = typename NumTraits<typename traits<Derived>::Scalar>::Real;
479 EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase<Derived>& m) {
480 EIGEN_USING_STD(pow)
481 return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1) / p);
482 }
483};
484
485template <typename Derived>
486struct lpNorm_selector<Derived, 1> {
487 EIGEN_DEVICE_FUNC static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(
488 const MatrixBase<Derived>& m) {
489 return m.cwiseAbs().sum();
490 }
491};
492
493template <typename Derived>
494struct lpNorm_selector<Derived, 2> {
495 EIGEN_DEVICE_FUNC static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(
496 const MatrixBase<Derived>& m) {
497 return m.norm();
498 }
499};
500
501template <typename Derived>
502struct lpNorm_selector<Derived, Infinity> {
503 using RealScalar = typename NumTraits<typename traits<Derived>::Scalar>::Real;
504 EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase<Derived>& m) {
505 if (Derived::SizeAtCompileTime == 0 || (Derived::SizeAtCompileTime == Dynamic && m.size() == 0))
506 return RealScalar(0);
507 return m.cwiseAbs().maxCoeff();
508 }
509};
510
511} // end namespace internal
512
527template <typename Derived>
528template <int p>
529#ifndef EIGEN_PARSED_BY_DOXYGEN
530EIGEN_DEVICE_FUNC inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
531#else
532EIGEN_DEVICE_FUNC MatrixBase<Derived>::RealScalar
533#endif
535 return internal::lpNorm_selector<Derived, p>::run(*this);
536}
537
538//---------- implementation of isOrthogonal / isUnitary ----------
539
546template <typename Derived>
547template <typename OtherDerived>
548bool MatrixBase<Derived>::isOrthogonal(const MatrixBase<OtherDerived>& other, const RealScalar& prec) const {
549 typename internal::nested_eval<Derived, 2>::type nested(derived());
550 typename internal::nested_eval<OtherDerived, 2>::type otherNested(other.derived());
551 return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
552}
553
565template <typename Derived>
566bool MatrixBase<Derived>::isUnitary(const RealScalar& prec) const {
567 typename internal::nested_eval<Derived, 1>::type self(derived());
568 for (Index i = 0; i < cols(); ++i) {
569 if (!internal::isApprox(self.col(i).squaredNorm(), static_cast<RealScalar>(1), prec)) return false;
570 for (Index j = 0; j < i; ++j)
571 if (!internal::isMuchSmallerThan(self.col(i).dot(self.col(j)), static_cast<Scalar>(1), prec)) return false;
572 }
573 return true;
574}
575
576} // end namespace Eigen
577
578#endif // EIGEN_DOT_H
constexpr const GlobalUnaryPowReturnType< Derived, ScalarExponent > pow(const Eigen::ArrayBase< Derived > &x, const ScalarExponent &exponent)
internal::traits< Derived >::Scalar maxCoeff() const
Definition Redux.h:799
typename internal::traits< Derived >::Scalar Scalar
Definition DenseBase.h:63
constexpr CastXpr< NewType >::Type cast() const
Definition DenseBase.h:66
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
void stableNormalize()
Definition Dot.h:438
constexpr ScalarBinaryOpTraits< typenameinternal::traits< Derived >::Scalar, typenameinternal::traits< OtherDerived >::Scalar >::ReturnType dot(const MatrixBase< OtherDerived > &other) const
Definition Dot.h:299
const PlainObject stableNormalized() const
Definition Dot.h:380
const PlainObject normalized() const
Definition Dot.h:339
RealScalar lpNorm() const
Definition Dot.h:534
bool isUnitary(const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition Dot.h:566
const CwiseUnaryOp< internal::scalar_abs_op< Scalar >, const Derived > cwiseAbs() const
constexpr RealScalar squaredNorm() const
Definition Dot.h:313
void normalize()
Definition Dot.h:360
RealScalar norm() const
Definition Dot.h:325
bool isOrthogonal(const MatrixBase< OtherDerived > &other, const RealScalar &prec=NumTraits< Scalar >::dummy_precision()) const
Definition Dot.h:548
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
constexpr unsigned int DirectAccessBit
Definition Constants.h:160
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition NumTraits.h:233
Determines whether the given binary operation of two numeric types is allowed and what the scalar ret...
Definition XprHelper.h:1062