From fd4618b20dd8391e65a249bb5dba4e55b64b6e9b Mon Sep 17 00:00:00 2001 From: Ayzen Date: Thu, 5 Mar 2026 14:42:33 +0300 Subject: [PATCH] init commit --- .gitignore | 221 + Makefile | 83 + .../common_cpp/config/include/run_config.hpp | 97 + .../common_cpp/config/src/run_config.cpp | 398 + .../common_cpp/ipc/include/shared_types.hpp | 91 + .../common_cpp/ipc/include/shm_ring.hpp | 61 + .../common_cpp/ipc/src/shared_types.cpp | 336 + .../common_cpp/ipc/src/shm_ring.cpp | 380 + .../include/calibration_master.hpp | 32 + .../include/calibrator_interface.hpp | 21 + .../src/calibration_master.cpp | 101 + .../src/through_calibrator.cpp | 76 + .../include/data_preprocessor.hpp | 47 + .../src/data_preprocessor.cpp | 85 + .../data_preprocessor/src/main.cpp | 86 + .../include/reference_master.hpp | 30 + .../reference_master/src/reference_master.cpp | 141 + .../data_processor/include/data_processor.hpp | 48 + .../include/processing_live_config.hpp | 49 + .../data_processor/src/data_processor.cpp | 156 + .../processing/data_processor/src/main.cpp | 69 + .../src/processing_live_config.cpp | 189 + .../processors/include/bscan_processor.hpp | 16 + .../include/passthrough_processor.hpp | 16 + .../include/processor_interface.hpp | 21 + .../processors/src/bscan_processor.cpp | 237 + .../processors/src/passthrough_processor.cpp | 39 + .../interfaces/radar_driver.hpp | 37 + .../interfaces/switch_driver.hpp | 24 + .../librevna_minimal_driver_lifecycle.cpp | 212 + .../librevna_minimal_driver_protocol.cpp | 130 + .../librevna_minimal_driver_transport.cpp | 359 + .../librevna/librevna_protocol_common.hpp | 112 + .../radar/librevna_minimal_driver.hpp | 97 + .../switches/h7992_minimal_driver.cpp | 160 + .../switches/h7992_minimal_driver.hpp | 51 + .../switches/hmc349a_minimal_driver.cpp | 147 + .../switches/hmc349a_minimal_driver.hpp | 52 + .../include/sweep_orchestrator.hpp | 62 + .../sweep_orchestrator/include/sweep_plan.hpp | 22 + .../sweep_orchestrator/src/main.cpp | 135 + .../src/sweep_orchestrator.cpp | 178 + .../sweep_orchestrator/src/sweep_plan.cpp | 19 + .../third_party/eigen/COPYING.APACHE | 203 + .../third_party/eigen/COPYING.BSD | 26 + .../third_party/eigen/COPYING.MINPACK | 51 + .../third_party/eigen/COPYING.MPL2 | 373 + .../third_party/eigen/COPYING.README | 11 + .../third_party/eigen/Eigen/AccelerateSupport | 52 + .../third_party/eigen/Eigen/Cholesky | 43 + .../third_party/eigen/Eigen/CholmodSupport | 48 + .../third_party/eigen/Eigen/Core | 482 + .../third_party/eigen/Eigen/Dense | 7 + .../third_party/eigen/Eigen/Eigen | 2 + .../third_party/eigen/Eigen/Eigenvalues | 63 + .../third_party/eigen/Eigen/Geometry | 62 + .../third_party/eigen/Eigen/Householder | 31 + .../eigen/Eigen/IterativeLinearSolvers | 52 + .../third_party/eigen/Eigen/Jacobi | 33 + .../third_party/eigen/Eigen/KLUSupport | 43 + .../third_party/eigen/Eigen/LU | 49 + .../third_party/eigen/Eigen/MetisSupport | 35 + .../third_party/eigen/Eigen/OrderingMethods | 73 + .../third_party/eigen/Eigen/PaStiXSupport | 51 + .../third_party/eigen/Eigen/PardisoSupport | 38 + .../third_party/eigen/Eigen/QR | 48 + .../third_party/eigen/Eigen/QtAlignedMalloc | 32 + .../third_party/eigen/Eigen/SPQRSupport | 41 + .../third_party/eigen/Eigen/SVD | 55 + .../third_party/eigen/Eigen/Sparse | 33 + .../third_party/eigen/Eigen/SparseCholesky | 40 + .../third_party/eigen/Eigen/SparseCore | 70 + .../third_party/eigen/Eigen/SparseLU | 50 + .../third_party/eigen/Eigen/SparseQR | 38 + .../third_party/eigen/Eigen/StdDeque | 30 + .../third_party/eigen/Eigen/StdList | 29 + .../third_party/eigen/Eigen/StdVector | 30 + .../third_party/eigen/Eigen/SuperLUSupport | 70 + .../third_party/eigen/Eigen/ThreadPool | 80 + .../third_party/eigen/Eigen/UmfPackSupport | 42 + .../third_party/eigen/Eigen/Version | 14 + .../src/AccelerateSupport/AccelerateSupport.h | 423 + .../AccelerateSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/Cholesky/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/Cholesky/LDLT.h | 661 + .../eigen/Eigen/src/Cholesky/LLT.h | 516 + .../eigen/Eigen/src/Cholesky/LLT_LAPACKE.h | 124 + .../Eigen/src/CholmodSupport/CholmodSupport.h | 738 + .../src/CholmodSupport/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/Core/ArithmeticSequence.h | 239 + .../third_party/eigen/Eigen/src/Core/Array.h | 374 + .../eigen/Eigen/src/Core/ArrayBase.h | 210 + .../eigen/Eigen/src/Core/ArrayWrapper.h | 166 + .../third_party/eigen/Eigen/src/Core/Assign.h | 84 + .../eigen/Eigen/src/Core/AssignEvaluator.h | 1066 + .../eigen/Eigen/src/Core/Assign_AOCL.h | 301 + .../eigen/Eigen/src/Core/Assign_MKL.h | 183 + .../eigen/Eigen/src/Core/BandMatrix.h | 338 + .../third_party/eigen/Eigen/src/Core/Block.h | 427 + .../eigen/Eigen/src/Core/CommaInitializer.h | 148 + .../eigen/Eigen/src/Core/ConditionEstimator.h | 173 + .../eigen/Eigen/src/Core/CoreEvaluators.h | 1972 ++ .../eigen/Eigen/src/Core/CoreIterators.h | 141 + .../eigen/Eigen/src/Core/CwiseBinaryOp.h | 166 + .../eigen/Eigen/src/Core/CwiseNullaryOp.h | 975 + .../eigen/Eigen/src/Core/CwiseTernaryOp.h | 171 + .../eigen/Eigen/src/Core/CwiseUnaryOp.h | 95 + .../eigen/Eigen/src/Core/CwiseUnaryView.h | 169 + .../eigen/Eigen/src/Core/DenseBase.h | 672 + .../eigen/Eigen/src/Core/DenseCoeffsBase.h | 583 + .../eigen/Eigen/src/Core/DenseStorage.h | 546 + .../eigen/Eigen/src/Core/DeviceWrapper.h | 153 + .../eigen/Eigen/src/Core/Diagonal.h | 221 + .../eigen/Eigen/src/Core/DiagonalMatrix.h | 473 + .../eigen/Eigen/src/Core/DiagonalProduct.h | 30 + .../third_party/eigen/Eigen/src/Core/Dot.h | 267 + .../eigen/Eigen/src/Core/EigenBase.h | 149 + .../third_party/eigen/Eigen/src/Core/Fill.h | 140 + .../eigen/Eigen/src/Core/FindCoeff.h | 464 + .../eigen/Eigen/src/Core/ForceAlignedAccess.h | 108 + .../third_party/eigen/Eigen/src/Core/Fuzzy.h | 132 + .../eigen/Eigen/src/Core/GeneralProduct.h | 518 + .../eigen/Eigen/src/Core/GenericPacketMath.h | 1706 ++ .../eigen/Eigen/src/Core/GlobalFunctions.h | 230 + .../third_party/eigen/Eigen/src/Core/IO.h | 233 + .../eigen/Eigen/src/Core/IndexedView.h | 322 + .../eigen/Eigen/src/Core/InnerProduct.h | 260 + .../Eigen/src/Core/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/Core/Inverse.h | 108 + .../third_party/eigen/Eigen/src/Core/Map.h | 154 + .../eigen/Eigen/src/Core/MapBase.h | 283 + .../eigen/Eigen/src/Core/MathFunctions.h | 2160 ++ .../eigen/Eigen/src/Core/MathFunctionsImpl.h | 265 + .../third_party/eigen/Eigen/src/Core/Matrix.h | 536 + .../eigen/Eigen/src/Core/MatrixBase.h | 557 + .../eigen/Eigen/src/Core/NestByValue.h | 91 + .../eigen/Eigen/src/Core/NoAlias.h | 102 + .../eigen/Eigen/src/Core/NumTraits.h | 335 + .../Eigen/src/Core/PartialReduxEvaluator.h | 253 + .../eigen/Eigen/src/Core/PermutationMatrix.h | 555 + .../eigen/Eigen/src/Core/PlainObjectBase.h | 1008 + .../eigen/Eigen/src/Core/Product.h | 307 + .../eigen/Eigen/src/Core/ProductEvaluators.h | 1275 + .../third_party/eigen/Eigen/src/Core/Random.h | 207 + .../eigen/Eigen/src/Core/RandomImpl.h | 265 + .../eigen/Eigen/src/Core/RealView.h | 292 + .../third_party/eigen/Eigen/src/Core/Redux.h | 535 + .../third_party/eigen/Eigen/src/Core/Ref.h | 384 + .../eigen/Eigen/src/Core/Replicate.h | 130 + .../eigen/Eigen/src/Core/Reshaped.h | 363 + .../eigen/Eigen/src/Core/ReturnByValue.h | 111 + .../eigen/Eigen/src/Core/Reverse.h | 202 + .../third_party/eigen/Eigen/src/Core/Select.h | 92 + .../eigen/Eigen/src/Core/SelfAdjointView.h | 329 + .../eigen/Eigen/src/Core/SelfCwiseBinaryOp.h | 50 + .../Eigen/src/Core/SkewSymmetricMatrix3.h | 382 + .../third_party/eigen/Eigen/src/Core/Solve.h | 174 + .../eigen/Eigen/src/Core/SolveTriangular.h | 237 + .../eigen/Eigen/src/Core/SolverBase.h | 167 + .../eigen/Eigen/src/Core/StableNorm.h | 216 + .../eigen/Eigen/src/Core/StlIterators.h | 618 + .../third_party/eigen/Eigen/src/Core/Stride.h | 115 + .../third_party/eigen/Eigen/src/Core/Swap.h | 100 + .../eigen/Eigen/src/Core/Transpose.h | 428 + .../eigen/Eigen/src/Core/Transpositions.h | 323 + .../eigen/Eigen/src/Core/TriangularMatrix.h | 928 + .../eigen/Eigen/src/Core/VectorBlock.h | 83 + .../eigen/Eigen/src/Core/VectorwiseOp.h | 735 + .../eigen/Eigen/src/Core/Visitor.h | 537 + .../eigen/Eigen/src/Core/arch/AVX/Complex.h | 580 + .../Eigen/src/Core/arch/AVX/MathFunctions.h | 129 + .../Eigen/src/Core/arch/AVX/PacketMath.h | 3045 ++ .../Eigen/src/Core/arch/AVX/Reductions.h | 353 + .../Eigen/src/Core/arch/AVX/TypeCasting.h | 342 + .../Eigen/src/Core/arch/AVX512/Complex.h | 479 + .../Eigen/src/Core/arch/AVX512/GemmKernel.h | 1249 + .../src/Core/arch/AVX512/MathFunctions.h | 119 + .../src/Core/arch/AVX512/MathFunctionsFP16.h | 75 + .../Eigen/src/Core/arch/AVX512/PacketMath.h | 3172 ++ .../src/Core/arch/AVX512/PacketMathFP16.h | 1411 + .../Eigen/src/Core/arch/AVX512/Reductions.h | 297 + .../Eigen/src/Core/arch/AVX512/TrsmKernel.h | 1171 + .../src/Core/arch/AVX512/TrsmUnrolls.inc | 1219 + .../Eigen/src/Core/arch/AVX512/TypeCasting.h | 285 + .../src/Core/arch/AVX512/TypeCastingFP16.h | 130 + .../Eigen/src/Core/arch/AltiVec/Complex.h | 639 + .../src/Core/arch/AltiVec/MathFunctions.h | 81 + .../src/Core/arch/AltiVec/MatrixProduct.h | 3686 +++ .../Core/arch/AltiVec/MatrixProductCommon.h | 205 + .../src/Core/arch/AltiVec/MatrixProductMMA.h | 900 + .../arch/AltiVec/MatrixProductMMAbfloat16.h | 742 + .../Core/arch/AltiVec/MatrixVectorProduct.inc | 2818 ++ .../Eigen/src/Core/arch/AltiVec/PacketMath.h | 3651 +++ .../Eigen/src/Core/arch/AltiVec/TypeCasting.h | 153 + .../Eigen/src/Core/arch/Default/BFloat16.h | 903 + .../Eigen/src/Core/arch/Default/ConjHelper.h | 146 + .../arch/Default/GenericPacketMathComplex.h | 282 + .../Default/GenericPacketMathDoubleWord.h | 208 + .../Default/GenericPacketMathFrexpLdexp.h | 162 + .../arch/Default/GenericPacketMathFunctions.h | 608 + .../Default/GenericPacketMathFunctionsFwd.h | 243 + .../Default/GenericPacketMathPolynomials.h | 151 + .../Core/arch/Default/GenericPacketMathPow.h | 710 + .../Core/arch/Default/GenericPacketMathTrig.h | 833 + .../eigen/Eigen/src/Core/arch/Default/Half.h | 1126 + .../Eigen/src/Core/arch/Default/Settings.h | 47 + .../eigen/Eigen/src/Core/arch/GPU/Complex.h | 196 + .../Eigen/src/Core/arch/GPU/MathFunctions.h | 104 + .../Eigen/src/Core/arch/GPU/PacketMath.h | 1710 ++ .../eigen/Eigen/src/Core/arch/GPU/Tuple.h | 268 + .../Eigen/src/Core/arch/GPU/TypeCasting.h | 77 + .../src/Core/arch/HIP/hcc/math_constants.h | 23 + .../Eigen/src/Core/arch/HVX/PacketMath.h | 1092 + .../eigen/Eigen/src/Core/arch/LSX/Complex.h | 520 + .../Core/arch/LSX/GeneralBlockPanelKernel.h | 23 + .../Eigen/src/Core/arch/LSX/MathFunctions.h | 43 + .../Eigen/src/Core/arch/LSX/PacketMath.h | 2846 ++ .../Eigen/src/Core/arch/LSX/TypeCasting.h | 526 + .../eigen/Eigen/src/Core/arch/MSA/Complex.h | 613 + .../Eigen/src/Core/arch/MSA/MathFunctions.h | 379 + .../Eigen/src/Core/arch/MSA/PacketMath.h | 1199 + .../eigen/Eigen/src/Core/arch/NEON/Complex.h | 738 + .../Core/arch/NEON/GeneralBlockPanelKernel.h | 243 + .../Eigen/src/Core/arch/NEON/MathFunctions.h | 63 + .../Eigen/src/Core/arch/NEON/PacketMath.h | 6100 ++++ .../Eigen/src/Core/arch/NEON/TypeCasting.h | 1642 + .../Eigen/src/Core/arch/NEON/UnaryFunctors.h | 57 + .../Core/arch/RVV10/GeneralBlockPanelKernel.h | 236 + .../Eigen/src/Core/arch/RVV10/MathFunctions.h | 30 + .../Eigen/src/Core/arch/RVV10/PacketMath.h | 2442 ++ .../Eigen/src/Core/arch/RVV10/PacketMath2.h | 1537 + .../Eigen/src/Core/arch/RVV10/PacketMath4.h | 1462 + .../src/Core/arch/RVV10/PacketMathBF16.h | 839 + .../src/Core/arch/RVV10/PacketMathFP16.h | 999 + .../Eigen/src/Core/arch/RVV10/TypeCasting.h | 284 + .../eigen/Eigen/src/Core/arch/SSE/Complex.h | 501 + .../Eigen/src/Core/arch/SSE/MathFunctions.h | 88 + .../Eigen/src/Core/arch/SSE/PacketMath.h | 2144 ++ .../Eigen/src/Core/arch/SSE/Reductions.h | 324 + .../Eigen/src/Core/arch/SSE/TypeCasting.h | 180 + .../Eigen/src/Core/arch/SVE/MathFunctions.h | 24 + .../Eigen/src/Core/arch/SVE/PacketMath.h | 678 + .../Eigen/src/Core/arch/SVE/TypeCasting.h | 52 + .../Eigen/src/Core/arch/SYCL/InteropHeaders.h | 226 + .../Eigen/src/Core/arch/SYCL/MathFunctions.h | 113 + .../Eigen/src/Core/arch/SYCL/PacketMath.h | 551 + .../Eigen/src/Core/arch/SYCL/TypeCasting.h | 83 + .../Eigen/src/Core/arch/ZVector/Complex.h | 553 + .../src/Core/arch/ZVector/MathFunctions.h | 244 + .../Eigen/src/Core/arch/ZVector/PacketMath.h | 1353 + .../eigen/Eigen/src/Core/arch/clang/Complex.h | 406 + .../Eigen/src/Core/arch/clang/MathFunctions.h | 47 + .../Eigen/src/Core/arch/clang/PacketMath.h | 875 + .../Eigen/src/Core/arch/clang/Reductions.h | 162 + .../Eigen/src/Core/arch/clang/TypeCasting.h | 100 + .../src/Core/functors/AssignmentFunctors.h | 174 + .../Eigen/src/Core/functors/BinaryFunctors.h | 748 + .../Eigen/src/Core/functors/NullaryFunctors.h | 274 + .../Eigen/src/Core/functors/StlFunctors.h | 149 + .../Eigen/src/Core/functors/TernaryFunctors.h | 53 + .../Eigen/src/Core/functors/UnaryFunctors.h | 1421 + .../Core/products/GeneralBlockPanelKernel.h | 2355 ++ .../src/Core/products/GeneralMatrixMatrix.h | 459 + .../products/GeneralMatrixMatrixTriangular.h | 330 + .../GeneralMatrixMatrixTriangular_BLAS.h | 150 + .../Core/products/GeneralMatrixMatrix_BLAS.h | 206 + .../src/Core/products/GeneralMatrixVector.h | 674 + .../Core/products/GeneralMatrixVector_BLAS.h | 141 + .../Eigen/src/Core/products/Parallelizer.h | 282 + .../Core/products/SelfadjointMatrixMatrix.h | 483 + .../products/SelfadjointMatrixMatrix_BLAS.h | 281 + .../Core/products/SelfadjointMatrixVector.h | 251 + .../products/SelfadjointMatrixVector_BLAS.h | 117 + .../src/Core/products/SelfadjointProduct.h | 133 + .../Core/products/SelfadjointRank2Update.h | 95 + .../Core/products/TriangularMatrixMatrix.h | 373 + .../products/TriangularMatrixMatrix_BLAS.h | 329 + .../Core/products/TriangularMatrixVector.h | 347 + .../products/TriangularMatrixVector_BLAS.h | 278 + .../Core/products/TriangularSolverMatrix.h | 448 + .../products/TriangularSolverMatrix_BLAS.h | 168 + .../Core/products/TriangularSolverVector.h | 122 + .../eigen/Eigen/src/Core/util/AOCL_Support.h | 175 + .../eigen/Eigen/src/Core/util/Assert.h | 158 + .../eigen/Eigen/src/Core/util/BlasUtil.h | 626 + .../src/Core/util/ConfigureVectorization.h | 609 + .../eigen/Eigen/src/Core/util/Constants.h | 601 + .../src/Core/util/DisableStupidWarnings.h | 146 + .../eigen/Eigen/src/Core/util/EmulateArray.h | 270 + .../Eigen/src/Core/util/ForwardDeclarations.h | 527 + .../Eigen/src/Core/util/GpuHipCudaDefines.inc | 101 + .../src/Core/util/GpuHipCudaUndefines.inc | 45 + .../Eigen/src/Core/util/IndexedViewHelper.h | 487 + .../Eigen/src/Core/util/IntegralConstant.h | 279 + .../eigen/Eigen/src/Core/util/MKL_support.h | 139 + .../eigen/Eigen/src/Core/util/Macros.h | 1392 + .../eigen/Eigen/src/Core/util/MaxSizeVector.h | 138 + .../eigen/Eigen/src/Core/util/Memory.h | 1383 + .../eigen/Eigen/src/Core/util/Meta.h | 680 + .../eigen/Eigen/src/Core/util/MoreMeta.h | 634 + .../src/Core/util/ReenableStupidWarnings.h | 44 + .../Eigen/src/Core/util/ReshapedHelper.h | 51 + .../eigen/Eigen/src/Core/util/Serializer.h | 209 + .../eigen/Eigen/src/Core/util/StaticAssert.h | 105 + .../eigen/Eigen/src/Core/util/SymbolicIndex.h | 445 + .../eigen/Eigen/src/Core/util/XprHelper.h | 1091 + .../src/Eigenvalues/ComplexEigenSolver.h | 314 + .../eigen/Eigen/src/Eigenvalues/ComplexQZ.h | 651 + .../Eigen/src/Eigenvalues/ComplexSchur.h | 443 + .../src/Eigenvalues/ComplexSchur_LAPACKE.h | 95 + .../eigen/Eigen/src/Eigenvalues/EigenSolver.h | 579 + .../src/Eigenvalues/GeneralizedEigenSolver.h | 402 + .../GeneralizedSelfAdjointEigenSolver.h | 212 + .../src/Eigenvalues/HessenbergDecomposition.h | 356 + .../src/Eigenvalues/InternalHeaderCheck.h | 3 + .../src/Eigenvalues/MatrixBaseEigenvalues.h | 141 + .../eigen/Eigen/src/Eigenvalues/RealQZ.h | 587 + .../eigen/Eigen/src/Eigenvalues/RealSchur.h | 519 + .../Eigen/src/Eigenvalues/RealSchur_LAPACKE.h | 83 + .../src/Eigenvalues/SelfAdjointEigenSolver.h | 865 + .../SelfAdjointEigenSolver_LAPACKE.h | 90 + .../src/Eigenvalues/Tridiagonalization.h | 529 + .../eigen/Eigen/src/Geometry/AlignedBox.h | 485 + .../eigen/Eigen/src/Geometry/AngleAxis.h | 245 + .../eigen/Eigen/src/Geometry/EulerAngles.h | 203 + .../eigen/Eigen/src/Geometry/Homogeneous.h | 452 + .../eigen/Eigen/src/Geometry/Hyperplane.h | 273 + .../Eigen/src/Geometry/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/Geometry/OrthoMethods.h | 257 + .../Eigen/src/Geometry/ParametrizedLine.h | 232 + .../eigen/Eigen/src/Geometry/Quaternion.h | 923 + .../eigen/Eigen/src/Geometry/Rotation2D.h | 201 + .../eigen/Eigen/src/Geometry/RotationBase.h | 209 + .../eigen/Eigen/src/Geometry/Scaling.h | 195 + .../eigen/Eigen/src/Geometry/Transform.h | 1494 + .../eigen/Eigen/src/Geometry/Translation.h | 204 + .../eigen/Eigen/src/Geometry/Umeyama.h | 161 + .../Eigen/src/Geometry/arch/Geometry_SIMD.h | 154 + .../Eigen/src/Householder/BlockHouseholder.h | 86 + .../eigen/Eigen/src/Householder/Householder.h | 162 + .../src/Householder/HouseholderSequence.h | 504 + .../src/Householder/InternalHeaderCheck.h | 3 + .../BasicPreconditioners.h | 213 + .../src/IterativeLinearSolvers/BiCGSTAB.h | 219 + .../ConjugateGradient.h | 217 + .../IncompleteCholesky.h | 402 + .../IterativeLinearSolvers/IncompleteLUT.h | 449 + .../InternalHeaderCheck.h | 3 + .../IterativeSolverBase.h | 395 + .../LeastSquareConjugateGradient.h | 193 + .../IterativeLinearSolvers/SolveWithGuess.h | 111 + .../Eigen/src/Jacobi/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/Jacobi/Jacobi.h | 468 + .../src/KLUSupport/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/KLUSupport/KLUSupport.h | 261 + .../eigen/Eigen/src/LU/Determinant.h | 98 + .../eigen/Eigen/src/LU/FullPivLU.h | 825 + .../eigen/Eigen/src/LU/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/LU/InverseImpl.h | 353 + .../eigen/Eigen/src/LU/PartialPivLU.h | 583 + .../eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h | 97 + .../eigen/Eigen/src/LU/arch/InverseSize4.h | 353 + .../src/MetisSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/MetisSupport/MetisSupport.h | 125 + .../eigen/Eigen/src/OrderingMethods/Amd.h | 413 + .../Eigen/src/OrderingMethods/Eigen_Colamd.h | 1690 ++ .../src/OrderingMethods/InternalHeaderCheck.h | 3 + .../Eigen/src/OrderingMethods/Ordering.h | 146 + .../src/PaStiXSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/PaStiXSupport/PaStiXSupport.h | 632 + .../src/PardisoSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/PardisoSupport/PardisoSupport.h | 500 + .../eigen/Eigen/src/QR/ColPivHouseholderQR.h | 674 + .../src/QR/ColPivHouseholderQR_LAPACKE.h | 161 + .../src/QR/CompleteOrthogonalDecomposition.h | 648 + .../eigen/Eigen/src/QR/FullPivHouseholderQR.h | 727 + .../eigen/Eigen/src/QR/HouseholderQR.h | 543 + .../Eigen/src/QR/HouseholderQR_LAPACKE.h | 77 + .../eigen/Eigen/src/QR/InternalHeaderCheck.h | 3 + .../src/SPQRSupport/InternalHeaderCheck.h | 3 + .../src/SPQRSupport/SuiteSparseQRSupport.h | 315 + .../third_party/eigen/Eigen/src/SVD/BDCSVD.h | 1470 + .../eigen/Eigen/src/SVD/BDCSVD_LAPACKE.h | 174 + .../eigen/Eigen/src/SVD/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/SVD/JacobiSVD.h | 851 + .../eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h | 127 + .../third_party/eigen/Eigen/src/SVD/SVDBase.h | 436 + .../Eigen/src/SVD/UpperBidiagonalization.h | 366 + .../src/SparseCholesky/InternalHeaderCheck.h | 3 + .../src/SparseCholesky/SimplicialCholesky.h | 868 + .../SparseCholesky/SimplicialCholesky_impl.h | 388 + .../eigen/Eigen/src/SparseCore/AmbiVector.h | 329 + .../Eigen/src/SparseCore/CompressedStorage.h | 206 + .../ConservativeSparseSparseProduct.h | 308 + .../src/SparseCore/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/SparseCore/SparseAssign.h | 279 + .../eigen/Eigen/src/SparseCore/SparseBlock.h | 560 + .../Eigen/src/SparseCore/SparseColEtree.h | 194 + .../src/SparseCore/SparseCompressedBase.h | 592 + .../src/SparseCore/SparseCwiseBinaryOp.h | 938 + .../Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 142 + .../Eigen/src/SparseCore/SparseDenseProduct.h | 489 + .../src/SparseCore/SparseDiagonalProduct.h | 146 + .../eigen/Eigen/src/SparseCore/SparseDot.h | 100 + .../eigen/Eigen/src/SparseCore/SparseFuzzy.h | 31 + .../eigen/Eigen/src/SparseCore/SparseMap.h | 295 + .../eigen/Eigen/src/SparseCore/SparseMatrix.h | 1876 ++ .../Eigen/src/SparseCore/SparseMatrixBase.h | 451 + .../Eigen/src/SparseCore/SparsePermutation.h | 249 + .../Eigen/src/SparseCore/SparseProduct.h | 178 + .../eigen/Eigen/src/SparseCore/SparseRedux.h | 47 + .../eigen/Eigen/src/SparseCore/SparseRef.h | 371 + .../src/SparseCore/SparseSelfAdjointView.h | 613 + .../Eigen/src/SparseCore/SparseSolverBase.h | 115 + .../SparseSparseProductWithPruning.h | 181 + .../Eigen/src/SparseCore/SparseTranspose.h | 83 + .../src/SparseCore/SparseTriangularView.h | 177 + .../eigen/Eigen/src/SparseCore/SparseUtil.h | 209 + .../eigen/Eigen/src/SparseCore/SparseVector.h | 532 + .../eigen/Eigen/src/SparseCore/SparseView.h | 225 + .../Eigen/src/SparseCore/TriangularSolver.h | 270 + .../Eigen/src/SparseLU/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/SparseLU/SparseLU.h | 968 + .../eigen/Eigen/src/SparseLU/SparseLUImpl.h | 79 + .../Eigen/src/SparseLU/SparseLU_Memory.h | 210 + .../Eigen/src/SparseLU/SparseLU_Structs.h | 113 + .../src/SparseLU/SparseLU_SupernodalMatrix.h | 315 + .../eigen/Eigen/src/SparseLU/SparseLU_Utils.h | 75 + .../Eigen/src/SparseLU/SparseLU_column_bmod.h | 177 + .../Eigen/src/SparseLU/SparseLU_column_dfs.h | 168 + .../src/SparseLU/SparseLU_copy_to_ucol.h | 106 + .../src/SparseLU/SparseLU_heap_relax_snode.h | 114 + .../Eigen/src/SparseLU/SparseLU_kernel_bmod.h | 133 + .../Eigen/src/SparseLU/SparseLU_panel_bmod.h | 215 + .../Eigen/src/SparseLU/SparseLU_panel_dfs.h | 232 + .../Eigen/src/SparseLU/SparseLU_pivotL.h | 136 + .../Eigen/src/SparseLU/SparseLU_pruneL.h | 130 + .../Eigen/src/SparseLU/SparseLU_relax_snode.h | 81 + .../Eigen/src/SparseQR/InternalHeaderCheck.h | 3 + .../eigen/Eigen/src/SparseQR/SparseQR.h | 705 + .../eigen/Eigen/src/StlSupport/StdDeque.h | 51 + .../eigen/Eigen/src/StlSupport/StdList.h | 50 + .../eigen/Eigen/src/StlSupport/StdVector.h | 51 + .../eigen/Eigen/src/StlSupport/details.h | 82 + .../src/SuperLUSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/SuperLUSupport/SuperLUSupport.h | 929 + .../eigen/Eigen/src/ThreadPool/Barrier.h | 70 + .../src/ThreadPool/CoreThreadPoolDevice.h | 336 + .../eigen/Eigen/src/ThreadPool/EventCount.h | 241 + .../eigen/Eigen/src/ThreadPool/ForkJoin.h | 140 + .../src/ThreadPool/InternalHeaderCheck.h | 4 + .../src/ThreadPool/NonBlockingThreadPool.h | 587 + .../eigen/Eigen/src/ThreadPool/RunQueue.h | 230 + .../eigen/Eigen/src/ThreadPool/ThreadCancel.h | 21 + .../Eigen/src/ThreadPool/ThreadEnvironment.h | 43 + .../eigen/Eigen/src/ThreadPool/ThreadLocal.h | 289 + .../src/ThreadPool/ThreadPoolInterface.h | 50 + .../eigen/Eigen/src/ThreadPool/ThreadYield.h | 16 + .../src/UmfPackSupport/InternalHeaderCheck.h | 3 + .../Eigen/src/UmfPackSupport/UmfPackSupport.h | 606 + .../third_party/eigen/Eigen/src/misc/Image.h | 80 + .../Eigen/src/misc/InternalHeaderCheck.h | 3 + .../third_party/eigen/Eigen/src/misc/Kernel.h | 77 + .../third_party/eigen/Eigen/src/misc/blas.h | 97 + .../eigen/Eigen/src/misc/lapacke.h | 10085 +++++++ .../eigen/Eigen/src/misc/lapacke_helpers.h | 163 + .../eigen/Eigen/src/misc/lapacke_mangling.h | 16 + .../Eigen/src/plugins/ArrayCwiseBinaryOps.inc | 324 + .../Eigen/src/plugins/ArrayCwiseUnaryOps.inc | 548 + .../eigen/Eigen/src/plugins/BlockMethods.inc | 1380 + .../src/plugins/CommonCwiseBinaryOps.inc | 122 + .../Eigen/src/plugins/CommonCwiseUnaryOps.inc | 167 + .../Eigen/src/plugins/IndexedViewMethods.inc | 192 + .../Eigen/src/plugins/InternalHeaderCheck.inc | 3 + .../src/plugins/MatrixCwiseBinaryOps.inc | 335 + .../Eigen/src/plugins/MatrixCwiseUnaryOps.inc | 129 + .../Eigen/src/plugins/ReshapedMethods.inc | 133 + .../eigen/unsupported/CMakeLists.txt | 11 + .../eigen/unsupported/Eigen/AdolcForward | 153 + .../eigen/unsupported/Eigen/AlignedVector3 | 211 + .../eigen/unsupported/Eigen/ArpackSupport | 33 + .../eigen/unsupported/Eigen/AutoDiff | 48 + .../third_party/eigen/unsupported/Eigen/BVH | 108 + .../eigen/unsupported/Eigen/CMakeLists.txt | 31 + .../unsupported/Eigen/CXX11/CMakeLists.txt | 8 + .../eigen/unsupported/Eigen/CXX11/Tensor | 142 + .../unsupported/Eigen/CXX11/TensorSymmetry | 40 + .../eigen/unsupported/Eigen/CXX11/ThreadPool | 1 + .../CXX11/src/Tensor/InternalHeaderCheck.h | 3 + .../Eigen/CXX11/src/Tensor/README.md | 2352 ++ .../Eigen/CXX11/src/Tensor/Tensor.h | 382 + .../Eigen/CXX11/src/Tensor/TensorArgMax.h | 282 + .../Eigen/CXX11/src/Tensor/TensorAssign.h | 211 + .../Eigen/CXX11/src/Tensor/TensorBase.h | 1244 + .../Eigen/CXX11/src/Tensor/TensorBlock.h | 1474 + .../CXX11/src/Tensor/TensorBroadcasting.h | 1001 + .../Eigen/CXX11/src/Tensor/TensorChipping.h | 469 + .../CXX11/src/Tensor/TensorConcatenation.h | 351 + .../CXX11/src/Tensor/TensorContraction.h | 958 + .../src/Tensor/TensorContractionBlocking.h | 69 + .../CXX11/src/Tensor/TensorContractionCuda.h | 7 + .../CXX11/src/Tensor/TensorContractionGpu.h | 1387 + .../src/Tensor/TensorContractionMapper.h | 537 + .../CXX11/src/Tensor/TensorContractionSycl.h | 1653 ++ .../src/Tensor/TensorContractionThreadPool.h | 1544 + .../Eigen/CXX11/src/Tensor/TensorConversion.h | 416 + .../CXX11/src/Tensor/TensorConvolution.h | 1106 + .../CXX11/src/Tensor/TensorConvolutionSycl.h | 538 + .../Eigen/CXX11/src/Tensor/TensorCostModel.h | 189 + .../Eigen/CXX11/src/Tensor/TensorCustomOp.h | 307 + .../Eigen/CXX11/src/Tensor/TensorDevice.h | 138 + .../Eigen/CXX11/src/Tensor/TensorDeviceCuda.h | 7 + .../CXX11/src/Tensor/TensorDeviceDefault.h | 113 + .../Eigen/CXX11/src/Tensor/TensorDeviceGpu.h | 364 + .../Eigen/CXX11/src/Tensor/TensorDeviceSycl.h | 567 + .../CXX11/src/Tensor/TensorDeviceThreadPool.h | 346 + .../CXX11/src/Tensor/TensorDimensionList.h | 117 + .../Eigen/CXX11/src/Tensor/TensorDimensions.h | 334 + .../Eigen/CXX11/src/Tensor/TensorEvalTo.h | 188 + .../Eigen/CXX11/src/Tensor/TensorEvaluator.h | 859 + .../Eigen/CXX11/src/Tensor/TensorExecutor.h | 670 + .../Eigen/CXX11/src/Tensor/TensorExpr.h | 338 + .../Eigen/CXX11/src/Tensor/TensorFFT.h | 650 + .../Eigen/CXX11/src/Tensor/TensorFixedSize.h | 221 + .../Eigen/CXX11/src/Tensor/TensorForcedEval.h | 230 + .../src/Tensor/TensorForwardDeclarations.h | 215 + .../Eigen/CXX11/src/Tensor/TensorFunctors.h | 422 + .../Eigen/CXX11/src/Tensor/TensorGenerator.h | 269 + .../CXX11/src/Tensor/TensorGlobalFunctions.h | 36 + .../Eigen/CXX11/src/Tensor/TensorIO.h | 413 + .../Eigen/CXX11/src/Tensor/TensorImagePatch.h | 590 + .../Eigen/CXX11/src/Tensor/TensorIndexList.h | 617 + .../Eigen/CXX11/src/Tensor/TensorInflation.h | 224 + .../CXX11/src/Tensor/TensorInitializer.h | 78 + .../Eigen/CXX11/src/Tensor/TensorIntDiv.h | 258 + .../Eigen/CXX11/src/Tensor/TensorLayoutSwap.h | 185 + .../Eigen/CXX11/src/Tensor/TensorMacros.h | 85 + .../Eigen/CXX11/src/Tensor/TensorMap.h | 189 + .../Eigen/CXX11/src/Tensor/TensorMeta.h | 291 + .../Eigen/CXX11/src/Tensor/TensorMorphing.h | 980 + .../Eigen/CXX11/src/Tensor/TensorPadding.h | 620 + .../Eigen/CXX11/src/Tensor/TensorPatch.h | 258 + .../Eigen/CXX11/src/Tensor/TensorRandom.h | 297 + .../Eigen/CXX11/src/Tensor/TensorReduction.h | 1023 + .../CXX11/src/Tensor/TensorReductionGpu.h | 958 + .../CXX11/src/Tensor/TensorReductionSycl.h | 584 + .../Eigen/CXX11/src/Tensor/TensorRef.h | 390 + .../Eigen/CXX11/src/Tensor/TensorReverse.h | 406 + .../Eigen/CXX11/src/Tensor/TensorRoll.h | 361 + .../Eigen/CXX11/src/Tensor/TensorScan.h | 474 + .../Eigen/CXX11/src/Tensor/TensorScanSycl.h | 506 + .../Eigen/CXX11/src/Tensor/TensorShuffling.h | 413 + .../Eigen/CXX11/src/Tensor/TensorStorage.h | 143 + .../Eigen/CXX11/src/Tensor/TensorStriding.h | 312 + .../Eigen/CXX11/src/Tensor/TensorTrace.h | 281 + .../Eigen/CXX11/src/Tensor/TensorTraits.h | 232 + .../Eigen/CXX11/src/Tensor/TensorUInt128.h | 229 + .../CXX11/src/Tensor/TensorVolumePatch.h | 621 + .../src/TensorSymmetry/DynamicSymmetry.h | 296 + .../src/TensorSymmetry/InternalHeaderCheck.h | 4 + .../CXX11/src/TensorSymmetry/StaticSymmetry.h | 223 + .../Eigen/CXX11/src/TensorSymmetry/Symmetry.h | 335 + .../TensorSymmetry/util/TemplateGroupTheory.h | 492 + .../Eigen/CXX11/src/util/CXX11Meta.h | 18 + .../Eigen/CXX11/src/util/CXX11Workarounds.h | 85 + .../eigen/unsupported/Eigen/EulerAngles | 44 + .../third_party/eigen/unsupported/Eigen/FFT | 430 + .../eigen/unsupported/Eigen/IterativeSolvers | 92 + .../eigen/unsupported/Eigen/KroneckerProduct | 35 + .../unsupported/Eigen/LevenbergMarquardt | 49 + .../eigen/unsupported/Eigen/MPRealSupport | 214 + .../eigen/unsupported/Eigen/MatrixFunctions | 504 + .../third_party/eigen/unsupported/Eigen/NNLS | 388 + .../unsupported/Eigen/NonLinearOptimization | 141 + .../eigen/unsupported/Eigen/NumericalDiff | 57 + .../eigen/unsupported/Eigen/OpenGLSupport | 350 + .../eigen/unsupported/Eigen/Polynomials | 140 + .../eigen/unsupported/Eigen/SparseExtra | 60 + .../eigen/unsupported/Eigen/SpecialFunctions | 107 + .../eigen/unsupported/Eigen/Splines | 36 + .../Eigen/src/AutoDiff/AutoDiffJacobian.h | 76 + .../Eigen/src/AutoDiff/AutoDiffScalar.h | 571 + .../Eigen/src/AutoDiff/AutoDiffVector.h | 169 + .../Eigen/src/AutoDiff/CoherentPadOp.h | 152 + .../Eigen/src/AutoDiff/InternalHeaderCheck.h | 3 + .../unsupported/Eigen/src/BVH/BVAlgorithms.h | 291 + .../Eigen/src/BVH/InternalHeaderCheck.h | 3 + .../eigen/unsupported/Eigen/src/BVH/KdBVH.h | 223 + .../ArpackSelfAdjointEigenSolver.h | 699 + .../src/Eigenvalues/InternalHeaderCheck.h | 3 + .../Eigen/src/EulerAngles/CMakeLists.txt | 6 + .../Eigen/src/EulerAngles/EulerAngles.h | 350 + .../Eigen/src/EulerAngles/EulerSystem.h | 283 + .../src/EulerAngles/InternalHeaderCheck.h | 3 + .../Eigen/src/FFT/InternalHeaderCheck.h | 3 + .../unsupported/Eigen/src/FFT/duccfft_impl.h | 71 + .../unsupported/Eigen/src/FFT/fftw_impl.h | 216 + .../unsupported/Eigen/src/FFT/imklfft_impl.h | 248 + .../unsupported/Eigen/src/FFT/kissfft_impl.h | 416 + .../Eigen/src/FFT/pocketfft_impl.h | 67 + .../Eigen/src/IterativeSolvers/BiCGSTABL.h | 339 + .../Eigen/src/IterativeSolvers/DGMRES.h | 490 + .../Eigen/src/IterativeSolvers/GMRES.h | 315 + .../Eigen/src/IterativeSolvers/IDRS.h | 395 + .../Eigen/src/IterativeSolvers/IDRSTABL.h | 476 + .../Eigen/src/IterativeSolvers/IncompleteLU.h | 88 + .../IterativeSolvers/InternalHeaderCheck.h | 4 + .../Eigen/src/IterativeSolvers/MINRES.h | 254 + .../Eigen/src/IterativeSolvers/Scaling.h | 172 + .../KroneckerProduct/InternalHeaderCheck.h | 4 + .../KroneckerProduct/KroneckerTensorProduct.h | 284 + .../LevenbergMarquardt/CopyrightMINPACK.txt | 52 + .../LevenbergMarquardt/InternalHeaderCheck.h | 4 + .../Eigen/src/LevenbergMarquardt/LMcovar.h | 80 + .../Eigen/src/LevenbergMarquardt/LMonestep.h | 187 + .../Eigen/src/LevenbergMarquardt/LMpar.h | 146 + .../Eigen/src/LevenbergMarquardt/LMqrsolv.h | 178 + .../LevenbergMarquardt/LevenbergMarquardt.h | 360 + .../src/MatrixFunctions/InternalHeaderCheck.h | 4 + .../src/MatrixFunctions/MatrixExponential.h | 457 + .../src/MatrixFunctions/MatrixFunction.h | 543 + .../src/MatrixFunctions/MatrixLogarithm.h | 366 + .../Eigen/src/MatrixFunctions/MatrixPower.h | 694 + .../src/MatrixFunctions/MatrixSquareRoot.h | 345 + .../Eigen/src/MatrixFunctions/StemFunction.h | 115 + .../HybridNonLinearSolver.h | 545 + .../InternalHeaderCheck.h | 4 + .../LevenbergMarquardt.h | 587 + .../Eigen/src/NonLinearOptimization/chkder.h | 57 + .../Eigen/src/NonLinearOptimization/covar.h | 66 + .../Eigen/src/NonLinearOptimization/dogleg.h | 103 + .../Eigen/src/NonLinearOptimization/fdjac1.h | 73 + .../Eigen/src/NonLinearOptimization/lmpar.h | 263 + .../Eigen/src/NonLinearOptimization/qrsolv.h | 89 + .../Eigen/src/NonLinearOptimization/r1mpyq.h | 33 + .../Eigen/src/NonLinearOptimization/r1updt.h | 96 + .../Eigen/src/NonLinearOptimization/rwupdt.h | 47 + .../src/NumericalDiff/InternalHeaderCheck.h | 3 + .../Eigen/src/NumericalDiff/NumericalDiff.h | 127 + .../Eigen/src/Polynomials/Companion.h | 255 + .../src/Polynomials/InternalHeaderCheck.h | 3 + .../Eigen/src/Polynomials/PolynomialSolver.h | 387 + .../Eigen/src/Polynomials/PolynomialUtils.h | 144 + .../Eigen/src/SparseExtra/BlockSparseMatrix.h | 931 + .../src/SparseExtra/InternalHeaderCheck.h | 3 + .../Eigen/src/SparseExtra/MarketIO.h | 366 + .../src/SparseExtra/MatrixMarketIterator.h | 217 + .../Eigen/src/SparseExtra/RandomSetter.h | 308 + .../Eigen/src/SparseExtra/SparseInverse.h | 232 + .../BesselFunctionsArrayAPI.h | 276 + .../BesselFunctionsBFloat16.h | 71 + .../BesselFunctionsFunctors.h | 323 + .../SpecialFunctions/BesselFunctionsHalf.h | 69 + .../SpecialFunctions/BesselFunctionsImpl.h | 1638 + .../BesselFunctionsPacketMath.h | 108 + .../SpecialFunctions/HipVectorCompatibility.h | 71 + .../SpecialFunctions/InternalHeaderCheck.h | 4 + .../SpecialFunctionsArrayAPI.h | 159 + .../SpecialFunctionsBFloat16.h | 73 + .../SpecialFunctionsFunctors.h | 326 + .../SpecialFunctions/SpecialFunctionsHalf.h | 73 + .../SpecialFunctions/SpecialFunctionsImpl.h | 2071 ++ .../SpecialFunctionsPacketMath.h | 112 + .../arch/AVX/BesselFunctions.h | 13 + .../arch/AVX/SpecialFunctions.h | 13 + .../arch/AVX512/BesselFunctions.h | 13 + .../arch/AVX512/SpecialFunctions.h | 13 + .../arch/GPU/SpecialFunctions.h | 317 + .../arch/NEON/BesselFunctions.h | 43 + .../arch/NEON/SpecialFunctions.h | 33 + .../Eigen/src/Splines/InternalHeaderCheck.h | 3 + .../unsupported/Eigen/src/Splines/Spline.h | 479 + .../Eigen/src/Splines/SplineFitting.h | 393 + .../unsupported/Eigen/src/Splines/SplineFwd.h | 109 + .../third_party/eigen/unsupported/README.txt | 50 + .../eigen/unsupported/bench/bench_svd.cpp | 111 + .../benchmarks/AutoDiff/CMakeLists.txt | 1 + .../benchmarks/AutoDiff/bench_autodiff.cpp | 177 + .../unsupported/benchmarks/CMakeLists.txt | 35 + .../IterativeSolvers/CMakeLists.txt | 1 + .../bench_iterative_solvers.cpp | 209 + .../KroneckerProduct/CMakeLists.txt | 1 + .../KroneckerProduct/bench_kronecker.cpp | 83 + .../benchmarks/MatrixFunctions/CMakeLists.txt | 3 + .../bench_matrix_exponential.cpp | 52 + .../bench_matrix_logarithm.cpp | 51 + .../MatrixFunctions/bench_matrix_power.cpp | 99 + .../SpecialFunctions/CMakeLists.txt | 1 + .../bench_special_functions.cpp | 127 + .../benchmarks/Splines/CMakeLists.txt | 1 + .../benchmarks/Splines/bench_splines.cpp | 98 + .../benchmarks/Tensor/CMakeLists.txt | 8 + .../benchmarks/Tensor/bench_broadcasting.cpp | 111 + .../Tensor/bench_coefficient_wise.cpp | 131 + .../benchmarks/Tensor/bench_contraction.cpp | 148 + .../benchmarks/Tensor/bench_convolution.cpp | 151 + .../benchmarks/Tensor/bench_morphing.cpp | 142 + .../benchmarks/Tensor/bench_reduction.cpp | 158 + .../benchmarks/Tensor/bench_shuffling.cpp | 115 + .../benchmarks/Tensor/bench_tensor_fft.cpp | 80 + .../eigen/unsupported/doc/CMakeLists.txt | 4 + .../eigen/unsupported/doc/Overview.dox | 31 + .../eigen/unsupported/doc/SYCL.dox | 9 + .../unsupported/doc/eigendoxy_layout.xml.in | 269 + .../unsupported/doc/examples/BVH_Example.cpp | 62 + .../unsupported/doc/examples/CMakeLists.txt | 23 + .../unsupported/doc/examples/EulerAngles.cpp | 44 + .../eigen/unsupported/doc/examples/FFT.cpp | 103 + .../doc/examples/MatrixExponential.cpp | 13 + .../doc/examples/MatrixFunction.cpp | 16 + .../doc/examples/MatrixLogarithm.cpp | 12 + .../unsupported/doc/examples/MatrixPower.cpp | 16 + .../doc/examples/MatrixPower_optimal.cpp | 25 + .../unsupported/doc/examples/MatrixSine.cpp | 19 + .../unsupported/doc/examples/MatrixSinh.cpp | 19 + .../doc/examples/MatrixSquareRoot.cpp | 14 + .../doc/examples/PolynomialSolver1.cpp | 52 + .../doc/examples/PolynomialUtils1.cpp | 22 + .../doc/examples/SYCL/CMakeLists.txt | 31 + .../doc/examples/SYCL/CwiseMul.cpp | 63 + .../unsupported/doc/snippets/CMakeLists.txt | 26 + .../eigen/unsupported/test/BVH.cpp | 247 + .../eigen/unsupported/test/CMakeLists.txt | 359 + .../eigen/unsupported/test/EulerAngles.cpp | 282 + .../eigen/unsupported/test/FFT.cpp | 2 + .../eigen/unsupported/test/FFTW.cpp | 2 + .../eigen/unsupported/test/NNLS.cpp | 471 + .../test/NonLinearOptimization.cpp | 1879 ++ .../eigen/unsupported/test/NumericalDiff.cpp | 102 + .../eigen/unsupported/test/alignedvector3.cpp | 86 + .../eigen/unsupported/test/autodiff.cpp | 348 + .../unsupported/test/autodiff_scalar.cpp | 97 + .../unsupported/test/bessel_functions.cpp | 275 + .../eigen/unsupported/test/bicgstabl.cpp | 30 + .../unsupported/test/cxx11_tensor_argmax.cpp | 289 + .../test/cxx11_tensor_argmax_gpu.cu | 270 + .../test/cxx11_tensor_argmax_sycl.cpp | 258 + .../unsupported/test/cxx11_tensor_assign.cpp | 359 + .../test/cxx11_tensor_block_access.cpp | 523 + .../test/cxx11_tensor_block_eval.cpp | 797 + .../test/cxx11_tensor_block_io.cpp | 432 + .../test/cxx11_tensor_broadcast_sycl.cpp | 140 + .../test/cxx11_tensor_broadcasting.cpp | 312 + .../test/cxx11_tensor_builtins_sycl.cpp | 509 + .../test/cxx11_tensor_cast_float16_gpu.cu | 73 + .../unsupported/test/cxx11_tensor_casts.cpp | 87 + .../test/cxx11_tensor_chipping.cpp | 419 + .../test/cxx11_tensor_chipping_sycl.cpp | 612 + .../test/cxx11_tensor_comparisons.cpp | 192 + .../cxx11_tensor_complex_cwise_ops_gpu.cu | 90 + .../test/cxx11_tensor_complex_gpu.cu | 176 + .../test/cxx11_tensor_concatenation.cpp | 128 + .../test/cxx11_tensor_concatenation_sycl.cpp | 191 + .../unsupported/test/cxx11_tensor_const.cpp | 56 + .../test/cxx11_tensor_contract_gpu.cu | 210 + .../test/cxx11_tensor_contract_sycl.cpp | 846 + .../test/cxx11_tensor_contraction.cpp | 567 + .../test/cxx11_tensor_convolution.cpp | 145 + .../test/cxx11_tensor_convolution_sycl.cpp | 458 + .../test/cxx11_tensor_custom_index.cpp | 83 + .../test/cxx11_tensor_custom_op.cpp | 102 + .../test/cxx11_tensor_custom_op_sycl.cpp | 170 + .../unsupported/test/cxx11_tensor_device.cu | 436 + .../test/cxx11_tensor_device_sycl.cpp | 90 + .../test/cxx11_tensor_dimension.cpp | 82 + .../unsupported/test/cxx11_tensor_empty.cpp | 35 + .../test/cxx11_tensor_executor.cpp | 704 + .../unsupported/test/cxx11_tensor_expr.cpp | 476 + .../unsupported/test/cxx11_tensor_fft.cpp | 296 + .../test/cxx11_tensor_fixed_size.cpp | 263 + .../test/cxx11_tensor_forced_eval.cpp | 75 + .../test/cxx11_tensor_forced_eval_sycl.cpp | 78 + .../test/cxx11_tensor_generator.cpp | 82 + .../test/cxx11_tensor_generator_sycl.cpp | 140 + .../unsupported/test/cxx11_tensor_gpu.cu | 1561 + .../unsupported/test/cxx11_tensor_ifft.cpp | 157 + .../test/cxx11_tensor_image_op_sycl.cpp | 100 + .../test/cxx11_tensor_image_patch.cpp | 811 + .../test/cxx11_tensor_image_patch_sycl.cpp | 1155 + .../test/cxx11_tensor_index_list.cpp | 424 + .../test/cxx11_tensor_inflation.cpp | 75 + .../test/cxx11_tensor_inflation_sycl.cpp | 130 + .../unsupported/test/cxx11_tensor_intdiv.cpp | 135 + .../unsupported/test/cxx11_tensor_io.cpp | 152 + .../test/cxx11_tensor_layout_swap.cpp | 56 + .../test/cxx11_tensor_layout_swap_sycl.cpp | 120 + .../unsupported/test/cxx11_tensor_lvalue.cpp | 36 + .../unsupported/test/cxx11_tensor_map.cpp | 322 + .../unsupported/test/cxx11_tensor_math.cpp | 42 + .../test/cxx11_tensor_math_sycl.cpp | 102 + .../test/cxx11_tensor_mixed_indices.cpp | 53 + .../test/cxx11_tensor_morphing.cpp | 551 + .../test/cxx11_tensor_morphing_sycl.cpp | 371 + .../unsupported/test/cxx11_tensor_move.cpp | 68 + .../test/cxx11_tensor_notification.cpp | 67 + .../test/cxx11_tensor_of_bfloat16_gpu.cu | 461 + .../test/cxx11_tensor_of_complex.cpp | 108 + .../test/cxx11_tensor_of_const_values.cpp | 98 + .../test/cxx11_tensor_of_float16_gpu.cu | 462 + .../test/cxx11_tensor_of_float16_sycl.cpp | 392 + .../test/cxx11_tensor_of_strings.cpp | 141 + .../unsupported/test/cxx11_tensor_padding.cpp | 90 + .../test/cxx11_tensor_padding_sycl.cpp | 148 + .../unsupported/test/cxx11_tensor_patch.cpp | 170 + .../test/cxx11_tensor_patch_sycl.cpp | 249 + .../unsupported/test/cxx11_tensor_random.cpp | 80 + .../test/cxx11_tensor_random_gpu.cu | 78 + .../test/cxx11_tensor_random_sycl.cpp | 84 + .../test/cxx11_tensor_reduction.cpp | 520 + .../test/cxx11_tensor_reduction_gpu.cu | 151 + .../test/cxx11_tensor_reduction_sycl.cpp | 857 + .../unsupported/test/cxx11_tensor_ref.cpp | 243 + .../unsupported/test/cxx11_tensor_reverse.cpp | 179 + .../test/cxx11_tensor_reverse_sycl.cpp | 232 + .../unsupported/test/cxx11_tensor_roll.cpp | 156 + .../test/cxx11_tensor_roundings.cpp | 57 + .../unsupported/test/cxx11_tensor_scan.cpp | 108 + .../unsupported/test/cxx11_tensor_scan_gpu.cu | 72 + .../test/cxx11_tensor_scan_sycl.cpp | 112 + .../test/cxx11_tensor_shuffling.cpp | 270 + .../test/cxx11_tensor_shuffling_sycl.cpp | 114 + .../unsupported/test/cxx11_tensor_simple.cpp | 332 + .../test/cxx11_tensor_striding.cpp | 114 + .../test/cxx11_tensor_striding_sycl.cpp | 193 + .../unsupported/test/cxx11_tensor_sugar.cpp | 78 + .../unsupported/test/cxx11_tensor_sycl.cpp | 348 + .../test/cxx11_tensor_symmetry.cpp | 799 + .../test/cxx11_tensor_thread_local.cpp | 144 + .../test/cxx11_tensor_thread_pool.cpp | 776 + .../unsupported/test/cxx11_tensor_trace.cpp | 168 + .../unsupported/test/cxx11_tensor_uint128.cpp | 157 + .../test/cxx11_tensor_volume_patch.cpp | 107 + .../test/cxx11_tensor_volume_patch_sycl.cpp | 229 + .../eigen/unsupported/test/dgmres.cpp | 30 + .../eigen/unsupported/test/duccfft.cpp | 4 + .../eigen/unsupported/test/fft_test_shared.h | 311 + .../eigen/unsupported/test/forward_adolc.cpp | 127 + .../eigen/unsupported/test/gmres.cpp | 30 + .../eigen/unsupported/test/idrs.cpp | 26 + .../eigen/unsupported/test/idrstabl.cpp | 28 + .../unsupported/test/kronecker_product.cpp | 242 + .../unsupported/test/levenberg_marquardt.cpp | 1555 + .../unsupported/test/matrix_exponential.cpp | 128 + .../unsupported/test/matrix_function.cpp | 210 + .../eigen/unsupported/test/matrix_functions.h | 56 + .../eigen/unsupported/test/matrix_power.cpp | 197 + .../unsupported/test/matrix_square_root.cpp | 29 + .../eigen/unsupported/test/minres.cpp | 41 + .../eigen/unsupported/test/mklfft.cpp | 2 + .../eigen/unsupported/test/mpreal_support.cpp | 69 + .../eigen/unsupported/test/openglsupport.cpp | 594 + .../eigen/unsupported/test/pocketfft.cpp | 2 + .../unsupported/test/polynomialsolver.cpp | 206 + .../unsupported/test/polynomialutils.cpp | 102 + .../eigen/unsupported/test/sparse_extra.cpp | 254 + .../unsupported/test/special_functions.cpp | 425 + .../unsupported/test/special_packetmath.cpp | 160 + .../eigen/unsupported/test/splines.cpp | 205 + .../third_party/nlohmann/json.hpp | 24765 ++++++++++++++++ python_app/__init__.py | 1 + python_app/docs/README.md | 22 + python_app/docs/architecture_overview.md | 46 + python_app/docs/gui_architecture.md | 43 + python_app/docs/hardware_layer.md | 35 + python_app/docs/module_reference.md | 50 + python_app/docs/operations_runbook.md | 49 + .../preprocessing_and_capture_workflow.md | 32 + python_app/docs/runtime_data_flow.md | 39 + python_app/docs/shm_protocol_and_readers.md | 28 + python_app/docs/storage_formats.md | 41 + python_app/gui/__init__.py | 1 + python_app/gui/app_window.py | 137 + python_app/gui/controllers/__init__.py | 1 + .../controllers/app_window_config_mixin.py | 356 + .../controllers/app_window_pipeline_mixin.py | 380 + .../gui/controllers/app_window_plot_mixin.py | 378 + .../app_window_preprocess_mixin.py | 224 + .../controllers/app_window_snapshot_mixin.py | 119 + .../gui/controllers/app_window_ui_mixin.py | 192 + .../gui/controllers/sections/__init__.py | 19 + .../sections/data_actions_section.py | 46 + .../sections/hardware_actions_section.py | 25 + .../controllers/sections/pipeline_section.py | 34 + .../sections/preprocess_summary_section.py | 19 + .../sections/processing_section.py | 134 + .../gui/controllers/sections/radar_section.py | 51 + .../controllers/sections/switch_section.py | 82 + python_app/gui/main.py | 31 + python_app/gui/plotting/__init__.py | 19 + python_app/gui/plotting/bscan_history.py | 114 + python_app/gui/plotting/bscan_math.py | 37 + python_app/gui/preprocess_dialog.py | 252 + python_app/gui/runtime/__init__.py | 13 + python_app/gui/runtime/constraints.py | 21 + python_app/gui/runtime/history.py | 53 + python_app/gui/theme.py | 125 + python_app/hardware_full/__init__.py | 1 + python_app/hardware_full/librevna_backends.py | 163 + .../hardware_full/librevna_driver/__init__.py | 72 + .../librevna_driver/api/__init__.py | 9 + .../librevna_driver/api/config.py | 54 + .../hardware_full/librevna_driver/api/vna.py | 99 + .../hardware_full/librevna_driver/device.py | 115 + .../hardware_full/librevna_driver/enums.py | 87 + .../librevna_driver/exceptions.py | 39 + .../librevna_driver/logging_utils.py | 52 + .../hardware_full/librevna_driver/models.py | 255 + .../librevna_driver/protocol/__init__.py | 31 + .../librevna_driver/protocol/codec.py | 407 + .../librevna_driver/protocol/crc32.py | 10 + .../librevna_driver/protocol/frame.py | 123 + .../librevna_driver/protocol/structs.py | 89 + .../hardware_full/librevna_driver/session.py | 424 + .../librevna_driver/sweep/__init__.py | 10 + .../librevna_driver/sweep/assembler.py | 181 + .../librevna_driver/transport/__init__.py | 5 + .../librevna_driver/transport/usb.py | 244 + python_app/hardware_full/librevna_service.py | 98 + .../hardware_full/switch_drivers/__init__.py | 13 + .../hardware_full/switch_drivers/gpio_uapi.py | 200 + .../switch_drivers/h7992_driver.py | 86 + .../switch_drivers/hmc349a_driver.py | 84 + .../hardware_full/switch_drivers/interface.py | 25 + .../switch_drivers/mock_driver.py | 55 + python_app/hardware_full/switch_service.py | 85 + python_app/models/__init__.py | 1 + python_app/models/dataset_model.py | 61 + python_app/models/run_config_codec.py | 177 + python_app/models/run_config_model.py | 39 + python_app/models/run_config_schema.py | 146 + python_app/models/run_config_validation.py | 62 + python_app/orchestration/__init__.py | 1 + python_app/orchestration/config_writer.py | 42 + .../orchestration/live_processing_config.py | 61 + .../orchestration/process_supervisor.py | 202 + python_app/orchestration/shm/__init__.py | 21 + python_app/orchestration/shm/binary_cursor.py | 50 + python_app/orchestration/shm/decoder.py | 114 + python_app/orchestration/shm/ring_reader.py | 150 + python_app/orchestration/shm_reader.py | 21 + python_app/runtime/calibration_bundle.bin | Bin 0 -> 19416 bytes python_app/runtime/reference_bundle.bin | Bin 0 -> 19416 bytes python_app/runtime/run_config_smoke.json | 114 + python_app/scripts/__init__.py | 1 + python_app/scripts/check_snapshot_numpy.py | 298 + .../convert_snapshot_to_vna_history.py | 353 + .../scripts/hardware_raw_orchestrator_test.py | 360 + python_app/scripts/manual_smoke_run.py | 152 + python_app/scripts/vna_only_raw_test.py | 72 + python_app/storage/__init__.py | 1 + python_app/storage/npz/__init__.py | 13 + python_app/storage/npz/paths.py | 52 + python_app/storage/npz/serialize.py | 77 + python_app/storage/npz/snapshot_numpy.py | 225 + python_app/storage/npz/store.py | 204 + python_app/storage/npz_store.py | 21 + python_app/storage/store_api.py | 37 + python_app/workflows/__init__.py | 1 + python_app/workflows/calibration_workflow.py | 81 + python_app/workflows/reference_workflow.py | 81 + .../workflows/sequential_capture_workflow.py | 168 + requirements.txt | 4 + run_config.json | 84 + start.sh | 204 + 964 files changed, 325114 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 data_acq_and_processing/common_cpp/config/include/run_config.hpp create mode 100644 data_acq_and_processing/common_cpp/config/src/run_config.cpp create mode 100644 data_acq_and_processing/common_cpp/ipc/include/shared_types.hpp create mode 100644 data_acq_and_processing/common_cpp/ipc/include/shm_ring.hpp create mode 100644 data_acq_and_processing/common_cpp/ipc/src/shared_types.cpp create mode 100644 data_acq_and_processing/common_cpp/ipc/src/shm_ring.cpp create mode 100644 data_acq_and_processing/preprocessing/calibration_master/include/calibration_master.hpp create mode 100644 data_acq_and_processing/preprocessing/calibration_master/include/calibrator_interface.hpp create mode 100644 data_acq_and_processing/preprocessing/calibration_master/src/calibration_master.cpp create mode 100644 data_acq_and_processing/preprocessing/calibration_master/src/through_calibrator.cpp create mode 100644 data_acq_and_processing/preprocessing/data_preprocessor/include/data_preprocessor.hpp create mode 100644 data_acq_and_processing/preprocessing/data_preprocessor/src/data_preprocessor.cpp create mode 100644 data_acq_and_processing/preprocessing/data_preprocessor/src/main.cpp create mode 100644 data_acq_and_processing/preprocessing/reference_master/include/reference_master.hpp create mode 100644 data_acq_and_processing/preprocessing/reference_master/src/reference_master.cpp create mode 100644 data_acq_and_processing/processing/data_processor/include/data_processor.hpp create mode 100644 data_acq_and_processing/processing/data_processor/include/processing_live_config.hpp create mode 100644 data_acq_and_processing/processing/data_processor/src/data_processor.cpp create mode 100644 data_acq_and_processing/processing/data_processor/src/main.cpp create mode 100644 data_acq_and_processing/processing/data_processor/src/processing_live_config.cpp create mode 100644 data_acq_and_processing/processing/processors/include/bscan_processor.hpp create mode 100644 data_acq_and_processing/processing/processors/include/passthrough_processor.hpp create mode 100644 data_acq_and_processing/processing/processors/include/processor_interface.hpp create mode 100644 data_acq_and_processing/processing/processors/src/bscan_processor.cpp create mode 100644 data_acq_and_processing/processing/processors/src/passthrough_processor.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/radar_driver.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/switch_driver.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_lifecycle.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_protocol.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_transport.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_protocol_common.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna_minimal_driver.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/include/sweep_orchestrator.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/include/sweep_plan.hpp create mode 100644 data_acq_and_processing/sweep_orchestrator/src/main.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/src/sweep_orchestrator.cpp create mode 100644 data_acq_and_processing/sweep_orchestrator/src/sweep_plan.cpp create mode 100644 data_acq_and_processing/third_party/eigen/COPYING.APACHE create mode 100644 data_acq_and_processing/third_party/eigen/COPYING.BSD create mode 100644 data_acq_and_processing/third_party/eigen/COPYING.MINPACK create mode 100644 data_acq_and_processing/third_party/eigen/COPYING.MPL2 create mode 100644 data_acq_and_processing/third_party/eigen/COPYING.README create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/AccelerateSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Cholesky create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/CholmodSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Core create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Dense create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Eigen create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Eigenvalues create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Geometry create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Householder create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/IterativeLinearSolvers create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Jacobi create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/KLUSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/LU create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/MetisSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/OrderingMethods create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/PaStiXSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/PardisoSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/QR create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/QtAlignedMalloc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SPQRSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SVD create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Sparse create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SparseCholesky create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SparseCore create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SparseLU create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SparseQR create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/StdDeque create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/StdList create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/StdVector create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/SuperLUSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/ThreadPool create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/UmfPackSupport create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/Version create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/AccelerateSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LDLT.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/CholmodSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArithmeticSequence.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Array.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayWrapper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/AssignEvaluator.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_AOCL.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_MKL.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/BandMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Block.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CommaInitializer.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ConditionEstimator.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreEvaluators.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreIterators.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseBinaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseNullaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseTernaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseCoeffsBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseStorage.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DeviceWrapper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Diagonal.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Dot.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/EigenBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fill.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/FindCoeff.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ForceAlignedAccess.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fuzzy.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/GeneralProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/GenericPacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/GlobalFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/IO.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/IndexedView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/InnerProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Inverse.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Map.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/MapBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctionsImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Matrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/MatrixBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/NestByValue.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/NoAlias.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/NumTraits.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/PartialReduxEvaluator.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/PermutationMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/PlainObjectBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Product.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ProductEvaluators.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Random.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/RandomImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/RealView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Redux.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Ref.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Replicate.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reshaped.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/ReturnByValue.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reverse.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Select.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfAdjointView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/SkewSymmetricMatrix3.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Solve.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolveTriangular.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolverBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/StableNorm.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/StlIterators.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Stride.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Swap.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpose.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpositions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/TriangularMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorBlock.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorwiseOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/Visitor.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX/Reductions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/GemmKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/MathFunctionsFP16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/PacketMathFP16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/Reductions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/TrsmKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/TrsmUnrolls.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AVX512/TypeCastingFP16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MatrixProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductCommon.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MatrixProductMMAbfloat16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/MatrixVectorProduct.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/AltiVec/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/BFloat16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/ConjHelper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathComplex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathDoubleWord.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathFrexpLdexp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathFunctionsFwd.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathPolynomials.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathPow.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/GenericPacketMathTrig.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/Half.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/Default/Settings.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/GPU/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/GPU/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/GPU/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/GPU/Tuple.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/GPU/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/HIP/hcc/math_constants.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/HVX/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/LSX/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/LSX/GeneralBlockPanelKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/LSX/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/LSX/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/LSX/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/MSA/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/MSA/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/MSA/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/GeneralBlockPanelKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/NEON/UnaryFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/GeneralBlockPanelKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/PacketMath2.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/PacketMath4.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/PacketMathBF16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/PacketMathFP16.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/RVV10/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SSE/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SSE/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SSE/Reductions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SVE/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SVE/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SVE/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SYCL/InteropHeaders.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SYCL/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SYCL/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/SYCL/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/ZVector/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/clang/Complex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/clang/MathFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/clang/PacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/clang/Reductions.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/arch/clang/TypeCasting.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/AssignmentFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/BinaryFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/NullaryFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/StlFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/TernaryFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/functors/UnaryFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/Parallelizer.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularMatrixVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/products/TriangularSolverVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/AOCL_Support.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Assert.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/BlasUtil.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/ConfigureVectorization.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Constants.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/DisableStupidWarnings.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/EmulateArray.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/ForwardDeclarations.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/GpuHipCudaDefines.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/GpuHipCudaUndefines.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/IndexedViewHelper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/IntegralConstant.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/MKL_support.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Macros.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/MaxSizeVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Memory.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Meta.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/MoreMeta.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/ReshapedHelper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/Serializer.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/StaticAssert.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/SymbolicIndex.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Core/util/XprHelper.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/ComplexQZ.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/ComplexSchur.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/EigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/RealQZ.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/RealSchur.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/AlignedBox.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/AngleAxis.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/EulerAngles.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Homogeneous.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Hyperplane.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/OrthoMethods.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/ParametrizedLine.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Quaternion.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Rotation2D.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/RotationBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Scaling.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Transform.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Translation.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/Umeyama.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Geometry/arch/Geometry_SIMD.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Householder/BlockHouseholder.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Householder/Householder.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Householder/HouseholderSequence.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Householder/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Jacobi/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/Jacobi/Jacobi.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/KLUSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/KLUSupport/KLUSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/Determinant.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/FullPivLU.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/InverseImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/PartialPivLU.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/LU/arch/InverseSize4.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/MetisSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/MetisSupport/MetisSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/OrderingMethods/Amd.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/OrderingMethods/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/OrderingMethods/Ordering.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/PaStiXSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/PardisoSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/PardisoSupport/PardisoSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/ColPivHouseholderQR.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/FullPivHouseholderQR.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/HouseholderQR.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/QR/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SPQRSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/BDCSVD.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/BDCSVD_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/JacobiSVD.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/SVDBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SVD/UpperBidiagonalization.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCholesky/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/AmbiVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/CompressedStorage.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseAssign.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseBlock.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseColEtree.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseCompressedBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseDenseProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseDot.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseFuzzy.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseMap.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseMatrixBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparsePermutation.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseRedux.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseRef.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseSolverBase.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseTranspose.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseTriangularView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseUtil.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/SparseView.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseCore/TriangularSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLUImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_Memory.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_Structs.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_Utils.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseQR/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SparseQR/SparseQR.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/StlSupport/StdDeque.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/StlSupport/StdList.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/StlSupport/StdVector.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/StlSupport/details.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SuperLUSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/Barrier.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/CoreThreadPoolDevice.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/EventCount.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ForkJoin.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/NonBlockingThreadPool.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/RunQueue.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ThreadCancel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ThreadEnvironment.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ThreadLocal.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ThreadPoolInterface.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/ThreadPool/ThreadYield.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/UmfPackSupport/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/Image.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/Kernel.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/blas.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/lapacke.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/lapacke_helpers.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/misc/lapacke_mangling.h create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/BlockMethods.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/IndexedViewMethods.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/InternalHeaderCheck.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.inc create mode 100644 data_acq_and_processing/third_party/eigen/Eigen/src/plugins/ReshapedMethods.inc create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/AdolcForward create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/AlignedVector3 create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/ArpackSupport create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/AutoDiff create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/BVH create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/Tensor create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/TensorSymmetry create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/ThreadPool create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/README.md create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/Tensor.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorArgMax.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorAssign.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorBlock.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorBroadcasting.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorChipping.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorConcatenation.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContraction.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionBlocking.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionCuda.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionGpu.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionMapper.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionSycl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorContractionThreadPool.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorConversion.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorConvolution.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorConvolutionSycl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorCostModel.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorCustomOp.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceCuda.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceDefault.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceGpu.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceSycl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceThreadPool.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDimensionList.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorDimensions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorEvalTo.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorExpr.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorFixedSize.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorForcedEval.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorGenerator.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorGlobalFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorIO.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorImagePatch.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorIndexList.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorInflation.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorInitializer.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorIntDiv.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorLayoutSwap.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorMacros.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorMap.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorPadding.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorPatch.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorRandom.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorReduction.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorReductionGpu.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorReductionSycl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorRef.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorReverse.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorRoll.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorScan.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorScanSycl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorShuffling.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorStriding.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorTrace.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorTraits.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorUInt128.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorVolumePatch.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/TensorSymmetry/DynamicSymmetry.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/TensorSymmetry/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/TensorSymmetry/StaticSymmetry.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/TensorSymmetry/Symmetry.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/TensorSymmetry/util/TemplateGroupTheory.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/util/CXX11Meta.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/CXX11/src/util/CXX11Workarounds.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/EulerAngles create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/FFT create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/IterativeSolvers create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/KroneckerProduct create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/LevenbergMarquardt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/MPRealSupport create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/MatrixFunctions create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/NNLS create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/NonLinearOptimization create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/NumericalDiff create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/OpenGLSupport create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/Polynomials create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/SparseExtra create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/SpecialFunctions create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/Splines create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/AutoDiff/CoherentPadOp.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/AutoDiff/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/BVH/BVAlgorithms.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/BVH/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/BVH/KdBVH.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Eigenvalues/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/EulerAngles/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/EulerAngles/EulerAngles.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/EulerAngles/EulerSystem.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/EulerAngles/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/duccfft_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/fftw_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/imklfft_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/kissfft_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/FFT/pocketfft_impl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/BiCGSTABL.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/DGMRES.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/GMRES.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/IDRS.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/IDRSTABL.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/IncompleteLU.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/MINRES.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/IterativeSolvers/Scaling.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/KroneckerProduct/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/MatrixFunctions/StemFunction.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/chkder.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/covar.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/dogleg.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/lmpar.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/r1updt.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NumericalDiff/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Polynomials/Companion.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Polynomials/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Polynomials/PolynomialSolver.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Polynomials/PolynomialUtils.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/BlockSparseMatrix.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/MarketIO.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/RandomSetter.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SparseExtra/SparseInverse.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsArrayAPI.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsBFloat16.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsHalf.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsPacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/HipVectorCompatibility.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsBFloat16.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/AVX/BesselFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/AVX/SpecialFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/AVX512/BesselFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/AVX512/SpecialFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/GPU/SpecialFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/NEON/BesselFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/SpecialFunctions/arch/NEON/SpecialFunctions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Splines/InternalHeaderCheck.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Splines/Spline.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Splines/SplineFitting.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/Eigen/src/Splines/SplineFwd.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/README.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/bench/bench_svd.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/AutoDiff/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/AutoDiff/bench_autodiff.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/IterativeSolvers/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/IterativeSolvers/bench_iterative_solvers.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/KroneckerProduct/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/KroneckerProduct/bench_kronecker.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/MatrixFunctions/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/MatrixFunctions/bench_matrix_power.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/SpecialFunctions/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/SpecialFunctions/bench_special_functions.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Splines/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Splines/bench_splines.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_broadcasting.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_coefficient_wise.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_contraction.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_convolution.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_morphing.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_reduction.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_shuffling.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/benchmarks/Tensor/bench_tensor_fft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/Overview.dox create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/SYCL.dox create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/eigendoxy_layout.xml.in create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/BVH_Example.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/EulerAngles.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/FFT.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixExponential.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixFunction.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixLogarithm.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixPower.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixPower_optimal.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixSine.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixSinh.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/MatrixSquareRoot.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/PolynomialSolver1.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/PolynomialUtils1.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/SYCL/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/examples/SYCL/CwiseMul.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/doc/snippets/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/BVH.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/CMakeLists.txt create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/EulerAngles.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/FFT.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/FFTW.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/NNLS.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/NonLinearOptimization.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/NumericalDiff.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/alignedvector3.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/autodiff.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/autodiff_scalar.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/bessel_functions.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/bicgstabl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_argmax.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_argmax_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_argmax_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_assign.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_block_access.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_block_eval.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_block_io.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_broadcast_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_broadcasting.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_builtins_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_cast_float16_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_casts.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_chipping.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_chipping_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_comparisons.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_complex_cwise_ops_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_complex_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_concatenation.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_concatenation_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_const.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_contract_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_contract_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_contraction.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_convolution.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_convolution_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_custom_index.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_custom_op.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_custom_op_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_device.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_device_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_dimension.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_empty.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_executor.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_expr.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_fft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_fixed_size.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_forced_eval.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_forced_eval_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_generator.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_generator_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_ifft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_image_op_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_image_patch.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_image_patch_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_index_list.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_inflation.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_inflation_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_intdiv.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_io.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_layout_swap.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_layout_swap_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_lvalue.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_map.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_math.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_math_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_mixed_indices.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_morphing.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_morphing_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_move.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_notification.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_bfloat16_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_complex.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_const_values.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_float16_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_float16_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_of_strings.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_padding.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_padding_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_patch.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_patch_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_random.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_random_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_random_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_reduction.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_reduction_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_reduction_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_ref.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_reverse.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_reverse_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_roll.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_roundings.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_scan.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_scan_gpu.cu create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_scan_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_shuffling.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_shuffling_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_simple.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_striding.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_striding_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_sugar.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_symmetry.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_thread_local.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_thread_pool.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_trace.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_uint128.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_volume_patch.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/cxx11_tensor_volume_patch_sycl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/dgmres.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/duccfft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/fft_test_shared.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/forward_adolc.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/gmres.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/idrs.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/idrstabl.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/kronecker_product.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/levenberg_marquardt.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/matrix_exponential.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/matrix_function.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/matrix_functions.h create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/matrix_power.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/matrix_square_root.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/minres.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/mklfft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/mpreal_support.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/openglsupport.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/pocketfft.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/polynomialsolver.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/polynomialutils.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/sparse_extra.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/special_functions.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/special_packetmath.cpp create mode 100644 data_acq_and_processing/third_party/eigen/unsupported/test/splines.cpp create mode 100644 data_acq_and_processing/third_party/nlohmann/json.hpp create mode 100644 python_app/__init__.py create mode 100644 python_app/docs/README.md create mode 100644 python_app/docs/architecture_overview.md create mode 100644 python_app/docs/gui_architecture.md create mode 100644 python_app/docs/hardware_layer.md create mode 100644 python_app/docs/module_reference.md create mode 100644 python_app/docs/operations_runbook.md create mode 100644 python_app/docs/preprocessing_and_capture_workflow.md create mode 100644 python_app/docs/runtime_data_flow.md create mode 100644 python_app/docs/shm_protocol_and_readers.md create mode 100644 python_app/docs/storage_formats.md create mode 100644 python_app/gui/__init__.py create mode 100644 python_app/gui/app_window.py create mode 100644 python_app/gui/controllers/__init__.py create mode 100644 python_app/gui/controllers/app_window_config_mixin.py create mode 100644 python_app/gui/controllers/app_window_pipeline_mixin.py create mode 100644 python_app/gui/controllers/app_window_plot_mixin.py create mode 100644 python_app/gui/controllers/app_window_preprocess_mixin.py create mode 100644 python_app/gui/controllers/app_window_snapshot_mixin.py create mode 100644 python_app/gui/controllers/app_window_ui_mixin.py create mode 100644 python_app/gui/controllers/sections/__init__.py create mode 100644 python_app/gui/controllers/sections/data_actions_section.py create mode 100644 python_app/gui/controllers/sections/hardware_actions_section.py create mode 100644 python_app/gui/controllers/sections/pipeline_section.py create mode 100644 python_app/gui/controllers/sections/preprocess_summary_section.py create mode 100644 python_app/gui/controllers/sections/processing_section.py create mode 100644 python_app/gui/controllers/sections/radar_section.py create mode 100644 python_app/gui/controllers/sections/switch_section.py create mode 100644 python_app/gui/main.py create mode 100644 python_app/gui/plotting/__init__.py create mode 100644 python_app/gui/plotting/bscan_history.py create mode 100644 python_app/gui/plotting/bscan_math.py create mode 100644 python_app/gui/preprocess_dialog.py create mode 100644 python_app/gui/runtime/__init__.py create mode 100644 python_app/gui/runtime/constraints.py create mode 100644 python_app/gui/runtime/history.py create mode 100644 python_app/gui/theme.py create mode 100644 python_app/hardware_full/__init__.py create mode 100644 python_app/hardware_full/librevna_backends.py create mode 100644 python_app/hardware_full/librevna_driver/__init__.py create mode 100644 python_app/hardware_full/librevna_driver/api/__init__.py create mode 100644 python_app/hardware_full/librevna_driver/api/config.py create mode 100644 python_app/hardware_full/librevna_driver/api/vna.py create mode 100644 python_app/hardware_full/librevna_driver/device.py create mode 100644 python_app/hardware_full/librevna_driver/enums.py create mode 100644 python_app/hardware_full/librevna_driver/exceptions.py create mode 100644 python_app/hardware_full/librevna_driver/logging_utils.py create mode 100644 python_app/hardware_full/librevna_driver/models.py create mode 100644 python_app/hardware_full/librevna_driver/protocol/__init__.py create mode 100644 python_app/hardware_full/librevna_driver/protocol/codec.py create mode 100644 python_app/hardware_full/librevna_driver/protocol/crc32.py create mode 100644 python_app/hardware_full/librevna_driver/protocol/frame.py create mode 100644 python_app/hardware_full/librevna_driver/protocol/structs.py create mode 100644 python_app/hardware_full/librevna_driver/session.py create mode 100644 python_app/hardware_full/librevna_driver/sweep/__init__.py create mode 100644 python_app/hardware_full/librevna_driver/sweep/assembler.py create mode 100644 python_app/hardware_full/librevna_driver/transport/__init__.py create mode 100644 python_app/hardware_full/librevna_driver/transport/usb.py create mode 100644 python_app/hardware_full/librevna_service.py create mode 100644 python_app/hardware_full/switch_drivers/__init__.py create mode 100644 python_app/hardware_full/switch_drivers/gpio_uapi.py create mode 100644 python_app/hardware_full/switch_drivers/h7992_driver.py create mode 100644 python_app/hardware_full/switch_drivers/hmc349a_driver.py create mode 100644 python_app/hardware_full/switch_drivers/interface.py create mode 100644 python_app/hardware_full/switch_drivers/mock_driver.py create mode 100644 python_app/hardware_full/switch_service.py create mode 100644 python_app/models/__init__.py create mode 100644 python_app/models/dataset_model.py create mode 100644 python_app/models/run_config_codec.py create mode 100644 python_app/models/run_config_model.py create mode 100644 python_app/models/run_config_schema.py create mode 100644 python_app/models/run_config_validation.py create mode 100644 python_app/orchestration/__init__.py create mode 100644 python_app/orchestration/config_writer.py create mode 100644 python_app/orchestration/live_processing_config.py create mode 100644 python_app/orchestration/process_supervisor.py create mode 100644 python_app/orchestration/shm/__init__.py create mode 100644 python_app/orchestration/shm/binary_cursor.py create mode 100644 python_app/orchestration/shm/decoder.py create mode 100644 python_app/orchestration/shm/ring_reader.py create mode 100644 python_app/orchestration/shm_reader.py create mode 100644 python_app/runtime/calibration_bundle.bin create mode 100644 python_app/runtime/reference_bundle.bin create mode 100644 python_app/runtime/run_config_smoke.json create mode 100644 python_app/scripts/__init__.py create mode 100644 python_app/scripts/check_snapshot_numpy.py create mode 100644 python_app/scripts/convert_snapshot_to_vna_history.py create mode 100644 python_app/scripts/hardware_raw_orchestrator_test.py create mode 100644 python_app/scripts/manual_smoke_run.py create mode 100644 python_app/scripts/vna_only_raw_test.py create mode 100644 python_app/storage/__init__.py create mode 100644 python_app/storage/npz/__init__.py create mode 100644 python_app/storage/npz/paths.py create mode 100644 python_app/storage/npz/serialize.py create mode 100644 python_app/storage/npz/snapshot_numpy.py create mode 100644 python_app/storage/npz/store.py create mode 100644 python_app/storage/npz_store.py create mode 100644 python_app/storage/store_api.py create mode 100644 python_app/workflows/__init__.py create mode 100644 python_app/workflows/calibration_workflow.py create mode 100644 python_app/workflows/reference_workflow.py create mode 100644 python_app/workflows/sequential_capture_workflow.py create mode 100644 requirements.txt create mode 100644 run_config.json create mode 100755 start.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c7e674 --- /dev/null +++ b/.gitignore @@ -0,0 +1,221 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class +build* +# C extensions +*.so +*.npy +snapshots/ +test_results* +meta.json +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ +tests/artifacts/ +tests/tests/artifacts/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..75d2816 --- /dev/null +++ b/Makefile @@ -0,0 +1,83 @@ +CXX := g++ +CXXFLAGS := -std=c++20 -O2 -Wall -Wextra -Wpedantic -pthread +LDFLAGS := -pthread -lrt +ORCH_LDFLAGS := $(LDFLAGS) -lusb-1.0 + +BUILD_DIR := build +BIN_DIR := $(BUILD_DIR)/bin + +INCLUDES := \ + -Idata_acq_and_processing/common_cpp/ipc/include \ + -Idata_acq_and_processing/common_cpp/config/include \ + -Idata_acq_and_processing/third_party \ + -Idata_acq_and_processing/third_party/eigen \ + -Idata_acq_and_processing/sweep_orchestrator/include \ + -Idata_acq_and_processing/sweep_orchestrator/device_drivers/interfaces \ + -Idata_acq_and_processing/sweep_orchestrator/device_drivers/radar \ + -Idata_acq_and_processing/sweep_orchestrator/device_drivers/switches \ + -Idata_acq_and_processing/preprocessing/calibration_master/include \ + -Idata_acq_and_processing/preprocessing/reference_master/include \ + -Idata_acq_and_processing/preprocessing/data_preprocessor/include \ + -Idata_acq_and_processing/processing/processors/include \ + -Idata_acq_and_processing/processing/data_processor/include + +COMMON_SOURCES := \ + data_acq_and_processing/common_cpp/ipc/src/shm_ring.cpp \ + data_acq_and_processing/common_cpp/ipc/src/shared_types.cpp \ + data_acq_and_processing/common_cpp/config/src/run_config.cpp + +ORCH_SOURCES := \ + data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_lifecycle.cpp \ + data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_transport.cpp \ + data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_protocol.cpp \ + data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.cpp \ + data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.cpp \ + data_acq_and_processing/sweep_orchestrator/src/sweep_plan.cpp \ + data_acq_and_processing/sweep_orchestrator/src/sweep_orchestrator.cpp \ + data_acq_and_processing/sweep_orchestrator/src/main.cpp + +PREPROC_SOURCES := \ + data_acq_and_processing/preprocessing/calibration_master/src/calibration_master.cpp \ + data_acq_and_processing/preprocessing/calibration_master/src/through_calibrator.cpp \ + data_acq_and_processing/preprocessing/reference_master/src/reference_master.cpp \ + data_acq_and_processing/preprocessing/data_preprocessor/src/data_preprocessor.cpp \ + data_acq_and_processing/preprocessing/data_preprocessor/src/main.cpp + +PROCESSOR_SOURCES := \ + data_acq_and_processing/processing/processors/src/bscan_processor.cpp \ + data_acq_and_processing/processing/processors/src/passthrough_processor.cpp \ + data_acq_and_processing/processing/data_processor/src/processing_live_config.cpp \ + data_acq_and_processing/processing/data_processor/src/data_processor.cpp \ + data_acq_and_processing/processing/data_processor/src/main.cpp + +SWEEP_ORCH_OBJS := $(addprefix $(BUILD_DIR)/,$(COMMON_SOURCES:.cpp=.o) $(ORCH_SOURCES:.cpp=.o)) +PREPROCESSOR_OBJS := $(addprefix $(BUILD_DIR)/,$(COMMON_SOURCES:.cpp=.o) $(PREPROC_SOURCES:.cpp=.o)) +DATA_PROCESSOR_OBJS := $(addprefix $(BUILD_DIR)/,$(COMMON_SOURCES:.cpp=.o) $(PROCESSOR_SOURCES:.cpp=.o)) + +TARGETS := \ + $(BIN_DIR)/sweep_orchestrator \ + $(BIN_DIR)/data_preprocessor \ + $(BIN_DIR)/data_processor + +.PHONY: all clean + +all: $(TARGETS) + +$(BIN_DIR)/sweep_orchestrator: $(SWEEP_ORCH_OBJS) + @mkdir -p $(BIN_DIR) + $(CXX) $(SWEEP_ORCH_OBJS) -o $@ $(ORCH_LDFLAGS) + +$(BIN_DIR)/data_preprocessor: $(PREPROCESSOR_OBJS) + @mkdir -p $(BIN_DIR) + $(CXX) $(PREPROCESSOR_OBJS) -o $@ $(LDFLAGS) + +$(BIN_DIR)/data_processor: $(DATA_PROCESSOR_OBJS) + @mkdir -p $(BIN_DIR) + $(CXX) $(DATA_PROCESSOR_OBJS) -o $@ $(LDFLAGS) + +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ + +clean: + rm -rf $(BUILD_DIR) diff --git a/data_acq_and_processing/common_cpp/config/include/run_config.hpp b/data_acq_and_processing/common_cpp/config/include/run_config.hpp new file mode 100644 index 0000000..3728db3 --- /dev/null +++ b/data_acq_and_processing/common_cpp/config/include/run_config.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include +#include +#include + +#include "shared_types.hpp" + +namespace radar::config { + +enum class DriverMode { + Mock, + Native, +}; + +enum class SwitchDriverKind { + H7992, + HMC349A, +}; + +struct RadarSweepSettings { + // Frequency sweep bounds and acquisition settings. + float start_hz = 1'000'000.0F; + float stop_hz = 6'000'000'000.0F; + std::uint32_t points = 501; + float if_bandwidth_hz = 1'000.0F; + float power_dbm = -10.0F; +}; + +struct RadarConfig { + // Radar device identity and runtime mode. + std::string model = "librevna"; + std::string serial{}; + DriverMode driver_mode = DriverMode::Mock; + float mock_signal_hz = 5'000'000.0F; + RadarSweepSettings sweep{}; +}; + +struct SwitchConfig { + // One RF switch attached to a specific radar port. + std::string name{}; + DriverMode driver_mode = DriverMode::Mock; + SwitchDriverKind driver_kind = SwitchDriverKind::H7992; + std::uint32_t radar_port = 0; + std::uint32_t positions = 4; + std::uint32_t default_position = 0; + std::string gpio_chip = "/dev/gpiochip0"; + std::int32_t pin_a = 17; + std::int32_t pin_b = 27; + bool invert_logic = false; +}; + +struct RingEndpointConfig { + // Shared-memory endpoint geometry. + std::string name{}; + std::uint32_t capacity = 32; + std::uint32_t slot_size_bytes = 2U * 1024U * 1024U; +}; + +struct RingsConfig { + RingEndpointConfig raw{.name = "/radar_raw"}; + RingEndpointConfig raw_tap{.name = "/radar_raw_tap"}; + RingEndpointConfig preprocessed{.name = "/radar_preprocessed"}; + RingEndpointConfig preprocessed_tap{.name = "/radar_preprocessed_tap"}; + RingEndpointConfig results{.name = "/radar_results"}; +}; + +struct RuntimeConfig { + // Runtime pacing and behavior flags for C++ workers. + std::uint32_t settling_ms = 0; + std::uint32_t idle_sleep_ms = 2; + bool continuous = true; + std::string processing_live_config_path = "python_app/runtime/processing_live.json"; +}; + +struct PreprocessConfig { + // Names and bundle paths selected by Python GUI layer. + std::string calibration_set{}; + std::string reference_set{}; + std::string calibration_bundle_path{}; + std::string reference_bundle_path{}; +}; + +struct RunConfig { + // Single configuration object shared by all C++ processes. + RadarConfig radar{}; + SwitchConfig input_switch{}; + SwitchConfig output_switch{}; + RingsConfig rings{}; + RuntimeConfig runtime{}; + PreprocessConfig preprocess{}; + std::vector run_combos{}; +}; + +[[nodiscard]] auto load_run_config(const std::string& path) -> RunConfig; + +} // namespace radar::config diff --git a/data_acq_and_processing/common_cpp/config/src/run_config.cpp b/data_acq_and_processing/common_cpp/config/src/run_config.cpp new file mode 100644 index 0000000..9d8cae9 --- /dev/null +++ b/data_acq_and_processing/common_cpp/config/src/run_config.cpp @@ -0,0 +1,398 @@ +#include "run_config.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace radar::config { +namespace { + +using Json = nlohmann::json; + +[[nodiscard]] auto required_field(const Json& object, const std::string& key) -> const Json& { + const auto found = object.find(key); + if (found == object.end()) { + throw std::runtime_error("Missing required config field: " + key); + } + return *found; +} + +[[nodiscard]] auto optional_field(const Json& object, const std::string& key) -> const Json* { + const auto found = object.find(key); + if (found == object.end()) { + return nullptr; + } + return &(*found); +} + +[[nodiscard]] auto as_object(const Json& value, const std::string& context) -> const Json* { + if (!value.is_object()) { + throw std::runtime_error("Expected JSON object at " + context); + } + return &value; +} + +[[nodiscard]] auto as_array(const Json& value, const std::string& context) -> const Json* { + if (!value.is_array()) { + throw std::runtime_error("Expected JSON array at " + context); + } + return &value; +} + +[[nodiscard]] auto as_string(const Json& value, const std::string& context) -> const std::string& { + if (!value.is_string()) { + throw std::runtime_error("Expected JSON string at " + context); + } + return value.get_ref(); +} + +[[nodiscard]] auto as_bool(const Json& value, const std::string& context) -> bool { + if (!value.is_boolean()) { + throw std::runtime_error("Expected JSON bool at " + context); + } + return value.get(); +} + +[[nodiscard]] auto as_number(const Json& value, const std::string& context) -> double { + if (!value.is_number()) { + throw std::runtime_error("Expected JSON number at " + context); + } + return value.get(); +} + +[[nodiscard]] auto number_to_u32(double value, const std::string& context) -> std::uint32_t { + if (value < 0.0 || value > static_cast(std::numeric_limits::max())) { + throw std::runtime_error("Value out of uint32 range at " + context); + } + + const auto rounded = std::round(value); + if (std::fabs(value - rounded) > 0.000001) { + throw std::runtime_error("Expected integer value at " + context); + } + return static_cast(rounded); +} + +[[nodiscard]] auto number_to_i32(double value, const std::string& context) -> std::int32_t { + const auto rounded = std::round(value); + if (std::fabs(value - rounded) > 0.000001) { + throw std::runtime_error("Expected integer value at " + context); + } + + if (rounded < static_cast(std::numeric_limits::min()) || + rounded > static_cast(std::numeric_limits::max())) { + throw std::runtime_error("Value out of int32 range at " + context); + } + return static_cast(rounded); +} + +[[nodiscard]] auto optional_string( + const Json& object, + const std::string& key, + const std::string& fallback +) -> std::string { + if (const auto* value = optional_field(object, key); value != nullptr) { + return as_string(*value, key); + } + return fallback; +} + +[[nodiscard]] auto optional_bool(const Json& object, const std::string& key, bool fallback) -> bool { + if (const auto* value = optional_field(object, key); value != nullptr) { + return as_bool(*value, key); + } + return fallback; +} + +[[nodiscard]] auto optional_u32( + const Json& object, + const std::string& key, + std::uint32_t fallback +) -> std::uint32_t { + if (const auto* value = optional_field(object, key); value != nullptr) { + return number_to_u32(as_number(*value, key), key); + } + return fallback; +} + +[[nodiscard]] auto optional_i32( + const Json& object, + const std::string& key, + std::int32_t fallback +) -> std::int32_t { + if (const auto* value = optional_field(object, key); value != nullptr) { + return number_to_i32(as_number(*value, key), key); + } + return fallback; +} + +[[nodiscard]] auto optional_f32(const Json& object, const std::string& key, float fallback) -> float { + if (const auto* value = optional_field(object, key); value != nullptr) { + return static_cast(as_number(*value, key)); + } + return fallback; +} + +[[nodiscard]] auto parse_driver_mode(const std::string& value) -> DriverMode { + if (value == "mock") { + return DriverMode::Mock; + } + if (value == "native") { + return DriverMode::Native; + } + throw std::runtime_error("Unsupported driver_mode value: " + value); +} + +[[nodiscard]] auto parse_switch_driver_kind(const std::string& value) -> SwitchDriverKind { + if (value == "h7992") { + return SwitchDriverKind::H7992; + } + if (value == "hmc349a") { + return SwitchDriverKind::HMC349A; + } + throw std::runtime_error("Unsupported switch driver value: " + value); +} + +void validate_radar_sweep(const RadarSweepSettings& sweep) { + if (sweep.points == 0U) { + throw std::runtime_error("radar.sweep.points must be > 0"); + } + if (sweep.stop_hz < sweep.start_hz) { + throw std::runtime_error("radar.sweep.stop_hz must be >= start_hz"); + } +} + +void validate_switch_config(const SwitchConfig& config) { + if (config.radar_port != 1U && config.radar_port != 2U) { + throw std::runtime_error("Switch radar_port must be 1 or 2 for " + config.name); + } + + if (config.positions == 0U) { + throw std::runtime_error("Switch positions must be > 0 for " + config.name); + } + if (config.default_position >= config.positions) { + throw std::runtime_error("Switch default_position is out of range for " + config.name); + } + + if (config.driver_mode != DriverMode::Native) { + return; + } + + if (config.gpio_chip.empty()) { + throw std::runtime_error("gpio_chip is required for native switch mode: " + config.name); + } + + if (config.driver_kind == SwitchDriverKind::H7992) { + if (config.positions > 4U) { + throw std::runtime_error("Native H7992 switch driver supports positions <= 4 for " + config.name); + } + if (config.pin_a < 0 || config.pin_b < 0 || config.pin_a == config.pin_b) { + throw std::runtime_error("pin_a/pin_b are invalid for native H7992 mode: " + config.name); + } + return; + } + + if (config.positions > 2U) { + throw std::runtime_error("Native HMC349A switch driver supports positions <= 2 for " + config.name); + } + if (config.pin_a < 0) { + throw std::runtime_error("pin_a (control) is required for native HMC349A mode: " + config.name); + } +} + +void validate_combo_key(const ipc::ComboKey& key, const RunConfig& config) { + if (key.input_pos >= config.input_switch.positions) { + throw std::runtime_error("run.combos input index out of range"); + } + if (key.output_pos >= config.output_switch.positions) { + throw std::runtime_error("run.combos output index out of range"); + } +} + +[[nodiscard]] auto parse_switch_config( + const Json& object, + const std::string& default_name, + std::uint32_t default_radar_port +) -> SwitchConfig { + const auto* switch_obj = as_object(object, default_name); + + SwitchConfig config{}; + config.name = optional_string(*switch_obj, "name", default_name); + config.driver_mode = parse_driver_mode(optional_string(*switch_obj, "driver_mode", "mock")); + config.driver_kind = parse_switch_driver_kind(optional_string(*switch_obj, "driver", "h7992")); + config.radar_port = optional_u32(*switch_obj, "radar_port", default_radar_port); + config.positions = optional_u32(*switch_obj, "positions", 4); + config.default_position = optional_u32(*switch_obj, "default_position", 0); + config.gpio_chip = optional_string(*switch_obj, "gpio_chip", "/dev/gpiochip0"); + config.pin_a = optional_i32(*switch_obj, "pin_a", 17); + config.pin_b = optional_i32(*switch_obj, "pin_b", 27); + config.invert_logic = optional_bool(*switch_obj, "invert_logic", false); + + validate_switch_config(config); + + return config; +} + +[[nodiscard]] auto parse_ring_endpoint( + const Json& object, + const std::string& key, + const RingEndpointConfig& fallback +) -> RingEndpointConfig { + RingEndpointConfig endpoint = fallback; + const auto* value = optional_field(object, key); + if (value == nullptr) { + return endpoint; + } + + const auto* endpoint_obj = as_object(*value, key); + endpoint.name = optional_string(*endpoint_obj, "name", endpoint.name); + endpoint.capacity = optional_u32(*endpoint_obj, "capacity", endpoint.capacity); + endpoint.slot_size_bytes = optional_u32(*endpoint_obj, "slot_size_bytes", endpoint.slot_size_bytes); + + if (endpoint.capacity == 0U) { + throw std::runtime_error("Ring capacity must be > 0 for " + key); + } + if (endpoint.slot_size_bytes == 0U) { + throw std::runtime_error("Ring slot_size_bytes must be > 0 for " + key); + } + if (endpoint.name.empty() || endpoint.name.front() != '/') { + throw std::runtime_error("Ring name must start with '/' for " + key); + } + + return endpoint; +} + +} // namespace + +auto load_run_config(const std::string& path) -> RunConfig { + std::ifstream stream(path); + if (!stream.is_open()) { + throw std::runtime_error("Failed to open config file: " + path); + } + + const std::string json_text((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); + if (json_text.empty()) { + throw std::runtime_error("Config file is empty: " + path); + } + + Json root{}; + try { + root = Json::parse(json_text); + } catch (const Json::parse_error& error) { + throw std::runtime_error("Failed to parse config file: " + path + ": " + std::string(error.what())); + } + + const auto* root_obj = as_object(root, "root"); + RunConfig config{}; + + { + const auto* radar_obj = as_object(required_field(*root_obj, "radar"), "radar"); + config.radar.model = optional_string(*radar_obj, "model", "librevna"); + config.radar.serial = optional_string(*radar_obj, "serial", ""); + config.radar.driver_mode = parse_driver_mode(optional_string(*radar_obj, "driver_mode", "mock")); + config.radar.mock_signal_hz = optional_f32(*radar_obj, "mock_signal_hz", 5'000'000.0F); + + const auto* sweep_obj = as_object(required_field(*radar_obj, "sweep"), "radar.sweep"); + config.radar.sweep.start_hz = + static_cast(as_number(required_field(*sweep_obj, "start_hz"), "radar.sweep.start_hz")); + config.radar.sweep.stop_hz = + static_cast(as_number(required_field(*sweep_obj, "stop_hz"), "radar.sweep.stop_hz")); + config.radar.sweep.points = + number_to_u32(as_number(required_field(*sweep_obj, "points"), "radar.sweep.points"), "radar.sweep.points"); + config.radar.sweep.if_bandwidth_hz = static_cast( + as_number(required_field(*sweep_obj, "if_bandwidth_hz"), "radar.sweep.if_bandwidth_hz") + ); + config.radar.sweep.power_dbm = optional_f32(*sweep_obj, "stimulus_power_dbm", -10.0F); + validate_radar_sweep(config.radar.sweep); + } + + { + const auto* switches_obj = as_object(required_field(*root_obj, "switches"), "switches"); + + if (const auto* port1_value = optional_field(*switches_obj, "port1"); port1_value != nullptr) { + const auto* port1_obj = as_object(*port1_value, "switches.port1"); + const auto* port2_obj = as_object(required_field(*switches_obj, "port2"), "switches.port2"); + config.output_switch = parse_switch_config(*port1_obj, "port1", 1); + config.input_switch = parse_switch_config(*port2_obj, "port2", 2); + } else { + config.input_switch = parse_switch_config( + *as_object(required_field(*switches_obj, "input"), "switches.input"), + "input", + 2 + ); + config.output_switch = parse_switch_config( + *as_object(required_field(*switches_obj, "output"), "switches.output"), + "output", + 1 + ); + } + + if (config.input_switch.radar_port == config.output_switch.radar_port) { + throw std::runtime_error("Switch radar_port mapping must be unique for two switches"); + } + } + + { + const auto* run_obj = as_object(required_field(*root_obj, "run"), "run"); + config.runtime.settling_ms = optional_u32(*run_obj, "settling_ms", 0); + config.runtime.idle_sleep_ms = optional_u32(*run_obj, "idle_sleep_ms", 2); + config.runtime.continuous = optional_bool(*run_obj, "continuous", true); + config.runtime.processing_live_config_path = optional_string( + *run_obj, + "processing_live_config_path", + "python_app/runtime/processing_live.json" + ); + + const auto* combos = as_array(required_field(*run_obj, "combos"), "run.combos"); + if (combos->empty()) { + throw std::runtime_error("run.combos must not be empty"); + } + + config.run_combos.reserve(combos->size()); + for (const auto& combo_value : *combos) { + const auto* combo_obj = as_object(combo_value, "run.combos[]"); + + ipc::ComboKey key{}; + key.input_pos = number_to_u32( + as_number(required_field(*combo_obj, "input"), "run.combos.input"), + "run.combos.input" + ); + key.output_pos = number_to_u32( + as_number(required_field(*combo_obj, "output"), "run.combos.output"), + "run.combos.output" + ); + validate_combo_key(key, config); + config.run_combos.push_back(key); + } + } + + { + const auto* preprocess_obj = as_object(required_field(*root_obj, "preprocess"), "preprocess"); + config.preprocess.calibration_set = optional_string(*preprocess_obj, "calibration_set", ""); + config.preprocess.reference_set = optional_string(*preprocess_obj, "reference_set", ""); + config.preprocess.calibration_bundle_path = optional_string(*preprocess_obj, "calibration_bundle_path", ""); + config.preprocess.reference_bundle_path = optional_string(*preprocess_obj, "reference_bundle_path", ""); + } + + { + const auto* rings_obj = as_object(required_field(*root_obj, "rings"), "rings"); + config.rings.raw = parse_ring_endpoint(*rings_obj, "raw", config.rings.raw); + config.rings.raw_tap = parse_ring_endpoint(*rings_obj, "raw_tap", config.rings.raw_tap); + config.rings.preprocessed = parse_ring_endpoint(*rings_obj, "preprocessed", config.rings.preprocessed); + config.rings.preprocessed_tap = parse_ring_endpoint( + *rings_obj, + "preprocessed_tap", + config.rings.preprocessed_tap + ); + config.rings.results = parse_ring_endpoint(*rings_obj, "results", config.rings.results); + } + + return config; +} + +} // namespace radar::config diff --git a/data_acq_and_processing/common_cpp/ipc/include/shared_types.hpp b/data_acq_and_processing/common_cpp/ipc/include/shared_types.hpp new file mode 100644 index 0000000..1118951 --- /dev/null +++ b/data_acq_and_processing/common_cpp/ipc/include/shared_types.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace radar::ipc { + +struct Complex32 { + float re = 0.0F; + float im = 0.0F; +}; + +struct ComboKey { + // Zero-based switch positions. + std::uint32_t input_pos = 0; + std::uint32_t output_pos = 0; + + [[nodiscard]] auto operator==(const ComboKey& other) const -> bool { + return input_pos == other.input_pos && output_pos == other.output_pos; + } +}; + +struct ComboKeyHash { + [[nodiscard]] auto operator()(const ComboKey& key) const noexcept -> std::size_t { + return (static_cast(key.input_pos) << 32U) ^ static_cast(key.output_pos); + } +}; + +struct SweepTraceBlock { + ComboKey combo{}; + // Frequency axis in Hz. Must have the same size as `s21`. + std::vector frequency_hz{}; + // Complex S21 samples for matching frequency points. + std::vector s21{}; +}; + +struct RawSweepCollection { + std::uint64_t collection_id = 0; + std::uint64_t monotonic_ns = 0; + std::vector traces{}; +}; + +using PreprocessedCollection = RawSweepCollection; + +enum class ResultKind : std::uint8_t { + TraceComplex = 1, + ScalarF32 = 2, +}; + +struct ResultPayload { + std::string processing_name{}; + ResultKind kind = ResultKind::TraceComplex; + // Valid for TraceComplex payloads. + std::vector frequency_hz{}; + // Valid for TraceComplex payloads. + std::vector trace{}; + // Valid for ScalarF32 payloads. + float scalar_value = 0.0F; +}; + +struct ResultBlock { + ComboKey combo{}; + std::vector payloads{}; +}; + +struct ResultCollection { + std::uint64_t collection_id = 0; + std::uint64_t monotonic_ns = 0; + std::vector blocks{}; +}; + +// Wire-format serialization helpers for IPC rings. +[[nodiscard]] auto serialize_raw_collection(const RawSweepCollection& collection) -> std::vector; +[[nodiscard]] auto deserialize_raw_collection(std::span bytes) -> RawSweepCollection; + +[[nodiscard]] auto serialize_preprocessed_collection(const PreprocessedCollection& collection) + -> std::vector; +[[nodiscard]] auto deserialize_preprocessed_collection(std::span bytes) + -> PreprocessedCollection; + +[[nodiscard]] auto serialize_result_collection(const ResultCollection& collection) -> std::vector; +[[nodiscard]] auto deserialize_result_collection(std::span bytes) -> ResultCollection; + +// Monotonic timestamp helper used for produced collections. +[[nodiscard]] auto current_monotonic_ns() -> std::uint64_t; + +} // namespace radar::ipc diff --git a/data_acq_and_processing/common_cpp/ipc/include/shm_ring.hpp b/data_acq_and_processing/common_cpp/ipc/include/shm_ring.hpp new file mode 100644 index 0000000..648147e --- /dev/null +++ b/data_acq_and_processing/common_cpp/ipc/include/shm_ring.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace radar::ipc { + +class ShmRing { + public: + ShmRing() = default; + ~ShmRing(); + + ShmRing(const ShmRing&) = delete; + auto operator=(const ShmRing&) -> ShmRing& = delete; + + ShmRing(ShmRing&& other) noexcept; + auto operator=(ShmRing&& other) noexcept -> ShmRing&; + + [[nodiscard]] static auto open_or_create( + const std::string& name, + std::uint32_t capacity, + std::uint32_t slot_size_bytes + ) -> ShmRing; + + // Opens ring by name and validates wire-format header fields. + [[nodiscard]] static auto open_existing(const std::string& name) -> ShmRing; + // Removes shared memory object by name (safe if it does not exist). + static void unlink_ring(const std::string& name); + + [[nodiscard]] auto is_open() const -> bool; + [[nodiscard]] auto capacity() const -> std::uint32_t; + [[nodiscard]] auto slot_size_bytes() const -> std::uint32_t; + [[nodiscard]] auto dropped_count() const -> std::uint64_t; + + // Pushes payload with overwrite-oldest policy on overflow. + [[nodiscard]] auto push(std::span payload) -> bool; + // Pops the next payload if available. + [[nodiscard]] auto pop(std::vector& payload) -> bool; + + private: + struct Header; + struct SlotHeader; + + int fd_ = -1; + std::size_t mapped_size_ = 0; + void* mapped_ = nullptr; + Header* header_ = nullptr; + + // Slot geometry helpers. + [[nodiscard]] auto slot_stride_bytes() const -> std::size_t; + [[nodiscard]] auto slot_header(std::uint64_t sequence) const -> SlotHeader*; + [[nodiscard]] auto slot_payload(SlotHeader* slot) const -> std::uint8_t*; + + void close(); + static void validate_name(const std::string& name); +}; + +} // namespace radar::ipc diff --git a/data_acq_and_processing/common_cpp/ipc/src/shared_types.cpp b/data_acq_and_processing/common_cpp/ipc/src/shared_types.cpp new file mode 100644 index 0000000..45eb1c7 --- /dev/null +++ b/data_acq_and_processing/common_cpp/ipc/src/shared_types.cpp @@ -0,0 +1,336 @@ +#include "shared_types.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace radar::ipc { +namespace { + +constexpr std::uint32_t kRawCollectionMagic = 0x31574152U; // RAW1 +constexpr std::uint32_t kPreprocessedCollectionMagic = 0x31525050U; // PRP1 +constexpr std::uint32_t kResultCollectionMagic = 0x314C5352U; // RSL1 + +template +concept TriviallySerializable = std::is_trivially_copyable_v; + +[[nodiscard]] auto checked_count_to_u32(std::size_t count, const std::string& label) -> std::uint32_t { + if (count > std::numeric_limits::max()) { + throw std::runtime_error(label + " exceeds uint32 wire-format limit"); + } + return static_cast(count); +} + +void ensure_equal_sizes(std::size_t left, std::size_t right, const std::string& label) { + if (left != right) { + throw std::runtime_error(label + " has inconsistent vector sizes"); + } +} + +class BinaryWriter { + public: + template + void write(const T& value) { + const auto old_size = bytes_.size(); + bytes_.resize(old_size + sizeof(T)); + std::memcpy(bytes_.data() + old_size, &value, sizeof(T)); + } + + void write_string(const std::string& value) { + if (value.size() > std::numeric_limits::max()) { + throw std::runtime_error("String is too large for wire format"); + } + + write(static_cast(value.size())); + + const auto old_size = bytes_.size(); + bytes_.resize(old_size + value.size()); + std::memcpy(bytes_.data() + old_size, value.data(), value.size()); + } + + [[nodiscard]] auto finish() && -> std::vector { + return std::move(bytes_); + } + + private: + std::vector bytes_{}; +}; + +class BinaryReader { + public: + explicit BinaryReader(std::span bytes) : bytes_(bytes) {} + + template + [[nodiscard]] auto read() -> T { + ensure_available(sizeof(T)); + + T value{}; + std::memcpy(&value, bytes_.data() + offset_, sizeof(T)); + offset_ += sizeof(T); + return value; + } + + [[nodiscard]] auto read_string() -> std::string { + const auto size = read(); + ensure_available(size); + + const auto* begin = reinterpret_cast(bytes_.data() + offset_); + std::string value(begin, begin + size); + offset_ += size; + return value; + } + + [[nodiscard]] auto is_consumed() const -> bool { + return offset_ == bytes_.size(); + } + + private: + void ensure_available(std::size_t size) const { + if (offset_ + size > bytes_.size()) { + throw std::runtime_error("Unexpected end of serialized payload"); + } + } + + std::span bytes_{}; + std::size_t offset_ = 0; +}; + +void write_trace_block(BinaryWriter& writer, const SweepTraceBlock& trace) { + ensure_equal_sizes(trace.frequency_hz.size(), trace.s21.size(), "Sweep trace"); + + writer.write(trace.combo.input_pos); + writer.write(trace.combo.output_pos); + writer.write(checked_count_to_u32(trace.frequency_hz.size(), "Trace point count")); + + for (const auto frequency_hz : trace.frequency_hz) { + writer.write(frequency_hz); + } + + for (const auto& point : trace.s21) { + writer.write(point.re); + writer.write(point.im); + } +} + +[[nodiscard]] auto read_trace_block(BinaryReader& reader) -> SweepTraceBlock { + SweepTraceBlock trace{}; + trace.combo.input_pos = reader.read(); + trace.combo.output_pos = reader.read(); + + const auto point_count = reader.read(); + trace.frequency_hz.reserve(point_count); + trace.s21.reserve(point_count); + + for (std::uint32_t index = 0; index < point_count; ++index) { + trace.frequency_hz.push_back(reader.read()); + } + + for (std::uint32_t index = 0; index < point_count; ++index) { + trace.s21.push_back(Complex32{ + .re = reader.read(), + .im = reader.read(), + }); + } + + return trace; +} + +void write_trace_collection(BinaryWriter& writer, std::uint32_t magic, const RawSweepCollection& collection) { + writer.write(magic); + writer.write(collection.collection_id); + writer.write(collection.monotonic_ns); + writer.write(checked_count_to_u32(collection.traces.size(), "Trace count")); + + for (const auto& trace : collection.traces) { + write_trace_block(writer, trace); + } +} + +[[nodiscard]] auto read_trace_collection(BinaryReader& reader, std::uint32_t expected_magic) -> RawSweepCollection { + const auto magic = reader.read(); + if (magic != expected_magic) { + throw std::runtime_error("Unexpected trace collection magic"); + } + + RawSweepCollection collection{}; + collection.collection_id = reader.read(); + collection.monotonic_ns = reader.read(); + + const auto trace_count = reader.read(); + collection.traces.reserve(trace_count); + for (std::uint32_t index = 0; index < trace_count; ++index) { + collection.traces.push_back(read_trace_block(reader)); + } + + return collection; +} + +void write_trace_result_payload(BinaryWriter& writer, const ResultPayload& payload) { + ensure_equal_sizes(payload.frequency_hz.size(), payload.trace.size(), "Result trace payload"); + + writer.write(checked_count_to_u32(payload.trace.size(), "Result trace point count")); + for (const auto frequency_hz : payload.frequency_hz) { + writer.write(frequency_hz); + } + for (const auto& sample : payload.trace) { + writer.write(sample.re); + writer.write(sample.im); + } +} + +auto read_trace_result_payload(BinaryReader& reader, ResultPayload* payload) -> void { + const auto point_count = reader.read(); + + payload->frequency_hz.reserve(point_count); + payload->trace.reserve(point_count); + + for (std::uint32_t index = 0; index < point_count; ++index) { + payload->frequency_hz.push_back(reader.read()); + } + for (std::uint32_t index = 0; index < point_count; ++index) { + payload->trace.push_back(Complex32{ + .re = reader.read(), + .im = reader.read(), + }); + } +} + +void write_result_payload(BinaryWriter& writer, const ResultPayload& payload) { + writer.write(static_cast(payload.kind)); + writer.write_string(payload.processing_name); + + switch (payload.kind) { + case ResultKind::TraceComplex: + write_trace_result_payload(writer, payload); + return; + case ResultKind::ScalarF32: + writer.write(payload.scalar_value); + return; + default: + throw std::runtime_error("Unsupported result payload kind"); + } +} + +[[nodiscard]] auto read_result_payload(BinaryReader& reader) -> ResultPayload { + ResultPayload payload{}; + payload.kind = static_cast(reader.read()); + payload.processing_name = reader.read_string(); + + switch (payload.kind) { + case ResultKind::TraceComplex: + read_trace_result_payload(reader, &payload); + return payload; + case ResultKind::ScalarF32: + payload.scalar_value = reader.read(); + return payload; + default: + throw std::runtime_error("Unsupported result payload kind in stream"); + } +} + +void write_result_block(BinaryWriter& writer, const ResultBlock& block) { + writer.write(block.combo.input_pos); + writer.write(block.combo.output_pos); + writer.write(checked_count_to_u32(block.payloads.size(), "Result payload count")); + + for (const auto& payload : block.payloads) { + write_result_payload(writer, payload); + } +} + +[[nodiscard]] auto read_result_block(BinaryReader& reader) -> ResultBlock { + ResultBlock block{}; + block.combo.input_pos = reader.read(); + block.combo.output_pos = reader.read(); + + const auto payload_count = reader.read(); + block.payloads.reserve(payload_count); + for (std::uint32_t index = 0; index < payload_count; ++index) { + block.payloads.push_back(read_result_payload(reader)); + } + + return block; +} + +void ensure_reader_consumed(const BinaryReader& reader, const std::string& payload_label) { + if (!reader.is_consumed()) { + throw std::runtime_error("Unexpected trailing bytes in " + payload_label); + } +} + +} // namespace + +auto serialize_raw_collection(const RawSweepCollection& collection) -> std::vector { + BinaryWriter writer{}; + write_trace_collection(writer, kRawCollectionMagic, collection); + return std::move(writer).finish(); +} + +auto deserialize_raw_collection(std::span bytes) -> RawSweepCollection { + BinaryReader reader(bytes); + auto collection = read_trace_collection(reader, kRawCollectionMagic); + ensure_reader_consumed(reader, "raw collection"); + return collection; +} + +auto serialize_preprocessed_collection(const PreprocessedCollection& collection) -> std::vector { + BinaryWriter writer{}; + write_trace_collection(writer, kPreprocessedCollectionMagic, collection); + return std::move(writer).finish(); +} + +auto deserialize_preprocessed_collection(std::span bytes) -> PreprocessedCollection { + BinaryReader reader(bytes); + auto collection = read_trace_collection(reader, kPreprocessedCollectionMagic); + ensure_reader_consumed(reader, "preprocessed collection"); + return collection; +} + +auto serialize_result_collection(const ResultCollection& collection) -> std::vector { + BinaryWriter writer{}; + writer.write(kResultCollectionMagic); + writer.write(collection.collection_id); + writer.write(collection.monotonic_ns); + writer.write(checked_count_to_u32(collection.blocks.size(), "Result block count")); + + for (const auto& block : collection.blocks) { + write_result_block(writer, block); + } + + return std::move(writer).finish(); +} + +auto deserialize_result_collection(std::span bytes) -> ResultCollection { + BinaryReader reader(bytes); + + const auto magic = reader.read(); + if (magic != kResultCollectionMagic) { + throw std::runtime_error("Unexpected result collection magic"); + } + + ResultCollection collection{}; + collection.collection_id = reader.read(); + collection.monotonic_ns = reader.read(); + + const auto block_count = reader.read(); + collection.blocks.reserve(block_count); + for (std::uint32_t index = 0; index < block_count; ++index) { + collection.blocks.push_back(read_result_block(reader)); + } + + ensure_reader_consumed(reader, "result collection"); + return collection; +} + +auto current_monotonic_ns() -> std::uint64_t { + const auto now = std::chrono::steady_clock::now().time_since_epoch(); + const auto now_ns = std::chrono::duration_cast(now).count(); + return static_cast(now_ns); +} + +} // namespace radar::ipc diff --git a/data_acq_and_processing/common_cpp/ipc/src/shm_ring.cpp b/data_acq_and_processing/common_cpp/ipc/src/shm_ring.cpp new file mode 100644 index 0000000..d683c0a --- /dev/null +++ b/data_acq_and_processing/common_cpp/ipc/src/shm_ring.cpp @@ -0,0 +1,380 @@ +#include "shm_ring.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace radar::ipc { + +struct alignas(64) ShmRing::Header { + char magic[8]{}; + std::uint32_t version = 0; + std::uint32_t capacity = 0; + std::uint32_t slot_size_bytes = 0; + std::uint32_t reserved = 0; + std::atomic write_seq{}; + std::atomic read_seq{}; + std::atomic dropped{}; +}; + +struct alignas(16) ShmRing::SlotHeader { + std::uint32_t payload_size = 0; + std::uint32_t reserved = 0; + std::uint64_t sequence = 0; +}; + +namespace { + +constexpr std::string_view kRingMagic = "RDRRING2"; +constexpr std::uint32_t kRingVersion = 1; +constexpr auto kHeaderInitWaitTimeout = std::chrono::milliseconds(1000); +constexpr auto kHeaderInitPollInterval = std::chrono::milliseconds(2); + +[[nodiscard]] auto checked_u64_diff(std::uint64_t left, std::uint64_t right) -> std::uint64_t { + return left >= right ? left - right : 0; +} + +[[nodiscard]] auto errno_message(const std::string& action, const std::string& name) -> std::runtime_error { + return std::runtime_error(action + " " + name + ": " + std::strerror(errno)); +} + +class ScopedFd { + public: + explicit ScopedFd(int fd) : fd_(fd) {} + + ~ScopedFd() { + if (fd_ >= 0) { + ::close(fd_); + } + } + + ScopedFd(const ScopedFd&) = delete; + auto operator=(const ScopedFd&) -> ScopedFd& = delete; + + ScopedFd(ScopedFd&& other) noexcept : fd_(std::exchange(other.fd_, -1)) {} + + auto release() -> int { + return std::exchange(fd_, -1); + } + + private: + int fd_ = -1; +}; + +class ScopedMmap { + public: + ScopedMmap(void* address, std::size_t size) : address_(address), size_(size) {} + + ~ScopedMmap() { + if (address_ != nullptr && address_ != MAP_FAILED) { + munmap(address_, size_); + } + } + + ScopedMmap(const ScopedMmap&) = delete; + auto operator=(const ScopedMmap&) -> ScopedMmap& = delete; + + ScopedMmap(ScopedMmap&& other) noexcept + : address_(std::exchange(other.address_, nullptr)), + size_(std::exchange(other.size_, 0U)) {} + + auto release() -> std::pair { + return {std::exchange(address_, nullptr), std::exchange(size_, 0U)}; + } + + private: + void* address_ = nullptr; + std::size_t size_ = 0; +}; + +} // namespace + +ShmRing::~ShmRing() { + close(); +} + +ShmRing::ShmRing(ShmRing&& other) noexcept { + *this = std::move(other); +} + +auto ShmRing::operator=(ShmRing&& other) noexcept -> ShmRing& { + if (this != &other) { + close(); + + fd_ = std::exchange(other.fd_, -1); + mapped_size_ = std::exchange(other.mapped_size_, 0U); + mapped_ = std::exchange(other.mapped_, nullptr); + header_ = std::exchange(other.header_, nullptr); + } + return *this; +} + +auto ShmRing::open_or_create( + const std::string& name, + std::uint32_t capacity, + std::uint32_t slot_size_bytes +) -> ShmRing { + validate_name(name); + if (capacity == 0U) { + throw std::runtime_error("Ring capacity must be > 0"); + } + if (slot_size_bytes == 0U) { + throw std::runtime_error("Ring slot size must be > 0"); + } + + bool created = false; + int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0660); + if (fd >= 0) { + created = true; + } else if (errno == EEXIST) { + fd = shm_open(name.c_str(), O_RDWR, 0660); + } + + if (fd < 0) { + throw errno_message("Failed to open shared memory ring", name); + } + + ScopedFd scoped_fd(fd); + + const auto slot_stride = sizeof(SlotHeader) + static_cast(slot_size_bytes); + const auto mapped_size = sizeof(Header) + slot_stride * capacity; + + if (created) { + if (ftruncate(fd, static_cast(mapped_size)) != 0) { + throw errno_message("Failed to resize shared memory ring", name); + } + } + + void* mapped = mmap(nullptr, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapped == MAP_FAILED) { + throw errno_message("Failed to mmap shared memory ring", name); + } + + ScopedMmap scoped_mmap(mapped, mapped_size); + auto* header = static_cast(mapped); + + if (created) { + std::memset(mapped, 0, mapped_size); + std::memcpy(header->magic, kRingMagic.data(), kRingMagic.size()); + header->version = kRingVersion; + header->capacity = capacity; + header->slot_size_bytes = slot_size_bytes; + + new (&header->write_seq) std::atomic(0); + new (&header->read_seq) std::atomic(0); + new (&header->dropped) std::atomic(0); + std::atomic_thread_fence(std::memory_order_release); + } else { + const auto deadline = std::chrono::steady_clock::now() + kHeaderInitWaitTimeout; + + while (true) { + std::atomic_thread_fence(std::memory_order_acquire); + + const bool magic_ok = std::memcmp(header->magic, kRingMagic.data(), kRingMagic.size()) == 0; + const bool version_ok = header->version == kRingVersion; + const bool geometry_ok = header->capacity == capacity && header->slot_size_bytes == slot_size_bytes; + + if (magic_ok && version_ok && geometry_ok) { + break; + } + + if (std::chrono::steady_clock::now() >= deadline) { + if (!magic_ok) { + throw std::runtime_error("Shared memory ring magic mismatch for " + name); + } + if (!version_ok) { + throw std::runtime_error("Shared memory ring version mismatch for " + name); + } + throw std::runtime_error("Shared memory ring geometry mismatch for " + name); + } + + std::this_thread::sleep_for(kHeaderInitPollInterval); + } + } + + ShmRing ring{}; + ring.fd_ = scoped_fd.release(); + + const auto [released_mapped, released_size] = scoped_mmap.release(); + ring.mapped_ = released_mapped; + ring.mapped_size_ = released_size; + ring.header_ = static_cast(released_mapped); + return ring; +} + +auto ShmRing::open_existing(const std::string& name) -> ShmRing { + validate_name(name); + + const int fd = shm_open(name.c_str(), O_RDWR, 0660); + if (fd < 0) { + throw errno_message("Failed to open shared memory ring", name); + } + + ScopedFd scoped_fd(fd); + + struct stat info {}; + if (fstat(fd, &info) != 0) { + throw errno_message("Failed to stat shared memory ring", name); + } + + if (info.st_size < static_cast(sizeof(Header))) { + throw std::runtime_error("Shared memory ring size is too small for " + name); + } + + const auto mapped_size = static_cast(info.st_size); + void* mapped = mmap(nullptr, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapped == MAP_FAILED) { + throw errno_message("Failed to mmap shared memory ring", name); + } + + ScopedMmap scoped_mmap(mapped, mapped_size); + auto* header = static_cast(mapped); + + if (std::memcmp(header->magic, kRingMagic.data(), kRingMagic.size()) != 0) { + throw std::runtime_error("Shared memory ring magic mismatch for " + name); + } + if (header->version != kRingVersion) { + throw std::runtime_error("Shared memory ring version mismatch for " + name); + } + + ShmRing ring{}; + ring.fd_ = scoped_fd.release(); + + const auto [released_mapped, released_size] = scoped_mmap.release(); + ring.mapped_ = released_mapped; + ring.mapped_size_ = released_size; + ring.header_ = static_cast(released_mapped); + return ring; +} + +void ShmRing::unlink_ring(const std::string& name) { + validate_name(name); + if (shm_unlink(name.c_str()) != 0 && errno != ENOENT) { + throw errno_message("Failed to unlink shared memory ring", name); + } +} + +auto ShmRing::is_open() const -> bool { + return header_ != nullptr; +} + +auto ShmRing::capacity() const -> std::uint32_t { + return header_ != nullptr ? header_->capacity : 0; +} + +auto ShmRing::slot_size_bytes() const -> std::uint32_t { + return header_ != nullptr ? header_->slot_size_bytes : 0; +} + +auto ShmRing::dropped_count() const -> std::uint64_t { + if (header_ == nullptr) { + return 0; + } + return header_->dropped.load(std::memory_order_acquire); +} + +auto ShmRing::push(std::span payload) -> bool { + if (header_ == nullptr) { + throw std::runtime_error("Ring is not open"); + } + if (payload.size() > header_->slot_size_bytes) { + return false; + } + + const auto write_seq = header_->write_seq.load(std::memory_order_relaxed); + const auto read_seq = header_->read_seq.load(std::memory_order_acquire); + + if (checked_u64_diff(write_seq, read_seq) >= header_->capacity) { + header_->read_seq.store(read_seq + 1U, std::memory_order_release); + header_->dropped.fetch_add(1U, std::memory_order_relaxed); + } + + auto* slot = slot_header(write_seq); + slot->payload_size = static_cast(payload.size()); + slot->sequence = write_seq + 1U; + std::memcpy(slot_payload(slot), payload.data(), payload.size()); + + std::atomic_thread_fence(std::memory_order_release); + header_->write_seq.store(write_seq + 1U, std::memory_order_release); + return true; +} + +auto ShmRing::pop(std::vector& payload) -> bool { + if (header_ == nullptr) { + throw std::runtime_error("Ring is not open"); + } + + const auto read_seq = header_->read_seq.load(std::memory_order_relaxed); + const auto write_seq = header_->write_seq.load(std::memory_order_acquire); + if (read_seq >= write_seq) { + return false; + } + + auto* slot = slot_header(read_seq); + if (slot->sequence != read_seq + 1U) { + // Producer overwrote this slot before consumer read it. Resync to latest. + header_->read_seq.store(write_seq, std::memory_order_release); + return false; + } + + const auto payload_size = slot->payload_size; + if (payload_size > header_->slot_size_bytes) { + header_->read_seq.store(write_seq, std::memory_order_release); + throw std::runtime_error("Invalid payload size in shared memory slot"); + } + + payload.resize(payload_size); + std::memcpy(payload.data(), slot_payload(slot), payload_size); + + std::atomic_thread_fence(std::memory_order_acquire); + header_->read_seq.store(read_seq + 1U, std::memory_order_release); + return true; +} + +auto ShmRing::slot_stride_bytes() const -> std::size_t { + return sizeof(SlotHeader) + header_->slot_size_bytes; +} + +auto ShmRing::slot_header(std::uint64_t sequence) const -> SlotHeader* { + const auto index = sequence % header_->capacity; + auto* slots_begin = static_cast(mapped_) + sizeof(Header); + return reinterpret_cast(slots_begin + index * slot_stride_bytes()); +} + +auto ShmRing::slot_payload(SlotHeader* slot) const -> std::uint8_t* { + return reinterpret_cast(slot) + sizeof(SlotHeader); +} + +void ShmRing::close() { + if (mapped_ != nullptr) { + munmap(mapped_, mapped_size_); + mapped_ = nullptr; + } + + if (fd_ >= 0) { + ::close(fd_); + fd_ = -1; + } + + mapped_size_ = 0; + header_ = nullptr; +} + +void ShmRing::validate_name(const std::string& name) { + if (name.empty() || name.front() != '/') { + throw std::runtime_error("POSIX shm name must start with '/'"); + } +} + +} // namespace radar::ipc diff --git a/data_acq_and_processing/preprocessing/calibration_master/include/calibration_master.hpp b/data_acq_and_processing/preprocessing/calibration_master/include/calibration_master.hpp new file mode 100644 index 0000000..a0489fc --- /dev/null +++ b/data_acq_and_processing/preprocessing/calibration_master/include/calibration_master.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +#include "calibrator_interface.hpp" +#include "shared_types.hpp" + +namespace radar::preprocessing { + +class CalibrationMaster { + public: + // `calibrator` encapsulates the actual calibration algorithm (v1: through). + explicit CalibrationMaster(std::unique_ptr calibrator); + + // Loads a serialized raw sweep bundle with one calibration standard per combo. + void load_bundle(const std::string& path); + // Ensures all runtime combos are present in loaded standards. + void validate_combos(const std::vector& combos) const; + // Applies calibration standard corresponding to measured trace combo. + [[nodiscard]] auto apply(const ipc::SweepTraceBlock& measured_trace) const -> ipc::SweepTraceBlock; + + private: + std::unique_ptr calibrator_impl_; + std::unordered_map standards_by_combo_{}; +}; + +[[nodiscard]] auto make_through_calibrator() -> std::unique_ptr; + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/calibration_master/include/calibrator_interface.hpp b/data_acq_and_processing/preprocessing/calibration_master/include/calibrator_interface.hpp new file mode 100644 index 0000000..159f9a5 --- /dev/null +++ b/data_acq_and_processing/preprocessing/calibration_master/include/calibrator_interface.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "shared_types.hpp" + +namespace radar::preprocessing { + +class CalibratorInterface { + public: + virtual ~CalibratorInterface() = default; + + [[nodiscard]] virtual auto name() const -> std::string = 0; + [[nodiscard]] virtual auto apply( + const std::vector& measured, + const std::vector& calibration + ) const -> std::vector = 0; +}; + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/calibration_master/src/calibration_master.cpp b/data_acq_and_processing/preprocessing/calibration_master/src/calibration_master.cpp new file mode 100644 index 0000000..c20a8d1 --- /dev/null +++ b/data_acq_and_processing/preprocessing/calibration_master/src/calibration_master.cpp @@ -0,0 +1,101 @@ +#include "calibration_master.hpp" + +#include +#include +#include +#include +#include +#include + +namespace radar::preprocessing { +namespace { + +[[nodiscard]] auto combo_to_string(const ipc::ComboKey& combo) -> std::string { + return "input=" + std::to_string(combo.input_pos) + " output=" + std::to_string(combo.output_pos); +} + +[[nodiscard]] auto read_binary_file(const std::string& path, const std::string& bundle_label) + -> std::vector { + std::ifstream stream(path, std::ios::binary); + if (!stream.is_open()) { + throw std::runtime_error("Failed to open " + bundle_label + " bundle: " + path); + } + + return std::vector(std::istreambuf_iterator(stream), std::istreambuf_iterator()); +} + +void validate_trace_layout(const ipc::SweepTraceBlock& trace, const std::string& trace_label) { + if (trace.frequency_hz.size() != trace.s21.size()) { + throw std::runtime_error( + trace_label + " frequency/complex vector size mismatch for combo " + combo_to_string(trace.combo) + ); + } +} + +} // namespace + +CalibrationMaster::CalibrationMaster(std::unique_ptr calibrator) + : calibrator_impl_(std::move(calibrator)) { + if (!calibrator_impl_) { + throw std::runtime_error("CalibrationMaster requires a non-null calibrator"); + } +} + +void CalibrationMaster::load_bundle(const std::string& path) { + if (path.empty()) { + throw std::runtime_error("Calibration bundle path must not be empty"); + } + + const auto bytes = read_binary_file(path, "calibration"); + if (bytes.empty()) { + throw std::runtime_error("Calibration bundle is empty: " + path); + } + + const auto collection = ipc::deserialize_raw_collection(bytes); + standards_by_combo_.clear(); + standards_by_combo_.reserve(collection.traces.size()); + for (const auto& trace : collection.traces) { + validate_trace_layout(trace, "Calibration standard"); + standards_by_combo_.insert_or_assign(trace.combo, trace); + } + + if (standards_by_combo_.empty()) { + throw std::runtime_error("Calibration bundle does not contain traces: " + path); + } +} + +void CalibrationMaster::validate_combos(const std::vector& combos) const { + for (const auto& combo : combos) { + if (!standards_by_combo_.contains(combo)) { + throw std::runtime_error("Calibration data is missing for combo " + combo_to_string(combo)); + } + } +} + +auto CalibrationMaster::apply(const ipc::SweepTraceBlock& measured_trace) const -> ipc::SweepTraceBlock { + validate_trace_layout(measured_trace, "Measured trace"); + + const auto found = standards_by_combo_.find(measured_trace.combo); + if (found == standards_by_combo_.end()) { + throw std::runtime_error( + "Calibration standard is missing for measured combo " + combo_to_string(measured_trace.combo) + ); + } + + const auto& standard = found->second; + validate_trace_layout(standard, "Calibration standard"); + if (measured_trace.s21.size() != standard.s21.size()) { + throw std::runtime_error( + "Calibration standard point count mismatch for combo " + combo_to_string(measured_trace.combo) + ); + } + + ipc::SweepTraceBlock output{}; + output.combo = measured_trace.combo; + output.frequency_hz = measured_trace.frequency_hz; + output.s21 = calibrator_impl_->apply(measured_trace.s21, standard.s21); + + return output; +} + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/calibration_master/src/through_calibrator.cpp b/data_acq_and_processing/preprocessing/calibration_master/src/through_calibrator.cpp new file mode 100644 index 0000000..5aff8cd --- /dev/null +++ b/data_acq_and_processing/preprocessing/calibration_master/src/through_calibrator.cpp @@ -0,0 +1,76 @@ +#include "calibration_master.hpp" + +#include +#include +#include +#include + +#include + +namespace radar::preprocessing { +namespace { + +class ThroughCalibrator final : public CalibratorInterface { + public: + [[nodiscard]] auto name() const -> std::string override { + return "through"; + } + + [[nodiscard]] auto apply( + const std::vector& measured, + const std::vector& calibration + ) const -> std::vector override { + if (measured.size() != calibration.size()) { + throw std::runtime_error("Through calibration vector size mismatch"); + } + + static_assert(sizeof(ipc::Complex32) == sizeof(float) * 2U, "Complex32 layout must be two contiguous floats"); + + constexpr float epsilon = 1e-12F; + using InterleavedComplexView = Eigen::Matrix; + + const auto point_count = static_cast(measured.size()); + Eigen::Map measured_view( + reinterpret_cast(measured.data()), + point_count, + 2 + ); + Eigen::Map calibration_view( + reinterpret_cast(calibration.data()), + point_count, + 2 + ); + + const auto measured_re = measured_view.col(0).array(); + const auto measured_im = measured_view.col(1).array(); + const auto calibration_re = calibration_view.col(0).array(); + const auto calibration_im = calibration_view.col(1).array(); + + const Eigen::ArrayXf magnitude_squared = calibration_re.square() + calibration_im.square(); + const auto stable_division_mask = (magnitude_squared > epsilon); + + const Eigen::ArrayXf corrected_re = stable_division_mask.select( + ((measured_re * calibration_re) + (measured_im * calibration_im)) / magnitude_squared, + measured_re + ); + const Eigen::ArrayXf corrected_im = stable_division_mask.select( + ((measured_im * calibration_re) - (measured_re * calibration_im)) / magnitude_squared, + measured_im + ); + + std::vector corrected(measured.size()); + Eigen::Map corrected_view(reinterpret_cast(corrected.data()), point_count, 2); + corrected_view.col(0) = corrected_re.matrix(); + corrected_view.col(1) = corrected_im.matrix(); + + return corrected; + } +}; + +} // namespace + +auto make_through_calibrator() -> std::unique_ptr { + return std::make_unique(); +} + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/data_preprocessor/include/data_preprocessor.hpp b/data_acq_and_processing/preprocessing/data_preprocessor/include/data_preprocessor.hpp new file mode 100644 index 0000000..8ee571f --- /dev/null +++ b/data_acq_and_processing/preprocessing/data_preprocessor/include/data_preprocessor.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include + +#include "calibration_master.hpp" +#include "reference_master.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" + +namespace radar::preprocessing { + +class DataPreprocessor { + public: + DataPreprocessor( + const config::RunConfig& config, + CalibrationMaster& calibration_master, + ReferenceMaster& reference_master, + ipc::ShmRing& raw_ring, + ipc::ShmRing& preprocessed_ring, + ipc::ShmRing* preprocessed_tap_ring = nullptr + ); + + // Main processing loop. Runs until stop flag is set. + void run(const std::atomic& stop_requested); + + private: + void validate_startup_prerequisites() const; + [[nodiscard]] auto try_pop_raw_collection( + std::vector& serialized_raw, + ipc::RawSweepCollection* out_collection + ) -> bool; + void publish_preprocessed_collection(const ipc::PreprocessedCollection& collection); + + [[nodiscard]] auto preprocess_collection(const ipc::RawSweepCollection& raw_collection) const + -> ipc::PreprocessedCollection; + + const config::RunConfig& config_; + CalibrationMaster& calibration_master_; + ReferenceMaster& reference_master_; + ipc::ShmRing& raw_ring_; + ipc::ShmRing& preprocessed_ring_; + ipc::ShmRing* preprocessed_tap_ring_ = nullptr; +}; + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/data_preprocessor/src/data_preprocessor.cpp b/data_acq_and_processing/preprocessing/data_preprocessor/src/data_preprocessor.cpp new file mode 100644 index 0000000..3729de4 --- /dev/null +++ b/data_acq_and_processing/preprocessing/data_preprocessor/src/data_preprocessor.cpp @@ -0,0 +1,85 @@ +#include "data_preprocessor.hpp" + +#include +#include +#include +#include + +namespace radar::preprocessing { + +DataPreprocessor::DataPreprocessor( + const config::RunConfig& config, + CalibrationMaster& calibration_master, + ReferenceMaster& reference_master, + ipc::ShmRing& raw_ring, + ipc::ShmRing& preprocessed_ring, + ipc::ShmRing* preprocessed_tap_ring +) + : config_(config), + calibration_master_(calibration_master), + reference_master_(reference_master), + raw_ring_(raw_ring), + preprocessed_ring_(preprocessed_ring), + preprocessed_tap_ring_(preprocessed_tap_ring) {} + +void DataPreprocessor::validate_startup_prerequisites() const { + calibration_master_.validate_combos(config_.run_combos); + reference_master_.validate_combos(config_.run_combos); +} + +auto DataPreprocessor::try_pop_raw_collection( + std::vector& serialized_raw, + ipc::RawSweepCollection* out_collection +) -> bool { + if (!raw_ring_.pop(serialized_raw)) { + std::this_thread::sleep_for(std::chrono::milliseconds(config_.runtime.idle_sleep_ms)); + return false; + } + + *out_collection = ipc::deserialize_raw_collection(serialized_raw); + return true; +} + +void DataPreprocessor::publish_preprocessed_collection(const ipc::PreprocessedCollection& collection) { + const auto serialized_preprocessed = ipc::serialize_preprocessed_collection(collection); + if (!preprocessed_ring_.push(serialized_preprocessed)) { + throw std::runtime_error("Preprocessed ring slot is too small for serialized collection"); + } + if (preprocessed_tap_ring_ != nullptr && !preprocessed_tap_ring_->push(serialized_preprocessed)) { + throw std::runtime_error("Preprocessed tap ring slot is too small for serialized collection"); + } +} + +void DataPreprocessor::run(const std::atomic& stop_requested) { + validate_startup_prerequisites(); + + std::vector serialized_raw{}; + ipc::RawSweepCollection raw_collection{}; + while (!stop_requested.load(std::memory_order_relaxed)) { + if (!try_pop_raw_collection(serialized_raw, &raw_collection)) { + continue; + } + + const auto preprocessed_collection = preprocess_collection(raw_collection); + publish_preprocessed_collection(preprocessed_collection); + } +} + +auto DataPreprocessor::preprocess_collection(const ipc::RawSweepCollection& raw_collection) const + -> ipc::PreprocessedCollection { + ipc::PreprocessedCollection preprocessed{}; + preprocessed.collection_id = raw_collection.collection_id; + preprocessed.monotonic_ns = ipc::current_monotonic_ns(); + preprocessed.traces.reserve(raw_collection.traces.size()); + + for (const auto& raw_trace : raw_collection.traces) { + // Pipeline order is fixed: calibration first, then reference subtraction. + const auto calibrated = calibration_master_.apply(raw_trace); + const auto referenced = reference_master_.apply(calibrated); + preprocessed.traces.push_back(referenced); + } + + return preprocessed; +} + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/data_preprocessor/src/main.cpp b/data_acq_and_processing/preprocessing/data_preprocessor/src/main.cpp new file mode 100644 index 0000000..48f671a --- /dev/null +++ b/data_acq_and_processing/preprocessing/data_preprocessor/src/main.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +#include "calibration_master.hpp" +#include "data_preprocessor.hpp" +#include "reference_master.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" + +namespace { + +constexpr const char* kDefaultConfigPath = "run_config.json"; + +std::atomic g_stop_requested{false}; + +void signal_handler(int /*signal*/) { + g_stop_requested.store(true, std::memory_order_relaxed); +} + +void install_signal_handlers() { + std::signal(SIGINT, signal_handler); + std::signal(SIGTERM, signal_handler); +} + +[[nodiscard]] auto read_config_path(int argc, char** argv) -> std::string { + std::string config_path = kDefaultConfigPath; + for (int index = 1; index < argc; ++index) { + const std::string arg = argv[index]; + if (arg == "--config" && (index + 1) < argc) { + config_path = argv[++index]; + } + } + return config_path; +} + +} // namespace + +int main(int argc, char** argv) { + install_signal_handlers(); + + try { + const auto config_path = read_config_path(argc, argv); + const auto config = radar::config::load_run_config(config_path); + + auto raw_ring = radar::ipc::ShmRing::open_or_create( + config.rings.raw.name, + config.rings.raw.capacity, + config.rings.raw.slot_size_bytes + ); + auto preprocessed_ring = radar::ipc::ShmRing::open_or_create( + config.rings.preprocessed.name, + config.rings.preprocessed.capacity, + config.rings.preprocessed.slot_size_bytes + ); + auto preprocessed_tap_ring = radar::ipc::ShmRing::open_or_create( + config.rings.preprocessed_tap.name, + config.rings.preprocessed_tap.capacity, + config.rings.preprocessed_tap.slot_size_bytes + ); + + // Load preprocessing assets once before entering run loop. + radar::preprocessing::CalibrationMaster calibration_master(radar::preprocessing::make_through_calibrator()); + calibration_master.load_bundle(config.preprocess.calibration_bundle_path); + + radar::preprocessing::ReferenceMaster reference_master; + reference_master.load_bundle(config.preprocess.reference_bundle_path); + reference_master.prepare_calibrated(calibration_master); + + radar::preprocessing::DataPreprocessor preprocessor( + config, + calibration_master, + reference_master, + raw_ring, + preprocessed_ring, + &preprocessed_tap_ring + ); + preprocessor.run(g_stop_requested); + return 0; + } catch (const std::exception& exception) { + std::cerr << "data_preprocessor error: " << exception.what() << '\n'; + return 1; + } +} diff --git a/data_acq_and_processing/preprocessing/reference_master/include/reference_master.hpp b/data_acq_and_processing/preprocessing/reference_master/include/reference_master.hpp new file mode 100644 index 0000000..cb23ca1 --- /dev/null +++ b/data_acq_and_processing/preprocessing/reference_master/include/reference_master.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "shared_types.hpp" + +namespace radar::preprocessing { + +class CalibrationMaster; + +class ReferenceMaster { + public: + // Loads a serialized raw sweep bundle with one reference trace per combo. + void load_bundle(const std::string& path); + // Builds calibrated references in memory using currently loaded raw references. + // Must be called after load_bundle() and after calibration standards are loaded. + void prepare_calibrated(const CalibrationMaster& calibration_master); + // Ensures all runtime combos are present in loaded references. + void validate_combos(const std::vector& combos) const; + // Subtracts per-combo reference trace from calibrated trace. + [[nodiscard]] auto apply(const ipc::SweepTraceBlock& calibrated_trace) const -> ipc::SweepTraceBlock; + + private: + std::unordered_map raw_references_by_combo_{}; + std::unordered_map calibrated_references_by_combo_{}; +}; + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/preprocessing/reference_master/src/reference_master.cpp b/data_acq_and_processing/preprocessing/reference_master/src/reference_master.cpp new file mode 100644 index 0000000..2ef3695 --- /dev/null +++ b/data_acq_and_processing/preprocessing/reference_master/src/reference_master.cpp @@ -0,0 +1,141 @@ +#include "reference_master.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "calibration_master.hpp" + +namespace radar::preprocessing { +namespace { + +[[nodiscard]] auto combo_to_string(const ipc::ComboKey& combo) -> std::string { + return "input=" + std::to_string(combo.input_pos) + " output=" + std::to_string(combo.output_pos); +} + +[[nodiscard]] auto read_binary_file(const std::string& path, const std::string& bundle_label) + -> std::vector { + std::ifstream stream(path, std::ios::binary); + if (!stream.is_open()) { + throw std::runtime_error("Failed to open " + bundle_label + " bundle: " + path); + } + + return std::vector(std::istreambuf_iterator(stream), std::istreambuf_iterator()); +} + +void validate_trace_layout(const ipc::SweepTraceBlock& trace, const std::string& trace_label) { + if (trace.frequency_hz.size() != trace.s21.size()) { + throw std::runtime_error( + trace_label + " frequency/complex vector size mismatch for combo " + combo_to_string(trace.combo) + ); + } +} + +} // namespace + +void ReferenceMaster::load_bundle(const std::string& path) { + if (path.empty()) { + throw std::runtime_error("Reference bundle path must not be empty"); + } + + const auto bytes = read_binary_file(path, "reference"); + if (bytes.empty()) { + throw std::runtime_error("Reference bundle is empty: " + path); + } + + const auto collection = ipc::deserialize_raw_collection(bytes); + raw_references_by_combo_.clear(); + raw_references_by_combo_.reserve(collection.traces.size()); + calibrated_references_by_combo_.clear(); + for (const auto& trace : collection.traces) { + validate_trace_layout(trace, "Reference trace"); + raw_references_by_combo_.insert_or_assign(trace.combo, trace); + } + + if (raw_references_by_combo_.empty()) { + throw std::runtime_error("Reference bundle does not contain traces: " + path); + } +} + +void ReferenceMaster::prepare_calibrated(const CalibrationMaster& calibration_master) { + if (raw_references_by_combo_.empty()) { + throw std::runtime_error("Reference bundle must be loaded before prepare_calibrated()"); + } + + calibrated_references_by_combo_.clear(); + calibrated_references_by_combo_.reserve(raw_references_by_combo_.size()); + for (const auto& [combo, raw_reference] : raw_references_by_combo_) { + auto calibrated = calibration_master.apply(raw_reference); + calibrated.combo = combo; + calibrated_references_by_combo_.insert_or_assign(combo, std::move(calibrated)); + } +} + +void ReferenceMaster::validate_combos(const std::vector& combos) const { + if (calibrated_references_by_combo_.empty()) { + throw std::runtime_error( + "Calibrated references are not prepared. Call ReferenceMaster::prepare_calibrated() at startup." + ); + } + + for (const auto& combo : combos) { + if (!raw_references_by_combo_.contains(combo)) { + throw std::runtime_error("Raw reference data is missing for combo " + combo_to_string(combo)); + } + if (!calibrated_references_by_combo_.contains(combo)) { + throw std::runtime_error("Calibrated reference data is missing for combo " + combo_to_string(combo)); + } + } +} + +auto ReferenceMaster::apply(const ipc::SweepTraceBlock& calibrated_trace) const -> ipc::SweepTraceBlock { + validate_trace_layout(calibrated_trace, "Calibrated trace"); + + const auto found = calibrated_references_by_combo_.find(calibrated_trace.combo); + if (found == calibrated_references_by_combo_.end()) { + throw std::runtime_error( + "Calibrated reference trace is missing for combo " + combo_to_string(calibrated_trace.combo) + ); + } + + const auto& reference = found->second; + validate_trace_layout(reference, "Calibrated reference trace"); + if (calibrated_trace.s21.size() != reference.s21.size()) { + throw std::runtime_error( + "Reference point count mismatch for combo " + combo_to_string(calibrated_trace.combo) + ); + } + + ipc::SweepTraceBlock output{}; + output.combo = calibrated_trace.combo; + output.frequency_hz = calibrated_trace.frequency_hz; + output.s21.resize(calibrated_trace.s21.size()); + + static_assert(sizeof(ipc::Complex32) == sizeof(float) * 2U, "Complex32 layout must be two contiguous floats"); + using InterleavedComplexView = Eigen::Matrix; + const auto point_count = static_cast(calibrated_trace.s21.size()); + + Eigen::Map calibrated_view( + reinterpret_cast(calibrated_trace.s21.data()), + point_count, + 2 + ); + Eigen::Map reference_view( + reinterpret_cast(reference.s21.data()), + point_count, + 2 + ); + Eigen::Map output_view(reinterpret_cast(output.s21.data()), point_count, 2); + + output_view = calibrated_view - reference_view; + + return output; +} + +} // namespace radar::preprocessing diff --git a/data_acq_and_processing/processing/data_processor/include/data_processor.hpp b/data_acq_and_processing/processing/data_processor/include/data_processor.hpp new file mode 100644 index 0000000..23562e4 --- /dev/null +++ b/data_acq_and_processing/processing/data_processor/include/data_processor.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "processor_interface.hpp" +#include "processing_live_config.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" + +namespace radar::processing { + +using ProcessorRegistry = std::unordered_map>; + +class DataProcessor { + public: + DataProcessor( + const config::RunConfig& config, + ipc::ShmRing& preprocessed_ring, + ipc::ShmRing& results_ring, + ProcessorRegistry processors + ); + + void run(const std::atomic& stop_requested); + + private: + [[nodiscard]] auto process_collection( + const ipc::PreprocessedCollection& preprocessed, + ProcessorInterface& processor, + const ProcessingLiveConfig& live_config + ) -> ipc::ResultCollection; + + [[nodiscard]] auto resolve_processor(const ProcessingLiveConfig& live_config) -> ProcessorInterface&; + + const config::RunConfig& config_; + ipc::ShmRing& preprocessed_ring_; + ipc::ShmRing& results_ring_; + ProcessorRegistry processors_{}; + std::string default_processor_mode_{}; + ProcessingLiveConfigLoader live_config_loader_; +}; + +[[nodiscard]] auto create_default_processors() -> ProcessorRegistry; + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/data_processor/include/processing_live_config.hpp b/data_acq_and_processing/processing/data_processor/include/processing_live_config.hpp new file mode 100644 index 0000000..a15f32c --- /dev/null +++ b/data_acq_and_processing/processing/data_processor/include/processing_live_config.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include + +namespace radar::processing { + +enum class HistoryCommand { + None, + RemoveLast, + ClearAll, +}; + +struct ProcessingLiveConfig { + std::string processor_mode = "pass_through"; + float gain_db = 0.0F; + float phase_deg = 0.0F; + std::string bscan_axis = "abs"; + float bscan_cut_m = 0.824F; + float bscan_max_depth_m = 1.0F; + float bscan_gain = 1.0F; + float bscan_start_freq_mhz = 100.0F; + float bscan_stop_freq_mhz = 8800.0F; + std::uint64_t history_command_seq = 0; + HistoryCommand history_command = HistoryCommand::None; +}; + +class ProcessingLiveConfigLoader { + public: + explicit ProcessingLiveConfigLoader(std::string path); + + [[nodiscard]] auto current() const -> ProcessingLiveConfig; + [[nodiscard]] auto refresh_if_needed() -> ProcessingLiveConfig; + [[nodiscard]] auto revision() const -> std::uint64_t; + + private: + [[nodiscard]] auto read_from_file() const -> ProcessingLiveConfig; + + std::string path_{}; + ProcessingLiveConfig current_{}; + std::filesystem::file_time_type last_write_time_{}; + bool has_last_write_time_ = false; + std::uint64_t revision_ = 0; + std::chrono::steady_clock::time_point next_check_at_{}; +}; + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/data_processor/src/data_processor.cpp b/data_acq_and_processing/processing/data_processor/src/data_processor.cpp new file mode 100644 index 0000000..d39b5a0 --- /dev/null +++ b/data_acq_and_processing/processing/data_processor/src/data_processor.cpp @@ -0,0 +1,156 @@ +#include "data_processor.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "bscan_processor.hpp" +#include "passthrough_processor.hpp" + +namespace radar::processing { +namespace { + +constexpr const char* kDefaultProcessorMode = "pass_through"; +constexpr std::size_t kBscanReplayWindow = 50U; + +[[nodiscard]] auto replay_history_limit(const config::RunConfig& config) -> std::size_t { + const auto preprocessed_capacity = static_cast(std::max(1U, config.rings.preprocessed.capacity)); + const auto results_capacity = static_cast(std::max(1U, config.rings.results.capacity)); + return std::min({preprocessed_capacity, results_capacity, kBscanReplayWindow}); +} + +void publish_result_collection(const ipc::ResultCollection& collection, ipc::ShmRing& results_ring) { + const auto out_bytes = ipc::serialize_result_collection(collection); + if (!results_ring.push(out_bytes)) { + throw std::runtime_error("Results ring slot is too small for serialized collection"); + } +} + +} // namespace + +DataProcessor::DataProcessor( + const config::RunConfig& config, + ipc::ShmRing& preprocessed_ring, + ipc::ShmRing& results_ring, + ProcessorRegistry processors +) + : config_(config), + preprocessed_ring_(preprocessed_ring), + results_ring_(results_ring), + processors_(std::move(processors)), + default_processor_mode_(kDefaultProcessorMode), + live_config_loader_(config.runtime.processing_live_config_path) { + if (processors_.empty()) { + throw std::runtime_error("DataProcessor requires at least one processor"); + } + if (const auto found = processors_.find(default_processor_mode_); found == processors_.end()) { + default_processor_mode_ = processors_.begin()->first; + } +} + +void DataProcessor::run(const std::atomic& stop_requested) { + std::vector bytes{}; + std::deque preprocessed_history{}; + const std::size_t history_limit = replay_history_limit(config_); + std::uint64_t last_replayed_revision = live_config_loader_.revision(); + std::uint64_t last_applied_history_command_seq = 0; + + while (!stop_requested.load(std::memory_order_relaxed)) { + const auto live_config = live_config_loader_.refresh_if_needed(); + const auto live_revision = live_config_loader_.revision(); + auto& processor = resolve_processor(live_config); + + if (live_revision != last_replayed_revision) { + if (live_config.history_command_seq > last_applied_history_command_seq) { + if (live_config.history_command == HistoryCommand::RemoveLast) { + if (!preprocessed_history.empty()) { + preprocessed_history.pop_back(); + } + } else if (live_config.history_command == HistoryCommand::ClearAll) { + preprocessed_history.clear(); + } + last_applied_history_command_seq = live_config.history_command_seq; + } + + if (live_config.processor_mode == "bscan") { + for (const auto& cached : preprocessed_history) { + const auto replay_result = process_collection(cached, processor, live_config); + publish_result_collection(replay_result, results_ring_); + } + } else if (!preprocessed_history.empty()) { + const auto replay_result = process_collection(preprocessed_history.back(), processor, live_config); + publish_result_collection(replay_result, results_ring_); + } + last_replayed_revision = live_revision; + } + + if (preprocessed_ring_.pop(bytes)) { + auto preprocessed = ipc::deserialize_preprocessed_collection(bytes); + preprocessed_history.push_back(std::move(preprocessed)); + while (preprocessed_history.size() > history_limit) { + preprocessed_history.pop_front(); + } + + const auto result_collection = process_collection(preprocessed_history.back(), processor, live_config); + publish_result_collection(result_collection, results_ring_); + continue; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(config_.runtime.idle_sleep_ms)); + } +} + +auto DataProcessor::process_collection( + const ipc::PreprocessedCollection& preprocessed, + ProcessorInterface& processor, + const ProcessingLiveConfig& live_config +) -> ipc::ResultCollection { + ipc::ResultCollection results{}; + results.collection_id = preprocessed.collection_id; + // Keep source monotonic timestamp stable across live-config replays. + results.monotonic_ns = preprocessed.monotonic_ns; + results.blocks.reserve(preprocessed.traces.size()); + + for (const auto& trace : preprocessed.traces) { + ipc::ResultBlock block{}; + block.combo = trace.combo; + block.payloads.reserve(1U); + block.payloads.push_back(processor.process(trace, live_config)); + + results.blocks.push_back(std::move(block)); + } + + return results; +} + +auto DataProcessor::resolve_processor(const ProcessingLiveConfig& live_config) -> ProcessorInterface& { + const std::string requested_mode = + live_config.processor_mode.empty() ? default_processor_mode_ : live_config.processor_mode; + + if (auto found = processors_.find(requested_mode); found != processors_.end()) { + return *(found->second); + } + if (auto fallback = processors_.find(default_processor_mode_); fallback != processors_.end()) { + return *(fallback->second); + } + return *(processors_.begin()->second); +} + +auto create_default_processors() -> ProcessorRegistry { + ProcessorRegistry processors{}; + { + auto processor = std::make_unique(); + processors.emplace(processor->name(), std::move(processor)); + } + { + auto processor = std::make_unique(); + processors.emplace(processor->name(), std::move(processor)); + } + return processors; +} + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/data_processor/src/main.cpp b/data_acq_and_processing/processing/data_processor/src/main.cpp new file mode 100644 index 0000000..903c257 --- /dev/null +++ b/data_acq_and_processing/processing/data_processor/src/main.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "data_processor.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" + +namespace { + +constexpr const char* kDefaultConfigPath = "run_config.json"; + +std::atomic g_stop_requested{false}; + +void signal_handler(int /*signal*/) { + g_stop_requested.store(true, std::memory_order_relaxed); +} + +void install_signal_handlers() { + std::signal(SIGINT, signal_handler); + std::signal(SIGTERM, signal_handler); +} + +[[nodiscard]] auto read_config_path(int argc, char** argv) -> std::string { + std::string config_path = kDefaultConfigPath; + for (int index = 1; index < argc; ++index) { + const std::string arg = argv[index]; + if (arg == "--config" && (index + 1) < argc) { + config_path = argv[++index]; + } + } + return config_path; +} + +} // namespace + +int main(int argc, char** argv) { + install_signal_handlers(); + + try { + const auto config_path = read_config_path(argc, argv); + const auto config = radar::config::load_run_config(config_path); + + auto preprocessed_ring = radar::ipc::ShmRing::open_or_create( + config.rings.preprocessed.name, + config.rings.preprocessed.capacity, + config.rings.preprocessed.slot_size_bytes + ); + auto results_ring = radar::ipc::ShmRing::open_or_create( + config.rings.results.name, + config.rings.results.capacity, + config.rings.results.slot_size_bytes + ); + + radar::processing::DataProcessor processor( + config, + preprocessed_ring, + results_ring, + radar::processing::create_default_processors() + ); + processor.run(g_stop_requested); + return 0; + } catch (const std::exception& exception) { + std::cerr << "data_processor error: " << exception.what() << '\n'; + return 1; + } +} diff --git a/data_acq_and_processing/processing/data_processor/src/processing_live_config.cpp b/data_acq_and_processing/processing/data_processor/src/processing_live_config.cpp new file mode 100644 index 0000000..fc0124a --- /dev/null +++ b/data_acq_and_processing/processing/data_processor/src/processing_live_config.cpp @@ -0,0 +1,189 @@ +#include "processing_live_config.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace radar::processing { +namespace { + +using Json = nlohmann::json; + +[[nodiscard]] auto parse_history_command(const std::string& value) -> HistoryCommand { + if (value == "none") { + return HistoryCommand::None; + } + if (value == "remove_last") { + return HistoryCommand::RemoveLast; + } + if (value == "clear_all") { + return HistoryCommand::ClearAll; + } + throw std::runtime_error("processing.history_command must be one of: none, remove_last, clear_all"); +} + +[[nodiscard]] auto parse_u64_number(const Json& value, const std::string& field_name) -> std::uint64_t { + if (!value.is_number()) { + throw std::runtime_error(field_name + " must be number"); + } + const double numeric = value.get(); + if (numeric < 0.0 || numeric > static_cast(std::numeric_limits::max())) { + throw std::runtime_error(field_name + " is out of uint64 range"); + } + const double rounded = std::round(numeric); + if (std::fabs(numeric - rounded) > 1e-6) { + throw std::runtime_error(field_name + " must be integer"); + } + return static_cast(rounded); +} + +[[nodiscard]] auto parse_live_config(const std::string& json_text, const std::string& path) -> ProcessingLiveConfig { + if (json_text.empty()) { + throw std::runtime_error("Processing live config is empty: " + path); + } + + Json root{}; + try { + root = Json::parse(json_text); + } catch (const Json::parse_error& error) { + throw std::runtime_error("Failed to parse processing live config: " + std::string(error.what())); + } + + if (!root.is_object()) { + throw std::runtime_error("Processing live config root must be JSON object"); + } + + ProcessingLiveConfig config{}; + if (const auto found = root.find("processor_mode"); found != root.end()) { + if (!found->is_string()) { + throw std::runtime_error("processing.processor_mode must be string"); + } + config.processor_mode = found->get(); + } + if (const auto found = root.find("gain_db"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.gain_db must be number"); + } + config.gain_db = static_cast(found->get()); + } + if (const auto found = root.find("phase_deg"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.phase_deg must be number"); + } + config.phase_deg = static_cast(found->get()); + } + if (const auto found = root.find("bscan_axis"); found != root.end()) { + if (!found->is_string()) { + throw std::runtime_error("processing.bscan_axis must be string"); + } + config.bscan_axis = found->get(); + } + if (const auto found = root.find("bscan_cut_m"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.bscan_cut_m must be number"); + } + config.bscan_cut_m = static_cast(found->get()); + } + if (const auto found = root.find("bscan_max_depth_m"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.bscan_max_depth_m must be number"); + } + config.bscan_max_depth_m = static_cast(found->get()); + } + if (const auto found = root.find("bscan_gain"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.bscan_gain must be number"); + } + config.bscan_gain = static_cast(found->get()); + } + if (const auto found = root.find("bscan_start_freq_mhz"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.bscan_start_freq_mhz must be number"); + } + config.bscan_start_freq_mhz = static_cast(found->get()); + } + if (const auto found = root.find("bscan_stop_freq_mhz"); found != root.end()) { + if (!found->is_number()) { + throw std::runtime_error("processing.bscan_stop_freq_mhz must be number"); + } + config.bscan_stop_freq_mhz = static_cast(found->get()); + } + if (const auto found = root.find("history_command_seq"); found != root.end()) { + config.history_command_seq = parse_u64_number(*found, "processing.history_command_seq"); + } + if (const auto found = root.find("history_command"); found != root.end()) { + if (!found->is_string()) { + throw std::runtime_error("processing.history_command must be string"); + } + config.history_command = parse_history_command(found->get()); + } + return config; +} + +} // namespace + +ProcessingLiveConfigLoader::ProcessingLiveConfigLoader(std::string path) + : path_(std::move(path)), + next_check_at_(std::chrono::steady_clock::now()) { + if (path_.empty()) { + throw std::runtime_error("Processing live config path must not be empty"); + } +} + +auto ProcessingLiveConfigLoader::current() const -> ProcessingLiveConfig { + return current_; +} + +auto ProcessingLiveConfigLoader::revision() const -> std::uint64_t { + return revision_; +} + +auto ProcessingLiveConfigLoader::refresh_if_needed() -> ProcessingLiveConfig { + const auto now = std::chrono::steady_clock::now(); + if (now < next_check_at_) { + return current_; + } + next_check_at_ = now + std::chrono::milliseconds(100); + + std::error_code time_error{}; + const auto file_time = std::filesystem::last_write_time(path_, time_error); + if (time_error) { + return current_; + } + + if (has_last_write_time_ && file_time == last_write_time_) { + return current_; + } + + try { + current_ = read_from_file(); + last_write_time_ = file_time; + has_last_write_time_ = true; + ++revision_; + } catch (const std::exception& error) { + std::cerr << "data_processor warning: failed to refresh live processing config: " << error.what() << '\n'; + } + + return current_; +} + +auto ProcessingLiveConfigLoader::read_from_file() const -> ProcessingLiveConfig { + std::ifstream stream(path_); + if (!stream.is_open()) { + throw std::runtime_error("Failed to open live processing config: " + path_); + } + + std::stringstream buffer{}; + buffer << stream.rdbuf(); + return parse_live_config(buffer.str(), path_); +} + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/processors/include/bscan_processor.hpp b/data_acq_and_processing/processing/processors/include/bscan_processor.hpp new file mode 100644 index 0000000..fc9b931 --- /dev/null +++ b/data_acq_and_processing/processing/processors/include/bscan_processor.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "processor_interface.hpp" + +namespace radar::processing { + +class BScanProcessor final : public ProcessorInterface { + public: + [[nodiscard]] auto name() const -> std::string override; + [[nodiscard]] auto process( + const ipc::SweepTraceBlock& trace, + const ProcessingLiveConfig& live_config + ) -> ipc::ResultPayload override; +}; + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/processors/include/passthrough_processor.hpp b/data_acq_and_processing/processing/processors/include/passthrough_processor.hpp new file mode 100644 index 0000000..c849913 --- /dev/null +++ b/data_acq_and_processing/processing/processors/include/passthrough_processor.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "processor_interface.hpp" + +namespace radar::processing { + +class PassThroughProcessor final : public ProcessorInterface { + public: + [[nodiscard]] auto name() const -> std::string override; + [[nodiscard]] auto process( + const ipc::SweepTraceBlock& trace, + const ProcessingLiveConfig& live_config + ) -> ipc::ResultPayload override; +}; + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/processors/include/processor_interface.hpp b/data_acq_and_processing/processing/processors/include/processor_interface.hpp new file mode 100644 index 0000000..78990f4 --- /dev/null +++ b/data_acq_and_processing/processing/processors/include/processor_interface.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "processing_live_config.hpp" +#include "shared_types.hpp" + +namespace radar::processing { + +class ProcessorInterface { + public: + virtual ~ProcessorInterface() = default; + + [[nodiscard]] virtual auto name() const -> std::string = 0; + [[nodiscard]] virtual auto process( + const ipc::SweepTraceBlock& trace, + const ProcessingLiveConfig& live_config + ) -> ipc::ResultPayload = 0; +}; + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/processors/src/bscan_processor.cpp b/data_acq_and_processing/processing/processors/src/bscan_processor.cpp new file mode 100644 index 0000000..a20b01d --- /dev/null +++ b/data_acq_and_processing/processing/processors/src/bscan_processor.cpp @@ -0,0 +1,237 @@ +#include "bscan_processor.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace radar::processing { +namespace { + +constexpr double kPi = 3.14159265358979323846; +constexpr double kSpeedOfLightMetersPerSec = 299'792'458.0; + +struct BScanProfile { + std::vector depth_m{}; + std::vector response{}; +}; + +[[nodiscard]] auto next_power_of_two(std::size_t value) -> std::size_t { + if (value <= 1U) { + return 1U; + } + + std::size_t power = 1U; + while (power < value) { + if (power > (std::numeric_limits::max() >> 1U)) { + return value; + } + power <<= 1U; + } + return power; +} + +void fft_inplace(std::vector>& values, bool inverse) { + const std::size_t size = values.size(); + if (size <= 1U) { + return; + } + + for (std::size_t index = 1U, bit_reversed = 0U; index < size; ++index) { + std::size_t bit = size >> 1U; + while (bit_reversed & bit) { + bit_reversed ^= bit; + bit >>= 1U; + } + bit_reversed ^= bit; + if (index < bit_reversed) { + std::swap(values[index], values[bit_reversed]); + } + } + + for (std::size_t len = 2U; len <= size; len <<= 1U) { + const double angle = 2.0 * kPi * (inverse ? 1.0 : -1.0) / static_cast(len); + const std::complex twiddle_step(std::cos(angle), std::sin(angle)); + const std::size_t half_len = len >> 1U; + + for (std::size_t offset = 0U; offset < size; offset += len) { + std::complex twiddle(1.0, 0.0); + for (std::size_t i = 0U; i < half_len; ++i) { + const auto even = values[offset + i]; + const auto odd = values[offset + i + half_len] * twiddle; + + values[offset + i] = even + odd; + values[offset + i + half_len] = even - odd; + twiddle *= twiddle_step; + } + } + } + + if (!inverse) { + return; + } + + const double scale = 1.0 / static_cast(size); + for (auto& value : values) { + value *= scale; + } +} + +[[nodiscard]] auto select_axis(std::complex sample, std::string_view axis) -> double { + if (axis == "real") { + return std::real(sample); + } + if (axis == "phase") { + return std::arg(sample); + } + return std::abs(sample); +} + +[[nodiscard]] auto fallback_profile(const ipc::SweepTraceBlock& trace) -> BScanProfile { + const std::size_t point_count = std::min(trace.frequency_hz.size(), trace.s21.size()); + BScanProfile fallback{}; + fallback.depth_m.reserve(point_count); + fallback.response.reserve(point_count); + + const float denominator = point_count > 1U ? static_cast(point_count - 1U) : 1.0F; + for (std::size_t index = 0U; index < point_count; ++index) { + const auto& sample = trace.s21[index]; + fallback.depth_m.push_back(static_cast(static_cast(index) / denominator)); + fallback.response.push_back(std::sqrt(sample.re * sample.re + sample.im * sample.im)); + } + return fallback; +} + +[[nodiscard]] auto compute_bscan_profile( + const ipc::SweepTraceBlock& trace, + const ProcessingLiveConfig& live_config +) -> BScanProfile { + const std::size_t point_count = std::min(trace.frequency_hz.size(), trace.s21.size()); + if (point_count < 2U) { + return fallback_profile(trace); + } + + const double configured_start_hz = static_cast(live_config.bscan_start_freq_mhz) * 1'000'000.0; + const double configured_stop_hz = static_cast(live_config.bscan_stop_freq_mhz) * 1'000'000.0; + const double start_hz = std::min(configured_start_hz, configured_stop_hz); + const double stop_hz = std::max(configured_start_hz, configured_stop_hz); + + std::vector filtered_freq_hz{}; + std::vector> filtered_s21{}; + filtered_freq_hz.reserve(point_count); + filtered_s21.reserve(point_count); + + for (std::size_t index = 0U; index < point_count; ++index) { + const double frequency_hz = static_cast(trace.frequency_hz[index]); + if (frequency_hz < start_hz || frequency_hz > stop_hz) { + continue; + } + const auto& sample = trace.s21[index]; + filtered_freq_hz.push_back(frequency_hz); + filtered_s21.emplace_back(static_cast(sample.re), static_cast(sample.im)); + } + + if (filtered_freq_hz.size() < 2U) { + return fallback_profile(trace); + } + + const std::size_t filtered_count = filtered_freq_hz.size(); + const double df = (filtered_freq_hz.back() - filtered_freq_hz.front()) / static_cast(filtered_count - 1U); + if (df <= 0.0) { + return fallback_profile(trace); + } + + const auto start_bin = static_cast(std::llround(filtered_freq_hz.front() / df)); + if (start_bin < 0) { + return fallback_profile(trace); + } + + const auto start_index = static_cast(start_bin); + if (start_index > (std::numeric_limits::max() / 2U)) { + return fallback_profile(trace); + } + if (start_index > (std::numeric_limits::max() - filtered_count + 1U)) { + return fallback_profile(trace); + } + + const std::size_t min_fft_len = 2U * (start_index + filtered_count - 1U); + const std::size_t fft_len = next_power_of_two(min_fft_len); + if (fft_len < min_fft_len || (fft_len & (fft_len - 1U)) != 0U) { + return fallback_profile(trace); + } + if (start_index > fft_len || filtered_count > (fft_len - start_index)) { + return fallback_profile(trace); + } + + std::vector> spectrum(fft_len, std::complex(0.0, 0.0)); + for (std::size_t index = 0U; index < filtered_count; ++index) { + spectrum[start_index + index] = filtered_s21[index]; + } + + fft_inplace(spectrum, true); + + const double dt = 1.0 / (static_cast(fft_len) * df); + const double cut_m = std::max(0.0, static_cast(live_config.bscan_cut_m)); + const double max_depth_m = std::max(0.0, static_cast(live_config.bscan_max_depth_m)); + const double gain = static_cast(live_config.bscan_gain); + const double window_start = 2.0 * cut_m; + const double window_stop = window_start + (2.0 * max_depth_m); + + BScanProfile profile{}; + profile.depth_m.reserve(spectrum.size()); + profile.response.reserve(spectrum.size()); + + const std::string_view axis = live_config.bscan_axis; + for (std::size_t index = 0U; index < spectrum.size(); ++index) { + const double depth_raw = static_cast(index) * dt * kSpeedOfLightMetersPerSec; + if (depth_raw < window_start || depth_raw > window_stop) { + continue; + } + + const double one_way_depth = (depth_raw - window_start) / 2.0; + double gain_shape = std::pow(one_way_depth, gain); + if (!std::isfinite(gain_shape)) { + gain_shape = 0.0; + } + + const double axis_value = select_axis(spectrum[index], axis); + const double output_value = axis_value * gain_shape; + + profile.depth_m.push_back(static_cast(one_way_depth)); + profile.response.push_back(static_cast(output_value)); + } + + return profile; +} + +} // namespace + +auto BScanProcessor::name() const -> std::string { + return "bscan"; +} + +auto BScanProcessor::process(const ipc::SweepTraceBlock& trace, const ProcessingLiveConfig& live_config) + -> ipc::ResultPayload { + ipc::ResultPayload payload{}; + payload.processing_name = name(); + payload.kind = ipc::ResultKind::TraceComplex; + + auto profile = compute_bscan_profile(trace, live_config); + payload.frequency_hz = std::move(profile.depth_m); + payload.trace.reserve(profile.response.size()); + for (const auto value : profile.response) { + payload.trace.push_back(ipc::Complex32{ + .re = value, + .im = 0.0F, + }); + } + + return payload; +} + +} // namespace radar::processing diff --git a/data_acq_and_processing/processing/processors/src/passthrough_processor.cpp b/data_acq_and_processing/processing/processors/src/passthrough_processor.cpp new file mode 100644 index 0000000..cba60ed --- /dev/null +++ b/data_acq_and_processing/processing/processors/src/passthrough_processor.cpp @@ -0,0 +1,39 @@ +#include "passthrough_processor.hpp" + +#include + +namespace radar::processing { +namespace { + +constexpr float kPi = 3.14159265358979323846F; + +} // namespace + +auto PassThroughProcessor::name() const -> std::string { + return "pass_through"; +} + +auto PassThroughProcessor::process(const ipc::SweepTraceBlock& trace, const ProcessingLiveConfig& live_config) + -> ipc::ResultPayload { + ipc::ResultPayload payload{}; + payload.processing_name = name(); + payload.kind = ipc::ResultKind::TraceComplex; + payload.frequency_hz = trace.frequency_hz; + payload.trace = trace.s21; + + const float linear_gain = std::pow(10.0F, live_config.gain_db / 20.0F); + const float phase_rad = live_config.phase_deg * (kPi / 180.0F); + const float cos_phase = std::cos(phase_rad); + const float sin_phase = std::sin(phase_rad); + + for (auto& sample : payload.trace) { + const float re = sample.re; + const float im = sample.im; + sample.re = linear_gain * ((re * cos_phase) - (im * sin_phase)); + sample.im = linear_gain * ((re * sin_phase) + (im * cos_phase)); + } + + return payload; +} + +} // namespace radar::processing diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/radar_driver.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/radar_driver.hpp new file mode 100644 index 0000000..78c06a4 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/radar_driver.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "shared_types.hpp" + +namespace radar::drivers { + +/** + * @brief One S21 sweep acquired from the radar. + * + * Both vectors must have equal size and aligned indices. + */ +struct SweepTrace { + std::vector frequency_hz{}; + std::vector s21{}; +}; + +/** + * @brief Minimal radar interface used by the sweep orchestrator. + * + * Implementations are expected to be lightweight: configuration is handled by + * the Python layer, while this interface only opens/closes and acquires S21. + */ +class RadarDriver { + public: + virtual ~RadarDriver() = default; + + /** @brief Open underlying transport and prepare acquisition. */ + virtual void open() = 0; + /** @brief Release all allocated resources. */ + virtual void close() = 0; + /** @brief Acquire one S21 sweep. */ + [[nodiscard]] virtual auto acquire_s21_sweep() -> SweepTrace = 0; +}; + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/switch_driver.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/switch_driver.hpp new file mode 100644 index 0000000..e99ce8e --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/interfaces/switch_driver.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace radar::drivers { + +/** + * @brief Unified RF switch interface consumed by the orchestrator. + */ +class SwitchDriver { + public: + virtual ~SwitchDriver() = default; + + /** @brief Open underlying transport and set initial switch state. */ + virtual void open() = 0; + /** @brief Release driver resources. */ + virtual void close() = 0; + /** @brief Number of selectable positions exposed by this switch. */ + [[nodiscard]] virtual auto position_count() const -> std::uint32_t = 0; + /** @brief Switch to a 0-based position. */ + virtual void switch_to(std::uint32_t position) = 0; +}; + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_lifecycle.cpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_lifecycle.cpp new file mode 100644 index 0000000..7e0cabe --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_lifecycle.cpp @@ -0,0 +1,212 @@ +#include "../librevna_minimal_driver.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "librevna_protocol_common.hpp" + +namespace radar::drivers { +namespace detail = radar::drivers::librevna::detail; +namespace { + +constexpr std::uint32_t kNativeAcquireMaxAttempts = 3U; + +[[nodiscard]] auto is_retryable_native_acquire_error(std::string_view message) -> bool { + constexpr std::array kRetryableSubstrings = { + "Timeout waiting for expected LibreVNA packet type", + "Timeout waiting for LibreVNA ACK", + "LibreVNA returned NACK", + "Failed to read LibreVNA USB bulk packet", + "Failed to write LibreVNA USB bulk packet", + }; + + return std::any_of( + kRetryableSubstrings.begin(), + kRetryableSubstrings.end(), + [message](std::string_view needle) { + return message.find(needle) != std::string_view::npos; + } + ); +} + +} // namespace + +LibreVnaMinimalDriver::LibreVnaMinimalDriver(LibreVnaMinimalDriverSettings settings) : settings_(std::move(settings)) {} + +void LibreVnaMinimalDriver::open() { + if (is_open_) { + return; + } + if (settings_.sweep.points == 0U) { + throw std::runtime_error("Radar sweep points must be > 0"); + } + + if (settings_.mode == config::DriverMode::Native) { + open_native(); + } + + is_open_ = true; +} + +void LibreVnaMinimalDriver::close() { + if (!is_open_) { + return; + } + + if (settings_.mode == config::DriverMode::Native) { + close_native(); + } + + is_open_ = false; +} + +auto LibreVnaMinimalDriver::acquire_s21_sweep() -> SweepTrace { + if (!is_open_) { + throw std::runtime_error("Radar driver is not open"); + } + + ++sweep_index_; + switch (settings_.mode) { + case config::DriverMode::Mock: + return acquire_mock(); + case config::DriverMode::Native: { + std::exception_ptr last_exception{}; + std::string last_message{}; + + for (std::uint32_t attempt = 1; attempt <= kNativeAcquireMaxAttempts; ++attempt) { + try { + return acquire_native(); + } catch (const std::exception& exception) { + last_exception = std::current_exception(); + last_message = exception.what(); + + if (!is_retryable_native_acquire_error(last_message) || attempt == kNativeAcquireMaxAttempts) { + break; + } + + // Recover from transient USB/protocol stalls by reconnecting the device. + close_native(); + open_native(); + } + } + + if (last_exception != nullptr) { + std::rethrow_exception(last_exception); + } + throw std::runtime_error("Native acquisition failed without exception detail"); + } + default: + throw std::runtime_error("Unsupported radar driver mode"); + } +} + +auto LibreVnaMinimalDriver::acquire_mock() -> SweepTrace { + SweepTrace trace{}; + trace.frequency_hz.reserve(settings_.sweep.points); + trace.s21.reserve(settings_.sweep.points); + + const auto span_hz = settings_.sweep.stop_hz - settings_.sweep.start_hz; + const auto denominator = settings_.sweep.points > 1U ? static_cast(settings_.sweep.points - 1U) : 1.0F; + + for (std::uint32_t point = 0; point < settings_.sweep.points; ++point) { + const auto ratio = static_cast(point) / denominator; + const auto frequency_hz = settings_.sweep.start_hz + span_hz * ratio; + const auto phase = 2.0F * detail::kPi * (frequency_hz / std::max(settings_.mock_signal_hz, 1.0F)) + + static_cast(sweep_index_) * 0.05F; + const auto envelope = 0.6F + 0.4F * std::sin(0.5F * phase); + + ipc::Complex32 sample{}; + sample.re = envelope * std::cos(phase); + sample.im = envelope * std::sin(phase); + + trace.frequency_hz.push_back(frequency_hz); + trace.s21.push_back(sample); + } + + return trace; +} + +auto LibreVnaMinimalDriver::acquire_native() -> SweepTrace { + if (usb_handle_ == nullptr) { + throw std::runtime_error("LibreVNA native handle is not open"); + } + + // Drop stale datapoints left in queue by previous operations. + while (pop_packet(detail::kPacketVnaDatapoint).has_value()) { + } + + send_packet_no_payload(detail::kPacketInitiateSweep, true); + + SweepTrace trace{}; + trace.frequency_hz.assign(settings_.sweep.points, 0.0F); + trace.s21.assign(settings_.sweep.points, ipc::Complex32{}); + + std::vector received(settings_.sweep.points, 0U); + std::uint32_t received_count = 0; + + const auto ifbw_hz = std::max(settings_.sweep.if_bandwidth_hz, 1.0F); + const auto estimated_sweep_ms = static_cast( + std::ceil((1'000.0 * static_cast(settings_.sweep.points)) / static_cast(ifbw_hz)) + ); + // Keep generous timeout margin on slower hosts. + const auto timeout_ms = std::max(20'000ULL, estimated_sweep_ms * 8ULL + 1'000ULL); + const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms); + + while (received_count < settings_.sweep.points) { + NativePacket packet{}; + try { + packet = wait_for_packet(detail::kPacketVnaDatapoint, deadline); + } catch (const std::exception& exception) { + throw std::runtime_error( + "Timeout while collecting VNADatapoints (" + std::to_string(received_count) + "/" + + std::to_string(settings_.sweep.points) + " points received): " + exception.what() + ); + } + + std::uint32_t point_number = 0; + float frequency_hz = 0.0F; + ipc::Complex32 s21{}; + + if (!decode_vna_datapoint_s21(packet.payload, point_number, frequency_hz, s21)) { + throw std::runtime_error("Failed to decode S21 from VNADatapoint packet"); + } + if (point_number >= settings_.sweep.points) { + throw std::runtime_error("Received out-of-range VNADatapoint index"); + } + + if (received[point_number] == 0U) { + received[point_number] = 1U; + ++received_count; + } + + trace.frequency_hz[point_number] = frequency_hz; + trace.s21[point_number] = s21; + } + + return trace; +} + +void LibreVnaMinimalDriver::validate_device_info_payload(std::span payload) const { + if (payload.size() != detail::kDeviceInfoPayloadSize) { + throw std::runtime_error("Unexpected DeviceInfo payload size"); + } + + const auto protocol = detail::read_u16_le(payload, detail::kDeviceInfoProtocolOffset); + if (protocol != detail::kProtocolV14) { + throw std::runtime_error("Unsupported LibreVNA protocol version (expected v14)"); + } + + const auto ports = payload[detail::kDeviceInfoNumPortsOffset]; + if (ports < 2U) { + throw std::runtime_error("LibreVNA reported invalid number of ports"); + } +} + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_protocol.cpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_protocol.cpp new file mode 100644 index 0000000..793729b --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_protocol.cpp @@ -0,0 +1,130 @@ +#include "../librevna_minimal_driver.hpp" + +#include +#include +#include +#include +#include + +#include "librevna_protocol_common.hpp" + +namespace radar::drivers { +namespace detail = radar::drivers::librevna::detail; + +auto LibreVnaMinimalDriver::encode_frame( + std::uint8_t packet_type, + std::span payload +) -> std::vector { + const auto length = payload.size() + detail::kFrameOverheadBytes; + if (length > 0xFFFFU) { + throw std::runtime_error("Protocol frame is too large"); + } + + std::vector frame(length, 0); + frame[0] = detail::kFrameHeader; + detail::write_u16_le(frame, 1, static_cast(length)); + frame[3] = packet_type; + std::copy(payload.begin(), payload.end(), frame.begin() + 4); + + std::uint32_t crc = 0; + if (packet_type != detail::kPacketVnaDatapoint) { + crc = crc32(std::span(frame.data(), frame.size() - 4U)); + } + detail::write_u32_le(frame, frame.size() - 4U, crc); + + return frame; +} + +auto LibreVnaMinimalDriver::decode_vna_datapoint_s21( + std::span payload, + std::uint32_t& point_number_out, + float& frequency_out, + ipc::Complex32& s21_out +) -> bool { + // VNADatapoint payload layout: + // [0..7]=freq_or_time, [8..9]=cdbm, [10..11]=point_number, + // followed by N tuples of {real:f32, imag:f32, flags:u8}. + if (payload.size() < 12U) { + return false; + } + + const auto values_block = payload.size() - 12U; + if ((values_block % 9U) != 0U) { + return false; + } + + const auto num_values = values_block / 9U; + if (num_values == 0U) { + return false; + } + + point_number_out = detail::read_u16_le(payload, 10); + frequency_out = static_cast(detail::read_u64_le(payload, 0)); + + const auto real_offset = 12U; + const auto imag_offset = real_offset + (4U * num_values); + const auto flags_offset = imag_offset + (4U * num_values); + + std::array, 8> ref_by_stage{}; + std::array, 8> measured_by_stage{}; + std::array has_ref{}; + std::array has_measured{}; + + for (std::size_t index = 0; index < num_values; ++index) { + const auto flags = payload[flags_offset + index]; + const auto stage = static_cast(flags >> 5U); + if (stage >= ref_by_stage.size()) { + continue; + } + + const auto value = std::complex( + detail::read_f32_le(payload, real_offset + (4U * index)), + detail::read_f32_le(payload, imag_offset + (4U * index)) + ); + + const bool is_reference = (flags & detail::kReferenceFlagMask) != 0U; + if ((flags & detail::kPort1Mask) != 0U && is_reference) { + ref_by_stage[stage] = value; + has_ref[stage] = true; + } + if ((flags & detail::kPort2Mask) != 0U && !is_reference) { + measured_by_stage[stage] = value; + has_measured[stage] = true; + } + } + + // We need one reference sample from port1 and one measured sample from port2. + for (std::size_t stage = 0; stage < ref_by_stage.size(); ++stage) { + if (!has_ref[stage] || !has_measured[stage]) { + continue; + } + if (std::norm(ref_by_stage[stage]) <= 0.0F) { + continue; + } + + const auto ratio = measured_by_stage[stage] / ref_by_stage[stage]; + s21_out.re = ratio.real(); + s21_out.im = ratio.imag(); + return true; + } + + return false; +} + +auto LibreVnaMinimalDriver::crc32(std::span data) -> std::uint32_t { + std::uint32_t crc = 0xFFFFFFFFU; + for (const auto byte : data) { + crc ^= static_cast(byte); + for (int bit = 0; bit < 8; ++bit) { + const auto lsb = crc & 1U; + crc >>= 1U; + if (lsb != 0U) { + crc ^= 0xEDB88320U; + } + } + } + return ~crc; +} + +} // namespace radar::drivers + diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_transport.cpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_transport.cpp new file mode 100644 index 0000000..bbfeb98 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_minimal_driver_transport.cpp @@ -0,0 +1,359 @@ +#include "../librevna_minimal_driver.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "librevna_protocol_common.hpp" + +namespace radar::drivers { +namespace detail = radar::drivers::librevna::detail; +namespace { + +[[nodiscard]] auto libusb_error_message(const std::string& prefix, int status_code) -> std::string { + return prefix + ": " + libusb_error_name(status_code); +} + +[[nodiscard]] auto is_supported_vid_pid(std::uint16_t vendor_id, std::uint16_t product_id) -> bool { + return std::any_of( + detail::kSupportedUsbIds.begin(), + detail::kSupportedUsbIds.end(), + [vendor_id, product_id](const auto& pair) { + return pair.first == vendor_id && pair.second == product_id; + } + ); +} + +[[nodiscard]] auto parse_serial_string(libusb_device_handle* handle, std::uint8_t serial_index) -> std::string { + if (handle == nullptr || serial_index == 0U) { + return {}; + } + + std::array serial_bytes{}; + const auto length = libusb_get_string_descriptor_ascii( + handle, + serial_index, + serial_bytes.data(), + static_cast(serial_bytes.size()) + ); + if (length <= 0) { + return {}; + } + + return std::string( + reinterpret_cast(serial_bytes.data()), + reinterpret_cast(serial_bytes.data() + length) + ); +} + +[[nodiscard]] auto find_matching_device_handle( + libusb_context* usb_context, + const std::string& expected_serial +) -> libusb_device_handle* { + libusb_device** devices = nullptr; + const auto device_count = libusb_get_device_list(usb_context, &devices); + if (device_count < 0) { + throw std::runtime_error( + libusb_error_message("Failed to enumerate USB devices", static_cast(device_count)) + ); + } + + libusb_device_handle* selected_handle = nullptr; + for (ssize_t index = 0; index < device_count; ++index) { + auto* device = devices[index]; + if (device == nullptr) { + continue; + } + + libusb_device_descriptor descriptor{}; + const auto descriptor_status = libusb_get_device_descriptor(device, &descriptor); + if (descriptor_status != LIBUSB_SUCCESS) { + continue; + } + if (!is_supported_vid_pid(descriptor.idVendor, descriptor.idProduct)) { + continue; + } + + libusb_device_handle* candidate_handle = nullptr; + if (libusb_open(device, &candidate_handle) != LIBUSB_SUCCESS || candidate_handle == nullptr) { + continue; + } + + if (!expected_serial.empty()) { + const auto serial = parse_serial_string(candidate_handle, descriptor.iSerialNumber); + if (serial != expected_serial) { + libusb_close(candidate_handle); + continue; + } + } + + selected_handle = candidate_handle; + break; + } + + libusb_free_device_list(devices, 1); + return selected_handle; +} + +} // namespace + +void LibreVnaMinimalDriver::open_native() { + if (usb_context_ != nullptr || usb_handle_ != nullptr) { + throw std::runtime_error("LibreVNA native state is already initialized"); + } + + const auto init_status = libusb_init(&usb_context_); + if (init_status != LIBUSB_SUCCESS) { + usb_context_ = nullptr; + throw std::runtime_error(libusb_error_message("Failed to initialize libusb", init_status)); + } + + try { + auto* selected_handle = find_matching_device_handle(usb_context_, settings_.serial); + + if (selected_handle == nullptr) { + const auto serial_hint = settings_.serial.empty() ? std::string() : " for serial '" + settings_.serial + "'"; + throw std::runtime_error("No compatible LibreVNA USB device found" + serial_hint); + } + + usb_handle_ = selected_handle; + + const auto auto_detach_status = libusb_set_auto_detach_kernel_driver(usb_handle_, 1); + if (auto_detach_status != LIBUSB_SUCCESS && auto_detach_status != LIBUSB_ERROR_NOT_SUPPORTED) { + throw std::runtime_error( + libusb_error_message("Failed to configure USB auto-detach kernel driver", auto_detach_status) + ); + } + + const auto claim_status = libusb_claim_interface(usb_handle_, detail::kUsbInterface); + if (claim_status != LIBUSB_SUCCESS) { + throw std::runtime_error(libusb_error_message("Failed to claim LibreVNA USB interface", claim_status)); + } + interface_claimed_ = true; + + rx_buffer_.clear(); + packet_queue_.clear(); + + send_packet_no_payload(detail::kPacketRequestDeviceInfo, true); + const auto info_packet = wait_for_packet( + detail::kPacketDeviceInfo, + std::chrono::steady_clock::now() + std::chrono::seconds(detail::kDeviceInfoTimeoutSeconds) + ); + validate_device_info_payload(info_packet.payload); + protocol_version_ = detail::read_u16_le(info_packet.payload, detail::kDeviceInfoProtocolOffset); + device_num_ports_ = info_packet.payload[detail::kDeviceInfoNumPortsOffset]; + } catch (...) { + close_native(); + throw; + } +} + +void LibreVnaMinimalDriver::close_native() { + rx_buffer_.clear(); + packet_queue_.clear(); + + if (usb_handle_ != nullptr && interface_claimed_) { + libusb_release_interface(usb_handle_, detail::kUsbInterface); + interface_claimed_ = false; + } + + if (usb_handle_ != nullptr) { + libusb_close(usb_handle_); + usb_handle_ = nullptr; + } + + if (usb_context_ != nullptr) { + libusb_exit(usb_context_); + usb_context_ = nullptr; + } + + protocol_version_ = 0; + device_num_ports_ = 0; +} + +void LibreVnaMinimalDriver::send_packet( + std::uint8_t packet_type, + std::span payload, + bool require_ack +) { + if (usb_handle_ == nullptr) { + throw std::runtime_error("Cannot send packet: LibreVNA USB handle is not open"); + } + + auto frame = encode_frame(packet_type, payload); + + int transferred = 0; + const auto transfer_status = libusb_bulk_transfer( + usb_handle_, + detail::kEndpointOut, + reinterpret_cast(frame.data()), + static_cast(frame.size()), + &transferred, + detail::kUsbWriteTimeoutMs + ); + if (transfer_status != LIBUSB_SUCCESS) { + throw std::runtime_error(libusb_error_message("Failed to write LibreVNA USB bulk packet", transfer_status)); + } + if (transferred != static_cast(frame.size())) { + throw std::runtime_error("Incomplete LibreVNA USB bulk write"); + } + + if (require_ack) { + wait_for_ack(std::chrono::steady_clock::now() + std::chrono::milliseconds(detail::kAckTimeoutMs)); + } +} + +void LibreVnaMinimalDriver::send_packet_no_payload(std::uint8_t packet_type, bool require_ack) { + send_packet(packet_type, std::span{}, require_ack); +} + +void LibreVnaMinimalDriver::wait_for_ack(std::chrono::steady_clock::time_point deadline) { + while (std::chrono::steady_clock::now() < deadline) { + std::optional ack_or_nack{}; + for (auto iter = packet_queue_.begin(); iter != packet_queue_.end(); ++iter) { + if (iter->packet_type != detail::kPacketAck && iter->packet_type != detail::kPacketNack) { + continue; + } + ack_or_nack = std::move(*iter); + packet_queue_.erase(iter); + break; + } + + if (ack_or_nack.has_value()) { + if (ack_or_nack->packet_type == detail::kPacketAck) { + return; + } + throw std::runtime_error("LibreVNA returned NACK"); + } + + pump_usb(deadline); + } + + throw std::runtime_error("Timeout waiting for LibreVNA ACK"); +} + +auto LibreVnaMinimalDriver::wait_for_packet( + std::uint8_t expected_type, + std::chrono::steady_clock::time_point deadline +) -> NativePacket { + while (std::chrono::steady_clock::now() < deadline) { + if (auto packet = pop_packet(expected_type); packet.has_value()) { + return *packet; + } + pump_usb(deadline); + } + + throw std::runtime_error("Timeout waiting for expected LibreVNA packet type"); +} + +void LibreVnaMinimalDriver::pump_usb(std::chrono::steady_clock::time_point deadline) { + if (usb_handle_ == nullptr) { + throw std::runtime_error("Cannot read packets: LibreVNA USB handle is not open"); + } + + const auto now = std::chrono::steady_clock::now(); + if (now >= deadline) { + return; + } + + const auto remaining_ms = std::chrono::duration_cast(deadline - now).count(); + const auto timeout_ms = static_cast( + std::clamp(remaining_ms, detail::kUsbReadPollMinTimeoutMs, detail::kUsbReadPollMaxTimeoutMs) + ); + + std::array buffer{}; + int transferred = 0; + const auto transfer_status = libusb_bulk_transfer( + usb_handle_, + detail::kEndpointIn, + buffer.data(), + static_cast(buffer.size()), + &transferred, + timeout_ms + ); + + if (transfer_status == LIBUSB_ERROR_TIMEOUT) { + return; + } + if (transfer_status != LIBUSB_SUCCESS) { + throw std::runtime_error(libusb_error_message("Failed to read LibreVNA USB bulk packet", transfer_status)); + } + if (transferred <= 0) { + return; + } + + rx_buffer_.insert(rx_buffer_.end(), buffer.begin(), buffer.begin() + transferred); + decode_frames_from_buffer(); +} + +void LibreVnaMinimalDriver::decode_frames_from_buffer() { + while (true) { + const auto header_iter = std::find(rx_buffer_.begin(), rx_buffer_.end(), detail::kFrameHeader); + if (header_iter == rx_buffer_.end()) { + rx_buffer_.clear(); + return; + } + + if (header_iter != rx_buffer_.begin()) { + rx_buffer_.erase(rx_buffer_.begin(), header_iter); + } + + if (rx_buffer_.size() < 4U) { + return; + } + + const auto declared_length = detail::read_u16_le(rx_buffer_, 1); + if (declared_length < detail::kFrameOverheadBytes || declared_length > detail::kMaxFrameLengthBytes) { + rx_buffer_.erase(rx_buffer_.begin()); + continue; + } + + if (rx_buffer_.size() < declared_length) { + return; + } + + const std::vector frame(rx_buffer_.begin(), rx_buffer_.begin() + declared_length); + rx_buffer_.erase(rx_buffer_.begin(), rx_buffer_.begin() + declared_length); + + const auto packet_type = frame[3]; + const auto received_crc = detail::read_u32_le(frame, frame.size() - 4U); + + if (packet_type == detail::kPacketVnaDatapoint) { + if (received_crc != 0U) { + throw std::runtime_error("Invalid VNADatapoint CRC (expected zero)"); + } + } else { + const auto expected_crc = crc32(std::span(frame.data(), frame.size() - 4U)); + if (received_crc != expected_crc) { + throw std::runtime_error("Invalid LibreVNA packet CRC"); + } + } + + NativePacket packet{}; + packet.packet_type = packet_type; + packet.payload.assign(frame.begin() + 4, frame.end() - 4); + packet_queue_.push_back(std::move(packet)); + } +} + +auto LibreVnaMinimalDriver::pop_packet(std::uint8_t packet_type) -> std::optional { + for (auto iter = packet_queue_.begin(); iter != packet_queue_.end(); ++iter) { + if (iter->packet_type != packet_type) { + continue; + } + + auto packet = std::move(*iter); + packet_queue_.erase(iter); + return packet; + } + + return std::nullopt; +} + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_protocol_common.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_protocol_common.hpp new file mode 100644 index 0000000..477976f --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna/librevna_protocol_common.hpp @@ -0,0 +1,112 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace radar::drivers::librevna::detail { + +constexpr float kPi = 3.14159265358979323846F; + +// Frame format: +// [0]=header, [1..2]=length_le, [3]=packet_type, [...payload...], [crc32_le] +constexpr std::uint8_t kFrameHeader = 0x5A; +constexpr std::size_t kFrameOverheadBytes = 8; +constexpr std::size_t kMaxFrameLengthBytes = 4096; + +constexpr unsigned char kEndpointOut = 0x01; +constexpr unsigned char kEndpointIn = 0x81; +constexpr int kUsbInterface = 0; + +constexpr std::uint8_t kPacketDeviceInfo = 5; +constexpr std::uint8_t kPacketAck = 7; +constexpr std::uint8_t kPacketNack = 10; +constexpr std::uint8_t kPacketRequestDeviceInfo = 15; +constexpr std::uint8_t kPacketVnaDatapoint = 27; +constexpr std::uint8_t kPacketInitiateSweep = 32; + +constexpr std::size_t kDeviceInfoPayloadSize = 57; +constexpr std::size_t kDeviceInfoProtocolOffset = 0; +constexpr std::size_t kDeviceInfoNumPortsOffset = 54; +constexpr std::uint16_t kProtocolV14 = 14; + +constexpr std::uint8_t kReferenceFlagMask = 0x10; +constexpr std::uint8_t kPort1Mask = 0x01; +constexpr std::uint8_t kPort2Mask = 0x02; + +constexpr std::array, 3> kSupportedUsbIds = { + std::pair{0x0483, 0x564E}, + std::pair{0x0483, 0x4121}, + std::pair{0x1209, 0x4121}, +}; + +constexpr int kUsbWriteTimeoutMs = 500; +constexpr int kAckTimeoutMs = 800; +constexpr int kDeviceInfoTimeoutSeconds = 2; +constexpr std::size_t kUsbReadChunkBytes = 16 * 1024; +constexpr int kUsbReadPollMinTimeoutMs = 1; +constexpr int kUsbReadPollMaxTimeoutMs = 50; + +[[nodiscard]] inline auto read_u16_le(std::span data, std::size_t offset) -> std::uint16_t { + if ((offset + sizeof(std::uint16_t)) > data.size()) { + throw std::runtime_error("Failed to decode uint16 from payload"); + } + return static_cast(data[offset]) | + (static_cast(data[offset + 1]) << 8U); +} + +[[nodiscard]] inline auto read_u32_le(std::span data, std::size_t offset) -> std::uint32_t { + if ((offset + sizeof(std::uint32_t)) > data.size()) { + throw std::runtime_error("Failed to decode uint32 from payload"); + } + return static_cast(data[offset]) | + (static_cast(data[offset + 1]) << 8U) | + (static_cast(data[offset + 2]) << 16U) | + (static_cast(data[offset + 3]) << 24U); +} + +[[nodiscard]] inline auto read_u64_le(std::span data, std::size_t offset) -> std::uint64_t { + if ((offset + sizeof(std::uint64_t)) > data.size()) { + throw std::runtime_error("Failed to decode uint64 from payload"); + } + + std::uint64_t value = 0; + for (std::size_t index = 0; index < sizeof(std::uint64_t); ++index) { + value |= static_cast(data[offset + index]) << (index * 8U); + } + return value; +} + +[[nodiscard]] inline auto read_f32_le(std::span data, std::size_t offset) -> float { + const auto raw = read_u32_le(data, offset); + float out = 0.0F; + std::memcpy(&out, &raw, sizeof(float)); + return out; +} + +inline void write_u16_le(std::span data, std::size_t offset, std::uint16_t value) { + if ((offset + sizeof(std::uint16_t)) > data.size()) { + throw std::runtime_error("Failed to encode uint16 into frame"); + } + + data[offset] = static_cast(value & 0xFFU); + data[offset + 1] = static_cast((value >> 8U) & 0xFFU); +} + +inline void write_u32_le(std::span data, std::size_t offset, std::uint32_t value) { + if ((offset + sizeof(std::uint32_t)) > data.size()) { + throw std::runtime_error("Failed to encode uint32 into frame"); + } + + data[offset] = static_cast(value & 0xFFU); + data[offset + 1] = static_cast((value >> 8U) & 0xFFU); + data[offset + 2] = static_cast((value >> 16U) & 0xFFU); + data[offset + 3] = static_cast((value >> 24U) & 0xFFU); +} + +} // namespace radar::drivers::librevna::detail + diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna_minimal_driver.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna_minimal_driver.hpp new file mode 100644 index 0000000..2340f9b --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/radar/librevna_minimal_driver.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#if __has_include() +#include +#else +#include +#endif + +#include "radar_driver.hpp" +#include "run_config.hpp" + +namespace radar::drivers { + +/** + * @brief Runtime settings for minimal LibreVNA acquisition. + */ +struct LibreVnaMinimalDriverSettings { + config::DriverMode mode = config::DriverMode::Mock; + std::string serial{}; + config::RadarSweepSettings sweep{}; + float mock_signal_hz = 5'000'000.0F; +}; + +/** + * @brief Minimal radar driver that acquires S21 sweeps from LibreVNA. + * + * This class intentionally keeps scope narrow: open/close transport and + * acquire one sweep. Full device configuration is expected to be done by the + * Python layer before this process starts. + */ +class LibreVnaMinimalDriver final : public RadarDriver { + public: + explicit LibreVnaMinimalDriver(LibreVnaMinimalDriverSettings settings); + + void open() override; + void close() override; + [[nodiscard]] auto acquire_s21_sweep() -> SweepTrace override; + + private: + /** + * @brief Raw protocol packet decoded from framed USB stream. + */ + struct NativePacket { + std::uint8_t packet_type = 0; + std::vector payload{}; + }; + + [[nodiscard]] auto acquire_mock() -> SweepTrace; + [[nodiscard]] auto acquire_native() -> SweepTrace; + + void open_native(); + void close_native(); + + void send_packet(std::uint8_t packet_type, std::span payload, bool require_ack); + void send_packet_no_payload(std::uint8_t packet_type, bool require_ack); + void wait_for_ack(std::chrono::steady_clock::time_point deadline); + [[nodiscard]] auto wait_for_packet(std::uint8_t expected_type, std::chrono::steady_clock::time_point deadline) + -> NativePacket; + void pump_usb(std::chrono::steady_clock::time_point deadline); + void decode_frames_from_buffer(); + + [[nodiscard]] auto pop_packet(std::uint8_t packet_type) -> std::optional; + [[nodiscard]] static auto encode_frame(std::uint8_t packet_type, std::span payload) + -> std::vector; + [[nodiscard]] static auto decode_vna_datapoint_s21( + std::span payload, + std::uint32_t& point_number_out, + float& frequency_out, + ipc::Complex32& s21_out + ) -> bool; + [[nodiscard]] static auto crc32(std::span data) -> std::uint32_t; + void validate_device_info_payload(std::span payload) const; + + LibreVnaMinimalDriverSettings settings_{}; + bool is_open_ = false; + std::uint64_t sweep_index_ = 0; + + libusb_context* usb_context_ = nullptr; + libusb_device_handle* usb_handle_ = nullptr; + bool interface_claimed_ = false; + + std::vector rx_buffer_{}; + std::deque packet_queue_{}; + + std::uint16_t protocol_version_ = 0; + std::uint8_t device_num_ports_ = 0; +}; + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.cpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.cpp new file mode 100644 index 0000000..74fe792 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.cpp @@ -0,0 +1,160 @@ +#include "h7992_minimal_driver.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace radar::drivers { +namespace { + +// Position mapping for H7992 control pins: +// position -> (A, B) +constexpr std::array, 4> kPositionToAB = { + std::array{0, 0}, + std::array{0, 1}, + std::array{1, 0}, + std::array{1, 1}, +}; + +void validate_open_settings(const H7992MinimalDriverSettings& settings) { + if (settings.positions == 0U || settings.positions > 4U) { + throw std::runtime_error("H7992 switch positions must be in range [1, 4] for " + settings.name); + } + if (settings.default_position >= settings.positions) { + throw std::runtime_error("Switch default_position out of range for " + settings.name); + } +} + +[[nodiscard]] auto make_line_values(std::uint8_t pin_a_state, std::uint8_t pin_b_state) -> gpio_v2_line_values { + gpio_v2_line_values values{}; + values.mask = (1ULL << 0U) | (1ULL << 1U); + values.bits = + (static_cast(pin_a_state) << 0U) | (static_cast(pin_b_state) << 1U); + return values; +} + +} // namespace + +H7992MinimalDriver::H7992MinimalDriver(H7992MinimalDriverSettings settings) : settings_(std::move(settings)) {} + +void H7992MinimalDriver::open() { + if (is_open_) { + return; + } + validate_open_settings(settings_); + + if (settings_.mode == config::DriverMode::Native) { + open_native(); + } + + is_open_ = true; + switch_to(settings_.default_position); +} + +void H7992MinimalDriver::close() { + if (!is_open_) { + return; + } + + if (settings_.mode == config::DriverMode::Native) { + close_native(); + } + + is_open_ = false; +} + +auto H7992MinimalDriver::position_count() const -> std::uint32_t { + return settings_.positions; +} + +void H7992MinimalDriver::switch_to(std::uint32_t position) { + if (!is_open_) { + throw std::runtime_error("Switch driver is not open for " + settings_.name); + } + if (position >= settings_.positions) { + throw std::runtime_error("Switch position out of range for " + settings_.name); + } + + switch (settings_.mode) { + case config::DriverMode::Mock: + break; + case config::DriverMode::Native: + switch_native(position); + break; + default: + throw std::runtime_error("Unsupported switch driver mode for " + settings_.name); + } + + current_position_ = position; +} + +void H7992MinimalDriver::open_native() { + if (settings_.gpio_chip.empty()) { + throw std::runtime_error("gpio_chip is empty for native switch " + settings_.name); + } + if (settings_.pin_a < 0 || settings_.pin_b < 0 || settings_.pin_a == settings_.pin_b) { + throw std::runtime_error("Invalid pin_a/pin_b for native switch " + settings_.name); + } + + chip_fd_ = ::open(settings_.gpio_chip.c_str(), O_RDONLY | O_CLOEXEC); + if (chip_fd_ < 0) { + throw std::runtime_error( + "Failed to open gpio chip '" + settings_.gpio_chip + "' for " + settings_.name + ": " + std::strerror(errno) + ); + } + + gpio_v2_line_request request{}; + // The first requested line maps to logical bit 0, the second to bit 1. + request.offsets[0] = static_cast(settings_.pin_a); + request.offsets[1] = static_cast(settings_.pin_b); + request.num_lines = 2; + request.config.flags = GPIO_V2_LINE_FLAG_OUTPUT; + std::snprintf(request.consumer, sizeof(request.consumer), "radar_%s", settings_.name.c_str()); + + if (::ioctl(chip_fd_, GPIO_V2_GET_LINE_IOCTL, &request) != 0) { + const auto error = std::strerror(errno); + ::close(chip_fd_); + chip_fd_ = -1; + throw std::runtime_error("Failed to request GPIO lines for " + settings_.name + ": " + error); + } + + line_fd_ = request.fd; + if (line_fd_ < 0) { + ::close(chip_fd_); + chip_fd_ = -1; + throw std::runtime_error("GPIO line request returned invalid fd for " + settings_.name); + } +} + +void H7992MinimalDriver::close_native() { + if (line_fd_ >= 0) { + ::close(line_fd_); + line_fd_ = -1; + } + if (chip_fd_ >= 0) { + ::close(chip_fd_); + chip_fd_ = -1; + } +} + +void H7992MinimalDriver::switch_native(std::uint32_t position) { + if (line_fd_ < 0) { + throw std::runtime_error("Native GPIO line fd is not open for " + settings_.name); + } + + const auto [pin_a_state, pin_b_state] = kPositionToAB[position]; + auto values = make_line_values(pin_a_state, pin_b_state); + + if (::ioctl(line_fd_, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) != 0) { + throw std::runtime_error("Failed to switch GPIO state for " + settings_.name + ": " + std::strerror(errno)); + } +} + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.hpp new file mode 100644 index 0000000..d927ebb --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/h7992_minimal_driver.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include "run_config.hpp" +#include "switch_driver.hpp" + +namespace radar::drivers { + +/** + * @brief Runtime settings for the H7992 GPIO switch driver. + */ +struct H7992MinimalDriverSettings { + std::string name{}; + config::DriverMode mode = config::DriverMode::Native; + std::uint32_t positions = 4; + std::uint32_t default_position = 0; + std::string gpio_chip = "/dev/gpiochip0"; + std::int32_t pin_a = 17; + std::int32_t pin_b = 27; +}; + +/** + * @brief Minimal H7992 implementation for fast position switching. + * + * Native mode uses Linux GPIO character-device API (uAPI v2). + * Mock mode keeps state in memory without touching hardware. + */ +class H7992MinimalDriver final : public SwitchDriver { + public: + explicit H7992MinimalDriver(H7992MinimalDriverSettings settings); + + void open() override; + void close() override; + [[nodiscard]] auto position_count() const -> std::uint32_t override; + void switch_to(std::uint32_t position) override; + + private: + void open_native(); + void close_native(); + void switch_native(std::uint32_t position); + + H7992MinimalDriverSettings settings_{}; + bool is_open_ = false; + std::uint32_t current_position_ = 0; + int chip_fd_ = -1; + int line_fd_ = -1; +}; + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.cpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.cpp new file mode 100644 index 0000000..774ac82 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.cpp @@ -0,0 +1,147 @@ +#include "hmc349a_minimal_driver.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace radar::drivers { +namespace { + +void validate_open_settings(const HMC349AMinimalDriverSettings& settings) { + if (settings.positions == 0U || settings.positions > 2U) { + throw std::runtime_error("HMC349A switch positions must be in range [1, 2] for " + settings.name); + } + if (settings.default_position >= settings.positions) { + throw std::runtime_error("Switch default_position out of range for " + settings.name); + } +} + +} // namespace + +HMC349AMinimalDriver::HMC349AMinimalDriver(HMC349AMinimalDriverSettings settings) + : settings_(std::move(settings)) {} + +void HMC349AMinimalDriver::open() { + if (is_open_) { + return; + } + + validate_open_settings(settings_); + + if (settings_.mode == config::DriverMode::Native) { + open_native(); + } + + is_open_ = true; + switch_to(settings_.default_position); +} + +void HMC349AMinimalDriver::close() { + if (!is_open_) { + return; + } + + if (settings_.mode == config::DriverMode::Native) { + close_native(); + } + + is_open_ = false; +} + +auto HMC349AMinimalDriver::position_count() const -> std::uint32_t { + return settings_.positions; +} + +void HMC349AMinimalDriver::switch_to(std::uint32_t position) { + if (!is_open_) { + throw std::runtime_error("Switch driver is not open for " + settings_.name); + } + if (position >= settings_.positions) { + throw std::runtime_error("Switch position out of range for " + settings_.name); + } + + switch (settings_.mode) { + case config::DriverMode::Mock: + break; + case config::DriverMode::Native: + switch_native(position); + break; + default: + throw std::runtime_error("Unsupported switch driver mode for " + settings_.name); + } + + current_position_ = position; +} + +void HMC349AMinimalDriver::open_native() { + if (settings_.gpio_chip.empty()) { + throw std::runtime_error("gpio_chip is empty for native switch " + settings_.name); + } + if (settings_.pin_a < 0) { + throw std::runtime_error("pin_a (control) is invalid for native switch " + settings_.name); + } + + chip_fd_ = ::open(settings_.gpio_chip.c_str(), O_RDONLY | O_CLOEXEC); + if (chip_fd_ < 0) { + throw std::runtime_error( + "Failed to open gpio chip '" + settings_.gpio_chip + "' for " + settings_.name + ": " + std::strerror(errno) + ); + } + + gpio_v2_line_request request{}; + // Bit 0 controls pin_a. + request.offsets[0] = static_cast(settings_.pin_a); + request.num_lines = 1; + request.config.flags = GPIO_V2_LINE_FLAG_OUTPUT; + std::snprintf(request.consumer, sizeof(request.consumer), "radar_%s", settings_.name.c_str()); + + if (::ioctl(chip_fd_, GPIO_V2_GET_LINE_IOCTL, &request) != 0) { + const auto error = std::strerror(errno); + ::close(chip_fd_); + chip_fd_ = -1; + throw std::runtime_error("Failed to request GPIO lines for " + settings_.name + ": " + error); + } + + line_fd_ = request.fd; + if (line_fd_ < 0) { + ::close(chip_fd_); + chip_fd_ = -1; + throw std::runtime_error("GPIO line request returned invalid fd for " + settings_.name); + } +} + +void HMC349AMinimalDriver::close_native() { + if (line_fd_ >= 0) { + ::close(line_fd_); + line_fd_ = -1; + } + if (chip_fd_ >= 0) { + ::close(chip_fd_); + chip_fd_ = -1; + } +} + +void HMC349AMinimalDriver::switch_native(std::uint32_t position) { + if (line_fd_ < 0) { + throw std::runtime_error("Native GPIO line fd is not open for " + settings_.name); + } + + const std::uint8_t requested_state = static_cast(position & 0x01U); + const std::uint8_t control_state = settings_.invert_logic ? (requested_state ^ 0x01U) : requested_state; + + gpio_v2_line_values values{}; + values.mask = (1ULL << 0U); + values.bits = static_cast(control_state); + + if (::ioctl(line_fd_, GPIO_V2_LINE_SET_VALUES_IOCTL, &values) != 0) { + throw std::runtime_error("Failed to switch GPIO state for " + settings_.name + ": " + std::strerror(errno)); + } +} + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.hpp b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.hpp new file mode 100644 index 0000000..c70c0c6 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/device_drivers/switches/hmc349a_minimal_driver.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +#include "run_config.hpp" +#include "switch_driver.hpp" + +namespace radar::drivers { + +/** + * @brief Runtime settings for the HMC349A GPIO switch driver. + */ +struct HMC349AMinimalDriverSettings { + std::string name{}; + config::DriverMode mode = config::DriverMode::Native; + std::uint32_t positions = 2; + std::uint32_t default_position = 0; + std::string gpio_chip = "/dev/gpiochip0"; + std::int32_t pin_a = 17; ///< Control pin. + bool invert_logic = false; ///< Invert control logic for position mapping. +}; + +/** + * @brief Minimal HMC349A implementation for deterministic GPIO control. + * + * Native mode uses Linux GPIO character-device API (uAPI v2). + * Mock mode keeps state in memory without touching hardware. + */ +class HMC349AMinimalDriver final : public SwitchDriver { + public: + explicit HMC349AMinimalDriver(HMC349AMinimalDriverSettings settings); + + void open() override; + void close() override; + [[nodiscard]] auto position_count() const -> std::uint32_t override; + void switch_to(std::uint32_t position) override; + + private: + void open_native(); + void close_native(); + void switch_native(std::uint32_t position); + + HMC349AMinimalDriverSettings settings_{}; + bool is_open_ = false; + std::uint32_t current_position_ = 0; + + int chip_fd_ = -1; + int line_fd_ = -1; +}; + +} // namespace radar::drivers diff --git a/data_acq_and_processing/sweep_orchestrator/include/sweep_orchestrator.hpp b/data_acq_and_processing/sweep_orchestrator/include/sweep_orchestrator.hpp new file mode 100644 index 0000000..2f2055d --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/include/sweep_orchestrator.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include +#include + +#include "radar_driver.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" +#include "sweep_plan.hpp" +#include "switch_driver.hpp" + +namespace radar::acq { + +/** + * @brief Produces raw sweep collections for configured switch combinations. + * + * Lifecycle: + * 1. Open radar and switch drivers. + * 2. Iterate configured combinations, acquire one sweep per combination. + * 3. Publish serialized collections into the raw shared-memory ring. + */ +class SweepOrchestrator { + public: + /** + * @param config Runtime config loaded from JSON. + * @param radar_driver Radar device implementation. + * @param input_switch_driver Switch connected to radar input path. + * @param output_switch_driver Switch connected to radar output path. + * @param raw_ring Shared-memory ring for raw collections. + * @param raw_tap_ring Optional tap ring for GUI/debug readers. + */ + SweepOrchestrator( + const config::RunConfig& config, + drivers::RadarDriver& radar_driver, + drivers::SwitchDriver& input_switch_driver, + drivers::SwitchDriver& output_switch_driver, + ipc::ShmRing& raw_ring, + ipc::ShmRing* raw_tap_ring = nullptr + ); + + /** + * @brief Run acquisition loop until stop is requested or single run completes. + */ + void run(const std::atomic& stop_requested); + + private: + /** + * @brief Acquire one collection for all combinations in `plan_`. + */ + [[nodiscard]] auto acquire_one_collection(std::uint64_t collection_id, const std::atomic& stop_requested) + -> ipc::RawSweepCollection; + + const config::RunConfig& config_; + drivers::RadarDriver& radar_driver_; + drivers::SwitchDriver& input_switch_driver_; + drivers::SwitchDriver& output_switch_driver_; + ipc::ShmRing& raw_ring_; + ipc::ShmRing* raw_tap_ring_ = nullptr; + SweepPlan plan_{}; +}; + +} // namespace radar::acq diff --git a/data_acq_and_processing/sweep_orchestrator/include/sweep_plan.hpp b/data_acq_and_processing/sweep_orchestrator/include/sweep_plan.hpp new file mode 100644 index 0000000..246705a --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/include/sweep_plan.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "run_config.hpp" +#include "shared_types.hpp" + +namespace radar::acq { + +/** + * @brief Pre-validated execution order of switch combinations for one collection. + */ +struct SweepPlan { + std::vector ordered_combos{}; +}; + +/** + * @brief Build and validate sweep execution plan from runtime config. + */ +[[nodiscard]] auto build_sweep_plan(const config::RunConfig& config) -> SweepPlan; + +} // namespace radar::acq diff --git a/data_acq_and_processing/sweep_orchestrator/src/main.cpp b/data_acq_and_processing/sweep_orchestrator/src/main.cpp new file mode 100644 index 0000000..c6d3fcc --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/src/main.cpp @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "h7992_minimal_driver.hpp" +#include "hmc349a_minimal_driver.hpp" +#include "librevna_minimal_driver.hpp" +#include "run_config.hpp" +#include "shm_ring.hpp" +#include "sweep_orchestrator.hpp" + +namespace { + +constexpr const char* kDefaultConfigPath = "run_config.json"; +std::atomic g_stop_requested{false}; + +void signal_handler(int /*signal*/) { + g_stop_requested.store(true, std::memory_order_relaxed); +} + +void install_signal_handlers() { + std::signal(SIGINT, signal_handler); + std::signal(SIGTERM, signal_handler); +} + +[[nodiscard]] auto read_config_path(int argc, char** argv) -> std::string { + std::string config_path = kDefaultConfigPath; + + for (int index = 1; index < argc; ++index) { + const std::string arg = argv[index]; + if (arg == "--config" && (index + 1) < argc) { + config_path = argv[++index]; + } + } + + return config_path; +} + +[[nodiscard]] auto make_radar_driver(const radar::config::RadarConfig& config) -> radar::drivers::LibreVnaMinimalDriver { + return radar::drivers::LibreVnaMinimalDriver({ + .mode = config.driver_mode, + .serial = config.serial, + .sweep = config.sweep, + .mock_signal_hz = config.mock_signal_hz, + }); +} + +[[nodiscard]] auto make_h7992_driver(const radar::config::SwitchConfig& config) + -> std::unique_ptr { + return std::make_unique( + radar::drivers::H7992MinimalDriverSettings{ + .name = config.name, + .mode = config.driver_mode, + .positions = config.positions, + .default_position = config.default_position, + .gpio_chip = config.gpio_chip, + .pin_a = config.pin_a, + .pin_b = config.pin_b, + } + ); +} + +[[nodiscard]] auto make_hmc349a_driver(const radar::config::SwitchConfig& config) + -> std::unique_ptr { + return std::make_unique( + radar::drivers::HMC349AMinimalDriverSettings{ + .name = config.name, + .mode = config.driver_mode, + .positions = config.positions, + .default_position = config.default_position, + .gpio_chip = config.gpio_chip, + .pin_a = config.pin_a, + .invert_logic = config.invert_logic, + } + ); +} + +[[nodiscard]] auto make_switch_driver(const radar::config::SwitchConfig& config) + -> std::unique_ptr { + using radar::config::SwitchDriverKind; + + switch (config.driver_kind) { + case SwitchDriverKind::H7992: + return make_h7992_driver(config); + case SwitchDriverKind::HMC349A: + return make_hmc349a_driver(config); + default: + throw std::runtime_error("Unsupported switch driver kind"); + } +} + +} // namespace + +int main(int argc, char** argv) { + install_signal_handlers(); + + try { + const auto config_path = read_config_path(argc, argv); + const auto config = radar::config::load_run_config(config_path); + + auto raw_ring = radar::ipc::ShmRing::open_or_create( + config.rings.raw.name, + config.rings.raw.capacity, + config.rings.raw.slot_size_bytes + ); + auto raw_tap_ring = radar::ipc::ShmRing::open_or_create( + config.rings.raw_tap.name, + config.rings.raw_tap.capacity, + config.rings.raw_tap.slot_size_bytes + ); + + auto radar_driver = make_radar_driver(config.radar); + + auto input_switch = make_switch_driver(config.input_switch); + auto output_switch = make_switch_driver(config.output_switch); + + radar::acq::SweepOrchestrator orchestrator( + config, + radar_driver, + *input_switch, + *output_switch, + raw_ring, + &raw_tap_ring + ); + orchestrator.run(g_stop_requested); + return 0; + } catch (const std::exception& exception) { + std::cerr << "sweep_orchestrator error: " << exception.what() << '\n'; + return 1; + } +} diff --git a/data_acq_and_processing/sweep_orchestrator/src/sweep_orchestrator.cpp b/data_acq_and_processing/sweep_orchestrator/src/sweep_orchestrator.cpp new file mode 100644 index 0000000..ac909d0 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/src/sweep_orchestrator.cpp @@ -0,0 +1,178 @@ +#include "sweep_orchestrator.hpp" + +#include +#include +#include +#include +#include + +namespace radar::acq { +namespace { + +[[nodiscard]] inline auto should_stop(const std::atomic& stop_requested) -> bool { + return stop_requested.load(std::memory_order_relaxed); +} + +void sleep_if_needed_ms(std::uint32_t delay_ms) { + if (delay_ms == 0U) { + return; + } + std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms)); +} + +void validate_sweep(const drivers::SweepTrace& sweep) { + if (sweep.frequency_hz.size() != sweep.s21.size()) { + throw std::runtime_error("Radar driver returned inconsistent sweep vectors"); + } +} + +class DriverLifecycleGuard { + public: + DriverLifecycleGuard( + drivers::RadarDriver& radar_driver, + drivers::SwitchDriver& input_switch_driver, + drivers::SwitchDriver& output_switch_driver + ) + : radar_driver_(radar_driver), + input_switch_driver_(input_switch_driver), + output_switch_driver_(output_switch_driver) {} + + ~DriverLifecycleGuard() noexcept { + if (!active_) { + return; + } + + // Shutdown should never hide the primary error path. + try { + output_switch_driver_.close(); + } catch (...) { + } + try { + input_switch_driver_.close(); + } catch (...) { + } + try { + radar_driver_.close(); + } catch (...) { + } + } + + void open_all() { + radar_driver_.open(); + input_switch_driver_.open(); + output_switch_driver_.open(); + active_ = true; + } + + void close_all() { + if (!active_) { + return; + } + output_switch_driver_.close(); + input_switch_driver_.close(); + radar_driver_.close(); + active_ = false; + } + + private: + drivers::RadarDriver& radar_driver_; + drivers::SwitchDriver& input_switch_driver_; + drivers::SwitchDriver& output_switch_driver_; + bool active_ = false; +}; + +void publish_collection(ipc::ShmRing& raw_ring, ipc::ShmRing* raw_tap_ring, const ipc::RawSweepCollection& collection) { + const auto serialized_collection = ipc::serialize_raw_collection(collection); + if (!raw_ring.push(serialized_collection)) { + throw std::runtime_error("Raw ring slot is too small for serialized collection"); + } + if (raw_tap_ring != nullptr && !raw_tap_ring->push(serialized_collection)) { + throw std::runtime_error("Raw tap ring slot is too small for serialized collection"); + } +} + +} // namespace + +SweepOrchestrator::SweepOrchestrator( + const config::RunConfig& config, + drivers::RadarDriver& radar_driver, + drivers::SwitchDriver& input_switch_driver, + drivers::SwitchDriver& output_switch_driver, + ipc::ShmRing& raw_ring, + ipc::ShmRing* raw_tap_ring +) + : config_(config), + radar_driver_(radar_driver), + input_switch_driver_(input_switch_driver), + output_switch_driver_(output_switch_driver), + raw_ring_(raw_ring), + raw_tap_ring_(raw_tap_ring), + plan_(build_sweep_plan(config)) {} + +void SweepOrchestrator::run(const std::atomic& stop_requested) { + DriverLifecycleGuard lifecycle_guard(radar_driver_, input_switch_driver_, output_switch_driver_); + // Open devices once and keep them active for the whole acquisition loop. + lifecycle_guard.open_all(); + + std::uint64_t collection_id = 0; + while (!should_stop(stop_requested)) { + auto raw_collection = acquire_one_collection(++collection_id, stop_requested); + if (raw_collection.traces.empty()) { + if (!config_.runtime.continuous) { + break; + } + sleep_if_needed_ms(config_.runtime.idle_sleep_ms); + continue; + } + + publish_collection(raw_ring_, raw_tap_ring_, raw_collection); + + if (!config_.runtime.continuous) { + break; + } + } + + lifecycle_guard.close_all(); +} + +auto SweepOrchestrator::acquire_one_collection( + std::uint64_t collection_id, + const std::atomic& stop_requested +) -> ipc::RawSweepCollection { + ipc::RawSweepCollection collection{}; + collection.collection_id = collection_id; + collection.monotonic_ns = ipc::current_monotonic_ns(); + collection.traces.reserve(plan_.ordered_combos.size()); + bool interrupted = false; + + for (const auto& combo : plan_.ordered_combos) { + if (should_stop(stop_requested)) { + interrupted = true; + break; + } + + // Hardware flow for each combo: + // 1) switch output path, 2) switch input path, 3) optional settle. + output_switch_driver_.switch_to(combo.output_pos); + input_switch_driver_.switch_to(combo.input_pos); + sleep_if_needed_ms(config_.runtime.settling_ms); + + auto sweep = radar_driver_.acquire_s21_sweep(); + validate_sweep(sweep); + + ipc::SweepTraceBlock trace{}; + trace.combo = combo; + trace.frequency_hz = std::move(sweep.frequency_hz); + trace.s21 = std::move(sweep.s21); + collection.traces.push_back(std::move(trace)); + } + + if (interrupted) { + // Do not emit partial collections when stop was requested mid-cycle. + collection.traces.clear(); + } + + return collection; +} + +} // namespace radar::acq diff --git a/data_acq_and_processing/sweep_orchestrator/src/sweep_plan.cpp b/data_acq_and_processing/sweep_orchestrator/src/sweep_plan.cpp new file mode 100644 index 0000000..1c8fd85 --- /dev/null +++ b/data_acq_and_processing/sweep_orchestrator/src/sweep_plan.cpp @@ -0,0 +1,19 @@ +#include "sweep_plan.hpp" + +#include + +namespace radar::acq { + +auto build_sweep_plan(const config::RunConfig& config) -> SweepPlan { + // RunConfig is already validated in common_cpp/config. Keep this function + // focused on plan construction only. + if (config.run_combos.empty()) { + throw std::runtime_error("run.combos must not be empty"); + } + + SweepPlan plan{}; + plan.ordered_combos = config.run_combos; + return plan; +} + +} // namespace radar::acq diff --git a/data_acq_and_processing/third_party/eigen/COPYING.APACHE b/data_acq_and_processing/third_party/eigen/COPYING.APACHE new file mode 100644 index 0000000..61e948d --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/COPYING.APACHE @@ -0,0 +1,203 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ \ No newline at end of file diff --git a/data_acq_and_processing/third_party/eigen/COPYING.BSD b/data_acq_and_processing/third_party/eigen/COPYING.BSD new file mode 100644 index 0000000..8964ddf --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/COPYING.BSD @@ -0,0 +1,26 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ diff --git a/data_acq_and_processing/third_party/eigen/COPYING.MINPACK b/data_acq_and_processing/third_party/eigen/COPYING.MINPACK new file mode 100644 index 0000000..132cc3f --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/COPYING.MINPACK @@ -0,0 +1,51 @@ +Minpack Copyright Notice (1999) University of Chicago. All rights reserved + +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above +copyright notice, this list of conditions and the following +disclaimer. + +2. Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials +provided with the distribution. + +3. The end-user documentation included with the +redistribution, if any, must include the following +acknowledgment: + + "This product includes software developed by the + University of Chicago, as Operator of Argonne National + Laboratory. + +Alternately, this acknowledgment may appear in the software +itself, if and wherever such third-party acknowledgments +normally appear. + +4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" +WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE +UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND +THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE +OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY +OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR +USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF +THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) +DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION +UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL +BE CORRECTED. + +5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT +HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF +ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, +INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF +ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF +PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER +SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT +(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, +EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE +POSSIBILITY OF SUCH LOSS OR DAMAGES. diff --git a/data_acq_and_processing/third_party/eigen/COPYING.MPL2 b/data_acq_and_processing/third_party/eigen/COPYING.MPL2 new file mode 100644 index 0000000..ee6256c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/COPYING.MPL2 @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/data_acq_and_processing/third_party/eigen/COPYING.README b/data_acq_and_processing/third_party/eigen/COPYING.README new file mode 100644 index 0000000..52c077f --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/COPYING.README @@ -0,0 +1,11 @@ +Eigen is primarily MPL2 licensed. See COPYING.MPL2 and these links: + http://www.mozilla.org/MPL/2.0/ + http://www.mozilla.org/MPL/2.0/FAQ.html + +Some files contain third-party code under BSD, LGPL, Apache, or other +MPL2-compatible licenses, hence the other COPYING.* files here. + +Note that some optional external dependencies (e.g. FFTW, MPFR C++) +and some bundled benchmark code (bench/btl/) are distributed under +different licenses, including the GPL. Refer to the individual source +files and their respective COPYING files for details. diff --git a/data_acq_and_processing/third_party/eigen/Eigen/AccelerateSupport b/data_acq_and_processing/third_party/eigen/Eigen/AccelerateSupport new file mode 100644 index 0000000..533be68 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/AccelerateSupport @@ -0,0 +1,52 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ACCELERATESUPPORT_MODULE_H +#define EIGEN_ACCELERATESUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \ingroup Support_modules + * \defgroup AccelerateSupport_Module AccelerateSupport module + * + * This module provides an interface to the Apple Accelerate library. + * It provides the seven following main factorization classes: + * - class AccelerateLLT: a Cholesky (LL^T) factorization. + * - class AccelerateLDLT: the default LDL^T factorization. + * - class AccelerateLDLTUnpivoted: a Cholesky-like LDL^T factorization with only 1x1 pivots and no pivoting + * - class AccelerateLDLTSBK: an LDL^T factorization with Supernode Bunch-Kaufman and static pivoting + * - class AccelerateLDLTTPP: an LDL^T factorization with full threshold partial pivoting + * - class AccelerateQR: a QR factorization + * - class AccelerateCholeskyAtA: a QR factorization without storing Q (equivalent to A^TA = R^T R) + * + * \code + * #include + * \endcode + * + * In order to use this module, the Accelerate headers must be accessible from + * the include paths, and your binary must be linked to the Accelerate framework. + * The Accelerate library is only available on Apple hardware. + * + * Note that many of the algorithms can be influenced by the UpLo template + * argument. All matrices are assumed to be symmetric. For example, the following + * creates an LDLT factorization where your matrix is symmetric (implicit) and + * uses the lower triangle: + * + * \code + * AccelerateLDLT, Lower> ldlt; + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/AccelerateSupport/AccelerateSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_ACCELERATESUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Cholesky b/data_acq_and_processing/third_party/eigen/Eigen/Cholesky new file mode 100644 index 0000000..b05ed82 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Cholesky @@ -0,0 +1,43 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CHOLESKY_MODULE_H +#define EIGEN_CHOLESKY_MODULE_H + +#include "Core" +#include "Jacobi" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup Cholesky_Module Cholesky module + * + * + * + * This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices. + * Those decompositions are also accessible via the following methods: + * - MatrixBase::llt() + * - MatrixBase::ldlt() + * - SelfAdjointView::llt() + * - SelfAdjointView::ldlt() + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/Cholesky/LLT.h" +#include "src/Cholesky/LDLT.h" +#ifdef EIGEN_USE_LAPACKE +#include "src/misc/lapacke_helpers.h" +#include "src/Cholesky/LLT_LAPACKE.h" +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_CHOLESKY_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/CholmodSupport b/data_acq_and_processing/third_party/eigen/Eigen/CholmodSupport new file mode 100644 index 0000000..adc5f8d --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/CholmodSupport @@ -0,0 +1,48 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CHOLMODSUPPORT_MODULE_H +#define EIGEN_CHOLMODSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include + +/** \ingroup Support_modules + * \defgroup CholmodSupport_Module CholmodSupport module + * + * This module provides an interface to the Cholmod library which is part of the suitesparse package. It provides the two following main factorization classes: + * - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization. + * - class CholmodDecomposition: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of + * the underlying factorization method (supernodal or simplicial). + * + * For the sake of completeness, this module also propose the two following classes: + * - class CholmodSimplicialLLT + * - class CholmodSimplicialLDLT + * Note that these classes does not bring any particular advantage compared to the built-in + * SimplicialLLT and SimplicialLDLT factorization classes. + * + * \code + * #include + * \endcode + * + * In order to use this module, the cholmod headers must be accessible from the include paths, and your binary must be + * linked to the cholmod library and its dependencies. The dependencies depend on how cholmod has been compiled. For a + * cmake based project, you can use our FindCholmod.cmake module to help you in this task. + * + */ + +// IWYU pragma: begin_exports +#include "src/CholmodSupport/CholmodSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_CHOLMODSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Core b/data_acq_and_processing/third_party/eigen/Eigen/Core new file mode 100644 index 0000000..616b184 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Core @@ -0,0 +1,482 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2007-2011 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CORE_MODULE_H +#define EIGEN_CORE_MODULE_H + +// Eigen version information. +#include "Version" + +// first thing Eigen does: stop the compiler from reporting useless warnings. +#include "src/Core/util/DisableStupidWarnings.h" + +// then include this file where all our macros are defined. It's really important to do it first because +// it's where we do all the compiler/OS/arch detections and define most defaults. +#include "src/Core/util/Macros.h" + +// This detects SSE/AVX/NEON/etc. and configure alignment settings +#include "src/Core/util/ConfigureVectorization.h" + +// We need cuda_runtime.h/hip_runtime.h to ensure that +// the EIGEN_USING_STD macro works properly on the device side +#if defined(EIGEN_CUDACC) +#include +#elif defined(EIGEN_HIPCC) +#include +#endif + +#ifdef EIGEN_EXCEPTIONS +#include +#endif + +// Disable the ipa-cp-clone optimization flag with MinGW 6.x or older (enabled by default with -O3) +// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details. +#if EIGEN_COMP_MINGW && EIGEN_GNUC_STRICT_LESS_THAN(6, 0, 0) +#pragma GCC optimize("-fno-ipa-cp-clone") +#endif + +// Prevent ICC from specializing std::complex operators that silently fail +// on device. This allows us to use our own device-compatible specializations +// instead. +#if EIGEN_COMP_ICC && defined(EIGEN_GPU_COMPILE_PHASE) && !defined(_OVERRIDE_COMPLEX_SPECIALIZATION_) +#define _OVERRIDE_COMPLEX_SPECIALIZATION_ 1 +#endif +#include + +// this include file manages BLAS and MKL related macros +// and inclusion of their respective header files +#include "src/Core/util/MKL_support.h" +#include "src/Core/util/AOCL_Support.h" // ← ADD THIS + + +#if defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16) +#define EIGEN_HAS_GPU_FP16 +#endif + +#if defined(EIGEN_HAS_CUDA_BF16) || defined(EIGEN_HAS_HIP_BF16) +#define EIGEN_HAS_GPU_BF16 +#endif + +#if (defined _OPENMP) && (!defined EIGEN_DONT_PARALLELIZE) +#define EIGEN_HAS_OPENMP +#endif + +#ifdef EIGEN_HAS_OPENMP +#include +#include +#endif + +// MSVC for windows mobile does not have the errno.h file +#if !(EIGEN_COMP_MSVC && EIGEN_OS_WINCE) && !EIGEN_COMP_ARM +#define EIGEN_HAS_ERRNO +#endif + +#ifdef EIGEN_HAS_ERRNO +#include +#endif +#include +#include +#include +#include +#ifndef EIGEN_NO_IO +#include +#include +#endif +#include +#include +#include +#include // for CHAR_BIT +// for min/max: +#include + +#include +#include +#include + +// for std::is_nothrow_move_assignable +#include + +// for std::this_thread::yield(). +#if !defined(EIGEN_USE_BLAS) && (defined(EIGEN_HAS_OPENMP) || defined(EIGEN_GEMM_THREADPOOL)) +#include +#endif + +// for __cpp_lib feature test macros +#if defined(__has_include) && __has_include() +#include +#endif + +// for std::bit_cast() +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#include +#endif + +// for outputting debug info +#ifdef EIGEN_DEBUG_ASSIGN +#include +#endif + +// required for __cpuid, needs to be included after cmath +// also required for _BitScanReverse on Windows on ARM +#if EIGEN_COMP_MSVC && (EIGEN_ARCH_i386_OR_x86_64 || EIGEN_ARCH_ARM64) && !EIGEN_OS_WINCE +#include +#endif + +#if defined(EIGEN_USE_SYCL) +#undef min +#undef max +#undef isnan +#undef isinf +#undef isfinite +#include +#include +#include +#include +#ifndef EIGEN_SYCL_LOCAL_THREAD_DIM0 +#define EIGEN_SYCL_LOCAL_THREAD_DIM0 16 +#endif +#ifndef EIGEN_SYCL_LOCAL_THREAD_DIM1 +#define EIGEN_SYCL_LOCAL_THREAD_DIM1 16 +#endif +#endif + +#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS || defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API || \ + defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS || defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API || \ + defined EIGEN2_SUPPORT +// This will generate an error message: +#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information +#endif + +namespace Eigen { + +// we use size_t frequently and we'll never remember to prepend it with std:: every time just to +// ensure QNX/QCC support +using std::size_t; +// gcc 4.6.0 wants std:: for ptrdiff_t +using std::ptrdiff_t; + +} // namespace Eigen + +/** \defgroup Core_Module Core module + * This is the main module of Eigen providing dense matrix and vector support + * (both fixed and dynamic size) with all the features corresponding to a BLAS library + * and much more... + * + * \code + * #include + * \endcode + */ + +#ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else +#include "src/misc/lapacke.h" +#endif +#endif + +// IWYU pragma: begin_exports +#include "src/Core/util/Constants.h" +#include "src/Core/util/Meta.h" +#include "src/Core/util/Assert.h" +#include "src/Core/util/ForwardDeclarations.h" +#include "src/Core/util/StaticAssert.h" +#include "src/Core/util/XprHelper.h" +#include "src/Core/util/Memory.h" +#include "src/Core/util/IntegralConstant.h" +#include "src/Core/util/Serializer.h" +#include "src/Core/util/SymbolicIndex.h" +#include "src/Core/util/EmulateArray.h" +#include "src/Core/util/MoreMeta.h" + +#include "src/Core/NumTraits.h" +#include "src/Core/MathFunctions.h" +#include "src/Core/RandomImpl.h" +#include "src/Core/GenericPacketMath.h" +#include "src/Core/MathFunctionsImpl.h" +#include "src/Core/arch/Default/ConjHelper.h" +// Generic half float support +#include "src/Core/arch/Default/Half.h" +#include "src/Core/arch/Default/BFloat16.h" +#include "src/Core/arch/Default/GenericPacketMathFunctionsFwd.h" + +#if defined(EIGEN_VECTORIZE_GENERIC) && !defined(EIGEN_DONT_VECTORIZE) +#include "src/Core/arch/clang/PacketMath.h" +#include "src/Core/arch/clang/TypeCasting.h" +#include "src/Core/arch/clang/Complex.h" +#include "src/Core/arch/clang/Reductions.h" +#include "src/Core/arch/clang/MathFunctions.h" +#else +#if defined EIGEN_VECTORIZE_AVX512 +#include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" +#include "src/Core/arch/AVX/PacketMath.h" +#include "src/Core/arch/AVX/Reductions.h" +#include "src/Core/arch/AVX512/PacketMath.h" +#include "src/Core/arch/AVX512/Reductions.h" +#if defined EIGEN_VECTORIZE_AVX512FP16 +#include "src/Core/arch/AVX512/PacketMathFP16.h" +#endif +#include "src/Core/arch/SSE/TypeCasting.h" +#include "src/Core/arch/AVX/TypeCasting.h" +#include "src/Core/arch/AVX512/TypeCasting.h" +#if defined EIGEN_VECTORIZE_AVX512FP16 +#include "src/Core/arch/AVX512/TypeCastingFP16.h" +#endif +#include "src/Core/arch/SSE/Complex.h" +#include "src/Core/arch/AVX/Complex.h" +#include "src/Core/arch/AVX512/Complex.h" +#include "src/Core/arch/SSE/MathFunctions.h" +#include "src/Core/arch/AVX/MathFunctions.h" +#include "src/Core/arch/AVX512/MathFunctions.h" +#if defined EIGEN_VECTORIZE_AVX512FP16 +#include "src/Core/arch/AVX512/MathFunctionsFP16.h" +#endif +#include "src/Core/arch/AVX512/TrsmKernel.h" +#elif defined EIGEN_VECTORIZE_AVX +// Use AVX for floats and doubles, SSE for integers +#include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" +#include "src/Core/arch/SSE/TypeCasting.h" +#include "src/Core/arch/SSE/Complex.h" +#include "src/Core/arch/AVX/PacketMath.h" +#include "src/Core/arch/AVX/Reductions.h" +#include "src/Core/arch/AVX/TypeCasting.h" +#include "src/Core/arch/AVX/Complex.h" +#include "src/Core/arch/SSE/MathFunctions.h" +#include "src/Core/arch/AVX/MathFunctions.h" +#elif defined EIGEN_VECTORIZE_SSE +#include "src/Core/arch/SSE/PacketMath.h" +#include "src/Core/arch/SSE/Reductions.h" +#include "src/Core/arch/SSE/TypeCasting.h" +#include "src/Core/arch/SSE/MathFunctions.h" +#include "src/Core/arch/SSE/Complex.h" +#endif + +#if defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX) +#include "src/Core/arch/AltiVec/PacketMath.h" +#include "src/Core/arch/AltiVec/TypeCasting.h" +#include "src/Core/arch/AltiVec/MathFunctions.h" +#include "src/Core/arch/AltiVec/Complex.h" +#elif defined EIGEN_VECTORIZE_NEON +#include "src/Core/arch/NEON/PacketMath.h" +#include "src/Core/arch/NEON/TypeCasting.h" +#include "src/Core/arch/NEON/MathFunctions.h" +#include "src/Core/arch/NEON/Complex.h" +#elif defined EIGEN_VECTORIZE_LSX +#include "src/Core/arch/LSX/PacketMath.h" +#include "src/Core/arch/LSX/TypeCasting.h" +#include "src/Core/arch/LSX/MathFunctions.h" +#include "src/Core/arch/LSX/Complex.h" +#elif defined EIGEN_VECTORIZE_SVE +#include "src/Core/arch/SVE/PacketMath.h" +#include "src/Core/arch/SVE/TypeCasting.h" +#include "src/Core/arch/SVE/MathFunctions.h" +#elif defined EIGEN_VECTORIZE_RVV10 +#include "src/Core/arch/RVV10/PacketMath.h" +#include "src/Core/arch/RVV10/PacketMath4.h" +#include "src/Core/arch/RVV10/PacketMath2.h" +#include "src/Core/arch/RVV10/TypeCasting.h" +#include "src/Core/arch/RVV10/MathFunctions.h" +#if defined EIGEN_VECTORIZE_RVV10FP16 +#include "src/Core/arch/RVV10/PacketMathFP16.h" +#endif +#if defined EIGEN_VECTORIZE_RVV10BF16 +#include "src/Core/arch/RVV10/PacketMathBF16.h" +#endif +#elif defined EIGEN_VECTORIZE_ZVECTOR +#include "src/Core/arch/ZVector/PacketMath.h" +#include "src/Core/arch/ZVector/MathFunctions.h" +#include "src/Core/arch/ZVector/Complex.h" +#elif defined EIGEN_VECTORIZE_MSA +#include "src/Core/arch/MSA/PacketMath.h" +#include "src/Core/arch/MSA/MathFunctions.h" +#include "src/Core/arch/MSA/Complex.h" +#elif defined EIGEN_VECTORIZE_HVX +#include "src/Core/arch/HVX/PacketMath.h" +#endif + +#if defined EIGEN_VECTORIZE_GPU +#include "src/Core/arch/GPU/PacketMath.h" +#include "src/Core/arch/GPU/MathFunctions.h" +#include "src/Core/arch/GPU/TypeCasting.h" +#endif + +#if defined(EIGEN_USE_SYCL) +#include "src/Core/arch/SYCL/InteropHeaders.h" +#if !defined(EIGEN_DONT_VECTORIZE_SYCL) +#include "src/Core/arch/SYCL/PacketMath.h" +#include "src/Core/arch/SYCL/MathFunctions.h" +#include "src/Core/arch/SYCL/TypeCasting.h" +#endif +#endif + +#endif // #ifndef EIGEN_VECTORIZE_GENERIC + +#include "src/Core/arch/Default/Settings.h" +// This file provides generic implementations valid for scalar as well +#include "src/Core/arch/Default/GenericPacketMathFunctions.h" + +#include "src/Core/functors/TernaryFunctors.h" +#include "src/Core/functors/BinaryFunctors.h" +#include "src/Core/functors/UnaryFunctors.h" +#include "src/Core/functors/NullaryFunctors.h" +#include "src/Core/functors/StlFunctors.h" +#include "src/Core/functors/AssignmentFunctors.h" + +// Specialized functors for GPU. +#ifdef EIGEN_GPUCC +#include "src/Core/arch/GPU/Complex.h" +#endif + +// Specializations of vectorized activation functions for NEON. +#ifdef EIGEN_VECTORIZE_NEON +#include "src/Core/arch/NEON/UnaryFunctors.h" +#endif + +#include "src/Core/util/IndexedViewHelper.h" +#include "src/Core/util/ReshapedHelper.h" +#include "src/Core/ArithmeticSequence.h" +#ifndef EIGEN_NO_IO +#include "src/Core/IO.h" +#endif +#include "src/Core/DenseCoeffsBase.h" +#include "src/Core/DenseBase.h" +#include "src/Core/MatrixBase.h" +#include "src/Core/EigenBase.h" + +#include "src/Core/Product.h" +#include "src/Core/CoreEvaluators.h" +#include "src/Core/AssignEvaluator.h" +#include "src/Core/RealView.h" +#include "src/Core/Assign.h" + +#include "src/Core/ArrayBase.h" +#include "src/Core/util/BlasUtil.h" +#include "src/Core/DenseStorage.h" +#include "src/Core/NestByValue.h" + +// #include "src/Core/ForceAlignedAccess.h" + +#include "src/Core/ReturnByValue.h" +#include "src/Core/NoAlias.h" +#include "src/Core/PlainObjectBase.h" +#include "src/Core/Matrix.h" +#include "src/Core/Array.h" +#include "src/Core/Fill.h" +#include "src/Core/CwiseTernaryOp.h" +#include "src/Core/CwiseBinaryOp.h" +#include "src/Core/CwiseUnaryOp.h" +#include "src/Core/CwiseNullaryOp.h" +#include "src/Core/CwiseUnaryView.h" +#include "src/Core/SelfCwiseBinaryOp.h" +#include "src/Core/InnerProduct.h" +#include "src/Core/Dot.h" +#include "src/Core/StableNorm.h" +#include "src/Core/Stride.h" +#include "src/Core/MapBase.h" +#include "src/Core/Map.h" +#include "src/Core/Ref.h" +#include "src/Core/Block.h" +#include "src/Core/VectorBlock.h" +#include "src/Core/IndexedView.h" +#include "src/Core/Reshaped.h" +#include "src/Core/Transpose.h" +#include "src/Core/DiagonalMatrix.h" +#include "src/Core/Diagonal.h" +#include "src/Core/DiagonalProduct.h" +#include "src/Core/SkewSymmetricMatrix3.h" +#include "src/Core/Redux.h" +#include "src/Core/Visitor.h" +#include "src/Core/FindCoeff.h" +#include "src/Core/Fuzzy.h" +#include "src/Core/Swap.h" +#include "src/Core/CommaInitializer.h" +#include "src/Core/GeneralProduct.h" +#include "src/Core/Solve.h" +#include "src/Core/Inverse.h" +#include "src/Core/SolverBase.h" +#include "src/Core/PermutationMatrix.h" +#include "src/Core/Transpositions.h" +#include "src/Core/TriangularMatrix.h" +#include "src/Core/SelfAdjointView.h" +#include "src/Core/products/GeneralBlockPanelKernel.h" +#include "src/Core/DeviceWrapper.h" +#ifdef EIGEN_GEMM_THREADPOOL +#include "ThreadPool" +#endif +#include "src/Core/products/Parallelizer.h" +#include "src/Core/ProductEvaluators.h" +#include "src/Core/products/GeneralMatrixVector.h" +#include "src/Core/products/GeneralMatrixMatrix.h" +#include "src/Core/SolveTriangular.h" +#include "src/Core/products/GeneralMatrixMatrixTriangular.h" +#include "src/Core/products/SelfadjointMatrixVector.h" +#include "src/Core/products/SelfadjointMatrixMatrix.h" +#include "src/Core/products/SelfadjointProduct.h" +#include "src/Core/products/SelfadjointRank2Update.h" +#include "src/Core/products/TriangularMatrixVector.h" +#include "src/Core/products/TriangularMatrixMatrix.h" +#include "src/Core/products/TriangularSolverMatrix.h" +#include "src/Core/products/TriangularSolverVector.h" +#include "src/Core/BandMatrix.h" +#include "src/Core/CoreIterators.h" +#include "src/Core/ConditionEstimator.h" + +#if !defined(EIGEN_VECTORIZE_GENERIC) +#if defined(EIGEN_VECTORIZE_VSX) +#include "src/Core/arch/AltiVec/MatrixProduct.h" +#elif defined EIGEN_VECTORIZE_NEON +#include "src/Core/arch/NEON/GeneralBlockPanelKernel.h" +#elif defined EIGEN_VECTORIZE_LSX +#include "src/Core/arch/LSX/GeneralBlockPanelKernel.h" +#elif defined EIGEN_VECTORIZE_RVV10 +#include "src/Core/arch/RVV10/GeneralBlockPanelKernel.h" +#endif + +#if defined(EIGEN_VECTORIZE_AVX512) +#include "src/Core/arch/AVX512/GemmKernel.h" +#endif +#endif + +#include "src/Core/Select.h" +#include "src/Core/VectorwiseOp.h" +#include "src/Core/PartialReduxEvaluator.h" +#include "src/Core/Random.h" +#include "src/Core/Replicate.h" +#include "src/Core/Reverse.h" +#include "src/Core/ArrayWrapper.h" +#include "src/Core/StlIterators.h" + +#ifdef EIGEN_USE_BLAS +#include "src/Core/products/GeneralMatrixMatrix_BLAS.h" +#include "src/Core/products/GeneralMatrixVector_BLAS.h" +#include "src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h" +#include "src/Core/products/SelfadjointMatrixMatrix_BLAS.h" +#include "src/Core/products/SelfadjointMatrixVector_BLAS.h" +#include "src/Core/products/TriangularMatrixMatrix_BLAS.h" +#include "src/Core/products/TriangularMatrixVector_BLAS.h" +#include "src/Core/products/TriangularSolverMatrix_BLAS.h" +#endif // EIGEN_USE_BLAS + +#ifdef EIGEN_USE_MKL_VML +#include "src/Core/Assign_MKL.h" +#endif + +#ifdef EIGEN_USE_AOCL_VML +#include "src/Core/Assign_AOCL.h" +#endif + +#include "src/Core/GlobalFunctions.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_CORE_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Dense b/data_acq_and_processing/third_party/eigen/Eigen/Dense new file mode 100644 index 0000000..5768910 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Dense @@ -0,0 +1,7 @@ +#include "Core" +#include "LU" +#include "Cholesky" +#include "QR" +#include "SVD" +#include "Geometry" +#include "Eigenvalues" diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Eigen b/data_acq_and_processing/third_party/eigen/Eigen/Eigen new file mode 100644 index 0000000..654c8dc --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Eigen @@ -0,0 +1,2 @@ +#include "Dense" +#include "Sparse" diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Eigenvalues b/data_acq_and_processing/third_party/eigen/Eigen/Eigenvalues new file mode 100644 index 0000000..8039000 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Eigenvalues @@ -0,0 +1,63 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_EIGENVALUES_MODULE_H +#define EIGEN_EIGENVALUES_MODULE_H + +#include "Core" + +#include "Cholesky" +#include "Jacobi" +#include "Householder" +#include "LU" +#include "Geometry" +#include "Sparse" // Needed by ComplexQZ. + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup Eigenvalues_Module Eigenvalues module + * + * + * + * This module mainly provides various eigenvalue solvers. + * This module also provides some MatrixBase methods, including: + * - MatrixBase::eigenvalues(), + * - MatrixBase::operatorNorm() + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/Eigenvalues/Tridiagonalization.h" +#include "src/Eigenvalues/RealSchur.h" +#include "src/Eigenvalues/EigenSolver.h" +#include "src/Eigenvalues/SelfAdjointEigenSolver.h" +#include "src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h" +#include "src/Eigenvalues/HessenbergDecomposition.h" +#include "src/Eigenvalues/ComplexSchur.h" +#include "src/Eigenvalues/ComplexEigenSolver.h" +#include "src/Eigenvalues/RealQZ.h" +#include "src/Eigenvalues/ComplexQZ.h" +#include "src/Eigenvalues/GeneralizedEigenSolver.h" +#include "src/Eigenvalues/MatrixBaseEigenvalues.h" +#ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else +#include "src/misc/lapacke.h" +#endif +#include "src/Eigenvalues/RealSchur_LAPACKE.h" +#include "src/Eigenvalues/ComplexSchur_LAPACKE.h" +#include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h" +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_EIGENVALUES_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Geometry b/data_acq_and_processing/third_party/eigen/Eigen/Geometry new file mode 100644 index 0000000..fd81ae2 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Geometry @@ -0,0 +1,62 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_GEOMETRY_MODULE_H +#define EIGEN_GEOMETRY_MODULE_H + +#include "Core" + +#include "SVD" +#include "LU" +#include + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup Geometry_Module Geometry module + * + * This module provides support for: + * - fixed-size homogeneous transformations + * - translation, scaling, 2D and 3D rotations + * - \link Quaternion quaternions \endlink + * - cross products (\ref MatrixBase::cross(), \ref MatrixBase::cross3()) + * - orthogonal vector generation (MatrixBase::unitOrthogonal) + * - some linear components: \link ParametrizedLine parametrized-lines \endlink and \link Hyperplane hyperplanes \endlink + * - \link AlignedBox axis aligned bounding boxes \endlink + * - \link umeyama() least-square transformation fitting \endlink + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/Geometry/OrthoMethods.h" +#include "src/Geometry/EulerAngles.h" +#include "src/Geometry/Homogeneous.h" +#include "src/Geometry/RotationBase.h" +#include "src/Geometry/Rotation2D.h" +#include "src/Geometry/Quaternion.h" +#include "src/Geometry/AngleAxis.h" +#include "src/Geometry/Transform.h" +#include "src/Geometry/Translation.h" +#include "src/Geometry/Scaling.h" +#include "src/Geometry/Hyperplane.h" +#include "src/Geometry/ParametrizedLine.h" +#include "src/Geometry/AlignedBox.h" +#include "src/Geometry/Umeyama.h" + +#ifndef EIGEN_VECTORIZE_GENERIC +// TODO(rmlarsen): Make these work with generic vectorization if possible. +// Use the SSE optimized version whenever possible. +#if (defined EIGEN_VECTORIZE_SSE) || (defined EIGEN_VECTORIZE_NEON) +#include "src/Geometry/arch/Geometry_SIMD.h" +#endif +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_GEOMETRY_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Householder b/data_acq_and_processing/third_party/eigen/Eigen/Householder new file mode 100644 index 0000000..5070e07 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Householder @@ -0,0 +1,31 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_HOUSEHOLDER_MODULE_H +#define EIGEN_HOUSEHOLDER_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup Householder_Module Householder module + * This module provides Householder transformations. + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/Householder/Householder.h" +#include "src/Householder/HouseholderSequence.h" +#include "src/Householder/BlockHouseholder.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_HOUSEHOLDER_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/IterativeLinearSolvers b/data_acq_and_processing/third_party/eigen/Eigen/IterativeLinearSolvers new file mode 100644 index 0000000..fe5159e --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/IterativeLinearSolvers @@ -0,0 +1,52 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ITERATIVELINEARSOLVERS_MODULE_H +#define EIGEN_ITERATIVELINEARSOLVERS_MODULE_H + +#include "SparseCore" +#include "OrderingMethods" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** + * \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module + * + * This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a + squared matrix, usually very large and sparse. + * Those solvers are accessible via the following classes: + * - ConjugateGradient for selfadjoint (hermitian) matrices, + * - LeastSquaresConjugateGradient for rectangular least-square problems, + * - BiCGSTAB for general square matrices. + * + * These iterative solvers are associated with some preconditioners: + * - IdentityPreconditioner - not really useful + * - DiagonalPreconditioner - also called Jacobi preconditioner, work very well on diagonal dominant matrices. + * - IncompleteLUT - incomplete LU factorization with dual thresholding + * + * Such problems can also be solved using the direct sparse decomposition modules: SparseCholesky, CholmodSupport, + UmfPackSupport, SuperLUSupport, AccelerateSupport. + * + \code + #include + \endcode + */ + +// IWYU pragma: begin_exports +#include "src/IterativeLinearSolvers/SolveWithGuess.h" +#include "src/IterativeLinearSolvers/IterativeSolverBase.h" +#include "src/IterativeLinearSolvers/BasicPreconditioners.h" +#include "src/IterativeLinearSolvers/ConjugateGradient.h" +#include "src/IterativeLinearSolvers/LeastSquareConjugateGradient.h" +#include "src/IterativeLinearSolvers/BiCGSTAB.h" +#include "src/IterativeLinearSolvers/IncompleteLUT.h" +#include "src/IterativeLinearSolvers/IncompleteCholesky.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_ITERATIVELINEARSOLVERS_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Jacobi b/data_acq_and_processing/third_party/eigen/Eigen/Jacobi new file mode 100644 index 0000000..31eb36a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Jacobi @@ -0,0 +1,33 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_JACOBI_MODULE_H +#define EIGEN_JACOBI_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup Jacobi_Module Jacobi module + * This module provides Jacobi and Givens rotations. + * + * \code + * #include + * \endcode + * + * In addition to listed classes, it defines the two following MatrixBase methods to apply a Jacobi or Givens rotation: + * - MatrixBase::applyOnTheLeft() + * - MatrixBase::applyOnTheRight(). + */ + +// IWYU pragma: begin_exports +#include "src/Jacobi/Jacobi.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_JACOBI_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/KLUSupport b/data_acq_and_processing/third_party/eigen/Eigen/KLUSupport new file mode 100644 index 0000000..13959a3 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/KLUSupport @@ -0,0 +1,43 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_KLUSUPPORT_MODULE_H +#define EIGEN_KLUSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { +#include +#include +} + +/** \ingroup Support_modules + * \defgroup KLUSupport_Module KLUSupport module + * + * This module provides an interface to the KLU library which is part of the suitesparse package. It provides the following factorization class: + * - class KLU: a sparse LU factorization, well-suited for circuit simulation. + * + * \code + * #include + * \endcode + * + * In order to use this module, the klu and btf headers must be accessible from the include paths, and your binary must + * be linked to the klu library and its dependencies. The dependencies depend on how umfpack has been compiled. For a + * cmake based project, you can use our FindKLU.cmake module to help you in this task. + * + */ + +// IWYU pragma: begin_exports +#include "src/KLUSupport/KLUSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_KLUSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/LU b/data_acq_and_processing/third_party/eigen/Eigen/LU new file mode 100644 index 0000000..64dcdee --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/LU @@ -0,0 +1,49 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_LU_MODULE_H +#define EIGEN_LU_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup LU_Module LU module + * This module includes %LU decomposition and related notions such as matrix inversion and determinant. + * This module defines the following MatrixBase methods: + * - MatrixBase::inverse() + * - MatrixBase::determinant() + * + * \code + * #include + * \endcode + */ + +#include "src/misc/Kernel.h" +#include "src/misc/Image.h" + +// IWYU pragma: begin_exports +#include "src/LU/FullPivLU.h" +#include "src/LU/PartialPivLU.h" +#ifdef EIGEN_USE_LAPACKE +#include "src/misc/lapacke_helpers.h" +#include "src/LU/PartialPivLU_LAPACKE.h" +#endif +#include "src/LU/Determinant.h" +#include "src/LU/InverseImpl.h" + +#ifndef EIGEN_VECTORIZE_GENERIC +// TODO(rmlarsen): Make these work with generic vectorization if possible. +#if defined EIGEN_VECTORIZE_SSE || defined EIGEN_VECTORIZE_NEON +#include "src/LU/arch/InverseSize4.h" +#endif +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_LU_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/MetisSupport b/data_acq_and_processing/third_party/eigen/Eigen/MetisSupport new file mode 100644 index 0000000..3636d3a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/MetisSupport @@ -0,0 +1,35 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_METISSUPPORT_MODULE_H +#define EIGEN_METISSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { +#include +} + +/** \ingroup Support_modules + * \defgroup MetisSupport_Module MetisSupport module + * + * \code + * #include + * \endcode + * This module defines an interface to the METIS reordering package (http://glaros.dtc.umn.edu/gkhome/views/metis). + * It can be used just as any other built-in method as explained in \link OrderingMethods_Module here. \endlink + */ + +// IWYU pragma: begin_exports +#include "src/MetisSupport/MetisSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_METISSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/OrderingMethods b/data_acq_and_processing/third_party/eigen/Eigen/OrderingMethods new file mode 100644 index 0000000..0167419 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/OrderingMethods @@ -0,0 +1,73 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ORDERINGMETHODS_MODULE_H +#define EIGEN_ORDERINGMETHODS_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** + * \defgroup OrderingMethods_Module OrderingMethods module + * + * This module is currently for internal use only + * + * It defines various built-in and external ordering methods for sparse matrices. + * They are typically used to reduce the number of elements during + * the sparse matrix decomposition (LLT, LU, QR). + * Precisely, in a preprocessing step, a permutation matrix P is computed using + * those ordering methods and applied to the columns of the matrix. + * Using for instance the sparse Cholesky decomposition, it is expected that + * the nonzeros elements in LLT(A*P) will be much smaller than that in LLT(A). + * + * + * Usage : + * \code + * #include + * \endcode + * + * A simple usage is as a template parameter in the sparse decomposition classes : + * + * \code + * SparseLU > solver; + * \endcode + * + * \code + * SparseQR > solver; + * \endcode + * + * It is possible as well to call directly a particular ordering method for your own purpose, + * \code + * AMDOrdering ordering; + * PermutationMatrix perm; + * SparseMatrix A; + * //Fill the matrix ... + * + * ordering(A, perm); // Call AMD + * \endcode + * + * \note Some of these methods (like AMD or METIS), need the sparsity pattern + * of the input matrix to be symmetric. When the matrix is structurally unsymmetric, + * Eigen computes internally the pattern of \f$A^T*A\f$ before calling the method. + * If your matrix is already symmetric (at least in structure), you can avoid that + * by calling the method with a SelfAdjointView type. + * + * \code + * // Call the ordering on the pattern of the lower triangular matrix A + * ordering(A.selfadjointView(), perm); + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/OrderingMethods/Amd.h" +#include "src/OrderingMethods/Ordering.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_ORDERINGMETHODS_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/PaStiXSupport b/data_acq_and_processing/third_party/eigen/Eigen/PaStiXSupport new file mode 100644 index 0000000..dd1cfcb --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/PaStiXSupport @@ -0,0 +1,51 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PASTIXSUPPORT_MODULE_H +#define EIGEN_PASTIXSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { +#include +#include +} + +#ifdef complex +#undef complex +#endif + +/** \ingroup Support_modules + * \defgroup PaStiXSupport_Module PaStiXSupport module + * + * This module provides an interface to the PaSTiX library. + * PaSTiX is a general \b supernodal, \b parallel and \b opensource sparse solver. + * It provides the two following main factorization classes: + * - class PastixLLT : a supernodal, parallel LLt Cholesky factorization. + * - class PastixLDLT: a supernodal, parallel LDLt Cholesky factorization. + * - class PastixLU : a supernodal, parallel LU factorization (optimized for a symmetric pattern). + * + * \code + * #include + * \endcode + * + * In order to use this module, the PaSTiX headers must be accessible from the include paths, and your binary must be + * linked to the PaSTiX library and its dependencies. This wrapper resuires PaStiX version 5.x compiled without MPI + * support. The dependencies depend on how PaSTiX has been compiled. For a cmake based project, you can use our + * FindPaSTiX.cmake module to help you in this task. + * + */ + +// IWYU pragma: begin_exports +#include "src/PaStiXSupport/PaStiXSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_PASTIXSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/PardisoSupport b/data_acq_and_processing/third_party/eigen/Eigen/PardisoSupport new file mode 100644 index 0000000..4aef5fb --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/PardisoSupport @@ -0,0 +1,38 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PARDISOSUPPORT_MODULE_H +#define EIGEN_PARDISOSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include + +/** \ingroup Support_modules + * \defgroup PardisoSupport_Module PardisoSupport module + * + * This module brings support for the Intel(R) MKL PARDISO direct sparse solvers. + * + * \code + * #include + * \endcode + * + * In order to use this module, the MKL headers must be accessible from the include paths, and your binary must be + * linked to the MKL library and its dependencies. See this \ref TopicUsingIntelMKL "page" for more information on + * MKL-Eigen integration. + * + */ + +// IWYU pragma: begin_exports +#include "src/PardisoSupport/PardisoSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_PARDISOSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/QR b/data_acq_and_processing/third_party/eigen/Eigen/QR new file mode 100644 index 0000000..c38b453 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/QR @@ -0,0 +1,48 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_QR_MODULE_H +#define EIGEN_QR_MODULE_H + +#include "Core" + +#include "Cholesky" +#include "Jacobi" +#include "Householder" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup QR_Module QR module + * + * + * + * This module provides various QR decompositions + * This module also provides some MatrixBase methods, including: + * - MatrixBase::householderQr() + * - MatrixBase::colPivHouseholderQr() + * - MatrixBase::fullPivHouseholderQr() + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/QR/HouseholderQR.h" +#include "src/QR/FullPivHouseholderQR.h" +#include "src/QR/ColPivHouseholderQR.h" +#include "src/QR/CompleteOrthogonalDecomposition.h" +#ifdef EIGEN_USE_LAPACKE +#include "src/misc/lapacke_helpers.h" +#include "src/QR/HouseholderQR_LAPACKE.h" +#include "src/QR/ColPivHouseholderQR_LAPACKE.h" +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_QR_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/QtAlignedMalloc b/data_acq_and_processing/third_party/eigen/Eigen/QtAlignedMalloc new file mode 100644 index 0000000..585f8e8 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/QtAlignedMalloc @@ -0,0 +1,32 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_QTMALLOC_MODULE_H +#define EIGEN_QTMALLOC_MODULE_H + +#include "Core" + +#if (!EIGEN_MALLOC_ALREADY_ALIGNED) + +#include "src/Core/util/DisableStupidWarnings.h" + +void *qMalloc(std::size_t size) { return Eigen::internal::aligned_malloc(size); } + +void qFree(void *ptr) { Eigen::internal::aligned_free(ptr); } + +void *qRealloc(void *ptr, std::size_t size) { + void *newPtr = Eigen::internal::aligned_malloc(size); + std::memcpy(newPtr, ptr, size); + Eigen::internal::aligned_free(ptr); + return newPtr; +} + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif + +#endif // EIGEN_QTMALLOC_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SPQRSupport b/data_acq_and_processing/third_party/eigen/Eigen/SPQRSupport new file mode 100644 index 0000000..c01dbe0 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SPQRSupport @@ -0,0 +1,41 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPQRSUPPORT_MODULE_H +#define EIGEN_SPQRSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include "SuiteSparseQR.hpp" + +/** \ingroup Support_modules + * \defgroup SPQRSupport_Module SuiteSparseQR module + * + * This module provides an interface to the SPQR library, which is part of the suitesparse package. + * + * \code + * #include + * \endcode + * + * In order to use this module, the SPQR headers must be accessible from the include paths, and your binary must be + * linked to the SPQR library and its dependencies (Cholmod, AMD, COLAMD,...). For a cmake based project, you can use + * our FindSPQR.cmake and FindCholmod.Cmake modules + * + */ + +#include "CholmodSupport" + +// IWYU pragma: begin_exports +#include "src/SPQRSupport/SuiteSparseQRSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SVD b/data_acq_and_processing/third_party/eigen/Eigen/SVD new file mode 100644 index 0000000..b616a6a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SVD @@ -0,0 +1,55 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SVD_MODULE_H +#define EIGEN_SVD_MODULE_H + +#include "QR" +#include "Householder" +#include "Jacobi" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup SVD_Module SVD module + * + * + * + * This module provides SVD decomposition for matrices (both real and complex). + * Two decomposition algorithms are provided: + * - JacobiSVD implementing two-sided Jacobi iterations is numerically very accurate, fast for small matrices, but very + * slow for larger ones. + * - BDCSVD implementing a recursive divide & conquer strategy on top of an upper-bidiagonalization which remains fast + * for large problems. These decompositions are accessible via the respective classes and following MatrixBase methods: + * - MatrixBase::jacobiSvd() + * - MatrixBase::bdcSvd() + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/SVD/UpperBidiagonalization.h" +#include "src/SVD/SVDBase.h" +#include "src/SVD/JacobiSVD.h" +#include "src/SVD/BDCSVD.h" +#ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else +#include "src/misc/lapacke.h" +#endif +#ifndef EIGEN_USE_LAPACKE_STRICT +#include "src/SVD/JacobiSVD_LAPACKE.h" +#endif +#include "src/SVD/BDCSVD_LAPACKE.h" +#endif +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SVD_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Sparse b/data_acq_and_processing/third_party/eigen/Eigen/Sparse new file mode 100644 index 0000000..4d0ee8b --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Sparse @@ -0,0 +1,33 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_MODULE_H +#define EIGEN_SPARSE_MODULE_H + +/** \defgroup Sparse_Module Sparse meta-module + * + * Meta-module including all related modules: + * - \ref SparseCore_Module + * - \ref OrderingMethods_Module + * - \ref SparseCholesky_Module + * - \ref SparseLU_Module + * - \ref SparseQR_Module + * - \ref IterativeLinearSolvers_Module + * + \code + #include + \endcode + */ + +#include "SparseCore" +#include "OrderingMethods" +#include "SparseCholesky" +#include "SparseLU" +#include "SparseQR" +#include "IterativeLinearSolvers" + +#endif // EIGEN_SPARSE_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SparseCholesky b/data_acq_and_processing/third_party/eigen/Eigen/SparseCholesky new file mode 100644 index 0000000..6abdcd6 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SparseCholesky @@ -0,0 +1,40 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2013 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSECHOLESKY_MODULE_H +#define EIGEN_SPARSECHOLESKY_MODULE_H + +#include "SparseCore" +#include "OrderingMethods" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** + * \defgroup SparseCholesky_Module SparseCholesky module + * + * This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) + * matrices. Those decompositions are accessible via the following classes: + * - SimplicialLLt, + * - SimplicialLDLt + * + * Such problems can also be solved using the ConjugateGradient solver from the IterativeLinearSolvers module. + * + * \code + * #include + * \endcode + */ + +// IWYU pragma: begin_exports +#include "src/SparseCholesky/SimplicialCholesky.h" +#include "src/SparseCholesky/SimplicialCholesky_impl.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SPARSECHOLESKY_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SparseCore b/data_acq_and_processing/third_party/eigen/Eigen/SparseCore new file mode 100644 index 0000000..56a9401 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SparseCore @@ -0,0 +1,70 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSECORE_MODULE_H +#define EIGEN_SPARSECORE_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include +#include +#include +#include +#include +#include + +/** + * \defgroup SparseCore_Module SparseCore module + * + * This module provides a sparse matrix representation, and basic associated matrix manipulations + * and operations. + * + * See the \ref TutorialSparse "Sparse tutorial" + * + * \code + * #include + * \endcode + * + * This module depends on: Core. + */ + +// IWYU pragma: begin_exports +#include "src/SparseCore/SparseUtil.h" +#include "src/SparseCore/SparseMatrixBase.h" +#include "src/SparseCore/SparseAssign.h" +#include "src/SparseCore/CompressedStorage.h" +#include "src/SparseCore/AmbiVector.h" +#include "src/SparseCore/SparseCompressedBase.h" +#include "src/SparseCore/SparseMatrix.h" +#include "src/SparseCore/SparseMap.h" +#include "src/SparseCore/SparseVector.h" +#include "src/SparseCore/SparseRef.h" +#include "src/SparseCore/SparseCwiseUnaryOp.h" +#include "src/SparseCore/SparseCwiseBinaryOp.h" +#include "src/SparseCore/SparseTranspose.h" +#include "src/SparseCore/SparseBlock.h" +#include "src/SparseCore/SparseDot.h" +#include "src/SparseCore/SparseRedux.h" +#include "src/SparseCore/SparseView.h" +#include "src/SparseCore/SparseDiagonalProduct.h" +#include "src/SparseCore/ConservativeSparseSparseProduct.h" +#include "src/SparseCore/SparseSparseProductWithPruning.h" +#include "src/SparseCore/SparseProduct.h" +#include "src/SparseCore/SparseDenseProduct.h" +#include "src/SparseCore/SparseSelfAdjointView.h" +#include "src/SparseCore/SparseTriangularView.h" +#include "src/SparseCore/TriangularSolver.h" +#include "src/SparseCore/SparsePermutation.h" +#include "src/SparseCore/SparseFuzzy.h" +#include "src/SparseCore/SparseSolverBase.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SPARSECORE_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SparseLU b/data_acq_and_processing/third_party/eigen/Eigen/SparseLU new file mode 100644 index 0000000..6faf130 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SparseLU @@ -0,0 +1,50 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 Désiré Nuentsa-Wakam +// Copyright (C) 2012 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSELU_MODULE_H +#define EIGEN_SPARSELU_MODULE_H + +#include "SparseCore" + +/** + * \defgroup SparseLU_Module SparseLU module + * This module defines a supernodal factorization of general sparse matrices. + * The code is fully optimized for supernode-panel updates with specialized kernels. + * Please, see the documentation of the SparseLU class for more details. + */ + +// Ordering interface +#include "OrderingMethods" + +#include "src/Core/util/DisableStupidWarnings.h" + +// IWYU pragma: begin_exports +#include "src/SparseLU/SparseLU_Structs.h" +#include "src/SparseLU/SparseLU_SupernodalMatrix.h" +#include "src/SparseLU/SparseLUImpl.h" +#include "src/SparseCore/SparseColEtree.h" +#include "src/SparseLU/SparseLU_Memory.h" +#include "src/SparseLU/SparseLU_heap_relax_snode.h" +#include "src/SparseLU/SparseLU_relax_snode.h" +#include "src/SparseLU/SparseLU_pivotL.h" +#include "src/SparseLU/SparseLU_panel_dfs.h" +#include "src/SparseLU/SparseLU_kernel_bmod.h" +#include "src/SparseLU/SparseLU_panel_bmod.h" +#include "src/SparseLU/SparseLU_column_dfs.h" +#include "src/SparseLU/SparseLU_column_bmod.h" +#include "src/SparseLU/SparseLU_copy_to_ucol.h" +#include "src/SparseLU/SparseLU_pruneL.h" +#include "src/SparseLU/SparseLU_Utils.h" +#include "src/SparseLU/SparseLU.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SPARSELU_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SparseQR b/data_acq_and_processing/third_party/eigen/Eigen/SparseQR new file mode 100644 index 0000000..b4f1cad --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SparseQR @@ -0,0 +1,38 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSEQR_MODULE_H +#define EIGEN_SPARSEQR_MODULE_H + +#include "SparseCore" +#include "OrderingMethods" +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup SparseQR_Module SparseQR module + * \brief Provides QR decomposition for sparse matrices + * + * This module provides a simplicial version of the left-looking Sparse QR decomposition. + * The columns of the input matrix should be reordered to limit the fill-in during the + * decomposition. Built-in methods (COLAMD, AMD) or external methods (METIS) can be used to this end. + * See the \link OrderingMethods_Module OrderingMethods\endlink module for the list + * of built-in and external ordering methods. + * + * \code + * #include + * \endcode + * + * + */ + +// IWYU pragma: begin_exports +#include "src/SparseCore/SparseColEtree.h" +#include "src/SparseQR/SparseQR.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/StdDeque b/data_acq_and_processing/third_party/eigen/Eigen/StdDeque new file mode 100644 index 0000000..01e1d76 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/StdDeque @@ -0,0 +1,30 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// Copyright (C) 2009 Hauke Heibel +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STDDEQUE_MODULE_H +#define EIGEN_STDDEQUE_MODULE_H + +#include "Core" +#include + +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && \ + (EIGEN_MAX_STATIC_ALIGN_BYTES <= 16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ + +#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) + +#else + +// IWYU pragma: begin_exports +#include "src/StlSupport/StdDeque.h" +// IWYU pragma: end_exports + +#endif + +#endif // EIGEN_STDDEQUE_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/StdList b/data_acq_and_processing/third_party/eigen/Eigen/StdList new file mode 100644 index 0000000..1453c9f --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/StdList @@ -0,0 +1,29 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Hauke Heibel +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STDLIST_MODULE_H +#define EIGEN_STDLIST_MODULE_H + +#include "Core" +#include + +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && \ + (EIGEN_MAX_STATIC_ALIGN_BYTES <= 16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ + +#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) + +#else + +// IWYU pragma: begin_exports +#include "src/StlSupport/StdList.h" +// IWYU pragma: end_exports + +#endif + +#endif // EIGEN_STDLIST_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/StdVector b/data_acq_and_processing/third_party/eigen/Eigen/StdVector new file mode 100644 index 0000000..711a654 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/StdVector @@ -0,0 +1,30 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// Copyright (C) 2009 Hauke Heibel +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STDVECTOR_MODULE_H +#define EIGEN_STDVECTOR_MODULE_H + +#include "Core" +#include + +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && \ + (EIGEN_MAX_STATIC_ALIGN_BYTES <= 16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ + +#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) + +#else + +// IWYU pragma: begin_exports +#include "src/StlSupport/StdVector.h" +// IWYU pragma: end_exports + +#endif + +#endif // EIGEN_STDVECTOR_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/SuperLUSupport b/data_acq_and_processing/third_party/eigen/Eigen/SuperLUSupport new file mode 100644 index 0000000..79e2222 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/SuperLUSupport @@ -0,0 +1,70 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SUPERLUSUPPORT_MODULE_H +#define EIGEN_SUPERLUSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#ifdef EMPTY +#define EIGEN_EMPTY_WAS_ALREADY_DEFINED +#endif + +typedef int int_t; +#include +#include +#include + +// slu_util.h defines a preprocessor token named EMPTY which is really polluting, +// so we remove it in favor of a SUPERLU_EMPTY token. +// If EMPTY was already defined then we don't undef it. + +#if defined(EIGEN_EMPTY_WAS_ALREADY_DEFINED) +#undef EIGEN_EMPTY_WAS_ALREADY_DEFINED +#elif defined(EMPTY) +#undef EMPTY +#endif + +#define SUPERLU_EMPTY (-1) + +namespace Eigen { +struct SluMatrix; +} + +/** \ingroup Support_modules + * \defgroup SuperLUSupport_Module SuperLUSupport module + * + * This module provides an interface to the SuperLU library. + * It provides the following factorization class: + * - class SuperLU: a supernodal sequential LU factorization. + * - class SuperILU: a supernodal sequential incomplete LU factorization (to be used as a preconditioner for iterative + * methods). + * + * \warning This wrapper requires at least versions 4.0 of SuperLU. The 3.x versions are not supported. + * + * \warning When including this module, you have to use SUPERLU_EMPTY instead of EMPTY which is no longer defined + * because it is too polluting. + * + * \code + * #include + * \endcode + * + * In order to use this module, the superlu headers must be accessible from the include paths, and your binary must be + * linked to the superlu library and its dependencies. The dependencies depend on how superlu has been compiled. For a + * cmake based project, you can use our FindSuperLU.cmake module to help you in this task. + * + */ + +// IWYU pragma: begin_exports +#include "src/SuperLUSupport/SuperLUSupport.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SUPERLUSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/ThreadPool b/data_acq_and_processing/third_party/eigen/Eigen/ThreadPool new file mode 100644 index 0000000..39e5d1e --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/ThreadPool @@ -0,0 +1,80 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2016 Benoit Steiner +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_THREADPOOL_MODULE_H +#define EIGEN_THREADPOOL_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \defgroup ThreadPool_Module ThreadPool Module + * + * This module provides 2 threadpool implementations + * - a simple reference implementation + * - a faster non blocking implementation + * + * \code + * #include + * \endcode + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// There are non-parenthesized calls to "max" in the header, +// which trigger a check in test/main.h causing compilation to fail. +// We work around the check here by removing the check for max in +// the case where we have to emulate thread_local. +#ifdef max +#undef max +#endif +#include + +#include "src/Core/util/Meta.h" +#include "src/Core/util/MaxSizeVector.h" + +#ifndef EIGEN_MUTEX +#define EIGEN_MUTEX std::mutex +#endif +#ifndef EIGEN_MUTEX_LOCK +#define EIGEN_MUTEX_LOCK std::unique_lock +#endif +#ifndef EIGEN_CONDVAR +#define EIGEN_CONDVAR std::condition_variable +#endif + +// IWYU pragma: begin_exports +#include "src/ThreadPool/ThreadLocal.h" +#include "src/ThreadPool/ThreadYield.h" +#include "src/ThreadPool/ThreadCancel.h" +#include "src/ThreadPool/EventCount.h" +#include "src/ThreadPool/RunQueue.h" +#include "src/ThreadPool/ThreadPoolInterface.h" +#include "src/ThreadPool/ThreadEnvironment.h" +#include "src/ThreadPool/Barrier.h" +#include "src/ThreadPool/NonBlockingThreadPool.h" +#include "src/ThreadPool/CoreThreadPoolDevice.h" +#include "src/ThreadPool/ForkJoin.h" +// IWYU pragma: end_exports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_CXX11_THREADPOOL_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/UmfPackSupport b/data_acq_and_processing/third_party/eigen/Eigen/UmfPackSupport new file mode 100644 index 0000000..126344c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/UmfPackSupport @@ -0,0 +1,42 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_UMFPACKSUPPORT_MODULE_H +#define EIGEN_UMFPACKSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { +#include +} + +/** \ingroup Support_modules + * \defgroup UmfPackSupport_Module UmfPackSupport module + * + * This module provides an interface to the UmfPack library which is part of the suitesparse package. It provides the following factorization class: + * - class UmfPackLU: a multifrontal sequential LU factorization. + * + * \code + * #include + * \endcode + * + * In order to use this module, the umfpack headers must be accessible from the include paths, and your binary must be + * linked to the umfpack library and its dependencies. The dependencies depend on how umfpack has been compiled. For a + * cmake based project, you can use our FindUmfPack.cmake module to help you in this task. + * + */ + +// IWYU pragma: begin_exports +#include "src/UmfPackSupport/UmfPackSupport.h" +// IWYU pragma: endexports + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_UMFPACKSUPPORT_MODULE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/Version b/data_acq_and_processing/third_party/eigen/Eigen/Version new file mode 100644 index 0000000..164c87f --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/Version @@ -0,0 +1,14 @@ +#ifndef EIGEN_VERSION_H +#define EIGEN_VERSION_H + +// The "WORLD" version will forever remain "3" for the "Eigen3" library. +#define EIGEN_WORLD_VERSION 3 +// As of Eigen3 5.0.0, we have moved to Semantic Versioning (semver.org). +#define EIGEN_MAJOR_VERSION 5 +#define EIGEN_MINOR_VERSION 0 +#define EIGEN_PATCH_VERSION 1 +#define EIGEN_PRERELEASE_VERSION "dev" +#define EIGEN_BUILD_VERSION "master" +#define EIGEN_VERSION_STRING "5.0.1-dev+master" + +#endif // EIGEN_VERSION_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/AccelerateSupport.h b/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/AccelerateSupport.h new file mode 100644 index 0000000..13a26df --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/AccelerateSupport.h @@ -0,0 +1,423 @@ +#ifndef EIGEN_ACCELERATESUPPORT_H +#define EIGEN_ACCELERATESUPPORT_H + +#include + +#include + +namespace Eigen { + +template +class AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateLLT + * \brief A direct Cholesky (LLT) factorization and solver based on Accelerate + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ additional information about the matrix structure. Default is Lower. + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateLLT + */ +template +using AccelerateLLT = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateLDLT + * \brief The default Cholesky (LDLT) factorization and solver based on Accelerate + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ additional information about the matrix structure. Default is Lower. + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLT + */ +template +using AccelerateLDLT = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateLDLTUnpivoted + * \brief A direct Cholesky-like LDL^T factorization and solver based on Accelerate with only 1x1 pivots and no pivoting + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ additional information about the matrix structure. Default is Lower. + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTUnpivoted + */ +template +using AccelerateLDLTUnpivoted = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateLDLTSBK + * \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with Supernode Bunch-Kaufman and static + * pivoting + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ additional information about the matrix structure. Default is Lower. + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTSBK + */ +template +using AccelerateLDLTSBK = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateLDLTTPP + * \brief A direct Cholesky (LDLT) factorization and solver based on Accelerate with full threshold partial pivoting + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ additional information about the matrix structure. Default is Lower. + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateLDLTTPP + */ +template +using AccelerateLDLTTPP = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateQR + * \brief A QR factorization and solver based on Accelerate + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateQR + */ +template +using AccelerateQR = AccelerateImpl; + +/** \ingroup AccelerateSupport_Module + * \typedef AccelerateCholeskyAtA + * \brief A QR factorization and solver based on Accelerate without storing Q (equivalent to A^TA = R^T R) + * + * \warning Only single and double precision real scalar types are supported by Accelerate + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseSolverConcept, class AccelerateCholeskyAtA + */ +template +using AccelerateCholeskyAtA = AccelerateImpl; + +namespace internal { +template +struct AccelFactorizationDeleter { + void operator()(T* sym) { + if (sym) { + SparseCleanup(*sym); + delete sym; + sym = nullptr; + } + } +}; + +template +struct SparseTypesTraitBase { + typedef DenseVecT AccelDenseVector; + typedef DenseMatT AccelDenseMatrix; + typedef SparseMatT AccelSparseMatrix; + + typedef SparseOpaqueSymbolicFactorization SymbolicFactorization; + typedef NumFactT NumericFactorization; + + typedef AccelFactorizationDeleter SymbolicFactorizationDeleter; + typedef AccelFactorizationDeleter NumericFactorizationDeleter; +}; + +template +struct SparseTypesTrait {}; + +template <> +struct SparseTypesTrait : SparseTypesTraitBase {}; + +template <> +struct SparseTypesTrait + : SparseTypesTraitBase { +}; + +} // end namespace internal + +template +class AccelerateImpl : public SparseSolverBase > { + protected: + using Base = SparseSolverBase; + using Base::derived; + using Base::m_isInitialized; + + public: + using Base::_solve_impl; + + typedef MatrixType_ MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::StorageIndex StorageIndex; + enum { ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic }; + enum { UpLo = UpLo_ }; + + using AccelDenseVector = typename internal::SparseTypesTrait::AccelDenseVector; + using AccelDenseMatrix = typename internal::SparseTypesTrait::AccelDenseMatrix; + using AccelSparseMatrix = typename internal::SparseTypesTrait::AccelSparseMatrix; + using SymbolicFactorization = typename internal::SparseTypesTrait::SymbolicFactorization; + using NumericFactorization = typename internal::SparseTypesTrait::NumericFactorization; + using SymbolicFactorizationDeleter = typename internal::SparseTypesTrait::SymbolicFactorizationDeleter; + using NumericFactorizationDeleter = typename internal::SparseTypesTrait::NumericFactorizationDeleter; + + AccelerateImpl() { + m_isInitialized = false; + + auto check_flag_set = [](int value, int flag) { return ((value & flag) == flag); }; + + if (check_flag_set(UpLo_, Symmetric)) { + m_sparseKind = SparseSymmetric; + m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle; + } else if (check_flag_set(UpLo_, UnitLower)) { + m_sparseKind = SparseUnitTriangular; + m_triType = SparseLowerTriangle; + } else if (check_flag_set(UpLo_, UnitUpper)) { + m_sparseKind = SparseUnitTriangular; + m_triType = SparseUpperTriangle; + } else if (check_flag_set(UpLo_, StrictlyLower)) { + m_sparseKind = SparseTriangular; + m_triType = SparseLowerTriangle; + } else if (check_flag_set(UpLo_, StrictlyUpper)) { + m_sparseKind = SparseTriangular; + m_triType = SparseUpperTriangle; + } else if (check_flag_set(UpLo_, Lower)) { + m_sparseKind = SparseTriangular; + m_triType = SparseLowerTriangle; + } else if (check_flag_set(UpLo_, Upper)) { + m_sparseKind = SparseTriangular; + m_triType = SparseUpperTriangle; + } else { + m_sparseKind = SparseOrdinary; + m_triType = (UpLo_ & Lower) ? SparseLowerTriangle : SparseUpperTriangle; + } + + m_order = SparseOrderDefault; + } + + explicit AccelerateImpl(const MatrixType& matrix) : AccelerateImpl() { compute(matrix); } + + ~AccelerateImpl() {} + + inline Index cols() const { return m_nCols; } + inline Index rows() const { return m_nRows; } + + ComputationInfo info() const { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + void analyzePattern(const MatrixType& matrix); + + void factorize(const MatrixType& matrix); + + void compute(const MatrixType& matrix); + + template + void _solve_impl(const MatrixBase& b, MatrixBase& dest) const; + + /** Sets the ordering algorithm to use. */ + void setOrder(SparseOrder_t order) { m_order = order; } + + private: + template + void buildAccelSparseMatrix(const SparseMatrix& a, AccelSparseMatrix& A, std::vector& columnStarts) { + const Index nColumnsStarts = a.cols() + 1; + + columnStarts.resize(nColumnsStarts); + + for (Index i = 0; i < nColumnsStarts; i++) columnStarts[i] = a.outerIndexPtr()[i]; + + SparseAttributes_t attributes{}; + attributes.transpose = false; + attributes.triangle = m_triType; + attributes.kind = m_sparseKind; + + SparseMatrixStructure structure{}; + structure.attributes = attributes; + structure.rowCount = static_cast(a.rows()); + structure.columnCount = static_cast(a.cols()); + structure.blockSize = 1; + structure.columnStarts = columnStarts.data(); + structure.rowIndices = const_cast(a.innerIndexPtr()); + + A.structure = structure; + A.data = const_cast(a.valuePtr()); + } + + void doAnalysis(AccelSparseMatrix& A) { + m_numericFactorization.reset(nullptr); + + SparseSymbolicFactorOptions opts{}; + opts.control = SparseDefaultControl; + opts.orderMethod = m_order; + opts.order = nullptr; + opts.ignoreRowsAndColumns = nullptr; + opts.malloc = malloc; + opts.free = free; + opts.reportError = nullptr; + + m_symbolicFactorization.reset(new SymbolicFactorization(SparseFactor(Solver_, A.structure, opts))); + + SparseStatus_t status = m_symbolicFactorization->status; + + updateInfoStatus(status); + + if (status != SparseStatusOK) m_symbolicFactorization.reset(nullptr); + } + + void doFactorization(AccelSparseMatrix& A) { + SparseStatus_t status = SparseStatusReleased; + + if (m_symbolicFactorization) { + m_numericFactorization.reset(new NumericFactorization(SparseFactor(*m_symbolicFactorization, A))); + + status = m_numericFactorization->status; + + if (status != SparseStatusOK) m_numericFactorization.reset(nullptr); + } + + updateInfoStatus(status); + } + + protected: + void updateInfoStatus(SparseStatus_t status) const { + switch (status) { + case SparseStatusOK: + m_info = Success; + break; + case SparseFactorizationFailed: + case SparseMatrixIsSingular: + m_info = NumericalIssue; + break; + case SparseInternalError: + case SparseParameterError: + case SparseStatusReleased: + default: + m_info = InvalidInput; + break; + } + } + + mutable ComputationInfo m_info; + Index m_nRows, m_nCols; + std::unique_ptr m_symbolicFactorization; + std::unique_ptr m_numericFactorization; + SparseKind_t m_sparseKind; + SparseTriangle_t m_triType; + SparseOrder_t m_order; +}; + +/** Computes the symbolic and numeric decomposition of matrix \a a */ +template +void AccelerateImpl::compute(const MatrixType& a) { + if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); + + m_nRows = a.rows(); + m_nCols = a.cols(); + + AccelSparseMatrix A{}; + std::vector columnStarts; + + buildAccelSparseMatrix(a, A, columnStarts); + + doAnalysis(A); + + if (m_symbolicFactorization) doFactorization(A); + + m_isInitialized = true; +} + +/** Performs a symbolic decomposition on the sparsity pattern of matrix \a a. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ +template +void AccelerateImpl::analyzePattern(const MatrixType& a) { + if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); + + m_nRows = a.rows(); + m_nCols = a.cols(); + + AccelSparseMatrix A{}; + std::vector columnStarts; + + buildAccelSparseMatrix(a, A, columnStarts); + + doAnalysis(A); + + m_isInitialized = true; +} + +/** Performs a numeric decomposition of matrix \a a. + * + * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been + * performed. + * + * \sa analyzePattern() + */ +template +void AccelerateImpl::factorize(const MatrixType& a) { + eigen_assert(m_symbolicFactorization && "You must first call analyzePattern()"); + eigen_assert(m_nRows == a.rows() && m_nCols == a.cols()); + + if (EnforceSquare_) eigen_assert(a.rows() == a.cols()); + + AccelSparseMatrix A{}; + std::vector columnStarts; + + buildAccelSparseMatrix(a, A, columnStarts); + + doFactorization(A); +} + +template +template +void AccelerateImpl::_solve_impl(const MatrixBase& b, + MatrixBase& x) const { + if (!m_numericFactorization) { + m_info = InvalidInput; + return; + } + + eigen_assert(m_nRows == b.rows()); + eigen_assert(((b.cols() == 1) || b.outerStride() == b.rows())); + + SparseStatus_t status = SparseStatusOK; + + Scalar* b_ptr = const_cast(b.derived().data()); + Scalar* x_ptr = const_cast(x.derived().data()); + + AccelDenseMatrix xmat{}; + xmat.attributes = SparseAttributes_t(); + xmat.columnCount = static_cast(x.cols()); + xmat.rowCount = static_cast(x.rows()); + xmat.columnStride = xmat.rowCount; + xmat.data = x_ptr; + + AccelDenseMatrix bmat{}; + bmat.attributes = SparseAttributes_t(); + bmat.columnCount = static_cast(b.cols()); + bmat.rowCount = static_cast(b.rows()); + bmat.columnStride = bmat.rowCount; + bmat.data = b_ptr; + + SparseSolve(*m_numericFactorization, bmat, xmat); + + updateInfoStatus(status); +} + +} // end namespace Eigen + +#endif // EIGEN_ACCELERATESUPPORT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/InternalHeaderCheck.h b/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/InternalHeaderCheck.h new file mode 100644 index 0000000..69bcff5 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/AccelerateSupport/InternalHeaderCheck.h @@ -0,0 +1,3 @@ +#ifndef EIGEN_ACCELERATESUPPORT_MODULE_H +#error "Please include Eigen/AccelerateSupport instead of including headers inside the src directory directly." +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/InternalHeaderCheck.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/InternalHeaderCheck.h new file mode 100644 index 0000000..5de2b21 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/InternalHeaderCheck.h @@ -0,0 +1,3 @@ +#ifndef EIGEN_CHOLESKY_MODULE_H +#error "Please include Eigen/Cholesky instead of including headers inside the src directory directly." +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LDLT.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LDLT.h new file mode 100644 index 0000000..45912a2 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LDLT.h @@ -0,0 +1,661 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// Copyright (C) 2009 Keir Mierle +// Copyright (C) 2009 Benoit Jacob +// Copyright (C) 2011 Timothy E. Holy +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_LDLT_H +#define EIGEN_LDLT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : traits { + typedef MatrixXpr XprKind; + typedef SolverStorage StorageKind; + typedef int StorageIndex; + enum { Flags = 0 }; +}; + +template +struct LDLT_Traits; + +// PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef +enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite }; +} // namespace internal + +/** \ingroup Cholesky_Module + * + * \class LDLT + * + * \brief Robust Cholesky decomposition of a matrix with pivoting + * + * \tparam MatrixType_ the type of the matrix of which to compute the LDL^T Cholesky decomposition + * \tparam UpLo_ the triangular part that will be used for the decomposition: Lower (default) or Upper. + * The other triangular part won't be read. + * + * Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite + * matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L + * is lower triangular with a unit diagonal and D is a diagonal matrix. + * + * The decomposition uses pivoting to ensure stability, so that D will have + * zeros in the bottom right rank(A) - n submatrix. Avoiding the square root + * on D also stabilizes the computation. + * + * Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky + * decomposition to determine whether a system of equations has a solution. + * + * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. + * + * \sa MatrixBase::ldlt(), SelfAdjointView::ldlt(), class LLT + */ +template +class LDLT : public SolverBase > { + public: + typedef MatrixType_ MatrixType; + typedef SolverBase Base; + friend class SolverBase; + + EIGEN_GENERIC_PUBLIC_INTERFACE(LDLT) + enum { + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, + UpLo = UpLo_ + }; + typedef Matrix TmpMatrixType; + + typedef Transpositions TranspositionType; + typedef PermutationMatrix PermutationType; + + typedef internal::LDLT_Traits Traits; + + /** \brief Default Constructor. + * + * The default constructor is useful in cases in which the user intends to + * perform decompositions via LDLT::compute(const MatrixType&). + */ + LDLT() + : m_matrix(), + m_l1_norm(0), + m_transpositions(), + m_sign(internal::ZeroSign), + m_isInitialized(false), + m_info(InvalidInput) {} + + /** \brief Default Constructor with memory preallocation + * + * Like the default constructor but with preallocation of the internal data + * according to the specified problem \a size. + * \sa LDLT() + */ + explicit LDLT(Index size) + : m_matrix(size, size), + m_l1_norm(0), + m_transpositions(size), + m_temporary(size), + m_sign(internal::ZeroSign), + m_isInitialized(false), + m_info(InvalidInput) {} + + /** \brief Constructor with decomposition + * + * This calculates the decomposition for the input \a matrix. + * + * \sa LDLT(Index size) + */ + template + explicit LDLT(const EigenBase& matrix) + : m_matrix(matrix.rows(), matrix.cols()), + m_l1_norm(0), + m_transpositions(matrix.rows()), + m_temporary(matrix.rows()), + m_sign(internal::ZeroSign), + m_isInitialized(false), + m_info(InvalidInput) { + compute(matrix.derived()); + } + + /** \brief Constructs a LDLT factorization from a given matrix + * + * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c + * MatrixType is a Eigen::Ref. + * + * \sa LDLT(const EigenBase&) + */ + template + explicit LDLT(EigenBase& matrix) + : m_matrix(matrix.derived()), + m_l1_norm(0), + m_transpositions(matrix.rows()), + m_temporary(matrix.rows()), + m_sign(internal::ZeroSign), + m_isInitialized(false), + m_info(InvalidInput) { + compute(matrix.derived()); + } + + /** Clear any existing decomposition + * \sa rankUpdate(w,sigma) + */ + void setZero() { m_isInitialized = false; } + + /** \returns a view of the upper triangular matrix U */ + inline typename Traits::MatrixU matrixU() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return Traits::getU(m_matrix); + } + + /** \returns a view of the lower triangular matrix L */ + inline typename Traits::MatrixL matrixL() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return Traits::getL(m_matrix); + } + + /** \returns the permutation matrix P as a transposition sequence. + */ + inline const TranspositionType& transpositionsP() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_transpositions; + } + + /** \returns the coefficients of the diagonal matrix D */ + inline Diagonal vectorD() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_matrix.diagonal(); + } + + /** \returns true if the matrix is positive (semidefinite) */ + inline bool isPositive() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign; + } + + /** \returns true if the matrix is negative (semidefinite) */ + inline bool isNegative(void) const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign; + } + +#ifdef EIGEN_PARSED_BY_DOXYGEN + /** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * This function also supports in-place solves using the syntax x = decompositionObject.solve(x) . + * + * \note_about_checking_solutions + * + * More precisely, this method solves \f$ A x = b \f$ using the decomposition \f$ A = P^T L D L^* P \f$ + * by solving the systems \f$ P^T y_1 = b \f$, \f$ L y_2 = y_1 \f$, \f$ D y_3 = y_2 \f$, + * \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then + * \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the + * least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function + * computes the least-square solution of \f$ A x = b \f$ if \f$ A \f$ is singular. + * + * \sa MatrixBase::ldlt(), SelfAdjointView::ldlt() + */ + template + inline Solve solve(const MatrixBase& b) const; +#endif + + template + bool solveInPlace(MatrixBase& bAndX) const; + + template + LDLT& compute(const EigenBase& matrix); + + /** \returns an estimate of the reciprocal condition number of the matrix of + * which \c *this is the LDLT decomposition. + */ + RealScalar rcond() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return internal::rcond_estimate_helper(m_l1_norm, *this); + } + + template + LDLT& rankUpdate(const MatrixBase& w, const RealScalar& alpha = 1); + + /** \returns the internal LDLT decomposition matrix + * + * TODO: document the storage layout. + */ + inline const MatrixType& matrixLDLT() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_matrix; + } + + MatrixType reconstructedMatrix() const; + + /** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix + * is self-adjoint. + * + * This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as: + * \code x = decomposition.adjoint().solve(b) \endcode + */ + const LDLT& adjoint() const { return *this; } + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was successful, + * \c NumericalIssue if the factorization failed because of a zero pivot. + */ + ComputationInfo info() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return m_info; + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + void _solve_impl(const RhsType& rhs, DstType& dst) const; + + template + void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const; +#endif + + protected: + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + + /** \internal + * Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U. + * The strict upper part is used during the decomposition, the strict lower + * part correspond to the coefficients of L (its diagonal is equal to 1 and + * is not stored), and the diagonal entries correspond to D. + */ + MatrixType m_matrix; + RealScalar m_l1_norm; + TranspositionType m_transpositions; + TmpMatrixType m_temporary; + internal::SignMatrix m_sign; + bool m_isInitialized; + ComputationInfo m_info; +}; + +namespace internal { + +template +struct ldlt_inplace; + +template <> +struct ldlt_inplace { + template + static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign) { + using std::abs; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename TranspositionType::StorageIndex IndexType; + eigen_assert(mat.rows() == mat.cols()); + const Index size = mat.rows(); + bool found_zero_pivot = false; + bool ret = true; + + if (size <= 1) { + transpositions.setIdentity(); + if (size == 0) + sign = ZeroSign; + else if (numext::real(mat.coeff(0, 0)) > static_cast(0)) + sign = PositiveSemiDef; + else if (numext::real(mat.coeff(0, 0)) < static_cast(0)) + sign = NegativeSemiDef; + else + sign = ZeroSign; + return true; + } + + for (Index k = 0; k < size; ++k) { + // Find largest diagonal element + Index index_of_biggest_in_corner; + mat.diagonal().tail(size - k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner); + index_of_biggest_in_corner += k; + + transpositions.coeffRef(k) = IndexType(index_of_biggest_in_corner); + if (k != index_of_biggest_in_corner) { + // apply the transposition while taking care to consider only + // the lower triangular part + Index s = size - index_of_biggest_in_corner - 1; // trailing size after the biggest element + mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k)); + mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s)); + std::swap(mat.coeffRef(k, k), mat.coeffRef(index_of_biggest_in_corner, index_of_biggest_in_corner)); + for (Index i = k + 1; i < index_of_biggest_in_corner; ++i) { + Scalar tmp = mat.coeffRef(i, k); + mat.coeffRef(i, k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner, i)); + mat.coeffRef(index_of_biggest_in_corner, i) = numext::conj(tmp); + } + if (NumTraits::IsComplex) + mat.coeffRef(index_of_biggest_in_corner, k) = numext::conj(mat.coeff(index_of_biggest_in_corner, k)); + } + + // partition the matrix: + // A00 | - | - + // lu = A10 | A11 | - + // A20 | A21 | A22 + Index rs = size - k - 1; + Block A21(mat, k + 1, k, rs, 1); + Block A10(mat, k, 0, 1, k); + Block A20(mat, k + 1, 0, rs, k); + + if (k > 0) { + temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint(); + mat.coeffRef(k, k) -= (A10 * temp.head(k)).value(); + if (rs > 0) A21.noalias() -= A20 * temp.head(k); + } + + // In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot + // was smaller than the cutoff value. However, since LDLT is not rank-revealing + // we should only make sure that we do not introduce INF or NaN values. + // Remark that LAPACK also uses 0 as the cutoff value. + RealScalar realAkk = numext::real(mat.coeffRef(k, k)); + bool pivot_is_valid = (abs(realAkk) > RealScalar(0)); + + if (k == 0 && !pivot_is_valid) { + // The entire diagonal is zero, there is nothing more to do + // except filling the transpositions, and checking whether the matrix is zero. + sign = ZeroSign; + for (Index j = 0; j < size; ++j) { + transpositions.coeffRef(j) = IndexType(j); + ret = ret && (mat.col(j).tail(size - j - 1).array() == Scalar(0)).all(); + } + return ret; + } + + if ((rs > 0) && pivot_is_valid) + A21 /= realAkk; + else if (rs > 0) + ret = ret && (A21.array() == Scalar(0)).all(); + + if (found_zero_pivot && pivot_is_valid) + ret = false; // factorization failed + else if (!pivot_is_valid) + found_zero_pivot = true; + + if (sign == PositiveSemiDef) { + if (realAkk < static_cast(0)) sign = Indefinite; + } else if (sign == NegativeSemiDef) { + if (realAkk > static_cast(0)) sign = Indefinite; + } else if (sign == ZeroSign) { + if (realAkk > static_cast(0)) + sign = PositiveSemiDef; + else if (realAkk < static_cast(0)) + sign = NegativeSemiDef; + } + } + + return ret; + } + + // Reference for the algorithm: Davis and Hager, "Multiple Rank + // Modifications of a Sparse Cholesky Factorization" (Algorithm 1) + // Trivial rearrangements of their computations (Timothy E. Holy) + // allow their algorithm to work for rank-1 updates even if the + // original matrix is not of full rank. + // Here only rank-1 updates are implemented, to reduce the + // requirement for intermediate storage and improve accuracy + template + static bool updateInPlace(MatrixType& mat, MatrixBase& w, + const typename MatrixType::RealScalar& sigma = 1) { + using numext::isfinite; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + + const Index size = mat.rows(); + eigen_assert(mat.cols() == size && w.size() == size); + + RealScalar alpha = 1; + + // Apply the update + for (Index j = 0; j < size; j++) { + // Check for termination due to an original decomposition of low-rank + if (!(isfinite)(alpha)) break; + + // Update the diagonal terms + RealScalar dj = numext::real(mat.coeff(j, j)); + Scalar wj = w.coeff(j); + RealScalar swj2 = sigma * numext::abs2(wj); + RealScalar gamma = dj * alpha + swj2; + + mat.coeffRef(j, j) += swj2 / alpha; + alpha += swj2 / dj; + + // Update the terms of L + Index rs = size - j - 1; + w.tail(rs) -= wj * mat.col(j).tail(rs); + if (!numext::is_exactly_zero(gamma)) mat.col(j).tail(rs) += (sigma * numext::conj(wj) / gamma) * w.tail(rs); + } + return true; + } + + template + static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, + const typename MatrixType::RealScalar& sigma = 1) { + // Apply the permutation to the input w + tmp = transpositions * w; + + return ldlt_inplace::updateInPlace(mat, tmp, sigma); + } +}; + +template <> +struct ldlt_inplace { + template + static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, + SignMatrix& sign) { + Transpose matt(mat); + return ldlt_inplace::unblocked(matt, transpositions, temp, sign); + } + + template + static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, + const typename MatrixType::RealScalar& sigma = 1) { + Transpose matt(mat); + return ldlt_inplace::update(matt, transpositions, tmp, w.conjugate(), sigma); + } +}; + +template +struct LDLT_Traits { + typedef const TriangularView MatrixL; + typedef const TriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); } + static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); } +}; + +template +struct LDLT_Traits { + typedef const TriangularView MatrixL; + typedef const TriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); } + static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); } +}; + +} // end namespace internal + +/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix + */ +template +template +LDLT& LDLT::compute(const EigenBase& a) { + eigen_assert(a.rows() == a.cols()); + const Index size = a.rows(); + + m_matrix = a.derived(); + + // Compute matrix L1 norm = max abs column sum. + m_l1_norm = RealScalar(0); + // TODO: move this code to SelfAdjointView + for (Index col = 0; col < size; ++col) { + RealScalar abs_col_sum; + if (UpLo_ == Lower) + abs_col_sum = + m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>(); + else + abs_col_sum = + m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>(); + if (abs_col_sum > m_l1_norm) m_l1_norm = abs_col_sum; + } + + m_transpositions.resize(size); + m_isInitialized = false; + m_temporary.resize(size); + m_sign = internal::ZeroSign; + + m_info = internal::ldlt_inplace::unblocked(m_matrix, m_transpositions, m_temporary, m_sign) ? Success + : NumericalIssue; + + m_isInitialized = true; + return *this; +} + +/** Update the LDLT decomposition: given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T. + * \param w a vector to be incorporated into the decomposition. + * \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column + * vectors. Optional; default value is +1. \sa setZero() + */ +template +template +LDLT& LDLT::rankUpdate( + const MatrixBase& w, const typename LDLT::RealScalar& sigma) { + typedef typename TranspositionType::StorageIndex IndexType; + const Index size = w.rows(); + if (m_isInitialized) { + eigen_assert(m_matrix.rows() == size); + } else { + m_matrix.resize(size, size); + m_matrix.setZero(); + m_transpositions.resize(size); + for (Index i = 0; i < size; i++) m_transpositions.coeffRef(i) = IndexType(i); + m_temporary.resize(size); + m_sign = sigma >= 0 ? internal::PositiveSemiDef : internal::NegativeSemiDef; + m_isInitialized = true; + } + + internal::ldlt_inplace::update(m_matrix, m_transpositions, m_temporary, w, sigma); + + return *this; +} + +#ifndef EIGEN_PARSED_BY_DOXYGEN +template +template +void LDLT::_solve_impl(const RhsType& rhs, DstType& dst) const { + _solve_impl_transposed(rhs, dst); +} + +template +template +void LDLT::_solve_impl_transposed(const RhsType& rhs, DstType& dst) const { + // dst = P b + dst = m_transpositions * rhs; + + // dst = L^-1 (P b) + // dst = L^-*T (P b) + matrixL().template conjugateIf().solveInPlace(dst); + + // dst = D^-* (L^-1 P b) + // dst = D^-1 (L^-*T P b) + // more precisely, use pseudo-inverse of D (see bug 241) + using std::abs; + const typename Diagonal::RealReturnType vecD(vectorD()); + // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min()) + // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS: + // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits::epsilon(),RealScalar(1) + // / NumTraits::highest()); However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the + // highest diagonal element is not well justified and leads to numerical issues in some cases. Moreover, Lapack's + // xSYTRS routines use 0 for the tolerance. Using numeric_limits::min() gives us more robustness to denormals. + RealScalar tolerance = (std::numeric_limits::min)(); + for (Index i = 0; i < vecD.size(); ++i) { + if (abs(vecD(i)) > tolerance) + dst.row(i) /= vecD(i); + else + dst.row(i).setZero(); + } + + // dst = L^-* (D^-* L^-1 P b) + // dst = L^-T (D^-1 L^-*T P b) + matrixL().transpose().template conjugateIf().solveInPlace(dst); + + // dst = P^T (L^-* D^-* L^-1 P b) = A^-1 b + // dst = P^-T (L^-T D^-1 L^-*T P b) = A^-1 b + dst = m_transpositions.transpose() * dst; +} +#endif + +/** \internal use x = ldlt_object.solve(x); + * + * This is the \em in-place version of solve(). + * + * \param bAndX represents both the right-hand side matrix b and result x. + * + * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD. + * + * This version avoids a copy when the right hand side matrix b is not + * needed anymore. + * + * \sa LDLT::solve(), MatrixBase::ldlt() + */ +template +template +bool LDLT::solveInPlace(MatrixBase& bAndX) const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + eigen_assert(m_matrix.rows() == bAndX.rows()); + + bAndX = this->solve(bAndX); + + return true; +} + +/** \returns the matrix represented by the decomposition, + * i.e., it returns the product: P^T L D L^* P. + * This function is provided for debug purpose. */ +template +MatrixType LDLT::reconstructedMatrix() const { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + const Index size = m_matrix.rows(); + MatrixType res(size, size); + + // P + res.setIdentity(); + res = transpositionsP() * res; + // L^* P + res = matrixU() * res; + // D(L^*P) + res = vectorD().real().asDiagonal() * res; + // L(DL^*P) + res = matrixL() * res; + // P^T (LDL^*P) + res = transpositionsP().transpose() * res; + + return res; +} + +/** \cholesky_module + * \returns the Cholesky decomposition with full pivoting without square root of \c *this + * \sa MatrixBase::ldlt() + */ +template +inline LDLT::PlainObject, UpLo> SelfAdjointView::ldlt() + const { + return LDLT(m_matrix); +} + +/** \cholesky_module + * \returns the Cholesky decomposition with full pivoting without square root of \c *this + * \sa SelfAdjointView::ldlt() + */ +template +inline LDLT::PlainObject> MatrixBase::ldlt() const { + return LDLT(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_LDLT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT.h new file mode 100644 index 0000000..7066cd0 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT.h @@ -0,0 +1,516 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_LLT_H +#define EIGEN_LLT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct traits > : traits { + typedef MatrixXpr XprKind; + typedef SolverStorage StorageKind; + typedef int StorageIndex; + enum { Flags = 0 }; +}; + +template +struct LLT_Traits; +} // namespace internal + +/** \ingroup Cholesky_Module + * + * \class LLT + * + * \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features + * + * \tparam MatrixType_ the type of the matrix of which we are computing the LL^T Cholesky decomposition + * \tparam UpLo_ the triangular part that will be used for the decomposition: Lower (default) or Upper. + * The other triangular part won't be read. + * + * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite + * matrix A such that A = LL^* = U^*U, where L is lower triangular. + * + * While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b, + * for that purpose, we recommend the Cholesky decomposition without square root which is more stable + * and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other + * situations like generalised eigen problems with hermitian matrices. + * + * Remember that Cholesky decompositions are not rank-revealing. This LLT decomposition is only stable on positive + * definite matrices, use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine + * whether a system of equations has a solution. + * + * Example: \include LLT_example.cpp + * Output: \verbinclude LLT_example.out + * + * \b Performance: for best performance, it is recommended to use a column-major storage format + * with the Lower triangular part (the default), or, equivalently, a row-major storage format + * with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization + * step, and rank-updates can be up to 3 times slower. + * + * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. + * + * Note that during the decomposition, only the lower (or upper, as defined by UpLo_) triangular part of A is + * considered. Therefore, the strict lower part does not have to store correct values. + * + * \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT + */ +template +class LLT : public SolverBase > { + public: + typedef MatrixType_ MatrixType; + typedef SolverBase Base; + friend class SolverBase; + + EIGEN_GENERIC_PUBLIC_INTERFACE(LLT) + enum { MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime }; + + enum { PacketSize = internal::packet_traits::size, AlignmentMask = int(PacketSize) - 1, UpLo = UpLo_ }; + + typedef internal::LLT_Traits Traits; + + /** + * \brief Default Constructor. + * + * The default constructor is useful in cases in which the user intends to + * perform decompositions via LLT::compute(const MatrixType&). + */ + LLT() : m_matrix(), m_l1_norm(0), m_isInitialized(false), m_info(InvalidInput) {} + + /** \brief Default Constructor with memory preallocation + * + * Like the default constructor but with preallocation of the internal data + * according to the specified problem \a size. + * \sa LLT() + */ + explicit LLT(Index size) : m_matrix(size, size), m_l1_norm(0), m_isInitialized(false), m_info(InvalidInput) {} + + template + explicit LLT(const EigenBase& matrix) + : m_matrix(matrix.rows(), matrix.cols()), m_l1_norm(0), m_isInitialized(false), m_info(InvalidInput) { + compute(matrix.derived()); + } + + /** \brief Constructs a LLT factorization from a given matrix + * + * This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when + * \c MatrixType is a Eigen::Ref. + * + * \sa LLT(const EigenBase&) + */ + template + explicit LLT(EigenBase& matrix) + : m_matrix(matrix.derived()), m_l1_norm(0), m_isInitialized(false), m_info(InvalidInput) { + compute(matrix.derived()); + } + + /** \returns a view of the upper triangular matrix U */ + inline typename Traits::MatrixU matrixU() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + return Traits::getU(m_matrix); + } + + /** \returns a view of the lower triangular matrix L */ + inline typename Traits::MatrixL matrixL() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + return Traits::getL(m_matrix); + } + +#ifdef EIGEN_PARSED_BY_DOXYGEN + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * Since this LLT class assumes anyway that the matrix A is invertible, the solution + * theoretically exists and is unique regardless of b. + * + * Example: \include LLT_solve.cpp + * Output: \verbinclude LLT_solve.out + * + * \sa solveInPlace(), MatrixBase::llt(), SelfAdjointView::llt() + */ + template + inline Solve solve(const MatrixBase& b) const; +#endif + + template + void solveInPlace(const MatrixBase& bAndX) const; + + template + LLT& compute(const EigenBase& matrix); + + /** \returns an estimate of the reciprocal condition number of the matrix of + * which \c *this is the Cholesky decomposition. + */ + RealScalar rcond() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + eigen_assert(m_info == Success && "LLT failed because matrix appears to be negative"); + return internal::rcond_estimate_helper(m_l1_norm, *this); + } + + /** \returns the LLT decomposition matrix + * + * TODO: document the storage layout + */ + inline const MatrixType& matrixLLT() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + return m_matrix; + } + + MatrixType reconstructedMatrix() const; + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was successful, + * \c NumericalIssue if the matrix.appears not to be positive definite. + */ + ComputationInfo info() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + return m_info; + } + + /** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix + * is self-adjoint. + * + * This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as: + * \code x = decomposition.adjoint().solve(b) \endcode + */ + const LLT& adjoint() const noexcept { return *this; } + + constexpr Index rows() const noexcept { return m_matrix.rows(); } + constexpr Index cols() const noexcept { return m_matrix.cols(); } + + template + LLT& rankUpdate(const VectorType& vec, const RealScalar& sigma = 1); + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + void _solve_impl(const RhsType& rhs, DstType& dst) const; + + template + void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const; +#endif + + protected: + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + + /** \internal + * Used to compute and store L + * The strict upper part is not used and even not initialized. + */ + MatrixType m_matrix; + RealScalar m_l1_norm; + bool m_isInitialized; + ComputationInfo m_info; +}; + +namespace internal { + +template +struct llt_inplace; + +template +static Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, + const typename MatrixType::RealScalar& sigma) { + using std::sqrt; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::ColXpr ColXpr; + typedef internal::remove_all_t ColXprCleaned; + typedef typename ColXprCleaned::SegmentReturnType ColXprSegment; + typedef Matrix TempVectorType; + typedef typename TempVectorType::SegmentReturnType TempVecSegment; + + Index n = mat.cols(); + eigen_assert(mat.rows() == n && vec.size() == n); + + TempVectorType temp; + + if (sigma > 0) { + // This version is based on Givens rotations. + // It is faster than the other one below, but only works for updates, + // i.e., for sigma > 0 + temp = sqrt(sigma) * vec; + + for (Index i = 0; i < n; ++i) { + JacobiRotation g; + g.makeGivens(mat(i, i), -temp(i), &mat(i, i)); + + Index rs = n - i - 1; + if (rs > 0) { + ColXprSegment x(mat.col(i).tail(rs)); + TempVecSegment y(temp.tail(rs)); + apply_rotation_in_the_plane(x, y, g); + } + } + } else { + temp = vec; + RealScalar beta = 1; + for (Index j = 0; j < n; ++j) { + RealScalar Ljj = numext::real(mat.coeff(j, j)); + RealScalar dj = numext::abs2(Ljj); + Scalar wj = temp.coeff(j); + RealScalar swj2 = sigma * numext::abs2(wj); + RealScalar gamma = dj * beta + swj2; + + RealScalar x = dj + swj2 / beta; + if (x <= RealScalar(0)) return j; + RealScalar nLjj = sqrt(x); + mat.coeffRef(j, j) = nLjj; + beta += swj2 / dj; + + // Update the terms of L + Index rs = n - j - 1; + if (rs) { + temp.tail(rs) -= (wj / Ljj) * mat.col(j).tail(rs); + if (!numext::is_exactly_zero(gamma)) + mat.col(j).tail(rs) = + (nLjj / Ljj) * mat.col(j).tail(rs) + (nLjj * sigma * numext::conj(wj) / gamma) * temp.tail(rs); + } + } + } + return -1; +} + +template +struct llt_inplace { + typedef typename NumTraits::Real RealScalar; + template + static Index unblocked(MatrixType& mat) { + using std::sqrt; + + eigen_assert(mat.rows() == mat.cols()); + const Index size = mat.rows(); + for (Index k = 0; k < size; ++k) { + Index rs = size - k - 1; // remaining size + + Block A21(mat, k + 1, k, rs, 1); + Block A10(mat, k, 0, 1, k); + Block A20(mat, k + 1, 0, rs, k); + + RealScalar x = numext::real(mat.coeff(k, k)); + if (k > 0) x -= A10.squaredNorm(); + if (x <= RealScalar(0)) return k; + mat.coeffRef(k, k) = x = sqrt(x); + if (k > 0 && rs > 0) A21.noalias() -= A20 * A10.adjoint(); + if (rs > 0) A21 /= x; + } + return -1; + } + + template + static Index blocked(MatrixType& m) { + eigen_assert(m.rows() == m.cols()); + Index size = m.rows(); + if (size < 32) return unblocked(m); + + Index blockSize = size / 8; + blockSize = (blockSize / 16) * 16; + blockSize = (std::min)((std::max)(blockSize, Index(8)), Index(128)); + + for (Index k = 0; k < size; k += blockSize) { + // partition the matrix: + // A00 | - | - + // lu = A10 | A11 | - + // A20 | A21 | A22 + Index bs = (std::min)(blockSize, size - k); + Index rs = size - k - bs; + Block A11(m, k, k, bs, bs); + Block A21(m, k + bs, k, rs, bs); + Block A22(m, k + bs, k + bs, rs, rs); + + Index ret; + if ((ret = unblocked(A11)) >= 0) return k + ret; + if (rs > 0) A11.adjoint().template triangularView().template solveInPlace(A21); + if (rs > 0) + A22.template selfadjointView().rankUpdate(A21, + typename NumTraits::Literal(-1)); // bottleneck + } + return -1; + } + + template + static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) { + return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); + } +}; + +template +struct llt_inplace { + typedef typename NumTraits::Real RealScalar; + + template + static EIGEN_STRONG_INLINE Index unblocked(MatrixType& mat) { + Transpose matt(mat); + return llt_inplace::unblocked(matt); + } + template + static EIGEN_STRONG_INLINE Index blocked(MatrixType& mat) { + Transpose matt(mat); + return llt_inplace::blocked(matt); + } + template + static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) { + Transpose matt(mat); + return llt_inplace::rankUpdate(matt, vec.conjugate(), sigma); + } +}; + +template +struct LLT_Traits { + typedef const TriangularView MatrixL; + typedef const TriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); } + static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); } + static bool inplace_decomposition(MatrixType& m) { + return llt_inplace::blocked(m) == -1; + } +}; + +template +struct LLT_Traits { + typedef const TriangularView MatrixL; + typedef const TriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); } + static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); } + static bool inplace_decomposition(MatrixType& m) { + return llt_inplace::blocked(m) == -1; + } +}; + +} // end namespace internal + +/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix + * + * \returns a reference to *this + * + * Example: \include TutorialLinAlgComputeTwice.cpp + * Output: \verbinclude TutorialLinAlgComputeTwice.out + */ +template +template +LLT& LLT::compute(const EigenBase& a) { + eigen_assert(a.rows() == a.cols()); + const Index size = a.rows(); + m_matrix.resize(size, size); + if (!internal::is_same_dense(m_matrix, a.derived())) m_matrix = a.derived(); + + // Compute matrix L1 norm = max abs column sum. + m_l1_norm = RealScalar(0); + // TODO: move this code to SelfAdjointView + for (Index col = 0; col < size; ++col) { + RealScalar abs_col_sum; + if (UpLo_ == Lower) + abs_col_sum = + m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>(); + else + abs_col_sum = + m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>(); + if (abs_col_sum > m_l1_norm) m_l1_norm = abs_col_sum; + } + + m_isInitialized = true; + bool ok = Traits::inplace_decomposition(m_matrix); + m_info = ok ? Success : NumericalIssue; + + return *this; +} + +/** Performs a rank one update (or dowdate) of the current decomposition. + * If A = LL^* before the rank one update, + * then after it we have LL^* = A + sigma * v v^* where \a v must be a vector + * of same dimension. + */ +template +template +LLT& LLT::rankUpdate(const VectorType& v, const RealScalar& sigma) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType); + eigen_assert(v.size() == m_matrix.cols()); + eigen_assert(m_isInitialized); + if (internal::llt_inplace::rankUpdate(m_matrix, v, sigma) >= 0) + m_info = NumericalIssue; + else + m_info = Success; + + return *this; +} + +#ifndef EIGEN_PARSED_BY_DOXYGEN +template +template +void LLT::_solve_impl(const RhsType& rhs, DstType& dst) const { + _solve_impl_transposed(rhs, dst); +} + +template +template +void LLT::_solve_impl_transposed(const RhsType& rhs, DstType& dst) const { + dst = rhs; + + matrixL().template conjugateIf().solveInPlace(dst); + matrixU().template conjugateIf().solveInPlace(dst); +} +#endif + +/** \internal use x = llt_object.solve(x); + * + * This is the \em in-place version of solve(). + * + * \param bAndX represents both the right-hand side matrix b and result x. + * + * This version avoids a copy when the right hand side matrix b is not needed anymore. + * + * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. + * This function will const_cast it, so constness isn't honored here. + * + * \sa LLT::solve(), MatrixBase::llt() + */ +template +template +void LLT::solveInPlace(const MatrixBase& bAndX) const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + eigen_assert(m_matrix.rows() == bAndX.rows()); + matrixL().solveInPlace(bAndX); + matrixU().solveInPlace(bAndX); +} + +/** \returns the matrix represented by the decomposition, + * i.e., it returns the product: L L^*. + * This function is provided for debug purpose. */ +template +MatrixType LLT::reconstructedMatrix() const { + eigen_assert(m_isInitialized && "LLT is not initialized."); + return matrixL() * matrixL().adjoint().toDenseMatrix(); +} + +/** \cholesky_module + * \returns the LLT decomposition of \c *this + * \sa SelfAdjointView::llt() + */ +template +inline LLT::PlainObject> MatrixBase::llt() const { + return LLT(derived()); +} + +/** \cholesky_module + * \returns the LLT decomposition of \c *this + * \sa SelfAdjointView::llt() + */ +template +inline LLT::PlainObject, UpLo> SelfAdjointView::llt() + const { + return LLT(m_matrix); +} + +} // end namespace Eigen + +#endif // EIGEN_LLT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h new file mode 100644 index 0000000..cb55b15 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h @@ -0,0 +1,124 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ******************************************************************************** + * Content : Eigen bindings to LAPACKe + * LLt decomposition based on LAPACKE_?potrf function. + ******************************************************************************** +*/ + +#ifndef EIGEN_LLT_LAPACKE_H +#define EIGEN_LLT_LAPACKE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +namespace lapacke_helpers { +// ------------------------------------------------------------------------------------------------------------------- +// Dispatch for rank update handling upper and lower parts +// ------------------------------------------------------------------------------------------------------------------- + +template +struct rank_update {}; + +template <> +struct rank_update { + template + static Index run(MatrixType &mat, const VectorType &vec, const typename MatrixType::RealScalar &sigma) { + return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); + } +}; + +template <> +struct rank_update { + template + static Index run(MatrixType &mat, const VectorType &vec, const typename MatrixType::RealScalar &sigma) { + Transpose matt(mat); + return Eigen::internal::llt_rank_update_lower(matt, vec.conjugate(), sigma); + } +}; + +// ------------------------------------------------------------------------------------------------------------------- +// Generic lapacke llt implementation that hands of to the dispatches +// ------------------------------------------------------------------------------------------------------------------- + +template +struct lapacke_llt { + EIGEN_STATIC_ASSERT(((Mode == Lower) || (Mode == Upper)), MODE_MUST_BE_UPPER_OR_LOWER) + template + static Index blocked(MatrixType &m) { + eigen_assert(m.rows() == m.cols()); + if (m.rows() == 0) { + return -1; + } + /* Set up parameters for ?potrf */ + lapack_int size = to_lapack(m.rows()); + lapack_int matrix_order = lapack_storage_of(m); + constexpr char uplo = Mode == Upper ? 'U' : 'L'; + Scalar *a = &(m.coeffRef(0, 0)); + lapack_int lda = to_lapack(m.outerStride()); + + lapack_int info = potrf(matrix_order, uplo, size, to_lapack(a), lda); + info = (info == 0) ? -1 : info > 0 ? info - 1 : size; + return info; + } + + template + static Index rankUpdate(MatrixType &mat, const VectorType &vec, const typename MatrixType::RealScalar &sigma) { + return rank_update::run(mat, vec, sigma); + } +}; +} // namespace lapacke_helpers +// end namespace lapacke_helpers + +/* + * Here, we just put the generic implementation from lapacke_llt into a full specialization of the llt_inplace + * type. By being a full specialization, the versions defined here thus get precedence over the generic implementation + * in LLT.h for double, float and complex double, complex float types. + */ + +#define EIGEN_LAPACKE_LLT(EIGTYPE) \ + template <> \ + struct llt_inplace : public lapacke_helpers::lapacke_llt {}; \ + template <> \ + struct llt_inplace : public lapacke_helpers::lapacke_llt {}; + +EIGEN_LAPACKE_LLT(double) +EIGEN_LAPACKE_LLT(float) +EIGEN_LAPACKE_LLT(std::complex) +EIGEN_LAPACKE_LLT(std::complex) + +#undef EIGEN_LAPACKE_LLT + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_LLT_LAPACKE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/CholmodSupport.h b/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/CholmodSupport.h new file mode 100644 index 0000000..dc3d6a3 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/CholmodSupport.h @@ -0,0 +1,738 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CHOLMODSUPPORT_H +#define EIGEN_CHOLMODSUPPORT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct cholmod_configure_matrix; + +template <> +struct cholmod_configure_matrix { + template + static void run(CholmodType& mat) { + mat.xtype = CHOLMOD_REAL; + mat.dtype = CHOLMOD_DOUBLE; + } +}; + +template <> +struct cholmod_configure_matrix > { + template + static void run(CholmodType& mat) { + mat.xtype = CHOLMOD_COMPLEX; + mat.dtype = CHOLMOD_DOUBLE; + } +}; + +// Other scalar types are not yet supported by Cholmod +// template<> struct cholmod_configure_matrix { +// template +// static void run(CholmodType& mat) { +// mat.xtype = CHOLMOD_REAL; +// mat.dtype = CHOLMOD_SINGLE; +// } +// }; +// +// template<> struct cholmod_configure_matrix > { +// template +// static void run(CholmodType& mat) { +// mat.xtype = CHOLMOD_COMPLEX; +// mat.dtype = CHOLMOD_SINGLE; +// } +// }; + +} // namespace internal + +/** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object. + * Note that the data are shared. + */ +template +cholmod_sparse viewAsCholmod(Ref > mat) { + cholmod_sparse res; + res.nzmax = mat.nonZeros(); + res.nrow = mat.rows(); + res.ncol = mat.cols(); + res.p = mat.outerIndexPtr(); + res.i = mat.innerIndexPtr(); + res.x = mat.valuePtr(); + res.z = 0; + res.sorted = 1; + if (mat.isCompressed()) { + res.packed = 1; + res.nz = 0; + } else { + res.packed = 0; + res.nz = mat.innerNonZeroPtr(); + } + + res.dtype = 0; + res.stype = -1; + + if (internal::is_same::value) { + res.itype = CHOLMOD_INT; + } else if (internal::is_same::value) { + res.itype = CHOLMOD_LONG; + } else { + eigen_assert(false && "Index type not supported yet"); + } + + // setup res.xtype + internal::cholmod_configure_matrix::run(res); + + res.stype = 0; + + return res; +} + +template +const cholmod_sparse viewAsCholmod(const SparseMatrix& mat) { + cholmod_sparse res = viewAsCholmod(Ref >(mat.const_cast_derived())); + return res; +} + +template +const cholmod_sparse viewAsCholmod(const SparseVector& mat) { + cholmod_sparse res = viewAsCholmod(Ref >(mat.const_cast_derived())); + return res; +} + +/** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix. + * The data are not copied but shared. */ +template +cholmod_sparse viewAsCholmod(const SparseSelfAdjointView, UpLo>& mat) { + cholmod_sparse res = viewAsCholmod(Ref >(mat.matrix().const_cast_derived())); + + if (UpLo == Upper) res.stype = 1; + if (UpLo == Lower) res.stype = -1; + // swap stype for rowmajor matrices (only works for real matrices) + EIGEN_STATIC_ASSERT((Options_ & RowMajorBit) == 0 || NumTraits::IsComplex == 0, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); + if (Options_ & RowMajorBit) res.stype *= -1; + + return res; +} + +/** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix. + * The data are not copied but shared. */ +template +cholmod_dense viewAsCholmod(MatrixBase& mat) { + EIGEN_STATIC_ASSERT((internal::traits::Flags & RowMajorBit) == 0, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); + typedef typename Derived::Scalar Scalar; + + cholmod_dense res; + res.nrow = mat.rows(); + res.ncol = mat.cols(); + res.nzmax = res.nrow * res.ncol; + res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride(); + res.x = (void*)(mat.derived().data()); + res.z = 0; + + internal::cholmod_configure_matrix::run(res); + + return res; +} + +/** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix. + * The data are not copied but shared. */ +template +Map > viewAsEigen(cholmod_sparse& cm) { + return Map >( + cm.nrow, cm.ncol, static_cast(cm.p)[cm.ncol], static_cast(cm.p), + static_cast(cm.i), static_cast(cm.x)); +} + +/** Returns a view of the Cholmod sparse matrix factor \a cm as an Eigen sparse matrix. + * The data are not copied but shared. */ +template +Map > viewAsEigen(cholmod_factor& cm) { + return Map >( + cm.n, cm.n, static_cast(cm.p)[cm.n], static_cast(cm.p), + static_cast(cm.i), static_cast(cm.x)); +} + +namespace internal { + +// template specializations for int and long that call the correct cholmod method + +#define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \ + template \ + inline ret cm_##name(cholmod_common& Common) { \ + return cholmod_##name(&Common); \ + } \ + template <> \ + inline ret cm_##name(cholmod_common & Common) { \ + return cholmod_l_##name(&Common); \ + } + +#define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \ + template \ + inline ret cm_##name(t1& a1, cholmod_common& Common) { \ + return cholmod_##name(&a1, &Common); \ + } \ + template <> \ + inline ret cm_##name(t1 & a1, cholmod_common & Common) { \ + return cholmod_l_##name(&a1, &Common); \ + } + +EIGEN_CHOLMOD_SPECIALIZE0(int, start) +EIGEN_CHOLMOD_SPECIALIZE0(int, finish) + +EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L) +EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense, cholmod_dense*, X) +EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A) + +EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A) +EIGEN_CHOLMOD_SPECIALIZE1(cholmod_sparse*, factor_to_sparse, cholmod_factor, L) + +template +inline cholmod_dense* cm_solve(int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) { + return cholmod_solve(sys, &L, &B, &Common); +} +template <> +inline cholmod_dense* cm_solve(int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common& Common) { + return cholmod_l_solve(sys, &L, &B, &Common); +} + +template +inline cholmod_sparse* cm_spsolve(int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common& Common) { + return cholmod_spsolve(sys, &L, &B, &Common); +} +template <> +inline cholmod_sparse* cm_spsolve(int sys, cholmod_factor& L, cholmod_sparse& B, + cholmod_common& Common) { + return cholmod_l_spsolve(sys, &L, &B, &Common); +} + +template +inline int cm_factorize_p(cholmod_sparse* A, double beta[2], StorageIndex_* fset, std::size_t fsize, cholmod_factor* L, + cholmod_common& Common) { + return cholmod_factorize_p(A, beta, fset, fsize, L, &Common); +} +template <> +inline int cm_factorize_p(cholmod_sparse* A, double beta[2], SuiteSparse_long* fset, + std::size_t fsize, cholmod_factor* L, cholmod_common& Common) { + return cholmod_l_factorize_p(A, beta, fset, fsize, L, &Common); +} + +#undef EIGEN_CHOLMOD_SPECIALIZE0 +#undef EIGEN_CHOLMOD_SPECIALIZE1 + +} // namespace internal + +enum CholmodMode { CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt }; + +/** \ingroup CholmodSupport_Module + * \class CholmodBase + * \brief The base class for the direct Cholesky factorization of Cholmod + * \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT + */ +template +class CholmodBase : public SparseSolverBase { + protected: + typedef SparseSolverBase Base; + using Base::derived; + using Base::m_isInitialized; + + public: + typedef MatrixType_ MatrixType; + enum { UpLo = UpLo_ }; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef MatrixType CholMatrixType; + typedef typename MatrixType::StorageIndex StorageIndex; + enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime }; + + public: + CholmodBase() : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false) { + EIGEN_STATIC_ASSERT((internal::is_same::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY); + m_shiftOffset[0] = m_shiftOffset[1] = 0.0; + internal::cm_start(m_cholmod); + } + + explicit CholmodBase(const MatrixType& matrix) + : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false) { + EIGEN_STATIC_ASSERT((internal::is_same::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY); + m_shiftOffset[0] = m_shiftOffset[1] = 0.0; + internal::cm_start(m_cholmod); + compute(matrix); + } + + ~CholmodBase() { + if (m_cholmodFactor) internal::cm_free_factor(m_cholmodFactor, m_cholmod); + internal::cm_finish(m_cholmod); + } + + inline StorageIndex cols() const { return internal::convert_index(m_cholmodFactor->n); } + inline StorageIndex rows() const { return internal::convert_index(m_cholmodFactor->n); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was successful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + Derived& compute(const MatrixType& matrix) { + analyzePattern(matrix); + factorize(matrix); + return derived(); + } + + /** Performs a symbolic decomposition on the sparsity pattern of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) { + if (m_cholmodFactor) { + internal::cm_free_factor(m_cholmodFactor, m_cholmod); + m_cholmodFactor = 0; + } + cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView()); + m_cholmodFactor = internal::cm_analyze(A, m_cholmod); + + this->m_isInitialized = true; + this->m_info = Success; + m_analysisIsOk = true; + m_factorizationIsOk = false; + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been + * performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix) { + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView()); + internal::cm_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod); + + // If the factorization failed, either the input matrix was zero (so m_cholmodFactor == nullptr), or minor is the + // column at which it failed. On success minor == n. + this->m_info = + (m_cholmodFactor != nullptr && m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue); + m_factorizationIsOk = true; + } + + /** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations. + * See the Cholmod user guide for details. */ + cholmod_common& cholmod() { return m_cholmod; } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + void _solve_impl(const MatrixBase& b, MatrixBase& dest) const { + eigen_assert(m_factorizationIsOk && + "The decomposition is not in a valid state for solving, you must first call either compute() or " + "symbolic()/numeric()"); + const Index size = m_cholmodFactor->n; + EIGEN_UNUSED_VARIABLE(size); + eigen_assert(size == b.rows()); + + // Cholmod needs column-major storage without inner-stride, which corresponds to the default behavior of Ref. + Ref > b_ref(b.derived()); + + cholmod_dense b_cd = viewAsCholmod(b_ref); + cholmod_dense* x_cd = internal::cm_solve(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod); + if (!x_cd) { + this->m_info = NumericalIssue; + return; + } + // TODO: optimize this copy by swapping when possible (be careful with alignment, etc.) + // NOTE Actually, the copy can be avoided by calling cholmod_solve2 instead of cholmod_solve + dest = Matrix::Map(reinterpret_cast(x_cd->x), + b.rows(), b.cols()); + internal::cm_free_dense(x_cd, m_cholmod); + } + + /** \internal */ + template + void _solve_impl(const SparseMatrixBase& b, SparseMatrixBase& dest) const { + eigen_assert(m_factorizationIsOk && + "The decomposition is not in a valid state for solving, you must first call either compute() or " + "symbolic()/numeric()"); + const Index size = m_cholmodFactor->n; + EIGEN_UNUSED_VARIABLE(size); + eigen_assert(size == b.rows()); + + // note: cs stands for Cholmod Sparse + Ref > b_ref( + b.const_cast_derived()); + cholmod_sparse b_cs = viewAsCholmod(b_ref); + cholmod_sparse* x_cs = internal::cm_spsolve(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod); + if (!x_cs) { + this->m_info = NumericalIssue; + return; + } + // TODO: optimize this copy by swapping when possible (be careful with alignment, etc.) + // NOTE cholmod_spsolve in fact just calls the dense solver for blocks of 4 columns at a time (similar to Eigen's + // sparse solver) + dest.derived() = viewAsEigen(*x_cs); + internal::cm_free_sparse(x_cs, m_cholmod); + } +#endif // EIGEN_PARSED_BY_DOXYGEN + + /** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization. + * + * During the numerical factorization, an offset term is added to the diagonal coefficients:\n + * \c d_ii = \a offset + \c d_ii + * + * The default is \a offset=0. + * + * \returns a reference to \c *this. + */ + Derived& setShift(const RealScalar& offset) { + m_shiftOffset[0] = double(offset); + return derived(); + } + + /** \returns the determinant of the underlying matrix from the current factorization */ + Scalar determinant() const { + using std::exp; + return exp(logDeterminant()); + } + + /** \returns the log determinant of the underlying matrix from the current factorization */ + Scalar logDeterminant() const { + using numext::real; + using std::log; + eigen_assert(m_factorizationIsOk && + "The decomposition is not in a valid state for solving, you must first call either compute() or " + "symbolic()/numeric()"); + + RealScalar logDet = 0; + Scalar* x = static_cast(m_cholmodFactor->x); + if (m_cholmodFactor->is_super) { + // Supernodal factorization stored as a packed list of dense column-major blocks, + // as described by the following structure: + + // super[k] == index of the first column of the j-th super node + StorageIndex* super = static_cast(m_cholmodFactor->super); + // pi[k] == offset to the description of row indices + StorageIndex* pi = static_cast(m_cholmodFactor->pi); + // px[k] == offset to the respective dense block + StorageIndex* px = static_cast(m_cholmodFactor->px); + + Index nb_super_nodes = m_cholmodFactor->nsuper; + for (Index k = 0; k < nb_super_nodes; ++k) { + StorageIndex ncols = super[k + 1] - super[k]; + StorageIndex nrows = pi[k + 1] - pi[k]; + + Map, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows + 1)); + logDet += sk.real().log().sum(); + } + } else { + // Simplicial factorization stored as standard CSC matrix. + StorageIndex* p = static_cast(m_cholmodFactor->p); + Index size = m_cholmodFactor->n; + for (Index k = 0; k < size; ++k) logDet += log(real(x[p[k]])); + } + if (m_cholmodFactor->is_ll) logDet *= 2.0; + return logDet; + } + + template + void dumpMemory(Stream& /*s*/) {} + + protected: + mutable cholmod_common m_cholmod; + cholmod_factor* m_cholmodFactor; + double m_shiftOffset[2]; + mutable ComputationInfo m_info; + int m_factorizationIsOk; + int m_analysisIsOk; +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodSimplicialLLT + * \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization + * using the Cholmod library. + * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical + * interest. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices X and B can be + * either dense or sparse. + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \implsparsesolverconcept + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non + * compressed. + * + * \warning Only double precision real and complex scalar types are supported by Cholmod. + * + * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT + */ +template +class CholmodSimplicialLLT : public CholmodBase > { + typedef CholmodBase Base; + using Base::m_cholmod; + + public: + typedef MatrixType_ MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::StorageIndex StorageIndex; + typedef TriangularView MatrixL; + typedef TriangularView MatrixU; + + CholmodSimplicialLLT() : Base() { init(); } + + CholmodSimplicialLLT(const MatrixType& matrix) : Base() { + init(); + this->compute(matrix); + } + + ~CholmodSimplicialLLT() {} + + /** \returns an expression of the factor L */ + inline MatrixL matrixL() const { return viewAsEigen(*Base::m_cholmodFactor); } + + /** \returns an expression of the factor U (= L^*) */ + inline MatrixU matrixU() const { return matrixL().adjoint(); } + + protected: + void init() { + m_cholmod.final_asis = 0; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + m_cholmod.final_ll = 1; + } +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodSimplicialLDLT + * \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization + * using the Cholmod library. + * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical + * interest. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices X and B can be + * either dense or sparse. + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \implsparsesolverconcept + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non + * compressed. + * + * \warning Only double precision real and complex scalar types are supported by Cholmod. + * + * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT + */ +template +class CholmodSimplicialLDLT : public CholmodBase > { + typedef CholmodBase Base; + using Base::m_cholmod; + + public: + typedef MatrixType_ MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::StorageIndex StorageIndex; + typedef Matrix VectorType; + typedef TriangularView MatrixL; + typedef TriangularView MatrixU; + + CholmodSimplicialLDLT() : Base() { init(); } + + CholmodSimplicialLDLT(const MatrixType& matrix) : Base() { + init(); + this->compute(matrix); + } + + ~CholmodSimplicialLDLT() {} + + /** \returns a vector expression of the diagonal D */ + inline VectorType vectorD() const { + auto cholmodL = viewAsEigen(*Base::m_cholmodFactor); + + VectorType D{cholmodL.rows()}; + + for (Index k = 0; k < cholmodL.outerSize(); ++k) { + typename decltype(cholmodL)::InnerIterator it{cholmodL, k}; + D(k) = it.value(); + } + + return D; + } + + /** \returns an expression of the factor L */ + inline MatrixL matrixL() const { return viewAsEigen(*Base::m_cholmodFactor); } + + /** \returns an expression of the factor U (= L^*) */ + inline MatrixU matrixU() const { return matrixL().adjoint(); } + + protected: + void init() { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + } +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodSupernodalLLT + * \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization + * using the Cholmod library. + * This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM. + * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \implsparsesolverconcept + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non + * compressed. + * + * \warning Only double precision real and complex scalar types are supported by Cholmod. + * + * \sa \ref TutorialSparseSolverConcept + */ +template +class CholmodSupernodalLLT : public CholmodBase > { + typedef CholmodBase Base; + using Base::m_cholmod; + + public: + typedef MatrixType_ MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::StorageIndex StorageIndex; + + CholmodSupernodalLLT() : Base() { init(); } + + CholmodSupernodalLLT(const MatrixType& matrix) : Base() { + init(); + this->compute(matrix); + } + + ~CholmodSupernodalLLT() {} + + /** \returns an expression of the factor L */ + inline MatrixType matrixL() const { + // Convert Cholmod factor's supernodal storage format to Eigen's CSC storage format + cholmod_sparse* cholmodL = internal::cm_factor_to_sparse(*Base::m_cholmodFactor, m_cholmod); + MatrixType L = viewAsEigen(*cholmodL); + internal::cm_free_sparse(cholmodL, m_cholmod); + + return L; + } + + /** \returns an expression of the factor U (= L^*) */ + inline MatrixType matrixU() const { return matrixL().adjoint(); } + + protected: + void init() { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SUPERNODAL; + } +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodDecomposition + * \brief A general Cholesky factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization + * using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * This variant permits to change the underlying Cholesky method at runtime. + * On the other hand, it does not provide access to the result of the factorization. + * The default is to let Cholmod automatically choose between a simplicial and supernodal factorization. + * + * \tparam MatrixType_ the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo_ the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \implsparsesolverconcept + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non + * compressed. + * + * \warning Only double precision real and complex scalar types are supported by Cholmod. + * + * \sa \ref TutorialSparseSolverConcept + */ +template +class CholmodDecomposition : public CholmodBase > { + typedef CholmodBase Base; + using Base::m_cholmod; + + public: + typedef MatrixType_ MatrixType; + + CholmodDecomposition() : Base() { init(); } + + CholmodDecomposition(const MatrixType& matrix) : Base() { + init(); + this->compute(matrix); + } + + ~CholmodDecomposition() {} + + void setMode(CholmodMode mode) { + switch (mode) { + case CholmodAuto: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_AUTO; + break; + case CholmodSimplicialLLt: + m_cholmod.final_asis = 0; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + m_cholmod.final_ll = 1; + break; + case CholmodSupernodalLLt: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SUPERNODAL; + break; + case CholmodLDLt: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + break; + default: + break; + } + } + + protected: + void init() { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_AUTO; + } +}; + +} // end namespace Eigen + +#endif // EIGEN_CHOLMODSUPPORT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/InternalHeaderCheck.h b/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/InternalHeaderCheck.h new file mode 100644 index 0000000..0fb3abc --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/CholmodSupport/InternalHeaderCheck.h @@ -0,0 +1,3 @@ +#ifndef EIGEN_CHOLMODSUPPORT_MODULE_H +#error "Please include Eigen/CholmodSupport instead of including headers inside the src directory directly." +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArithmeticSequence.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArithmeticSequence.h new file mode 100644 index 0000000..4161771 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArithmeticSequence.h @@ -0,0 +1,239 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2017 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARITHMETIC_SEQUENCE_H +#define EIGEN_ARITHMETIC_SEQUENCE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// Helper to cleanup the type of the increment: +template +struct cleanup_seq_incr { + typedef typename cleanup_index_type::type type; +}; + +} // namespace internal + +//-------------------------------------------------------------------------------- +// seq(first,last,incr) and seqN(first,size,incr) +//-------------------------------------------------------------------------------- + +template > +class ArithmeticSequence; + +template +ArithmeticSequence::type, + typename internal::cleanup_index_type::type, + typename internal::cleanup_seq_incr::type> +seqN(FirstType first, SizeType size, IncrType incr); + +/** \class ArithmeticSequence + * \ingroup Core_Module + * + * This class represents an arithmetic progression \f$ a_0, a_1, a_2, ..., a_{n-1}\f$ defined by + * its \em first value \f$ a_0 \f$, its \em size (aka length) \em n, and the \em increment (aka stride) + * that is equal to \f$ a_{i+1}-a_{i}\f$ for any \em i. + * + * It is internally used as the return type of the Eigen::seq and Eigen::seqN functions, and as the input arguments + * of DenseBase::operator()(const RowIndices&, const ColIndices&), and most of the time this is the + * only way it is used. + * + * \tparam FirstType type of the first element, usually an Index, + * but internally it can be a symbolic expression + * \tparam SizeType type representing the size of the sequence, usually an Index + * or a compile time integral constant. Internally, it can also be a symbolic expression + * \tparam IncrType type of the increment, can be a runtime Index, or a compile time integral constant (default is + * compile-time 1) + * + * \sa Eigen::seq, Eigen::seqN, DenseBase::operator()(const RowIndices&, const ColIndices&), class IndexedView + */ +template +class ArithmeticSequence { + public: + constexpr ArithmeticSequence() = default; + constexpr ArithmeticSequence(FirstType first, SizeType size) : m_first(first), m_size(size) {} + constexpr ArithmeticSequence(FirstType first, SizeType size, IncrType incr) + : m_first(first), m_size(size), m_incr(incr) {} + + enum { + // SizeAtCompileTime = internal::get_fixed_value::value, + IncrAtCompileTime = internal::get_fixed_value::value + }; + + /** \returns the size, i.e., number of elements, of the sequence */ + constexpr Index size() const { return m_size; } + + /** \returns the first element \f$ a_0 \f$ in the sequence */ + constexpr Index first() const { return m_first; } + + /** \returns the value \f$ a_i \f$ at index \a i in the sequence. */ + constexpr Index operator[](Index i) const { return m_first + i * m_incr; } + + constexpr const FirstType& firstObject() const { return m_first; } + constexpr const SizeType& sizeObject() const { return m_size; } + constexpr const IncrType& incrObject() const { return m_incr; } + + protected: + FirstType m_first; + SizeType m_size; + IncrType m_incr; + + public: + constexpr auto reverse() const -> decltype(Eigen::seqN(m_first + (m_size + fix<-1>()) * m_incr, m_size, -m_incr)) { + return seqN(m_first + (m_size + fix<-1>()) * m_incr, m_size, -m_incr); + } +}; + +/** \returns an ArithmeticSequence starting at \a first, of length \a size, and increment \a incr + * + * \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */ +template +ArithmeticSequence::type, + typename internal::cleanup_index_type::type, + typename internal::cleanup_seq_incr::type> +seqN(FirstType first, SizeType size, IncrType incr) { + return ArithmeticSequence::type, + typename internal::cleanup_index_type::type, + typename internal::cleanup_seq_incr::type>(first, size, incr); +} + +/** \returns an ArithmeticSequence starting at \a first, of length \a size, and unit increment + * + * \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) */ +template +ArithmeticSequence::type, + typename internal::cleanup_index_type::type> +seqN(FirstType first, SizeType size) { + return ArithmeticSequence::type, + typename internal::cleanup_index_type::type>(first, size); +} + +#ifdef EIGEN_PARSED_BY_DOXYGEN + +/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and with positive (or negative) increment \a + * incr + * + * It is essentially an alias to: + * \code + * seqN(f, (l-f+incr)/incr, incr); + * \endcode + * + * \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) + */ +template +auto seq(FirstType f, LastType l, IncrType incr); + +/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment + * + * It is essentially an alias to: + * \code + * seqN(f,l-f+1); + * \endcode + * + * \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) + */ +template +auto seq(FirstType f, LastType l); + +#else // EIGEN_PARSED_BY_DOXYGEN + +template +auto seq(FirstType f, LastType l) + -> decltype(seqN(typename internal::cleanup_index_type::type(f), + (typename internal::cleanup_index_type::type(l) - + typename internal::cleanup_index_type::type(f) + fix<1>()))) { + return seqN(typename internal::cleanup_index_type::type(f), + (typename internal::cleanup_index_type::type(l) - + typename internal::cleanup_index_type::type(f) + fix<1>())); +} + +template +auto seq(FirstType f, LastType l, IncrType incr) + -> decltype(seqN(typename internal::cleanup_index_type::type(f), + (typename internal::cleanup_index_type::type(l) - + typename internal::cleanup_index_type::type(f) + + typename internal::cleanup_seq_incr::type(incr)) / + typename internal::cleanup_seq_incr::type(incr), + typename internal::cleanup_seq_incr::type(incr))) { + typedef typename internal::cleanup_seq_incr::type CleanedIncrType; + return seqN(typename internal::cleanup_index_type::type(f), + (typename internal::cleanup_index_type::type(l) - + typename internal::cleanup_index_type::type(f) + CleanedIncrType(incr)) / + CleanedIncrType(incr), + CleanedIncrType(incr)); +} + +#endif // EIGEN_PARSED_BY_DOXYGEN + +namespace placeholders { + +/** \cpp11 + * \returns a symbolic ArithmeticSequence representing the last \a size elements with increment \a incr. + * + * It is a shortcut for: \code seqN(last-(size-fix<1>)*incr, size, incr) \endcode + * \anchor Eigen_placeholders_lastN + * \sa lastN(SizeType), seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */ +template +auto lastN(SizeType size, IncrType incr) + -> decltype(seqN(Eigen::placeholders::last - (size - fix<1>()) * incr, size, incr)) { + return seqN(Eigen::placeholders::last - (size - fix<1>()) * incr, size, incr); +} + +/** \cpp11 + * \returns a symbolic ArithmeticSequence representing the last \a size elements with a unit increment. + * + * It is a shortcut for: \code seq(last+fix<1>-size, last) \endcode + * + * \sa lastN(SizeType,IncrType, seqN(FirstType,SizeType), seq(FirstType,LastType) */ +template +auto lastN(SizeType size) -> decltype(seqN(Eigen::placeholders::last + fix<1>() - size, size)) { + return seqN(Eigen::placeholders::last + fix<1>() - size, size); +} + +} // namespace placeholders + +/** \namespace Eigen::indexing + * \ingroup Core_Module + * + * The sole purpose of this namespace is to be able to import all functions + * and symbols that are expected to be used within operator() for indexing + * and slicing. If you already imported the whole Eigen namespace: + * \code using namespace Eigen; \endcode + * then you are already all set. Otherwise, if you don't want/cannot import + * the whole Eigen namespace, the following line: + * \code using namespace Eigen::indexing; \endcode + * is equivalent to: + * \code + using Eigen::fix; + using Eigen::seq; + using Eigen::seqN; + using Eigen::placeholders::all; + using Eigen::placeholders::last; + using Eigen::placeholders::lastN; // c++11 only + using Eigen::placeholders::lastp1; + \endcode + */ +namespace indexing { +using Eigen::fix; +using Eigen::seq; +using Eigen::seqN; +using Eigen::placeholders::all; +using Eigen::placeholders::last; +using Eigen::placeholders::lastN; +using Eigen::placeholders::lastp1; +} // namespace indexing + +} // end namespace Eigen + +#endif // EIGEN_ARITHMETIC_SEQUENCE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Array.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Array.h new file mode 100644 index 0000000..b6b4637 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Array.h @@ -0,0 +1,374 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARRAY_H +#define EIGEN_ARRAY_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits> + : traits> { + typedef ArrayXpr XprKind; + typedef ArrayBase> XprBase; +}; +} // namespace internal + +/** \class Array + * \ingroup Core_Module + * + * \brief General-purpose arrays with easy API for coefficient-wise operations + * + * The %Array class is very similar to the Matrix class. It provides + * general-purpose one- and two-dimensional arrays. The difference between the + * %Array and the %Matrix class is primarily in the API: the API for the + * %Array class provides easy access to coefficient-wise operations, while the + * API for the %Matrix class provides easy access to linear-algebra + * operations. + * + * See documentation of class Matrix for detailed information on the template parameters + * storage layout. + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAY_PLUGIN. + * + * \sa \blank \ref TutorialArrayClass, \ref TopicClassHierarchy + */ +template +class Array : public PlainObjectBase> { + public: + typedef PlainObjectBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Array) + + enum { Options = Options_ }; + typedef typename Base::PlainObject PlainObject; + + protected: + template + friend struct internal::conservative_resize_like_impl; + + using Base::m_storage; + + public: + using Base::base; + using Base::coeff; + using Base::coeffRef; + + /** + * The usage of + * using Base::operator=; + * fails on MSVC. Since the code below is working with GCC and MSVC, we skipped + * the usage of 'using'. This should be done only for operator=. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array& operator=(const EigenBase& other) { + return Base::operator=(other); + } + + /** Set all the entries to \a value. + * \sa DenseBase::setConstant(), DenseBase::fill() + */ + /* This overload is needed because the usage of + * using Base::operator=; + * fails on MSVC. Since the code below is working with GCC and MSVC, we skipped + * the usage of 'using'. This should be done only for operator=. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array& operator=(const Scalar& value) { + Base::setConstant(value); + return *this; + } + + /** Copies the value of the expression \a other into \c *this with automatic resizing. + * + * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), + * it will be initialized. + * + * Note that copying a row-vector into a vector (and conversely) is allowed. + * The resizing, if any, is then done in the appropriate way so that row-vectors + * remain row-vectors and vectors remain vectors. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array& operator=(const DenseBase& other) { + return Base::_set(other); + } + + /** + * \brief Assigns arrays to each other. + * + * \note This is a special case of the templated operator=. Its purpose is + * to prevent a default operator= from hiding the templated operator=. + * + * \callgraph + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array& operator=(const Array& other) { return Base::_set(other); } + + /** Default constructor. + * + * For fixed-size matrices, does nothing. + * + * For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix + * is called a null matrix. This constructor is the unique way to create null matrices: resizing + * a matrix to 0 is not supported. + * + * \sa resize(Index,Index) + */ +#ifdef EIGEN_INITIALIZE_COEFFS + EIGEN_DEVICE_FUNC constexpr Array() : Base() { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED } +#else + EIGEN_DEVICE_FUNC constexpr Array() = default; +#endif + /** \brief Move constructor */ + EIGEN_DEVICE_FUNC constexpr Array(Array&&) = default; + EIGEN_DEVICE_FUNC Array& operator=(Array&& other) noexcept(std::is_nothrow_move_assignable::value) { + Base::operator=(std::move(other)); + return *this; + } + + /** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients. + * + * \only_for_vectors + * + * This constructor is for 1D array or vectors with more than 4 coefficients. + * + * \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this + * constructor must match the fixed number of rows (resp. columns) of \c *this. + * + * + * Example: \include Array_variadic_ctor_cxx11.cpp + * Output: \verbinclude Array_variadic_ctor_cxx11.out + * + * \sa Array(const std::initializer_list>&) + * \sa Array(const Scalar&), Array(const Scalar&,const Scalar&) + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, + const ArgTypes&... args) + : Base(a0, a1, a2, a3, args...) {} + + /** \brief Constructs an array and initializes it from the coefficients given as initializer-lists grouped by row. + * \cpp11 + * + * In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients: + * + * Example: \include Array_initializer_list_23_cxx11.cpp + * Output: \verbinclude Array_initializer_list_23_cxx11.out + * + * Each of the inner initializer lists must contain the exact same number of elements, otherwise an assertion is + * triggered. + * + * In the case of a compile-time column 1D array, implicit transposition from a single row is allowed. + * Therefore Array{{1,2,3,4,5}} is legal and the more verbose syntax + * Array{{1},{2},{3},{4},{5}} can be avoided: + * + * Example: \include Array_initializer_list_vector_cxx11.cpp + * Output: \verbinclude Array_initializer_list_vector_cxx11.out + * + * In the case of fixed-sized arrays, the initializer list sizes must exactly match the array sizes, + * and implicit transposition is allowed for compile-time 1D arrays only. + * + * \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) + */ + EIGEN_DEVICE_FUNC constexpr Array(const std::initializer_list>& list) : Base(list) {} + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit Array(const T& x) { + Base::template _init1(x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const T0& val0, const T1& val1) { + this->template _init2(val0, val1); + } + +#else + /** \brief Constructs a fixed-sized array initialized with coefficients starting at \a data */ + EIGEN_DEVICE_FUNC explicit Array(const Scalar* data); + /** Constructs a vector or row-vector with given dimension. \only_for_vectors + * + * Note that this is only useful for dynamic-size vectors. For fixed-size vectors, + * it is redundant to pass the dimension here, so it makes more sense to use the default + * constructor Array() instead. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit Array(Index dim); + /** constructs an initialized 1x1 Array with the given coefficient + * \sa const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args */ + Array(const Scalar& value); + /** constructs an uninitialized array with \a rows rows and \a cols columns. + * + * This is useful for dynamic-size arrays. For fixed-size arrays, + * it is redundant to pass these parameters, so one should use the default constructor + * Array() instead. */ + Array(Index rows, Index cols); + /** constructs an initialized 2D vector with given coefficients + * \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) */ + Array(const Scalar& val0, const Scalar& val1); +#endif // end EIGEN_PARSED_BY_DOXYGEN + + /** constructs an initialized 3D vector with given coefficients + * \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3) + m_storage.data()[0] = val0; + m_storage.data()[1] = val1; + m_storage.data()[2] = val2; + } + /** constructs an initialized 4D vector with given coefficients + * \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2, + const Scalar& val3) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4) + m_storage.data()[0] = val0; + m_storage.data()[1] = val1; + m_storage.data()[2] = val2; + m_storage.data()[3] = val3; + } + + /** Copy constructor */ + EIGEN_DEVICE_FUNC constexpr Array(const Array&) = default; + + private: + struct PrivateType {}; + + public: + /** \sa MatrixBase::operator=(const EigenBase&) */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Array( + const EigenBase& other, + std::enable_if_t::value, PrivateType> = + PrivateType()) + : Base(other.derived()) {} + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return 1; } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return this->innerSize(); } + +#ifdef EIGEN_ARRAY_PLUGIN +#include EIGEN_ARRAY_PLUGIN +#endif + + private: + template + friend struct internal::matrix_swap_impl; +}; + +/** \defgroup arraytypedefs Global array typedefs + * \ingroup Core_Module + * + * %Eigen defines several typedef shortcuts for most common 1D and 2D array types. + * + * The general patterns are the following: + * + * \c ArrayRowsColsType where \c Rows and \c Cols can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for + * dynamic size, and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c + * cd for complex double. + * + * For example, \c Array33d is a fixed-size 3x3 array type of doubles, and \c ArrayXXf is a dynamic-size matrix of + * floats. + * + * There are also \c ArraySizeType which are self-explanatory. For example, \c Array4cf is + * a fixed-size 1D array of 4 complex floats. + * + * With \cpp11, template alias are also defined for common sizes. + * They follow the same pattern as above except that the scalar type suffix is replaced by a + * template parameter, i.e.: + * - `ArrayRowsCols` where `Rows` and `Cols` can be \c 2,\c 3,\c 4, or \c X for fixed or dynamic size. + * - `ArraySize` where `Size` can be \c 2,\c 3,\c 4 or \c X for fixed or dynamic size 1D arrays. + * + * \sa class Array + */ + +#define EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ + /** \ingroup arraytypedefs */ \ + typedef Array Array##SizeSuffix##SizeSuffix##TypeSuffix; \ + /** \ingroup arraytypedefs */ \ + typedef Array Array##SizeSuffix##TypeSuffix; + +#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \ + /** \ingroup arraytypedefs */ \ + typedef Array Array##Size##X##TypeSuffix; \ + /** \ingroup arraytypedefs */ \ + typedef Array Array##X##Size##TypeSuffix; + +#define EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ + EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 2, 2) \ + EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 3, 3) \ + EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 4, 4) \ + EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \ + EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \ + EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \ + EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 4) + +EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(int, i) +EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(float, f) +EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(double, d) +EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex, cf) +EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex, cd) + +#undef EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES +#undef EIGEN_MAKE_ARRAY_TYPEDEFS +#undef EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS + +#define EIGEN_MAKE_ARRAY_TYPEDEFS(Size, SizeSuffix) \ + /** \ingroup arraytypedefs */ \ + /** \brief \cpp11 */ \ + template \ + using Array##SizeSuffix##SizeSuffix = Array; \ + /** \ingroup arraytypedefs */ \ + /** \brief \cpp11 */ \ + template \ + using Array##SizeSuffix = Array; + +#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Size) \ + /** \ingroup arraytypedefs */ \ + /** \brief \cpp11 */ \ + template \ + using Array##Size##X = Array; \ + /** \ingroup arraytypedefs */ \ + /** \brief \cpp11 */ \ + template \ + using Array##X##Size = Array; + +EIGEN_MAKE_ARRAY_TYPEDEFS(2, 2) +EIGEN_MAKE_ARRAY_TYPEDEFS(3, 3) +EIGEN_MAKE_ARRAY_TYPEDEFS(4, 4) +EIGEN_MAKE_ARRAY_TYPEDEFS(Dynamic, X) +EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(2) +EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(3) +EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(4) + +#undef EIGEN_MAKE_ARRAY_TYPEDEFS +#undef EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS + +#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \ + using Eigen::Matrix##SizeSuffix##TypeSuffix; \ + using Eigen::Vector##SizeSuffix##TypeSuffix; \ + using Eigen::RowVector##SizeSuffix##TypeSuffix; + +#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(TypeSuffix) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) + +#define EIGEN_USING_ARRAY_TYPEDEFS \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(i) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(f) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(d) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cf) \ + EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cd) + +} // end namespace Eigen + +#endif // EIGEN_ARRAY_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayBase.h new file mode 100644 index 0000000..dacc239 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayBase.h @@ -0,0 +1,210 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARRAYBASE_H +#define EIGEN_ARRAYBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +class MatrixWrapper; + +/** \class ArrayBase + * \ingroup Core_Module + * + * \brief Base class for all 1D and 2D array, and related expressions + * + * An array is similar to a dense vector or matrix. While matrices are mathematical + * objects with well defined linear algebra operators, an array is just a collection + * of scalar values arranged in a one or two dimensional fashion. As the main consequence, + * all operations applied to an array are performed coefficient wise. Furthermore, + * arrays support scalar math functions of the c++ standard library (e.g., std::sin(x)), and convenient + * constructors allowing to easily write generic code working for both scalar values + * and arrays. + * + * This class is the base that is inherited by all array expression types. + * + * \tparam Derived is the derived type, e.g., an array or an expression type. + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAYBASE_PLUGIN. + * + * \sa class MatrixBase, \ref TopicClassHierarchy + */ +template +class ArrayBase : public DenseBase { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** The base class for a given storage type. */ + typedef ArrayBase StorageBaseType; + + typedef ArrayBase Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl; + + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::packet_traits::type PacketScalar; + typedef typename NumTraits::Real RealScalar; + + typedef DenseBase Base; + using Base::ColsAtCompileTime; + using Base::Flags; + using Base::IsVectorAtCompileTime; + using Base::MaxColsAtCompileTime; + using Base::MaxRowsAtCompileTime; + using Base::MaxSizeAtCompileTime; + using Base::RowsAtCompileTime; + using Base::SizeAtCompileTime; + + using Base::coeff; + using Base::coeffRef; + using Base::cols; + using Base::const_cast_derived; + using Base::derived; + using Base::lazyAssign; + using Base::rows; + using Base::size; + using Base::operator-; + using Base::operator=; + using Base::operator+=; + using Base::operator-=; + using Base::operator*=; + using Base::operator/=; + + typedef typename Base::CoeffReturnType CoeffReturnType; + + typedef typename Base::PlainObject PlainObject; + + /** \internal Represents a matrix with all coefficients equal to one another*/ + typedef CwiseNullaryOp, PlainObject> ConstantReturnType; +#endif // not EIGEN_PARSED_BY_DOXYGEN + +#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase +#define EIGEN_DOC_UNARY_ADDONS(X, Y) +#include "../plugins/MatrixCwiseUnaryOps.inc" +#include "../plugins/ArrayCwiseUnaryOps.inc" +#include "../plugins/CommonCwiseBinaryOps.inc" +#include "../plugins/MatrixCwiseBinaryOps.inc" +#include "../plugins/ArrayCwiseBinaryOps.inc" +#ifdef EIGEN_ARRAYBASE_PLUGIN +#include EIGEN_ARRAYBASE_PLUGIN +#endif +#undef EIGEN_CURRENT_STORAGE_BASE_CLASS +#undef EIGEN_DOC_UNARY_ADDONS + + /** Special case of the template operator=, in order to prevent the compiler + * from generating a default operator= (issue hit with g++ 4.1) + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const ArrayBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); + } + + /** Set all the entries to \a value. + * \sa DenseBase::setConstant(), DenseBase::fill() */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const Scalar& value) { + Base::setConstant(value); + return derived(); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const Scalar& other) { + internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other), + internal::add_assign_op()); + return derived(); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const Scalar& other) { + internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other), + internal::sub_assign_op()); + return derived(); + } + + /** replaces \c *this by \c *this + \a other. + * + * \returns a reference to \c *this + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const ArrayBase& other) { + call_assignment(derived(), other.derived(), internal::add_assign_op()); + return derived(); + } + + /** replaces \c *this by \c *this - \a other. + * + * \returns a reference to \c *this + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const ArrayBase& other) { + call_assignment(derived(), other.derived(), internal::sub_assign_op()); + return derived(); + } + + /** replaces \c *this by \c *this * \a other coefficient wise. + * + * \returns a reference to \c *this + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const ArrayBase& other) { + call_assignment(derived(), other.derived(), internal::mul_assign_op()); + return derived(); + } + + /** replaces \c *this by \c *this / \a other coefficient wise. + * + * \returns a reference to \c *this + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const ArrayBase& other) { + call_assignment(derived(), other.derived(), internal::div_assign_op()); + return derived(); + } + + public: + EIGEN_DEVICE_FUNC constexpr ArrayBase& array() { return *this; } + EIGEN_DEVICE_FUNC constexpr const ArrayBase& array() const { return *this; } + + /** \returns an \link Eigen::MatrixBase Matrix \endlink expression of this array + * \sa MatrixBase::array() */ + EIGEN_DEVICE_FUNC constexpr MatrixWrapper matrix() { return MatrixWrapper(derived()); } + EIGEN_DEVICE_FUNC constexpr const MatrixWrapper matrix() const { + return MatrixWrapper(derived()); + } + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(ArrayBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(ArrayBase) + + private: + explicit ArrayBase(Index); + ArrayBase(Index, Index); + template + explicit ArrayBase(const ArrayBase&); + + protected: + // mixing arrays and matrices is not legal + template + Derived& operator+=(const MatrixBase&) { + EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar)) == -1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); + return *this; + } + // mixing arrays and matrices is not legal + template + Derived& operator-=(const MatrixBase&) { + EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar)) == -1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); + return *this; + } +}; + +} // end namespace Eigen + +#endif // EIGEN_ARRAYBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayWrapper.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayWrapper.h new file mode 100644 index 0000000..fb05ab5 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ArrayWrapper.h @@ -0,0 +1,166 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARRAYWRAPPER_H +#define EIGEN_ARRAYWRAPPER_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class ArrayWrapper + * \ingroup Core_Module + * + * \brief Expression of a mathematical vector or matrix as an array object + * + * This class is the return type of MatrixBase::array(), and most of the time + * this is the only way it is used. + * + * \sa MatrixBase::array(), class MatrixWrapper + */ + +namespace internal { +template +struct traits > : public traits > { + typedef ArrayXpr XprKind; + // Let's remove NestByRefBit + enum { + Flags0 = traits >::Flags, + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag + }; +}; +} // namespace internal + +template +class ArrayWrapper : public ArrayBase > { + public: + typedef ArrayBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper) + typedef internal::remove_all_t NestedExpression; + + typedef std::conditional_t::value, Scalar, const Scalar> + ScalarWithConstIfNotLvalue; + + typedef typename internal::ref_selector::non_const_type NestedExpressionType; + + using Base::coeffRef; + + EIGEN_DEVICE_FUNC constexpr explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) + : m_expression(matrix) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); } + + EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_expression.data(); } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index rowId, Index colId) const { + return m_expression.coeffRef(rowId, colId); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const { return m_expression.coeffRef(index); } + + template + EIGEN_DEVICE_FUNC inline void evalTo(Dest& dst) const { + dst = m_expression; + } + + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { + return m_expression; + } + + /** Forwards the resizing request to the nested expression + * \sa DenseBase::resize(Index) */ + EIGEN_DEVICE_FUNC void resize(Index newSize) { m_expression.resize(newSize); } + /** Forwards the resizing request to the nested expression + * \sa DenseBase::resize(Index,Index)*/ + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { m_expression.resize(rows, cols); } + + protected: + NestedExpressionType m_expression; +}; + +/** \class MatrixWrapper + * \ingroup Core_Module + * + * \brief Expression of an array as a mathematical vector or matrix + * + * This class is the return type of ArrayBase::matrix(), and most of the time + * this is the only way it is used. + * + * \sa MatrixBase::matrix(), class ArrayWrapper + */ + +namespace internal { +template +struct traits > : public traits > { + typedef MatrixXpr XprKind; + // Let's remove NestByRefBit + enum { + Flags0 = traits >::Flags, + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag + }; +}; +} // namespace internal + +template +class MatrixWrapper : public MatrixBase > { + public: + typedef MatrixBase > Base; + EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper) + typedef internal::remove_all_t NestedExpression; + + typedef std::conditional_t::value, Scalar, const Scalar> + ScalarWithConstIfNotLvalue; + + typedef typename internal::ref_selector::non_const_type NestedExpressionType; + + using Base::coeffRef; + + EIGEN_DEVICE_FUNC constexpr explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); } + + EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_expression.data(); } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index rowId, Index colId) const { + return m_expression.derived().coeffRef(rowId, colId); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const { return m_expression.coeffRef(index); } + + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { + return m_expression; + } + + /** Forwards the resizing request to the nested expression + * \sa DenseBase::resize(Index) */ + EIGEN_DEVICE_FUNC void resize(Index newSize) { m_expression.resize(newSize); } + /** Forwards the resizing request to the nested expression + * \sa DenseBase::resize(Index,Index)*/ + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { m_expression.resize(rows, cols); } + + protected: + NestedExpressionType m_expression; +}; + +} // end namespace Eigen + +#endif // EIGEN_ARRAYWRAPPER_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign.h new file mode 100644 index 0000000..3d30d86 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign.h @@ -0,0 +1,84 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2007 Michael Olbrich +// Copyright (C) 2006-2010 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ASSIGN_H +#define EIGEN_ASSIGN_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::lazyAssign( + const DenseBase& other) { + enum { SameType = internal::is_same::value }; + + EIGEN_STATIC_ASSERT_LVALUE(Derived) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived, OtherDerived) + EIGEN_STATIC_ASSERT( + SameType, + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + + eigen_assert(rows() == other.rows() && cols() == other.cols()); + internal::call_assignment_no_alias(derived(), other.derived()); + + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator=( + const DenseBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator=(const DenseBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& MatrixBase::operator=(const MatrixBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& MatrixBase::operator=( + const DenseBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& MatrixBase::operator=( + const EigenBase& other) { + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& MatrixBase::operator=( + const ReturnByValue& other) { + other.derived().evalTo(derived()); + return derived(); +} + +} // end namespace Eigen + +#endif // EIGEN_ASSIGN_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/AssignEvaluator.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/AssignEvaluator.h new file mode 100644 index 0000000..3afdd3e --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/AssignEvaluator.h @@ -0,0 +1,1066 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Benoit Jacob +// Copyright (C) 2011-2014 Gael Guennebaud +// Copyright (C) 2011-2012 Jitse Niesen +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ASSIGN_EVALUATOR_H +#define EIGEN_ASSIGN_EVALUATOR_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +// This implementation is based on Assign.h + +namespace internal { + +/*************************************************************************** + * Part 1 : the logic deciding a strategy for traversal and unrolling * + ***************************************************************************/ + +// copy_using_evaluator_traits is based on assign_traits + +template +struct copy_using_evaluator_traits { + using Src = typename SrcEvaluator::XprType; + using Dst = typename DstEvaluator::XprType; + using DstScalar = typename Dst::Scalar; + + static constexpr int DstFlags = DstEvaluator::Flags; + static constexpr int SrcFlags = SrcEvaluator::Flags; + + public: + static constexpr int DstAlignment = DstEvaluator::Alignment; + static constexpr int SrcAlignment = SrcEvaluator::Alignment; + static constexpr int JointAlignment = plain_enum_min(DstAlignment, SrcAlignment); + static constexpr bool DstHasDirectAccess = bool(DstFlags & DirectAccessBit); + static constexpr bool SrcIsRowMajor = bool(SrcFlags & RowMajorBit); + static constexpr bool DstIsRowMajor = bool(DstFlags & RowMajorBit); + static constexpr bool IsVectorAtCompileTime = Dst::IsVectorAtCompileTime; + static constexpr int RowsAtCompileTime = size_prefer_fixed(Src::RowsAtCompileTime, Dst::RowsAtCompileTime); + static constexpr int ColsAtCompileTime = size_prefer_fixed(Src::ColsAtCompileTime, Dst::ColsAtCompileTime); + static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime); + static constexpr int MaxRowsAtCompileTime = + min_size_prefer_fixed(Src::MaxRowsAtCompileTime, Dst::MaxRowsAtCompileTime); + static constexpr int MaxColsAtCompileTime = + min_size_prefer_fixed(Src::MaxColsAtCompileTime, Dst::MaxColsAtCompileTime); + static constexpr int MaxSizeAtCompileTime = + min_size_prefer_fixed(Src::MaxSizeAtCompileTime, Dst::MaxSizeAtCompileTime); + static constexpr int InnerSizeAtCompileTime = IsVectorAtCompileTime ? SizeAtCompileTime + : DstIsRowMajor ? ColsAtCompileTime + : RowsAtCompileTime; + static constexpr int MaxInnerSizeAtCompileTime = IsVectorAtCompileTime ? MaxSizeAtCompileTime + : DstIsRowMajor ? MaxColsAtCompileTime + : MaxRowsAtCompileTime; + static constexpr int RestrictedInnerSize = min_size_prefer_fixed(MaxInnerSizeAtCompileTime, MaxPacketSize); + static constexpr int RestrictedLinearSize = min_size_prefer_fixed(MaxSizeAtCompileTime, MaxPacketSize); + static constexpr int OuterStride = outer_stride_at_compile_time::ret; + + // TODO: distinguish between linear traversal and inner-traversal packet types. + using LinearPacketType = typename find_best_packet::type; + using InnerPacketType = typename find_best_packet::type; + + static constexpr int LinearPacketSize = unpacket_traits::size; + static constexpr int InnerPacketSize = unpacket_traits::size; + + public: + static constexpr int LinearRequiredAlignment = unpacket_traits::alignment; + static constexpr int InnerRequiredAlignment = unpacket_traits::alignment; + + private: + static constexpr bool StorageOrdersAgree = DstIsRowMajor == SrcIsRowMajor; + static constexpr bool MightVectorize = StorageOrdersAgree && bool(DstFlags & SrcFlags & ActualPacketAccessBit) && + bool(functor_traits::PacketAccess); + static constexpr bool MayInnerVectorize = MightVectorize && (InnerSizeAtCompileTime != Dynamic) && + (InnerSizeAtCompileTime % InnerPacketSize == 0) && + (OuterStride != Dynamic) && (OuterStride % InnerPacketSize == 0) && + (EIGEN_UNALIGNED_VECTORIZE || JointAlignment >= InnerRequiredAlignment); + static constexpr bool MayLinearize = StorageOrdersAgree && (DstFlags & SrcFlags & LinearAccessBit); + static constexpr bool MayLinearVectorize = + MightVectorize && MayLinearize && DstHasDirectAccess && + (EIGEN_UNALIGNED_VECTORIZE || (DstAlignment >= LinearRequiredAlignment) || MaxSizeAtCompileTime == Dynamic) && + (MaxSizeAtCompileTime == Dynamic || MaxSizeAtCompileTime >= LinearPacketSize); + /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, + so it's only good for large enough sizes. */ + static constexpr int InnerSizeThreshold = (EIGEN_UNALIGNED_VECTORIZE ? 1 : 3) * InnerPacketSize; + static constexpr bool MaySliceVectorize = + MightVectorize && DstHasDirectAccess && + (MaxInnerSizeAtCompileTime == Dynamic || MaxInnerSizeAtCompileTime >= InnerSizeThreshold); + /* slice vectorization can be slow, so we only want it if the slices are big, which is + indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block + in a fixed-size matrix + However, with EIGEN_UNALIGNED_VECTORIZE and unrolling, slice vectorization is still worth it */ + + public: + static constexpr int Traversal = SizeAtCompileTime == 0 ? AllAtOnceTraversal + : (MayLinearVectorize && (LinearPacketSize > InnerPacketSize)) + ? LinearVectorizedTraversal + : MayInnerVectorize ? InnerVectorizedTraversal + : MayLinearVectorize ? LinearVectorizedTraversal + : MaySliceVectorize ? SliceVectorizedTraversal + : MayLinearize ? LinearTraversal + : DefaultTraversal; + static constexpr bool Vectorized = Traversal == InnerVectorizedTraversal || Traversal == LinearVectorizedTraversal || + Traversal == SliceVectorizedTraversal; + + using PacketType = std::conditional_t; + + private: + static constexpr int ActualPacketSize = Vectorized ? unpacket_traits::size : 1; + static constexpr int UnrollingLimit = EIGEN_UNROLLING_LIMIT * ActualPacketSize; + static constexpr int CoeffReadCost = int(DstEvaluator::CoeffReadCost) + int(SrcEvaluator::CoeffReadCost); + static constexpr bool MayUnrollCompletely = + (SizeAtCompileTime != Dynamic) && (SizeAtCompileTime * CoeffReadCost <= UnrollingLimit); + static constexpr bool MayUnrollInner = + (InnerSizeAtCompileTime != Dynamic) && (InnerSizeAtCompileTime * CoeffReadCost <= UnrollingLimit); + + public: + static constexpr int Unrolling = + (Traversal == InnerVectorizedTraversal || Traversal == DefaultTraversal) + ? (MayUnrollCompletely ? CompleteUnrolling + : MayUnrollInner ? InnerUnrolling + : NoUnrolling) + : Traversal == LinearVectorizedTraversal + ? (MayUnrollCompletely && (EIGEN_UNALIGNED_VECTORIZE || (DstAlignment >= LinearRequiredAlignment)) + ? CompleteUnrolling + : NoUnrolling) + : Traversal == LinearTraversal ? (MayUnrollCompletely ? CompleteUnrolling : NoUnrolling) +#if EIGEN_UNALIGNED_VECTORIZE + : Traversal == SliceVectorizedTraversal ? (MayUnrollInner ? InnerUnrolling : NoUnrolling) +#endif + : NoUnrolling; + static constexpr bool UsePacketSegment = has_packet_segment::value; + +#ifdef EIGEN_DEBUG_ASSIGN + static void debug() { + std::cerr << "DstXpr: " << typeid(typename DstEvaluator::XprType).name() << std::endl; + std::cerr << "SrcXpr: " << typeid(typename SrcEvaluator::XprType).name() << std::endl; + std::cerr.setf(std::ios::hex, std::ios::basefield); + std::cerr << "DstFlags" + << " = " << DstFlags << " (" << demangle_flags(DstFlags) << " )" << std::endl; + std::cerr << "SrcFlags" + << " = " << SrcFlags << " (" << demangle_flags(SrcFlags) << " )" << std::endl; + std::cerr.unsetf(std::ios::hex); + EIGEN_DEBUG_VAR(DstAlignment) + EIGEN_DEBUG_VAR(SrcAlignment) + EIGEN_DEBUG_VAR(LinearRequiredAlignment) + EIGEN_DEBUG_VAR(InnerRequiredAlignment) + EIGEN_DEBUG_VAR(JointAlignment) + EIGEN_DEBUG_VAR(InnerSizeAtCompileTime) + EIGEN_DEBUG_VAR(MaxInnerSizeAtCompileTime) + EIGEN_DEBUG_VAR(LinearPacketSize) + EIGEN_DEBUG_VAR(InnerPacketSize) + EIGEN_DEBUG_VAR(ActualPacketSize) + EIGEN_DEBUG_VAR(StorageOrdersAgree) + EIGEN_DEBUG_VAR(MightVectorize) + EIGEN_DEBUG_VAR(MayLinearize) + EIGEN_DEBUG_VAR(MayInnerVectorize) + EIGEN_DEBUG_VAR(MayLinearVectorize) + EIGEN_DEBUG_VAR(MaySliceVectorize) + std::cerr << "Traversal" + << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl; + EIGEN_DEBUG_VAR(SrcEvaluator::CoeffReadCost) + EIGEN_DEBUG_VAR(DstEvaluator::CoeffReadCost) + EIGEN_DEBUG_VAR(Dst::SizeAtCompileTime) + EIGEN_DEBUG_VAR(UnrollingLimit) + EIGEN_DEBUG_VAR(MayUnrollCompletely) + EIGEN_DEBUG_VAR(MayUnrollInner) + std::cerr << "Unrolling" + << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl; + std::cerr << std::endl; + } +#endif +}; + +/*************************************************************************** + * Part 2 : meta-unrollers + ***************************************************************************/ + +/************************ +*** Default traversal *** +************************/ + +template +struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling { + static constexpr int Outer = Index_ / Kernel::AssignmentTraits::InnerSizeAtCompileTime; + static constexpr int Inner = Index_ % Kernel::AssignmentTraits::InnerSizeAtCompileTime; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + kernel.assignCoeffByOuterInner(Outer, Inner); + copy_using_evaluator_DefaultTraversal_CompleteUnrolling::run(kernel); + } +}; + +template +struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +template +struct copy_using_evaluator_DefaultTraversal_InnerUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Index outer) { + kernel.assignCoeffByOuterInner(outer, Index_); + copy_using_evaluator_DefaultTraversal_InnerUnrolling::run(kernel, outer); + } +}; + +template +struct copy_using_evaluator_DefaultTraversal_InnerUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&, Index) {} +}; + +/*********************** +*** Linear traversal *** +***********************/ + +template +struct copy_using_evaluator_LinearTraversal_CompleteUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + kernel.assignCoeff(Index_); + copy_using_evaluator_LinearTraversal_CompleteUnrolling::run(kernel); + } +}; + +template +struct copy_using_evaluator_LinearTraversal_CompleteUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +/************************** +*** Inner vectorization *** +**************************/ + +template +struct copy_using_evaluator_innervec_CompleteUnrolling { + using PacketType = typename Kernel::PacketType; + static constexpr int Outer = Index_ / Kernel::AssignmentTraits::InnerSizeAtCompileTime; + static constexpr int Inner = Index_ % Kernel::AssignmentTraits::InnerSizeAtCompileTime; + static constexpr int NextIndex = Index_ + unpacket_traits::size; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::SrcAlignment; + static constexpr int DstAlignment = Kernel::AssignmentTraits::DstAlignment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { + kernel.template assignPacketByOuterInner(Outer, Inner); + copy_using_evaluator_innervec_CompleteUnrolling::run(kernel); + } +}; + +template +struct copy_using_evaluator_innervec_CompleteUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +template +struct copy_using_evaluator_innervec_InnerUnrolling { + using PacketType = typename Kernel::PacketType; + static constexpr int NextIndex = Index_ + unpacket_traits::size; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel, Index outer) { + kernel.template assignPacketByOuterInner(outer, Index_); + copy_using_evaluator_innervec_InnerUnrolling::run(kernel, + outer); + } +}; + +template +struct copy_using_evaluator_innervec_InnerUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&, Index) {} +}; + +template +struct copy_using_evaluator_innervec_segment { + using PacketType = typename Kernel::PacketType; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel, Index outer) { + kernel.template assignPacketSegmentByOuterInner(outer, Start, 0, + Stop - Start); + } +}; + +template +struct copy_using_evaluator_innervec_segment + : copy_using_evaluator_DefaultTraversal_InnerUnrolling {}; + +template +struct copy_using_evaluator_innervec_segment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&, Index) {} +}; + +template +struct copy_using_evaluator_innervec_segment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&, Index) {} +}; + +/*************************************************************************** + * Part 3 : implementation of all cases + ***************************************************************************/ + +// dense_assignment_loop is based on assign_impl + +template +struct dense_assignment_loop_impl; + +template +struct dense_assignment_loop { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { +#ifdef __cpp_lib_is_constant_evaluated + if (internal::is_constant_evaluated()) + dense_assignment_loop_impl::run(kernel); + else +#endif + dense_assignment_loop_impl::run(kernel); + } +}; + +/************************ +***** Special Cases ***** +************************/ + +// Zero-sized assignment is a no-op. +template +struct dense_assignment_loop_impl { + static constexpr int SizeAtCompileTime = Kernel::AssignmentTraits::SizeAtCompileTime; + + EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE constexpr run(Kernel& /*kernel*/) { + EIGEN_STATIC_ASSERT(SizeAtCompileTime == 0, EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT) + } +}; + +/************************ +*** Default traversal *** +************************/ + +template +struct dense_assignment_loop_impl { + EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE constexpr run(Kernel& kernel) { + for (Index outer = 0; outer < kernel.outerSize(); ++outer) { + for (Index inner = 0; inner < kernel.innerSize(); ++inner) { + kernel.assignCoeffByOuterInner(outer, inner); + } + } + } +}; + +template +struct dense_assignment_loop_impl { + static constexpr int SizeAtCompileTime = Kernel::AssignmentTraits::SizeAtCompileTime; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + copy_using_evaluator_DefaultTraversal_CompleteUnrolling::run(kernel); + } +}; + +template +struct dense_assignment_loop_impl { + static constexpr int InnerSizeAtCompileTime = Kernel::AssignmentTraits::InnerSizeAtCompileTime; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + const Index outerSize = kernel.outerSize(); + for (Index outer = 0; outer < outerSize; ++outer) + copy_using_evaluator_DefaultTraversal_InnerUnrolling::run(kernel, outer); + } +}; + +/*************************** +*** Linear vectorization *** +***************************/ + +// The goal of unaligned_dense_assignment_loop is simply to factorize the handling +// of the non vectorizable beginning and ending parts + +template +struct unaligned_dense_assignment_loop { + // if Skip == true, then do nothing + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& /*kernel*/, Index /*start*/, Index /*end*/) {} + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& /*kernel*/, Index /*outer*/, + Index /*innerStart*/, Index /*innerEnd*/) {} +}; + +template +struct unaligned_dense_assignment_loop { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Index start, Index end) { + Index count = end - start; + eigen_assert(count <= unpacket_traits::size); + if (count > 0) kernel.template assignPacketSegment(start, 0, count); + } + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Index outer, Index start, Index end) { + Index count = end - start; + eigen_assert(count <= unpacket_traits::size); + if (count > 0) + kernel.template assignPacketSegmentByOuterInner(outer, start, 0, count); + } +}; + +template +struct unaligned_dense_assignment_loop { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Index start, Index end) { + for (Index index = start; index < end; ++index) kernel.assignCoeff(index); + } + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel, Index outer, Index innerStart, + Index innerEnd) { + for (Index inner = innerStart; inner < innerEnd; ++inner) kernel.assignCoeffByOuterInner(outer, inner); + } +}; + +template +struct copy_using_evaluator_linearvec_CompleteUnrolling { + using PacketType = typename Kernel::PacketType; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::SrcAlignment; + static constexpr int DstAlignment = Kernel::AssignmentTraits::DstAlignment; + static constexpr int NextIndex = Index_ + unpacket_traits::size; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { + kernel.template assignPacket(Index_); + copy_using_evaluator_linearvec_CompleteUnrolling::run(kernel); + } +}; + +template +struct copy_using_evaluator_linearvec_CompleteUnrolling { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +template +struct copy_using_evaluator_linearvec_segment { + using PacketType = typename Kernel::PacketType; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::SrcAlignment; + static constexpr int DstAlignment = Kernel::AssignmentTraits::DstAlignment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { + kernel.template assignPacketSegment(Index_, 0, Stop - Index_); + } +}; + +template +struct copy_using_evaluator_linearvec_segment + : copy_using_evaluator_LinearTraversal_CompleteUnrolling {}; + +template +struct copy_using_evaluator_linearvec_segment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +template +struct copy_using_evaluator_linearvec_segment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel&) {} +}; + +template +struct dense_assignment_loop_impl { + using Scalar = typename Kernel::Scalar; + using PacketType = typename Kernel::PacketType; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::JointAlignment; + static constexpr int DstAlignment = plain_enum_max(Kernel::AssignmentTraits::DstAlignment, alignof(Scalar)); + static constexpr int RequestedAlignment = unpacket_traits::alignment; + static constexpr bool Alignable = + (DstAlignment >= RequestedAlignment) || ((RequestedAlignment - DstAlignment) % sizeof(Scalar) == 0); + static constexpr int Alignment = Alignable ? RequestedAlignment : DstAlignment; + static constexpr bool DstIsAligned = DstAlignment >= Alignment; + static constexpr bool UsePacketSegment = Kernel::AssignmentTraits::UsePacketSegment; + + using head_loop = + unaligned_dense_assignment_loop; + using tail_loop = unaligned_dense_assignment_loop; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + const Index size = kernel.size(); + const Index alignedStart = DstIsAligned ? 0 : first_aligned(kernel.dstDataPtr(), size); + const Index alignedEnd = alignedStart + numext::round_down(size - alignedStart, PacketSize); + + head_loop::run(kernel, 0, alignedStart); + + for (Index index = alignedStart; index < alignedEnd; index += PacketSize) + kernel.template assignPacket(index); + + tail_loop::run(kernel, alignedEnd, size); + } +}; + +template +struct dense_assignment_loop_impl { + using PacketType = typename Kernel::PacketType; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int Size = Kernel::AssignmentTraits::SizeAtCompileTime; + static constexpr int AlignedSize = numext::round_down(Size, PacketSize); + static constexpr bool UsePacketSegment = Kernel::AssignmentTraits::UsePacketSegment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + copy_using_evaluator_linearvec_CompleteUnrolling::run(kernel); + copy_using_evaluator_linearvec_segment::run(kernel); + } +}; + +/************************** +*** Inner vectorization *** +**************************/ + +template +struct dense_assignment_loop_impl { + using PacketType = typename Kernel::PacketType; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::JointAlignment; + static constexpr int DstAlignment = Kernel::AssignmentTraits::DstAlignment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + const Index innerSize = kernel.innerSize(); + const Index outerSize = kernel.outerSize(); + for (Index outer = 0; outer < outerSize; ++outer) + for (Index inner = 0; inner < innerSize; inner += PacketSize) + kernel.template assignPacketByOuterInner(outer, inner); + } +}; + +template +struct dense_assignment_loop_impl { + static constexpr int SizeAtCompileTime = Kernel::AssignmentTraits::SizeAtCompileTime; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { + copy_using_evaluator_innervec_CompleteUnrolling::run(kernel); + } +}; + +template +struct dense_assignment_loop_impl { + static constexpr int InnerSize = Kernel::AssignmentTraits::InnerSizeAtCompileTime; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::SrcAlignment; + static constexpr int DstAlignment = Kernel::AssignmentTraits::DstAlignment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) { + const Index outerSize = kernel.outerSize(); + for (Index outer = 0; outer < outerSize; ++outer) + copy_using_evaluator_innervec_InnerUnrolling::run(kernel, + outer); + } +}; + +/*********************** +*** Linear traversal *** +***********************/ + +template +struct dense_assignment_loop_impl { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + const Index size = kernel.size(); + for (Index i = 0; i < size; ++i) kernel.assignCoeff(i); + } +}; + +template +struct dense_assignment_loop_impl { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + copy_using_evaluator_LinearTraversal_CompleteUnrolling::run( + kernel); + } +}; + +/************************** +*** Slice vectorization *** +***************************/ + +template +struct dense_assignment_loop_impl { + using Scalar = typename Kernel::Scalar; + using PacketType = typename Kernel::PacketType; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int SrcAlignment = Kernel::AssignmentTraits::JointAlignment; + static constexpr int DstAlignment = plain_enum_max(Kernel::AssignmentTraits::DstAlignment, alignof(Scalar)); + static constexpr int RequestedAlignment = unpacket_traits::alignment; + static constexpr bool Alignable = + (DstAlignment >= RequestedAlignment) || ((RequestedAlignment - DstAlignment) % sizeof(Scalar) == 0); + static constexpr int Alignment = Alignable ? RequestedAlignment : DstAlignment; + static constexpr bool DstIsAligned = DstAlignment >= Alignment; + static constexpr bool UsePacketSegment = Kernel::AssignmentTraits::UsePacketSegment; + + using head_loop = unaligned_dense_assignment_loop; + using tail_loop = unaligned_dense_assignment_loop; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + const Scalar* dst_ptr = kernel.dstDataPtr(); + const Index innerSize = kernel.innerSize(); + const Index outerSize = kernel.outerSize(); + const Index alignedStep = Alignable ? (PacketSize - kernel.outerStride() % PacketSize) % PacketSize : 0; + Index alignedStart = ((!Alignable) || DstIsAligned) ? 0 : internal::first_aligned(dst_ptr, innerSize); + + for (Index outer = 0; outer < outerSize; ++outer) { + const Index alignedEnd = alignedStart + numext::round_down(innerSize - alignedStart, PacketSize); + + head_loop::run(kernel, outer, 0, alignedStart); + + // do the vectorizable part of the assignment + for (Index inner = alignedStart; inner < alignedEnd; inner += PacketSize) + kernel.template assignPacketByOuterInner(outer, inner); + + tail_loop::run(kernel, outer, alignedEnd, innerSize); + + alignedStart = numext::mini((alignedStart + alignedStep) % PacketSize, innerSize); + } + } +}; + +#if EIGEN_UNALIGNED_VECTORIZE +template +struct dense_assignment_loop_impl { + using PacketType = typename Kernel::PacketType; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int InnerSize = Kernel::AssignmentTraits::InnerSizeAtCompileTime; + static constexpr int VectorizableSize = numext::round_down(InnerSize, PacketSize); + static constexpr bool UsePacketSegment = Kernel::AssignmentTraits::UsePacketSegment; + + using packet_loop = copy_using_evaluator_innervec_InnerUnrolling; + using packet_segment_loop = copy_using_evaluator_innervec_segment; + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(Kernel& kernel) { + for (Index outer = 0; outer < kernel.outerSize(); ++outer) { + packet_loop::run(kernel, outer); + packet_segment_loop::run(kernel, outer); + } + } +}; +#endif + +/*************************************************************************** + * Part 4 : Generic dense assignment kernel + ***************************************************************************/ + +// This class generalize the assignment of a coefficient (or packet) from one dense evaluator +// to another dense writable evaluator. +// It is parametrized by the two evaluators, and the actual assignment functor. +// This abstraction level permits to keep the evaluation loops as simple and as generic as possible. +// One can customize the assignment using this generic dense_assignment_kernel with different +// functors, or by completely overloading it, by-passing a functor. +template +class generic_dense_assignment_kernel { + protected: + typedef typename DstEvaluatorTypeT::XprType DstXprType; + typedef typename SrcEvaluatorTypeT::XprType SrcXprType; + + public: + typedef DstEvaluatorTypeT DstEvaluatorType; + typedef SrcEvaluatorTypeT SrcEvaluatorType; + typedef typename DstEvaluatorType::Scalar Scalar; + typedef copy_using_evaluator_traits AssignmentTraits; + typedef typename AssignmentTraits::PacketType PacketType; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr generic_dense_assignment_kernel(DstEvaluatorType& dst, + const SrcEvaluatorType& src, + const Functor& func, + DstXprType& dstExpr) + : m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr) { +#ifdef EIGEN_DEBUG_ASSIGN + AssignmentTraits::debug(); +#endif + } + + EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return m_dstExpr.size(); } + EIGEN_DEVICE_FUNC constexpr Index innerSize() const noexcept { return m_dstExpr.innerSize(); } + EIGEN_DEVICE_FUNC constexpr Index outerSize() const noexcept { return m_dstExpr.outerSize(); } + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_dstExpr.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_dstExpr.cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_dstExpr.outerStride(); } + + EIGEN_DEVICE_FUNC constexpr DstEvaluatorType& dstEvaluator() noexcept { return m_dst; } + EIGEN_DEVICE_FUNC constexpr const SrcEvaluatorType& srcEvaluator() const noexcept { return m_src; } + + /// Assign src(row,col) to dst(row,col) through the assignment functor. + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeff(Index row, Index col) { + m_functor.assignCoeff(m_dst.coeffRef(row, col), m_src.coeff(row, col)); + } + + /// \sa assignCoeff(Index,Index) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeff(Index index) { + m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index)); + } + + /// \sa assignCoeff(Index,Index) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void assignCoeffByOuterInner(Index outer, Index inner) { + Index row = rowIndexByOuterInner(outer, inner); + Index col = colIndexByOuterInner(outer, inner); + assignCoeff(row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index row, Index col) { + m_functor.template assignPacket(&m_dst.coeffRef(row, col), + m_src.template packet(row, col)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index index) { + m_functor.template assignPacket(&m_dst.coeffRef(index), m_src.template packet(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner) { + Index row = rowIndexByOuterInner(outer, inner); + Index col = colIndexByOuterInner(outer, inner); + assignPacket(row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketSegment(Index row, Index col, Index begin, Index count) { + m_functor.template assignPacketSegment( + &m_dst.coeffRef(row, col), m_src.template packetSegment(row, col, begin, count), begin, + count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketSegment(Index index, Index begin, Index count) { + m_functor.template assignPacketSegment( + &m_dst.coeffRef(index), m_src.template packetSegment(index, begin, count), begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketSegmentByOuterInner(Index outer, Index inner, Index begin, + Index count) { + Index row = rowIndexByOuterInner(outer, inner); + Index col = colIndexByOuterInner(outer, inner); + assignPacketSegment(row, col, begin, count); + } + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr Index rowIndexByOuterInner(Index outer, Index inner) { + typedef typename DstEvaluatorType::ExpressionTraits Traits; + return int(Traits::RowsAtCompileTime) == 1 ? 0 + : int(Traits::ColsAtCompileTime) == 1 ? inner + : int(DstEvaluatorType::Flags) & RowMajorBit ? outer + : inner; + } + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr Index colIndexByOuterInner(Index outer, Index inner) { + typedef typename DstEvaluatorType::ExpressionTraits Traits; + return int(Traits::ColsAtCompileTime) == 1 ? 0 + : int(Traits::RowsAtCompileTime) == 1 ? inner + : int(DstEvaluatorType::Flags) & RowMajorBit ? inner + : outer; + } + + EIGEN_DEVICE_FUNC const Scalar* dstDataPtr() const { return m_dstExpr.data(); } + + protected: + DstEvaluatorType& m_dst; + const SrcEvaluatorType& m_src; + const Functor& m_functor; + // TODO: find a way to avoid the needs of the original expression + DstXprType& m_dstExpr; +}; + +// Special kernel used when computing small products whose operands have dynamic dimensions. It ensures that the +// PacketSize used is no larger than 4, thereby increasing the chance that vectorized instructions will be used +// when computing the product. + +template +class restricted_packet_dense_assignment_kernel + : public generic_dense_assignment_kernel { + protected: + typedef generic_dense_assignment_kernel Base; + + public: + typedef typename Base::Scalar Scalar; + typedef typename Base::DstXprType DstXprType; + typedef copy_using_evaluator_traits AssignmentTraits; + typedef typename AssignmentTraits::PacketType PacketType; + + EIGEN_DEVICE_FUNC restricted_packet_dense_assignment_kernel(DstEvaluatorTypeT& dst, const SrcEvaluatorTypeT& src, + const Functor& func, DstXprType& dstExpr) + : Base(dst, src, func, dstExpr) {} +}; + +/*************************************************************************** + * Part 5 : Entry point for dense rectangular assignment + ***************************************************************************/ + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize_if_allowed(DstXprType& dst, const SrcXprType& src, + const Functor& /*func*/) { + EIGEN_ONLY_USED_FOR_DEBUG(dst); + EIGEN_ONLY_USED_FOR_DEBUG(src); + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize_if_allowed(DstXprType& dst, const SrcXprType& src, + const internal::assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if (((dst.rows() != dstRows) || (dst.cols() != dstCols))) { +#ifdef EIGEN_NO_AUTOMATIC_RESIZING + eigen_assert( + (dst.size() == 0 || (DstXprType::IsVectorAtCompileTime ? (dst.size() == src.size()) + : (dst.rows() == dstRows && dst.cols() == dstCols))) && + "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined"); +#else + dst.resize(dstRows, dstCols); + eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols); +#endif + } +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, + const Functor& func) { + typedef evaluator DstEvaluatorType; + typedef evaluator SrcEvaluatorType; + + SrcEvaluatorType srcEvaluator(src); + + // NOTE To properly handle A = (A*A.transpose())/s with A rectangular, + // we need to resize the destination after the source evaluator has been created. + resize_if_allowed(dst, src, func); + + DstEvaluatorType dstEvaluator(dst); + + typedef generic_dense_assignment_kernel Kernel; + Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); + + dense_assignment_loop::run(kernel); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src) { + call_dense_assignment_loop(dst, src, internal::assign_op()); +} + +/*************************************************************************** + * Part 6 : Generic assignment + ***************************************************************************/ + +// Based on the respective shapes of the destination and source, +// the class AssignmentKind determine the kind of assignment mechanism. +// AssignmentKind must define a Kind typedef. +template +struct AssignmentKind; + +// Assignment kind defined in this file: +struct Dense2Dense {}; +struct EigenBase2EigenBase {}; + +template +struct AssignmentKind { + typedef EigenBase2EigenBase Kind; +}; +template <> +struct AssignmentKind { + typedef Dense2Dense Kind; +}; + +// This is the main assignment class +template ::Shape, + typename evaluator_traits::Shape>::Kind, + typename EnableIf = void> +struct Assignment; + +// The only purpose of this call_assignment() function is to deal with noalias() / "assume-aliasing" and automatic +// transposition. Indeed, I (Gael) think that this concept of "assume-aliasing" was a mistake, and it makes thing quite +// complicated. So this intermediate function removes everything related to "assume-aliasing" such that Assignment does +// not has to bother about these annoying details. + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment(Dst& dst, const Src& src) { + call_assignment(dst, src, internal::assign_op()); +} +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_assignment(const Dst& dst, const Src& src) { + call_assignment(dst, src, internal::assign_op()); +} + +// Deal with "assume-aliasing" +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment( + Dst& dst, const Src& src, const Func& func, std::enable_if_t::value, void*> = 0) { + typename plain_matrix_type::type tmp(src); + call_assignment_no_alias(dst, tmp, func); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment( + Dst& dst, const Src& src, const Func& func, std::enable_if_t::value, void*> = 0) { + call_assignment_no_alias(dst, src, func); +} + +// by-pass "assume-aliasing" +// When there is no aliasing, we require that 'dst' has been properly resized +template class StorageBase, typename Src, typename Func> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment(NoAlias& dst, const Src& src, + const Func& func) { + call_assignment_no_alias(dst.expression(), src, func); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias(Dst& dst, const Src& src, + const Func& func) { + enum { + NeedToTranspose = ((int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1) || + (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)) && + int(Dst::SizeAtCompileTime) != 1 + }; + + typedef std::conditional_t, Dst> ActualDstTypeCleaned; + typedef std::conditional_t, Dst&> ActualDstType; + ActualDstType actualDst(dst); + + // TODO: check whether this is the right place to perform these checks: + EIGEN_STATIC_ASSERT_LVALUE(Dst) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned, Src) + EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename ActualDstTypeCleaned::Scalar, typename Src::Scalar); + + Assignment::run(actualDst, src, func); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_restricted_packet_assignment_no_alias(Dst& dst, const Src& src, + const Func& func) { + typedef evaluator DstEvaluatorType; + typedef evaluator SrcEvaluatorType; + typedef restricted_packet_dense_assignment_kernel Kernel; + + EIGEN_STATIC_ASSERT_LVALUE(Dst) + EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename Dst::Scalar, typename Src::Scalar); + + SrcEvaluatorType srcEvaluator(src); + resize_if_allowed(dst, src, func); + + DstEvaluatorType dstEvaluator(dst); + Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); + + dense_assignment_loop::run(kernel); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias(Dst& dst, const Src& src) { + call_assignment_no_alias(dst, src, internal::assign_op()); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, + const Func& func) { + // TODO: check whether this is the right place to perform these checks: + EIGEN_STATIC_ASSERT_LVALUE(Dst) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Dst, Src) + EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename Dst::Scalar, typename Src::Scalar); + + Assignment::run(dst, src, func); +} +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src) { + call_assignment_no_alias_no_transpose(dst, src, internal::assign_op()); +} + +// forward declaration +template +EIGEN_DEVICE_FUNC void check_for_aliasing(const Dst& dst, const Src& src); + +// Generic Dense to Dense assignment +// Note that the last template argument "Weak" is needed to make it possible to perform +// both partial specialization+SFINAE without ambiguous specialization +template +struct Assignment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE constexpr void run(DstXprType& dst, const SrcXprType& src, + const Functor& func) { +#ifndef EIGEN_NO_DEBUG + if (!internal::is_constant_evaluated()) { + internal::check_for_aliasing(dst, src); + } +#endif + + call_dense_assignment_loop(dst, src, func); + } +}; + +template +struct Assignment, SrcPlainObject>, + assign_op, Dense2Dense, Weak> { + using Scalar = typename DstXprType::Scalar; + using NullaryOp = scalar_constant_op; + using SrcXprType = CwiseNullaryOp; + using Functor = assign_op; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const Functor& /*func*/) { + eigen_fill_impl::run(dst, src); + } +}; + +template +struct Assignment, SrcPlainObject>, + assign_op, Dense2Dense, Weak> { + using Scalar = typename DstXprType::Scalar; + using NullaryOp = scalar_zero_op; + using SrcXprType = CwiseNullaryOp; + using Functor = assign_op; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const Functor& /*func*/) { + eigen_zero_impl::run(dst, src); + } +}; + +// Generic assignment through evalTo. +// TODO: evaluate whether this generic evalTo-based assignment path is still needed. +// Note that the last template argument "Weak" is needed to make it possible to perform +// both partial specialization+SFINAE without ambiguous specialization +template +struct Assignment { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run( + DstXprType& dst, const SrcXprType& src, + const internal::assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + src.evalTo(dst); + } + + // NOTE The following two functions are templated to avoid their instantiation if not needed + // This is needed because some expressions supports evalTo only and/or have 'void' as scalar type. + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run( + DstXprType& dst, const SrcXprType& src, + const internal::add_assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + src.addTo(dst); + } + + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run( + DstXprType& dst, const SrcXprType& src, + const internal::sub_assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + src.subTo(dst); + } +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_ASSIGN_EVALUATOR_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_AOCL.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_AOCL.h new file mode 100644 index 0000000..da3ef7c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_AOCL.h @@ -0,0 +1,301 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * Assign_AOCL.h - AOCL Vectorized Math Dispatch Layer for Eigen + * + * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved. + * + * Description: + * ------------ + * This file implements a high-performance dispatch layer that automatically + * routes Eigen's element-wise mathematical operations to AMD Optimizing CPU + * Libraries (AOCL) Vector Math Library (VML) functions when beneficial for + * performance. + * + * The dispatch system uses C++ template specialization to intercept Eigen's + * assignment operations and redirect them to AOCL's VRDA functions, which + * provide optimized implementations for AMD Zen architectures. + * + * Key Features: + * ------------- + * 1. Automatic Dispatch: Seamlessly routes supported operations to AOCL without + * requiring code changes in user applications + * + * 2. Performance Optimization: Uses AOCL VRDA functions optimized for Zen + * family processors with automatic SIMD instruction selection (AVX2, AVX-512) + * + * 3. Threshold-Based Activation: Only activates for vectors larger than + * EIGEN_AOCL_VML_THRESHOLD (default: 128 elements) to avoid overhead on + * small vectors + * + * 4. Precision-Specific Handling: + * - Double precision: AOCL VRDA vectorized functions + * - Single precision: Scalar fallback (preserves correctness) + * + * 5. Memory Layout Compatibility: Ensures direct memory access and compatible + * storage orders between source and destination for optimal performance + * + * Supported Operations: + * --------------------- + * UNARY OPERATIONS (vector → vector): + * - Transcendental: exp(), sin(), cos(), sqrt(), log(), log10(), log2() + * + * BINARY OPERATIONS (vector op vector → vector): + * - Arithmetic: +, *, pow() + * + * Template Specialization Mechanism: + * ----------------------------------- + * The system works by specializing Eigen's Assignment template for: + * 1. CwiseUnaryOp with scalar_*_op functors (unary operations) + * 2. CwiseBinaryOp with scalar_*_op functors (binary operations) + * 3. Dense2Dense assignment context with AOCL-compatible traits + * + * Dispatch conditions (all must be true): + * - Source and destination have DirectAccessBit (contiguous memory) + * - Compatible storage orders (both row-major or both column-major) + * - Vector size ≥ EIGEN_AOCL_VML_THRESHOLD or Dynamic size + * - Supported data type (currently double precision for VRDA) + * + * Integration Example: + * -------------------- + * // Standard Eigen code - no changes required + * VectorXd x = VectorXd::Random(10000); + * VectorXd y = VectorXd::Random(10000); + * VectorXd result; + * + * // These operations are automatically dispatched to AOCL: + * result = x.array().exp(); // → amd_vrda_exp() + * result = x.array().sin(); // → amd_vrda_sin() + * result = x.array() + y.array(); // → amd_vrda_add() + * result = x.array().pow(y.array()); // → amd_vrda_pow() + * + * Configuration: + * -------------- + * Required preprocessor definitions: + * - EIGEN_USE_AOCL_ALL or EIGEN_USE_AOCL_MT: Enable AOCL integration + * - EIGEN_USE_AOCL_VML: Enable Vector Math Library dispatch + * + * Compilation Requirements: + * ------------------------- + * Include paths: + * - AOCL headers: -I${AOCL_ROOT}/include + * - Eigen headers: -I/path/to/eigen + * + * Link libraries: + * - AOCL MathLib: -lamdlibm + * - Standard math: -lm + * + * Compiler flags: + * - Optimization: -O3 (required for inlining) + * - Architecture: -march=znver5 or -march=native + * - Vectorization: -mfma -mavx512f (if supported) + * + * Platform Support: + * ------------------ + * - Primary: Linux x86_64 with AMD Zen family processors + * - Compilers: GCC 8+, Clang 10+, AOCC (recommended) + * - AOCL Version: 4.0+ (with VRDA support) + * + * Error Handling: + * --------------- + * - Graceful fallback to scalar operations for unsupported configurations + * - Compile-time detection of AOCL availability + * - Runtime size and alignment validation with eigen_assert() + * + * Developer: + * ---------- + * Name: Sharad Saurabh Bhaskar + * Email: shbhaska@amd.com + * Organization: Advanced Micro Devices, Inc. + */ + + +#ifndef EIGEN_ASSIGN_AOCL_H +#define EIGEN_ASSIGN_AOCL_H + +namespace Eigen { +namespace internal { + +// Traits for unary operations. +template class aocl_assign_traits { +private: + enum { + DstHasDirectAccess = !!(Dst::Flags & DirectAccessBit), + SrcHasDirectAccess = !!(Src::Flags & DirectAccessBit), + StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)), + InnerSize = Dst::IsVectorAtCompileTime ? int(Dst::SizeAtCompileTime) + : (Dst::Flags & RowMajorBit) ? int(Dst::ColsAtCompileTime) + : int(Dst::RowsAtCompileTime), + LargeEnough = + (InnerSize == Dynamic) || (InnerSize >= EIGEN_AOCL_VML_THRESHOLD) + }; + +public: + enum { + EnableAoclVML = DstHasDirectAccess && SrcHasDirectAccess && + StorageOrdersAgree && LargeEnough, + Traversal = LinearTraversal + }; +}; + +// Traits for binary operations (e.g., add, pow). +template +class aocl_assign_binary_traits { +private: + enum { + DstHasDirectAccess = !!(Dst::Flags & DirectAccessBit), + LhsHasDirectAccess = !!(Lhs::Flags & DirectAccessBit), + RhsHasDirectAccess = !!(Rhs::Flags & DirectAccessBit), + StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Lhs::IsRowMajor)) && + (int(Dst::IsRowMajor) == int(Rhs::IsRowMajor)), + InnerSize = Dst::IsVectorAtCompileTime ? int(Dst::SizeAtCompileTime) + : (Dst::Flags & RowMajorBit) ? int(Dst::ColsAtCompileTime) + : int(Dst::RowsAtCompileTime), + LargeEnough = + (InnerSize == Dynamic) || (InnerSize >= EIGEN_AOCL_VML_THRESHOLD) + }; + +public: + enum { + EnableAoclVML = DstHasDirectAccess && LhsHasDirectAccess && + RhsHasDirectAccess && StorageOrdersAgree && LargeEnough + }; +}; + +// Unary operation dispatch for float (scalar fallback). +#define EIGEN_AOCL_VML_UNARY_CALL_FLOAT(EIGENOP) \ + template \ + struct Assignment< \ + DstXprType, CwiseUnaryOp, SrcXprNested>, \ + assign_op, Dense2Dense, \ + std::enable_if_t< \ + aocl_assign_traits::EnableAoclVML>> { \ + typedef CwiseUnaryOp, SrcXprNested> \ + SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, \ + const assign_op &) { \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + Eigen::Index n = dst.size(); \ + if (n <= 0) \ + return; \ + const float *input = \ + reinterpret_cast(src.nestedExpression().data()); \ + float *output = reinterpret_cast(dst.data()); \ + for (Eigen::Index i = 0; i < n; ++i) { \ + output[i] = std::EIGENOP(input[i]); \ + } \ + } \ + }; + +// Unary operation dispatch for double (AOCL vectorized). +#define EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(EIGENOP, AOCLOP) \ + template \ + struct Assignment< \ + DstXprType, CwiseUnaryOp, SrcXprNested>, \ + assign_op, Dense2Dense, \ + std::enable_if_t< \ + aocl_assign_traits::EnableAoclVML>> { \ + typedef CwiseUnaryOp, SrcXprNested> \ + SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, \ + const assign_op &) { \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + Eigen::Index n = dst.size(); \ + eigen_assert(n <= INT_MAX && "AOCL does not support arrays larger than INT_MAX"); \ + if (n <= 0) \ + return; \ + const double *input = \ + reinterpret_cast(src.nestedExpression().data()); \ + double *output = reinterpret_cast(dst.data()); \ + int aocl_n = internal::convert_index(n); \ + AOCLOP(aocl_n, const_cast(input), output); \ + } \ + }; + +// Instantiate unary calls for float (scalar). +// EIGEN_AOCL_VML_UNARY_CALL_FLOAT(exp) + +// Instantiate unary calls for double (AOCL vectorized). +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(exp2, amd_vrda_exp2) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(exp, amd_vrda_exp) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(sin, amd_vrda_sin) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(cos, amd_vrda_cos) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(sqrt, amd_vrda_sqrt) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(cbrt, amd_vrda_cbrt) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(abs, amd_vrda_fabs) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(log, amd_vrda_log) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(log10, amd_vrda_log10) +EIGEN_AOCL_VML_UNARY_CALL_DOUBLE(log2, amd_vrda_log2) + +// Binary operation dispatch for float (scalar fallback). +#define EIGEN_AOCL_VML_BINARY_CALL_FLOAT(EIGENOP, STDFUNC) \ + template \ + struct Assignment< \ + DstXprType, \ + CwiseBinaryOp, LhsXprNested, \ + RhsXprNested>, \ + assign_op, Dense2Dense, \ + std::enable_if_t::EnableAoclVML>> { \ + typedef CwiseBinaryOp, LhsXprNested, \ + RhsXprNested> \ + SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, \ + const assign_op &) { \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + Eigen::Index n = dst.size(); \ + if (n <= 0) \ + return; \ + const float *lhs = reinterpret_cast(src.lhs().data()); \ + const float *rhs = reinterpret_cast(src.rhs().data()); \ + float *output = reinterpret_cast(dst.data()); \ + for (Eigen::Index i = 0; i < n; ++i) { \ + output[i] = STDFUNC(lhs[i], rhs[i]); \ + } \ + } \ + }; + +// Binary operation dispatch for double (AOCL vectorized). +#define EIGEN_AOCL_VML_BINARY_CALL_DOUBLE(EIGENOP, AOCLOP) \ + template \ + struct Assignment< \ + DstXprType, \ + CwiseBinaryOp, LhsXprNested, \ + RhsXprNested>, \ + assign_op, Dense2Dense, \ + std::enable_if_t::EnableAoclVML>> { \ + typedef CwiseBinaryOp, LhsXprNested, \ + RhsXprNested> \ + SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, \ + const assign_op &) { \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + Eigen::Index n = dst.size(); \ + eigen_assert(n <= INT_MAX && "AOCL does not support arrays larger than INT_MAX"); \ + if (n <= 0) \ + return; \ + const double *lhs = reinterpret_cast(src.lhs().data()); \ + const double *rhs = reinterpret_cast(src.rhs().data()); \ + double *output = reinterpret_cast(dst.data()); \ + int aocl_n = internal::convert_index(n); \ + AOCLOP(aocl_n, const_cast(lhs), const_cast(rhs), output); \ + } \ + }; + +// Instantiate binary calls for float (scalar). +// EIGEN_AOCL_VML_BINARY_CALL_FLOAT(sum, std::plus) // Using +// scalar_sum_op for addition EIGEN_AOCL_VML_BINARY_CALL_FLOAT(pow, std::pow) + +// Instantiate binary calls for double (AOCL vectorized). +EIGEN_AOCL_VML_BINARY_CALL_DOUBLE(sum, amd_vrda_add) // Using scalar_sum_op for addition +EIGEN_AOCL_VML_BINARY_CALL_DOUBLE(pow, amd_vrda_pow) +EIGEN_AOCL_VML_BINARY_CALL_DOUBLE(max, amd_vrda_fmax) +EIGEN_AOCL_VML_BINARY_CALL_DOUBLE(min, amd_vrda_fmin) + +} // namespace internal +} // namespace Eigen + +#endif // EIGEN_ASSIGN_AOCL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_MKL.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_MKL.h new file mode 100644 index 0000000..7636445 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Assign_MKL.h @@ -0,0 +1,183 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + Copyright (C) 2015 Gael Guennebaud + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * MKL VML support for coefficient-wise unary Eigen expressions like a=b.sin() + ******************************************************************************** +*/ + +#ifndef EIGEN_ASSIGN_VML_H +#define EIGEN_ASSIGN_VML_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +class vml_assign_traits { + private: + enum { + DstHasDirectAccess = Dst::Flags & DirectAccessBit, + SrcHasDirectAccess = Src::Flags & DirectAccessBit, + StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)), + InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime) + : int(Dst::Flags) & RowMajorBit ? int(Dst::ColsAtCompileTime) + : int(Dst::RowsAtCompileTime), + InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime) + : int(Dst::Flags) & RowMajorBit ? int(Dst::MaxColsAtCompileTime) + : int(Dst::MaxRowsAtCompileTime), + MaxSizeAtCompileTime = Dst::SizeAtCompileTime, + + MightEnableVml = bool(StorageOrdersAgree) && bool(DstHasDirectAccess) && bool(SrcHasDirectAccess) && + Src::InnerStrideAtCompileTime == 1 && Dst::InnerStrideAtCompileTime == 1, + MightLinearize = bool(MightEnableVml) && (int(Dst::Flags) & int(Src::Flags) & LinearAccessBit), + VmlSize = bool(MightLinearize) ? MaxSizeAtCompileTime : InnerMaxSize, + LargeEnough = (VmlSize == Dynamic) || VmlSize >= EIGEN_MKL_VML_THRESHOLD + }; + + public: + enum { EnableVml = MightEnableVml && LargeEnough, Traversal = MightLinearize ? LinearTraversal : DefaultTraversal }; +}; + +#define EIGEN_PP_EXPAND(ARG) ARG +#if !defined(EIGEN_FAST_MATH) || (EIGEN_FAST_MATH != 1) +#define EIGEN_VMLMODE_EXPAND_xLA , VML_HA +#else +#define EIGEN_VMLMODE_EXPAND_xLA , VML_LA +#endif + +#define EIGEN_VMLMODE_EXPAND_x_ + +#define EIGEN_VMLMODE_PREFIX_xLA vm +#define EIGEN_VMLMODE_PREFIX_x_ v +#define EIGEN_VMLMODE_PREFIX(VMLMODE) EIGEN_CAT(EIGEN_VMLMODE_PREFIX_x, VMLMODE) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE, VMLMODE) \ + template \ + struct Assignment, SrcXprNested>, \ + assign_op, Dense2Dense, \ + std::enable_if_t::EnableVml>> { \ + typedef CwiseUnaryOp, SrcXprNested> SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + if (vml_assign_traits::Traversal == (int)LinearTraversal) { \ + VMLOP(dst.size(), (const VMLTYPE *)src.nestedExpression().data(), \ + (VMLTYPE *)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \ + } else { \ + const Index outerSize = dst.outerSize(); \ + for (Index outer = 0; outer < outerSize; ++outer) { \ + const EIGENTYPE *src_ptr = src.IsRowMajor ? &(src.nestedExpression().coeffRef(outer, 0)) \ + : &(src.nestedExpression().coeffRef(0, outer)); \ + EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer, 0)) : &(dst.coeffRef(0, outer)); \ + VMLOP(dst.innerSize(), (const VMLTYPE *)src_ptr, \ + (VMLTYPE *)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \ + } \ + } \ + } \ + }; + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE), s##VMLOP), float, float, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE), d##VMLOP), double, double, VMLMODE) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(EIGENOP, VMLOP, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE), c##VMLOP), scomplex, \ + MKL_Complex8, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE), z##VMLOP), dcomplex, \ + MKL_Complex16, VMLMODE) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS(EIGENOP, VMLOP, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP, VMLMODE) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(EIGENOP, VMLOP, VMLMODE) + +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sin, Sin, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(asin, Asin, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sinh, Sinh, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(cos, Cos, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(acos, Acos, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(cosh, Cosh, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(tan, Tan, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(atan, Atan, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(tanh, Tanh, LA) +// EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(exp, Exp, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(log, Ln, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(log10, Log10, LA) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sqrt, Sqrt, _) + +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(arg, Arg, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(round, Round, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(floor, Floor, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(cbrt, Cbrt, _) + +#define EIGEN_MKL_VML_DECLARE_POW_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE, VMLMODE) \ + template \ + struct Assignment, SrcXprNested, \ + const CwiseNullaryOp, Plain>>, \ + assign_op, Dense2Dense, \ + std::enable_if_t::EnableVml>> { \ + typedef CwiseBinaryOp, SrcXprNested, \ + const CwiseNullaryOp, Plain>> \ + SrcXprType; \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ + VMLTYPE exponent = reinterpret_cast(src.rhs().functor().m_other); \ + if (vml_assign_traits::Traversal == LinearTraversal) { \ + VMLOP(dst.size(), (const VMLTYPE *)src.lhs().data(), exponent, \ + (VMLTYPE *)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \ + } else { \ + const Index outerSize = dst.outerSize(); \ + for (Index outer = 0; outer < outerSize; ++outer) { \ + const EIGENTYPE *src_ptr = \ + src.IsRowMajor ? &(src.lhs().coeffRef(outer, 0)) : &(src.lhs().coeffRef(0, outer)); \ + EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer, 0)) : &(dst.coeffRef(0, outer)); \ + VMLOP(dst.innerSize(), (const VMLTYPE *)src_ptr, exponent, \ + (VMLTYPE *)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \ + } \ + } \ + } \ + }; + +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmsPowx, float, float, LA) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmdPowx, double, double, LA) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmcPowx, scomplex, MKL_Complex8, LA) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmzPowx, dcomplex, MKL_Complex16, LA) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_ASSIGN_VML_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/BandMatrix.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/BandMatrix.h new file mode 100644 index 0000000..57b0322 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/BandMatrix.h @@ -0,0 +1,338 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_BANDMATRIX_H +#define EIGEN_BANDMATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +class BandMatrixBase : public EigenBase { + public: + enum { + Flags = internal::traits::Flags, + CoeffReadCost = internal::traits::CoeffReadCost, + RowsAtCompileTime = internal::traits::RowsAtCompileTime, + ColsAtCompileTime = internal::traits::ColsAtCompileTime, + MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = internal::traits::MaxColsAtCompileTime, + Supers = internal::traits::Supers, + Subs = internal::traits::Subs, + Options = internal::traits::Options + }; + typedef typename internal::traits::Scalar Scalar; + typedef Matrix DenseMatrixType; + typedef typename DenseMatrixType::StorageIndex StorageIndex; + typedef typename internal::traits::CoefficientsType CoefficientsType; + typedef EigenBase Base; + + protected: + enum { + DataRowsAtCompileTime = ((Supers != Dynamic) && (Subs != Dynamic)) ? 1 + Supers + Subs : Dynamic, + SizeAtCompileTime = min_size_prefer_dynamic(RowsAtCompileTime, ColsAtCompileTime) + }; + + public: + using Base::cols; + using Base::derived; + using Base::rows; + + /** \returns the number of super diagonals */ + inline Index supers() const { return derived().supers(); } + + /** \returns the number of sub diagonals */ + inline Index subs() const { return derived().subs(); } + + /** \returns an expression of the underlying coefficient matrix */ + inline const CoefficientsType& coeffs() const { return derived().coeffs(); } + + /** \returns an expression of the underlying coefficient matrix */ + inline CoefficientsType& coeffs() { return derived().coeffs(); } + + /** \returns a vector expression of the \a i -th column, + * only the meaningful part is returned. + * \warning the internal storage must be column major. */ + inline Block col(Index i) { + EIGEN_STATIC_ASSERT((int(Options) & int(RowMajor)) == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); + Index start = 0; + Index len = coeffs().rows(); + if (i <= supers()) { + start = supers() - i; + len = (std::min)(rows(), std::max(0, coeffs().rows() - (supers() - i))); + } else if (i >= rows() - subs()) + len = std::max(0, coeffs().rows() - (i + 1 - rows() + subs())); + return Block(coeffs(), start, i, len, 1); + } + + /** \returns a vector expression of the main diagonal */ + inline Block diagonal() { + return Block(coeffs(), supers(), 0, 1, (std::min)(rows(), cols())); + } + + /** \returns a vector expression of the main diagonal (const version) */ + inline const Block diagonal() const { + return Block(coeffs(), supers(), 0, 1, (std::min)(rows(), cols())); + } + + template + struct DiagonalIntReturnType { + enum { + ReturnOpposite = + (int(Options) & int(SelfAdjoint)) && (((Index) > 0 && Supers == 0) || ((Index) < 0 && Subs == 0)), + Conjugate = ReturnOpposite && NumTraits::IsComplex, + ActualIndex = ReturnOpposite ? -Index : Index, + DiagonalSize = + (RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic) + ? Dynamic + : (ActualIndex < 0 ? min_size_prefer_dynamic(ColsAtCompileTime, RowsAtCompileTime + ActualIndex) + : min_size_prefer_dynamic(RowsAtCompileTime, ColsAtCompileTime - ActualIndex)) + }; + typedef Block BuildType; + typedef std::conditional_t, BuildType>, BuildType> + Type; + }; + + /** \returns a vector expression of the \a N -th sub or super diagonal */ + template + inline typename DiagonalIntReturnType::Type diagonal() { + return typename DiagonalIntReturnType::BuildType(coeffs(), supers() - N, (std::max)(0, N), 1, diagonalLength(N)); + } + + /** \returns a vector expression of the \a N -th sub or super diagonal */ + template + inline const typename DiagonalIntReturnType::Type diagonal() const { + return typename DiagonalIntReturnType::BuildType(coeffs(), supers() - N, (std::max)(0, N), 1, diagonalLength(N)); + } + + /** \returns a vector expression of the \a i -th sub or super diagonal */ + inline Block diagonal(Index i) { + eigen_assert((i < 0 && -i <= subs()) || (i >= 0 && i <= supers())); + return Block(coeffs(), supers() - i, std::max(0, i), 1, diagonalLength(i)); + } + + /** \returns a vector expression of the \a i -th sub or super diagonal */ + inline const Block diagonal(Index i) const { + eigen_assert((i < 0 && -i <= subs()) || (i >= 0 && i <= supers())); + return Block(coeffs(), supers() - i, std::max(0, i), 1, + diagonalLength(i)); + } + + template + inline void evalTo(Dest& dst) const { + dst.resize(rows(), cols()); + dst.setZero(); + dst.diagonal() = diagonal(); + for (Index i = 1; i <= supers(); ++i) dst.diagonal(i) = diagonal(i); + for (Index i = 1; i <= subs(); ++i) dst.diagonal(-i) = diagonal(-i); + } + + DenseMatrixType toDenseMatrix() const { + DenseMatrixType res(rows(), cols()); + evalTo(res); + return res; + } + + protected: + inline Index diagonalLength(Index i) const { + return i < 0 ? (std::min)(cols(), rows() + i) : (std::min)(rows(), cols() - i); + } +}; + +/** + * \class BandMatrix + * \ingroup Core_Module + * + * \brief Represents a rectangular matrix with a banded storage + * + * \tparam Scalar_ Numeric type, i.e. float, double, int + * \tparam Rows_ Number of rows, or \b Dynamic + * \tparam Cols_ Number of columns, or \b Dynamic + * \tparam Supers_ Number of super diagonal + * \tparam Subs_ Number of sub diagonal + * \tparam Options_ A combination of either \b #RowMajor or \b #ColMajor, and of \b #SelfAdjoint + * The former controls \ref TopicStorageOrders "storage order", and defaults to + * column-major. The latter controls whether the matrix represents a selfadjoint + * matrix in which case either Supers of Subs have to be null. + * + * \sa class TridiagonalMatrix + */ + +template +struct traits > { + typedef Scalar_ Scalar; + typedef Dense StorageKind; + typedef Eigen::Index StorageIndex; + enum { + CoeffReadCost = NumTraits::ReadCost, + RowsAtCompileTime = Rows_, + ColsAtCompileTime = Cols_, + MaxRowsAtCompileTime = Rows_, + MaxColsAtCompileTime = Cols_, + Flags = LvalueBit, + Supers = Supers_, + Subs = Subs_, + Options = Options_, + DataRowsAtCompileTime = ((Supers != Dynamic) && (Subs != Dynamic)) ? 1 + Supers + Subs : Dynamic + }; + typedef Matrix + CoefficientsType; +}; + +template +class BandMatrix : public BandMatrixBase > { + public: + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::traits::StorageIndex StorageIndex; + typedef typename internal::traits::CoefficientsType CoefficientsType; + + explicit inline BandMatrix(Index rows = Rows, Index cols = Cols, Index supers = Supers, Index subs = Subs) + : m_coeffs(1 + supers + subs, cols), m_rows(rows), m_supers(supers), m_subs(subs) {} + + /** \returns the number of columns */ + constexpr Index rows() const { return m_rows.value(); } + + /** \returns the number of rows */ + constexpr Index cols() const { return m_coeffs.cols(); } + + /** \returns the number of super diagonals */ + constexpr Index supers() const { return m_supers.value(); } + + /** \returns the number of sub diagonals */ + constexpr Index subs() const { return m_subs.value(); } + + inline const CoefficientsType& coeffs() const { return m_coeffs; } + inline CoefficientsType& coeffs() { return m_coeffs; } + + protected: + CoefficientsType m_coeffs; + internal::variable_if_dynamic m_rows; + internal::variable_if_dynamic m_supers; + internal::variable_if_dynamic m_subs; +}; + +template +class BandMatrixWrapper; + +template +struct traits > { + typedef typename CoefficientsType_::Scalar Scalar; + typedef typename CoefficientsType_::StorageKind StorageKind; + typedef typename CoefficientsType_::StorageIndex StorageIndex; + enum { + CoeffReadCost = internal::traits::CoeffReadCost, + RowsAtCompileTime = Rows_, + ColsAtCompileTime = Cols_, + MaxRowsAtCompileTime = Rows_, + MaxColsAtCompileTime = Cols_, + Flags = LvalueBit, + Supers = Supers_, + Subs = Subs_, + Options = Options_, + DataRowsAtCompileTime = ((Supers != Dynamic) && (Subs != Dynamic)) ? 1 + Supers + Subs : Dynamic + }; + typedef CoefficientsType_ CoefficientsType; +}; + +template +class BandMatrixWrapper + : public BandMatrixBase > { + public: + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::traits::CoefficientsType CoefficientsType; + typedef typename internal::traits::StorageIndex StorageIndex; + + explicit inline BandMatrixWrapper(const CoefficientsType& coeffs, Index rows = Rows_, Index cols = Cols_, + Index supers = Supers_, Index subs = Subs_) + : m_coeffs(coeffs), m_rows(rows), m_supers(supers), m_subs(subs) { + EIGEN_UNUSED_VARIABLE(cols); + // eigen_assert(coeffs.cols()==cols() && (supers()+subs()+1)==coeffs.rows()); + } + + /** \returns the number of columns */ + constexpr Index rows() const { return m_rows.value(); } + + /** \returns the number of rows */ + constexpr Index cols() const { return m_coeffs.cols(); } + + /** \returns the number of super diagonals */ + constexpr Index supers() const { return m_supers.value(); } + + /** \returns the number of sub diagonals */ + constexpr Index subs() const { return m_subs.value(); } + + inline const CoefficientsType& coeffs() const { return m_coeffs; } + + protected: + const CoefficientsType& m_coeffs; + internal::variable_if_dynamic m_rows; + internal::variable_if_dynamic m_supers; + internal::variable_if_dynamic m_subs; +}; + +/** + * \class TridiagonalMatrix + * \ingroup Core_Module + * + * \brief Represents a tridiagonal matrix with a compact banded storage + * + * \tparam Scalar Numeric type, i.e. float, double, int + * \tparam Size Number of rows and cols, or \b Dynamic + * \tparam Options Can be 0 or \b SelfAdjoint + * + * \sa class BandMatrix + */ +template +class TridiagonalMatrix : public BandMatrix { + typedef BandMatrix Base; + typedef typename Base::StorageIndex StorageIndex; + + public: + explicit TridiagonalMatrix(Index size = Size) : Base(size, size, Options & SelfAdjoint ? 0 : 1, 1) {} + + inline typename Base::template DiagonalIntReturnType<1>::Type super() { return Base::template diagonal<1>(); } + inline const typename Base::template DiagonalIntReturnType<1>::Type super() const { + return Base::template diagonal<1>(); + } + inline typename Base::template DiagonalIntReturnType<-1>::Type sub() { return Base::template diagonal<-1>(); } + inline const typename Base::template DiagonalIntReturnType<-1>::Type sub() const { + return Base::template diagonal<-1>(); + } + + protected: +}; + +struct BandShape {}; + +template +struct evaluator_traits > + : public evaluator_traits_base > { + typedef BandShape Shape; +}; + +template +struct evaluator_traits > + : public evaluator_traits_base > { + typedef BandShape Shape; +}; + +template <> +struct AssignmentKind { + typedef EigenBase2EigenBase Kind; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_BANDMATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Block.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Block.h new file mode 100644 index 0000000..c2d8bea --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Block.h @@ -0,0 +1,427 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_BLOCK_H +#define EIGEN_BLOCK_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits> : traits { + typedef typename traits::Scalar Scalar; + typedef typename traits::StorageKind StorageKind; + typedef typename traits::XprKind XprKind; + typedef typename ref_selector::type XprTypeNested; + typedef std::remove_reference_t XprTypeNested_; + enum { + MatrixRows = traits::RowsAtCompileTime, + MatrixCols = traits::ColsAtCompileTime, + RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows, + ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols, + MaxRowsAtCompileTime = BlockRows == 0 ? 0 + : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) + : int(traits::MaxRowsAtCompileTime), + MaxColsAtCompileTime = BlockCols == 0 ? 0 + : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) + : int(traits::MaxColsAtCompileTime), + + XprTypeIsRowMajor = (int(traits::Flags) & RowMajorBit) != 0, + IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1 + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0 + : XprTypeIsRowMajor, + HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), + InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), + InnerStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time::ret) + : int(outer_stride_at_compile_time::ret), + OuterStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time::ret) + : int(inner_stride_at_compile_time::ret), + + // FIXME, this traits is rather specialized for dense object and it needs to be cleaned further + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, + Flags = (traits::Flags & (DirectAccessBit | (InnerPanel_ ? CompressedAccessBit : 0))) | FlagsLvalueBit | + FlagsRowMajorBit, + // FIXME DirectAccessBit should not be handled by expressions + // + // Alignment is needed by MapBase's assertions + // We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the + // respective evaluator + Alignment = 0, + InnerPanel = InnerPanel_ ? 1 : 0 + }; +}; + +template ::ret> +class BlockImpl_dense; + +} // end namespace internal + +template +class BlockImpl; + +/** \class Block + * \ingroup Core_Module + * + * \brief Expression of a fixed-size or dynamic-size block + * + * \tparam XprType the type of the expression in which we are taking a block + * \tparam BlockRows the number of rows of the block we are taking at compile time (optional) + * \tparam BlockCols the number of columns of the block we are taking at compile time (optional) + * \tparam InnerPanel is true, if the block maps to a set of rows of a row major matrix or + * to set of columns of a column major matrix (optional). The parameter allows to determine + * at compile time whether aligned access is possible on the block expression. + * + * This class represents an expression of either a fixed-size or dynamic-size block. It is the return + * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block(Index,Index) and + * most of the time this is the only way it is used. + * + * However, if you want to directly manipulate block expressions, + * for instance if you want to write a function returning such an expression, you + * will need to use this class. + * + * Here is an example illustrating the dynamic case: + * \include class_Block.cpp + * Output: \verbinclude class_Block.out + * + * \note Even though this expression has dynamic size, in the case where \a XprType + * has fixed size, this expression inherits a fixed maximal size which means that evaluating + * it does not cause a dynamic memory allocation. + * + * Here is an example illustrating the fixed-size case: + * \include class_FixedBlock.cpp + * Output: \verbinclude class_FixedBlock.out + * + * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock + */ +template +class Block + : public BlockImpl::StorageKind> { + typedef BlockImpl::StorageKind> Impl; + using BlockHelper = internal::block_xpr_helper; + + public: + // typedef typename Impl::Base Base; + typedef Impl Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(Block) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) + + typedef internal::remove_all_t NestedExpression; + + /** Column or Row constructor + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index i) : Impl(xpr, i) { + eigen_assert((i >= 0) && (((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) && i < xpr.rows()) || + ((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) && i < xpr.cols()))); + } + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol) + : Impl(xpr, startRow, startCol) { + EIGEN_STATIC_ASSERT(RowsAtCompileTime != Dynamic && ColsAtCompileTime != Dynamic, + THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) + eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= xpr.rows() && startCol >= 0 && + BlockCols >= 0 && startCol + BlockCols <= xpr.cols()); + } + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Block(XprType& xpr, Index startRow, Index startCol, Index blockRows, + Index blockCols) + : Impl(xpr, startRow, startCol, blockRows, blockCols) { + eigen_assert((RowsAtCompileTime == Dynamic || RowsAtCompileTime == blockRows) && + (ColsAtCompileTime == Dynamic || ColsAtCompileTime == blockCols)); + eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 && + blockCols >= 0 && startCol <= xpr.cols() - blockCols); + } + + // convert nested blocks (e.g. Block>) to a simple block expression (Block) + + using ConstUnwindReturnType = Block; + using UnwindReturnType = Block; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstUnwindReturnType unwind() const { + return ConstUnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0), + this->rows(), this->cols()); + } + + template ::value>> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UnwindReturnType unwind() { + return UnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0), + this->rows(), this->cols()); + } +}; + +// The generic default implementation for dense block simply forward to the internal::BlockImpl_dense +// that must be specialized for direct and non-direct access... +template +class BlockImpl + : public internal::BlockImpl_dense { + typedef internal::BlockImpl_dense Impl; + typedef typename XprType::StorageIndex StorageIndex; + + public: + typedef Impl Base; + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl) + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index i) : Impl(xpr, i) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol) + : Impl(xpr, startRow, startCol) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol, + Index blockRows, Index blockCols) + : Impl(xpr, startRow, startCol, blockRows, blockCols) {} +}; + +namespace internal { + +/** \internal Internal implementation of dense Blocks in the general case. */ +template +class BlockImpl_dense : public internal::dense_xpr_base>::type { + typedef Block BlockType; + typedef typename internal::ref_selector::non_const_type XprTypeNested; + + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense) + + /** Column or Row constructor + */ + EIGEN_DEVICE_FUNC constexpr BlockImpl_dense(XprType& xpr, Index i) + : m_xpr(xpr), + // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, + // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, + // all other cases are invalid. + // The case a 1x1 matrix seems ambiguous, but the result is the same anyway. + m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? i : 0), + m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? i : 0), + m_blockRows(BlockRows == 1 ? 1 : xpr.rows()), + m_blockCols(BlockCols == 1 ? 1 : xpr.cols()) {} + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr BlockImpl_dense(XprType& xpr, Index startRow, Index startCol) + : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(BlockRows), m_blockCols(BlockCols) {} + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr BlockImpl_dense(XprType& xpr, Index startRow, Index startCol, Index blockRows, + Index blockCols) + : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), m_blockRows(blockRows), m_blockCols(blockCols) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_blockRows.value(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_blockCols.value(); } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index rowId, Index colId) { + EIGEN_STATIC_ASSERT_LVALUE(XprType) + return m_xpr.coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index rowId, Index colId) const { + return m_xpr.derived().coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const { + return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value()); + } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index) { + EIGEN_STATIC_ASSERT_LVALUE(XprType) + return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const { + return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index index) const { + return m_xpr.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + template + EIGEN_DEVICE_FUNC inline PacketScalar packet(Index rowId, Index colId) const { + return m_xpr.template packet(rowId + m_startRow.value(), colId + m_startCol.value()); + } + + template + EIGEN_DEVICE_FUNC inline void writePacket(Index rowId, Index colId, const PacketScalar& val) { + m_xpr.template writePacket(rowId + m_startRow.value(), colId + m_startCol.value(), val); + } + + template + EIGEN_DEVICE_FUNC inline PacketScalar packet(Index index) const { + return m_xpr.template packet(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + template + EIGEN_DEVICE_FUNC inline void writePacket(Index index, const PacketScalar& val) { + m_xpr.template writePacket(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val); + } + +#ifdef EIGEN_PARSED_BY_DOXYGEN + /** \sa MapBase::data() */ + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const; + EIGEN_DEVICE_FUNC inline Index innerStride() const; + EIGEN_DEVICE_FUNC inline Index outerStride() const; +#endif + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t& nestedExpression() const { + return m_xpr; + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; } + + EIGEN_DEVICE_FUNC constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); } + + EIGEN_DEVICE_FUNC constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); } + + protected: + XprTypeNested m_xpr; + const internal::variable_if_dynamic + m_startRow; + const internal::variable_if_dynamic + m_startCol; + const internal::variable_if_dynamic m_blockRows; + const internal::variable_if_dynamic m_blockCols; +}; + +/** \internal Internal implementation of dense Blocks in the direct access case.*/ +template +class BlockImpl_dense + : public MapBase> { + typedef Block BlockType; + typedef typename internal::ref_selector::non_const_type XprTypeNested; + enum { XprTypeIsRowMajor = (int(traits::Flags) & RowMajorBit) != 0 }; + + /** \internal Returns base+offset (unless base is null, in which case returns null). + * Adding an offset to nullptr is undefined behavior, so we must avoid it. + */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE static Scalar* add_to_nullable_pointer(Scalar* base, Index offset) { + return base != nullptr ? base + offset : nullptr; + } + + public: + typedef MapBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense) + + /** Column or Row constructor + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index i) + : Base((BlockRows == 0 || BlockCols == 0) + ? nullptr + : add_to_nullable_pointer( + xpr.data(), + i * (((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor)) || + ((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) && + (XprTypeIsRowMajor)) + ? xpr.innerStride() + : xpr.outerStride())), + BlockRows == 1 ? 1 : xpr.rows(), BlockCols == 1 ? 1 : xpr.cols()), + m_xpr(xpr), + m_startRow((BlockRows == 1) && (BlockCols == XprType::ColsAtCompileTime) ? i : 0), + m_startCol((BlockRows == XprType::RowsAtCompileTime) && (BlockCols == 1) ? i : 0) { + init(); + } + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index startRow, Index startCol) + : Base((BlockRows == 0 || BlockCols == 0) + ? nullptr + : add_to_nullable_pointer(xpr.data(), + xpr.innerStride() * (XprTypeIsRowMajor ? startCol : startRow) + + xpr.outerStride() * (XprTypeIsRowMajor ? startRow : startCol))), + m_xpr(xpr), + m_startRow(startRow), + m_startCol(startCol) { + init(); + } + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, Index startRow, Index startCol, Index blockRows, + Index blockCols) + : Base((blockRows == 0 || blockCols == 0) + ? nullptr + : add_to_nullable_pointer(xpr.data(), + xpr.innerStride() * (XprTypeIsRowMajor ? startCol : startRow) + + xpr.outerStride() * (XprTypeIsRowMajor ? startRow : startCol)), + blockRows, blockCols), + m_xpr(xpr), + m_startRow(startRow), + m_startCol(startCol) { + init(); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const internal::remove_all_t& nestedExpression() const noexcept { + return m_xpr; + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE XprType& nestedExpression() { return m_xpr; } + + /** \sa MapBase::innerStride() */ + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { + return internal::traits::HasSameStorageOrderAsXprType ? m_xpr.innerStride() : m_xpr.outerStride(); + } + + /** \sa MapBase::outerStride() */ + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { + return internal::traits::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride(); + } + + EIGEN_DEVICE_FUNC constexpr StorageIndex startRow() const noexcept { return m_startRow.value(); } + + EIGEN_DEVICE_FUNC constexpr StorageIndex startCol() const noexcept { return m_startCol.value(); } + +#ifndef __SUNPRO_CC + // FIXME sunstudio is not friendly with the above friend... + // META-FIXME there is no 'friend' keyword around here. Is this obsolete? + protected: +#endif + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal used by allowAligned() */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, + Index blockCols) + : Base(data, blockRows, blockCols), m_xpr(xpr) { + init(); + } +#endif + + protected: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void init() { + m_outerStride = + internal::traits::HasSameStorageOrderAsXprType ? m_xpr.outerStride() : m_xpr.innerStride(); + } + + XprTypeNested m_xpr; + const internal::variable_if_dynamic + m_startRow; + const internal::variable_if_dynamic + m_startCol; + Index m_outerStride; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_BLOCK_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CommaInitializer.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CommaInitializer.h new file mode 100644 index 0000000..4541f47 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CommaInitializer.h @@ -0,0 +1,148 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_COMMAINITIALIZER_H +#define EIGEN_COMMAINITIALIZER_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class CommaInitializer + * \ingroup Core_Module + * + * \brief Helper class used by the comma initializer operator + * + * This class is internally used to implement the comma initializer feature. It is + * the return type of MatrixBase::operator<<, and most of the time this is the only + * way it is used. + * + * \sa \blank \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished() + */ +template +struct CommaInitializer { + typedef typename XprType::Scalar Scalar; + + EIGEN_DEVICE_FUNC constexpr CommaInitializer(XprType& xpr, const Scalar& s) + : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) { + eigen_assert(m_xpr.rows() > 0 && m_xpr.cols() > 0 && "Cannot comma-initialize a 0x0 matrix (operator<<)"); + m_xpr.coeffRef(0, 0) = s; + } + + template + EIGEN_DEVICE_FUNC inline CommaInitializer(XprType& xpr, const DenseBase& other) + : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows()) { + eigen_assert(m_xpr.rows() >= other.rows() && m_xpr.cols() >= other.cols() && + "Cannot comma-initialize a 0x0 matrix (operator<<)"); + m_xpr.template block(0, 0, other.rows(), + other.cols()) = other; + } + + /* Copy/Move constructor which transfers ownership. This is crucial in + * absence of return value optimization to avoid assertions during destruction. */ + EIGEN_DEVICE_FUNC inline CommaInitializer(const CommaInitializer& o) + : m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) { + // Mark original object as finished. In absence of R-value references we need to const_cast: + const_cast(o).m_row = m_xpr.rows(); + const_cast(o).m_col = m_xpr.cols(); + const_cast(o).m_currentBlockRows = 0; + } + + /* inserts a scalar value in the target matrix */ + EIGEN_DEVICE_FUNC CommaInitializer &operator,(const Scalar& s) { + if (m_col == m_xpr.cols()) { + m_row += m_currentBlockRows; + m_col = 0; + m_currentBlockRows = 1; + eigen_assert(m_row < m_xpr.rows() && "Too many rows passed to comma initializer (operator<<)"); + } + eigen_assert(m_col < m_xpr.cols() && "Too many coefficients passed to comma initializer (operator<<)"); + eigen_assert(m_currentBlockRows == 1); + m_xpr.coeffRef(m_row, m_col++) = s; + return *this; + } + + /* inserts a matrix expression in the target matrix */ + template + EIGEN_DEVICE_FUNC CommaInitializer &operator,(const DenseBase& other) { + if (m_col == m_xpr.cols() && (other.cols() != 0 || other.rows() != m_currentBlockRows)) { + m_row += m_currentBlockRows; + m_col = 0; + m_currentBlockRows = other.rows(); + eigen_assert(m_row + m_currentBlockRows <= m_xpr.rows() && + "Too many rows passed to comma initializer (operator<<)"); + } + eigen_assert((m_col + other.cols() <= m_xpr.cols()) && + "Too many coefficients passed to comma initializer (operator<<)"); + eigen_assert(m_currentBlockRows == other.rows()); + m_xpr.template block(m_row, m_col, other.rows(), + other.cols()) = other; + m_col += other.cols(); + return *this; + } + + EIGEN_DEVICE_FUNC inline ~CommaInitializer() +#if defined VERIFY_RAISES_ASSERT && (!defined EIGEN_NO_ASSERTION_CHECKING) && defined EIGEN_EXCEPTIONS + noexcept(false) // Eigen::eigen_assert_exception +#endif + { + finished(); + } + + /** \returns the built matrix once all its coefficients have been set. + * Calling finished is 100% optional. Its purpose is to write expressions + * like this: + * \code + * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished()); + * \endcode + */ + EIGEN_DEVICE_FUNC inline XprType& finished() { + eigen_assert(((m_row + m_currentBlockRows) == m_xpr.rows() || m_xpr.cols() == 0) && m_col == m_xpr.cols() && + "Too few coefficients passed to comma initializer (operator<<)"); + return m_xpr; + } + + XprType& m_xpr; // target expression + Index m_row; // current row id + Index m_col; // current col id + Index m_currentBlockRows; // current block height +}; + +/** \anchor MatrixBaseCommaInitRef + * Convenient operator to set the coefficients of a matrix. + * + * The coefficients must be provided in a row major order and exactly match + * the size of the matrix. Otherwise an assertion is raised. + * + * Example: \include MatrixBase_set.cpp + * Output: \verbinclude MatrixBase_set.out + * + * \note According the c++ standard, the argument expressions of this comma initializer are evaluated in arbitrary + * order. + * + * \sa CommaInitializer::finished(), class CommaInitializer + */ +template +EIGEN_DEVICE_FUNC inline CommaInitializer DenseBase::operator<<(const Scalar& s) { + return CommaInitializer(*static_cast(this), s); +} + +/** \sa operator<<(const Scalar&) */ +template +template +EIGEN_DEVICE_FUNC inline CommaInitializer DenseBase::operator<<( + const DenseBase& other) { + return CommaInitializer(*static_cast(this), other); +} + +} // end namespace Eigen + +#endif // EIGEN_COMMAINITIALIZER_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ConditionEstimator.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ConditionEstimator.h new file mode 100644 index 0000000..dd1770b --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ConditionEstimator.h @@ -0,0 +1,173 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2016 Rasmus Munk Larsen (rmlarsen@google.com) +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CONDITIONESTIMATOR_H +#define EIGEN_CONDITIONESTIMATOR_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct rcond_compute_sign { + static inline Vector run(const Vector& v) { + const RealVector v_abs = v.cwiseAbs(); + return (v_abs.array() == static_cast(0)) + .select(Vector::Ones(v.size()), v.cwiseQuotient(v_abs)); + } +}; + +// Partial specialization to avoid elementwise division for real vectors. +template +struct rcond_compute_sign { + static inline Vector run(const Vector& v) { + return (v.array() < static_cast(0)) + .select(-Vector::Ones(v.size()), Vector::Ones(v.size())); + } +}; + +/** + * \returns an estimate of ||inv(matrix)||_1 given a decomposition of + * \a matrix that implements .solve() and .adjoint().solve() methods. + * + * This function implements Algorithms 4.1 and 5.1 from + * http://www.maths.manchester.ac.uk/~higham/narep/narep135.pdf + * which also forms the basis for the condition number estimators in + * LAPACK. Since at most 10 calls to the solve method of dec are + * performed, the total cost is O(dims^2), as opposed to O(dims^3) + * needed to compute the inverse matrix explicitly. + * + * The most common usage is in estimating the condition number + * ||matrix||_1 * ||inv(matrix)||_1. The first term ||matrix||_1 can be + * computed directly in O(n^2) operations. + * + * Supports the following decompositions: FullPivLU, PartialPivLU, LDLT, and + * LLT. + * + * \sa FullPivLU, PartialPivLU, LDLT, LLT. + */ +template +typename Decomposition::RealScalar rcond_invmatrix_L1_norm_estimate(const Decomposition& dec) { + typedef typename Decomposition::MatrixType MatrixType; + typedef typename Decomposition::Scalar Scalar; + typedef typename Decomposition::RealScalar RealScalar; + typedef typename internal::plain_col_type::type Vector; + typedef typename internal::plain_col_type::type RealVector; + const bool is_complex = (NumTraits::IsComplex != 0); + + eigen_assert(dec.rows() == dec.cols()); + const Index n = dec.rows(); + if (n == 0) return 0; + + // Disable Index to float conversion warning +#ifdef __INTEL_COMPILER +#pragma warning push +#pragma warning(disable : 2259) +#endif + Vector v = dec.solve(Vector::Ones(n) / Scalar(n)); +#ifdef __INTEL_COMPILER +#pragma warning pop +#endif + + // lower_bound is a lower bound on + // ||inv(matrix)||_1 = sup_v ||inv(matrix) v||_1 / ||v||_1 + // and is the objective maximized by the ("super-") gradient ascent + // algorithm below. + RealScalar lower_bound = v.template lpNorm<1>(); + if (n == 1) return lower_bound; + + // Gradient ascent algorithm follows: We know that the optimum is achieved at + // one of the simplices v = e_i, so in each iteration we follow a + // super-gradient to move towards the optimal one. + RealScalar old_lower_bound = lower_bound; + Vector sign_vector(n); + Vector old_sign_vector; + Index v_max_abs_index = -1; + Index old_v_max_abs_index = v_max_abs_index; + for (int k = 0; k < 4; ++k) { + sign_vector = internal::rcond_compute_sign::run(v); + if (k > 0 && !is_complex && sign_vector == old_sign_vector) { + // Break if the solution stagnated. + break; + } + // v_max_abs_index = argmax |real( inv(matrix)^T * sign_vector )| + v = dec.adjoint().solve(sign_vector); + v.real().cwiseAbs().maxCoeff(&v_max_abs_index); + if (v_max_abs_index == old_v_max_abs_index) { + // Break if the solution stagnated. + break; + } + // Move to the new simplex e_j, where j = v_max_abs_index. + v = dec.solve(Vector::Unit(n, v_max_abs_index)); // v = inv(matrix) * e_j. + lower_bound = v.template lpNorm<1>(); + if (lower_bound <= old_lower_bound) { + // Break if the gradient step did not increase the lower_bound. + break; + } + if (!is_complex) { + old_sign_vector = sign_vector; + } + old_v_max_abs_index = v_max_abs_index; + old_lower_bound = lower_bound; + } + // The following calculates an independent estimate of ||matrix||_1 by + // multiplying matrix by a vector with entries of slowly increasing + // magnitude and alternating sign: + // v_i = (-1)^{i} (1 + (i / (dim-1))), i = 0,...,dim-1. + // This improvement to Hager's algorithm above is due to Higham. It was + // added to make the algorithm more robust in certain corner cases where + // large elements in the matrix might otherwise escape detection due to + // exact cancellation (especially when op and op_adjoint correspond to a + // sequence of backsubstitutions and permutations), which could cause + // Hager's algorithm to vastly underestimate ||matrix||_1. + Scalar alternating_sign(RealScalar(1)); + for (Index i = 0; i < n; ++i) { + // The static_cast is needed when Scalar is a complex and RealScalar implements expression templates + v[i] = alternating_sign * static_cast(RealScalar(1) + (RealScalar(i) / (RealScalar(n - 1)))); + alternating_sign = -alternating_sign; + } + v = dec.solve(v); + const RealScalar alternate_lower_bound = (2 * v.template lpNorm<1>()) / (3 * RealScalar(n)); + return numext::maxi(lower_bound, alternate_lower_bound); +} + +/** \brief Reciprocal condition number estimator. + * + * Computing a decomposition of a dense matrix takes O(n^3) operations, while + * this method estimates the condition number quickly and reliably in O(n^2) + * operations. + * + * \returns an estimate of the reciprocal condition number + * (1 / (||matrix||_1 * ||inv(matrix)||_1)) of matrix, given ||matrix||_1 and + * its decomposition. Supports the following decompositions: FullPivLU, + * PartialPivLU, LDLT, and LLT. + * + * \sa FullPivLU, PartialPivLU, LDLT, LLT. + */ +template +typename Decomposition::RealScalar rcond_estimate_helper(typename Decomposition::RealScalar matrix_norm, + const Decomposition& dec) { + typedef typename Decomposition::RealScalar RealScalar; + eigen_assert(dec.rows() == dec.cols()); + if (dec.rows() == 0) return NumTraits::infinity(); + if (numext::is_exactly_zero(matrix_norm)) return RealScalar(0); + if (dec.rows() == 1) return RealScalar(1); + const RealScalar inverse_matrix_norm = rcond_invmatrix_L1_norm_estimate(dec); + return (numext::is_exactly_zero(inverse_matrix_norm) ? RealScalar(0) + : (RealScalar(1) / inverse_matrix_norm) / matrix_norm); +} + +} // namespace internal + +} // namespace Eigen + +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreEvaluators.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreEvaluators.h new file mode 100644 index 0000000..9df0c96 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreEvaluators.h @@ -0,0 +1,1972 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Benoit Jacob +// Copyright (C) 2011-2014 Gael Guennebaud +// Copyright (C) 2011-2012 Jitse Niesen +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_COREEVALUATORS_H +#define EIGEN_COREEVALUATORS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// This class returns the evaluator kind from the expression storage kind. +// Default assumes index based accessors +template +struct storage_kind_to_evaluator_kind { + typedef IndexBased Kind; +}; + +// This class returns the evaluator shape from the expression storage kind. +// It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc. +template +struct storage_kind_to_shape; + +template <> +struct storage_kind_to_shape { + typedef DenseShape Shape; +}; +template <> +struct storage_kind_to_shape { + typedef SolverShape Shape; +}; +template <> +struct storage_kind_to_shape { + typedef PermutationShape Shape; +}; +template <> +struct storage_kind_to_shape { + typedef TranspositionsShape Shape; +}; + +// Evaluators have to be specialized with respect to various criteria such as: +// - storage/structure/shape +// - scalar type +// - etc. +// Therefore, we need specialization of evaluator providing additional template arguments for each kind of evaluators. +// We currently distinguish the following kind of evaluators: +// - unary_evaluator for expressions taking only one arguments (CwiseUnaryOp, CwiseUnaryView, Transpose, +// MatrixWrapper, ArrayWrapper, Reverse, Replicate) +// - binary_evaluator for expression taking two arguments (CwiseBinaryOp) +// - ternary_evaluator for expression taking three arguments (CwiseTernaryOp) +// - product_evaluator for linear algebra products (Product); special case of binary_evaluator because it requires +// additional tags for dispatching. +// - mapbase_evaluator for Map, Block, Ref +// - block_evaluator for Block (special dispatching to a mapbase_evaluator or unary_evaluator) + +template ::Kind, + typename Arg2Kind = typename evaluator_traits::Kind, + typename Arg3Kind = typename evaluator_traits::Kind, + typename Arg1Scalar = typename traits::Scalar, + typename Arg2Scalar = typename traits::Scalar, + typename Arg3Scalar = typename traits::Scalar> +struct ternary_evaluator; + +template ::Kind, + typename RhsKind = typename evaluator_traits::Kind, + typename LhsScalar = typename traits::Scalar, + typename RhsScalar = typename traits::Scalar> +struct binary_evaluator; + +template ::Kind, + typename Scalar = typename T::Scalar> +struct unary_evaluator; + +// evaluator_traits contains traits for evaluator + +template +struct evaluator_traits_base { + // by default, get evaluator kind and shape from storage + typedef typename storage_kind_to_evaluator_kind::StorageKind>::Kind Kind; + typedef typename storage_kind_to_shape::StorageKind>::Shape Shape; +}; + +// Default evaluator traits +template +struct evaluator_traits : public evaluator_traits_base {}; + +template ::Shape> +struct evaluator_assume_aliasing { + static const bool value = false; +}; + +// By default, we assume a unary expression: +template +struct evaluator : public unary_evaluator { + typedef unary_evaluator Base; + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const T& xpr) : Base(xpr) {} +}; + +// TODO: Think about const-correctness +template +struct evaluator : evaluator { + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const T& xpr) : evaluator(xpr) {} +}; + +// ---------- base class for all evaluators ---------- + +template +struct evaluator_base { + // TODO: find a way to avoid propagating all these traits. They are currently only needed to handle + // outer,inner indices. + typedef traits ExpressionTraits; + + enum { Alignment = 0 }; + // noncopyable: + // Don't make this class inherit noncopyable as this kills EBO (Empty Base Optimization) + // and make complex evaluator much larger than then should do. + EIGEN_DEVICE_FUNC constexpr evaluator_base() = default; + + private: + EIGEN_DEVICE_FUNC evaluator_base(const evaluator_base&); + EIGEN_DEVICE_FUNC const evaluator_base& operator=(const evaluator_base&); +}; + +// -------------------- Matrix and Array -------------------- +// +// evaluator is a common base class for the +// Matrix and Array evaluators. +// Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense, +// so no need for more sophisticated dispatching. + +// this helper permits to completely eliminate m_outerStride if it is known at compiletime. +template +class plainobjectbase_evaluator_data { + public: + EIGEN_DEVICE_FUNC constexpr plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) : data(ptr) { +#ifndef EIGEN_INTERNAL_DEBUGGING + EIGEN_UNUSED_VARIABLE(outerStride); +#endif + eigen_internal_assert(outerStride == OuterStride); + } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return OuterStride; } + const Scalar* data; +}; + +template +class plainobjectbase_evaluator_data { + public: + EIGEN_DEVICE_FUNC constexpr plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) + : data(ptr), m_outerStride(outerStride) {} + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { return m_outerStride; } + const Scalar* data; + + protected: + Index m_outerStride; +}; + +template +struct evaluator> : evaluator_base { + typedef PlainObjectBase PlainObjectType; + typedef typename PlainObjectType::Scalar Scalar; + typedef typename PlainObjectType::CoeffReturnType CoeffReturnType; + + enum { + IsRowMajor = PlainObjectType::IsRowMajor, + IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime, + RowsAtCompileTime = PlainObjectType::RowsAtCompileTime, + ColsAtCompileTime = PlainObjectType::ColsAtCompileTime, + + CoeffReadCost = NumTraits::ReadCost, + Flags = traits::EvaluatorFlags, + Alignment = traits::Alignment + }; + enum { + // We do not need to know the outer stride for vectors + OuterStrideAtCompileTime = IsVectorAtCompileTime ? 0 + : int(IsRowMajor) ? ColsAtCompileTime + : RowsAtCompileTime + }; + + EIGEN_DEVICE_FUNC constexpr evaluator() : m_d(0, OuterStrideAtCompileTime) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const PlainObjectType& m) + : m_d(m.data(), IsVectorAtCompileTime ? 0 : m.outerStride()) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index row, Index col) const { + return coeff(getIndex(row, col)); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr CoeffReturnType coeff(Index index) const { return m_d.data[index]; } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index row, Index col) { + return coeffRef(getIndex(row, col)); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index index) { + return const_cast(m_d.data)[index]; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return packet(getIndex(row, col)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return ploadt(m_d.data + index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + writePacket(getIndex(row, col), x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + pstoret(const_cast(m_d.data) + index, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return packetSegment(getIndex(row, col), begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return ploadtSegment(m_d.data + index, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + writePacketSegment(getIndex(row, col), x, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + pstoretSegment(const_cast(m_d.data) + index, x, begin, count); + } + + protected: + plainobjectbase_evaluator_data m_d; + + private: + EIGEN_DEVICE_FUNC constexpr Index getIndex(Index row, Index col) const { + return IsRowMajor ? row * m_d.outerStride() + col : row + col * m_d.outerStride(); + } +}; + +template +struct evaluator> + : evaluator>> { + typedef Matrix XprType; + + EIGEN_DEVICE_FUNC constexpr evaluator() = default; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& m) : evaluator>(m) {} +}; + +template +struct evaluator> + : evaluator>> { + typedef Array XprType; + + EIGEN_DEVICE_FUNC constexpr evaluator() = default; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& m) : evaluator>(m) {} +}; + +// -------------------- Transpose -------------------- + +template +struct unary_evaluator, IndexBased> : evaluator_base> { + typedef Transpose XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost, + Flags = evaluator::Flags ^ RowMajorBit, + Alignment = evaluator::Alignment + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& t) + : m_argImpl(t.nestedExpression()) {} + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_argImpl.coeff(col, row); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_argImpl.coeff(index); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_argImpl.coeffRef(col, row); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE typename XprType::Scalar& coeffRef(Index index) { + return m_argImpl.coeffRef(index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_argImpl.template packet(col, row); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_argImpl.template packet(index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + m_argImpl.template writePacket(col, row, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + m_argImpl.template writePacket(index, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_argImpl.template packetSegment(col, row, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return m_argImpl.template packetSegment(index, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + m_argImpl.template writePacketSegment(col, row, x, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + m_argImpl.template writePacketSegment(index, x, begin, count); + } + + protected: + evaluator m_argImpl; +}; + +// -------------------- CwiseNullaryOp -------------------- +// Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator. +// Likewise, there is not need to more sophisticated dispatching here. + +template ::value, + bool has_unary = has_unary_operator::value, + bool has_binary = has_binary_operator::value> +struct nullary_wrapper { + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, + IndexType j) const { + return op(i, j); + } + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { + return op(i); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { + return op.template packetOp(i, j); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { + return op.template packetOp(i); + } +}; + +template +struct nullary_wrapper { + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType = 0, + IndexType = 0) const { + return op(); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType = 0, IndexType = 0) const { + return op.template packetOp(); + } +}; + +template +struct nullary_wrapper { + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, + IndexType j = 0) const { + return op(i, j); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j = 0) const { + return op.template packetOp(i, j); + } +}; + +// We need the following specialization for vector-only functors assigned to a runtime vector, +// for instance, using linspace and assigning a RowVectorXd to a MatrixXd or even a row of a MatrixXd. +// In this case, i==0 and j is used for the actual iteration. +template +struct nullary_wrapper { + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, + IndexType j) const { + eigen_assert(i == 0 || j == 0); + return op(i + j); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { + eigen_assert(i == 0 || j == 0); + return op.template packetOp(i + j); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { + return op(i); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { + return op.template packetOp(i); + } +}; + +template +struct nullary_wrapper {}; + +template +struct evaluator> + : evaluator_base> { + typedef CwiseNullaryOp XprType; + typedef remove_all_t PlainObjectTypeCleaned; + + enum { + CoeffReadCost = functor_traits::Cost, + + Flags = (evaluator::Flags & + (HereditaryBits | (functor_has_linear_access::ret ? LinearAccessBit : 0) | + (functor_traits::PacketAccess ? PacketAccessBit : 0))) | + (functor_traits::IsRepeatable ? 0 : EvalBeforeNestingBit), + Alignment = AlignedMax + }; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& n) : m_functor(n.functor()), m_wrapper() { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::CoeffReturnType CoeffReturnType; + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(IndexType row, IndexType col) const { + return m_wrapper(m_functor, row, col); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(IndexType index) const { + return m_wrapper(m_functor, index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(IndexType row, IndexType col) const { + return m_wrapper.template packetOp(m_functor, row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(IndexType index) const { + return m_wrapper.template packetOp(m_functor, index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(IndexType row, IndexType col, Index /*begin*/, + Index /*count*/) const { + return packet(row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(IndexType index, Index /*begin*/, + Index /*count*/) const { + return packet(index); + } + + protected: + const NullaryOp m_functor; + const nullary_wrapper m_wrapper; +}; + +// -------------------- CwiseUnaryOp -------------------- + +template +struct unary_evaluator, IndexBased> : evaluator_base> { + typedef CwiseUnaryOp XprType; + + enum { + CoeffReadCost = int(evaluator::CoeffReadCost) + int(functor_traits::Cost), + + Flags = evaluator::Flags & + (HereditaryBits | LinearAccessBit | (functor_traits::PacketAccess ? PacketAccessBit : 0)), + Alignment = evaluator::Alignment + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& op) : m_d(op) { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_d.func()(m_d.argImpl.coeff(row, col)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_d.func()(m_d.argImpl.coeff(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_d.func().packetOp(m_d.argImpl.template packet(row, col)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_d.func().packetOp(m_d.argImpl.template packet(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_d.func().packetOp(m_d.argImpl.template packetSegment(row, col, begin, count)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return m_d.func().packetOp(m_d.argImpl.template packetSegment(index, begin, count)); + } + + protected: + // this helper permits to completely eliminate the functor if it is empty + struct Data { + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Data(const XprType& xpr) + : op(xpr.functor()), argImpl(xpr.nestedExpression()) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const UnaryOp& func() const { return op; } + UnaryOp op; + evaluator argImpl; + }; + + Data m_d; +}; + +// ----------------------- Casting --------------------- + +template +struct unary_evaluator, ArgType>, IndexBased> { + using CastOp = core_cast_op; + using XprType = CwiseUnaryOp; + + // Use the largest packet type by default + using SrcPacketType = typename packet_traits::type; + static constexpr int SrcPacketSize = unpacket_traits::size; + static constexpr int SrcPacketBytes = SrcPacketSize * sizeof(SrcType); + + enum { + CoeffReadCost = int(evaluator::CoeffReadCost) + int(functor_traits::Cost), + PacketAccess = functor_traits::PacketAccess, + ActualPacketAccessBit = PacketAccess ? PacketAccessBit : 0, + Flags = evaluator::Flags & (HereditaryBits | LinearAccessBit | ActualPacketAccessBit), + IsRowMajor = (evaluator::Flags & RowMajorBit), + Alignment = evaluator::Alignment + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& xpr) + : m_argImpl(xpr.nestedExpression()), m_rows(xpr.rows()), m_cols(xpr.cols()) { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + template + using AltSrcScalarOp = std::enable_if_t<(unpacket_traits::size < SrcPacketSize && + !find_packet_by_size::size>::value), + bool>; + template + using SrcPacketArgs1 = + std::enable_if_t<(find_packet_by_size::size>::value), bool>; + template + using SrcPacketArgs2 = std::enable_if_t<(unpacket_traits::size) == (2 * SrcPacketSize), bool>; + template + using SrcPacketArgs4 = std::enable_if_t<(unpacket_traits::size) == (4 * SrcPacketSize), bool>; + template + using SrcPacketArgs8 = std::enable_if_t<(unpacket_traits::size) == (8 * SrcPacketSize), bool>; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool check_array_bounds(Index row, Index col, Index begin, Index count) const { + return IsRowMajor ? (col + count + begin <= cols()) : (row + count + begin <= rows()); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool check_array_bounds(Index index, Index begin, Index count) const { + return index + count + begin <= size(); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE SrcType srcCoeff(Index row, Index col, Index offset) const { + Index actualRow = IsRowMajor ? row : row + offset; + Index actualCol = IsRowMajor ? col + offset : col; + return m_argImpl.coeff(actualRow, actualCol); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE SrcType srcCoeff(Index index, Index offset) const { + Index actualIndex = index + offset; + return m_argImpl.coeff(actualIndex); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE DstType coeff(Index row, Index col) const { + return cast(srcCoeff(row, col, 0)); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE DstType coeff(Index index) const { + return cast(srcCoeff(index, 0)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType srcPacket(Index row, Index col, Index offset) const { + constexpr int PacketSize = unpacket_traits::size; + Index packetOffset = offset * PacketSize; + Index actualRow = IsRowMajor ? row : row + packetOffset; + Index actualCol = IsRowMajor ? col + packetOffset : col; + eigen_assert(check_array_bounds(actualRow, actualCol, 0, PacketSize) && "Array index out of bounds"); + return m_argImpl.template packet(actualRow, actualCol); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType srcPacket(Index index, Index offset) const { + constexpr int PacketSize = unpacket_traits::size; + Index packetOffset = offset * PacketSize; + Index actualIndex = index + packetOffset; + eigen_assert(check_array_bounds(actualIndex, 0, PacketSize) && "Array index out of bounds"); + return m_argImpl.template packet(actualIndex); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType srcPacketSegment(Index row, Index col, Index begin, Index count, + Index offset) const { + constexpr int PacketSize = unpacket_traits::size; + Index packetOffset = offset * PacketSize; + Index actualRow = IsRowMajor ? row : row + packetOffset; + Index actualCol = IsRowMajor ? col + packetOffset : col; + eigen_assert(check_array_bounds(actualRow, actualCol, begin, count) && "Array index out of bounds"); + return m_argImpl.template packetSegment(actualRow, actualCol, begin, count); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType srcPacketSegment(Index index, Index begin, Index count, + Index offset) const { + constexpr int PacketSize = unpacket_traits::size; + Index packetOffset = offset * PacketSize; + Index actualIndex = index + packetOffset; + eigen_assert(check_array_bounds(actualIndex, begin, count) && "Array index out of bounds"); + return m_argImpl.template packetSegment(actualIndex, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketBlock srcPacketSegmentHelper(Index row, Index col, + Index begin, + Index count) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets; + for (Index i = 0; i < NumPackets; i++) packets.packet[i] = pzero(PacketType()); + Index offset = begin / SrcPacketSize; + Index actualBegin = begin % SrcPacketSize; + for (; offset < NumPackets; offset++) { + Index actualCount = numext::mini(SrcPacketSize - actualBegin, count); + packets.packet[offset] = srcPacketSegment(row, col, actualBegin, actualCount, offset); + if (count == actualCount) break; + actualBegin = 0; + count -= actualCount; + } + return packets; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketBlock srcPacketSegmentHelper(Index index, + Index begin, + Index count) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets; + for (Index i = 0; i < NumPackets; i++) packets.packet[i] = pzero(PacketType()); + Index offset = begin / SrcPacketSize; + Index actualBegin = begin % SrcPacketSize; + for (; offset < NumPackets; offset++) { + Index actualCount = numext::mini(SrcPacketSize - actualBegin, count); + packets.packet[offset] = srcPacketSegment(index, actualBegin, actualCount, offset); + if (count == actualCount) break; + actualBegin = 0; + count -= actualCount; + } + return packets; + } + + // There is no source packet type with equal or fewer elements than DstPacketType. + // This is problematic as the evaluation loop may attempt to access data outside the bounds of the array. + // For example, consider the cast utilizing pcast with an array of size 4: {0.0f,1.0f,2.0f,3.0f}. + // The first iteration of the evaluation loop will load 16 bytes: {0.0f,1.0f,2.0f,3.0f} and cast to {0.0,1.0}, which + // is acceptable. The second iteration will load 16 bytes: {2.0f,3.0f,?,?}, which is outside the bounds of the array. + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index row, Index col) const { + constexpr int DstPacketSize = unpacket_traits::size; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacketSegment(row, col, 0, DstPacketSize, 0)); + } + // Use the source packet type with the same size as DstPacketType, if it exists + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index row, Index col) const { + constexpr int DstPacketSize = unpacket_traits::size; + using SizedSrcPacketType = typename find_packet_by_size::type; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacket(row, col, 0)); + } + // unpacket_traits::size == 2 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index row, Index col) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast(srcPacket(row, col, 0), + srcPacket(row, col, 1)); + } + // unpacket_traits::size == 4 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index row, Index col) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast(srcPacket(row, col, 0), srcPacket(row, col, 1), + srcPacket(row, col, 2), + srcPacket(row, col, 3)); + } + // unpacket_traits::size == 8 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index row, Index col) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast( + srcPacket(row, col, 0), srcPacket(row, col, 1), srcPacket(row, col, 2), + srcPacket(row, col, 3), srcPacket(row, col, 4), srcPacket(row, col, 5), + srcPacket(row, col, 6), srcPacket(row, col, 7)); + } + + // packetSegment variants + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + constexpr int DstPacketSize = unpacket_traits::size; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacketSegment(row, col, begin, count, 0)); + } + // Use the source packet type with the same size as DstPacketType, if it exists + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + constexpr int DstPacketSize = unpacket_traits::size; + using SizedSrcPacketType = typename find_packet_by_size::type; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast( + srcPacketSegment(row, col, begin, count, 0)); + } + // unpacket_traits::size == 2 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + constexpr int NumPackets = 2; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(row, col, begin, count); + return pcast(packets.packet[0], packets.packet[1]); + } + // unpacket_traits::size == 4 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + constexpr int NumPackets = 4; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(row, col, begin, count); + return pcast(packets.packet[0], packets.packet[1], packets.packet[2], + packets.packet[3]); + } + // unpacket_traits::size == 8 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + constexpr int NumPackets = 8; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(row, col, begin, count); + return pcast(packets.packet[0], packets.packet[1], packets.packet[2], + packets.packet[3], packets.packet[4], packets.packet[5], + packets.packet[6], packets.packet[7]); + } + + // Analogous routines for linear access. + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index index) const { + constexpr int DstPacketSize = unpacket_traits::size; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacketSegment(index, 0, DstPacketSize, 0)); + } + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index index) const { + constexpr int DstPacketSize = unpacket_traits::size; + using SizedSrcPacketType = typename find_packet_by_size::type; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacket(index, 0)); + } + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index index) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast(srcPacket(index, 0), srcPacket(index, 1)); + } + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index index) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast(srcPacket(index, 0), srcPacket(index, 1), + srcPacket(index, 2), srcPacket(index, 3)); + } + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packet(Index index) const { + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + return pcast(srcPacket(index, 0), srcPacket(index, 1), + srcPacket(index, 2), srcPacket(index, 3), + srcPacket(index, 4), srcPacket(index, 5), + srcPacket(index, 6), srcPacket(index, 7)); + } + + // packetSegment variants + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int DstPacketSize = unpacket_traits::size; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast(srcPacketSegment(index, begin, count, 0)); + } + // Use the source packet type with the same size as DstPacketType, if it exists + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int DstPacketSize = unpacket_traits::size; + using SizedSrcPacketType = typename find_packet_by_size::type; + constexpr int SrcBytesIncrement = DstPacketSize * sizeof(SrcType); + constexpr int SrcLoadMode = plain_enum_min(SrcBytesIncrement, LoadMode); + return pcast( + srcPacketSegment(index, begin, count, 0)); + } + // unpacket_traits::size == 2 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int NumPackets = 2; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(index, begin, count); + return pcast(packets.packet[0], packets.packet[1]); + } + // unpacket_traits::size == 4 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int NumPackets = 4; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(index, begin, count); + return pcast(packets.packet[0], packets.packet[1], packets.packet[2], + packets.packet[3]); + } + // unpacket_traits::size == 8 * SrcPacketSize + template = true> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DstPacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int NumPackets = 8; + constexpr int SrcLoadMode = plain_enum_min(SrcPacketBytes, LoadMode); + PacketBlock packets = + srcPacketSegmentHelper(index, begin, count); + return pcast(packets.packet[0], packets.packet[1], packets.packet[2], + packets.packet[3], packets.packet[4], packets.packet[5], + packets.packet[6], packets.packet[7]); + } + + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { return m_rows; } + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return m_cols; } + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return m_rows * m_cols; } + + protected: + const evaluator m_argImpl; + const variable_if_dynamic m_rows; + const variable_if_dynamic m_cols; +}; + +// -------------------- CwiseTernaryOp -------------------- + +// this is a ternary expression +template +struct evaluator> + : public ternary_evaluator> { + typedef CwiseTernaryOp XprType; + typedef ternary_evaluator> Base; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& xpr) : Base(xpr) {} +}; + +template +struct ternary_evaluator, IndexBased, IndexBased> + : evaluator_base> { + typedef CwiseTernaryOp XprType; + + enum { + CoeffReadCost = int(evaluator::CoeffReadCost) + int(evaluator::CoeffReadCost) + + int(evaluator::CoeffReadCost) + int(functor_traits::Cost), + + Arg1Flags = evaluator::Flags, + Arg2Flags = evaluator::Flags, + Arg3Flags = evaluator::Flags, + SameType = is_same::value && + is_same::value, + StorageOrdersAgree = (int(Arg1Flags) & RowMajorBit) == (int(Arg2Flags) & RowMajorBit) && + (int(Arg1Flags) & RowMajorBit) == (int(Arg3Flags) & RowMajorBit), + Flags0 = (int(Arg1Flags) | int(Arg2Flags) | int(Arg3Flags)) & + (HereditaryBits | + (int(Arg1Flags) & int(Arg2Flags) & int(Arg3Flags) & + ((StorageOrdersAgree ? LinearAccessBit : 0) | + (functor_traits::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)))), + Flags = (Flags0 & ~RowMajorBit) | (Arg1Flags & RowMajorBit), + Alignment = plain_enum_min(plain_enum_min(evaluator::Alignment, evaluator::Alignment), + evaluator::Alignment) + }; + + EIGEN_DEVICE_FUNC constexpr explicit ternary_evaluator(const XprType& xpr) : m_d(xpr) { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_d.func()(m_d.arg1Impl.coeff(row, col), m_d.arg2Impl.coeff(row, col), m_d.arg3Impl.coeff(row, col)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_d.func()(m_d.arg1Impl.coeff(index), m_d.arg2Impl.coeff(index), m_d.arg3Impl.coeff(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_d.func().packetOp(m_d.arg1Impl.template packet(row, col), + m_d.arg2Impl.template packet(row, col), + m_d.arg3Impl.template packet(row, col)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_d.func().packetOp(m_d.arg1Impl.template packet(index), + m_d.arg2Impl.template packet(index), + m_d.arg3Impl.template packet(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_d.func().packetOp(m_d.arg1Impl.template packetSegment(row, col, begin, count), + m_d.arg2Impl.template packetSegment(row, col, begin, count), + m_d.arg3Impl.template packetSegment(row, col, begin, count)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return m_d.func().packetOp(m_d.arg1Impl.template packetSegment(index, begin, count), + m_d.arg2Impl.template packetSegment(index, begin, count), + m_d.arg3Impl.template packetSegment(index, begin, count)); + } + + protected: + // this helper permits to completely eliminate the functor if it is empty + struct Data { + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Data(const XprType& xpr) + : op(xpr.functor()), arg1Impl(xpr.arg1()), arg2Impl(xpr.arg2()), arg3Impl(xpr.arg3()) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const TernaryOp& func() const { return op; } + TernaryOp op; + evaluator arg1Impl; + evaluator arg2Impl; + evaluator arg3Impl; + }; + + Data m_d; +}; + +template +struct scalar_boolean_select_spec { + using DummyTernaryOp = scalar_boolean_select_op; + using DummyArg3 = CwiseBinaryOp, CmpLhsType, CmpRhsType>; + using DummyXprType = CwiseTernaryOp; + + // only use the typed comparison if it is vectorized + static constexpr bool UseTyped = functor_traits>::PacketAccess; + using CondScalar = std::conditional_t; + + using TernaryOp = scalar_boolean_select_op; + using Arg3 = CwiseBinaryOp, CmpLhsType, CmpRhsType>; + using XprType = CwiseTernaryOp; + + using Base = ternary_evaluator; +}; + +// specialization for expressions like (a < b).select(c, d) to enable full vectorization +template +struct evaluator, Arg1, Arg2, + CwiseBinaryOp, CmpLhsType, CmpRhsType>>> + : public scalar_boolean_select_spec::Base { + using Helper = scalar_boolean_select_spec; + using Base = typename Helper::Base; + using DummyXprType = typename Helper::DummyXprType; + using Arg3 = typename Helper::Arg3; + using XprType = typename Helper::XprType; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const DummyXprType& xpr) + : Base(XprType(xpr.arg1(), xpr.arg2(), Arg3(xpr.arg3().lhs(), xpr.arg3().rhs()))) {} +}; + +// -------------------- CwiseBinaryOp -------------------- + +// this is a binary expression +template +struct evaluator> : public binary_evaluator> { + typedef CwiseBinaryOp XprType; + typedef binary_evaluator> Base; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} +}; + +template +struct binary_evaluator, IndexBased, IndexBased> + : evaluator_base> { + typedef CwiseBinaryOp XprType; + + enum { + CoeffReadCost = + int(evaluator::CoeffReadCost) + int(evaluator::CoeffReadCost) + int(functor_traits::Cost), + + LhsFlags = evaluator::Flags, + RhsFlags = evaluator::Flags, + SameType = is_same::value, + StorageOrdersAgree = (int(LhsFlags) & RowMajorBit) == (int(RhsFlags) & RowMajorBit), + Flags0 = (int(LhsFlags) | int(RhsFlags)) & + (HereditaryBits | + (int(LhsFlags) & int(RhsFlags) & + ((StorageOrdersAgree ? LinearAccessBit : 0) | + (functor_traits::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)))), + Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit), + Alignment = plain_enum_min(evaluator::Alignment, evaluator::Alignment) + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit binary_evaluator(const XprType& xpr) : m_d(xpr) { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_d.func()(m_d.lhsImpl.coeff(row, col), m_d.rhsImpl.coeff(row, col)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_d.func()(m_d.lhsImpl.coeff(index), m_d.rhsImpl.coeff(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_d.func().packetOp(m_d.lhsImpl.template packet(row, col), + m_d.rhsImpl.template packet(row, col)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_d.func().packetOp(m_d.lhsImpl.template packet(index), + m_d.rhsImpl.template packet(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_d.func().packetOp(m_d.lhsImpl.template packetSegment(row, col, begin, count), + m_d.rhsImpl.template packetSegment(row, col, begin, count)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return m_d.func().packetOp(m_d.lhsImpl.template packetSegment(index, begin, count), + m_d.rhsImpl.template packetSegment(index, begin, count)); + } + + protected: + // this helper permits to completely eliminate the functor if it is empty + struct Data { + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Data(const XprType& xpr) + : op(xpr.functor()), lhsImpl(xpr.lhs()), rhsImpl(xpr.rhs()) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const BinaryOp& func() const { return op; } + BinaryOp op; + evaluator lhsImpl; + evaluator rhsImpl; + }; + + Data m_d; +}; + +// -------------------- CwiseUnaryView -------------------- + +template +struct unary_evaluator, IndexBased> + : evaluator_base> { + typedef CwiseUnaryView XprType; + + enum { + CoeffReadCost = int(evaluator::CoeffReadCost) + int(functor_traits::Cost), + + Flags = (evaluator::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)), + + Alignment = 0 // FIXME: clarify why alignment is lost for CwiseUnaryView. + }; + + EIGEN_DEVICE_FUNC constexpr explicit unary_evaluator(const XprType& op) : m_d(op) { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_d.func()(m_d.argImpl.coeff(row, col)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_d.func()(m_d.argImpl.coeff(index)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_d.func()(m_d.argImpl.coeffRef(row, col)); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return m_d.func()(m_d.argImpl.coeffRef(index)); + } + + protected: + // this helper permits to completely eliminate the functor if it is empty + struct Data { + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Data(const XprType& xpr) + : op(xpr.functor()), argImpl(xpr.nestedExpression()) {} + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const UnaryOp& func() const { return op; } + UnaryOp op; + evaluator argImpl; + }; + + Data m_d; +}; + +// -------------------- Map -------------------- + +// FIXME: consider using Derived::PlainObject for PlainObjectType. +// but that might complicate template specialization +template +struct mapbase_evaluator; + +template +struct mapbase_evaluator : evaluator_base { + typedef Derived XprType; + typedef typename XprType::PointerType PointerType; + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + enum { + IsRowMajor = XprType::RowsAtCompileTime, + ColsAtCompileTime = XprType::ColsAtCompileTime, + CoeffReadCost = NumTraits::ReadCost + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit mapbase_evaluator(const XprType& map) + : m_data(const_cast(map.data())), + m_innerStride(map.innerStride()), + m_outerStride(map.outerStride()) { + EIGEN_STATIC_ASSERT(check_implication((evaluator::Flags & PacketAccessBit) != 0, + inner_stride_at_compile_time::ret == 1), + PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_data[col * colStride() + row * rowStride()]; + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_data[index * m_innerStride.value()]; + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_data[col * colStride() + row * rowStride()]; + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return m_data[index * m_innerStride.value()]; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + PointerType ptr = m_data + row * rowStride() + col * colStride(); + return ploadt(ptr); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return ploadt(m_data + index * m_innerStride.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + PointerType ptr = m_data + row * rowStride() + col * colStride(); + pstoret(ptr, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + pstoret(m_data + index * m_innerStride.value(), x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + PointerType ptr = m_data + row * rowStride() + col * colStride(); + return ploadtSegment(ptr, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return ploadtSegment(m_data + index * m_innerStride.value(), begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + PointerType ptr = m_data + row * rowStride() + col * colStride(); + pstoretSegment(ptr, x, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + pstoretSegment(m_data + index * m_innerStride.value(), x, begin, count); + } + + protected: + EIGEN_DEVICE_FUNC constexpr Index rowStride() const noexcept { + return XprType::IsRowMajor ? m_outerStride.value() : m_innerStride.value(); + } + EIGEN_DEVICE_FUNC constexpr Index colStride() const noexcept { + return XprType::IsRowMajor ? m_innerStride.value() : m_outerStride.value(); + } + + PointerType m_data; + const variable_if_dynamic m_innerStride; + const variable_if_dynamic m_outerStride; +}; + +template +struct evaluator> + : public mapbase_evaluator, PlainObjectType> { + typedef Map XprType; + typedef typename XprType::Scalar Scalar; + // TODO: should check for smaller packet types once we can handle multi-sized packet types + typedef typename packet_traits::type PacketScalar; + + enum { + InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 + ? int(PlainObjectType::InnerStrideAtCompileTime) + : int(StrideType::InnerStrideAtCompileTime), + OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 + ? int(PlainObjectType::OuterStrideAtCompileTime) + : int(StrideType::OuterStrideAtCompileTime), + HasNoInnerStride = InnerStrideAtCompileTime == 1, + HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0, + HasNoStride = HasNoInnerStride && HasNoOuterStride, + IsDynamicSize = PlainObjectType::SizeAtCompileTime == Dynamic, + + PacketAccessMask = bool(HasNoInnerStride) ? ~int(0) : ~int(PacketAccessBit), + LinearAccessMask = + bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime) ? ~int(0) : ~int(LinearAccessBit), + Flags = int(evaluator::Flags) & (LinearAccessMask & PacketAccessMask), + + Alignment = int(MapOptions) & int(AlignedMask) + }; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& map) + : mapbase_evaluator(map) {} +}; + +// -------------------- Ref -------------------- + +template +struct evaluator> + : public mapbase_evaluator, PlainObjectType> { + typedef Ref XprType; + + enum { + Flags = evaluator>::Flags, + Alignment = evaluator>::Alignment + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const XprType& ref) + : mapbase_evaluator(ref) {} +}; + +// -------------------- Block -------------------- + +template ::ret> +struct block_evaluator; + +template +struct evaluator> + : block_evaluator { + typedef Block XprType; + typedef typename XprType::Scalar Scalar; + // TODO: should check for smaller packet types once we can handle multi-sized packet types + typedef typename packet_traits::type PacketScalar; + + enum { + CoeffReadCost = evaluator::CoeffReadCost, + + RowsAtCompileTime = traits::RowsAtCompileTime, + ColsAtCompileTime = traits::ColsAtCompileTime, + MaxRowsAtCompileTime = traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = traits::MaxColsAtCompileTime, + + ArgTypeIsRowMajor = (int(evaluator::Flags) & RowMajorBit) != 0, + IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1 + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0 + : ArgTypeIsRowMajor, + HasSameStorageOrderAsArgType = (IsRowMajor == ArgTypeIsRowMajor), + InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), + InnerStrideAtCompileTime = HasSameStorageOrderAsArgType ? int(inner_stride_at_compile_time::ret) + : int(outer_stride_at_compile_time::ret), + OuterStrideAtCompileTime = HasSameStorageOrderAsArgType ? int(outer_stride_at_compile_time::ret) + : int(inner_stride_at_compile_time::ret), + MaskPacketAccessBit = (InnerStrideAtCompileTime == 1 || HasSameStorageOrderAsArgType) ? PacketAccessBit : 0, + + FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || + (InnerPanel && (evaluator::Flags & LinearAccessBit))) + ? LinearAccessBit + : 0, + FlagsRowMajorBit = XprType::Flags & RowMajorBit, + Flags0 = evaluator::Flags & ((HereditaryBits & ~RowMajorBit) | DirectAccessBit | MaskPacketAccessBit), + Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit, + + PacketAlignment = unpacket_traits::alignment, + Alignment0 = (InnerPanel && (OuterStrideAtCompileTime != Dynamic) && (OuterStrideAtCompileTime != 0) && + (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) + ? int(PacketAlignment) + : 0, + Alignment = plain_enum_min(evaluator::Alignment, Alignment0) + }; + typedef block_evaluator block_evaluator_type; + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const XprType& block) + : block_evaluator_type(block) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } +}; + +// no direct-access => dispatch to a unary evaluator +template +struct block_evaluator + : unary_evaluator> { + typedef Block XprType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit block_evaluator(const XprType& block) + : unary_evaluator(block) {} +}; + +template +struct unary_evaluator, IndexBased> + : evaluator_base> { + typedef Block XprType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& block) + : m_argImpl(block.nestedExpression()), + m_startRow(block.startRow()), + m_startCol(block.startCol()), + m_linear_offset(ForwardLinearAccess + ? (ArgType::IsRowMajor + ? block.startRow() * block.nestedExpression().cols() + block.startCol() + : block.startCol() * block.nestedExpression().rows() + block.startRow()) + : 0) {} + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + enum { + RowsAtCompileTime = XprType::RowsAtCompileTime, + ForwardLinearAccess = (InnerPanel || int(XprType::IsRowMajor) == int(ArgType::IsRowMajor)) && + bool(evaluator::Flags & LinearAccessBit) + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return linear_coeff_impl(index, bool_constant()); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return linear_coeffRef_impl(index, bool_constant()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_argImpl.template packet(m_startRow.value() + row, m_startCol.value() + col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + if (ForwardLinearAccess) + return m_argImpl.template packet(m_linear_offset.value() + index); + else + return packet(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + return m_argImpl.template writePacket(m_startRow.value() + row, m_startCol.value() + col, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + if (ForwardLinearAccess) + return m_argImpl.template writePacket(m_linear_offset.value() + index, x); + else + return writePacket(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, + x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_argImpl.template packetSegment(m_startRow.value() + row, m_startCol.value() + col, + begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + if (ForwardLinearAccess) + return m_argImpl.template packetSegment(m_linear_offset.value() + index, begin, count); + else + return packetSegment(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, + begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + return m_argImpl.template writePacketSegment(m_startRow.value() + row, + m_startCol.value() + col, x, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + if (ForwardLinearAccess) + return m_argImpl.template writePacketSegment(m_linear_offset.value() + index, x, begin, + count); + else + return writePacketSegment(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, x, begin, count); + } + + protected: + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType + linear_coeff_impl(Index index, internal::true_type /* ForwardLinearAccess */) const { + return m_argImpl.coeff(m_linear_offset.value() + index); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType + linear_coeff_impl(Index index, internal::false_type /* not ForwardLinearAccess */) const { + return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& linear_coeffRef_impl( + Index index, internal::true_type /* ForwardLinearAccess */) { + return m_argImpl.coeffRef(m_linear_offset.value() + index); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& linear_coeffRef_impl( + Index index, internal::false_type /* not ForwardLinearAccess */) { + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + } + + evaluator m_argImpl; + const variable_if_dynamic m_startRow; + const variable_if_dynamic m_startCol; + const variable_if_dynamic m_linear_offset; +}; + +// TODO: This evaluator does not actually use the child evaluator; +// all action is via the data() as returned by the Block expression. + +template +struct block_evaluator + : mapbase_evaluator, + typename Block::PlainObject> { + typedef Block XprType; + typedef typename XprType::Scalar Scalar; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit block_evaluator(const XprType& block) + : mapbase_evaluator(block) { + eigen_internal_assert((internal::is_constant_evaluated() || + (std::uintptr_t(block.data()) % plain_enum_max(1, evaluator::Alignment)) == 0) && + "data is not aligned"); + } +}; + +// -------------------- Replicate -------------------- + +template +struct unary_evaluator> + : evaluator_base> { + typedef Replicate XprType; + typedef typename XprType::CoeffReturnType CoeffReturnType; + enum { Factor = (RowFactor == Dynamic || ColFactor == Dynamic) ? Dynamic : RowFactor * ColFactor }; + typedef typename nested_eval::type ArgTypeNested; + typedef remove_all_t ArgTypeNestedCleaned; + + enum { + CoeffReadCost = evaluator::CoeffReadCost, + LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0, + Flags = (evaluator::Flags & (HereditaryBits | LinearAccessMask) & ~RowMajorBit) | + (traits::Flags & RowMajorBit), + + Alignment = evaluator::Alignment + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& replicate) + : m_arg(replicate.nestedExpression()), + m_argImpl(m_arg), + m_rows(replicate.nestedExpression().rows()), + m_cols(replicate.nestedExpression().cols()) {} + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + // try to avoid using modulo; this is a pure optimization strategy + const Index actual_row = traits::RowsAtCompileTime == 1 ? 0 : RowFactor == 1 ? row : row % m_rows.value(); + const Index actual_col = traits::ColsAtCompileTime == 1 ? 0 : ColFactor == 1 ? col : col % m_cols.value(); + + return m_argImpl.coeff(actual_row, actual_col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + // try to avoid using modulo; this is a pure optimization strategy + const Index actual_index = traits::RowsAtCompileTime == 1 + ? (ColFactor == 1 ? index : index % m_cols.value()) + : (RowFactor == 1 ? index : index % m_rows.value()); + + return m_argImpl.coeff(actual_index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + const Index actual_row = traits::RowsAtCompileTime == 1 ? 0 : RowFactor == 1 ? row : row % m_rows.value(); + const Index actual_col = traits::ColsAtCompileTime == 1 ? 0 : ColFactor == 1 ? col : col % m_cols.value(); + + return m_argImpl.template packet(actual_row, actual_col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + const Index actual_index = traits::RowsAtCompileTime == 1 + ? (ColFactor == 1 ? index : index % m_cols.value()) + : (RowFactor == 1 ? index : index % m_rows.value()); + + return m_argImpl.template packet(actual_index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + const Index actual_row = traits::RowsAtCompileTime == 1 ? 0 : RowFactor == 1 ? row : row % m_rows.value(); + const Index actual_col = traits::ColsAtCompileTime == 1 ? 0 : ColFactor == 1 ? col : col % m_cols.value(); + + return m_argImpl.template packetSegment(actual_row, actual_col, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + const Index actual_index = traits::RowsAtCompileTime == 1 + ? (ColFactor == 1 ? index : index % m_cols.value()) + : (RowFactor == 1 ? index : index % m_rows.value()); + + return m_argImpl.template packetSegment(actual_index, begin, count); + } + + protected: + const ArgTypeNested m_arg; + evaluator m_argImpl; + const variable_if_dynamic m_rows; + const variable_if_dynamic m_cols; +}; + +// -------------------- MatrixWrapper and ArrayWrapper -------------------- +// +// evaluator_wrapper_base is a common base class for the +// MatrixWrapper and ArrayWrapper evaluators. + +template +struct evaluator_wrapper_base : evaluator_base { + typedef remove_all_t ArgType; + enum { + CoeffReadCost = evaluator::CoeffReadCost, + Flags = evaluator::Flags, + Alignment = evaluator::Alignment + }; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {} + + typedef typename ArgType::Scalar Scalar; + typedef typename ArgType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_argImpl.coeff(row, col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_argImpl.coeff(index); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_argImpl.coeffRef(row, col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return m_argImpl.template packet(row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_argImpl.template packet(index); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + m_argImpl.template writePacket(row, col, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + m_argImpl.template writePacket(index, x); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return m_argImpl.template packetSegment(row, col, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + return m_argImpl.template packetSegment(index, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + m_argImpl.template writePacketSegment(row, col, x, begin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + m_argImpl.template writePacketSegment(index, x, begin, count); + } + + protected: + evaluator m_argImpl; +}; + +template +struct unary_evaluator> : evaluator_wrapper_base> { + typedef MatrixWrapper XprType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& wrapper) + : evaluator_wrapper_base>(wrapper.nestedExpression()) {} +}; + +template +struct unary_evaluator> : evaluator_wrapper_base> { + typedef ArrayWrapper XprType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& wrapper) + : evaluator_wrapper_base>(wrapper.nestedExpression()) {} +}; + +// -------------------- Reverse -------------------- + +// defined in Reverse.h: +template +struct reverse_packet_cond; + +template +struct unary_evaluator> : evaluator_base> { + typedef Reverse XprType; + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + enum { + IsRowMajor = XprType::IsRowMajor, + IsColMajor = !IsRowMajor, + ReverseRow = (Direction == Vertical) || (Direction == BothDirections), + ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), + ReversePacket = (Direction == BothDirections) || ((Direction == Vertical) && IsColMajor) || + ((Direction == Horizontal) && IsRowMajor), + + CoeffReadCost = evaluator::CoeffReadCost, + + // let's enable LinearAccess only with vectorization because of the product overhead + // FIXME: consider enabling DirectAccess with negative strides. + Flags0 = evaluator::Flags, + LinearAccess = + ((Direction == BothDirections) && (int(Flags0) & PacketAccessBit)) || + ((ReverseRow && XprType::ColsAtCompileTime == 1) || (ReverseCol && XprType::RowsAtCompileTime == 1)) + ? LinearAccessBit + : 0, + + Flags = int(Flags0) & (HereditaryBits | PacketAccessBit | LinearAccess), + + Alignment = 0 // FIXME: in some rare cases, Alignment could be preserved. + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& reverse) + : m_argImpl(reverse.nestedExpression()), + m_rows(ReverseRow ? reverse.nestedExpression().rows() : 1), + m_cols(ReverseCol ? reverse.nestedExpression().cols() : 1) {} + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row, ReverseCol ? m_cols.value() - col - 1 : col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row, ReverseCol ? m_cols.value() - col - 1 : col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1; + static constexpr int OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1; + using reverse_packet = reverse_packet_cond; + + Index actualRow = ReverseRow ? m_rows.value() - row - OffsetRow : row; + Index actualCol = ReverseCol ? m_cols.value() - col - OffsetCol : col; + + return reverse_packet::run(m_argImpl.template packet(actualRow, actualCol)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + static constexpr int PacketSize = unpacket_traits::size; + + Index actualIndex = m_rows.value() * m_cols.value() - index - PacketSize; + + return preverse(m_argImpl.template packet(actualIndex)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketType& x) { + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1; + static constexpr int OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1; + using reverse_packet = reverse_packet_cond; + + Index actualRow = ReverseRow ? m_rows.value() - row - OffsetRow : row; + Index actualCol = ReverseCol ? m_cols.value() - col - OffsetCol : col; + + m_argImpl.template writePacket(actualRow, actualCol, reverse_packet::run(x)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { + static constexpr int PacketSize = unpacket_traits::size; + + Index actualIndex = m_rows.value() * m_cols.value() - index - PacketSize; + + m_argImpl.template writePacket(actualIndex, preverse(x)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1; + static constexpr int OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1; + using reverse_packet = reverse_packet_cond; + + Index actualRow = ReverseRow ? m_rows.value() - row - OffsetRow : row; + Index actualCol = ReverseCol ? m_cols.value() - col - OffsetCol : col; + Index actualBegin = ReversePacket ? (PacketSize - count - begin) : begin; + + return reverse_packet::run( + m_argImpl.template packetSegment(actualRow, actualCol, actualBegin, count)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + static constexpr int PacketSize = unpacket_traits::size; + + Index actualIndex = m_rows.value() * m_cols.value() - index - PacketSize; + Index actualBegin = PacketSize - count - begin; + + return preverse(m_argImpl.template packetSegment(actualIndex, actualBegin, count)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index row, Index col, const PacketType& x, Index begin, + Index count) { + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1; + static constexpr int OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1; + using reverse_packet = reverse_packet_cond; + + Index actualRow = ReverseRow ? m_rows.value() - row - OffsetRow : row; + Index actualCol = ReverseCol ? m_cols.value() - col - OffsetCol : col; + Index actualBegin = ReversePacket ? (PacketSize - count - begin) : begin; + + m_argImpl.template writePacketSegment(actualRow, actualCol, reverse_packet::run(x), actualBegin, count); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacketSegment(Index index, const PacketType& x, Index begin, + Index count) { + static constexpr int PacketSize = unpacket_traits::size; + + Index actualIndex = m_rows.value() * m_cols.value() - index - PacketSize; + Index actualBegin = PacketSize - count - begin; + + m_argImpl.template writePacketSegment(actualIndex, preverse(x), actualBegin, count); + } + + protected: + evaluator m_argImpl; + + // If we do not reverse rows, then we do not need to know the number of rows; same for columns + // Nonetheless, in this case it is important to set to 1 such that the coeff(index) method works fine for vectors. + const variable_if_dynamic m_rows; + const variable_if_dynamic m_cols; +}; + +// -------------------- Diagonal -------------------- + +template +struct evaluator> : evaluator_base> { + typedef Diagonal XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost, + + Flags = + (unsigned int)(evaluator::Flags & (HereditaryBits | DirectAccessBit) & ~RowMajorBit) | LinearAccessBit, + + Alignment = 0 + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit evaluator(const XprType& diagonal) + : m_argImpl(diagonal.nestedExpression()), m_index(diagonal.index()) {} + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index) const { + return m_argImpl.coeff(row + rowOffset(), row + colOffset()); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + return m_argImpl.coeff(index + rowOffset(), index + colOffset()); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index) { + return m_argImpl.coeffRef(row + rowOffset(), row + colOffset()); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return m_argImpl.coeffRef(index + rowOffset(), index + colOffset()); + } + + protected: + evaluator m_argImpl; + const variable_if_dynamicindex m_index; + + private: + EIGEN_DEVICE_FUNC constexpr Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); } + EIGEN_DEVICE_FUNC constexpr Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; } +}; + +//---------------------------------------------------------------------- +// deprecated code +//---------------------------------------------------------------------- + +// -------------------- EvalToTemp -------------------- + +// expression class for evaluating nested expression to a temporary + +template +class EvalToTemp; + +template +struct traits> : public traits {}; + +template +class EvalToTemp : public dense_xpr_base>::type { + public: + typedef typename dense_xpr_base::type Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp) + + explicit EvalToTemp(const ArgType& arg) : m_arg(arg) {} + + const ArgType& arg() const { return m_arg; } + + constexpr Index rows() const noexcept { return m_arg.rows(); } + + constexpr Index cols() const noexcept { return m_arg.cols(); } + + private: + const ArgType& m_arg; +}; + +template +struct evaluator> : public evaluator { + typedef EvalToTemp XprType; + typedef typename ArgType::PlainObject PlainObject; + typedef evaluator Base; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& xpr) : m_result(xpr.arg()) { + internal::construct_at(this, m_result); + } + + // This constructor is used when nesting an EvalTo evaluator in another evaluator + EIGEN_DEVICE_FUNC constexpr evaluator(const ArgType& arg) : m_result(arg) { + internal::construct_at(this, m_result); + } + + protected: + PlainObject m_result; +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_COREEVALUATORS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreIterators.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreIterators.h new file mode 100644 index 0000000..f62cf23 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CoreIterators.h @@ -0,0 +1,141 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_COREITERATORS_H +#define EIGEN_COREITERATORS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core + */ + +namespace internal { + +template +class inner_iterator_selector; + +} + +/** \class InnerIterator + * \brief An InnerIterator allows to loop over the element of any matrix expression. + * + * \warning To be used with care because an evaluator is constructed every time an InnerIterator iterator is + * constructed. + * + * TODO: add a usage example + */ +template +class InnerIterator { + protected: + typedef internal::inner_iterator_selector::Kind> IteratorType; + typedef internal::evaluator EvaluatorType; + typedef typename internal::traits::Scalar Scalar; + + public: + /** Construct an iterator over the \a outerId -th row or column of \a xpr */ + InnerIterator(const XprType &xpr, const Index &outerId) : m_eval(xpr), m_iter(m_eval, outerId, xpr.innerSize()) {} + + /// \returns the value of the current coefficient. + EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); } + /** Increment the iterator \c *this to the next non-zero coefficient. + * Explicit zeros are not skipped over. To skip explicit zeros, see class SparseView + */ + EIGEN_STRONG_INLINE InnerIterator &operator++() { + m_iter.operator++(); + return *this; + } + EIGEN_STRONG_INLINE InnerIterator &operator+=(Index i) { + m_iter.operator+=(i); + return *this; + } + EIGEN_STRONG_INLINE InnerIterator operator+(Index i) { + InnerIterator result(*this); + result += i; + return result; + } + + /// \returns the column or row index of the current coefficient. + EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); } + /// \returns the row index of the current coefficient. + EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); } + /// \returns the column index of the current coefficient. + EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); } + /// \returns \c true if the iterator \c *this still references a valid coefficient. + EIGEN_STRONG_INLINE operator bool() const { return m_iter; } + + protected: + EvaluatorType m_eval; + IteratorType m_iter; + + private: + // If you get here, then you're not using the right InnerIterator type, e.g.: + // SparseMatrix A; + // SparseMatrix::InnerIterator it(A,0); + template + InnerIterator(const EigenBase &, Index outer); +}; + +namespace internal { + +// Generic inner iterator implementation for dense objects +template +class inner_iterator_selector { + protected: + typedef evaluator EvaluatorType; + typedef typename traits::Scalar Scalar; + enum { IsRowMajor = (XprType::Flags & RowMajorBit) == RowMajorBit }; + + public: + EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, const Index &innerSize) + : m_eval(eval), m_inner(0), m_outer(outerId), m_end(innerSize) {} + + EIGEN_STRONG_INLINE Scalar value() const { + return (IsRowMajor) ? m_eval.coeff(m_outer, m_inner) : m_eval.coeff(m_inner, m_outer); + } + + EIGEN_STRONG_INLINE inner_iterator_selector &operator++() { + m_inner++; + return *this; + } + + EIGEN_STRONG_INLINE Index index() const { return m_inner; } + inline Index row() const { return IsRowMajor ? m_outer : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer; } + + EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner >= 0; } + + protected: + const EvaluatorType &m_eval; + Index m_inner; + const Index m_outer; + const Index m_end; +}; + +// For iterator-based evaluator, inner-iterator is already implemented as +// evaluator<>::InnerIterator +template +class inner_iterator_selector : public evaluator::InnerIterator { + protected: + typedef typename evaluator::InnerIterator Base; + typedef evaluator EvaluatorType; + + public: + EIGEN_STRONG_INLINE inner_iterator_selector(const EvaluatorType &eval, const Index &outerId, + const Index & /*innerSize*/) + : Base(eval, outerId) {} +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_COREITERATORS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseBinaryOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseBinaryOp.h new file mode 100644 index 0000000..27fd434 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseBinaryOp.h @@ -0,0 +1,166 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CWISE_BINARY_OP_H +#define EIGEN_CWISE_BINARY_OP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits> { + // we must not inherit from traits since it has + // the potential to cause problems with MSVC + typedef remove_all_t Ancestor; + typedef typename traits::XprKind XprKind; + enum { + RowsAtCompileTime = traits::RowsAtCompileTime, + ColsAtCompileTime = traits::ColsAtCompileTime, + MaxRowsAtCompileTime = traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = traits::MaxColsAtCompileTime + }; + + // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor), + // we still want to handle the case when the result type is different. + typedef typename result_of::type Scalar; + typedef typename cwise_promote_storage_type::StorageKind, typename traits::StorageKind, + BinaryOp>::ret StorageKind; + typedef typename promote_index_type::StorageIndex, typename traits::StorageIndex>::type + StorageIndex; + typedef typename Lhs::Nested LhsNested; + typedef typename Rhs::Nested RhsNested; + typedef std::remove_reference_t LhsNested_; + typedef std::remove_reference_t RhsNested_; + enum { + Flags = cwise_promote_storage_order::StorageKind, typename traits::StorageKind, + LhsNested_::Flags & RowMajorBit, RhsNested_::Flags & RowMajorBit>::value + }; +}; +} // end namespace internal + +template +class CwiseBinaryOpImpl; + +/** \class CwiseBinaryOp + * \ingroup Core_Module + * + * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions + * + * \tparam BinaryOp template functor implementing the operator + * \tparam LhsType the type of the left-hand side + * \tparam RhsType the type of the right-hand side + * + * This class represents an expression where a coefficient-wise binary operator is applied to two expressions. + * It is the return type of binary operators, by which we mean only those binary operators where + * both the left-hand side and the right-hand side are Eigen expressions. + * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp. + * + * Most of the time, this is the only way that it is used, so you typically don't have to name + * CwiseBinaryOp types explicitly. + * + * \sa MatrixBase::binaryExpr(const MatrixBase &,const CustomBinaryOp &) const, class CwiseUnaryOp, class + * CwiseNullaryOp + */ +template +class CwiseBinaryOp : public CwiseBinaryOpImpl::StorageKind, + typename internal::traits::StorageKind, BinaryOp>::ret>, + internal::no_assignment_operator { + public: + typedef internal::remove_all_t Functor; + typedef internal::remove_all_t Lhs; + typedef internal::remove_all_t Rhs; + + typedef typename CwiseBinaryOpImpl< + BinaryOp, LhsType, RhsType, + typename internal::cwise_promote_storage_type::StorageKind, + typename internal::traits::StorageKind, BinaryOp>::ret>::Base + Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp) + + EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp, typename Lhs::Scalar, typename Rhs::Scalar) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) + + typedef typename internal::ref_selector::type LhsNested; + typedef typename internal::ref_selector::type RhsNested; + typedef std::remove_reference_t LhsNested_; + typedef std::remove_reference_t RhsNested_; + +#if EIGEN_COMP_MSVC + // Required for Visual Studio, which may fail to inline the copy constructor otherwise. + EIGEN_STRONG_INLINE CwiseBinaryOp(const CwiseBinaryOp&) = default; +#endif + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, + const BinaryOp& func = BinaryOp()) + : m_lhs(aLhs), m_rhs(aRhs), m_functor(func) { + eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()); + } + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { + // return the fixed size type if available to enable compile time optimizations + return internal::traits>::RowsAtCompileTime == Dynamic ? m_rhs.rows() + : m_lhs.rows(); + } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { + // return the fixed size type if available to enable compile time optimizations + return internal::traits>::ColsAtCompileTime == Dynamic ? m_rhs.cols() + : m_lhs.cols(); + } + + /** \returns the left hand side nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const LhsNested_& lhs() const { return m_lhs; } + /** \returns the right hand side nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const RhsNested_& rhs() const { return m_rhs; } + /** \returns the functor representing the binary operation */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const BinaryOp& functor() const { return m_functor; } + + protected: + LhsNested m_lhs; + RhsNested m_rhs; + const BinaryOp m_functor; +}; + +// Generic API dispatcher +template +class CwiseBinaryOpImpl : public internal::generic_xpr_base>::type { + public: + typedef typename internal::generic_xpr_base>::type Base; +}; + +/** replaces \c *this by \c *this - \a other. + * + * \returns a reference to \c *this + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Derived& MatrixBase::operator-=(const MatrixBase& other) { + call_assignment(derived(), other.derived(), internal::sub_assign_op()); + return derived(); +} + +/** replaces \c *this by \c *this + \a other. + * + * \returns a reference to \c *this + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Derived& MatrixBase::operator+=(const MatrixBase& other) { + call_assignment(derived(), other.derived(), internal::add_assign_op()); + return derived(); +} + +} // end namespace Eigen + +#endif // EIGEN_CWISE_BINARY_OP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseNullaryOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseNullaryOp.h new file mode 100644 index 0000000..7e117b6 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseNullaryOp.h @@ -0,0 +1,975 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CWISE_NULLARY_OP_H +#define EIGEN_CWISE_NULLARY_OP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : traits { + enum { Flags = traits::Flags & RowMajorBit }; +}; + +} // namespace internal + +/** \class CwiseNullaryOp + * \ingroup Core_Module + * + * \brief Generic expression of a matrix where all coefficients are defined by a functor + * + * \tparam NullaryOp template functor implementing the operator + * \tparam PlainObjectType the underlying plain matrix/array type + * + * This class represents an expression of a generic nullary operator. + * It is the return type of the Ones(), Zero(), Constant(), Identity() and Random() methods, + * and most of the time this is the only way it is used. + * + * However, if you want to write a function returning such an expression, you + * will need to use this class. + * + * The functor NullaryOp must expose one of the following method: + + +
\c operator()() if the procedural generation does not depend on the coefficient entries + (e.g., random numbers)
\c operator()(Index i)if the procedural generation makes + sense for vectors only and that it depends on the coefficient index \c i (e.g., linspace)
\c + operator()(Index i,Index j)if the procedural generation depends on the matrix coordinates \c i, \c j (e.g., + to generate a checkerboard with 0 and 1)
+ * It is also possible to expose the last two operators if the generation makes sense for matrices but can be optimized + for vectors. + * + * See DenseBase::NullaryExpr(Index,const CustomNullaryOp&) for an example binding + * C++11 random number generators. + * + * A nullary expression can also be used to implement custom sophisticated matrix manipulations + * that cannot be covered by the existing set of natively supported matrix manipulations. + * See this \ref TopicCustomizing_NullaryExpr "page" for some examples and additional explanations + * on the behavior of CwiseNullaryOp. + * + * \sa class CwiseUnaryOp, class CwiseBinaryOp, DenseBase::NullaryExpr + */ +template +class CwiseNullaryOp : public internal::dense_xpr_base >::type, + internal::no_assignment_operator { + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp) + + EIGEN_DEVICE_FUNC constexpr CwiseNullaryOp(Index rows, Index cols, const NullaryOp& func = NullaryOp()) + : m_rows(rows), m_cols(cols), m_functor(func) { + eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 && + (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); + } + EIGEN_DEVICE_FUNC constexpr CwiseNullaryOp(Index size, const NullaryOp& func = NullaryOp()) + : CwiseNullaryOp(RowsAtCompileTime == 1 ? 1 : size, RowsAtCompileTime == 1 ? size : 1, func) { + EIGEN_STATIC_ASSERT(CwiseNullaryOp::IsVectorAtCompileTime, YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX); + } + + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows.value(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols.value(); } + + /** \returns the functor representing the nullary operation */ + EIGEN_DEVICE_FUNC constexpr const NullaryOp& functor() const { return m_functor; } + + protected: + const internal::variable_if_dynamic m_rows; + const internal::variable_if_dynamic m_cols; + const NullaryOp m_functor; +}; + +/** \returns an expression of a matrix defined by a custom functor \a func + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this MatrixBase type. + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so NullaryExpr(const CustomNullaryOp&) should be used + * instead. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * \sa class CwiseNullaryOp + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +#ifndef EIGEN_PARSED_BY_DOXYGEN + const CwiseNullaryOp::PlainObject> +#else + const CwiseNullaryOp +#endif + DenseBase::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func) { + return CwiseNullaryOp(rows, cols, func); +} + +/** \returns an expression of a matrix defined by a custom functor \a func + * + * The parameter \a size is the size of the returned vector. + * Must be compatible with this MatrixBase type. + * + * \only_for_vectors + * + * This variant is meant to be used for dynamic-size vector types. For fixed-size types, + * it is redundant to pass \a size as argument, so NullaryExpr(const CustomNullaryOp&) should be used + * instead. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * Here is an example with C++11 random generators: \include random_cpp11.cpp + * Output: \verbinclude random_cpp11.out + * + * \sa class CwiseNullaryOp + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +#ifndef EIGEN_PARSED_BY_DOXYGEN + const CwiseNullaryOp::PlainObject> +#else + const CwiseNullaryOp +#endif + DenseBase::NullaryExpr(Index size, const CustomNullaryOp& func) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + if (RowsAtCompileTime == 1) + return CwiseNullaryOp(1, size, func); + else + return CwiseNullaryOp(size, 1, func); +} + +/** \returns an expression of a matrix defined by a custom functor \a func + * + * This variant is only for fixed-size DenseBase types. For dynamic-size types, you + * need to use the variants taking size arguments. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * \sa class CwiseNullaryOp + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +#ifndef EIGEN_PARSED_BY_DOXYGEN + const CwiseNullaryOp::PlainObject> +#else + const CwiseNullaryOp +#endif + DenseBase::NullaryExpr(const CustomNullaryOp& func) { + return CwiseNullaryOp(RowsAtCompileTime, ColsAtCompileTime, func); +} + +/** \returns an expression of a constant matrix of value \a value + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this DenseBase type. + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so Constant(const Scalar&) should be used + * instead. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * \sa class CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +DenseBase::Constant(Index rows, Index cols, const Scalar& value) { + return DenseBase::NullaryExpr(rows, cols, internal::scalar_constant_op(value)); +} + +/** \returns an expression of a constant matrix of value \a value + * + * The parameter \a size is the size of the returned vector. + * Must be compatible with this DenseBase type. + * + * \only_for_vectors + * + * This variant is meant to be used for dynamic-size vector types. For fixed-size types, + * it is redundant to pass \a size as argument, so Constant(const Scalar&) should be used + * instead. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * \sa class CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +DenseBase::Constant(Index size, const Scalar& value) { + return DenseBase::NullaryExpr(size, internal::scalar_constant_op(value)); +} + +/** \returns an expression of a constant matrix of value \a value + * + * This variant is only for fixed-size DenseBase types. For dynamic-size types, you + * need to use the variants taking size arguments. + * + * The template parameter \a CustomNullaryOp is the type of the functor. + * + * \sa class CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +DenseBase::Constant(const Scalar& value) { + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return DenseBase::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, + internal::scalar_constant_op(value)); +} + +/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(Index,const Scalar&,const Scalar&) + * + * \only_for_vectors + * + * Example: \include DenseBase_LinSpaced_seq_deprecated.cpp + * Output: \verbinclude DenseBase_LinSpaced_seq_deprecated.out + * + * \sa LinSpaced(Index,const Scalar&, const Scalar&), setLinSpaced(Index,const Scalar&,const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return DenseBase::NullaryExpr(size, internal::linspaced_op(low, high, size)); +} + +/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(const Scalar&,const Scalar&) + * + * \sa LinSpaced(const Scalar&, const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return DenseBase::NullaryExpr(Derived::SizeAtCompileTime, + internal::linspaced_op(low, high, Derived::SizeAtCompileTime)); +} + +/** + * \brief Sets a linearly spaced vector. + * + * The function generates 'size' equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. + * + * \only_for_vectors + * + * Example: \include DenseBase_LinSpaced.cpp + * Output: \verbinclude DenseBase_LinSpaced.out + * + * For integer scalar types, an even spacing is possible if and only if the length of the range, + * i.e., \c high-low is a scalar multiple of \c size-1, or if \c size is a scalar multiple of the + * number of values \c high-low+1 (meaning each value can be repeated the same number of time). + * If one of these two considions is not satisfied, then \c high is lowered to the largest value + * satisfying one of this constraint. + * Here are some examples: + * + * Example: \include DenseBase_LinSpacedInt.cpp + * Output: \verbinclude DenseBase_LinSpacedInt.out + * + * \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return DenseBase::NullaryExpr(size, internal::linspaced_op(low, high, size)); +} + +/** + * \copydoc DenseBase::LinSpaced(Index, const DenseBase::Scalar&, const DenseBase::Scalar&) + * Special version for fixed size types which does not require the size parameter. + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +DenseBase::LinSpaced(const Scalar& low, const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return DenseBase::NullaryExpr(Derived::SizeAtCompileTime, + internal::linspaced_op(low, high, Derived::SizeAtCompileTime)); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessEqualSpacedReturnType +DenseBase::EqualSpaced(Index size, const Scalar& low, const Scalar& step) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return DenseBase::NullaryExpr(size, internal::equalspaced_op(low, step)); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessEqualSpacedReturnType +DenseBase::EqualSpaced(const Scalar& low, const Scalar& step) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return DenseBase::NullaryExpr(Derived::SizeAtCompileTime, internal::equalspaced_op(low, step)); +} + +/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */ +template +EIGEN_DEVICE_FUNC bool DenseBase::isApproxToConstant(const Scalar& val, const RealScalar& prec) const { + typename internal::nested_eval::type self(derived()); + for (Index j = 0; j < cols(); ++j) + for (Index i = 0; i < rows(); ++i) + if (!internal::isApprox(self.coeff(i, j), val, prec)) return false; + return true; +} + +/** This is just an alias for isApproxToConstant(). + * + * \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ +template +EIGEN_DEVICE_FUNC bool DenseBase::isConstant(const Scalar& val, const RealScalar& prec) const { + return isApproxToConstant(val, prec); +} + +/** Alias for setConstant(): sets all coefficients in this expression to \a val. + * + * \sa setConstant(), Constant(), class CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) { + setConstant(val); +} + +/** Sets all coefficients in this expression to value \a val. + * + * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), + * Constant(), class CwiseNullaryOp, setZero(), setOnes() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) { + internal::eigen_fill_impl::run(derived(), val); + return derived(); +} + +/** Resizes to the given \a size, and sets all coefficients in this expression to the given value \a val. + * + * \only_for_vectors + * + * Example: \include Matrix_setConstant_int.cpp + * Output: \verbinclude Matrix_setConstant_int.out + * + * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, + * MatrixBase::Constant(const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index size, const Scalar& val) { + resize(size); + return setConstant(val); +} + +/** Resizes to the given size, and sets all coefficients in this expression to the given value \a val. + * + * \param rows the new number of rows + * \param cols the new number of columns + * \param val the value to which all coefficients are set + * + * Example: \include Matrix_setConstant_int_int.cpp + * Output: \verbinclude Matrix_setConstant_int_int.out + * + * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, + * MatrixBase::Constant(const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index rows, Index cols, + const Scalar& val) { + resize(rows, cols); + return setConstant(val); +} + +/** Resizes to the given size, changing only the number of columns, and sets all + * coefficients in this expression to the given value \a val. For the parameter + * of type NoChange_t, just pass the special value \c NoChange. + * + * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, + * MatrixBase::Constant(const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(NoChange_t, Index cols, + const Scalar& val) { + return setConstant(rows(), cols, val); +} + +/** Resizes to the given size, changing only the number of rows, and sets all + * coefficients in this expression to the given value \a val. For the parameter + * of type NoChange_t, just pass the special value \c NoChange. + * + * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, + * MatrixBase::Constant(const Scalar&) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index rows, NoChange_t, + const Scalar& val) { + return setConstant(rows, cols(), val); +} + +/** + * \brief Sets a linearly spaced vector. + * + * The function generates 'size' equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. + * + * \only_for_vectors + * + * Example: \include DenseBase_setLinSpaced.cpp + * Output: \verbinclude DenseBase_setLinSpaced.out + * + * For integer scalar types, do not miss the explanations on the definition + * of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink. + * + * \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, + const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op(low, high, newSize)); +} + +/** + * \brief Sets a linearly spaced vector. + * + * The function fills \c *this with equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. + * + * \only_for_vectors + * + * For integer scalar types, do not miss the explanations on the definition + * of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink. + * + * \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return setLinSpaced(size(), low, high); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setEqualSpaced(Index newSize, const Scalar& low, + const Scalar& step) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return derived() = Derived::NullaryExpr(newSize, internal::equalspaced_op(low, step)); +} +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setEqualSpaced(const Scalar& low, + const Scalar& step) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return setEqualSpaced(size(), low, step); +} + +// zero: + +/** \returns an expression of a zero matrix. + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this MatrixBase type. + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used + * instead. + * + * Example: \include MatrixBase_zero_int_int.cpp + * Output: \verbinclude MatrixBase_zero_int_int.out + * + * \sa Zero(), Zero(Index) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ZeroReturnType DenseBase::Zero( + Index rows, Index cols) { + return ZeroReturnType(rows, cols); +} + +/** \returns an expression of a zero vector. + * + * The parameter \a size is the size of the returned vector. + * Must be compatible with this MatrixBase type. + * + * \only_for_vectors + * + * This variant is meant to be used for dynamic-size vector types. For fixed-size types, + * it is redundant to pass \a size as argument, so Zero() should be used + * instead. + * + * Example: \include MatrixBase_zero_int.cpp + * Output: \verbinclude MatrixBase_zero_int.out + * + * \sa Zero(), Zero(Index,Index) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ZeroReturnType DenseBase::Zero( + Index size) { + return ZeroReturnType(size); +} + +/** \returns an expression of a fixed-size zero matrix or vector. + * + * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you + * need to use the variants taking size arguments. + * + * Example: \include MatrixBase_zero.cpp + * Output: \verbinclude MatrixBase_zero.out + * + * \sa Zero(Index), Zero(Index,Index) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ZeroReturnType DenseBase::Zero() { + return ZeroReturnType(RowsAtCompileTime, ColsAtCompileTime); +} + +/** \returns true if *this is approximately equal to the zero matrix, + * within the precision given by \a prec. + * + * Example: \include MatrixBase_isZero.cpp + * Output: \verbinclude MatrixBase_isZero.out + * + * \sa class CwiseNullaryOp, Zero() + */ +template +EIGEN_DEVICE_FUNC bool DenseBase::isZero(const RealScalar& prec) const { + typename internal::nested_eval::type self(derived()); + for (Index j = 0; j < cols(); ++j) + for (Index i = 0; i < rows(); ++i) + if (!internal::isMuchSmallerThan(self.coeff(i, j), static_cast(1), prec)) return false; + return true; +} + +/** Sets all coefficients in this expression to zero. + * + * Example: \include MatrixBase_setZero.cpp + * Output: \verbinclude MatrixBase_setZero.out + * + * \sa class CwiseNullaryOp, Zero() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setZero() { + internal::eigen_zero_impl::run(derived()); + return derived(); +} + +/** Resizes to the given \a size, and sets all coefficients in this expression to zero. + * + * \only_for_vectors + * + * Example: \include Matrix_setZero_int.cpp + * Output: \verbinclude Matrix_setZero_int.out + * + * \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index newSize) { + resize(newSize); + return setZero(); +} + +/** Resizes to the given size, and sets all coefficients in this expression to zero. + * + * \param rows the new number of rows + * \param cols the new number of columns + * + * Example: \include Matrix_setZero_int_int.cpp + * Output: \verbinclude Matrix_setZero_int_int.out + * + * \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index rows, Index cols) { + resize(rows, cols); + return setZero(); +} + +/** Resizes to the given size, changing only the number of columns, and sets all + * coefficients in this expression to zero. For the parameter of type NoChange_t, + * just pass the special value \c NoChange. + * + * \sa DenseBase::setZero(), setZero(Index), setZero(Index, Index), setZero(Index, NoChange_t), class CwiseNullaryOp, + * DenseBase::Zero() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(NoChange_t, Index cols) { + return setZero(rows(), cols); +} + +/** Resizes to the given size, changing only the number of rows, and sets all + * coefficients in this expression to zero. For the parameter of type NoChange_t, + * just pass the special value \c NoChange. + * + * \sa DenseBase::setZero(), setZero(Index), setZero(Index, Index), setZero(NoChange_t, Index), class CwiseNullaryOp, + * DenseBase::Zero() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index rows, NoChange_t) { + return setZero(rows, cols()); +} + +// ones: + +/** \returns an expression of a matrix where all coefficients equal one. + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this MatrixBase type. + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so Ones() should be used + * instead. + * + * Example: \include MatrixBase_ones_int_int.cpp + * Output: \verbinclude MatrixBase_ones_int_int.out + * + * \sa Ones(), Ones(Index), isOnes(), class Ones + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones( + Index rows, Index cols) { + return Constant(rows, cols, Scalar(1)); +} + +/** \returns an expression of a vector where all coefficients equal one. + * + * The parameter \a newSize is the size of the returned vector. + * Must be compatible with this MatrixBase type. + * + * \only_for_vectors + * + * This variant is meant to be used for dynamic-size vector types. For fixed-size types, + * it is redundant to pass \a size as argument, so Ones() should be used + * instead. + * + * Example: \include MatrixBase_ones_int.cpp + * Output: \verbinclude MatrixBase_ones_int.out + * + * \sa Ones(), Ones(Index,Index), isOnes(), class Ones + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones( + Index newSize) { + return Constant(newSize, Scalar(1)); +} + +/** \returns an expression of a fixed-size matrix or vector where all coefficients equal one. + * + * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you + * need to use the variants taking size arguments. + * + * Example: \include MatrixBase_ones.cpp + * Output: \verbinclude MatrixBase_ones.out + * + * \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones() { + return Constant(Scalar(1)); +} + +/** \returns true if *this is approximately equal to the matrix where all coefficients + * are equal to 1, within the precision given by \a prec. + * + * Example: \include MatrixBase_isOnes.cpp + * Output: \verbinclude MatrixBase_isOnes.out + * + * \sa class CwiseNullaryOp, Ones() + */ +template +EIGEN_DEVICE_FUNC bool DenseBase::isOnes(const RealScalar& prec) const { + return isApproxToConstant(Scalar(1), prec); +} + +/** Sets all coefficients in this expression to one. + * + * Example: \include MatrixBase_setOnes.cpp + * Output: \verbinclude MatrixBase_setOnes.out + * + * \sa class CwiseNullaryOp, Ones() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() { + return setConstant(Scalar(1)); +} + +/** Resizes to the given \a newSize, and sets all coefficients in this expression to one. + * + * \only_for_vectors + * + * Example: \include Matrix_setOnes_int.cpp + * Output: \verbinclude Matrix_setOnes_int.out + * + * \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index newSize) { + resize(newSize); + return setConstant(Scalar(1)); +} + +/** Resizes to the given size, and sets all coefficients in this expression to one. + * + * \param rows the new number of rows + * \param cols the new number of columns + * + * Example: \include Matrix_setOnes_int_int.cpp + * Output: \verbinclude Matrix_setOnes_int_int.out + * + * \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index rows, Index cols) { + resize(rows, cols); + return setConstant(Scalar(1)); +} + +/** Resizes to the given size, changing only the number of rows, and sets all + * coefficients in this expression to one. For the parameter of type NoChange_t, + * just pass the special value \c NoChange. + * + * \sa MatrixBase::setOnes(), setOnes(Index), setOnes(Index, Index), setOnes(NoChange_t, Index), class CwiseNullaryOp, + * MatrixBase::Ones() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index rows, NoChange_t) { + return setOnes(rows, cols()); +} + +/** Resizes to the given size, changing only the number of columns, and sets all + * coefficients in this expression to one. For the parameter of type NoChange_t, + * just pass the special value \c NoChange. + * + * \sa MatrixBase::setOnes(), setOnes(Index), setOnes(Index, Index), setOnes(Index, NoChange_t) class CwiseNullaryOp, + * MatrixBase::Ones() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(NoChange_t, Index cols) { + return setOnes(rows(), cols); +} + +// Identity: + +/** \returns an expression of the identity matrix (not necessarily square). + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this MatrixBase type. + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so Identity() should be used + * instead. + * + * Example: \include MatrixBase_identity_int_int.cpp + * Output: \verbinclude MatrixBase_identity_int_int.out + * + * \sa Identity(), setIdentity(), isIdentity() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +MatrixBase::Identity(Index rows, Index cols) { + return DenseBase::NullaryExpr(rows, cols, internal::scalar_identity_op()); +} + +/** \returns an expression of the identity matrix (not necessarily square). + * + * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you + * need to use the variant taking size arguments. + * + * Example: \include MatrixBase_identity.cpp + * Output: \verbinclude MatrixBase_identity.out + * + * \sa Identity(Index,Index), setIdentity(), isIdentity() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +MatrixBase::Identity() { + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return MatrixBase::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_identity_op()); +} + +/** \returns true if *this is approximately equal to the identity matrix + * (not necessarily square), + * within the precision given by \a prec. + * + * Example: \include MatrixBase_isIdentity.cpp + * Output: \verbinclude MatrixBase_isIdentity.out + * + * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), setIdentity() + */ +template +bool MatrixBase::isIdentity(const RealScalar& prec) const { + typename internal::nested_eval::type self(derived()); + for (Index j = 0; j < cols(); ++j) { + for (Index i = 0; i < rows(); ++i) { + if (i == j) { + if (!internal::isApprox(self.coeff(i, j), static_cast(1), prec)) return false; + } else { + if (!internal::isMuchSmallerThan(self.coeff(i, j), static_cast(1), prec)) return false; + } + } + } + return true; +} + +namespace internal { + +template = 16)> +struct setIdentity_impl { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Derived& run(Derived& m) { + return m = Derived::Identity(m.rows(), m.cols()); + } +}; + +template +struct setIdentity_impl { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Derived& run(Derived& m) { + m.setZero(); + const Index size = numext::mini(m.rows(), m.cols()); + for (Index i = 0; i < size; ++i) m.coeffRef(i, i) = typename Derived::Scalar(1); + return m; + } +}; + +} // end namespace internal + +/** Writes the identity expression (not necessarily square) into *this. + * + * Example: \include MatrixBase_setIdentity.cpp + * Output: \verbinclude MatrixBase_setIdentity.out + * + * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() { + return internal::setIdentity_impl::run(derived()); +} + +/** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this. + * + * \param rows the new number of rows + * \param cols the new number of columns + * + * Example: \include Matrix_setIdentity_int_int.cpp + * Output: \verbinclude Matrix_setIdentity_int_int.out + * + * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) { + derived().resize(rows, cols); + return setIdentity(); +} + +/** \returns an expression of the i-th unit (basis) vector. + * + * \only_for_vectors + * + * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit( + Index newSize, Index i) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return BasisReturnType(SquareMatrixType::Identity(newSize, newSize), i); +} + +/** \returns an expression of the i-th unit (basis) vector. + * + * \only_for_vectors + * + * This variant is for fixed-size vector only. + * + * \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit( + Index i) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return BasisReturnType(SquareMatrixType::Identity(), i); +} + +/** \returns an expression of the X axis unit vector (1{,0}^*) + * + * \only_for_vectors + * + * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), + * MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() { + return Derived::Unit(0); +} + +/** \returns an expression of the Y axis unit vector (0,1{,0}^*) + * + * \only_for_vectors + * + * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), + * MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() { + return Derived::Unit(1); +} + +/** \returns an expression of the Z axis unit vector (0,0,1{,0}^*) + * + * \only_for_vectors + * + * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), + * MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() { + return Derived::Unit(2); +} + +/** \returns an expression of the W axis unit vector (0,0,0,1) + * + * \only_for_vectors + * + * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), + * MatrixBase::UnitW() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() { + return Derived::Unit(3); +} + +/** \brief Set the coefficients of \c *this to the i-th unit (basis) vector + * + * \param i index of the unique coefficient to be set to 1 + * + * \only_for_vectors + * + * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Unit(Index,Index) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setUnit(Index i) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + eigen_assert(i < size()); + derived().setZero(); + derived().coeffRef(i) = Scalar(1); + return derived(); +} + +/** \brief Resizes to the given \a newSize, and writes the i-th unit (basis) vector into *this. + * + * \param newSize the new size of the vector + * \param i index of the unique coefficient to be set to 1 + * + * \only_for_vectors + * + * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Unit(Index,Index) + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setUnit(Index newSize, Index i) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + eigen_assert(i < newSize); + derived().resize(newSize); + return setUnit(i); +} + +} // end namespace Eigen + +#endif // EIGEN_CWISE_NULLARY_OP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseTernaryOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseTernaryOp.h new file mode 100644 index 0000000..8737791 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseTernaryOp.h @@ -0,0 +1,171 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2016 Eugene Brevdo +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CWISE_TERNARY_OP_H +#define EIGEN_CWISE_TERNARY_OP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits> { + // we must not inherit from traits since it has + // the potential to cause problems with MSVC + typedef remove_all_t Ancestor; + typedef typename traits::XprKind XprKind; + enum { + RowsAtCompileTime = traits::RowsAtCompileTime, + ColsAtCompileTime = traits::ColsAtCompileTime, + MaxRowsAtCompileTime = traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = traits::MaxColsAtCompileTime + }; + + // even though we require Arg1, Arg2, and Arg3 to have the same scalar type + // (see CwiseTernaryOp constructor), + // we still want to handle the case when the result type is different. + typedef typename result_of::type Scalar; + + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; + + typedef typename Arg1::Nested Arg1Nested; + typedef typename Arg2::Nested Arg2Nested; + typedef typename Arg3::Nested Arg3Nested; + typedef std::remove_reference_t Arg1Nested_; + typedef std::remove_reference_t Arg2Nested_; + typedef std::remove_reference_t Arg3Nested_; + enum { Flags = Arg1Nested_::Flags & RowMajorBit }; +}; +} // end namespace internal + +template +class CwiseTernaryOpImpl; + +/** \class CwiseTernaryOp + * \ingroup Core_Module + * + * \brief Generic expression where a coefficient-wise ternary operator is + * applied to two expressions + * + * \tparam TernaryOp template functor implementing the operator + * \tparam Arg1Type the type of the first argument + * \tparam Arg2Type the type of the second argument + * \tparam Arg3Type the type of the third argument + * + * This class represents an expression where a coefficient-wise ternary + * operator is applied to three expressions. + * It is the return type of ternary operators, by which we mean only those + * ternary operators where + * all three arguments are Eigen expressions. + * For example, the return type of betainc(matrix1, matrix2, matrix3) is a + * CwiseTernaryOp. + * + * Most of the time, this is the only way that it is used, so you typically + * don't have to name + * CwiseTernaryOp types explicitly. + * + * \sa MatrixBase::ternaryExpr(const MatrixBase &, const + * MatrixBase &, const CustomTernaryOp &) const, class CwiseBinaryOp, + * class CwiseUnaryOp, class CwiseNullaryOp + */ +template +class CwiseTernaryOp : public CwiseTernaryOpImpl::StorageKind>, + internal::no_assignment_operator { + public: + typedef internal::remove_all_t Arg1; + typedef internal::remove_all_t Arg2; + typedef internal::remove_all_t Arg3; + + // require the sizes to match + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Arg1, Arg2) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Arg1, Arg3) + + // The index types should match + EIGEN_STATIC_ASSERT((internal::is_same::StorageKind, + typename internal::traits::StorageKind>::value), + STORAGE_KIND_MUST_MATCH) + EIGEN_STATIC_ASSERT((internal::is_same::StorageKind, + typename internal::traits::StorageKind>::value), + STORAGE_KIND_MUST_MATCH) + + typedef typename CwiseTernaryOpImpl::StorageKind>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseTernaryOp) + + typedef typename internal::ref_selector::type Arg1Nested; + typedef typename internal::ref_selector::type Arg2Nested; + typedef typename internal::ref_selector::type Arg3Nested; + typedef std::remove_reference_t Arg1Nested_; + typedef std::remove_reference_t Arg2Nested_; + typedef std::remove_reference_t Arg3Nested_; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CwiseTernaryOp(const Arg1& a1, const Arg2& a2, const Arg3& a3, + const TernaryOp& func = TernaryOp()) + : m_arg1(a1), m_arg2(a2), m_arg3(a3), m_functor(func) { + eigen_assert(a1.rows() == a2.rows() && a1.cols() == a2.cols() && a1.rows() == a3.rows() && a1.cols() == a3.cols()); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index rows() const { + // return the fixed size type if available to enable compile time + // optimizations + if (internal::traits>::RowsAtCompileTime == Dynamic && + internal::traits>::RowsAtCompileTime == Dynamic) + return m_arg3.rows(); + else if (internal::traits>::RowsAtCompileTime == Dynamic && + internal::traits>::RowsAtCompileTime == Dynamic) + return m_arg2.rows(); + else + return m_arg1.rows(); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index cols() const { + // return the fixed size type if available to enable compile time + // optimizations + if (internal::traits>::ColsAtCompileTime == Dynamic && + internal::traits>::ColsAtCompileTime == Dynamic) + return m_arg3.cols(); + else if (internal::traits>::ColsAtCompileTime == Dynamic && + internal::traits>::ColsAtCompileTime == Dynamic) + return m_arg2.cols(); + else + return m_arg1.cols(); + } + + /** \returns the first argument nested expression */ + EIGEN_DEVICE_FUNC constexpr const Arg1Nested_& arg1() const { return m_arg1; } + /** \returns the first argument nested expression */ + EIGEN_DEVICE_FUNC constexpr const Arg2Nested_& arg2() const { return m_arg2; } + /** \returns the third argument nested expression */ + EIGEN_DEVICE_FUNC constexpr const Arg3Nested_& arg3() const { return m_arg3; } + /** \returns the functor representing the ternary operation */ + EIGEN_DEVICE_FUNC constexpr const TernaryOp& functor() const { return m_functor; } + + protected: + Arg1Nested m_arg1; + Arg2Nested m_arg2; + Arg3Nested m_arg3; + const TernaryOp m_functor; +}; + +// Generic API dispatcher +template +class CwiseTernaryOpImpl : public internal::generic_xpr_base>::type { + public: + typedef typename internal::generic_xpr_base>::type Base; +}; + +} // end namespace Eigen + +#endif // EIGEN_CWISE_TERNARY_OP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryOp.h new file mode 100644 index 0000000..fabf4fc --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryOp.h @@ -0,0 +1,95 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CWISE_UNARY_OP_H +#define EIGEN_CWISE_UNARY_OP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : traits { + typedef typename result_of::type Scalar; + typedef typename XprType::Nested XprTypeNested; + typedef std::remove_reference_t XprTypeNested_; + enum { Flags = XprTypeNested_::Flags & RowMajorBit }; +}; +} // namespace internal + +template +class CwiseUnaryOpImpl; + +/** \class CwiseUnaryOp + * \ingroup Core_Module + * + * \brief Generic expression where a coefficient-wise unary operator is applied to an expression + * + * \tparam UnaryOp template functor implementing the operator + * \tparam XprType the type of the expression to which we are applying the unary operator + * + * This class represents an expression where a unary operator is applied to an expression. + * It is the return type of all operations taking exactly 1 input expression, regardless of the + * presence of other inputs such as scalars. For example, the operator* in the expression 3*matrix + * is considered unary, because only the right-hand side is an expression, and its + * return type is a specialization of CwiseUnaryOp. + * + * Most of the time, this is the only way that it is used, so you typically don't have to name + * CwiseUnaryOp types explicitly. + * + * \sa MatrixBase::unaryExpr(const CustomUnaryOp &) const, class CwiseBinaryOp, class CwiseNullaryOp + */ +template +class CwiseUnaryOp : public CwiseUnaryOpImpl::StorageKind>, + internal::no_assignment_operator { + public: + typedef typename CwiseUnaryOpImpl::StorageKind>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp) + typedef typename internal::ref_selector::type XprTypeNested; + typedef internal::remove_all_t NestedExpression; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit CwiseUnaryOp(const XprType& xpr, + const UnaryOp& func = UnaryOp()) + : m_xpr(xpr), m_functor(func) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_xpr.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_xpr.cols(); } + + /** \returns the functor representing the unary operation */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const UnaryOp& functor() const { return m_functor; } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const internal::remove_all_t& nestedExpression() + const { + return m_xpr; + } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE internal::remove_all_t& nestedExpression() { + return m_xpr; + } + + protected: + XprTypeNested m_xpr; + const UnaryOp m_functor; +}; + +// Generic API dispatcher +template +class CwiseUnaryOpImpl : public internal::generic_xpr_base >::type { + public: + typedef typename internal::generic_xpr_base >::type Base; +}; + +} // end namespace Eigen + +#endif // EIGEN_CWISE_UNARY_OP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryView.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryView.h new file mode 100644 index 0000000..34546e8 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/CwiseUnaryView.h @@ -0,0 +1,169 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CWISE_UNARY_VIEW_H +#define EIGEN_CWISE_UNARY_VIEW_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : traits { + typedef typename result_of::Scalar&)>::type1 ScalarRef; + static_assert(std::is_reference::value, "Views must return a reference type."); + typedef remove_all_t Scalar; + typedef typename MatrixType::Nested MatrixTypeNested; + typedef remove_all_t MatrixTypeNested_; + enum { + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + Flags = + traits::Flags & + (RowMajorBit | FlagsLvalueBit | DirectAccessBit), // FIXME DirectAccessBit should not be handled by expressions + MatrixTypeInnerStride = inner_stride_at_compile_time::ret, + // need to cast the sizeof's from size_t to int explicitly, otherwise: + // "error: no integral type can represent all of the enumerator values + InnerStrideAtCompileTime = + StrideType::InnerStrideAtCompileTime == 0 + ? (MatrixTypeInnerStride == Dynamic + ? int(Dynamic) + : int(MatrixTypeInnerStride) * int(sizeof(typename traits::Scalar) / sizeof(Scalar))) + : int(StrideType::InnerStrideAtCompileTime), + + OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 + ? (outer_stride_at_compile_time::ret == Dynamic + ? int(Dynamic) + : outer_stride_at_compile_time::ret * + int(sizeof(typename traits::Scalar) / sizeof(Scalar))) + : int(StrideType::OuterStrideAtCompileTime) + }; +}; + +// Generic API dispatcher +template ::value> +class CwiseUnaryViewImpl : public generic_xpr_base >::type { + public: + typedef typename generic_xpr_base >::type Base; +}; + +template +class CwiseUnaryViewImpl + : public dense_xpr_base >::type { + public: + typedef CwiseUnaryView Derived; + typedef typename dense_xpr_base >::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Derived) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl) + + EIGEN_DEVICE_FUNC inline const Scalar* data() const { return &(this->coeffRef(0)); } + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const { + return StrideType::InnerStrideAtCompileTime != 0 ? int(StrideType::InnerStrideAtCompileTime) + : derived().nestedExpression().innerStride() * + sizeof(typename traits::Scalar) / sizeof(Scalar); + } + + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { + return StrideType::OuterStrideAtCompileTime != 0 ? int(StrideType::OuterStrideAtCompileTime) + : derived().nestedExpression().outerStride() * + sizeof(typename traits::Scalar) / sizeof(Scalar); + } + + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(CwiseUnaryViewImpl) + + // Allow const access to coeffRef for the case of direct access being enabled. + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const { + return internal::evaluator(derived()).coeffRef(index); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const { + return internal::evaluator(derived()).coeffRef(row, col); + } +}; + +template +class CwiseUnaryViewImpl + : public CwiseUnaryViewImpl { + public: + typedef CwiseUnaryViewImpl Base; + typedef CwiseUnaryView Derived; + EIGEN_DENSE_PUBLIC_INTERFACE(Derived) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl) + + using Base::data; + EIGEN_DEVICE_FUNC inline Scalar* data() { return &(this->coeffRef(0)); } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + return internal::evaluator(derived()).coeffRef(row, col); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + return internal::evaluator(derived()).coeffRef(index); + } + + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(CwiseUnaryViewImpl) +}; + +} // namespace internal + +/** \class CwiseUnaryView + * \ingroup Core_Module + * + * \brief Generic lvalue expression of a coefficient-wise unary operator of a matrix or a vector + * + * \tparam ViewOp template functor implementing the view + * \tparam MatrixType the type of the matrix we are applying the unary operator + * + * This class represents a lvalue expression of a generic unary view operator of a matrix or a vector. + * It is the return type of real() and imag(), and most of the time this is the only way it is used. + * + * \sa MatrixBase::unaryViewExpr(const CustomUnaryOp &) const, class CwiseUnaryOp + */ +template +class CwiseUnaryView : public internal::CwiseUnaryViewImpl::StorageKind> { + public: + typedef typename internal::CwiseUnaryViewImpl::StorageKind>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryView) + typedef typename internal::ref_selector::non_const_type MatrixTypeNested; + typedef internal::remove_all_t NestedExpression; + + explicit EIGEN_DEVICE_FUNC constexpr inline CwiseUnaryView(MatrixType& mat, const ViewOp& func = ViewOp()) + : m_matrix(mat), m_functor(func) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryView) + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); } + + /** \returns the functor representing unary operation */ + EIGEN_DEVICE_FUNC constexpr const ViewOp& functor() const { return m_functor; } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { + return m_matrix; + } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr std::remove_reference_t& nestedExpression() { return m_matrix; } + + protected: + MatrixTypeNested m_matrix; + ViewOp m_functor; +}; + +} // namespace Eigen + +#endif // EIGEN_CWISE_UNARY_VIEW_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseBase.h new file mode 100644 index 0000000..4331a72 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseBase.h @@ -0,0 +1,672 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2007-2010 Benoit Jacob +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DENSEBASE_H +#define EIGEN_DENSEBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +// The index type defined by EIGEN_DEFAULT_DENSE_INDEX_TYPE must be a signed type. +EIGEN_STATIC_ASSERT(NumTraits::IsSigned, THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE) + +/** \class DenseBase + * \ingroup Core_Module + * + * \brief Base class for all dense matrices, vectors, and arrays + * + * This class is the base that is inherited by all dense objects (matrix, vector, arrays, + * and related expression types). The common Eigen API for dense objects is contained in this class. + * + * \tparam Derived is the derived type, e.g., a matrix type or an expression. + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_DENSEBASE_PLUGIN. + * + * \sa \blank \ref TopicClassHierarchy + */ +template +class DenseBase +#ifndef EIGEN_PARSED_BY_DOXYGEN + : public DenseCoeffsBase::value> +#else + : public DenseCoeffsBase +#endif // not EIGEN_PARSED_BY_DOXYGEN +{ + public: + /** Inner iterator type to iterate over the coefficients of a row or column. + * \sa class InnerIterator + */ + typedef Eigen::InnerIterator InnerIterator; + + typedef typename internal::traits::StorageKind StorageKind; + + /** + * \brief The type used to store indices + * \details This typedef is relevant for types that store multiple indices such as + * PermutationMatrix or Transpositions, otherwise it defaults to Eigen::Index + * \sa \blank \ref TopicPreprocessorDirectives, Eigen::Index, SparseMatrixBase. + */ + typedef typename internal::traits::StorageIndex StorageIndex; + + /** The numeric type of the expression' coefficients, e.g. float, double, int or std::complex, etc. */ + typedef typename internal::traits::Scalar Scalar; + + /** The numeric type of the expression' coefficients, e.g. float, double, int or std::complex, etc. + * + * It is an alias for the Scalar type */ + typedef Scalar value_type; + + typedef typename NumTraits::Real RealScalar; + typedef DenseCoeffsBase::value> Base; + + using Base::coeff; + using Base::coeffByOuterInner; + using Base::colIndexByOuterInner; + using Base::cols; + using Base::const_cast_derived; + using Base::derived; + using Base::rowIndexByOuterInner; + using Base::rows; + using Base::size; + using Base::operator(); + using Base::operator[]; + using Base::colStride; + using Base::innerStride; + using Base::outerStride; + using Base::rowStride; + using Base::stride; + using Base::w; + using Base::x; + using Base::y; + using Base::z; + typedef typename Base::CoeffReturnType CoeffReturnType; + + enum { + + RowsAtCompileTime = internal::traits::RowsAtCompileTime, + /**< The number of rows at compile-time. This is just a copy of the value provided + * by the \a Derived type. If a value is not known at compile-time, + * it is set to the \a Dynamic constant. + * \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */ + + ColsAtCompileTime = internal::traits::ColsAtCompileTime, + /**< The number of columns at compile-time. This is just a copy of the value provided + * by the \a Derived type. If a value is not known at compile-time, + * it is set to the \a Dynamic constant. + * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */ + + SizeAtCompileTime = (internal::size_of_xpr_at_compile_time::ret), + /**< This is equal to the number of coefficients, i.e. the number of + * rows times the number of columns, or to \a Dynamic if this is not + * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */ + + MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, + /**< This value is equal to the maximum possible number of rows that this expression + * might have. If this expression might have an arbitrarily high number of rows, + * this value is set to \a Dynamic. + * + * This value is useful to know when evaluating an expression, in order to determine + * whether it is possible to avoid doing a dynamic memory allocation. + * + * \sa RowsAtCompileTime, MaxColsAtCompileTime, MaxSizeAtCompileTime + */ + + MaxColsAtCompileTime = internal::traits::MaxColsAtCompileTime, + /**< This value is equal to the maximum possible number of columns that this expression + * might have. If this expression might have an arbitrarily high number of columns, + * this value is set to \a Dynamic. + * + * This value is useful to know when evaluating an expression, in order to determine + * whether it is possible to avoid doing a dynamic memory allocation. + * + * \sa ColsAtCompileTime, MaxRowsAtCompileTime, MaxSizeAtCompileTime + */ + + MaxSizeAtCompileTime = internal::size_at_compile_time(internal::traits::MaxRowsAtCompileTime, + internal::traits::MaxColsAtCompileTime), + /**< This value is equal to the maximum possible number of coefficients that this expression + * might have. If this expression might have an arbitrarily high number of coefficients, + * this value is set to \a Dynamic. + * + * This value is useful to know when evaluating an expression, in order to determine + * whether it is possible to avoid doing a dynamic memory allocation. + * + * \sa SizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime + */ + + IsVectorAtCompileTime = + internal::traits::RowsAtCompileTime == 1 || internal::traits::ColsAtCompileTime == 1, + /**< This is set to true if either the number of rows or the number of + * columns is known at compile-time to be equal to 1. Indeed, in that case, + * we are dealing with a column-vector (if there is only one column) or with + * a row-vector (if there is only one row). */ + + NumDimensions = int(MaxSizeAtCompileTime) == 1 ? 0 + : bool(IsVectorAtCompileTime) ? 1 + : 2, + /**< This value is equal to Tensor::NumDimensions, i.e. 0 for scalars, 1 for vectors, + * and 2 for matrices. + */ + + Flags = internal::traits::Flags, + /**< This stores expression \ref flags flags which may or may not be inherited by new expressions + * constructed from this one. See the \ref flags "list of flags". + */ + + IsRowMajor = int(Flags) & RowMajorBit, /**< True if this expression has row-major storage order. */ + + InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime) + : int(IsRowMajor) ? int(ColsAtCompileTime) + : int(RowsAtCompileTime), + + InnerStrideAtCompileTime = internal::inner_stride_at_compile_time::ret, + OuterStrideAtCompileTime = internal::outer_stride_at_compile_time::ret + }; + + typedef typename internal::find_best_packet::type PacketScalar; + + enum { IsPlainObjectBase = 0 }; + + /** The plain matrix type corresponding to this expression. + * \sa PlainObject */ + typedef Matrix::Scalar, internal::traits::RowsAtCompileTime, + internal::traits::ColsAtCompileTime, + AutoAlign | (internal::traits::Flags & RowMajorBit ? RowMajor : ColMajor), + internal::traits::MaxRowsAtCompileTime, internal::traits::MaxColsAtCompileTime> + PlainMatrix; + + /** The plain array type corresponding to this expression. + * \sa PlainObject */ + typedef Array::Scalar, internal::traits::RowsAtCompileTime, + internal::traits::ColsAtCompileTime, + AutoAlign | (internal::traits::Flags & RowMajorBit ? RowMajor : ColMajor), + internal::traits::MaxRowsAtCompileTime, internal::traits::MaxColsAtCompileTime> + PlainArray; + + /** \brief The plain matrix or array type corresponding to this expression. + * + * This is not necessarily exactly the return type of eval(). In the case of plain matrices, + * the return type of eval() is a const reference to a matrix, not a matrix! It is however guaranteed + * that the return type of eval() is either PlainObject or const PlainObject&. + */ + typedef std::conditional_t::XprKind, MatrixXpr>::value, + PlainMatrix, PlainArray> + PlainObject; + + /** \returns the outer size. + * + * \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension + * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a + * column-major matrix, and the number of rows for a row-major matrix. */ + EIGEN_DEVICE_FUNC constexpr Index outerSize() const { + return IsVectorAtCompileTime ? 1 : int(IsRowMajor) ? this->rows() : this->cols(); + } + + /** \returns the inner size. + * + * \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension + * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a + * column-major matrix, and the number of columns for a row-major matrix. */ + EIGEN_DEVICE_FUNC constexpr Index innerSize() const { + return IsVectorAtCompileTime ? this->size() : int(IsRowMajor) ? this->cols() : this->rows(); + } + + /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are + * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and + * does nothing else. + */ + EIGEN_DEVICE_FUNC void resize(Index newSize) { + EIGEN_ONLY_USED_FOR_DEBUG(newSize); + eigen_assert(newSize == this->size() && "DenseBase::resize() does not actually allow to resize."); + } + /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are + * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and + * does nothing else. + */ + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { + EIGEN_ONLY_USED_FOR_DEBUG(rows); + EIGEN_ONLY_USED_FOR_DEBUG(cols); + eigen_assert(rows == this->rows() && cols == this->cols() && + "DenseBase::resize() does not actually allow to resize."); + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal Represents a matrix with all coefficients equal to one another*/ + typedef CwiseNullaryOp, PlainObject> ConstantReturnType; + /** \internal Represents a matrix with all coefficients equal to zero*/ + typedef CwiseNullaryOp, PlainObject> ZeroReturnType; + /** \internal \deprecated Represents a vector with linearly spaced coefficients that allows sequential access only. */ + EIGEN_DEPRECATED typedef CwiseNullaryOp, PlainObject> SequentialLinSpacedReturnType; + /** \internal Represents a vector with linearly spaced coefficients that allows random access. */ + typedef CwiseNullaryOp, PlainObject> RandomAccessLinSpacedReturnType; + /** \internal Represents a vector with equally spaced coefficients that allows random access. */ + typedef CwiseNullaryOp, PlainObject> RandomAccessEqualSpacedReturnType; + /** \internal the return type of MatrixBase::eigenvalues() */ + typedef Matrix::Scalar>::Real, + internal::traits::ColsAtCompileTime, 1> + EigenvaluesReturnType; + +#endif // not EIGEN_PARSED_BY_DOXYGEN + + /** Copies \a other into *this. \returns a reference to *this. */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator=(const DenseBase& other); + + /** Special case of the template operator=, in order to prevent the compiler + * from generating a default operator= (issue hit with g++ 4.1) + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator=(const DenseBase& other); + + template + EIGEN_DEVICE_FUNC constexpr Derived& operator=(const EigenBase& other); + + template + EIGEN_DEVICE_FUNC constexpr Derived& operator+=(const EigenBase& other); + + template + EIGEN_DEVICE_FUNC constexpr Derived& operator-=(const EigenBase& other); + + template + EIGEN_DEVICE_FUNC Derived& operator=(const ReturnByValue& func); + + /** \internal + * Copies \a other into *this without evaluating other. \returns a reference to *this. */ + template + /** \deprecated */ + EIGEN_DEPRECATED EIGEN_DEVICE_FUNC constexpr Derived& lazyAssign(const DenseBase& other); + + EIGEN_DEVICE_FUNC CommaInitializer operator<<(const Scalar& s); + + template + /** \deprecated it now returns \c *this */ + EIGEN_DEPRECATED const Derived& flagged() const { + return derived(); + } + + template + EIGEN_DEVICE_FUNC CommaInitializer operator<<(const DenseBase& other); + + typedef Transpose TransposeReturnType; + EIGEN_DEVICE_FUNC TransposeReturnType transpose(); + typedef Transpose ConstTransposeReturnType; + EIGEN_DEVICE_FUNC const ConstTransposeReturnType transpose() const; + EIGEN_DEVICE_FUNC void transposeInPlace(); + + EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(Index rows, Index cols, const Scalar& value); + EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(Index size, const Scalar& value); + EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(const Scalar& value); + + EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.") + EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, Index size, const Scalar& low, + const Scalar& high); + EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.") + EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, const Scalar& low, + const Scalar& high); + + EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Index size, const Scalar& low, + const Scalar& high); + EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(const Scalar& low, const Scalar& high); + + EIGEN_DEVICE_FUNC static const RandomAccessEqualSpacedReturnType EqualSpaced(Index size, const Scalar& low, + const Scalar& step); + EIGEN_DEVICE_FUNC static const RandomAccessEqualSpacedReturnType EqualSpaced(const Scalar& low, const Scalar& step); + + template + EIGEN_DEVICE_FUNC static const CwiseNullaryOp NullaryExpr(Index rows, Index cols, + const CustomNullaryOp& func); + template + EIGEN_DEVICE_FUNC static const CwiseNullaryOp NullaryExpr(Index size, + const CustomNullaryOp& func); + template + EIGEN_DEVICE_FUNC static const CwiseNullaryOp NullaryExpr(const CustomNullaryOp& func); + + EIGEN_DEVICE_FUNC static const ZeroReturnType Zero(Index rows, Index cols); + EIGEN_DEVICE_FUNC static const ZeroReturnType Zero(Index size); + EIGEN_DEVICE_FUNC static const ZeroReturnType Zero(); + EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index rows, Index cols); + EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index size); + EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(); + + EIGEN_DEVICE_FUNC void fill(const Scalar& value); + EIGEN_DEVICE_FUNC Derived& setConstant(const Scalar& value); + EIGEN_DEVICE_FUNC Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high); + EIGEN_DEVICE_FUNC Derived& setLinSpaced(const Scalar& low, const Scalar& high); + EIGEN_DEVICE_FUNC Derived& setEqualSpaced(Index size, const Scalar& low, const Scalar& step); + EIGEN_DEVICE_FUNC Derived& setEqualSpaced(const Scalar& low, const Scalar& step); + EIGEN_DEVICE_FUNC Derived& setZero(); + EIGEN_DEVICE_FUNC Derived& setOnes(); + EIGEN_DEVICE_FUNC Derived& setRandom(); + + template + EIGEN_DEVICE_FUNC constexpr bool isApprox(const DenseBase& other, + const RealScalar& prec = NumTraits::dummy_precision()) const; + EIGEN_DEVICE_FUNC constexpr bool isMuchSmallerThan( + const RealScalar& other, const RealScalar& prec = NumTraits::dummy_precision()) const; + template + EIGEN_DEVICE_FUNC constexpr bool isMuchSmallerThan( + const DenseBase& other, const RealScalar& prec = NumTraits::dummy_precision()) const; + + EIGEN_DEVICE_FUNC bool isApproxToConstant(const Scalar& value, + const RealScalar& prec = NumTraits::dummy_precision()) const; + EIGEN_DEVICE_FUNC bool isConstant(const Scalar& value, + const RealScalar& prec = NumTraits::dummy_precision()) const; + EIGEN_DEVICE_FUNC bool isZero(const RealScalar& prec = NumTraits::dummy_precision()) const; + EIGEN_DEVICE_FUNC bool isOnes(const RealScalar& prec = NumTraits::dummy_precision()) const; + + EIGEN_DEVICE_FUNC inline bool hasNaN() const; + EIGEN_DEVICE_FUNC inline bool allFinite() const; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator*=(const Scalar& other); + template ::value, typename = std::enable_if_t> + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator*=(const RealScalar& other); + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator/=(const Scalar& other); + template ::value, typename = std::enable_if_t> + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator/=(const RealScalar& other); + + typedef internal::add_const_on_value_type_t::type> EvalReturnType; + /** \returns the matrix or vector obtained by evaluating this expression. + * + * Notice that in the case of a plain matrix or vector (not an expression) this function just returns + * a const reference, in order to avoid a useless copy. + * + * \warning Be careful with eval() and the auto C++ keyword, as detailed in this \link TopicPitfalls_auto_keyword page + * \endlink. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EvalReturnType eval() const { + // Even though MSVC does not honor strong inlining when the return type + // is a dynamic matrix, we desperately need strong inlining for fixed + // size types on MSVC. + return typename internal::eval::type(derived()); + } + + /** swaps *this with the expression \a other. + * + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(const DenseBase& other) { + EIGEN_STATIC_ASSERT(!OtherDerived::IsPlainObjectBase, THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); + eigen_assert(rows() == other.rows() && cols() == other.cols()); + call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op()); + } + + /** swaps *this with the matrix or array \a other. + * + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(PlainObjectBase& other) { + eigen_assert(rows() == other.rows() && cols() == other.cols()); + call_assignment(derived(), other.derived(), internal::swap_assign_op()); + } + + EIGEN_DEVICE_FUNC constexpr inline const NestByValue nestByValue() const; + EIGEN_DEVICE_FUNC inline const ForceAlignedAccess forceAlignedAccess() const; + EIGEN_DEVICE_FUNC inline ForceAlignedAccess forceAlignedAccess(); + template + EIGEN_DEVICE_FUNC inline const std::conditional_t, Derived&> + forceAlignedAccessIf() const; + template + EIGEN_DEVICE_FUNC inline std::conditional_t, Derived&> forceAlignedAccessIf(); + + EIGEN_DEVICE_FUNC Scalar sum() const; + EIGEN_DEVICE_FUNC Scalar mean() const; + EIGEN_DEVICE_FUNC Scalar trace() const; + + EIGEN_DEVICE_FUNC Scalar prod() const; + + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; + + // By default, the fastest version with undefined NaN propagation semantics is + // used. + // TODO(rmlarsen): Replace with default template argument (C++14 is now the minimum standard). + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar minCoeff() const { + return minCoeff(); + } + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar maxCoeff() const { + return maxCoeff(); + } + + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff(IndexType* row, IndexType* col) const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff(IndexType* row, IndexType* col) const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff(IndexType* index) const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff(IndexType* index) const; + + // TODO(rmlarsen): Replace these methods with a default template argument (C++14 is now the minimum standard). + template + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar minCoeff(IndexType* row, IndexType* col) const { + return minCoeff(row, col); + } + template + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar maxCoeff(IndexType* row, IndexType* col) const { + return maxCoeff(row, col); + } + template + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar minCoeff(IndexType* index) const { + return minCoeff(index); + } + template + EIGEN_DEVICE_FUNC inline typename internal::traits::Scalar maxCoeff(IndexType* index) const { + return maxCoeff(index); + } + + template + EIGEN_DEVICE_FUNC Scalar redux(const BinaryOp& func) const; + + template + EIGEN_DEVICE_FUNC void visit(Visitor& func) const; + + /** \returns a WithFormat proxy object allowing to print a matrix the with given + * format \a fmt. + * + * See class IOFormat for some examples. + * + * \sa class IOFormat, class WithFormat + */ + inline const WithFormat format(const IOFormat& fmt) const { return WithFormat(derived(), fmt); } + + /** \returns the unique coefficient of a 1x1 expression */ + EIGEN_DEVICE_FUNC CoeffReturnType value() const { + EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) eigen_assert(this->rows() == 1 && this->cols() == 1); + return derived().coeff(0, 0); + } + + EIGEN_DEVICE_FUNC bool all() const; + EIGEN_DEVICE_FUNC bool any() const; + EIGEN_DEVICE_FUNC Index count() const; + + typedef VectorwiseOp RowwiseReturnType; + typedef const VectorwiseOp ConstRowwiseReturnType; + typedef VectorwiseOp ColwiseReturnType; + typedef const VectorwiseOp ConstColwiseReturnType; + + /** \returns a VectorwiseOp wrapper of *this for broadcasting and partial reductions + * + * Example: \include MatrixBase_rowwise.cpp + * Output: \verbinclude MatrixBase_rowwise.out + * + * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting + */ + // Code moved here due to a CUDA compiler bug + EIGEN_DEVICE_FUNC inline ConstRowwiseReturnType rowwise() const { return ConstRowwiseReturnType(derived()); } + EIGEN_DEVICE_FUNC RowwiseReturnType rowwise(); + + /** \returns a VectorwiseOp wrapper of *this broadcasting and partial reductions + * + * Example: \include MatrixBase_colwise.cpp + * Output: \verbinclude MatrixBase_colwise.out + * + * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting + */ + EIGEN_DEVICE_FUNC inline ConstColwiseReturnType colwise() const { return ConstColwiseReturnType(derived()); } + EIGEN_DEVICE_FUNC ColwiseReturnType colwise(); + + typedef CwiseNullaryOp, PlainObject> RandomReturnType; + static const RandomReturnType Random(Index rows, Index cols); + static const RandomReturnType Random(Index size); + static const RandomReturnType Random(); + + template + inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, + typename DenseBase::Scalar, Scalar>, + ThenDerived, ElseDerived, Derived> + select(const DenseBase& thenMatrix, const DenseBase& elseMatrix) const; + + template + inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, + typename DenseBase::Scalar, Scalar>, + ThenDerived, typename DenseBase::ConstantReturnType, Derived> + select(const DenseBase& thenMatrix, const typename DenseBase::Scalar& elseScalar) const; + + template + inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, + typename DenseBase::Scalar, Scalar>, + typename DenseBase::ConstantReturnType, ElseDerived, Derived> + select(const typename DenseBase::Scalar& thenScalar, const DenseBase& elseMatrix) const; + + template + RealScalar lpNorm() const; + + template + EIGEN_DEVICE_FUNC const Replicate replicate() const; + /** + * \return an expression of the replication of \c *this + * + * Example: \include MatrixBase_replicate_int_int.cpp + * Output: \verbinclude MatrixBase_replicate_int_int.out + * + * \sa VectorwiseOp::replicate(), DenseBase::replicate(), class Replicate + */ + // Code moved here due to a CUDA compiler bug + EIGEN_DEVICE_FUNC const Replicate replicate(Index rowFactor, Index colFactor) const { + return Replicate(derived(), rowFactor, colFactor); + } + + typedef Reverse ReverseReturnType; + typedef const Reverse ConstReverseReturnType; + EIGEN_DEVICE_FUNC ReverseReturnType reverse(); + /** This is the const version of reverse(). */ + // Code moved here due to a CUDA compiler bug + EIGEN_DEVICE_FUNC ConstReverseReturnType reverse() const { return ConstReverseReturnType(derived()); } + EIGEN_DEVICE_FUNC void reverseInPlace(); + +#ifdef EIGEN_PARSED_BY_DOXYGEN + /** STL-like RandomAccessIterator + * iterator type as returned by the begin() and end() methods. + */ + typedef random_access_iterator_type iterator; + /** This is the const version of iterator (aka read-only) */ + typedef random_access_iterator_type const_iterator; +#else + typedef std::conditional_t<(Flags & DirectAccessBit) == DirectAccessBit, + internal::pointer_based_stl_iterator, + internal::generic_randaccess_stl_iterator> + iterator_type; + + typedef std::conditional_t<(Flags & DirectAccessBit) == DirectAccessBit, + internal::pointer_based_stl_iterator, + internal::generic_randaccess_stl_iterator> + const_iterator_type; + + // Stl-style iterators are supported only for vectors. + + typedef std::conditional_t iterator; + + typedef std::conditional_t const_iterator; +#endif + + inline iterator begin(); + inline const_iterator begin() const; + inline const_iterator cbegin() const; + inline iterator end(); + inline const_iterator end() const; + inline const_iterator cend() const; + + using RealViewReturnType = std::conditional_t::IsComplex, RealView, Derived&>; + using ConstRealViewReturnType = + std::conditional_t::IsComplex, RealView, const Derived&>; + + EIGEN_DEVICE_FUNC RealViewReturnType realView(); + EIGEN_DEVICE_FUNC ConstRealViewReturnType realView() const; + +#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase +#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL +#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND) +#define EIGEN_DOC_UNARY_ADDONS(X, Y) +#include "../plugins/CommonCwiseUnaryOps.inc" +#include "../plugins/BlockMethods.inc" +#include "../plugins/IndexedViewMethods.inc" +#include "../plugins/ReshapedMethods.inc" +#ifdef EIGEN_DENSEBASE_PLUGIN +#include EIGEN_DENSEBASE_PLUGIN +#endif +#undef EIGEN_CURRENT_STORAGE_BASE_CLASS +#undef EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL +#undef EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF +#undef EIGEN_DOC_UNARY_ADDONS + + // disable the use of evalTo for dense objects with a nice compilation error + template + EIGEN_DEVICE_FUNC inline void evalTo(Dest&) const { + EIGEN_STATIC_ASSERT((internal::is_same::value), + THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS); + } + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase) + /** Default constructor. Do nothing. */ +#ifdef EIGEN_INTERNAL_DEBUGGING + EIGEN_DEVICE_FUNC constexpr DenseBase() { + /* Just checks for self-consistency of the flags. + * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down + */ + EIGEN_STATIC_ASSERT( + (internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, int(IsRowMajor)) && + internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, int(!IsRowMajor))), + INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION) + } +#else + EIGEN_DEVICE_FUNC constexpr DenseBase() = default; +#endif + + private: + EIGEN_DEVICE_FUNC explicit DenseBase(int); + EIGEN_DEVICE_FUNC DenseBase(int, int); + template + EIGEN_DEVICE_FUNC explicit DenseBase(const DenseBase&); +}; + +/** Free-function swap. + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + // Use forwarding references to capture all combinations of cv-qualified l+r-value cases. + std::enable_if_t>, std::decay_t>::value && + std::is_base_of>, std::decay_t>::value, + void> + swap(DerivedA&& a, DerivedB&& b) { + a.swap(b); +} + +} // end namespace Eigen + +#endif // EIGEN_DENSEBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseCoeffsBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseCoeffsBase.h new file mode 100644 index 0000000..c528416 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseCoeffsBase.h @@ -0,0 +1,583 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DENSECOEFFSBASE_H +#define EIGEN_DENSECOEFFSBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct add_const_on_value_type_if_arithmetic { + typedef std::conditional_t::value, T, add_const_on_value_type_t> type; +}; +} // namespace internal + +/** \brief Base class providing read-only coefficient access to matrices and arrays. + * \ingroup Core_Module + * \tparam Derived Type of the derived class + * + * \note #ReadOnlyAccessors Constant indicating read-only access + * + * This class defines the \c operator() \c const function and friends, which can be used to read specific + * entries of a matrix or array. + * + * \sa DenseCoeffsBase, DenseCoeffsBase, + * \ref TopicClassHierarchy + */ +template +class DenseCoeffsBase : public EigenBase { + public: + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::packet_traits::type PacketScalar; + + // Explanation for this CoeffReturnType typedef. + // - This is the return type of the coeff() method. + // - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references + // to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value). + // - The DirectAccessBit means exactly that the underlying data of coefficients can be directly accessed as a plain + // strided array, which means exactly that the underlying data of coefficients does exist in memory, which means + // exactly that the coefficients is const-referencable, which means exactly that we can have coeff() return a const + // reference. For example, Map have DirectAccessBit but not LvalueBit, so that Map.coeff() + // does points to a const Scalar& which exists in memory, while does not allow coeffRef() as it would not provide a + // lvalue. Notice that DirectAccessBit and LvalueBit are mutually orthogonal. + // - The is_arithmetic check is required since "const int", "const double", etc. will cause warnings on some systems + // while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is + // not possible, since the underlying expressions might not offer a valid address the reference could be referring to. + typedef std::conditional_t::Flags&(LvalueBit | DirectAccessBit)), const Scalar&, + std::conditional_t::value, Scalar, const Scalar>> + CoeffReturnType; + + typedef typename internal::add_const_on_value_type_if_arithmetic::type>::type + PacketReturnType; + + typedef EigenBase Base; + using Base::cols; + using Base::derived; + using Base::rows; + using Base::size; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const { + return int(Derived::RowsAtCompileTime) == 1 ? 0 + : int(Derived::ColsAtCompileTime) == 1 ? inner + : int(Derived::Flags) & RowMajorBit ? outer + : inner; + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const { + return int(Derived::ColsAtCompileTime) == 1 ? 0 + : int(Derived::RowsAtCompileTime) == 1 ? inner + : int(Derived::Flags) & RowMajorBit ? inner + : outer; + } + + /** Short version: don't use this function, use + * \link operator()(Index,Index) const \endlink instead. + * + * Long version: this function is similar to + * \link operator()(Index,Index) const \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator()(Index,Index) const \endlink. + * + * \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const + */ + EIGEN_DEVICE_FUNC constexpr CoeffReturnType coeff(Index row, Index col) const { + eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); + return internal::evaluator(derived()).coeff(row, col); + } + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType coeffByOuterInner(Index outer, Index inner) const { + return coeff(rowIndexByOuterInner(outer, inner), colIndexByOuterInner(outer, inner)); + } + + /** \returns the coefficient at given the given row and column. + * + * \sa operator()(Index,Index), operator[](Index) + */ + EIGEN_DEVICE_FUNC constexpr CoeffReturnType operator()(Index row, Index col) const { + eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); + return coeff(row, col); + } + +#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT + /** \returns the coefficient at given the given row and column. + * + * \sa operator[](Index,Index), operator[](Index) + */ + EIGEN_DEVICE_FUNC constexpr CoeffReturnType operator[](Index row, Index col) const { return operator()(row, col); } +#endif + + /** Short version: don't use this function, use + * \link operator[](Index) const \endlink instead. + * + * Long version: this function is similar to + * \link operator[](Index) const \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameter \a index is in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator[](Index) const \endlink. + * + * \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const + */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType coeff(Index index) const { + EIGEN_STATIC_ASSERT(internal::evaluator::Flags & LinearAccessBit, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS) + eigen_internal_assert(index >= 0 && index < size()); + return internal::evaluator(derived()).coeff(index); + } + + /** \returns the coefficient at given index. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](Index), operator()(Index,Index) const, x() const, y() const, + * z() const, w() const + */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType operator[](Index index) const { + EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) + eigen_assert(index >= 0 && index < size()); + return coeff(index); + } + + /** \returns the coefficient at given index. + * + * This is synonymous to operator[](Index) const. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](Index), operator()(Index,Index) const, x() const, y() const, + * z() const, w() const + */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType operator()(Index index) const { + eigen_assert(index >= 0 && index < size()); + return coeff(index); + } + + /** equivalent to operator[](0). */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType x() const { return (*this)[0]; } + + /** equivalent to operator[](1). */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType y() const { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 2, OUT_OF_RANGE_ACCESS); + return (*this)[1]; + } + + /** equivalent to operator[](2). */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType z() const { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 3, OUT_OF_RANGE_ACCESS); + return (*this)[2]; + } + + /** equivalent to operator[](3). */ + + EIGEN_DEVICE_FUNC constexpr CoeffReturnType w() const { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 4, OUT_OF_RANGE_ACCESS); + return (*this)[3]; + } + + /** \internal + * \returns the packet of coefficients starting at the given row and column. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit. + * + * The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ + + template + EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const { + typedef typename internal::packet_traits::type DefaultPacketType; + eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); + return internal::evaluator(derived()).template packet(row, col); + } + + /** \internal */ + template + EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const { + return packet(rowIndexByOuterInner(outer, inner), colIndexByOuterInner(outer, inner)); + } + + /** \internal + * \returns the packet of coefficients starting at the given index. It is your responsibility + * to ensure that a packet really starts there. This method is only available on expressions having the + * PacketAccessBit and the LinearAccessBit. + * + * The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select + * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets + * starting at an address which is a multiple of the packet size. + */ + + template + EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const { + EIGEN_STATIC_ASSERT(internal::evaluator::Flags & LinearAccessBit, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS) + typedef typename internal::packet_traits::type DefaultPacketType; + eigen_internal_assert(index >= 0 && index < size()); + return internal::evaluator(derived()).template packet(index); + } + + protected: + // explanation: DenseBase is doing "using ..." on the methods from DenseCoeffsBase. + // But some methods are only available in the DirectAccess case. + // So we add dummy methods here with these names, so that "using... " doesn't fail. + // It's not private so that the child class DenseBase can access them, and it's not public + // either since it's an implementation detail, so has to be protected. + void coeffRef(); + void coeffRefByOuterInner(); + void writePacket(); + void writePacketByOuterInner(); + void copyCoeff(); + void copyCoeffByOuterInner(); + void copyPacket(); + void copyPacketByOuterInner(); + void stride(); + void innerStride(); + void outerStride(); + void rowStride(); + void colStride(); +}; + +/** \brief Base class providing read/write coefficient access to matrices and arrays. + * \ingroup Core_Module + * \tparam Derived Type of the derived class + * + * \note #WriteAccessors Constant indicating read/write access + * + * This class defines the non-const \c operator() function and friends, which can be used to write specific + * entries of a matrix or array. This class inherits DenseCoeffsBase which + * defines the const variant for reading specific entries. + * + * \sa DenseCoeffsBase, \ref TopicClassHierarchy + */ +template +class DenseCoeffsBase : public DenseCoeffsBase { + public: + typedef DenseCoeffsBase Base; + + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::packet_traits::type PacketScalar; + typedef typename NumTraits::Real RealScalar; + + using Base::coeff; + using Base::colIndexByOuterInner; + using Base::cols; + using Base::derived; + using Base::rowIndexByOuterInner; + using Base::rows; + using Base::size; + using Base::operator[]; + using Base::operator(); + using Base::w; + using Base::x; + using Base::y; + using Base::z; + + /** Short version: don't use this function, use + * \link operator()(Index,Index) \endlink instead. + * + * Long version: this function is similar to + * \link operator()(Index,Index) \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator()(Index,Index) \endlink. + * + * \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index) + */ + EIGEN_DEVICE_FUNC constexpr Scalar& coeffRef(Index row, Index col) { + eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); + return internal::evaluator(derived()).coeffRef(row, col); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRefByOuterInner(Index outer, Index inner) { + return coeffRef(rowIndexByOuterInner(outer, inner), colIndexByOuterInner(outer, inner)); + } + + /** \returns a reference to the coefficient at given the given row and column. + * + * \sa operator[](Index) + */ + EIGEN_DEVICE_FUNC constexpr Scalar& operator()(Index row, Index col) { + eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); + return coeffRef(row, col); + } + +#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT + /** \returns a reference to the coefficient at given the given row and column. + * + * \sa operator[](Index) + */ + EIGEN_DEVICE_FUNC constexpr Scalar& operator[](Index row, Index col) { return operator()(row, col); } +#endif + + /** Short version: don't use this function, use + * \link operator[](Index) \endlink instead. + * + * Long version: this function is similar to + * \link operator[](Index) \endlink, but without the assertion. + * Use this for limiting the performance cost of debugging code when doing + * repeated coefficient access. Only use this when it is guaranteed that the + * parameters \a row and \a col are in range. + * + * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this + * function equivalent to \link operator[](Index) \endlink. + * + * \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index) + */ + + EIGEN_DEVICE_FUNC constexpr Scalar& coeffRef(Index index) { + EIGEN_STATIC_ASSERT(internal::evaluator::Flags & LinearAccessBit, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS) + eigen_internal_assert(index >= 0 && index < size()); + return internal::evaluator(derived()).coeffRef(index); + } + + /** \returns a reference to the coefficient at given index. + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() + */ + + EIGEN_DEVICE_FUNC constexpr Scalar& operator[](Index index) { + EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) + eigen_assert(index >= 0 && index < size()); + return coeffRef(index); + } + + /** \returns a reference to the coefficient at given index. + * + * This is synonymous to operator[](Index). + * + * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. + * + * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() + */ + + EIGEN_DEVICE_FUNC constexpr Scalar& operator()(Index index) { + eigen_assert(index >= 0 && index < size()); + return coeffRef(index); + } + + /** equivalent to operator[](0). */ + + EIGEN_DEVICE_FUNC constexpr Scalar& x() { return (*this)[0]; } + + /** equivalent to operator[](1). */ + + EIGEN_DEVICE_FUNC constexpr Scalar& y() { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 2, OUT_OF_RANGE_ACCESS); + return (*this)[1]; + } + + /** equivalent to operator[](2). */ + + EIGEN_DEVICE_FUNC constexpr Scalar& z() { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 3, OUT_OF_RANGE_ACCESS); + return (*this)[2]; + } + + /** equivalent to operator[](3). */ + + EIGEN_DEVICE_FUNC constexpr Scalar& w() { + EIGEN_STATIC_ASSERT(Derived::SizeAtCompileTime == -1 || Derived::SizeAtCompileTime >= 4, OUT_OF_RANGE_ACCESS); + return (*this)[3]; + } +}; + +/** \brief Base class providing direct read-only coefficient access to matrices and arrays. + * \ingroup Core_Module + * \tparam Derived Type of the derived class + * + * \note #DirectAccessors Constant indicating direct access + * + * This class defines functions to work with strides which can be used to access entries directly. This class + * inherits DenseCoeffsBase which defines functions to access entries read-only using + * \c operator() . + * + * \sa \blank \ref TopicClassHierarchy + */ +template +class DenseCoeffsBase : public DenseCoeffsBase { + public: + typedef DenseCoeffsBase Base; + typedef typename internal::traits::Scalar Scalar; + typedef typename NumTraits::Real RealScalar; + + using Base::cols; + using Base::derived; + using Base::rows; + using Base::size; + + /** \returns the pointer increment between two consecutive elements within a slice in the inner direction. + * + * \sa outerStride(), rowStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index innerStride() const { return derived().innerStride(); } + + /** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns + * in a column-major matrix). + * + * \sa innerStride(), rowStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { return derived().outerStride(); } + + // FIXME shall we remove it ? + constexpr Index stride() const { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); } + + /** \returns the pointer increment between two consecutive rows. + * + * \sa innerStride(), outerStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index rowStride() const { return Derived::IsRowMajor ? outerStride() : innerStride(); } + + /** \returns the pointer increment between two consecutive columns. + * + * \sa innerStride(), outerStride(), rowStride() + */ + EIGEN_DEVICE_FUNC constexpr Index colStride() const { return Derived::IsRowMajor ? innerStride() : outerStride(); } +}; + +/** \brief Base class providing direct read/write coefficient access to matrices and arrays. + * \ingroup Core_Module + * \tparam Derived Type of the derived class + * + * \note #DirectWriteAccessors Constant indicating direct access + * + * This class defines functions to work with strides which can be used to access entries directly. This class + * inherits DenseCoeffsBase which defines functions to access entries read/write using + * \c operator(). + * + * \sa \blank \ref TopicClassHierarchy + */ +template +class DenseCoeffsBase : public DenseCoeffsBase { + public: + typedef DenseCoeffsBase Base; + typedef typename internal::traits::Scalar Scalar; + typedef typename NumTraits::Real RealScalar; + + using Base::cols; + using Base::derived; + using Base::rows; + using Base::size; + + /** \returns the pointer increment between two consecutive elements within a slice in the inner direction. + * + * \sa outerStride(), rowStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return derived().innerStride(); } + + /** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns + * in a column-major matrix). + * + * \sa innerStride(), rowStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().outerStride(); } + + // FIXME shall we remove it ? + constexpr Index stride() const noexcept { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); } + + /** \returns the pointer increment between two consecutive rows. + * + * \sa innerStride(), outerStride(), colStride() + */ + EIGEN_DEVICE_FUNC constexpr Index rowStride() const noexcept { + return Derived::IsRowMajor ? outerStride() : innerStride(); + } + + /** \returns the pointer increment between two consecutive columns. + * + * \sa innerStride(), outerStride(), rowStride() + */ + EIGEN_DEVICE_FUNC constexpr Index colStride() const noexcept { + return Derived::IsRowMajor ? innerStride() : outerStride(); + } +}; + +namespace internal { + +template +struct first_aligned_impl { + static constexpr Index run(const Derived&) noexcept { return 0; } +}; + +template +struct first_aligned_impl { + static inline Index run(const Derived& m) { return internal::first_aligned(m.data(), m.size()); } +}; + +/** \internal \returns the index of the first element of the array stored by \a m that is properly aligned with respect + * to \a Alignment for vectorization. + * + * \tparam Alignment requested alignment in Bytes. + * + * There is also the variant first_aligned(const Scalar*, Integer) defined in Memory.h. See it for more + * documentation. + */ +template +static inline Index first_aligned(const DenseBase& m) { + enum { ReturnZero = (int(evaluator::Alignment) >= Alignment) || !(Derived::Flags & DirectAccessBit) }; + return first_aligned_impl::run(m.derived()); +} + +template +static inline Index first_default_aligned(const DenseBase& m) { + typedef typename Derived::Scalar Scalar; + typedef typename packet_traits::type DefaultPacketType; + return internal::first_aligned::alignment), Derived>(m); +} + +template ::ret> +struct inner_stride_at_compile_time { + enum { ret = traits::InnerStrideAtCompileTime }; +}; + +template +struct inner_stride_at_compile_time { + enum { ret = 0 }; +}; + +template ::ret> +struct outer_stride_at_compile_time { + enum { ret = traits::OuterStrideAtCompileTime }; +}; + +template +struct outer_stride_at_compile_time { + enum { ret = 0 }; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_DENSECOEFFSBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseStorage.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseStorage.h new file mode 100644 index 0000000..2892127 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DenseStorage.h @@ -0,0 +1,546 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2009 Benoit Jacob +// Copyright (C) 2010-2013 Hauke Heibel +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MATRIXSTORAGE_H +#define EIGEN_MATRIXSTORAGE_H + +#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN +#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) \ + X; \ + EIGEN_DENSE_STORAGE_CTOR_PLUGIN; +#else +#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) +#endif + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +#if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT) +#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) +#else +#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) \ + eigen_assert((is_constant_evaluated() || (std::uintptr_t(array) % Alignment == 0)) && \ + "this assertion is explained here: " \ + "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ + " **** READ THIS WEB PAGE !!! ****"); +#endif + +#if EIGEN_STACK_ALLOCATION_LIMIT +#define EIGEN_MAKE_STACK_ALLOCATION_ASSERT(X) \ + EIGEN_STATIC_ASSERT(X <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG) +#else +#define EIGEN_MAKE_STACK_ALLOCATION_ASSERT(X) +#endif + +/** \internal + * Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned: + * to 16 bytes boundary if the total size is a multiple of 16 bytes. + */ + +template ::value> +struct plain_array { + EIGEN_ALIGN_TO_BOUNDARY(Alignment) T array[Size]; +#if defined(EIGEN_NO_DEBUG) || defined(EIGEN_TESTING_PLAINOBJECT_CTOR) + EIGEN_DEVICE_FUNC constexpr plain_array() = default; +#else + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plain_array() { + EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(Alignment) + EIGEN_MAKE_STACK_ALLOCATION_ASSERT(Size * sizeof(T)) + } +#endif +}; + +template +struct plain_array { + // on some 32-bit platforms, stack-allocated arrays are aligned to 4 bytes, not the preferred alignment of T + EIGEN_ALIGN_TO_BOUNDARY(alignof(T)) T array[Size]; +#if defined(EIGEN_NO_DEBUG) || defined(EIGEN_TESTING_PLAINOBJECT_CTOR) + EIGEN_DEVICE_FUNC constexpr plain_array() = default; +#else + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plain_array() { EIGEN_MAKE_STACK_ALLOCATION_ASSERT(Size * sizeof(T)) } +#endif +}; + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap_plain_array(plain_array& a, + plain_array& b, + Index a_size, Index b_size) { + Index common_size = numext::mini(a_size, b_size); + std::swap_ranges(a.array, a.array + common_size, b.array); + if (a_size > b_size) + smart_copy(a.array + common_size, a.array + a_size, b.array + common_size); + else if (b_size > a_size) + smart_copy(b.array + common_size, b.array + b_size, a.array + common_size); +} + +template +class DenseStorage_impl { + plain_array m_data; + + public: +#ifndef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(const DenseStorage_impl&) = default; +#else + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl() { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + smart_copy(other.m_data.array, other.m_data.array + Size, m_data.array); + } +#endif + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + numext::swap(m_data, other.m_data); + } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return Rows * Cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data.array; } +}; +template +class DenseStorage_impl { + plain_array m_data; + Index m_rows = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index /*cols*/) + : m_rows(rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_rows = other.m_rows; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); + numext::swap(m_rows, other.m_rows); + } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index rows, Index /*cols*/) { m_rows = rows; } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index rows, Index /*cols*/) { m_rows = rows; } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * Cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data.array; } +}; +template +class DenseStorage_impl { + plain_array m_data; + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index /*rows*/, Index cols) + : m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_cols = other.m_cols; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index cols) { m_cols = cols; } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index /*rows*/, Index cols) { m_cols = cols; } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data.array; } +}; +template +class DenseStorage_impl { + plain_array m_data; + Index m_rows = 0; + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_rows(other.m_rows), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index cols) + : m_rows(rows), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + EIGEN_UNUSED_VARIABLE(size) + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + smart_copy(other.m_data.array, other.m_data.array + other.size(), m_data.array); + m_rows = other.m_rows; + m_cols = other.m_cols; + return *this; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap(DenseStorage_impl& other) { + swap_plain_array(m_data, other.m_data, size(), other.size()); + numext::swap(m_rows, other.m_rows); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data.array; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data.array; } +}; +// null matrix variants +template +class DenseStorage_impl { + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl&) {} + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index /*rows*/, Index /*cols*/) {} + EIGEN_DEVICE_FUNC constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return Rows * Cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return nullptr; } +}; +template +class DenseStorage_impl { + Index m_rows = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(Index /*size*/, Index rows, Index /*cols*/) : m_rows(rows) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { numext::swap(m_rows, other.m_rows); } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index rows, Index /*cols*/) { m_rows = rows; } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index rows, Index /*cols*/) { m_rows = rows; } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * Cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return nullptr; } +}; +template +class DenseStorage_impl { + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(Index /*size*/, Index /*rows*/, Index cols) : m_cols(cols) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { numext::swap(m_cols, other.m_cols); } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index /*rows*/, Index cols) { m_cols = cols; } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index /*rows*/, Index cols) { m_cols = cols; } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return nullptr; } +}; +template +class DenseStorage_impl { + Index m_rows = 0; + Index m_cols = 0; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(Index /*size*/, Index rows, Index cols) : m_rows(rows), m_cols(cols) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(const DenseStorage_impl&) = default; + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_rows, other.m_rows); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC constexpr void conservativeResize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr void resize(Index /*size*/, Index rows, Index cols) { + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return nullptr; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return nullptr; } +}; +// fixed-size matrix with dynamic memory allocation not currently supported +template +class DenseStorage_impl {}; +// dynamic-sized variants +template +class DenseStorage_impl { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_rows = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto(other.size())), m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index /*cols*/) + : m_data(conditional_aligned_new_auto(size)), m_rows(rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_rows(other.m_rows) { + other.m_data = nullptr; + other.m_rows = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_rows, other.m_rows); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index rows, Index /*cols*/) { + m_data = conditional_aligned_realloc_new_auto(m_data, size, this->size()); + m_rows = rows; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index rows, Index /*cols*/) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto(m_data, oldSize); + m_data = conditional_aligned_new_auto(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_rows = rows; + } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return Cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * Cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data; } +}; +template +class DenseStorage_impl { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_cols = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto(other.size())), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index /*rows*/, Index cols) + : m_data(conditional_aligned_new_auto(size)), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_cols(other.m_cols) { + other.m_data = nullptr; + other.m_cols = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index /*rows*/, Index cols) { + m_data = conditional_aligned_realloc_new_auto(m_data, size, this->size()); + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index /*rows*/, Index cols) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto(m_data, oldSize); + m_data = conditional_aligned_new_auto(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return Rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return Rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data; } +}; +template +class DenseStorage_impl { + static constexpr bool Align = (Options & DontAlign) == 0; + T* m_data = nullptr; + Index m_rows = 0; + Index m_cols = 0; + + public: + static constexpr int Size = Dynamic; + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl() = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(const DenseStorage_impl& other) + : m_data(conditional_aligned_new_auto(other.size())), m_rows(other.m_rows), m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = other.size()) + smart_copy(other.m_data, other.m_data + other.size(), m_data); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl(Index size, Index rows, Index cols) + : m_data(conditional_aligned_new_auto(size)), m_rows(rows), m_cols(cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl(DenseStorage_impl&& other) noexcept + : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) { + other.m_data = nullptr; + other.m_rows = 0; + other.m_cols = 0; + } + EIGEN_DEVICE_FUNC ~DenseStorage_impl() { conditional_aligned_delete_auto(m_data, size()); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr DenseStorage_impl& operator=(const DenseStorage_impl& other) { + resize(other.size(), other.rows(), other.cols()); + smart_copy(other.m_data, other.m_data + other.size(), m_data); + return *this; + } + EIGEN_DEVICE_FUNC constexpr DenseStorage_impl& operator=(DenseStorage_impl&& other) noexcept { + this->swap(other); + return *this; + } + EIGEN_DEVICE_FUNC constexpr void swap(DenseStorage_impl& other) noexcept { + numext::swap(m_data, other.m_data); + numext::swap(m_rows, other.m_rows); + numext::swap(m_cols, other.m_cols); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void conservativeResize(Index size, Index rows, Index cols) { + m_data = conditional_aligned_realloc_new_auto(m_data, size, this->size()); + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index size, Index rows, Index cols) { + Index oldSize = this->size(); + if (oldSize != size) { + conditional_aligned_delete_auto(m_data, oldSize); + m_data = conditional_aligned_new_auto(size); + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) + } + m_rows = rows; + m_cols = cols; + } + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + EIGEN_DEVICE_FUNC constexpr Index size() const { return m_rows * m_cols; } + EIGEN_DEVICE_FUNC constexpr T* data() { return m_data; } + EIGEN_DEVICE_FUNC constexpr const T* data() const { return m_data; } +}; +template +struct use_default_move { + static constexpr bool DynamicObject = Size == Dynamic; + static constexpr bool TrivialObject = + (!NumTraits::RequireInitialization) && (Rows >= 0) && (Cols >= 0) && (Size == Rows * Cols); + static constexpr bool value = DynamicObject || TrivialObject; +}; +} // end namespace internal + +/** \internal + * + * \class DenseStorage_impl + * \ingroup Core_Module + * + * \brief Stores the data of a matrix + * + * This class stores the data of fixed-size, dynamic-size or mixed matrices + * in a way as compact as possible. + * + * \sa Matrix + */ +template ::value> +class DenseStorage : public internal::DenseStorage_impl { + using Base = internal::DenseStorage_impl; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage(const DenseStorage&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage(Index size, Index rows, Index cols) : Base(size, rows, cols) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage& operator=(const DenseStorage&) = default; + // if DenseStorage meets the requirements of use_default_move, then use the move construction and move assignment + // operation defined in DenseStorage_impl, or the compiler-generated version if none is defined + EIGEN_DEVICE_FUNC constexpr DenseStorage(DenseStorage&&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage& operator=(DenseStorage&&) = default; +}; +template +class DenseStorage + : public internal::DenseStorage_impl { + using Base = internal::DenseStorage_impl; + + public: + EIGEN_DEVICE_FUNC constexpr DenseStorage() = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage(const DenseStorage&) = default; + EIGEN_DEVICE_FUNC constexpr DenseStorage(Index size, Index rows, Index cols) : Base(size, rows, cols) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage& operator=(const DenseStorage&) = default; + // if DenseStorage does not meet the requirements of use_default_move, then defer to the copy construction and copy + // assignment behavior + EIGEN_DEVICE_FUNC constexpr DenseStorage(DenseStorage&& other) + : DenseStorage(static_cast(other)) {} + EIGEN_DEVICE_FUNC constexpr DenseStorage& operator=(DenseStorage&& other) { + *this = other; + return *this; + } +}; + +} // end namespace Eigen + +#endif // EIGEN_MATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DeviceWrapper.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DeviceWrapper.h new file mode 100644 index 0000000..1a326ae --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DeviceWrapper.h @@ -0,0 +1,153 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2023 Charlie Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DEVICEWRAPPER_H +#define EIGEN_DEVICEWRAPPER_H + +namespace Eigen { +template +struct DeviceWrapper { + using Base = EigenBase>; + using Scalar = typename Derived::Scalar; + + EIGEN_DEVICE_FUNC DeviceWrapper(Base& xpr, Device& device) : m_xpr(xpr.derived()), m_device(device) {} + EIGEN_DEVICE_FUNC DeviceWrapper(const Base& xpr, Device& device) : m_xpr(xpr.derived()), m_device(device) {} + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const EigenBase& other) { + using AssignOp = internal::assign_op; + internal::call_assignment(*this, other.derived(), AssignOp()); + return m_xpr; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const EigenBase& other) { + using AddAssignOp = internal::add_assign_op; + internal::call_assignment(*this, other.derived(), AddAssignOp()); + return m_xpr; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const EigenBase& other) { + using SubAssignOp = internal::sub_assign_op; + internal::call_assignment(*this, other.derived(), SubAssignOp()); + return m_xpr; + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& derived() { return m_xpr; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Device& device() { return m_device; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NoAlias noalias() { + return NoAlias(*this); + } + + Derived& m_xpr; + Device& m_device; +}; + +namespace internal { + +// this is where we differentiate between lazy assignment and specialized kernels (e.g. matrix products) +template ::Shape, + typename evaluator_traits::Shape>::Kind, + typename EnableIf = void> +struct AssignmentWithDevice; + +// unless otherwise specified, use the default product implementation +template +struct AssignmentWithDevice, Functor, Device, Dense2Dense, Weak> { + using SrcXprType = Product; + using Base = Assignment; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func, + Device&) { + Base::run(dst, src, func); + } +}; + +// specialization for coeffcient-wise assignment +template +struct AssignmentWithDevice { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, const Functor& func, + Device& device) { +#ifndef EIGEN_NO_DEBUG + internal::check_for_aliasing(dst, src); +#endif + + call_dense_assignment_loop(dst, src, func, device); + } +}; + +// this allows us to use the default evaluation scheme if it is not specialized for the device +template +struct dense_assignment_loop_with_device { + using Base = dense_assignment_loop; + static EIGEN_DEVICE_FUNC constexpr void run(Kernel& kernel, Device&) { Base::run(kernel); } +}; + +// entry point for a generic expression with device +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_assignment_no_alias(DeviceWrapper dst, + const Src& src, const Func& func) { + enum { + NeedToTranspose = ((int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1) || + (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)) && + int(Dst::SizeAtCompileTime) != 1 + }; + + using ActualDstTypeCleaned = std::conditional_t, Dst>; + using ActualDstType = std::conditional_t, Dst&>; + ActualDstType actualDst(dst.derived()); + + // TODO: check whether this is the right place to perform these checks: + EIGEN_STATIC_ASSERT_LVALUE(Dst) + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned, Src) + EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename ActualDstTypeCleaned::Scalar, typename Src::Scalar); + + // this provides a mechanism for specializing simple assignments, matrix products, etc + AssignmentWithDevice::run(actualDst, src, func, dst.device()); +} + +// copy and pasted from AssignEvaluator except forward device to kernel +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, + const Functor& func, Device& device) { + using DstEvaluatorType = evaluator; + using SrcEvaluatorType = evaluator; + + SrcEvaluatorType srcEvaluator(src); + + // NOTE To properly handle A = (A*A.transpose())/s with A rectangular, + // we need to resize the destination after the source evaluator has been created. + resize_if_allowed(dst, src, func); + + DstEvaluatorType dstEvaluator(dst); + + using Kernel = generic_dense_assignment_kernel; + + Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); + + dense_assignment_loop_with_device::run(kernel, device); +} + +} // namespace internal + +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper EigenBase::device(Device& device) { + return DeviceWrapper(derived(), device); +} + +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper EigenBase::device( + Device& device) const { + return DeviceWrapper(derived(), device); +} +} // namespace Eigen +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Diagonal.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Diagonal.h new file mode 100644 index 0000000..61a4784 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Diagonal.h @@ -0,0 +1,221 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2007-2009 Benoit Jacob +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DIAGONAL_H +#define EIGEN_DIAGONAL_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class Diagonal + * \ingroup Core_Module + * + * \brief Expression of a diagonal/subdiagonal/superdiagonal in a matrix + * + * \tparam MatrixType the type of the object in which we are taking a sub/main/super diagonal + * \tparam DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal. + * A positive value means a superdiagonal, a negative value means a subdiagonal. + * You can also use DynamicIndex so the index can be set at runtime. + * + * The matrix is not required to be square. + * + * This class represents an expression of the main diagonal, or any sub/super diagonal + * of a square matrix. It is the return type of MatrixBase::diagonal() and MatrixBase::diagonal(Index) and most of the + * time this is the only way it is used. + * + * \sa MatrixBase::diagonal(), MatrixBase::diagonal(Index) + */ + +namespace internal { +template +struct traits > : traits { + typedef typename ref_selector::type MatrixTypeNested; + typedef std::remove_reference_t MatrixTypeNested_; + typedef typename MatrixType::StorageKind StorageKind; + enum { + RowsAtCompileTime = (int(DiagIndex) == DynamicIndex || int(MatrixType::SizeAtCompileTime) == Dynamic) + ? Dynamic + : (plain_enum_min(MatrixType::RowsAtCompileTime - plain_enum_max(-DiagIndex, 0), + MatrixType::ColsAtCompileTime - plain_enum_max(DiagIndex, 0))), + ColsAtCompileTime = 1, + MaxRowsAtCompileTime = + int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic + : DiagIndex == DynamicIndex + ? min_size_prefer_fixed(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime) + : (plain_enum_min(MatrixType::MaxRowsAtCompileTime - plain_enum_max(-DiagIndex, 0), + MatrixType::MaxColsAtCompileTime - plain_enum_max(DiagIndex, 0))), + MaxColsAtCompileTime = 1, + MaskLvalueBit = is_lvalue::value ? LvalueBit : 0, + Flags = (unsigned int)MatrixTypeNested_::Flags & (RowMajorBit | MaskLvalueBit | DirectAccessBit) & + ~RowMajorBit, // FIXME DirectAccessBit should not be handled by expressions + MatrixTypeOuterStride = outer_stride_at_compile_time::ret, + InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride + 1, + OuterStrideAtCompileTime = 0 + }; +}; +} // namespace internal + +template +class Diagonal : public internal::dense_xpr_base >::type { + public: + enum { DiagIndex = DiagIndex_ }; + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) + + EIGEN_DEVICE_FUNC constexpr explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) + : m_matrix(matrix), m_index(a_index) { + eigen_assert(a_index <= m_matrix.cols() && -a_index <= m_matrix.rows()); + } + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) + + EIGEN_DEVICE_FUNC constexpr inline Index rows() const { + return m_index.value() < 0 ? numext::mini(m_matrix.cols(), m_matrix.rows() + m_index.value()) + : numext::mini(m_matrix.rows(), m_matrix.cols() - m_index.value()); + } + + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return 1; } + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_matrix.outerStride() + 1; } + + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 0; } + + typedef std::conditional_t::value, Scalar, const Scalar> ScalarWithConstIfNotLvalue; + + EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue* data() { + return rows() > 0 ? &(m_matrix.coeffRef(rowOffset(), colOffset())) : nullptr; + } + EIGEN_DEVICE_FUNC inline const Scalar* data() const { + return rows() > 0 ? &(m_matrix.coeffRef(rowOffset(), colOffset())) : nullptr; + } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index) { + EIGEN_STATIC_ASSERT_LVALUE(MatrixType) + return m_matrix.coeffRef(row + rowOffset(), row + colOffset()); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index) const { + return m_matrix.coeffRef(row + rowOffset(), row + colOffset()); + } + + EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index row, Index) const { + return m_matrix.coeff(row + rowOffset(), row + colOffset()); + } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index idx) { + EIGEN_STATIC_ASSERT_LVALUE(MatrixType) + return m_matrix.coeffRef(idx + rowOffset(), idx + colOffset()); + } + + EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index idx) const { + return m_matrix.coeffRef(idx + rowOffset(), idx + colOffset()); + } + + EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index idx) const { + return m_matrix.coeff(idx + rowOffset(), idx + colOffset()); + } + + EIGEN_DEVICE_FUNC constexpr inline const internal::remove_all_t& nestedExpression() + const { + return m_matrix; + } + + EIGEN_DEVICE_FUNC constexpr inline Index index() const { return m_index.value(); } + + protected: + typename internal::ref_selector::non_const_type m_matrix; + const internal::variable_if_dynamicindex m_index; + + private: + // some compilers may fail to optimize std::max etc in case of compile-time constants... + EIGEN_DEVICE_FUNC constexpr Index absDiagIndex() const noexcept { + return m_index.value() > 0 ? m_index.value() : -m_index.value(); + } + EIGEN_DEVICE_FUNC constexpr Index rowOffset() const noexcept { return m_index.value() > 0 ? 0 : -m_index.value(); } + EIGEN_DEVICE_FUNC constexpr Index colOffset() const noexcept { return m_index.value() > 0 ? m_index.value() : 0; } + // trigger a compile-time error if someone try to call packet + template + typename MatrixType::PacketReturnType packet(Index) const; + template + typename MatrixType::PacketReturnType packet(Index, Index) const; +}; + +/** \returns an expression of the main diagonal of the matrix \c *this + * + * \c *this is not required to be square. + * + * Example: \include MatrixBase_diagonal.cpp + * Output: \verbinclude MatrixBase_diagonal.out + * + * \sa class Diagonal */ +template +EIGEN_DEVICE_FUNC constexpr typename MatrixBase::DiagonalReturnType MatrixBase::diagonal() { + return DiagonalReturnType(derived()); +} + +/** This is the const version of diagonal(). */ +template +EIGEN_DEVICE_FUNC constexpr const typename MatrixBase::ConstDiagonalReturnType MatrixBase::diagonal() + const { + return ConstDiagonalReturnType(derived()); +} + +/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this + * + * \c *this is not required to be square. + * + * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 + * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. + * + * Example: \include MatrixBase_diagonal_int.cpp + * Output: \verbinclude MatrixBase_diagonal_int.out + * + * \sa MatrixBase::diagonal(), class Diagonal */ +template +EIGEN_DEVICE_FUNC constexpr Diagonal MatrixBase::diagonal(Index index) { + return Diagonal(derived(), index); +} + +/** This is the const version of diagonal(Index). */ +template +EIGEN_DEVICE_FUNC constexpr const Diagonal MatrixBase::diagonal( + Index index) const { + return Diagonal(derived(), index); +} + +/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this + * + * \c *this is not required to be square. + * + * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 + * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. + * + * Example: \include MatrixBase_diagonal_template_int.cpp + * Output: \verbinclude MatrixBase_diagonal_template_int.out + * + * \sa MatrixBase::diagonal(), class Diagonal */ +template +template +EIGEN_DEVICE_FUNC constexpr Diagonal MatrixBase::diagonal() { + return Diagonal(derived()); +} + +/** This is the const version of diagonal(). */ +template +template +EIGEN_DEVICE_FUNC constexpr const Diagonal MatrixBase::diagonal() const { + return Diagonal(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_DIAGONAL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalMatrix.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalMatrix.h new file mode 100644 index 0000000..c14d081 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalMatrix.h @@ -0,0 +1,473 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// Copyright (C) 2007-2009 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DIAGONALMATRIX_H +#define EIGEN_DIAGONALMATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class DiagonalBase + * \ingroup Core_Module + * + * \brief Base class for diagonal matrices and expressions + * + * This is the base class that is inherited by diagonal matrix and related expression + * types, which internally use a vector for storing the diagonal entries. Diagonal + * types always represent square matrices. + * + * \tparam Derived is the derived type, a DiagonalMatrix or DiagonalWrapper. + * + * \sa class DiagonalMatrix, class DiagonalWrapper + */ +template +class DiagonalBase : public EigenBase { + public: + typedef typename internal::traits::DiagonalVectorType DiagonalVectorType; + typedef typename DiagonalVectorType::Scalar Scalar; + typedef typename DiagonalVectorType::RealScalar RealScalar; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; + + enum { + RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, + ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, + MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, + MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, + IsVectorAtCompileTime = 0, + Flags = NoPreferredStorageOrderBit + }; + + typedef Matrix + DenseMatrixType; + typedef DenseMatrixType DenseType; + typedef DiagonalMatrix + PlainObject; + + /** \returns a reference to the derived object. */ + EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast(this); } + /** \returns a const reference to the derived object. */ + EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast(this); } + + /** + * Constructs a dense matrix from \c *this. Note, this directly returns a dense matrix type, + * not an expression. + * \returns A dense matrix, with its diagonal entries set from the derived object. */ + EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); } + + /** \returns a reference to the derived object's vector of diagonal coefficients. */ + EIGEN_DEVICE_FUNC inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); } + /** \returns a const reference to the derived object's vector of diagonal coefficients. */ + EIGEN_DEVICE_FUNC inline DiagonalVectorType& diagonal() { return derived().diagonal(); } + + /** \returns the value of the coefficient as if \c *this was a dense matrix. */ + EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const { + eigen_assert(row >= 0 && col >= 0 && row < rows() && col <= cols()); + return row == col ? diagonal().coeff(row) : Scalar(0); + } + + /** \returns the number of rows. */ + EIGEN_DEVICE_FUNC constexpr Index rows() const { return diagonal().size(); } + /** \returns the number of columns. */ + EIGEN_DEVICE_FUNC constexpr Index cols() const { return diagonal().size(); } + + /** \returns the diagonal matrix product of \c *this by the dense matrix, \a matrix */ + template + EIGEN_DEVICE_FUNC const Product operator*( + const MatrixBase& matrix) const { + return Product(derived(), matrix.derived()); + } + + template + using DiagonalProductReturnType = DiagonalWrapper; + + /** \returns the diagonal matrix product of \c *this by the diagonal matrix \a other */ + template + EIGEN_DEVICE_FUNC const DiagonalProductReturnType operator*( + const DiagonalBase& other) const { + return diagonal().cwiseProduct(other.diagonal()).asDiagonal(); + } + + using DiagonalInverseReturnType = + DiagonalWrapper, const DiagonalVectorType>>; + + /** \returns the inverse \c *this. Computed as the coefficient-wise inverse of the diagonal. */ + EIGEN_DEVICE_FUNC inline const DiagonalInverseReturnType inverse() const { + return diagonal().cwiseInverse().asDiagonal(); + } + + using DiagonalScaleReturnType = + DiagonalWrapper; + + /** \returns the product of \c *this by the scalar \a scalar */ + EIGEN_DEVICE_FUNC inline const DiagonalScaleReturnType operator*(const Scalar& scalar) const { + return (diagonal() * scalar).asDiagonal(); + } + + using ScaleDiagonalReturnType = + DiagonalWrapper; + + /** \returns the product of a scalar and the diagonal matrix \a other */ + EIGEN_DEVICE_FUNC friend inline const ScaleDiagonalReturnType operator*(const Scalar& scalar, + const DiagonalBase& other) { + return (scalar * other.diagonal()).asDiagonal(); + } + + template + using DiagonalSumReturnType = DiagonalWrapper; + + /** \returns the sum of \c *this and the diagonal matrix \a other */ + template + EIGEN_DEVICE_FUNC inline const DiagonalSumReturnType operator+( + const DiagonalBase& other) const { + return (diagonal() + other.diagonal()).asDiagonal(); + } + + template + using DiagonalDifferenceReturnType = DiagonalWrapper; + + /** \returns the difference of \c *this and the diagonal matrix \a other */ + template + EIGEN_DEVICE_FUNC inline const DiagonalDifferenceReturnType operator-( + const DiagonalBase& other) const { + return (diagonal() - other.diagonal()).asDiagonal(); + } +}; + +/** \class DiagonalMatrix + * \ingroup Core_Module + * + * \brief Represents a diagonal matrix with its storage + * + * \tparam Scalar_ the type of coefficients + * \tparam SizeAtCompileTime the dimension of the matrix, or Dynamic + * \tparam MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults + * to SizeAtCompileTime. Most of the time, you do not need to specify it. + * + * \sa class DiagonalBase, class DiagonalWrapper + */ + +namespace internal { +template +struct traits> + : traits> { + typedef Matrix DiagonalVectorType; + typedef DiagonalShape StorageKind; + enum { Flags = LvalueBit | NoPreferredStorageOrderBit | NestByRefBit }; +}; +} // namespace internal +template +class DiagonalMatrix : public DiagonalBase> { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename internal::traits::DiagonalVectorType DiagonalVectorType; + typedef const DiagonalMatrix& Nested; + typedef Scalar_ Scalar; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; +#endif + + protected: + DiagonalVectorType m_diagonal; + + public: + /** const version of diagonal(). */ + EIGEN_DEVICE_FUNC constexpr inline const DiagonalVectorType& diagonal() const { return m_diagonal; } + /** \returns a reference to the stored vector of diagonal coefficients. */ + EIGEN_DEVICE_FUNC constexpr inline DiagonalVectorType& diagonal() { return m_diagonal; } + + /** Default constructor without initialization */ + EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix() {} + + /** Constructs a diagonal matrix with given dimension */ + EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(Index dim) : m_diagonal(dim) {} + + /** 2D constructor. */ + EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x, y) {} + + /** 3D constructor. */ + EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) + : m_diagonal(x, y, z) {} + + /** \brief Construct a diagonal matrix with fixed size from an arbitrary number of coefficients. + * + * \warning To construct a diagonal matrix of fixed size, the number of values passed to this + * constructor must match the fixed dimension of \c *this. + * + * \sa DiagonalMatrix(const Scalar&, const Scalar&) + * \sa DiagonalMatrix(const Scalar&, const Scalar&, const Scalar&) + */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE DiagonalMatrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, + const ArgTypes&... args) + : m_diagonal(a0, a1, a2, args...) {} + + /** \brief Constructs a DiagonalMatrix and initializes it by elements given by an initializer list of initializer + * lists \cpp11 + */ + EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE DiagonalMatrix( + const std::initializer_list>& list) + : m_diagonal(list) {} + + /** \brief Constructs a DiagonalMatrix from an r-value diagonal vector type */ + EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(DiagonalVectorType&& diag) : m_diagonal(std::move(diag)) {} + + /** Copy constructor. */ + template + EIGEN_DEVICE_FUNC constexpr inline DiagonalMatrix(const DiagonalBase& other) + : m_diagonal(other.diagonal()) {} + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */ + inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {} +#endif + + /** generic constructor from expression of the diagonal coefficients */ + template + EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalMatrix(const MatrixBase& other) + : m_diagonal(other) {} + + /** Copy operator. */ + template + EIGEN_DEVICE_FUNC DiagonalMatrix& operator=(const DiagonalBase& other) { + m_diagonal = other.diagonal(); + return *this; + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + EIGEN_DEVICE_FUNC DiagonalMatrix& operator=(const DiagonalMatrix& other) { + m_diagonal = other.diagonal(); + return *this; + } +#endif + + typedef DiagonalWrapper, DiagonalVectorType>> + InitializeReturnType; + + typedef DiagonalWrapper, DiagonalVectorType>> + ZeroInitializeReturnType; + + /** Initializes a diagonal matrix of size SizeAtCompileTime with coefficients set to zero */ + EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero() { return DiagonalVectorType::Zero().asDiagonal(); } + /** Initializes a diagonal matrix of size dim with coefficients set to zero */ + EIGEN_DEVICE_FUNC static const ZeroInitializeReturnType Zero(Index size) { + return DiagonalVectorType::Zero(size).asDiagonal(); + } + /** Initializes a identity matrix of size SizeAtCompileTime */ + EIGEN_DEVICE_FUNC static const InitializeReturnType Identity() { return DiagonalVectorType::Ones().asDiagonal(); } + /** Initializes a identity matrix of size dim */ + EIGEN_DEVICE_FUNC static const InitializeReturnType Identity(Index size) { + return DiagonalVectorType::Ones(size).asDiagonal(); + } + + /** Resizes to given size. */ + EIGEN_DEVICE_FUNC inline void resize(Index size) { m_diagonal.resize(size); } + /** Sets all coefficients to zero. */ + EIGEN_DEVICE_FUNC inline void setZero() { m_diagonal.setZero(); } + /** Resizes and sets all coefficients to zero. */ + EIGEN_DEVICE_FUNC inline void setZero(Index size) { m_diagonal.setZero(size); } + /** Sets this matrix to be the identity matrix of the current size. */ + EIGEN_DEVICE_FUNC inline void setIdentity() { m_diagonal.setOnes(); } + /** Sets this matrix to be the identity matrix of the given size. */ + EIGEN_DEVICE_FUNC inline void setIdentity(Index size) { m_diagonal.setOnes(size); } +}; + +/** \class DiagonalWrapper + * \ingroup Core_Module + * + * \brief Expression of a diagonal matrix + * + * \tparam DiagonalVectorType_ the type of the vector of diagonal coefficients + * + * This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients, + * instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal() + * and most of the time this is the only way that it is used. + * + * \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal() + */ + +namespace internal { +template +struct traits> { + typedef DiagonalVectorType_ DiagonalVectorType; + typedef typename DiagonalVectorType::Scalar Scalar; + typedef typename DiagonalVectorType::StorageIndex StorageIndex; + typedef DiagonalShape StorageKind; + typedef typename traits::XprKind XprKind; + enum { + RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, + ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, + MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, + MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, + Flags = (traits::Flags & LvalueBit) | NoPreferredStorageOrderBit + }; +}; +} // namespace internal + +template +class DiagonalWrapper : public DiagonalBase>, internal::no_assignment_operator { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef DiagonalVectorType_ DiagonalVectorType; + typedef DiagonalWrapper Nested; +#endif + + /** Constructor from expression of diagonal coefficients to wrap. */ + EIGEN_DEVICE_FUNC constexpr explicit inline DiagonalWrapper(DiagonalVectorType& a_diagonal) + : m_diagonal(a_diagonal) {} + + /** \returns a const reference to the wrapped expression of diagonal coefficients. */ + EIGEN_DEVICE_FUNC constexpr const DiagonalVectorType& diagonal() const { return m_diagonal; } + + protected: + typename DiagonalVectorType::Nested m_diagonal; +}; + +/** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients + * + * \only_for_vectors + * + * Example: \include MatrixBase_asDiagonal.cpp + * Output: \verbinclude MatrixBase_asDiagonal.out + * + * \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal() + **/ +template +EIGEN_DEVICE_FUNC constexpr const DiagonalWrapper MatrixBase::asDiagonal() const { + return DiagonalWrapper(derived()); +} + +/** \returns true if *this is approximately equal to a diagonal matrix, + * within the precision given by \a prec. + * + * Example: \include MatrixBase_isDiagonal.cpp + * Output: \verbinclude MatrixBase_isDiagonal.out + * + * \sa asDiagonal() + */ +template +bool MatrixBase::isDiagonal(const RealScalar& prec) const { + if (cols() != rows()) return false; + RealScalar maxAbsOnDiagonal = static_cast(-1); + for (Index j = 0; j < cols(); ++j) { + RealScalar absOnDiagonal = numext::abs(coeff(j, j)); + if (absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal; + } + for (Index j = 0; j < cols(); ++j) + for (Index i = 0; i < j; ++i) { + if (!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false; + if (!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false; + } + return true; +} + +/** \returns DiagonalWrapper. + * + * Example: \include MatrixBase_diagonalView.cpp + * Output: \verbinclude MatrixBase_diagonalView.out + * + * \sa diagonalView() + */ + +/** This is the non-const version of diagonalView() with DiagIndex_ . */ +template +template +EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> MatrixBase::diagonalView() { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived()); + return ReturnType(diag); +} + +/** This is the const version of diagonalView() with DiagIndex_ . */ +template +template +EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> MatrixBase::diagonalView() + const { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived()); + return ReturnType(diag); +} + +/** This is the non-const version of diagonalView() with dynamic index. */ +template +EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> MatrixBase::diagonalView( + Index index) { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived(), index); + return ReturnType(diag); +} + +/** This is the const version of diagonalView() with dynamic index. */ +template +EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> MatrixBase::diagonalView( + Index index) const { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived(), index); + return ReturnType(diag); +} + +namespace internal { + +template <> +struct storage_kind_to_shape { + typedef DiagonalShape Shape; +}; + +struct Diagonal2Dense {}; + +template <> +struct AssignmentKind { + typedef Diagonal2Dense Kind; +}; + +// Diagonal matrix to Dense assignment +template +struct Assignment { + static EIGEN_DEVICE_FUNC void run( + DstXprType& dst, const SrcXprType& src, + const internal::assign_op& /*func*/) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + dst.setZero(); + dst.diagonal() = src.diagonal(); + } + + static EIGEN_DEVICE_FUNC void run( + DstXprType& dst, const SrcXprType& src, + const internal::add_assign_op& /*func*/) { + dst.diagonal() += src.diagonal(); + } + + static EIGEN_DEVICE_FUNC void run( + DstXprType& dst, const SrcXprType& src, + const internal::sub_assign_op& /*func*/) { + dst.diagonal() -= src.diagonal(); + } +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_DIAGONALMATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalProduct.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalProduct.h new file mode 100644 index 0000000..bd0feea --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/DiagonalProduct.h @@ -0,0 +1,30 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2007-2009 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DIAGONALPRODUCT_H +#define EIGEN_DIAGONALPRODUCT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \returns the diagonal matrix product of \c *this by the diagonal matrix \a diagonal. + */ +template +template +EIGEN_DEVICE_FUNC inline const Product MatrixBase::operator*( + const DiagonalBase &a_diagonal) const { + return Product(derived(), a_diagonal.derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_DIAGONALPRODUCT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Dot.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Dot.h new file mode 100644 index 0000000..d0a30dd --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Dot.h @@ -0,0 +1,267 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008, 2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DOT_H +#define EIGEN_DOT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template ::Scalar> +struct squared_norm_impl { + using Real = typename NumTraits::Real; + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Real run(const Derived& a) { + return a.realView().cwiseAbs2().sum(); + } +}; + +template +struct squared_norm_impl { + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE bool run(const Derived& a) { return a.any(); } +}; + +} // end namespace internal + +/** \fn MatrixBase::dot + * \returns the dot product of *this with other. + * + * \only_for_vectors + * + * \note If the scalar type is complex numbers, then this function returns the hermitian + * (sesquilinear) dot product, conjugate-linear in the first variable and linear in the + * second variable. + * + * \sa squaredNorm(), norm() + */ +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE + typename ScalarBinaryOpTraits::Scalar, + typename internal::traits::Scalar>::ReturnType + MatrixBase::dot(const MatrixBase& other) const { + return internal::dot_impl::run(derived(), other.derived()); +} + +//---------- implementation of L2 norm and related functions ---------- + +/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the squared Frobenius norm. + * In both cases, it consists in the sum of the square of all the matrix entries. + * For vectors, this is also equal to the dot product of \c *this with itself. + * + * \sa dot(), norm(), lpNorm() + */ +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE typename NumTraits::Scalar>::Real +MatrixBase::squaredNorm() const { + return internal::squared_norm_impl::run(derived()); +} + +/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm. + * In both cases, it consists in the square root of the sum of the square of all the matrix entries. + * For vectors, this is also equal to the square root of the dot product of \c *this with itself. + * + * \sa lpNorm(), dot(), squaredNorm() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NumTraits::Scalar>::Real +MatrixBase::norm() const { + return numext::sqrt(squaredNorm()); +} + +/** \returns an expression of the quotient of \c *this by its own norm. + * + * \warning If the input vector is too small (i.e., this->norm()==0), + * then this function returns a copy of the input. + * + * \only_for_vectors + * + * \sa norm(), normalize() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::normalized() + const { + typedef typename internal::nested_eval::type Nested_; + Nested_ n(derived()); + RealScalar z = n.squaredNorm(); + // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU + if (z > RealScalar(0)) + return n / numext::sqrt(z); + else + return n; +} + +/** Normalizes the vector, i.e. divides it by its own norm. + * + * \only_for_vectors + * + * \warning If the input vector is too small (i.e., this->norm()==0), then \c *this is left unchanged. + * + * \sa norm(), normalized() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::normalize() { + RealScalar z = squaredNorm(); + // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU + if (z > RealScalar(0)) derived() /= numext::sqrt(z); +} + +/** \returns an expression of the quotient of \c *this by its own norm while avoiding underflow and overflow. + * + * \only_for_vectors + * + * This method is analogue to the normalized() method, but it reduces the risk of + * underflow and overflow when computing the norm. + * + * \warning If the input vector is too small (i.e., this->norm()==0), + * then this function returns a copy of the input. + * + * \sa stableNorm(), stableNormalize(), normalized() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject +MatrixBase::stableNormalized() const { + typedef typename internal::nested_eval::type Nested_; + Nested_ n(derived()); + RealScalar w = n.cwiseAbs().maxCoeff(); + RealScalar z = (n / w).squaredNorm(); + if (z > RealScalar(0)) + return n / (numext::sqrt(z) * w); + else + return n; +} + +/** Normalizes the vector while avoid underflow and overflow + * + * \only_for_vectors + * + * This method is analogue to the normalize() method, but it reduces the risk of + * underflow and overflow when computing the norm. + * + * \warning If the input vector is too small (i.e., this->norm()==0), then \c *this is left unchanged. + * + * \sa stableNorm(), stableNormalized(), normalize() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase::stableNormalize() { + RealScalar w = cwiseAbs().maxCoeff(); + RealScalar z = (derived() / w).squaredNorm(); + if (z > RealScalar(0)) derived() /= numext::sqrt(z) * w; +} + +//---------- implementation of other norms ---------- + +namespace internal { + +template +struct lpNorm_selector { + typedef typename NumTraits::Scalar>::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase& m) { + EIGEN_USING_STD(pow) + return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1) / p); + } +}; + +template +struct lpNorm_selector { + EIGEN_DEVICE_FUNC static inline typename NumTraits::Scalar>::Real run( + const MatrixBase& m) { + return m.cwiseAbs().sum(); + } +}; + +template +struct lpNorm_selector { + EIGEN_DEVICE_FUNC static inline typename NumTraits::Scalar>::Real run( + const MatrixBase& m) { + return m.norm(); + } +}; + +template +struct lpNorm_selector { + typedef typename NumTraits::Scalar>::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const MatrixBase& m) { + if (Derived::SizeAtCompileTime == 0 || (Derived::SizeAtCompileTime == Dynamic && m.size() == 0)) + return RealScalar(0); + return m.cwiseAbs().maxCoeff(); + } +}; + +} // end namespace internal + +/** \returns the \b coefficient-wise \f$ \ell^p \f$ norm of \c *this, that is, returns the p-th root of the sum of the + * p-th powers of the absolute values of the coefficients of \c *this. If \a p is the special value \a Eigen::Infinity, + * this function returns the \f$ \ell^\infty \f$ norm, that is the maximum of the absolute values of the coefficients of + * \c *this. + * + * In all cases, if \c *this is empty, then the value 0 is returned. + * + * \note For matrices, this function does not compute the operator-norm. That is, if \c *this is a matrix, then its + * coefficients are interpreted as a 1D vector. Nonetheless, you can easily compute the 1-norm and \f$\infty\f$-norm + * matrix operator norms using \link TutorialReductionsVisitorsBroadcastingReductionsNorm partial reductions \endlink. + * + * \sa norm() + */ +template +template +#ifndef EIGEN_PARSED_BY_DOXYGEN +EIGEN_DEVICE_FUNC inline typename NumTraits::Scalar>::Real +#else +EIGEN_DEVICE_FUNC MatrixBase::RealScalar +#endif +MatrixBase::lpNorm() const { + return internal::lpNorm_selector::run(*this); +} + +//---------- implementation of isOrthogonal / isUnitary ---------- + +/** \returns true if *this is approximately orthogonal to \a other, + * within the precision given by \a prec. + * + * Example: \include MatrixBase_isOrthogonal.cpp + * Output: \verbinclude MatrixBase_isOrthogonal.out + */ +template +template +bool MatrixBase::isOrthogonal(const MatrixBase& other, const RealScalar& prec) const { + typename internal::nested_eval::type nested(derived()); + typename internal::nested_eval::type otherNested(other.derived()); + return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm(); +} + +/** \returns true if *this is approximately an unitary matrix, + * within the precision given by \a prec. In the case where the \a Scalar + * type is real numbers, a unitary matrix is an orthogonal matrix, whence the name. + * + * \note This can be used to check whether a family of vectors forms an orthonormal basis. + * Indeed, \c m.isUnitary() returns true if and only if the columns (equivalently, the rows) of m form an + * orthonormal basis. + * + * Example: \include MatrixBase_isUnitary.cpp + * Output: \verbinclude MatrixBase_isUnitary.out + */ +template +bool MatrixBase::isUnitary(const RealScalar& prec) const { + typename internal::nested_eval::type self(derived()); + for (Index i = 0; i < cols(); ++i) { + if (!internal::isApprox(self.col(i).squaredNorm(), static_cast(1), prec)) return false; + for (Index j = 0; j < i; ++j) + if (!internal::isMuchSmallerThan(self.col(i).dot(self.col(j)), static_cast(1), prec)) return false; + } + return true; +} + +} // end namespace Eigen + +#endif // EIGEN_DOT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/EigenBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/EigenBase.h new file mode 100644 index 0000000..dfe4a64 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/EigenBase.h @@ -0,0 +1,149 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Benoit Jacob +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_EIGENBASE_H +#define EIGEN_EIGENBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class EigenBase + * \ingroup Core_Module + * + * Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T). + * + * In other words, an EigenBase object is an object that can be copied into a MatrixBase. + * + * Besides MatrixBase-derived classes, this also includes special matrix classes such as diagonal matrices, etc. + * + * Notice that this class is trivial, it is only used to disambiguate overloaded functions. + * + * \sa \blank \ref TopicClassHierarchy + */ +template +struct EigenBase { + // typedef typename internal::plain_matrix_type::type PlainObject; + + /** \brief The interface type of indices + * \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE. + * \sa StorageIndex, \ref TopicPreprocessorDirectives. + * DEPRECATED: Since Eigen 3.3, its usage is deprecated. Use Eigen::Index instead. + * Deprecation is not marked with a doxygen comment because there are too many existing usages to add the deprecation + * attribute. + */ + typedef Eigen::Index Index; + + // FIXME is it needed? + typedef typename internal::traits::StorageKind StorageKind; + + /** \returns a reference to the derived object */ + EIGEN_DEVICE_FUNC constexpr Derived& derived() { return *static_cast(this); } + /** \returns a const reference to the derived object */ + EIGEN_DEVICE_FUNC constexpr const Derived& derived() const { return *static_cast(this); } + + EIGEN_DEVICE_FUNC inline constexpr Derived& const_cast_derived() const { + return *static_cast(const_cast(this)); + } + EIGEN_DEVICE_FUNC constexpr inline const Derived& const_derived() const { return *static_cast(this); } + + /** \returns the number of rows. \sa cols(), RowsAtCompileTime */ + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return derived().rows(); } + /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().cols(); } + /** \returns the number of coefficients, which is rows()*cols(). + * \sa rows(), cols(), SizeAtCompileTime. */ + EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return rows() * cols(); } + + /** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */ + template + EIGEN_DEVICE_FUNC constexpr inline void evalTo(Dest& dst) const { + derived().evalTo(dst); + } + + /** \internal Don't use it, but do the equivalent: \code dst += *this; \endcode */ + template + EIGEN_DEVICE_FUNC constexpr inline void addTo(Dest& dst) const { + // This is the default implementation, + // derived class can reimplement it in a more optimized way. + typename Dest::PlainObject res(rows(), cols()); + evalTo(res); + dst += res; + } + + /** \internal Don't use it, but do the equivalent: \code dst -= *this; \endcode */ + template + EIGEN_DEVICE_FUNC constexpr inline void subTo(Dest& dst) const { + // This is the default implementation, + // derived class can reimplement it in a more optimized way. + typename Dest::PlainObject res(rows(), cols()); + evalTo(res); + dst -= res; + } + + /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheRight(*this); \endcode */ + template + EIGEN_DEVICE_FUNC constexpr inline void applyThisOnTheRight(Dest& dst) const { + // This is the default implementation, + // derived class can reimplement it in a more optimized way. + dst = dst * this->derived(); + } + + /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheLeft(*this); \endcode */ + template + EIGEN_DEVICE_FUNC constexpr inline void applyThisOnTheLeft(Dest& dst) const { + // This is the default implementation, + // derived class can reimplement it in a more optimized way. + dst = this->derived() * dst; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper device(Device& device); + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DeviceWrapper device(Device& device) const; +}; + +/*************************************************************************** + * Implementation of matrix base methods + ***************************************************************************/ + +/** \brief Copies the generic expression \a other into *this. + * + * \details The expression must provide a (templated) evalTo(Derived& dst) const + * function which does the actual job. In practice, this allows any user to write + * its own special matrix without having to modify MatrixBase + * + * \returns a reference to *this. + */ +template +template +EIGEN_DEVICE_FUNC constexpr Derived& DenseBase::operator=(const EigenBase& other) { + call_assignment(derived(), other.derived()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr Derived& DenseBase::operator+=(const EigenBase& other) { + call_assignment(derived(), other.derived(), internal::add_assign_op()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr Derived& DenseBase::operator-=(const EigenBase& other) { + call_assignment(derived(), other.derived(), internal::sub_assign_op()); + return derived(); +} + +} // end namespace Eigen + +#endif // EIGEN_EIGENBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fill.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fill.h new file mode 100644 index 0000000..cacf921 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fill.h @@ -0,0 +1,140 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2024 Charles Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_FILL_H +#define EIGEN_FILL_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct eigen_fill_helper : std::false_type {}; + +template +struct eigen_fill_helper> : std::true_type {}; + +template +struct eigen_fill_helper> : std::true_type {}; + +template +struct eigen_fill_helper> : eigen_fill_helper {}; + +template +struct eigen_fill_helper> + : std::integral_constant::value && + (Xpr::IsRowMajor ? (BlockRows == 1) : (BlockCols == 1))> {}; + +template +struct eigen_fill_helper>> : eigen_fill_helper {}; + +template +struct eigen_fill_helper>> + : std::integral_constant::value && + enum_eq_not_dynamic(OuterStride_, Xpr::InnerSizeAtCompileTime)> {}; + +template +struct eigen_fill_helper>> + : eigen_fill_helper>> {}; + +template +struct eigen_fill_helper>> + : eigen_fill_helper>> {}; + +template +struct eigen_fill_helper>> + : eigen_fill_helper>> {}; + +template +struct eigen_fill_impl { + using Scalar = typename Xpr::Scalar; + using Func = scalar_constant_op; + using PlainObject = typename Xpr::PlainObject; + using Constant = typename PlainObject::ConstantReturnType; + static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const Scalar& val) { + const Constant src(dst.rows(), dst.cols(), val); + run(dst, src); + } + template + static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const SrcXpr& src) { + call_dense_assignment_loop(dst, src, assign_op()); + } +}; + +#if EIGEN_COMP_MSVC || defined(EIGEN_GPU_COMPILE_PHASE) +template +struct eigen_fill_impl : eigen_fill_impl {}; +#else +template +struct eigen_fill_impl { + using Scalar = typename Xpr::Scalar; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const Scalar& val) { + const Scalar val_copy = val; + using std::fill_n; + fill_n(dst.data(), dst.size(), val_copy); + } + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) { + resize_if_allowed(dst, src, assign_op()); + const Scalar& val = src.functor()(); + run(dst, val); + } +}; +#endif + +template +struct eigen_memset_helper { + using Scalar = typename Xpr::Scalar; + static constexpr bool value = std::is_trivially_copyable::value && + !static_cast(NumTraits::RequireInitialization) && + eigen_fill_helper::value; +}; + +template +struct eigen_zero_impl { + using Scalar = typename Xpr::Scalar; + using PlainObject = typename Xpr::PlainObject; + using Zero = typename PlainObject::ZeroReturnType; + static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst) { + const Zero src(dst.rows(), dst.cols()); + run(dst, src); + } + template + static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const SrcXpr& src) { + call_dense_assignment_loop(dst, src, assign_op()); + } +}; + +template +struct eigen_zero_impl { + using Scalar = typename Xpr::Scalar; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst) { + const std::ptrdiff_t num_bytes = dst.size() * static_cast(sizeof(Scalar)); + if (num_bytes <= 0) return; + void* dst_ptr = static_cast(dst.data()); +#ifndef EIGEN_NO_DEBUG + eigen_assert((dst_ptr != nullptr) && "null pointer dereference error!"); +#endif + EIGEN_USING_STD(memset); + memset(dst_ptr, 0, static_cast(num_bytes)); + } + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) { + resize_if_allowed(dst, src, assign_op()); + run(dst); + } +}; + +} // namespace internal +} // namespace Eigen + +#endif // EIGEN_FILL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/FindCoeff.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/FindCoeff.h new file mode 100644 index 0000000..0102e8a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/FindCoeff.h @@ -0,0 +1,464 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2025 Charlie Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_FIND_COEFF_H +#define EIGEN_FIND_COEFF_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template ::IsInteger> +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return candidate > incumbent; + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pcmp_lt(incumbent, candidate); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) { + return (candidate > incumbent) || ((candidate != candidate) && (incumbent == incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) { + return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template +struct max_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return (candidate > incumbent) || ((candidate == candidate) && (incumbent != incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(candidate)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_max(a); + } +}; + +template ::IsInteger> +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return candidate < incumbent; + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pcmp_lt(candidate, incumbent); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline Scalar compareCoeff(const Scalar& incumbent, const Scalar& candidate) { + return (candidate < incumbent) || ((candidate != candidate) && (incumbent == incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) { + return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_coeff_functor { + EIGEN_DEVICE_FUNC inline bool compareCoeff(const Scalar& incumbent, const Scalar& candidate) const { + return (candidate < incumbent) || ((candidate == candidate) && (incumbent != incumbent)); + } + template + EIGEN_DEVICE_FUNC inline Packet comparePacket(const Packet& incumbent, const Packet& candidate) const { + return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(candidate)); + } + template + EIGEN_DEVICE_FUNC inline Scalar predux(const Packet& a) const { + return predux_min(a); + } +}; + +template +struct min_max_traits { + static constexpr bool PacketAccess = packet_traits::Vectorizable; +}; +template +struct functor_traits> : min_max_traits {}; +template +struct functor_traits> : min_max_traits {}; + +template +struct find_coeff_loop; +template +struct find_coeff_loop { + using Scalar = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& outer, Index& inner) { + Index outerSize = eval.outerSize(); + Index innerSize = eval.innerSize(); + + /* initialization performed in calling function */ + /* result = eval.coeff(0, 0); */ + /* outer = 0; */ + /* inner = 0; */ + + for (Index j = 0; j < outerSize; j++) { + for (Index i = 0; i < innerSize; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(j, i); + bool newRes = func.compareCoeff(res, xprCoeff); + if (newRes) { + outer = j; + inner = i; + res = xprCoeff; + } + } + } + } +}; +template +struct find_coeff_loop { + using Scalar = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& res, Index& index) { + Index size = eval.size(); + + /* initialization performed in calling function */ + /* result = eval.coeff(0); */ + /* index = 0; */ + + for (Index k = 0; k < size; k++) { + Scalar xprCoeff = eval.coeff(k); + bool newRes = func.compareCoeff(res, xprCoeff); + if (newRes) { + index = k; + res = xprCoeff; + } + } + } +}; +template +struct find_coeff_loop { + using ScalarImpl = find_coeff_loop; + using Scalar = typename Evaluator::Scalar; + using Packet = typename Evaluator::Packet; + static constexpr int PacketSize = unpacket_traits::size; + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& outer, + Index& inner) { + Index outerSize = eval.outerSize(); + Index innerSize = eval.innerSize(); + Index packetEnd = numext::round_down(innerSize, PacketSize); + + /* initialization performed in calling function */ + /* result = eval.coeff(0, 0); */ + /* outer = 0; */ + /* inner = 0; */ + + bool checkPacket = false; + + for (Index j = 0; j < outerSize; j++) { + Packet resultPacket = pset1(result); + for (Index i = 0; i < packetEnd; i += PacketSize) { + Packet xprPacket = eval.template packetByOuterInner(j, i); + if (predux_any(func.comparePacket(resultPacket, xprPacket))) { + outer = j; + inner = i; + result = func.predux(xprPacket); + resultPacket = pset1(result); + checkPacket = true; + } + } + + for (Index i = packetEnd; i < innerSize; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(j, i); + if (func.compareCoeff(result, xprCoeff)) { + outer = j; + inner = i; + result = xprCoeff; + checkPacket = false; + } + } + } + + if (checkPacket) { + result = eval.coeffByOuterInner(outer, inner); + Index i_end = inner + PacketSize; + for (Index i = inner; i < i_end; i++) { + Scalar xprCoeff = eval.coeffByOuterInner(outer, i); + if (func.compareCoeff(result, xprCoeff)) { + inner = i; + result = xprCoeff; + } + } + } + } +}; +template +struct find_coeff_loop { + using ScalarImpl = find_coeff_loop; + using Scalar = typename Evaluator::Scalar; + using Packet = typename Evaluator::Packet; + static constexpr int PacketSize = unpacket_traits::size; + static constexpr int Alignment = Evaluator::Alignment; + + static EIGEN_DEVICE_FUNC inline void run(const Evaluator& eval, Func& func, Scalar& result, Index& index) { + Index size = eval.size(); + Index packetEnd = numext::round_down(size, PacketSize); + + /* initialization performed in calling function */ + /* result = eval.coeff(0); */ + /* index = 0; */ + + Packet resultPacket = pset1(result); + bool checkPacket = false; + + for (Index k = 0; k < packetEnd; k += PacketSize) { + Packet xprPacket = eval.template packet(k); + if (predux_any(func.comparePacket(resultPacket, xprPacket))) { + index = k; + result = func.predux(xprPacket); + resultPacket = pset1(result); + checkPacket = true; + } + } + + for (Index k = packetEnd; k < size; k++) { + Scalar xprCoeff = eval.coeff(k); + if (func.compareCoeff(result, xprCoeff)) { + index = k; + result = xprCoeff; + checkPacket = false; + } + } + + if (checkPacket) { + result = eval.coeff(index); + Index k_end = index + PacketSize; + for (Index k = index; k < k_end; k++) { + Scalar xprCoeff = eval.coeff(k); + if (func.compareCoeff(result, xprCoeff)) { + index = k; + result = xprCoeff; + } + } + } + } +}; + +template +struct find_coeff_evaluator : public evaluator { + using Base = evaluator; + using Scalar = typename Derived::Scalar; + using Packet = typename packet_traits::type; + static constexpr int Flags = Base::Flags; + static constexpr bool IsRowMajor = bool(Flags & RowMajorBit); + EIGEN_DEVICE_FUNC inline find_coeff_evaluator(const Derived& xpr) : Base(xpr), m_xpr(xpr) {} + + EIGEN_DEVICE_FUNC inline Scalar coeffByOuterInner(Index outer, Index inner) const { + Index row = IsRowMajor ? outer : inner; + Index col = IsRowMajor ? inner : outer; + return Base::coeff(row, col); + } + template + EIGEN_DEVICE_FUNC inline PacketType packetByOuterInner(Index outer, Index inner) const { + Index row = IsRowMajor ? outer : inner; + Index col = IsRowMajor ? inner : outer; + return Base::template packet(row, col); + } + + EIGEN_DEVICE_FUNC inline Index innerSize() const { return m_xpr.innerSize(); } + EIGEN_DEVICE_FUNC inline Index outerSize() const { return m_xpr.outerSize(); } + EIGEN_DEVICE_FUNC inline Index size() const { return m_xpr.size(); } + + const Derived& m_xpr; +}; + +template +struct find_coeff_impl { + using Evaluator = find_coeff_evaluator; + static constexpr int Flags = Evaluator::Flags; + static constexpr int Alignment = Evaluator::Alignment; + static constexpr bool IsRowMajor = Derived::IsRowMajor; + static constexpr int MaxInnerSizeAtCompileTime = + IsRowMajor ? Derived::MaxColsAtCompileTime : Derived::MaxRowsAtCompileTime; + static constexpr int MaxSizeAtCompileTime = Derived::MaxSizeAtCompileTime; + + using Scalar = typename Derived::Scalar; + using Packet = typename Evaluator::Packet; + + static constexpr int PacketSize = unpacket_traits::size; + static constexpr bool Linearize = bool(Flags & LinearAccessBit); + static constexpr bool DontVectorize = + enum_lt_not_dynamic(Linearize ? MaxSizeAtCompileTime : MaxInnerSizeAtCompileTime, PacketSize); + static constexpr bool Vectorize = + !DontVectorize && bool(Flags & PacketAccessBit) && functor_traits::PacketAccess; + + using Loop = find_coeff_loop; + + template = true> + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer, + Index& inner) { + Evaluator eval(xpr); + Loop::run(eval, func, res, outer, inner); + } + template = true> + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& outer, + Index& inner) { + // where possible, use the linear loop and back-calculate the outer and inner indices + Index index = 0; + run(xpr, func, res, index); + outer = index / xpr.innerSize(); + inner = index % xpr.innerSize(); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& xpr, Func& func, Scalar& res, Index& index) { + Evaluator eval(xpr); + Loop::run(eval, func, res, index); + } +}; + +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar findCoeff(const DenseBase& mat, Func& func, + IndexType* rowPtr, IndexType* colPtr) { + eigen_assert(mat.rows() > 0 && mat.cols() > 0 && "you are using an empty matrix"); + using Scalar = typename DenseBase::Scalar; + using FindCoeffImpl = internal::find_coeff_impl; + Index outer = 0; + Index inner = 0; + Scalar res = mat.coeff(0, 0); + FindCoeffImpl::run(mat.derived(), func, res, outer, inner); + *rowPtr = internal::convert_index(Derived::IsRowMajor ? outer : inner); + if (colPtr) *colPtr = internal::convert_index(Derived::IsRowMajor ? inner : outer); + return res; +} + +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar findCoeff(const DenseBase& mat, Func& func, + IndexType* indexPtr) { + eigen_assert(mat.size() > 0 && "you are using an empty matrix"); + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + using Scalar = typename DenseBase::Scalar; + using FindCoeffImpl = internal::find_coeff_impl; + Index index = 0; + Scalar res = mat.coeff(0); + FindCoeffImpl::run(mat.derived(), func, res, index); + *indexPtr = internal::convert_index(index); + return res; +} + +} // namespace internal + +/** \fn DenseBase::minCoeff(IndexType* rowId, IndexType* colId) const + * \returns the minimum of all coefficients of *this and puts in *row and *col its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::minCoeff(IndexType* rowPtr, + IndexType* colPtr) const { + using Func = internal::min_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, rowPtr, colPtr); +} + +/** \returns the minimum of all coefficients of *this and puts in *index its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(), + * DenseBase::minCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::minCoeff(IndexType* indexPtr) const { + using Func = internal::min_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, indexPtr); +} + +/** \fn DenseBase::maxCoeff(IndexType* rowId, IndexType* colId) const + * \returns the maximum of all coefficients of *this and puts in *row and *col its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::maxCoeff(IndexType* rowPtr, + IndexType* colPtr) const { + using Func = internal::max_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, rowPtr, colPtr); +} + +/** \returns the maximum of all coefficients of *this and puts in *index its location. + * + * If there are multiple coefficients with the same extreme value, the location of the first instance is returned. + * + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), + * DenseBase::maxCoeff() + */ +template +template +EIGEN_DEVICE_FUNC typename internal::traits::Scalar DenseBase::maxCoeff(IndexType* indexPtr) const { + using Func = internal::max_coeff_functor; + Func func; + return internal::findCoeff(derived(), func, indexPtr); +} + +} // namespace Eigen + +#endif // EIGEN_FIND_COEFF_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ForceAlignedAccess.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ForceAlignedAccess.h new file mode 100644 index 0000000..4f69c20 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ForceAlignedAccess.h @@ -0,0 +1,108 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_FORCEALIGNEDACCESS_H +#define EIGEN_FORCEALIGNEDACCESS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class ForceAlignedAccess + * \ingroup Core_Module + * + * \brief Enforce aligned packet loads and stores regardless of what is requested + * + * \param ExpressionType the type of the object of which we are forcing aligned packet access + * + * This class is the return type of MatrixBase::forceAlignedAccess() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::forceAlignedAccess() + */ + +namespace internal { +template +struct traits> : public traits {}; +} // namespace internal + +template +class ForceAlignedAccess : public internal::dense_xpr_base>::type { + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(ForceAlignedAccess) + + EIGEN_DEVICE_FUNC explicit constexpr ForceAlignedAccess(const ExpressionType& matrix) : m_expression(matrix) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_expression.outerStride(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_expression.innerStride(); } + + EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index row, Index col) const { + return m_expression.coeff(row, col); + } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) { + return m_expression.const_cast_derived().coeffRef(row, col); + } + + EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index index) const { return m_expression.coeff(index); } + + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index) { return m_expression.const_cast_derived().coeffRef(index); } + + template + inline const PacketScalar packet(Index row, Index col) const { + return m_expression.template packet(row, col); + } + + template + inline void writePacket(Index row, Index col, const PacketScalar& x) { + m_expression.const_cast_derived().template writePacket(row, col, x); + } + + template + inline const PacketScalar packet(Index index) const { + return m_expression.template packet(index); + } + + template + inline void writePacket(Index index, const PacketScalar& x) { + m_expression.const_cast_derived().template writePacket(index, x); + } + + EIGEN_DEVICE_FUNC operator const ExpressionType&() const { return m_expression; } + + protected: + const ExpressionType& m_expression; + + private: + ForceAlignedAccess& operator=(const ForceAlignedAccess&); +}; + +/** \returns an expression of *this with forced aligned access + * \sa forceAlignedAccessIf(),class ForceAlignedAccess + */ +template +inline const ForceAlignedAccess MatrixBase::forceAlignedAccess() const { + return ForceAlignedAccess(derived()); +} + +/** \returns an expression of *this with forced aligned access + * \sa forceAlignedAccessIf(), class ForceAlignedAccess + */ +template +inline ForceAlignedAccess MatrixBase::forceAlignedAccess() { + return ForceAlignedAccess(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_FORCEALIGNEDACCESS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fuzzy.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fuzzy.h new file mode 100644 index 0000000..eaa553c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Fuzzy.h @@ -0,0 +1,132 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_FUZZY_H +#define EIGEN_FUZZY_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template ::IsInteger> +struct isApprox_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec) { + typename internal::nested_eval::type nested(x); + typename internal::nested_eval::type otherNested(y); + return (nested.matrix() - otherNested.matrix()).cwiseAbs2().sum() <= + prec * prec * numext::mini(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); + } +}; + +template +struct isApprox_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar&) { + return x.matrix() == y.matrix(); + } +}; + +template ::IsInteger> +struct isMuchSmallerThan_object_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec) { + return x.cwiseAbs2().sum() <= numext::abs2(prec) * y.cwiseAbs2().sum(); + } +}; + +template +struct isMuchSmallerThan_object_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived&, const typename Derived::RealScalar&) { + return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); + } +}; + +template ::IsInteger> +struct isMuchSmallerThan_scalar_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const typename Derived::RealScalar& y, + const typename Derived::RealScalar& prec) { + return x.cwiseAbs2().sum() <= numext::abs2(prec * y); + } +}; + +template +struct isMuchSmallerThan_scalar_selector { + EIGEN_DEVICE_FUNC static bool run(const Derived& x, const typename Derived::RealScalar&, + const typename Derived::RealScalar&) { + return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); + } +}; + +} // end namespace internal + +/** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$ + * are considered to be approximately equal within precision \f$ p \f$ if + * \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f] + * For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm + * L2 norm). + * + * \note Because of the multiplicativeness of this comparison, one can't use this function + * to check whether \c *this is approximately equal to the zero matrix or vector. + * Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix + * or vector. If you want to test whether \c *this is zero, use internal::isMuchSmallerThan(const + * RealScalar&, RealScalar) instead. + * + * \sa internal::isMuchSmallerThan(const RealScalar&, RealScalar) const + */ +template +template +EIGEN_DEVICE_FUNC constexpr bool DenseBase::isApprox(const DenseBase& other, + const RealScalar& prec) const { + return internal::isApprox_selector::run(derived(), other.derived(), prec); +} + +/** \returns \c true if the norm of \c *this is much smaller than \a other, + * within the precision determined by \a prec. + * + * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is + * considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if + * \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f] + * + * For matrices, the comparison is done using the Hilbert-Schmidt norm. For this reason, + * the value of the reference scalar \a other should come from the Hilbert-Schmidt norm + * of a reference matrix of same dimensions. + * + * \sa isApprox(), isMuchSmallerThan(const DenseBase&, RealScalar) const + */ +template +EIGEN_DEVICE_FUNC constexpr bool DenseBase::isMuchSmallerThan(const typename NumTraits::Real& other, + const RealScalar& prec) const { + return internal::isMuchSmallerThan_scalar_selector::run(derived(), other, prec); +} + +/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other, + * within the precision determined by \a prec. + * + * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is + * considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if + * \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f] + * For matrices, the comparison is done using the Hilbert-Schmidt norm. + * + * \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const + */ +template +template +EIGEN_DEVICE_FUNC constexpr bool DenseBase::isMuchSmallerThan(const DenseBase& other, + const RealScalar& prec) const { + return internal::isMuchSmallerThan_object_selector::run(derived(), other.derived(), prec); +} + +} // end namespace Eigen + +#endif // EIGEN_FUZZY_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GeneralProduct.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GeneralProduct.h new file mode 100644 index 0000000..707611a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GeneralProduct.h @@ -0,0 +1,518 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_GENERAL_PRODUCT_H +#define EIGEN_GENERAL_PRODUCT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +enum { Large = 2, Small = 3 }; + +// Define the threshold value to fallback from the generic matrix-matrix product +// implementation (heavy) to the lightweight coeff-based product one. +// See generic_product_impl +// in products/GeneralMatrixMatrix.h for more details. +// TODO This threshold should also be used in the compile-time selector below. +#ifndef EIGEN_GEMM_TO_COEFFBASED_THRESHOLD +// This default value has been obtained on a Haswell architecture. +#define EIGEN_GEMM_TO_COEFFBASED_THRESHOLD 20 +#endif + +namespace internal { + +template +struct product_type_selector; + +template +struct product_size_category { + enum { +#ifndef EIGEN_GPU_COMPILE_PHASE + is_large = MaxSize == Dynamic || Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || + (Size == Dynamic && MaxSize >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), +#else + is_large = 0, +#endif + value = is_large ? Large + : Size == 1 ? 1 + : Small + }; +}; + +template +struct product_type { + typedef remove_all_t Lhs_; + typedef remove_all_t Rhs_; + enum { + MaxRows = traits::MaxRowsAtCompileTime, + Rows = traits::RowsAtCompileTime, + MaxCols = traits::MaxColsAtCompileTime, + Cols = traits::ColsAtCompileTime, + MaxDepth = min_size_prefer_fixed(traits::MaxColsAtCompileTime, traits::MaxRowsAtCompileTime), + Depth = min_size_prefer_fixed(traits::ColsAtCompileTime, traits::RowsAtCompileTime) + }; + + // the splitting into different lines of code here, introducing the _select enums and the typedef below, + // is to work around an internal compiler error with gcc 4.1 and 4.2. + private: + enum { + rows_select = product_size_category::value, + cols_select = product_size_category::value, + depth_select = product_size_category::value + }; + typedef product_type_selector selector; + + public: + enum { value = selector::ret, ret = selector::ret }; +#ifdef EIGEN_DEBUG_PRODUCT + static void debug() { + EIGEN_DEBUG_VAR(Rows); + EIGEN_DEBUG_VAR(Cols); + EIGEN_DEBUG_VAR(Depth); + EIGEN_DEBUG_VAR(rows_select); + EIGEN_DEBUG_VAR(cols_select); + EIGEN_DEBUG_VAR(depth_select); + EIGEN_DEBUG_VAR(value); + } +#endif +}; + +/* The following allows to select the kind of product at compile time + * based on the three dimensions of the product. + * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */ +// FIXME: the current compile-time product-type mapping may not be optimal. +template +struct product_type_selector { + enum { ret = OuterProduct }; +}; +template +struct product_type_selector { + enum { ret = LazyCoeffBasedProductMode }; +}; +template +struct product_type_selector<1, N, 1> { + enum { ret = LazyCoeffBasedProductMode }; +}; +template +struct product_type_selector<1, 1, Depth> { + enum { ret = InnerProduct }; +}; +template <> +struct product_type_selector<1, 1, 1> { + enum { ret = InnerProduct }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector<1, Small, Small> { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = LazyCoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = LazyCoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = LazyCoeffBasedProductMode }; +}; +template <> +struct product_type_selector<1, Large, Small> { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector<1, Large, Large> { + enum { ret = GemvProduct }; +}; +template <> +struct product_type_selector<1, Small, Large> { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = GemvProduct }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = GemmProduct }; +}; +template <> +struct product_type_selector { + enum { ret = GemmProduct }; +}; +template <> +struct product_type_selector { + enum { ret = GemmProduct }; +}; +template <> +struct product_type_selector { + enum { ret = GemmProduct }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = CoeffBasedProductMode }; +}; +template <> +struct product_type_selector { + enum { ret = GemmProduct }; +}; + +} // end namespace internal + +/*********************************************************************** + * Implementation of Inner Vector Vector Product + ***********************************************************************/ + +// FIXME: consider returning a Scalar instead of a 1x1 matrix for inner products. +// Pro: more natural for the user. +// Con: in a meta-unrolled algorithm a matrix-matrix product may reduce to a +// row-vector times column-vector product. To handle this, we could specialize +// Block with operator=(Scalar x). + +/*********************************************************************** + * Implementation of Outer Vector Vector Product + ***********************************************************************/ + +/*********************************************************************** + * Implementation of General Matrix Vector Product + ***********************************************************************/ + +/* According to the shape/flags of the matrix we have to distinguish 3 different cases: + * 1 - the matrix is col-major, BLAS compatible and M is large => call fast BLAS-like colmajor routine + * 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine + * 3 - all other cases are handled using a simple loop along the outer-storage direction. + * Therefore we need a lower level meta selector. + * Furthermore, if the matrix is the rhs, then the product has to be transposed. + */ +namespace internal { + +template +struct gemv_dense_selector; + +} // end namespace internal + +namespace internal { + +template +struct gemv_static_vector_if; + +template +struct gemv_static_vector_if { + EIGEN_DEVICE_FUNC constexpr Scalar* data() { + eigen_internal_assert(false && "should never be called"); + return 0; + } +}; + +template +struct gemv_static_vector_if { + EIGEN_DEVICE_FUNC constexpr Scalar* data() { return 0; } +}; + +template +struct gemv_static_vector_if { +#if EIGEN_MAX_STATIC_ALIGN_BYTES != 0 + internal::plain_array m_data; + constexpr Scalar* data() { return m_data.array; } +#else + // Some architectures cannot align on the stack, + // => let's manually enforce alignment by allocating more data and return the address of the first aligned element. + internal::plain_array m_data; + constexpr Scalar* data() { + return reinterpret_cast((std::uintptr_t(m_data.array) & ~(std::size_t(EIGEN_MAX_ALIGN_BYTES - 1))) + + EIGEN_MAX_ALIGN_BYTES); + } +#endif +}; + +// The vector is on the left => transposition +template +struct gemv_dense_selector { + template + static void run(const Lhs& lhs, const Rhs& rhs, Dest& dest, const typename Dest::Scalar& alpha) { + Transpose destT(dest); + enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor }; + gemv_dense_selector::run(rhs.transpose(), lhs.transpose(), destT, + alpha); + } +}; + +template <> +struct gemv_dense_selector { + template + static inline void run(const Lhs& lhs, const Rhs& rhs, Dest& dest, const typename Dest::Scalar& alpha) { + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef typename Dest::Scalar ResScalar; + + typedef internal::blas_traits LhsBlasTraits; + typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; + typedef internal::blas_traits RhsBlasTraits; + typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType; + + typedef Map, plain_enum_min(AlignedMax, internal::packet_traits::size)> + MappedDest; + + ActualLhsType actualLhs = LhsBlasTraits::extract(lhs); + ActualRhsType actualRhs = RhsBlasTraits::extract(rhs); + + ResScalar actualAlpha = combine_scalar_factors(alpha, lhs, rhs); + + // make sure Dest is a compile-time vector type (bug 1166) + typedef std::conditional_t ActualDest; + + enum { + // FIXME: find a way to allow an inner stride on the result if packet_traits::size==1 + // on, the other hand it is good for the cache to pack the vector anyways... + EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime == 1), + ComplexByReal = (NumTraits::IsComplex) && (!NumTraits::IsComplex), + MightCannotUseDest = ((!EvalToDestAtCompileTime) || ComplexByReal) && (ActualDest::MaxSizeAtCompileTime != 0) + }; + + typedef const_blas_data_mapper LhsMapper; + typedef const_blas_data_mapper RhsMapper; + RhsScalar compatibleAlpha = get_factor::run(actualAlpha); + + if (!MightCannotUseDest) { + // shortcut if we are sure to be able to use dest directly, + // this ease the compiler to generate cleaner and more optimzized code for most common cases + general_matrix_vector_product::run(actualLhs.rows(), actualLhs.cols(), + LhsMapper(actualLhs.data(), + actualLhs.outerStride()), + RhsMapper(actualRhs.data(), + actualRhs.innerStride()), + dest.data(), 1, compatibleAlpha); + } else { + gemv_static_vector_if + static_dest; + + const bool alphaIsCompatible = (!ComplexByReal) || (numext::is_exactly_zero(numext::imag(actualAlpha))); + const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; + + ei_declare_aligned_stack_constructed_variable(ResScalar, actualDestPtr, dest.size(), + evalToDest ? dest.data() : static_dest.data()); + + if (!evalToDest) { +#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + constexpr int Size = Dest::SizeAtCompileTime; + Index size = dest.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN +#endif + if (!alphaIsCompatible) { + MappedDest(actualDestPtr, dest.size()).setZero(); + compatibleAlpha = RhsScalar(1); + } else + MappedDest(actualDestPtr, dest.size()) = dest; + } + + general_matrix_vector_product::run(actualLhs.rows(), actualLhs.cols(), + LhsMapper(actualLhs.data(), + actualLhs.outerStride()), + RhsMapper(actualRhs.data(), + actualRhs.innerStride()), + actualDestPtr, 1, compatibleAlpha); + + if (!evalToDest) { + if (!alphaIsCompatible) + dest.matrix() += actualAlpha * MappedDest(actualDestPtr, dest.size()); + else + dest = MappedDest(actualDestPtr, dest.size()); + } + } + } +}; + +template <> +struct gemv_dense_selector { + template + static void run(const Lhs& lhs, const Rhs& rhs, Dest& dest, const typename Dest::Scalar& alpha) { + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef typename Dest::Scalar ResScalar; + + typedef internal::blas_traits LhsBlasTraits; + typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; + typedef internal::blas_traits RhsBlasTraits; + typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType; + typedef internal::remove_all_t ActualRhsTypeCleaned; + + std::add_const_t actualLhs = LhsBlasTraits::extract(lhs); + std::add_const_t actualRhs = RhsBlasTraits::extract(rhs); + + ResScalar actualAlpha = combine_scalar_factors(alpha, lhs, rhs); + + enum { + // FIXME: find a way to allow an inner stride on the result if packet_traits::size==1 + // on, the other hand it is good for the cache to pack the vector anyways... + DirectlyUseRhs = + ActualRhsTypeCleaned::InnerStrideAtCompileTime == 1 || ActualRhsTypeCleaned::MaxSizeAtCompileTime == 0 + }; + + gemv_static_vector_if + static_rhs; + + ei_declare_aligned_stack_constructed_variable( + RhsScalar, actualRhsPtr, actualRhs.size(), + DirectlyUseRhs ? const_cast(actualRhs.data()) : static_rhs.data()); + + if (!DirectlyUseRhs) { +#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + constexpr int Size = ActualRhsTypeCleaned::SizeAtCompileTime; + Index size = actualRhs.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN +#endif + Map(actualRhsPtr, actualRhs.size()) = actualRhs; + } + + typedef const_blas_data_mapper LhsMapper; + typedef const_blas_data_mapper RhsMapper; + general_matrix_vector_product:: + run(actualLhs.rows(), actualLhs.cols(), LhsMapper(actualLhs.data(), actualLhs.outerStride()), + RhsMapper(actualRhsPtr, 1), dest.data(), + dest.col(0).innerStride(), // NOTE if dest is not a vector at compile-time, then dest.innerStride() might + // be wrong. (bug 1166) + actualAlpha); + } +}; + +template <> +struct gemv_dense_selector { + template + static void run(const Lhs& lhs, const Rhs& rhs, Dest& dest, const typename Dest::Scalar& alpha) { + EIGEN_STATIC_ASSERT((!nested_eval::Evaluate), + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE); + // TODO: if rhs is large enough it might be beneficial to make sure that dest is sequentially stored in memory, + // otherwise use a temp + typename nested_eval::type actual_rhs(rhs); + const Index size = rhs.rows(); + for (Index k = 0; k < size; ++k) dest += (alpha * actual_rhs.coeff(k)) * lhs.col(k); + } +}; + +template <> +struct gemv_dense_selector { + template + static void run(const Lhs& lhs, const Rhs& rhs, Dest& dest, const typename Dest::Scalar& alpha) { + EIGEN_STATIC_ASSERT((!nested_eval::Evaluate), + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE); + typename nested_eval::type actual_rhs(rhs); + const Index rows = dest.rows(); + for (Index i = 0; i < rows; ++i) + dest.coeffRef(i) += alpha * (lhs.row(i).cwiseProduct(actual_rhs.transpose())).sum(); + } +}; + +} // end namespace internal + +/*************************************************************************** + * Implementation of matrix base methods + ***************************************************************************/ + +/** \returns the matrix product of \c *this and \a other. + * + * \note If instead of the matrix product you want the coefficient-wise product, see Cwise::operator*(). + * + * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Product MatrixBase::operator*( + const MatrixBase& other) const { + // A note regarding the function declaration: In MSVC, this function will sometimes + // not be inlined since DenseStorage is an unwindable object for dynamic + // matrices and product types are holding a member to store the result. + // Thus it does not help tagging this function with EIGEN_STRONG_INLINE. + enum { + ProductIsValid = Derived::ColsAtCompileTime == Dynamic || OtherDerived::RowsAtCompileTime == Dynamic || + int(Derived::ColsAtCompileTime) == int(OtherDerived::RowsAtCompileTime), + AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, + SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived, OtherDerived) + }; + // note to the lost user: + // * for a dot product use: v1.dot(v2) + // * for a coeff-wise product use: v1.cwiseProduct(v2) + EIGEN_STATIC_ASSERT( + ProductIsValid || !(AreVectors && SameSizes), + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) + EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) + EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) +#ifdef EIGEN_DEBUG_PRODUCT + internal::product_type::debug(); +#endif + + return Product(derived(), other.derived()); +} + +/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. + * + * The returned product will behave like any other expressions: the coefficients of the product will be + * computed once at a time as requested. This might be useful in some extremely rare cases when only + * a small and no coherent fraction of the result's coefficients have to be computed. + * + * \warning This version of the matrix product can be much much slower. So use it only if you know + * what you are doing and that you measured a true speed improvement. + * + * \sa operator*(const MatrixBase&) + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Product +MatrixBase::lazyProduct(const MatrixBase& other) const { + enum { + ProductIsValid = Derived::ColsAtCompileTime == Dynamic || OtherDerived::RowsAtCompileTime == Dynamic || + int(Derived::ColsAtCompileTime) == int(OtherDerived::RowsAtCompileTime), + AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, + SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived, OtherDerived) + }; + // note to the lost user: + // * for a dot product use: v1.dot(v2) + // * for a coeff-wise product use: v1.cwiseProduct(v2) + EIGEN_STATIC_ASSERT( + ProductIsValid || !(AreVectors && SameSizes), + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) + EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) + EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) + + return Product(derived(), other.derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_PRODUCT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GenericPacketMath.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GenericPacketMath.h new file mode 100644 index 0000000..10c798a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GenericPacketMath.h @@ -0,0 +1,1706 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_GENERIC_PACKET_MATH_H +#define EIGEN_GENERIC_PACKET_MATH_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/** \internal + * \file GenericPacketMath.h + * + * Default implementation for types not supported by the vectorization. + * In practice these functions are provided to make easier the writing + * of generic vectorized code. + */ + +#ifndef EIGEN_DEBUG_ALIGNED_LOAD +#define EIGEN_DEBUG_ALIGNED_LOAD +#endif + +#ifndef EIGEN_DEBUG_UNALIGNED_LOAD +#define EIGEN_DEBUG_UNALIGNED_LOAD +#endif + +#ifndef EIGEN_DEBUG_ALIGNED_STORE +#define EIGEN_DEBUG_ALIGNED_STORE +#endif + +#ifndef EIGEN_DEBUG_UNALIGNED_STORE +#define EIGEN_DEBUG_UNALIGNED_STORE +#endif + +struct default_packet_traits { + enum { + // Ops that are implemented for most types. + HasAdd = 1, + HasSub = 1, + HasShift = 1, + HasMul = 1, + HasNegate = 1, + HasAbs = 1, + HasAbs2 = 1, + HasMin = 1, + HasMax = 1, + HasConj = 1, + HasSetLinear = 1, + HasSign = 1, + HasAbsDiff = 1, + // By default, the nearest integer functions (rint, round, floor, ceil, trunc) are enabled for all scalar and packet + // types + HasRound = 1, + + HasArg = 0, + // This flag is used to indicate whether packet comparison is supported. + // pcmp_eq and pcmp_lt should be defined for it to be true. + HasCmp = 0, + + HasDiv = 0, + HasReciprocal = 0, + HasSqrt = 0, + HasRsqrt = 0, + HasCbrt = 0, + HasExp = 0, + HasExpm1 = 0, + HasLog = 0, + HasLog1p = 0, + HasLog10 = 0, + HasPow = 0, + HasSin = 0, + HasCos = 0, + HasTan = 0, + HasASin = 0, + HasACos = 0, + HasATan = 0, + HasATanh = 0, + HasSinh = 0, + HasCosh = 0, + HasTanh = 0, + HasLGamma = 0, + HasDiGamma = 0, + HasZeta = 0, + HasPolygamma = 0, + HasErf = 0, + HasErfc = 0, + HasNdtri = 0, + HasBessel = 0, + HasIGamma = 0, + HasIGammaDerA = 0, + HasGammaSampleDerAlpha = 0, + HasIGammac = 0, + HasBetaInc = 0 + }; +}; + +template +struct packet_traits : default_packet_traits { + typedef T type; + typedef T half; + enum { + Vectorizable = 0, + size = 1, + AlignedOnScalar = 0, + }; + enum { + HasAdd = 0, + HasSub = 0, + HasAbsDiff = 0, + HasMul = 0, + HasNegate = 0, + HasAbs = 0, + HasAbs2 = 0, + HasMin = 0, + HasMax = 0, + HasConj = 0, + HasSetLinear = 0 + }; +}; + +template +struct packet_traits : packet_traits {}; + +struct default_unpacket_traits { + enum { vectorizable = false, masked_load_available = false, masked_store_available = false }; +}; + +template +struct unpacket_traits : default_unpacket_traits { + typedef T type; + typedef T half; + typedef typename numext::get_integer_by_size::signed_type integer_packet; + enum { + size = 1, + alignment = alignof(T), + }; +}; + +template +struct unpacket_traits : unpacket_traits {}; + +/** \internal A convenience utility for determining if the type is a scalar. + * This is used to enable some generic packet implementations. + */ +template +struct is_scalar { + using Scalar = typename unpacket_traits::type; + enum { value = internal::is_same::value }; +}; + +// automatically and succinctly define combinations of pcast when +// 1) the packets are the same type, or +// 2) the packets differ only in sign. +// In both of these cases, preinterpret (bit_cast) is equivalent to pcast (static_cast) +template ::value && is_scalar::value> +struct is_degenerate_helper : is_same {}; +template <> +struct is_degenerate_helper : std::true_type {}; +template <> +struct is_degenerate_helper : std::true_type {}; +template <> +struct is_degenerate_helper : std::true_type {}; +template <> +struct is_degenerate_helper : std::true_type {}; + +template +struct is_degenerate_helper { + using SrcScalar = typename unpacket_traits::type; + static constexpr int SrcSize = unpacket_traits::size; + using TgtScalar = typename unpacket_traits::type; + static constexpr int TgtSize = unpacket_traits::size; + static constexpr bool value = is_degenerate_helper::value && (SrcSize == TgtSize); +}; + +// is_degenerate::value == is_degenerate::value +template +struct is_degenerate { + static constexpr bool value = + is_degenerate_helper::value || is_degenerate_helper::value; +}; + +template +struct is_half { + using Scalar = typename unpacket_traits::type; + static constexpr int Size = unpacket_traits::size; + using DefaultPacket = typename packet_traits::type; + static constexpr int DefaultSize = unpacket_traits::size; + static constexpr bool value = Size != 1 && Size < DefaultSize; +}; + +template +struct type_casting_traits { + enum { + VectorizedCast = + is_degenerate::value && packet_traits::Vectorizable && packet_traits::Vectorizable, + SrcCoeffRatio = 1, + TgtCoeffRatio = 1 + }; +}; + +// provides a succinct template to define vectorized casting traits with respect to the largest accessible packet types +template +struct vectorized_type_casting_traits { + enum : int { + DefaultSrcPacketSize = packet_traits::size, + DefaultTgtPacketSize = packet_traits::size, + VectorizedCast = 1, + SrcCoeffRatio = plain_enum_max(DefaultTgtPacketSize / DefaultSrcPacketSize, 1), + TgtCoeffRatio = plain_enum_max(DefaultSrcPacketSize / DefaultTgtPacketSize, 1) + }; +}; + +/** \internal Wrapper to ensure that multiple packet types can map to the same + same underlying vector type. */ +template +struct eigen_packet_wrapper { + EIGEN_ALWAYS_INLINE operator T&() { return m_val; } + EIGEN_ALWAYS_INLINE operator const T&() const { return m_val; } + EIGEN_ALWAYS_INLINE eigen_packet_wrapper() = default; + EIGEN_ALWAYS_INLINE eigen_packet_wrapper(const T& v) : m_val(v) {} + EIGEN_ALWAYS_INLINE eigen_packet_wrapper& operator=(const T& v) { + m_val = v; + return *this; + } + + T m_val; +}; + +template ::value> +struct preinterpret_generic; + +template +struct preinterpret_generic { + // the packets are not the same, attempt scalar bit_cast + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Target run(const Packet& a) { + return numext::bit_cast(a); + } +}; + +template +struct preinterpret_generic { + // the packets are the same type: do nothing + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet& a) { return a; } +}; + +template +struct preinterpret_generic::as_real, ComplexPacket, false> { + using RealPacket = typename unpacket_traits::as_real; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE RealPacket run(const ComplexPacket& a) { return a.v; } +}; + +/** \internal \returns reinterpret_cast(a) */ +template +EIGEN_DEVICE_FUNC inline Target preinterpret(const Packet& a) { + return preinterpret_generic::run(a); +} + +template ::value, + bool TgtIsHalf = is_half::value> +struct pcast_generic; + +template +struct pcast_generic { + // the packets are not degenerate: attempt scalar static_cast + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TgtPacket run(const SrcPacket& a) { + return cast_impl::run(a); + } +}; + +template +struct pcast_generic { + // the packets are the same: do nothing + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet& a) { return a; } +}; + +template +struct pcast_generic { + // the packets are degenerate: preinterpret is equivalent to pcast + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TgtPacket run(const SrcPacket& a) { return preinterpret(a); } +}; + +/** \internal \returns static_cast(a) (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline TgtPacket pcast(const SrcPacket& a) { + return pcast_generic::run(a); +} +template +EIGEN_DEVICE_FUNC inline TgtPacket pcast(const SrcPacket& a, const SrcPacket& b) { + return pcast_generic::run(a, b); +} +template +EIGEN_DEVICE_FUNC inline TgtPacket pcast(const SrcPacket& a, const SrcPacket& b, const SrcPacket& c, + const SrcPacket& d) { + return pcast_generic::run(a, b, c, d); +} +template +EIGEN_DEVICE_FUNC inline TgtPacket pcast(const SrcPacket& a, const SrcPacket& b, const SrcPacket& c, const SrcPacket& d, + const SrcPacket& e, const SrcPacket& f, const SrcPacket& g, + const SrcPacket& h) { + return pcast_generic::run(a, b, c, d, e, f, g, h); +} + +template +struct pcast_generic { + // TgtPacket is a half packet of some other type + // perform cast and truncate result + using DefaultTgtPacket = typename is_half::DefaultPacket; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TgtPacket run(const SrcPacket& a) { + return preinterpret(pcast(a)); + } +}; + +/** \internal \returns a + b (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet padd(const Packet& a, const Packet& b) { + return a + b; +} +// Avoid compiler warning for boolean algebra. +template <> +EIGEN_DEVICE_FUNC inline bool padd(const bool& a, const bool& b) { + return a || b; +} + +/** \internal \returns a packet version of \a *from, (un-aligned masked add) + * There is no generic implementation. We only have implementations for specialized + * cases. Generic case should not be called. + */ +template +EIGEN_DEVICE_FUNC inline std::enable_if_t::masked_fpops_available, Packet> padd( + const Packet& a, const Packet& b, typename unpacket_traits::mask_t umask); + +/** \internal \returns a - b (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet psub(const Packet& a, const Packet& b) { + return a - b; +} + +/** \internal \returns -a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pnegate(const Packet& a) { + EIGEN_STATIC_ASSERT((!is_same::type, bool>::value), + NEGATE IS NOT DEFINED FOR BOOLEAN TYPES) + return numext::negate(a); +} + +/** \internal \returns conj(a) (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pconj(const Packet& a) { + return numext::conj(a); +} + +/** \internal \returns a * b (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pmul(const Packet& a, const Packet& b) { + return a * b; +} +// Avoid compiler warning for boolean algebra. +template <> +EIGEN_DEVICE_FUNC inline bool pmul(const bool& a, const bool& b) { + return a && b; +} + +/** \internal \returns a / b (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pdiv(const Packet& a, const Packet& b) { + return a / b; +} +// Avoid compiler warning for boolean algebra. +template <> +EIGEN_DEVICE_FUNC inline bool pdiv(const bool& a, const bool& b) { + return a && b; +} + +// In the generic packet case, memset to all one bits. +template +struct ptrue_impl { + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) { + Packet b; + memset(static_cast(&b), 0xff, sizeof(Packet)); + return b; + } +}; + +// Use a value of one for scalars. +template +struct ptrue_impl::value>> { + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar&) { return Scalar(1); } +}; + +// For booleans, we can only directly set a valid `bool` value to avoid UB. +template <> +struct ptrue_impl { + static EIGEN_DEVICE_FUNC inline bool run(const bool&) { return true; } +}; + +/** \internal \returns one bits. */ +template +EIGEN_DEVICE_FUNC inline Packet ptrue(const Packet& a) { + return ptrue_impl::run(a); +} + +// In the general packet case, memset to zero. +template +struct pzero_impl { + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) { + Packet b; + memset(static_cast(&b), 0x00, sizeof(Packet)); + return b; + } +}; + +// For scalars, explicitly set to Scalar(0), since the underlying representation +// for zero may not consist of all-zero bits. +template +struct pzero_impl::value>> { + static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) { return T(0); } +}; + +/** \internal \returns packet of zeros */ +template +EIGEN_DEVICE_FUNC inline Packet pzero(const Packet& a) { + return pzero_impl::run(a); +} + +template +struct bit_and { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a & b; } +}; + +template +struct bit_or { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a | b; } +}; + +template +struct bit_xor { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const { return a ^ b; } +}; + +template +struct bit_not { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T operator()(const T& a) const { return ~a; } +}; + +template <> +struct bit_and { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a && b; } +}; + +template <> +struct bit_or { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a || b; } +}; + +template <> +struct bit_xor { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a, const bool& b) const { return a != b; } +}; + +template <> +struct bit_not { + EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE bool operator()(const bool& a) const { return !a; } +}; + +// Use operators &, |, ^, ~. +template +struct operator_bitwise_helper { + EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) { return bit_and()(a, b); } + EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { return bit_or()(a, b); } + EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) { return bit_xor()(a, b); } + EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { return bit_not()(a); } +}; + +// Apply binary operations byte-by-byte +template +struct bytewise_bitwise_helper { + EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) { + return binary(a, b, bit_and()); + } + EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { return binary(a, b, bit_or()); } + EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) { + return binary(a, b, bit_xor()); + } + EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { return unary(a, bit_not()); } + + private: + template + EIGEN_DEVICE_FUNC static inline T unary(const T& a, Op op) { + const unsigned char* a_ptr = reinterpret_cast(&a); + T c; + unsigned char* c_ptr = reinterpret_cast(&c); + for (size_t i = 0; i < sizeof(T); ++i) { + *c_ptr++ = op(*a_ptr++); + } + return c; + } + + template + EIGEN_DEVICE_FUNC static inline T binary(const T& a, const T& b, Op op) { + const unsigned char* a_ptr = reinterpret_cast(&a); + const unsigned char* b_ptr = reinterpret_cast(&b); + T c; + unsigned char* c_ptr = reinterpret_cast(&c); + for (size_t i = 0; i < sizeof(T); ++i) { + *c_ptr++ = op(*a_ptr++, *b_ptr++); + } + return c; + } +}; + +// In the general case, use byte-by-byte manipulation. +template +struct bitwise_helper : public bytewise_bitwise_helper {}; + +// For integers or non-trivial scalars, use binary operators. +template +struct bitwise_helper::value && + (NumTraits::IsInteger || NumTraits::RequireInitialization)>> + : public operator_bitwise_helper {}; + +/** \internal \returns the bitwise and of \a a and \a b */ +template +EIGEN_DEVICE_FUNC inline Packet pand(const Packet& a, const Packet& b) { + return bitwise_helper::bitwise_and(a, b); +} + +/** \internal \returns the bitwise or of \a a and \a b */ +template +EIGEN_DEVICE_FUNC inline Packet por(const Packet& a, const Packet& b) { + return bitwise_helper::bitwise_or(a, b); +} + +/** \internal \returns the bitwise xor of \a a and \a b */ +template +EIGEN_DEVICE_FUNC inline Packet pxor(const Packet& a, const Packet& b) { + return bitwise_helper::bitwise_xor(a, b); +} + +/** \internal \returns the bitwise not of \a a */ +template +EIGEN_DEVICE_FUNC inline Packet pnot(const Packet& a) { + return bitwise_helper::bitwise_not(a); +} + +/** \internal \returns the bitwise and of \a a and not \a b */ +template +EIGEN_DEVICE_FUNC inline Packet pandnot(const Packet& a, const Packet& b) { + return pand(a, pnot(b)); +} + +/** \internal \returns a < b as a bit mask */ +template +EIGEN_DEVICE_FUNC inline Packet pcmp_lt(const Packet& a, const Packet& b) { + return a < b ? ptrue(a) : pzero(a); +} + +/** \internal \returns a == b as a bit mask */ +template +EIGEN_DEVICE_FUNC inline Packet pcmp_eq(const Packet& a, const Packet& b) { + return a == b ? ptrue(a) : pzero(a); +} + +/** \internal \returns a <= b as a bit mask */ +template +EIGEN_DEVICE_FUNC inline Packet pcmp_le(const Packet& a, const Packet& b) { + return por(pcmp_eq(a, b), pcmp_lt(a, b)); +} + +/** \internal \returns a < b or a==NaN or b==NaN as a bit mask */ +template +EIGEN_DEVICE_FUNC inline Packet pcmp_lt_or_nan(const Packet& a, const Packet& b) { + return a >= b ? pzero(a) : ptrue(a); +} + +// In the general case, use bitwise select. +template ::value> +struct pselect_impl { + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) { + return por(pand(a, mask), pandnot(b, mask)); + } +}; + +// For scalars, use ternary select. +template +struct pselect_impl { + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) { + return numext::select(mask, a, b); + } +}; + +/** \internal \returns \a or \b for each field in packet according to \mask */ +template +EIGEN_DEVICE_FUNC inline Packet pselect(const Packet& mask, const Packet& a, const Packet& b) { + return pselect_impl::run(mask, a, b); +} + +template <> +EIGEN_DEVICE_FUNC inline bool pselect(const bool& cond, const bool& a, const bool& b) { + return cond ? a : b; +} + +/** \internal \returns the min or max of \a a and \a b (coeff-wise) + If either \a a or \a b are NaN, the result is implementation defined. */ +template +struct pminmax_impl { + template + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { + return op(a, b); + } +}; + +/** \internal \returns the min or max of \a a and \a b (coeff-wise) + If either \a a or \a b are NaN, NaN is returned. */ +template <> +struct pminmax_impl { + template + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { + Packet not_nan_mask_a = pcmp_eq(a, a); + Packet not_nan_mask_b = pcmp_eq(b, b); + return pselect(not_nan_mask_a, pselect(not_nan_mask_b, op(a, b), b), a); + } +}; + +/** \internal \returns the min or max of \a a and \a b (coeff-wise) + If both \a a and \a b are NaN, NaN is returned. + Equivalent to std::fmin(a, b). */ +template <> +struct pminmax_impl { + template + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) { + Packet not_nan_mask_a = pcmp_eq(a, a); + Packet not_nan_mask_b = pcmp_eq(b, b); + return pselect(not_nan_mask_a, pselect(not_nan_mask_b, op(a, b), a), b); + } +}; + +#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) [](const Type& aa, const Type& bb) { return Func(aa, bb); } + +/** \internal \returns the min of \a a and \a b (coeff-wise). + If \a a or \a b is NaN, the return value is implementation defined. */ +template +EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) { + return numext::mini(a, b); +} + +/** \internal \returns the min of \a a and \a b (coeff-wise). + NaNPropagation determines the NaN propagation semantics. */ +template +EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) { + constexpr bool IsInteger = NumTraits::type>::IsInteger; + return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin))); +} + +/** \internal \returns the max of \a a and \a b (coeff-wise) + If \a a or \a b is NaN, the return value is implementation defined. */ +template +EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) { + return numext::maxi(a, b); +} + +/** \internal \returns the max of \a a and \a b (coeff-wise). + NaNPropagation determines the NaN propagation semantics. */ +template +EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) { + constexpr bool IsInteger = NumTraits::type>::IsInteger; + return pminmax_impl::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmax))); +} + +/** \internal \returns the absolute value of \a a */ +template +EIGEN_DEVICE_FUNC inline Packet pabs(const Packet& a) { + return numext::abs(a); +} +template <> +EIGEN_DEVICE_FUNC inline unsigned int pabs(const unsigned int& a) { + return a; +} +template <> +EIGEN_DEVICE_FUNC inline unsigned long pabs(const unsigned long& a) { + return a; +} +template <> +EIGEN_DEVICE_FUNC inline unsigned long long pabs(const unsigned long long& a) { + return a; +} + +/** \internal \returns the addsub value of \a a,b */ +template +EIGEN_DEVICE_FUNC inline Packet paddsub(const Packet& a, const Packet& b) { + return pselect(peven_mask(a), padd(a, b), psub(a, b)); +} + +/** \internal \returns the phase angle of \a a */ +template +EIGEN_DEVICE_FUNC inline Packet parg(const Packet& a) { + using numext::arg; + return arg(a); +} + +/** \internal \returns \a a arithmetically shifted by N bits to the right */ +template +EIGEN_DEVICE_FUNC inline T parithmetic_shift_right(const T& a) { + return numext::arithmetic_shift_right(a, N); +} + +/** \internal \returns \a a logically shifted by N bits to the right */ +template +EIGEN_DEVICE_FUNC inline T plogical_shift_right(const T& a) { + return numext::logical_shift_right(a, N); +} + +/** \internal \returns \a a shifted by N bits to the left */ +template +EIGEN_DEVICE_FUNC inline T plogical_shift_left(const T& a) { + return numext::logical_shift_left(a, N); +} + +/** \internal \returns the significant and exponent of the underlying floating point numbers + * See https://en.cppreference.com/w/cpp/numeric/math/frexp + */ +template +EIGEN_DEVICE_FUNC inline Packet pfrexp(const Packet& a, Packet& exponent) { + int exp; + EIGEN_USING_STD(frexp); + Packet result = static_cast(frexp(a, &exp)); + exponent = static_cast(exp); + return result; +} + +/** \internal \returns a * 2^((int)exponent) + * See https://en.cppreference.com/w/cpp/numeric/math/ldexp + */ +template +EIGEN_DEVICE_FUNC inline Packet pldexp(const Packet& a, const Packet& exponent) { + EIGEN_USING_STD(ldexp) + return static_cast(ldexp(a, static_cast(exponent))); +} + +/** \internal \returns the min of \a a and \a b (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline std::enable_if_t::type>::IsInteger, Packet> +pabsdiff(const Packet& a, const Packet& b) { + return pselect(pcmp_lt(a, b), psub(b, a), psub(a, b)); +} +template +EIGEN_DEVICE_FUNC inline std::enable_if_t::type>::IsInteger, Packet> +pabsdiff(const Packet& a, const Packet& b) { + return pabs(psub(a, b)); +} + +/** \internal \returns a packet version of \a *from, from must be properly aligned */ +template +EIGEN_DEVICE_FUNC inline Packet pload(const typename unpacket_traits::type* from) { + return *from; +} + +/** \internal \returns n elements of a packet version of \a *from, from must be properly aligned + * offset indicates the starting element in which to load and + * offset + n <= unpacket_traits::size + * All elements before offset and after the last element loaded will initialized with zero */ +template +EIGEN_DEVICE_FUNC inline Packet pload_partial(const typename unpacket_traits::type* from, const Index n, + const Index offset = 0) { + const Index packet_size = unpacket_traits::size; + eigen_assert(n + offset <= packet_size && "number of elements plus offset will read past end of packet"); + typedef typename unpacket_traits::type Scalar; + EIGEN_ALIGN_MAX Scalar elements[packet_size] = {Scalar(0)}; + for (Index i = offset; i < numext::mini(n + offset, packet_size); i++) { + elements[i] = from[i - offset]; + } + return pload(elements); +} + +/** \internal \returns a packet version of \a *from, (un-aligned load) */ +template +EIGEN_DEVICE_FUNC inline Packet ploadu(const typename unpacket_traits::type* from) { + return *from; +} + +/** \internal \returns n elements of a packet version of \a *from, (un-aligned load) + * All elements after the last element loaded will initialized with zero */ +template +EIGEN_DEVICE_FUNC inline Packet ploadu_partial(const typename unpacket_traits::type* from, const Index n, + const Index offset = 0) { + const Index packet_size = unpacket_traits::size; + eigen_assert(n + offset <= packet_size && "number of elements plus offset will read past end of packet"); + typedef typename unpacket_traits::type Scalar; + EIGEN_ALIGN_MAX Scalar elements[packet_size] = {Scalar(0)}; + for (Index i = offset; i < numext::mini(n + offset, packet_size); i++) { + elements[i] = from[i - offset]; + } + return pload(elements); +} + +/** \internal \returns a packet version of \a *from, (un-aligned masked load) + * There is no generic implementation. We only have implementations for specialized + * cases. Generic case should not be called. + */ +template +EIGEN_DEVICE_FUNC inline std::enable_if_t::masked_load_available, Packet> ploadu( + const typename unpacket_traits::type* from, typename unpacket_traits::mask_t umask); + +/** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */ +template +EIGEN_DEVICE_FUNC inline Packet pset1(const typename unpacket_traits::type& a) { + return a; +} + +/** \internal \returns a packet with constant coefficients set from bits */ +template +EIGEN_DEVICE_FUNC inline Packet pset1frombits(BitsType a); + +/** \internal \returns a packet with constant coefficients \a a[0], e.g.: (a[0],a[0],a[0],a[0]) */ +template +EIGEN_DEVICE_FUNC inline Packet pload1(const typename unpacket_traits::type* a) { + return pset1(*a); +} + +/** \internal \returns a packet with elements of \a *from duplicated. + * For instance, for a packet of 8 elements, 4 scalars will be read from \a *from and + * duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]} + * Currently, this function is only used for scalar * complex products. + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet ploaddup(const typename unpacket_traits::type* from) { + return *from; +} + +/** \internal \returns a packet with elements of \a *from quadrupled. + * For instance, for a packet of 8 elements, 2 scalars will be read from \a *from and + * replicated to form: {from[0],from[0],from[0],from[0],from[1],from[1],from[1],from[1]} + * Currently, this function is only used in matrix products. + * For packet-size smaller or equal to 4, this function is equivalent to pload1 + */ +template +EIGEN_DEVICE_FUNC inline Packet ploadquad(const typename unpacket_traits::type* from) { + return pload1(from); +} + +/** \internal equivalent to + * \code + * a0 = pload1(a+0); + * a1 = pload1(a+1); + * a2 = pload1(a+2); + * a3 = pload1(a+3); + * \endcode + * \sa pset1, pload1, ploaddup, pbroadcast2 + */ +template +EIGEN_DEVICE_FUNC inline void pbroadcast4(const typename unpacket_traits::type* a, Packet& a0, Packet& a1, + Packet& a2, Packet& a3) { + a0 = pload1(a + 0); + a1 = pload1(a + 1); + a2 = pload1(a + 2); + a3 = pload1(a + 3); +} + +/** \internal equivalent to + * \code + * a0 = pload1(a+0); + * a1 = pload1(a+1); + * \endcode + * \sa pset1, pload1, ploaddup, pbroadcast4 + */ +template +EIGEN_DEVICE_FUNC inline void pbroadcast2(const typename unpacket_traits::type* a, Packet& a0, Packet& a1) { + a0 = pload1(a + 0); + a1 = pload1(a + 1); +} + +/** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_traits::type& a) { + return a; +} + +template +struct peven_mask_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet&) { + typedef typename unpacket_traits::type Scalar; + const size_t n = unpacket_traits::size; + EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n]; + for (size_t i = 0; i < n; ++i) { + memset(elements + i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar)); + } + return ploadu(elements); + } +}; + +template +struct peven_mask_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar&) { return Scalar(1); } +}; + +/** \internal \returns a packet with constant coefficients \a a, e.g.: (x, 0, x, 0), + where x is the value of all 1-bits. */ +template +EIGEN_DEVICE_FUNC inline Packet peven_mask(const Packet& a) { + return peven_mask_impl::run(a); +} + +/** \internal copy the packet \a from to \a *to, \a to must be properly aligned */ +template +EIGEN_DEVICE_FUNC inline void pstore(Scalar* to, const Packet& from) { + (*to) = from; +} + +/** \internal copy n elements of the packet \a from to \a *to, \a to must be properly aligned + * offset indicates the starting element in which to store and + * offset + n <= unpacket_traits::size */ +template +EIGEN_DEVICE_FUNC inline void pstore_partial(Scalar* to, const Packet& from, const Index n, const Index offset = 0) { + const Index packet_size = unpacket_traits::size; + eigen_assert(n + offset <= packet_size && "number of elements plus offset will write past end of packet"); + EIGEN_ALIGN_MAX Scalar elements[packet_size]; + pstore(elements, from); + for (Index i = 0; i < numext::mini(n, packet_size - offset); i++) { + to[i] = elements[i + offset]; + } +} + +/** \internal copy the packet \a from to \a *to, (un-aligned store) */ +template +EIGEN_DEVICE_FUNC inline void pstoreu(Scalar* to, const Packet& from) { + (*to) = from; +} + +/** \internal copy n elements of the packet \a from to \a *to, (un-aligned store) */ +template +EIGEN_DEVICE_FUNC inline void pstoreu_partial(Scalar* to, const Packet& from, const Index n, const Index offset = 0) { + const Index packet_size = unpacket_traits::size; + eigen_assert(n + offset <= packet_size && "number of elements plus offset will write past end of packet"); + EIGEN_ALIGN_MAX Scalar elements[packet_size]; + pstore(elements, from); + for (Index i = 0; i < numext::mini(n, packet_size - offset); i++) { + to[i] = elements[i + offset]; + } +} + +/** \internal copy the packet \a from to \a *to, (un-aligned store with a mask) + * There is no generic implementation. We only have implementations for specialized + * cases. Generic case should not be called. + */ +template +EIGEN_DEVICE_FUNC inline std::enable_if_t::masked_store_available, void> pstoreu( + Scalar* to, const Packet& from, typename unpacket_traits::mask_t umask); + +template +EIGEN_DEVICE_FUNC inline Packet pgather(const Scalar* from, Index /*stride*/) { + return ploadu(from); +} + +template +EIGEN_DEVICE_FUNC inline Packet pgather_partial(const Scalar* from, Index stride, const Index n) { + const Index packet_size = unpacket_traits::size; + EIGEN_ALIGN_MAX Scalar elements[packet_size] = {Scalar(0)}; + for (Index i = 0; i < numext::mini(n, packet_size); i++) { + elements[i] = from[i * stride]; + } + return pload(elements); +} + +template +EIGEN_DEVICE_FUNC inline void pscatter(Scalar* to, const Packet& from, Index /*stride*/) { + pstore(to, from); +} + +template +EIGEN_DEVICE_FUNC inline void pscatter_partial(Scalar* to, const Packet& from, Index stride, const Index n) { + const Index packet_size = unpacket_traits::size; + EIGEN_ALIGN_MAX Scalar elements[packet_size]; + pstore(elements, from); + for (Index i = 0; i < numext::mini(n, packet_size); i++) { + to[i * stride] = elements[i]; + } +} + +/** \internal tries to do cache prefetching of \a addr */ +template +EIGEN_DEVICE_FUNC inline void prefetch(const Scalar* addr) { +#if defined(EIGEN_HIP_DEVICE_COMPILE) + // do nothing +#elif defined(EIGEN_CUDA_ARCH) +#if defined(__LP64__) || EIGEN_OS_WIN64 + // 64-bit pointer operand constraint for inlined asm + asm(" prefetch.L1 [ %1 ];" : "=l"(addr) : "l"(addr)); +#else + // 32-bit pointer operand constraint for inlined asm + asm(" prefetch.L1 [ %1 ];" : "=r"(addr) : "r"(addr)); +#endif +#elif (!EIGEN_COMP_MSVC) && (EIGEN_COMP_GNUC || EIGEN_COMP_CLANG || EIGEN_COMP_ICC) + __builtin_prefetch(addr); +#endif +} + +/** \internal \returns the reversed elements of \a a*/ +template +EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& a) { + return a; +} + +/** \internal \returns \a a with real and imaginary parts flipped (for complex types only) */ +template +EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet& a) { + return Packet(numext::imag(a), numext::real(a)); +} + +/** \internal \returns \a a with real part duplicated (for complex types only) */ +// TODO(rmlarsen): Define and use in all complex backends. +template +EIGEN_DEVICE_FUNC inline Packet pdupreal(const Packet& a) { + return Packet(numext::real(a), numext::real(a)); +} + +/** \internal \returns \a a with imaginary part duplicated (for complex types only) */ +// TODO(rmlarsen): Define and use in all complex backends. +template +EIGEN_DEVICE_FUNC inline Packet pdupimag(const Packet& a) { + return Packet(numext::imag(a), numext::imag(a)); +} + +/************************** + * Special math functions + ***************************/ + +/** \internal \returns isnan(a) */ +template +EIGEN_DEVICE_FUNC inline Packet pisnan(const Packet& a) { + return pandnot(ptrue(a), pcmp_eq(a, a)); +} + +/** \internal \returns isinf(a) */ +template +EIGEN_DEVICE_FUNC inline Packet pisinf(const Packet& a) { + using Scalar = typename unpacket_traits::type; + constexpr Scalar inf = NumTraits::infinity(); + return pcmp_eq(pabs(a), pset1(inf)); +} + +/** \internal \returns the sine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psin(const Packet& a) { + EIGEN_USING_STD(sin); + return sin(a); +} + +/** \internal \returns the cosine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcos(const Packet& a) { + EIGEN_USING_STD(cos); + return cos(a); +} + +/** \internal \returns the tan of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptan(const Packet& a) { + EIGEN_USING_STD(tan); + return tan(a); +} + +/** \internal \returns the arc sine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pasin(const Packet& a) { + EIGEN_USING_STD(asin); + return asin(a); +} + +/** \internal \returns the arc cosine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pacos(const Packet& a) { + EIGEN_USING_STD(acos); + return acos(a); +} + +/** \internal \returns the hyperbolic sine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psinh(const Packet& a) { + EIGEN_USING_STD(sinh); + return sinh(a); +} + +/** \internal \returns the hyperbolic cosine of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcosh(const Packet& a) { + EIGEN_USING_STD(cosh); + return cosh(a); +} + +/** \internal \returns the arc tangent of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patan(const Packet& a) { + EIGEN_USING_STD(atan); + return atan(a); +} + +/** \internal \returns the hyperbolic tan of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet ptanh(const Packet& a) { + EIGEN_USING_STD(tanh); + return tanh(a); +} + +/** \internal \returns the arc tangent of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet patanh(const Packet& a) { + EIGEN_USING_STD(atanh); + return atanh(a); +} + +/** \internal \returns the exp of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp(const Packet& a) { + return numext::exp(a); +} + +/** \internal \returns the exp2 of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexp2(const Packet& a) { + return numext::exp2(a); +} + +/** \internal \returns the expm1 of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pexpm1(const Packet& a) { + return numext::expm1(a); +} + +/** \internal \returns the log of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog(const Packet& a) { + EIGEN_USING_STD(log); + return log(a); +} + +/** \internal \returns the log1p of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog1p(const Packet& a) { + return numext::log1p(a); +} + +/** \internal \returns the log10 of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog10(const Packet& a) { + EIGEN_USING_STD(log10); + return log10(a); +} + +/** \internal \returns the log2 of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet plog2(const Packet& a) { + using Scalar = typename internal::unpacket_traits::type; + using RealScalar = typename NumTraits::Real; + return pmul(pset1(Scalar(RealScalar(EIGEN_LOG2E))), plog(a)); +} + +/** \internal \returns the square-root of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet psqrt(const Packet& a) { + return numext::sqrt(a); +} + +/** \internal \returns the cube-root of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet pcbrt(const Packet& a) { + return numext::cbrt(a); +} + +template ::value, + bool IsInteger = NumTraits::type>::IsInteger> +struct nearest_integer_packetop_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run_floor(const Packet& x) { return numext::floor(x); } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run_ceil(const Packet& x) { return numext::ceil(x); } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run_rint(const Packet& x) { return numext::rint(x); } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run_round(const Packet& x) { return numext::round(x); } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run_trunc(const Packet& x) { return numext::trunc(x); } +}; + +/** \internal \returns the rounded value of \a a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pround(const Packet& a) { + return nearest_integer_packetop_impl::run_round(a); +} + +/** \internal \returns the floor of \a a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pfloor(const Packet& a) { + return nearest_integer_packetop_impl::run_floor(a); +} + +/** \internal \returns the rounded value of \a a (coeff-wise) with current + * rounding mode */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet print(const Packet& a) { + return nearest_integer_packetop_impl::run_rint(a); +} + +/** \internal \returns the ceil of \a a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pceil(const Packet& a) { + return nearest_integer_packetop_impl::run_ceil(a); +} + +/** \internal \returns the truncation of \a a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet ptrunc(const Packet& a) { + return nearest_integer_packetop_impl::run_trunc(a); +} + +template +struct psign_impl { + static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a) { return numext::sign(a); } +}; + +/** \internal \returns the sign of \a a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet psign(const Packet& a) { + return psign_impl::run(a); +} + +template <> +EIGEN_DEVICE_FUNC inline bool psign(const bool& a) { + return a; +} + +/** \internal \returns the first element of a packet */ +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type pfirst(const Packet& a) { + return a; +} + +/** \internal \returns the sum of the elements of upper and lower half of \a a if \a a is larger than 4. + * For a packet {a0, a1, a2, a3, a4, a5, a6, a7}, it returns a half packet {a0+a4, a1+a5, a2+a6, a3+a7} + * For packet-size smaller or equal to 4, this boils down to a noop. + */ +template +EIGEN_DEVICE_FUNC inline std::conditional_t<(unpacket_traits::size % 8) == 0, + typename unpacket_traits::half, Packet> +predux_half(const Packet& a) { + return a; +} + +// Slow generic implementation of Packet reduction. +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_helper(const Packet& a, Op op) { + typedef typename unpacket_traits::type Scalar; + const size_t n = unpacket_traits::size; + EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n]; + pstoreu(elements, a); + for (size_t k = n / 2; k > 0; k /= 2) { + for (size_t i = 0; i < k; ++i) { + elements[i] = op(elements[i], elements[i + k]); + } + } + return elements[0]; +} + +/** \internal \returns the sum of the elements of \a a*/ +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux(const Packet& a) { + return a; +} + +/** \internal \returns the product of the elements of \a a */ +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_mul(const Packet& a) { + typedef typename unpacket_traits::type Scalar; + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmul))); +} + +/** \internal \returns the min of the elements of \a a */ +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_min(const Packet& a) { + typedef typename unpacket_traits::type Scalar; + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); +} + +/** \internal \returns the max of the elements of \a a */ +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_max(const Packet& a) { + typedef typename unpacket_traits::type Scalar; + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); +} + +template +struct predux_min_max_helper_impl { + using Scalar = typename unpacket_traits::type; + static constexpr bool UsePredux_ = NaNPropagation == PropagateFast || NumTraits::IsInteger; + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) { + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin))); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) { + return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax))); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_min(const Packet& a) { + return predux_min(a); + } + template = true> + static EIGEN_DEVICE_FUNC inline Scalar run_max(const Packet& a) { + return predux_max(a); + } +}; + +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_min(const Packet& a) { + return predux_min_max_helper_impl::run_min(a); +} + +template +EIGEN_DEVICE_FUNC inline typename unpacket_traits::type predux_max(const Packet& a) { + return predux_min_max_helper_impl::run_max(a); +} + +#undef EIGEN_BINARY_OP_NAN_PROPAGATION + +/** \internal \returns true if all coeffs of \a a means "true" + * It is supposed to be called on values returned by pcmp_*. + */ +// TODO: implement predux_all when needed. + +/** \internal \returns true if any coeffs of \a a means "true" + * It is supposed to be called on values returned by pcmp_*. + */ +template +EIGEN_DEVICE_FUNC inline bool predux_any(const Packet& a) { + // Dirty but generic implementation where "true" is assumed to be non 0 and all the sames. + // It is expected that "true" is either: + // - Scalar(1) + // - bits full of ones (NaN for floats), + // - or first bit equals to 1 (1 for ints, smallest denormal for floats). + // For all these cases, taking the sum is just fine, and this boils down to a no-op for scalars. + typedef typename unpacket_traits::type Scalar; + return numext::not_equal_strict(predux(a), Scalar(0)); +} + +/*************************************************************************** + * The following functions might not have to be overwritten for vectorized types + ***************************************************************************/ + +template +struct pmadd_impl { + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pmadd(const Packet& a, const Packet& b, const Packet& c) { + return padd(pmul(a, b), c); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pmsub(const Packet& a, const Packet& b, const Packet& c) { + return psub(pmul(a, b), c); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pnmadd(const Packet& a, const Packet& b, const Packet& c) { + return psub(c, pmul(a, b)); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pnmsub(const Packet& a, const Packet& b, const Packet& c) { + return pnegate(padd(pmul(a, b), c)); + } +}; + +template +struct pmadd_impl::value && NumTraits::IsSigned>> { + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmadd(const Scalar& a, const Scalar& b, const Scalar& c) { + return numext::madd(a, b, c); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmsub(const Scalar& a, const Scalar& b, const Scalar& c) { + return numext::madd(a, b, Scalar(-c)); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmadd(const Scalar& a, const Scalar& b, const Scalar& c) { + return numext::madd(Scalar(-a), b, c); + } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmsub(const Scalar& a, const Scalar& b, const Scalar& c) { + return -Scalar(numext::madd(a, b, c)); + } +}; + +// Multiply-add instructions. +/** \internal \returns a * b + c (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pmadd(const Packet& a, const Packet& b, const Packet& c) { + return pmadd_impl::pmadd(a, b, c); +} + +/** \internal \returns a * b - c (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pmsub(const Packet& a, const Packet& b, const Packet& c) { + return pmadd_impl::pmsub(a, b, c); +} + +/** \internal \returns -(a * b) + c (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pnmadd(const Packet& a, const Packet& b, const Packet& c) { + return pmadd_impl::pnmadd(a, b, c); +} + +/** \internal \returns -((a * b + c) (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet pnmsub(const Packet& a, const Packet& b, const Packet& c) { + return pmadd_impl::pnmsub(a, b, c); +} + +/** \internal copy a packet with constant coefficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned + */ +// NOTE: this function must really be templated on the packet type (think about different packet types for the same +// scalar type) +template +inline void pstore1(typename unpacket_traits::type* to, const typename unpacket_traits::type& a) { + pstore(to, pset1(a)); +} + +/** \internal \returns a packet version of \a *from. + * The pointer \a from must be aligned on a \a Alignment bytes boundary. */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt(const typename unpacket_traits::type* from) { + if (Alignment >= unpacket_traits::alignment) + return pload(from); + else + return ploadu(from); +} + +/** \internal \returns n elements of a packet version of \a *from. + * The pointer \a from must be aligned on a \a Alignment bytes boundary. */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_partial(const typename unpacket_traits::type* from, + const Index n, const Index offset = 0) { + if (Alignment >= unpacket_traits::alignment) + return pload_partial(from, n, offset); + else + return ploadu_partial(from, n, offset); +} + +/** \internal copy the packet \a from to \a *to. + * The pointer \a from must be aligned on a \a Alignment bytes boundary. */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& from) { + if (Alignment >= unpacket_traits::alignment) + pstore(to, from); + else + pstoreu(to, from); +} + +/** \internal copy n elements of the packet \a from to \a *to. + * The pointer \a from must be aligned on a \a Alignment bytes boundary. */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret_partial(Scalar* to, const Packet& from, const Index n, + const Index offset = 0) { + if (Alignment >= unpacket_traits::alignment) + pstore_partial(to, from, n, offset); + else + pstoreu_partial(to, from, n, offset); +} + +/** \internal \returns a packet version of \a *from. + * Unlike ploadt, ploadt_ro takes advantage of the read-only memory path on the + * hardware if available to speedup the loading of data that won't be modified + * by the current computation. + */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits::type* from) { + return ploadt(from); +} + +/*************************************************************************** + * Fast complex products (GCC generates a function call which is very slow) + ***************************************************************************/ + +// Eigen+CUDA does not support complexes. +#if !defined(EIGEN_GPUCC) + +template <> +inline std::complex pmul(const std::complex& a, const std::complex& b) { + return std::complex(a.real() * b.real() - a.imag() * b.imag(), a.imag() * b.real() + a.real() * b.imag()); +} + +template <> +inline std::complex pmul(const std::complex& a, const std::complex& b) { + return std::complex(a.real() * b.real() - a.imag() * b.imag(), a.imag() * b.real() + a.real() * b.imag()); +} + +#endif + +/*************************************************************************** + * PacketBlock, that is a collection of N packets where the number of words + * in the packet is a multiple of N. + ***************************************************************************/ +template ::size> +struct PacketBlock { + Packet packet[N]; +}; + +template +EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock& /*kernel*/) { + // Nothing to do in the scalar case, i.e. a 1x1 matrix. +} + +/** \internal \returns 1 / a (coeff-wise) */ +template +EIGEN_DEVICE_FUNC inline Packet preciprocal(const Packet& a) { + using Scalar = typename unpacket_traits::type; + return pdiv(pset1(Scalar(1)), a); +} + +/** \internal \returns the reciprocal square-root of \a a (coeff-wise) */ +template +EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet prsqrt(const Packet& a) { + return preciprocal(psqrt(a)); +} + +template ::value, + bool IsInteger = NumTraits::type>::IsInteger> +struct psignbit_impl; +template +struct psignbit_impl { + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static constexpr Packet run(const Packet& a) { return numext::signbit(a); } +}; +template +struct psignbit_impl { + // generic implementation if not specialized in PacketMath.h + // slower than arithmetic shift + typedef typename unpacket_traits::type Scalar; + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static Packet run(const Packet& a) { + const Packet cst_pos_one = pset1(Scalar(1)); + const Packet cst_neg_one = pset1(Scalar(-1)); + return pcmp_eq(por(pand(a, cst_neg_one), cst_pos_one), cst_neg_one); + } +}; +template +struct psignbit_impl { + // generic implementation for integer packets + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static constexpr Packet run(const Packet& a) { return pcmp_lt(a, pzero(a)); } +}; +/** \internal \returns the sign bit of \a a as a bitmask*/ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr Packet psignbit(const Packet& a) { + return psignbit_impl::run(a); +} + +/** \internal \returns the 2-argument arc tangent of \a y and \a x (coeff-wise) */ +template ::value, int> = 0> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet patan2(const Packet& y, const Packet& x) { + return numext::atan2(y, x); +} + +/** \internal \returns the 2-argument arc tangent of \a y and \a x (coeff-wise) */ +template ::value, int> = 0> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet patan2(const Packet& y, const Packet& x) { + typedef typename internal::unpacket_traits::type Scalar; + + // See https://en.cppreference.com/w/cpp/numeric/math/atan2 + // for how corner cases are supposed to be handled according to the + // IEEE floating-point standard (IEC 60559). + const Packet kSignMask = pset1(-Scalar(0)); + const Packet kZero = pzero(x); + const Packet kOne = pset1(Scalar(1)); + const Packet kPi = pset1(Scalar(EIGEN_PI)); + + const Packet x_has_signbit = psignbit(x); + const Packet y_signmask = pand(y, kSignMask); + const Packet x_signmask = pand(x, kSignMask); + const Packet result_signmask = pxor(y_signmask, x_signmask); + const Packet shift = por(pand(x_has_signbit, kPi), y_signmask); + + const Packet x_and_y_are_same = pcmp_eq(pabs(x), pabs(y)); + const Packet x_and_y_are_zero = pcmp_eq(por(x, y), kZero); + + Packet arg = pdiv(y, x); + arg = pselect(x_and_y_are_same, por(kOne, result_signmask), arg); + arg = pselect(x_and_y_are_zero, result_signmask, arg); + + Packet result = patan(arg); + result = padd(result, shift); + return result; +} + +/** \internal \returns the argument of \a a as a complex number */ +template ::value, int> = 0> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pcarg(const Packet& a) { + return Packet(numext::arg(a)); +} + +/** \internal \returns the argument of \a a as a complex number */ +template ::value, int> = 0> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pcarg(const Packet& a) { + EIGEN_STATIC_ASSERT(NumTraits::type>::IsComplex, + THIS METHOD IS FOR COMPLEX TYPES ONLY) + using RealPacket = typename unpacket_traits::as_real; + // a // r i r i ... + RealPacket aflip = pcplxflip(a).v; // i r i r ... + RealPacket result = patan2(aflip, a.v); // atan2 crap atan2 crap ... + return (Packet)pand(result, peven_mask(result)); // atan2 0 atan2 0 ... +} + +/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements + * outside this range are not defined. \a *from does not need to be aligned, and can be null if \a count is zero.*/ +template +EIGEN_DEVICE_FUNC inline Packet ploaduSegment(const typename unpacket_traits::type* from, Index begin, + Index count) { + using Scalar = typename unpacket_traits::type; + constexpr Index PacketSize = unpacket_traits::size; + eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range"); + Scalar aux[PacketSize] = {}; + for (Index k = begin; k < begin + count; k++) { + aux[k] = from[k]; + } + return ploadu(aux); +} + +/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements + * outside this range are not defined. \a *from must be aligned, and cannot be null.*/ +template +EIGEN_DEVICE_FUNC inline Packet ploadSegment(const typename unpacket_traits::type* from, Index begin, + Index count) { + return ploaduSegment(from, begin, count); +} + +/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to. +Elements outside of the range [begin, begin + count) are not defined. \a *to does not need to be aligned, and can be +null if \a count is zero.*/ +template +EIGEN_DEVICE_FUNC inline void pstoreuSegment(Scalar* to, const Packet& from, Index begin, Index count) { + constexpr Index PacketSize = unpacket_traits::size; + eigen_assert((begin >= 0 && count >= 0 && begin + count <= PacketSize) && "invalid range"); + Scalar aux[PacketSize]; + pstoreu(aux, from); + for (Index k = begin; k < begin + count; k++) { + to[k] = aux[k]; + } +} + +/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to. +Elements outside of the range [begin, begin + count) are not defined. \a *to must be aligned, and cannot be +null.*/ +template +EIGEN_DEVICE_FUNC inline void pstoreSegment(Scalar* to, const Packet& from, Index begin, Index count) { + return pstoreuSegment(to, from, begin, count); +} + +/** \internal \returns a packet populated with values in the range [begin, begin + count). Elements + * outside this range are not defined.*/ +template +EIGEN_DEVICE_FUNC inline Packet ploadtSegment(const typename unpacket_traits::type* from, Index begin, + Index count) { + constexpr int RequiredAlignment = unpacket_traits::alignment; + if (Alignment >= RequiredAlignment) { + return ploadSegment(from, begin, count); + } else { + return ploaduSegment(from, begin, count); + } +} + +/** \internal copy the packet \a from in the range [begin, begin + count) to \a *to. +Elements outside of the range [begin, begin + count) are not defined.*/ +template +EIGEN_DEVICE_FUNC inline void pstoretSegment(Scalar* to, const Packet& from, Index begin, Index count) { + constexpr int RequiredAlignment = unpacket_traits::alignment; + if (Alignment >= RequiredAlignment) { + pstoreSegment(to, from, begin, count); + } else { + pstoreuSegment(to, from, begin, count); + } +} + +#ifndef EIGEN_NO_IO + +template +class StreamablePacket { + public: + using Scalar = typename unpacket_traits::type; + StreamablePacket(const Packet& packet) { pstoreu(v_, packet); } + + friend std::ostream& operator<<(std::ostream& os, const StreamablePacket& packet) { + os << "{" << packet.v_[0]; + for (int i = 1; i < unpacket_traits::size; ++i) { + os << "," << packet.v_[i]; + } + os << "}"; + return os; + } + + private: + Scalar v_[unpacket_traits::size]; +}; + +/** + * \internal \returns an intermediary that can be used to ostream packets, e.g. for debugging. + */ +template +StreamablePacket postream(const Packet& packet) { + return StreamablePacket(packet); +} + +#endif // EIGEN_NO_IO + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_GENERIC_PACKET_MATH_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GlobalFunctions.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GlobalFunctions.h new file mode 100644 index 0000000..c32aac9 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/GlobalFunctions.h @@ -0,0 +1,230 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010-2016 Gael Guennebaud +// Copyright (C) 2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_GLOBAL_FUNCTIONS_H +#define EIGEN_GLOBAL_FUNCTIONS_H + +#ifdef EIGEN_PARSED_BY_DOXYGEN + +#define EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(NAME, FUNCTOR, DOC_OP, DOC_DETAILS) \ + /** \returns an expression of the coefficient-wise DOC_OP of \a x \ + \ \ + DOC_DETAILS \ + \ \ + \sa Math functions, class CwiseUnaryOp \ + */ \ + template \ + inline const Eigen::CwiseUnaryOp, const Derived> NAME( \ + const Eigen::ArrayBase& x); + +#else + +#define EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(NAME, FUNCTOR, DOC_OP, DOC_DETAILS) \ + template \ + inline const Eigen::CwiseUnaryOp, const Derived>(NAME)( \ + const Eigen::ArrayBase& x) { \ + return Eigen::CwiseUnaryOp, const Derived>(x.derived()); \ + } + +#endif // EIGEN_PARSED_BY_DOXYGEN + +#define EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(NAME, FUNCTOR) \ + \ + template \ + struct NAME##_retval > { \ + typedef const Eigen::CwiseUnaryOp, const Derived> type; \ + }; \ + template \ + struct NAME##_impl > { \ + static inline typename NAME##_retval >::type run(const Eigen::ArrayBase& x) { \ + return typename NAME##_retval >::type(x.derived()); \ + } \ + }; + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real, scalar_real_op, real part,\sa ArrayBase::real) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag, scalar_imag_op, imaginary part,\sa ArrayBase::imag) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(conj, scalar_conjugate_op, complex conjugate,\sa ArrayBase::conjugate) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(inverse, scalar_inverse_op, inverse,\sa ArrayBase::inverse) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin, scalar_sin_op, sine,\sa ArrayBase::sin) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos, scalar_cos_op, cosine,\sa ArrayBase::cos) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tan, scalar_tan_op, tangent,\sa ArrayBase::tan) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(atan, scalar_atan_op, arc - tangent,\sa ArrayBase::atan) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin, scalar_asin_op, arc - sine,\sa ArrayBase::asin) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acos, scalar_acos_op, arc - consine,\sa ArrayBase::acos) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sinh, scalar_sinh_op, hyperbolic sine,\sa ArrayBase::sinh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cosh, scalar_cosh_op, hyperbolic cosine,\sa ArrayBase::cosh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tanh, scalar_tanh_op, hyperbolic tangent,\sa ArrayBase::tanh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asinh, scalar_asinh_op, inverse hyperbolic sine,\sa ArrayBase::asinh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acosh, scalar_acosh_op, inverse hyperbolic cosine,\sa ArrayBase::acosh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(atanh, scalar_atanh_op, inverse hyperbolic tangent,\sa ArrayBase::atanh) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(logistic, scalar_logistic_op, logistic function,\sa ArrayBase::logistic) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(lgamma, scalar_lgamma_op, + natural logarithm of the gamma function,\sa ArrayBase::lgamma) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(digamma, scalar_digamma_op, derivative of lgamma,\sa ArrayBase::digamma) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erf, scalar_erf_op, error function,\sa ArrayBase::erf) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erfc, scalar_erfc_op, complement error function,\sa ArrayBase::erfc) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(ndtri, scalar_ndtri_op, inverse normal distribution function,\sa ArrayBase::ndtri) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp, scalar_exp_op, exponential,\sa ArrayBase::exp) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp2, scalar_exp2_op, exponential,\sa ArrayBase::exp2) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(expm1, scalar_expm1_op, exponential of a value minus 1,\sa ArrayBase::expm1) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log, scalar_log_op, natural logarithm,\sa Eigen::log10 DOXCOMMA ArrayBase::log) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log1p, scalar_log1p_op, natural logarithm of 1 plus the value,\sa ArrayBase::log1p) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10, scalar_log10_op, base 10 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log10) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log2, scalar_log2_op, base 2 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log2) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs, scalar_abs_op, absolute value,\sa ArrayBase::abs DOXCOMMA MatrixBase::cwiseAbs) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs2, scalar_abs2_op, + squared absolute value,\sa ArrayBase::abs2 DOXCOMMA MatrixBase::cwiseAbs2) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(arg, scalar_arg_op, complex argument,\sa ArrayBase::arg DOXCOMMA MatrixBase::cwiseArg) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(carg, scalar_carg_op, + complex argument, \sa ArrayBase::carg DOXCOMMA MatrixBase::cwiseCArg) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sqrt, scalar_sqrt_op, square root,\sa ArrayBase::sqrt DOXCOMMA MatrixBase::cwiseSqrt) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cbrt, scalar_cbrt_op, cube root,\sa ArrayBase::cbrt DOXCOMMA MatrixBase::cwiseCbrt) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(rsqrt, scalar_rsqrt_op, reciprocal square root,\sa ArrayBase::rsqrt) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(square, scalar_square_op, + square(power 2),\sa Eigen::abs2 DOXCOMMA Eigen::pow DOXCOMMA ArrayBase::square) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cube, scalar_cube_op, cube(power 3),\sa Eigen::pow DOXCOMMA ArrayBase::cube) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(rint, scalar_rint_op, + nearest integer,\sa Eigen::floor DOXCOMMA Eigen::ceil DOXCOMMA ArrayBase::round) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(round, scalar_round_op, + nearest integer,\sa Eigen::floor DOXCOMMA Eigen::ceil DOXCOMMA ArrayBase::round) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY( + floor, scalar_floor_op, nearest integer not greater than the given value,\sa Eigen::ceil DOXCOMMA ArrayBase::floor) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY( + ceil, scalar_ceil_op, nearest integer not less than the given value,\sa Eigen::floor DOXCOMMA ArrayBase::ceil) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(trunc, scalar_trunc_op, + nearest integer not greater in magnitude than the given value,\sa Eigen::trunc DOXCOMMA + ArrayBase::trunc) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY( + isnan, scalar_isnan_op, not -a - number test,\sa Eigen::isinf DOXCOMMA Eigen::isfinite DOXCOMMA ArrayBase::isnan) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY( + isinf, scalar_isinf_op, infinite value test,\sa Eigen::isnan DOXCOMMA Eigen::isfinite DOXCOMMA ArrayBase::isinf) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isfinite, scalar_isfinite_op, + finite value test,\sa Eigen::isinf DOXCOMMA Eigen::isnan DOXCOMMA ArrayBase::isfinite) +EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sign, scalar_sign_op, sign(or 0),\sa ArrayBase::sign) + +template +using GlobalUnaryPowReturnType = std::enable_if_t< + !internal::is_arithmetic::Real>::value && + internal::is_arithmetic::Real>::value, + CwiseUnaryOp, const Derived> >; + +/** \returns an expression of the coefficient-wise power of \a x to the given constant \a exponent. + * + * \tparam ScalarExponent is the scalar type of \a exponent. It must be compatible with the scalar type of the given + * expression (\c Derived::Scalar). + * + * \sa ArrayBase::pow() + * + * \relates ArrayBase + */ +#ifdef EIGEN_PARSED_BY_DOXYGEN +template +EIGEN_DEVICE_FUNC constexpr inline const GlobalUnaryPowReturnType pow( + const Eigen::ArrayBase& x, const ScalarExponent& exponent); +#else +template +EIGEN_DEVICE_FUNC constexpr inline const GlobalUnaryPowReturnType pow( + const Eigen::ArrayBase& x, const ScalarExponent& exponent) { + return GlobalUnaryPowReturnType( + x.derived(), internal::scalar_unary_pow_op(exponent)); +} +#endif + +/** \returns an expression of the coefficient-wise power of \a x to the given array of \a exponents. + * + * This function computes the coefficient-wise power. + * + * Example: \include Cwise_array_power_array.cpp + * Output: \verbinclude Cwise_array_power_array.out + * + * \sa ArrayBase::pow() + * + * \relates ArrayBase + */ +template +inline const Eigen::CwiseBinaryOp< + Eigen::internal::scalar_pow_op, const Derived, + const ExponentDerived> +pow(const Eigen::ArrayBase& x, const Eigen::ArrayBase& exponents) { + return Eigen::CwiseBinaryOp< + Eigen::internal::scalar_pow_op, const Derived, + const ExponentDerived>(x.derived(), exponents.derived()); +} + +/** \returns an expression of the coefficient-wise power of the scalar \a x to the given array of \a exponents. + * + * This function computes the coefficient-wise power between a scalar and an array of exponents. + * + * \tparam Scalar is the scalar type of \a x. It must be compatible with the scalar type of the given array expression + * (\c Derived::Scalar). + * + * Example: \include Cwise_scalar_power_array.cpp + * Output: \verbinclude Cwise_scalar_power_array.out + * + * \sa ArrayBase::pow() + * + * \relates ArrayBase + */ +#ifdef EIGEN_PARSED_BY_DOXYGEN +template +inline const CwiseBinaryOp, Constant, Derived> pow( + const Scalar& x, const Eigen::ArrayBase& x); +#else +template +EIGEN_DEVICE_FUNC inline const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE( + typename internal::promote_scalar_arg::type, + Derived, pow) pow(const Scalar& x, const Eigen::ArrayBase& exponents) { + typedef + typename internal::promote_scalar_arg::type + PromotedScalar; + return EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(PromotedScalar, Derived, pow)( + typename internal::plain_constant_type::type( + exponents.derived().rows(), exponents.derived().cols(), internal::scalar_constant_op(x)), + exponents.derived()); +} +#endif + +/** \returns an expression of the coefficient-wise atan2(\a x, \a y). \a x and \a y must be of the same type. + * + * This function computes the coefficient-wise atan2(). + * + * \sa ArrayBase::atan2() + * + * \relates ArrayBase + */ +template +inline const std::enable_if_t< + std::is_same::value, + Eigen::CwiseBinaryOp, + const LhsDerived, const RhsDerived> > +atan2(const Eigen::ArrayBase& x, const Eigen::ArrayBase& exponents) { + return Eigen::CwiseBinaryOp< + Eigen::internal::scalar_atan2_op, const LhsDerived, + const RhsDerived>(x.derived(), exponents.derived()); +} + +namespace internal { +EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real, scalar_real_op) +EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag, scalar_imag_op) +EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs2, scalar_abs2_op) +} // namespace internal +} // namespace Eigen + +// TODO: cleanly disable those functions that are not supported on Array (numext::real_ref, internal::random, +// internal::isApprox...) + +#endif // EIGEN_GLOBAL_FUNCTIONS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IO.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IO.h new file mode 100644 index 0000000..e2362fc --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IO.h @@ -0,0 +1,233 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_IO_H +#define EIGEN_IO_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +enum { DontAlignCols = 1 }; +enum { StreamPrecision = -1, FullPrecision = -2 }; + +namespace internal { +template +std::ostream& print_matrix(std::ostream& s, const Derived& _m, const IOFormat& fmt); +} + +/** \class IOFormat + * \ingroup Core_Module + * + * \brief Stores a set of parameters controlling the way matrices are printed + * + * List of available parameters: + * - \b precision number of digits for floating point values, or one of the special constants \c StreamPrecision and \c + * FullPrecision. The default is the special value \c StreamPrecision which means to use the stream's own precision + * setting, as set for instance using \c cout.precision(3). The other special value \c FullPrecision means that the + * number of digits will be computed to match the full precision of each floating-point type. + * - \b flags an OR-ed combination of flags, the default value is 0, the only currently available flag is \c + * DontAlignCols which allows to disable the alignment of columns, resulting in faster code. + * - \b coeffSeparator string printed between two coefficients of the same row + * - \b rowSeparator string printed between two rows + * - \b rowPrefix string printed at the beginning of each row + * - \b rowSuffix string printed at the end of each row + * - \b matPrefix string printed at the beginning of the matrix + * - \b matSuffix string printed at the end of the matrix + * - \b fill character printed to fill the empty space in aligned columns + * + * Example: \include IOFormat.cpp + * Output: \verbinclude IOFormat.out + * + * \sa DenseBase::format(), class WithFormat + */ +struct IOFormat { + /** Default constructor, see class IOFormat for the meaning of the parameters */ + IOFormat(int _precision = StreamPrecision, int _flags = 0, const std::string& _coeffSeparator = " ", + const std::string& _rowSeparator = "\n", const std::string& _rowPrefix = "", + const std::string& _rowSuffix = "", const std::string& _matPrefix = "", const std::string& _matSuffix = "", + const char _fill = ' ') + : matPrefix(_matPrefix), + matSuffix(_matSuffix), + rowPrefix(_rowPrefix), + rowSuffix(_rowSuffix), + rowSeparator(_rowSeparator), + rowSpacer(""), + coeffSeparator(_coeffSeparator), + fill(_fill), + precision(_precision), + flags(_flags) { + // TODO: check if rowPrefix, rowSuffix or rowSeparator contains a newline + // don't add rowSpacer if columns are not to be aligned + if ((flags & DontAlignCols)) return; + int i = int(matPrefix.length()) - 1; + while (i >= 0 && matPrefix[i] != '\n') { + rowSpacer += ' '; + i--; + } + } + std::string matPrefix, matSuffix; + std::string rowPrefix, rowSuffix, rowSeparator, rowSpacer; + std::string coeffSeparator; + char fill; + int precision; + int flags; +}; + +/** \class WithFormat + * \ingroup Core_Module + * + * \brief Pseudo expression providing matrix output with given format + * + * \tparam ExpressionType the type of the object on which IO stream operations are performed + * + * This class represents an expression with stream operators controlled by a given IOFormat. + * It is the return type of DenseBase::format() + * and most of the time this is the only way it is used. + * + * See class IOFormat for some examples. + * + * \sa DenseBase::format(), class IOFormat + */ +template +class WithFormat { + public: + WithFormat(const ExpressionType& matrix, const IOFormat& format) : m_matrix(matrix), m_format(format) {} + + friend std::ostream& operator<<(std::ostream& s, const WithFormat& wf) { + return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format); + } + + protected: + typename ExpressionType::Nested m_matrix; + IOFormat m_format; +}; + +namespace internal { + +// NOTE: This helper is kept for backward compatibility with previous code specializing +// this internal::significant_decimals_impl structure. In the future we should directly +// call max_digits10(). +template +struct significant_decimals_impl { + static inline int run() { return NumTraits::max_digits10(); } +}; + +/** \internal + * print the matrix \a _m to the output stream \a s using the output format \a fmt */ +template +std::ostream& print_matrix(std::ostream& s, const Derived& _m, const IOFormat& fmt) { + using internal::is_same; + + if (_m.size() == 0) { + s << fmt.matPrefix << fmt.matSuffix; + return s; + } + + typename Derived::Nested m = _m; + typedef typename Derived::Scalar Scalar; + typedef std::conditional_t::value || is_same::value || + is_same::value || is_same::value, + int, + std::conditional_t >::value || + is_same >::value || + is_same >::value || + is_same >::value, + std::complex, const Scalar&> > + PrintType; + + Index width = 0; + + std::streamsize explicit_precision; + if (fmt.precision == StreamPrecision) { + explicit_precision = 0; + } else if (fmt.precision == FullPrecision) { + if (NumTraits::IsInteger) { + explicit_precision = 0; + } else { + explicit_precision = significant_decimals_impl::run(); + } + } else { + explicit_precision = fmt.precision; + } + + std::streamsize old_precision = 0; + if (explicit_precision) old_precision = s.precision(explicit_precision); + + bool align_cols = !(fmt.flags & DontAlignCols); + if (align_cols) { + // compute the largest width + for (Index j = 0; j < m.cols(); ++j) + for (Index i = 0; i < m.rows(); ++i) { + std::stringstream sstr; + sstr.copyfmt(s); + sstr << static_cast(m.coeff(i, j)); + width = std::max(width, Index(sstr.str().length())); + } + } + std::streamsize old_width = s.width(); + char old_fill_character = s.fill(); + s << fmt.matPrefix; + for (Index i = 0; i < m.rows(); ++i) { + if (i) s << fmt.rowSpacer; + s << fmt.rowPrefix; + if (width) { + s.fill(fmt.fill); + s.width(width); + } + s << static_cast(m.coeff(i, 0)); + for (Index j = 1; j < m.cols(); ++j) { + s << fmt.coeffSeparator; + if (width) { + s.fill(fmt.fill); + s.width(width); + } + s << static_cast(m.coeff(i, j)); + } + s << fmt.rowSuffix; + if (i < m.rows() - 1) s << fmt.rowSeparator; + } + s << fmt.matSuffix; + if (explicit_precision) s.precision(old_precision); + if (width) { + s.fill(old_fill_character); + s.width(old_width); + } + return s; +} + +} // end namespace internal + +/** \relates DenseBase + * + * Outputs the matrix, to the given stream. + * + * If you wish to print the matrix with a format different than the default, use DenseBase::format(). + * + * It is also possible to change the default format by defining EIGEN_DEFAULT_IO_FORMAT before including Eigen headers. + * If not defined, this will automatically be defined to Eigen::IOFormat(), that is the Eigen::IOFormat with default + * parameters. + * + * \sa DenseBase::format() + */ +template +std::ostream& operator<<(std::ostream& s, const DenseBase& m) { + return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT); +} + +template +std::ostream& operator<<(std::ostream& s, const DiagonalBase& m) { + return internal::print_matrix(s, m.derived(), EIGEN_DEFAULT_IO_FORMAT); +} + +} // end namespace Eigen + +#endif // EIGEN_IO_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IndexedView.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IndexedView.h new file mode 100644 index 0000000..44d5c02 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/IndexedView.h @@ -0,0 +1,322 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2017 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_INDEXED_VIEW_H +#define EIGEN_INDEXED_VIEW_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct traits> : traits { + enum { + RowsAtCompileTime = int(IndexedViewHelper::SizeAtCompileTime), + ColsAtCompileTime = int(IndexedViewHelper::SizeAtCompileTime), + MaxRowsAtCompileTime = RowsAtCompileTime, + MaxColsAtCompileTime = ColsAtCompileTime, + + XprTypeIsRowMajor = (int(traits::Flags) & RowMajorBit) != 0, + IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1 + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0 + : XprTypeIsRowMajor, + + RowIncr = int(IndexedViewHelper::IncrAtCompileTime), + ColIncr = int(IndexedViewHelper::IncrAtCompileTime), + InnerIncr = IsRowMajor ? ColIncr : RowIncr, + OuterIncr = IsRowMajor ? RowIncr : ColIncr, + + HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), + XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time::ret) + : int(outer_stride_at_compile_time::ret), + XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time::ret) + : int(inner_stride_at_compile_time::ret), + + InnerSize = XprTypeIsRowMajor ? ColsAtCompileTime : RowsAtCompileTime, + IsBlockAlike = InnerIncr == 1 && OuterIncr == 1, + IsInnerPannel = HasSameStorageOrderAsXprType && + is_same, std::conditional_t>::value, + + InnerStrideAtCompileTime = + InnerIncr < 0 || InnerIncr == DynamicIndex || XprInnerStride == Dynamic || InnerIncr == Undefined + ? Dynamic + : XprInnerStride * InnerIncr, + OuterStrideAtCompileTime = + OuterIncr < 0 || OuterIncr == DynamicIndex || XprOuterstride == Dynamic || OuterIncr == Undefined + ? Dynamic + : XprOuterstride * OuterIncr, + + ReturnAsScalar = is_single_range::value && is_single_range::value, + ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike, + ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock), + + // FIXME: we deal with compile-time strides if and only if we have DirectAccessBit flag, + // but this is too strict regarding negative strides... + DirectAccessMask = (int(InnerIncr) != Undefined && int(OuterIncr) != Undefined && InnerIncr >= 0 && OuterIncr >= 0) + ? DirectAccessBit + : 0, + FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, + Flags = (traits::Flags & (HereditaryBits | DirectAccessMask)) | FlagsLvalueBit | FlagsRowMajorBit | + FlagsLinearAccessBit + }; + + typedef Block BlockType; +}; + +template +class IndexedViewImpl; + +} // namespace internal + +/** \class IndexedView + * \ingroup Core_Module + * + * \brief Expression of a non-sequential sub-matrix defined by arbitrary sequences of row and column indices + * + * \tparam XprType the type of the expression in which we are taking the intersections of sub-rows and sub-columns + * \tparam RowIndices the type of the object defining the sequence of row indices + * \tparam ColIndices the type of the object defining the sequence of column indices + * + * This class represents an expression of a sub-matrix (or sub-vector) defined as the intersection + * of sub-sets of rows and columns, that are themself defined by generic sequences of row indices \f$ + * \{r_0,r_1,..r_{m-1}\} \f$ and column indices \f$ \{c_0,c_1,..c_{n-1} \}\f$. Let \f$ A \f$ be the nested matrix, then + * the resulting matrix \f$ B \f$ has \c m rows and \c n columns, and its entries are given by: \f$ B(i,j) = A(r_i,c_j) + * \f$. + * + * The \c RowIndices and \c ColIndices types must be compatible with the following API: + * \code + * operator[](Index) const; + * Index size() const; + * \endcode + * + * Typical supported types thus include: + * - std::vector + * - std::valarray + * - std::array + * - Eigen::ArrayXi + * - decltype(ArrayXi::LinSpaced(...)) + * - Any view/expressions of the previous types + * - Eigen::ArithmeticSequence + * - Eigen::internal::AllRange (helper for Eigen::placeholders::all) + * - Eigen::internal::SingleRange (helper for single index) + * - etc. + * + * In typical usages of %Eigen, this class should never be used directly. It is the return type of + * DenseBase::operator()(const RowIndices&, const ColIndices&). + * + * \sa class Block + */ +template +class IndexedView + : public internal::IndexedViewImpl::StorageKind, + (internal::traits>::Flags & + DirectAccessBit) != 0> { + public: + typedef typename internal::IndexedViewImpl< + XprType, RowIndices, ColIndices, typename internal::traits::StorageKind, + (internal::traits>::Flags & DirectAccessBit) != 0> + Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(IndexedView) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedView) + + template + IndexedView(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {} +}; + +namespace internal { + +// Generic API dispatcher +template +class IndexedViewImpl : public internal::generic_xpr_base>::type { + public: + typedef typename internal::generic_xpr_base>::type Base; + typedef typename internal::ref_selector::non_const_type MatrixTypeNested; + typedef internal::remove_all_t NestedExpression; + typedef typename XprType::Scalar Scalar; + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl) + + template + IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices) + : m_xpr(xpr), m_rowIndices(rowIndices), m_colIndices(colIndices) {} + + /** \returns number of rows */ + Index rows() const { return IndexedViewHelper::size(m_rowIndices); } + + /** \returns number of columns */ + Index cols() const { return IndexedViewHelper::size(m_colIndices); } + + /** \returns the nested expression */ + const internal::remove_all_t& nestedExpression() const { return m_xpr; } + + /** \returns the nested expression */ + std::remove_reference_t& nestedExpression() { return m_xpr; } + + /** \returns a const reference to the object storing/generating the row indices */ + const RowIndices& rowIndices() const { return m_rowIndices; } + + /** \returns a const reference to the object storing/generating the column indices */ + const ColIndices& colIndices() const { return m_colIndices; } + + constexpr Scalar& coeffRef(Index rowId, Index colId) { + return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]); + } + + constexpr const Scalar& coeffRef(Index rowId, Index colId) const { + return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]); + } + + protected: + MatrixTypeNested m_xpr; + RowIndices m_rowIndices; + ColIndices m_colIndices; +}; + +template +class IndexedViewImpl + : public IndexedViewImpl { + public: + using Base = internal::IndexedViewImpl::StorageKind, false>; + using Derived = IndexedView; + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl) + + template + IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {} + + Index rowIncrement() const { + if (traits::RowIncr != DynamicIndex && traits::RowIncr != Undefined) { + return traits::RowIncr; + } + return IndexedViewHelper::incr(this->rowIndices()); + } + Index colIncrement() const { + if (traits::ColIncr != DynamicIndex && traits::ColIncr != Undefined) { + return traits::ColIncr; + } + return IndexedViewHelper::incr(this->colIndices()); + } + + Index innerIncrement() const { return traits::IsRowMajor ? colIncrement() : rowIncrement(); } + + Index outerIncrement() const { return traits::IsRowMajor ? rowIncrement() : colIncrement(); } + + std::decay_t* data() { + Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride(); + Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride(); + return this->nestedExpression().data() + row_offset + col_offset; + } + + const std::decay_t* data() const { + Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride(); + Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride(); + return this->nestedExpression().data() + row_offset + col_offset; + } + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { + if (traits::InnerStrideAtCompileTime != Dynamic) { + return traits::InnerStrideAtCompileTime; + } + return innerIncrement() * this->nestedExpression().innerStride(); + } + + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { + if (traits::OuterStrideAtCompileTime != Dynamic) { + return traits::OuterStrideAtCompileTime; + } + return outerIncrement() * this->nestedExpression().outerStride(); + } +}; + +template +struct unary_evaluator, IndexBased> + : evaluator_base> { + typedef IndexedView XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost /* TODO + cost of row/col index */, + + FlagsLinearAccessBit = + (traits::RowsAtCompileTime == 1 || traits::ColsAtCompileTime == 1) ? LinearAccessBit : 0, + + FlagsRowMajorBit = traits::FlagsRowMajorBit, + + Flags = (evaluator::Flags & (HereditaryBits & ~RowMajorBit /*| LinearAccessBit | DirectAccessBit*/)) | + FlagsLinearAccessBit | FlagsRowMajorBit, + + Alignment = 0 + }; + + EIGEN_DEVICE_FUNC constexpr explicit unary_evaluator(const XprType& xpr) + : m_argImpl(xpr.nestedExpression()), m_xpr(xpr) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && + m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); + return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && + m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); + return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + EIGEN_STATIC_ASSERT_LVALUE(XprType) + Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; + Index col = XprType::RowsAtCompileTime == 1 ? index : 0; + eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && + m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); + return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const { + Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; + Index col = XprType::RowsAtCompileTime == 1 ? index : 0; + eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && + m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); + return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index index) const { + Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; + Index col = XprType::RowsAtCompileTime == 1 ? index : 0; + eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && + m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); + return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); + } + + protected: + evaluator m_argImpl; + const XprType& m_xpr; +}; + +// Catch assignments to an IndexedView. +template +struct evaluator_assume_aliasing> { + static const bool value = true; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_INDEXED_VIEW_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InnerProduct.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InnerProduct.h new file mode 100644 index 0000000..ad9844d --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InnerProduct.h @@ -0,0 +1,260 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2024 Charlie Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_INNER_PRODUCT_EVAL_H +#define EIGEN_INNER_PRODUCT_EVAL_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// recursively searches for the largest simd type that does not exceed Size, or the smallest if no such type exists +template ::type, + bool Stop = + (unpacket_traits::size <= Size) || is_same::half>::value> +struct find_inner_product_packet_helper; + +template +struct find_inner_product_packet_helper { + using type = typename find_inner_product_packet_helper::half>::type; +}; + +template +struct find_inner_product_packet_helper { + using type = Packet; +}; + +template +struct find_inner_product_packet : find_inner_product_packet_helper {}; + +template +struct find_inner_product_packet { + using type = typename packet_traits::type; +}; + +template +struct inner_product_assert { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Lhs) + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Rhs) + EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Lhs, Rhs) +#ifndef EIGEN_NO_DEBUG + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, const Rhs& rhs) { + eigen_assert((lhs.size() == rhs.size()) && "Inner product: lhs and rhs vectors must have same size"); + } +#else + static EIGEN_DEVICE_FUNC void run(const Lhs&, const Rhs&) {} +#endif +}; + +template +struct inner_product_evaluator { + static constexpr int LhsFlags = evaluator::Flags; + static constexpr int RhsFlags = evaluator::Flags; + static constexpr int SizeAtCompileTime = size_prefer_fixed(Lhs::SizeAtCompileTime, Rhs::SizeAtCompileTime); + static constexpr int MaxSizeAtCompileTime = + min_size_prefer_fixed(Lhs::MaxSizeAtCompileTime, Rhs::MaxSizeAtCompileTime); + static constexpr int LhsAlignment = evaluator::Alignment; + static constexpr int RhsAlignment = evaluator::Alignment; + + using Scalar = typename Func::result_type; + using Packet = typename find_inner_product_packet::type; + + static constexpr bool Vectorize = + bool(LhsFlags & RhsFlags & PacketAccessBit) && Func::PacketAccess && + ((MaxSizeAtCompileTime == Dynamic) || (unpacket_traits::size <= MaxSizeAtCompileTime)); + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit inner_product_evaluator(const Lhs& lhs, const Rhs& rhs, + Func func = Func()) + : m_func(func), m_lhs(lhs), m_rhs(rhs), m_size(lhs.size()) { + inner_product_assert::run(lhs, rhs); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return m_size.value(); } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const { + return m_func.coeff(m_lhs.coeff(index), m_rhs.coeff(index)); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(const Scalar& value, Index index) const { + return m_func.coeff(value, m_lhs.coeff(index), m_rhs.coeff(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + return m_func.packet(m_lhs.template packet(index), + m_rhs.template packet(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(const PacketType& value, Index index) const { + return m_func.packet(value, m_lhs.template packet(index), + m_rhs.template packet(index)); + } + + const Func m_func; + const evaluator m_lhs; + const evaluator m_rhs; + const variable_if_dynamic m_size; +}; + +template +struct inner_product_impl; + +// scalar loop +template +struct inner_product_impl { + using Scalar = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval) { + const Index size = eval.size(); + if (size == 0) return Scalar(0); + + Scalar result = eval.coeff(0); + for (Index k = 1; k < size; k++) { + result = eval.coeff(result, k); + } + + return result; + } +}; + +// vector loop +template +struct inner_product_impl { + using UnsignedIndex = std::make_unsigned_t; + using Scalar = typename Evaluator::Scalar; + using Packet = typename Evaluator::Packet; + static constexpr int PacketSize = unpacket_traits::size; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval) { + const UnsignedIndex size = static_cast(eval.size()); + if (size < PacketSize) return inner_product_impl::run(eval); + + const UnsignedIndex packetEnd = numext::round_down(size, PacketSize); + const UnsignedIndex quadEnd = numext::round_down(size, 4 * PacketSize); + const UnsignedIndex numPackets = size / PacketSize; + const UnsignedIndex numRemPackets = (packetEnd - quadEnd) / PacketSize; + + Packet presult0, presult1, presult2, presult3; + + presult0 = eval.template packet(0 * PacketSize); + if (numPackets >= 2) presult1 = eval.template packet(1 * PacketSize); + if (numPackets >= 3) presult2 = eval.template packet(2 * PacketSize); + if (numPackets >= 4) { + presult3 = eval.template packet(3 * PacketSize); + + for (UnsignedIndex k = 4 * PacketSize; k < quadEnd; k += 4 * PacketSize) { + presult0 = eval.packet(presult0, k + 0 * PacketSize); + presult1 = eval.packet(presult1, k + 1 * PacketSize); + presult2 = eval.packet(presult2, k + 2 * PacketSize); + presult3 = eval.packet(presult3, k + 3 * PacketSize); + } + + if (numRemPackets >= 1) presult0 = eval.packet(presult0, quadEnd + 0 * PacketSize); + if (numRemPackets >= 2) presult1 = eval.packet(presult1, quadEnd + 1 * PacketSize); + if (numRemPackets == 3) presult2 = eval.packet(presult2, quadEnd + 2 * PacketSize); + + presult2 = padd(presult2, presult3); + } + + if (numPackets >= 3) presult1 = padd(presult1, presult2); + if (numPackets >= 2) presult0 = padd(presult0, presult1); + + Scalar result = predux(presult0); + for (UnsignedIndex k = packetEnd; k < size; k++) { + result = eval.coeff(result, k); + } + + return result; + } +}; + +template +struct conditional_conj; + +template +struct conditional_conj { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(const Scalar& a) { return numext::conj(a); } + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(const Packet& a) { + return pconj(a); + } +}; + +template +struct conditional_conj { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(const Scalar& a) { return a; } + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(const Packet& a) { + return a; + } +}; + +template +struct scalar_inner_product_op { + using result_type = typename ScalarBinaryOpTraits::ReturnType; + using conj_helper = conditional_conj; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type coeff(const LhsScalar& a, const RhsScalar& b) const { + return (conj_helper::coeff(a) * b); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type coeff(const result_type& accum, const LhsScalar& a, + const RhsScalar& b) const { + return (conj_helper::coeff(a) * b) + accum; + } + static constexpr bool PacketAccess = false; +}; + +// Partial specialization for packet access if and only if +// LhsScalar == RhsScalar == ScalarBinaryOpTraits::ReturnType. +template +struct scalar_inner_product_op< + Scalar, + std::enable_if_t::ReturnType, Scalar>::value, + Scalar>, + Conj> { + using result_type = Scalar; + using conj_helper = conditional_conj; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(const Scalar& a, const Scalar& b) const { + return pmul(conj_helper::coeff(a), b); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(const Scalar& accum, const Scalar& a, const Scalar& b) const { + return pmadd(conj_helper::coeff(a), b, accum); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(const Packet& a, const Packet& b) const { + return pmul(conj_helper::packet(a), b); + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(const Packet& accum, const Packet& a, const Packet& b) const { + return pmadd(conj_helper::packet(a), b, accum); + } + static constexpr bool PacketAccess = packet_traits::HasMul && packet_traits::HasAdd; +}; + +template +struct default_inner_product_impl { + using LhsScalar = typename traits::Scalar; + using RhsScalar = typename traits::Scalar; + using Op = scalar_inner_product_op; + using Evaluator = inner_product_evaluator; + using result_type = typename Evaluator::Scalar; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type run(const MatrixBase& a, const MatrixBase& b) { + Evaluator eval(a.derived(), b.derived(), Op()); + return inner_product_impl::run(eval); + } +}; + +template +struct dot_impl : default_inner_product_impl {}; + +} // namespace internal +} // namespace Eigen + +#endif // EIGEN_INNER_PRODUCT_EVAL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InternalHeaderCheck.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InternalHeaderCheck.h new file mode 100644 index 0000000..1cea572 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/InternalHeaderCheck.h @@ -0,0 +1,3 @@ +#ifndef EIGEN_CORE_MODULE_H +#error "Please include Eigen/Core instead of including headers inside the src directory directly." +#endif diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Inverse.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Inverse.h new file mode 100644 index 0000000..855e3b3 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Inverse.h @@ -0,0 +1,108 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2014-2019 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_INVERSE_H +#define EIGEN_INVERSE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +class InverseImpl; + +namespace internal { + +template +struct traits > : traits { + typedef typename XprType::PlainObject PlainObject; + typedef traits BaseTraits; + enum { Flags = BaseTraits::Flags & RowMajorBit }; +}; + +} // end namespace internal + +/** \class Inverse + * + * \brief Expression of the inverse of another expression + * + * \tparam XprType the type of the expression we are taking the inverse + * + * This class represents an abstract expression of A.inverse() + * and most of the time this is the only way it is used. + * + */ +template +class Inverse : public InverseImpl::StorageKind> { + public: + typedef typename XprType::StorageIndex StorageIndex; + typedef typename XprType::Scalar Scalar; + typedef typename internal::ref_selector::type XprTypeNested; + typedef internal::remove_all_t XprTypeNestedCleaned; + typedef typename internal::ref_selector::type Nested; + typedef internal::remove_all_t NestedExpression; + + explicit EIGEN_DEVICE_FUNC constexpr Inverse(const XprType& xpr) : m_xpr(xpr) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_xpr.cols(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_xpr.rows(); } + + EIGEN_DEVICE_FUNC constexpr const XprTypeNestedCleaned& nestedExpression() const { return m_xpr; } + + protected: + XprTypeNested m_xpr; +}; + +// Generic API dispatcher +template +class InverseImpl : public internal::generic_xpr_base >::type { + public: + typedef typename internal::generic_xpr_base >::type Base; + typedef typename XprType::Scalar Scalar; + + private: + Scalar coeff(Index row, Index col) const; + Scalar coeff(Index i) const; +}; + +namespace internal { + +/** \internal + * \brief Default evaluator for Inverse expression. + * + * This default evaluator for Inverse expression simply evaluate the inverse into a temporary + * by a call to internal::call_assignment_no_alias. + * Therefore, inverse implementers only have to specialize Assignment, ...> for + * there own nested expression. + * + * \sa class Inverse + */ +template +struct unary_evaluator > : public evaluator::PlainObject> { + typedef Inverse InverseType; + typedef typename InverseType::PlainObject PlainObject; + typedef evaluator Base; + + enum { Flags = Base::Flags | EvalBeforeNestingBit }; + + EIGEN_DEVICE_FUNC unary_evaluator(const InverseType& inv_xpr) : m_result(inv_xpr.rows(), inv_xpr.cols()) { + internal::construct_at(this, m_result); + internal::call_assignment_no_alias(m_result, inv_xpr); + } + + protected: + PlainObject m_result; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_INVERSE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Map.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Map.h new file mode 100644 index 0000000..52a8eca --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Map.h @@ -0,0 +1,154 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2007-2010 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MAP_H +#define EIGEN_MAP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : public traits { + typedef traits TraitsBase; + enum { + PlainObjectTypeInnerSize = ((traits::Flags & RowMajorBit) == RowMajorBit) + ? PlainObjectType::ColsAtCompileTime + : PlainObjectType::RowsAtCompileTime, + + InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 + ? int(PlainObjectType::InnerStrideAtCompileTime) + : int(StrideType::InnerStrideAtCompileTime), + OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 + ? (InnerStrideAtCompileTime == Dynamic || PlainObjectTypeInnerSize == Dynamic + ? Dynamic + : int(InnerStrideAtCompileTime) * int(PlainObjectTypeInnerSize)) + : int(StrideType::OuterStrideAtCompileTime), + Alignment = int(MapOptions) & int(AlignedMask), + Flags0 = TraitsBase::Flags & (~NestByRefBit), + Flags = is_lvalue::value ? int(Flags0) : (int(Flags0) & ~LvalueBit) + }; + + private: + enum { Options }; // Expressions don't have Options +}; +} // namespace internal + +/** \class Map + * \ingroup Core_Module + * + * \brief A matrix or vector expression mapping an existing array of data. + * + * \tparam PlainObjectType the equivalent matrix type of the mapped data + * \tparam MapOptions specifies the pointer alignment in bytes. It can be: \c #Aligned128, \c #Aligned64, \c #Aligned32, + * \c #Aligned16, \c #Aligned8 or \c #Unaligned. The default is \c #Unaligned. \tparam StrideType optionally specifies + * strides. By default, Map assumes the memory layout of an ordinary, contiguous array. This can be overridden by + * specifying strides. The type passed here must be a specialization of the Stride template, see examples below. + * + * This class represents a matrix or vector expression mapping an existing array of data. + * It can be used to let Eigen interface without any overhead with non-Eigen data structures, + * such as plain C arrays or structures from other libraries. By default, it assumes that the + * data is laid out contiguously in memory. You can however override this by explicitly specifying + * inner and outer strides. + * + * Here's an example of simply mapping a contiguous array as a \ref TopicStorageOrders "column-major" matrix: + * \include Map_simple.cpp + * Output: \verbinclude Map_simple.out + * + * If you need to map non-contiguous arrays, you can do so by specifying strides: + * + * Here's an example of mapping an array as a vector, specifying an inner stride, that is, the pointer + * increment between two consecutive coefficients. Here, we're specifying the inner stride as a compile-time + * fixed value. + * \include Map_inner_stride.cpp + * Output: \verbinclude Map_inner_stride.out + * + * Here's an example of mapping an array while specifying an outer stride. Here, since we're mapping + * as a column-major matrix, 'outer stride' means the pointer increment between two consecutive columns. + * Here, we're specifying the outer stride as a runtime parameter. Note that here \c OuterStride<> is + * a short version of \c OuterStride because the default template parameter of OuterStride + * is \c Dynamic + * \include Map_outer_stride.cpp + * Output: \verbinclude Map_outer_stride.out + * + * For more details and for an example of specifying both an inner and an outer stride, see class Stride. + * + * \b Tip: to change the array of data mapped by a Map object, you can use the C++ + * placement new syntax: + * + * Example: \include Map_placement_new.cpp + * Output: \verbinclude Map_placement_new.out + * + * This class is the return type of PlainObjectBase::Map() but can also be used directly. + * + * \sa PlainObjectBase::Map(), \ref TopicStorageOrders + */ +template +class Map : public MapBase > { + public: + typedef MapBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Map) + + typedef typename Base::PointerType PointerType; + typedef PointerType PointerArgType; + EIGEN_DEVICE_FUNC constexpr inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; } + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const { + return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; + } + + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { + return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() + : internal::traits::OuterStrideAtCompileTime != Dynamic + ? Index(internal::traits::OuterStrideAtCompileTime) + : IsVectorAtCompileTime ? (this->size() * innerStride()) + : int(Flags) & RowMajorBit ? (this->cols() * innerStride()) + : (this->rows() * innerStride()); + } + + /** Constructor in the fixed-size case. + * + * \param dataPtr pointer to the array to map + * \param stride optional Stride object, passing the strides. + */ + EIGEN_DEVICE_FUNC constexpr explicit inline Map(PointerArgType dataPtr, const StrideType& stride = StrideType()) + : Base(cast_to_pointer_type(dataPtr)), m_stride(stride) {} + + /** Constructor in the dynamic-size vector case. + * + * \param dataPtr pointer to the array to map + * \param size the size of the vector expression + * \param stride optional Stride object, passing the strides. + */ + EIGEN_DEVICE_FUNC constexpr inline Map(PointerArgType dataPtr, Index size, const StrideType& stride = StrideType()) + : Base(cast_to_pointer_type(dataPtr), size), m_stride(stride) {} + + /** Constructor in the dynamic-size matrix case. + * + * \param dataPtr pointer to the array to map + * \param rows the number of rows of the matrix expression + * \param cols the number of columns of the matrix expression + * \param stride optional Stride object, passing the strides. + */ + EIGEN_DEVICE_FUNC constexpr inline Map(PointerArgType dataPtr, Index rows, Index cols, + const StrideType& stride = StrideType()) + : Base(cast_to_pointer_type(dataPtr), rows, cols), m_stride(stride) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map) + + protected: + StrideType m_stride; +}; + +} // end namespace Eigen + +#endif // EIGEN_MAP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MapBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MapBase.h new file mode 100644 index 0000000..3e11725 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MapBase.h @@ -0,0 +1,283 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2007-2010 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MAPBASE_H +#define EIGEN_MAPBASE_H + +#define EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) \ + EIGEN_STATIC_ASSERT((int(internal::evaluator::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \ + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT) + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \ingroup Core_Module + * + * \brief Base class for dense Map and Block expression with direct access + * + * This base class provides the const low-level accessors (e.g. coeff, coeffRef) of dense + * Map and Block objects with direct access. + * Typical users do not have to directly deal with this class. + * + * This class can be extended by through the macro plugin \c EIGEN_MAPBASE_PLUGIN. + * See \link TopicCustomizing_Plugins customizing Eigen \endlink for details. + * + * The \c Derived class has to provide the following two methods describing the memory layout: + * \code Index innerStride() const; \endcode + * \code Index outerStride() const; \endcode + * + * \sa class Map, class Block + */ +template +class MapBase : public internal::dense_xpr_base::type { + public: + typedef typename internal::dense_xpr_base::type Base; + enum { + RowsAtCompileTime = internal::traits::RowsAtCompileTime, + ColsAtCompileTime = internal::traits::ColsAtCompileTime, + InnerStrideAtCompileTime = internal::traits::InnerStrideAtCompileTime, + SizeAtCompileTime = Base::SizeAtCompileTime + }; + + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::packet_traits::type PacketScalar; + typedef typename NumTraits::Real RealScalar; + typedef std::conditional_t::value), Scalar*, const Scalar*> PointerType; + + using Base::derived; + // using Base::RowsAtCompileTime; + // using Base::ColsAtCompileTime; + // using Base::SizeAtCompileTime; + using Base::Flags; + using Base::IsRowMajor; + using Base::IsVectorAtCompileTime; + using Base::MaxColsAtCompileTime; + using Base::MaxRowsAtCompileTime; + using Base::MaxSizeAtCompileTime; + + using Base::coeff; + using Base::coeffRef; + using Base::cols; + using Base::eval; + using Base::lazyAssign; + using Base::rows; + using Base::size; + + using Base::colStride; + using Base::innerStride; + using Base::outerStride; + using Base::rowStride; + + // bug 217 - compile error on ICC 11.1 + using Base::operator=; + + typedef typename Base::CoeffReturnType CoeffReturnType; + + /** \copydoc DenseBase::rows() */ + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_rows.value(); } + /** \copydoc DenseBase::cols() */ + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_cols.value(); } + + /** Returns a pointer to the first coefficient of the matrix or vector. + * + * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride(). + * + * \sa innerStride(), outerStride() + */ + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_data; } + + /** \copydoc PlainObjectBase::coeff(Index,Index) const */ + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeff(Index rowId, Index colId) const { + return m_data[colId * colStride() + rowId * rowStride()]; + } + + /** \copydoc PlainObjectBase::coeff(Index) const */ + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeff(Index index) const { + EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) + return m_data[index * innerStride()]; + } + + /** \copydoc PlainObjectBase::coeffRef(Index,Index) const */ + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeffRef(Index rowId, Index colId) const { + return this->m_data[colId * colStride() + rowId * rowStride()]; + } + + /** \copydoc PlainObjectBase::coeffRef(Index) const */ + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeffRef(Index index) const { + EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) + return this->m_data[index * innerStride()]; + } + + /** \internal */ + template + inline PacketScalar packet(Index rowId, Index colId) const { + return internal::ploadt(m_data + (colId * colStride() + rowId * rowStride())); + } + + /** \internal */ + template + inline PacketScalar packet(Index index) const { + EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) + return internal::ploadt(m_data + index * innerStride()); + } + + /** \internal Constructor for fixed size matrices or vectors */ + EIGEN_DEVICE_FUNC constexpr explicit inline MapBase(PointerType dataPtr) + : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) { + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + checkSanity(); + } + + /** \internal Constructor for dynamically sized vectors */ + EIGEN_DEVICE_FUNC constexpr inline MapBase(PointerType dataPtr, Index vecSize) + : m_data(dataPtr), + m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)), + m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime)) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + eigen_assert(vecSize >= 0); + eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize); + checkSanity(); + } + + /** \internal Constructor for dynamically sized matrices */ + EIGEN_DEVICE_FUNC constexpr inline MapBase(PointerType dataPtr, Index rows, Index cols) + : m_data(dataPtr), m_rows(rows), m_cols(cols) { + eigen_assert((dataPtr == 0) || (rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && + cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); + checkSanity(); + } + +#ifdef EIGEN_MAPBASE_PLUGIN +#include EIGEN_MAPBASE_PLUGIN +#endif + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) + + template + EIGEN_DEVICE_FUNC void checkSanity(std::enable_if_t<(internal::traits::Alignment > 0), void*> = 0) const { +// Temporary macro to allow scalars to not be properly aligned. This is while we sort out failures +// in TensorFlow Lite that are currently relying on this UB. +#ifndef EIGEN_ALLOW_UNALIGNED_SCALARS + // Pointer must be aligned to the Scalar type, otherwise we get UB. + eigen_assert((std::uintptr_t(m_data) % alignof(Scalar) == 0) && "data is not scalar-aligned"); +#endif +#if EIGEN_MAX_ALIGN_BYTES > 0 + // innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible + // value: + const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime); + EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride); + eigen_assert((((std::uintptr_t(m_data) % internal::traits::Alignment) == 0) || + (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits::Alignment) && + "data is not aligned"); +#endif + } + + template + EIGEN_DEVICE_FUNC void checkSanity(std::enable_if_t::Alignment == 0, void*> = 0) const { +#ifndef EIGEN_ALLOW_UNALIGNED_SCALARS + // Pointer must be aligned to the Scalar type, otherwise we get UB. + eigen_assert((std::uintptr_t(m_data) % alignof(Scalar) == 0) && "data is not scalar-aligned"); +#endif + } + + PointerType m_data; + const internal::variable_if_dynamic m_rows; + const internal::variable_if_dynamic m_cols; +}; + +/** \ingroup Core_Module + * + * \brief Base class for non-const dense Map and Block expression with direct access + * + * This base class provides the non-const low-level accessors (e.g. coeff and coeffRef) of + * dense Map and Block objects with direct access. + * It inherits MapBase which defines the const variant for reading specific entries. + * + * \sa class Map, class Block + */ +template +class MapBase : public MapBase { + typedef MapBase ReadOnlyMapBase; + + public: + typedef MapBase Base; + + typedef typename Base::Scalar Scalar; + typedef typename Base::PacketScalar PacketScalar; + typedef typename Base::StorageIndex StorageIndex; + typedef typename Base::PointerType PointerType; + + using Base::coeff; + using Base::coeffRef; + using Base::cols; + using Base::derived; + using Base::rows; + using Base::size; + + using Base::colStride; + using Base::innerStride; + using Base::outerStride; + using Base::rowStride; + + typedef std::conditional_t::value, Scalar, const Scalar> ScalarWithConstIfNotLvalue; + + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return this->m_data; } + EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { + return this->m_data; + } // no const-cast here so non-const-correct code will give a compile error + + EIGEN_DEVICE_FUNC constexpr inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col) { + return this->m_data[col * colStride() + row * rowStride()]; + } + + EIGEN_DEVICE_FUNC constexpr inline ScalarWithConstIfNotLvalue& coeffRef(Index index) { + EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) + return this->m_data[index * innerStride()]; + } + + template + inline void writePacket(Index row, Index col, const PacketScalar& val) { + internal::pstoret(this->m_data + (col * colStride() + row * rowStride()), val); + } + + template + inline void writePacket(Index index, const PacketScalar& val) { + EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) + internal::pstoret(this->m_data + index * innerStride(), val); + } + + EIGEN_DEVICE_FUNC constexpr explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {} + EIGEN_DEVICE_FUNC constexpr inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {} + EIGEN_DEVICE_FUNC constexpr inline MapBase(PointerType dataPtr, Index rows, Index cols) : Base(dataPtr, rows, cols) {} + + EIGEN_DEVICE_FUNC Derived& operator=(const MapBase& other) { + ReadOnlyMapBase::Base::operator=(other); + return derived(); + } + + // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base, + // see bugs 821 and 920. + using ReadOnlyMapBase::Base::operator=; + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) +}; + +#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS + +} // end namespace Eigen + +#endif // EIGEN_MAPBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctions.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctions.h new file mode 100644 index 0000000..4e7597c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctions.h @@ -0,0 +1,2160 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MATHFUNCTIONS_H +#define EIGEN_MATHFUNCTIONS_H + +// TODO: consider moving these constants to NumTraits. +// Source: WolframAlpha +#define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406L +#define EIGEN_LOG2E 1.442695040888963407359924681001892137426645954152985934135449406931109219L +#define EIGEN_LN2 0.693147180559945309417232121458176568075500134360255254120680009493393621L + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/** \internal \class global_math_functions_filtering_base + * + * What it does: + * Defines a typedef 'type' as follows: + * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then + * global_math_functions_filtering_base::type is a typedef for it. + * - otherwise, global_math_functions_filtering_base::type is a typedef for T. + * + * How it's used: + * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions. + * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know + * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase. + * So we must make sure to use sin_impl > and not sin_impl, otherwise our partial + * specialization won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells + * it. + * + * How it's implemented: + * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you + * replace the typename dummy by an integer template parameter, it doesn't work anymore! + */ + +template +struct global_math_functions_filtering_base { + typedef T type; +}; + +template +struct always_void { + typedef void type; +}; + +template +struct global_math_functions_filtering_base< + T, typename always_void::type> { + typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; +}; + +#define EIGEN_MATHFUNC_IMPL(func, scalar) \ + Eigen::internal::func##_impl::type> +#define EIGEN_MATHFUNC_RETVAL(func, scalar) \ + typename Eigen::internal::func##_retval< \ + typename Eigen::internal::global_math_functions_filtering_base::type>::type + +/**************************************************************************** + * Implementation of real * + ****************************************************************************/ + +template ::IsComplex> +struct real_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static constexpr RealScalar run(const Scalar& x) { return x; } +}; + +template +struct real_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + using std::real; + return real(x); + } +}; + +template +struct real_impl : real_default_impl {}; + +#if defined(EIGEN_GPU_COMPILE_PHASE) +template +struct real_impl> { + typedef T RealScalar; + EIGEN_DEVICE_FUNC static inline T run(const std::complex& x) { return x.real(); } +}; +#endif + +template +struct real_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of imag * + ****************************************************************************/ + +template ::IsComplex> +struct imag_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar&) { return RealScalar(0); } +}; + +template +struct imag_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + using std::imag; + return imag(x); + } +}; + +template +struct imag_impl : imag_default_impl {}; + +#if defined(EIGEN_GPU_COMPILE_PHASE) +template +struct imag_impl> { + typedef T RealScalar; + EIGEN_DEVICE_FUNC static inline T run(const std::complex& x) { return x.imag(); } +}; +#endif + +template +struct imag_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of real_ref * + ****************************************************************************/ + +template +struct real_ref_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar& run(Scalar& x) { return reinterpret_cast(&x)[0]; } + EIGEN_DEVICE_FUNC static inline const RealScalar& run(const Scalar& x) { + return reinterpret_cast(&x)[0]; + } +}; + +template +struct real_ref_retval { + typedef typename NumTraits::Real& type; +}; + +/**************************************************************************** + * Implementation of imag_ref * + ****************************************************************************/ + +template +struct imag_ref_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar& run(Scalar& x) { return reinterpret_cast(&x)[1]; } + EIGEN_DEVICE_FUNC static inline const RealScalar& run(const Scalar& x) { + return reinterpret_cast(&x)[1]; + } +}; + +template +struct imag_ref_default_impl { + EIGEN_DEVICE_FUNC constexpr static Scalar run(Scalar&) { return Scalar(0); } + EIGEN_DEVICE_FUNC constexpr static const Scalar run(const Scalar&) { return Scalar(0); } +}; + +template +struct imag_ref_impl : imag_ref_default_impl::IsComplex> {}; + +template +struct imag_ref_retval { + typedef typename NumTraits::Real& type; +}; + +} // namespace internal + +namespace numext { + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline internal::add_const_on_value_type_t real_ref( + const Scalar& x) { + return internal::real_ref_impl::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) { + return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar select(const Scalar& mask, const Scalar& a, const Scalar& b) { + return numext::is_exactly_zero(mask) ? b : a; +} + +} // namespace numext + +namespace internal { + +/**************************************************************************** + * Implementation of conj * + ****************************************************************************/ + +template ::IsComplex> +struct conj_default_impl { + EIGEN_DEVICE_FUNC static constexpr Scalar run(const Scalar& x) { return x; } +}; + +template +struct conj_default_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { + using std::conj; + return conj(x); + } +}; + +template ::IsComplex> +struct conj_impl : conj_default_impl {}; + +template +struct conj_retval { + typedef Scalar type; +}; + +/**************************************************************************** + * Implementation of abs2 * + ****************************************************************************/ + +template +struct abs2_impl_default { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { return x * x; } +}; + +template +struct abs2_impl_default // IsComplex +{ + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + return numext::real(x) * numext::real(x) + numext::imag(x) * numext::imag(x); + } +}; + +template +struct abs2_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + return abs2_impl_default::IsComplex>::run(x); + } +}; + +template +struct abs2_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of sqrt/rsqrt * + ****************************************************************************/ + +template +struct sqrt_impl { + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE Scalar run(const Scalar& x) { + EIGEN_USING_STD(sqrt); + return sqrt(x); + } +}; + +// Complex sqrt defined in MathFunctionsImpl.h. +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_sqrt(const ComplexT& a_x); + +// Custom implementation is faster than `std::sqrt`, works on +// GPU, and correctly handles special cases (unlike MSVC). +template +struct sqrt_impl> { + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE std::complex run(const std::complex& x) { return complex_sqrt(x); } +}; + +template +struct sqrt_retval { + typedef Scalar type; +}; + +// Default implementation relies on numext::sqrt, at bottom of file. +template +struct rsqrt_impl; + +// Complex rsqrt defined in MathFunctionsImpl.h. +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_rsqrt(const ComplexT& a_x); + +template +struct rsqrt_impl> { + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE std::complex run(const std::complex& x) { + return complex_rsqrt(x); + } +}; + +template +struct rsqrt_retval { + typedef Scalar type; +}; + +/**************************************************************************** + * Implementation of norm1 * + ****************************************************************************/ + +template +struct norm1_default_impl; + +template +struct norm1_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + EIGEN_USING_STD(abs); + return abs(numext::real(x)) + abs(numext::imag(x)); + } +}; + +template +struct norm1_default_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { + EIGEN_USING_STD(abs); + return abs(x); + } +}; + +template +struct norm1_impl : norm1_default_impl::IsComplex> {}; + +template +struct norm1_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of hypot * + ****************************************************************************/ + +template +struct hypot_impl; + +template +struct hypot_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of cast * + ****************************************************************************/ + +template +struct cast_impl { + EIGEN_DEVICE_FUNC static inline NewType run(const OldType& x) { return static_cast(x); } +}; + +template +struct cast_impl { + EIGEN_DEVICE_FUNC static inline bool run(const OldType& x) { return x != OldType(0); } +}; + +// Casting from S -> Complex leads to an implicit conversion from S to T, +// generating warnings on clang. Here we explicitly cast the real component. +template +struct cast_impl::IsComplex && NumTraits::IsComplex>> { + EIGEN_DEVICE_FUNC static inline NewType run(const OldType& x) { + typedef typename NumTraits::Real NewReal; + return static_cast(static_cast(x)); + } +}; + +// Returns NewType directly to avoid unintended intermediate conversions. + +template +EIGEN_DEVICE_FUNC inline NewType cast(const OldType& x) { + return cast_impl::run(x); +} + +/**************************************************************************** + * Implementation of arg * + ****************************************************************************/ + +// Visual Studio 2017 has a bug where arg(float) returns 0 for negative inputs. +// This seems to be fixed in VS 2019. +#if (!EIGEN_COMP_MSVC || EIGEN_COMP_MSVC >= 1920) +// std::arg is only defined for types of std::complex, or integer types or float/double/long double +template ::IsComplex || is_integral::value || + is_same::value || is_same::value || + is_same::value> +struct arg_default_impl; + +template +struct arg_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + // There is no official ::arg on device in CUDA/HIP, so we always need to use std::arg. + using std::arg; + return static_cast(arg(x)); + } +}; + +// Must be non-complex floating-point type (e.g. half/bfloat16). +template +struct arg_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + return (x < Scalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0); + } +}; +#else +template ::IsComplex> +struct arg_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + return (x < RealScalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0); + } +}; + +template +struct arg_default_impl { + typedef typename NumTraits::Real RealScalar; + EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { + EIGEN_USING_STD(arg); + return arg(x); + } +}; +#endif +template +struct arg_impl : arg_default_impl {}; + +template +struct arg_retval { + typedef typename NumTraits::Real type; +}; + +/**************************************************************************** + * Implementation of expm1 * + ****************************************************************************/ + +// This implementation is based on GSL Math's expm1. +namespace std_fallback { +// fallback expm1 implementation in case there is no expm1(Scalar) function in namespace of Scalar, +// or that there is no suitable std::expm1 function available. Implementation +// attributed to Kahan. See: http://www.plunk.org/~hatch/rightway.php. +template +EIGEN_DEVICE_FUNC inline Scalar expm1(const Scalar& x) { + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + typedef typename NumTraits::Real RealScalar; + + EIGEN_USING_STD(exp); + Scalar u = exp(x); + if (numext::equal_strict(u, Scalar(1))) { + return x; + } + Scalar um1 = u - RealScalar(1); + if (numext::equal_strict(um1, Scalar(-1))) { + return RealScalar(-1); + } + + EIGEN_USING_STD(log); + Scalar logu = log(u); + return numext::equal_strict(u, logu) ? u : (u - RealScalar(1)) * x / logu; +} +} // namespace std_fallback + +template +struct expm1_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + EIGEN_USING_STD(expm1); + return expm1(x); + } +}; + +template +struct expm1_retval { + typedef Scalar type; +}; + +/**************************************************************************** + * Implementation of log * + ****************************************************************************/ + +// Complex log defined in MathFunctionsImpl.h. +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_log(const ComplexT& z); + +template +struct log_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { + EIGEN_USING_STD(log); + return static_cast(log(x)); + } +}; + +template +struct log_impl> { + EIGEN_DEVICE_FUNC static inline std::complex run(const std::complex& z) { return complex_log(z); } +}; + +/**************************************************************************** + * Implementation of log1p * + ****************************************************************************/ + +namespace std_fallback { +// fallback log1p implementation in case there is no log1p(Scalar) function in namespace of Scalar, +// or that there is no suitable std::log1p function available +template +EIGEN_DEVICE_FUNC inline Scalar log1p(const Scalar& x) { + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + typedef typename NumTraits::Real RealScalar; + EIGEN_USING_STD(log); + Scalar x1p = RealScalar(1) + x; + Scalar log_1p = log_impl::run(x1p); + const bool is_small = numext::equal_strict(x1p, Scalar(1)); + const bool is_inf = numext::equal_strict(x1p, log_1p); + return (is_small || is_inf) ? x : x * (log_1p / (x1p - RealScalar(1))); +} +} // namespace std_fallback + +template +struct log1p_impl { + EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) + + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x) { + EIGEN_USING_STD(log1p); + return log1p(x); + } +}; + +// Specialization for complex types that are not supported by std::log1p. +template +struct log1p_impl> { + EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar) + + EIGEN_DEVICE_FUNC static inline std::complex run(const std::complex& x) { + return std_fallback::log1p(x); + } +}; + +template +struct log1p_retval { + typedef Scalar type; +}; + +/**************************************************************************** + * Implementation of pow * + ****************************************************************************/ + +template ::IsInteger && NumTraits::IsInteger> +struct pow_impl { + // typedef Scalar retval; + typedef typename ScalarBinaryOpTraits>::ReturnType + result_type; + static EIGEN_DEVICE_FUNC inline result_type run(const ScalarX& x, const ScalarY& y) { + EIGEN_USING_STD(pow); + return pow(x, y); + } +}; + +template +struct pow_impl { + typedef ScalarX result_type; + static EIGEN_DEVICE_FUNC inline ScalarX run(ScalarX x, ScalarY y) { + ScalarX res(1); + eigen_assert(!NumTraits::IsSigned || y >= 0); + if (y & 1) res *= x; + y >>= 1; + while (y) { + x *= x; + if (y & 1) res *= x; + y >>= 1; + } + return res; + } +}; + +enum { meta_floor_log2_terminate, meta_floor_log2_move_up, meta_floor_log2_move_down, meta_floor_log2_bogus }; + +template +struct meta_floor_log2_selector { + enum { + middle = (lower + upper) / 2, + value = (upper <= lower + 1) ? int(meta_floor_log2_terminate) + : (n < (1 << middle)) ? int(meta_floor_log2_move_down) + : (n == 0) ? int(meta_floor_log2_bogus) + : int(meta_floor_log2_move_up) + }; +}; + +template ::value> +struct meta_floor_log2 {}; + +template +struct meta_floor_log2 { + enum { value = meta_floor_log2::middle>::value }; +}; + +template +struct meta_floor_log2 { + enum { value = meta_floor_log2::middle, upper>::value }; +}; + +template +struct meta_floor_log2 { + enum { value = (n >= ((unsigned int)(1) << (lower + 1))) ? lower + 1 : lower }; +}; + +template +struct meta_floor_log2 { + // no value, error at compile time +}; + +template +struct count_bits_impl { + static_assert(std::is_integral::value && std::is_unsigned::value, + "BitsType must be an unsigned integer"); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + int n = CHAR_BIT * sizeof(BitsType); + int shift = n / 2; + while (bits > 0 && shift > 0) { + BitsType y = bits >> shift; + if (y > 0) { + n -= shift; + bits = y; + } + shift /= 2; + } + if (shift == 0) { + --n; + } + return n; + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + int n = CHAR_BIT * sizeof(BitsType); + int shift = n / 2; + while (bits > 0 && shift > 0) { + BitsType y = bits << shift; + if (y > 0) { + n -= shift; + bits = y; + } + shift /= 2; + } + if (shift == 0) { + --n; + } + return n; + } +}; + +// Count leading zeros. +template +EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + return count_bits_impl::clz(bits); +} + +// Count trailing zeros. +template +EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + return count_bits_impl::ctz(bits); +} + +#if EIGEN_COMP_GNUC || EIGEN_COMP_CLANG + +template +struct count_bits_impl< + BitsType, std::enable_if_t::value && sizeof(BitsType) <= sizeof(unsigned int)>> { + static constexpr int kNumBits = static_cast(sizeof(BitsType) * CHAR_BIT); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + static constexpr int kLeadingBitsOffset = (sizeof(unsigned int) - sizeof(BitsType)) * CHAR_BIT; + return bits == 0 ? kNumBits : __builtin_clz(static_cast(bits)) - kLeadingBitsOffset; + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + return bits == 0 ? kNumBits : __builtin_ctz(static_cast(bits)); + } +}; + +template +struct count_bits_impl::value && sizeof(unsigned int) < sizeof(BitsType) && + sizeof(BitsType) <= sizeof(unsigned long)>> { + static constexpr int kNumBits = static_cast(sizeof(BitsType) * CHAR_BIT); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + static constexpr int kLeadingBitsOffset = (sizeof(unsigned long) - sizeof(BitsType)) * CHAR_BIT; + return bits == 0 ? kNumBits : __builtin_clzl(static_cast(bits)) - kLeadingBitsOffset; + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + return bits == 0 ? kNumBits : __builtin_ctzl(static_cast(bits)); + } +}; + +template +struct count_bits_impl::value && sizeof(unsigned long) < sizeof(BitsType) && + sizeof(BitsType) <= sizeof(unsigned long long)>> { + static constexpr int kNumBits = static_cast(sizeof(BitsType) * CHAR_BIT); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + static constexpr int kLeadingBitsOffset = (sizeof(unsigned long long) - sizeof(BitsType)) * CHAR_BIT; + return bits == 0 ? kNumBits : __builtin_clzll(static_cast(bits)) - kLeadingBitsOffset; + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + return bits == 0 ? kNumBits : __builtin_ctzll(static_cast(bits)); + } +}; + +#elif EIGEN_COMP_MSVC + +template +struct count_bits_impl< + BitsType, std::enable_if_t::value && sizeof(BitsType) <= sizeof(unsigned long)>> { + static constexpr int kNumBits = static_cast(sizeof(BitsType) * CHAR_BIT); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + unsigned long out; + _BitScanReverse(&out, static_cast(bits)); + return bits == 0 ? kNumBits : (kNumBits - 1) - static_cast(out); + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + unsigned long out; + _BitScanForward(&out, static_cast(bits)); + return bits == 0 ? kNumBits : static_cast(out); + } +}; + +#ifdef _WIN64 + +template +struct count_bits_impl::value && sizeof(unsigned long) < sizeof(BitsType) && + sizeof(BitsType) <= sizeof(__int64)>> { + static constexpr int kNumBits = static_cast(sizeof(BitsType) * CHAR_BIT); + static EIGEN_DEVICE_FUNC inline int clz(BitsType bits) { + unsigned long out; + _BitScanReverse64(&out, static_cast(bits)); + return bits == 0 ? kNumBits : (kNumBits - 1) - static_cast(out); + } + + static EIGEN_DEVICE_FUNC inline int ctz(BitsType bits) { + unsigned long out; + _BitScanForward64(&out, static_cast(bits)); + return bits == 0 ? kNumBits : static_cast(out); + } +}; + +#endif // _WIN64 + +#endif // EIGEN_COMP_GNUC || EIGEN_COMP_CLANG + +template +struct log_2_impl { + static constexpr int kTotalBits = sizeof(BitsType) * CHAR_BIT; + static EIGEN_DEVICE_FUNC inline int run_ceil(const BitsType& x) { + const int n = kTotalBits - clz(x); + bool power_of_two = (x & (x - 1)) == 0; + return x == 0 ? 0 : power_of_two ? (n - 1) : n; + } + static EIGEN_DEVICE_FUNC inline int run_floor(const BitsType& x) { + const int n = kTotalBits - clz(x); + return x == 0 ? 0 : n - 1; + } +}; + +template +int log2_ceil(const BitsType& x) { + return log_2_impl::run_ceil(x); +} + +template +int log2_floor(const BitsType& x) { + return log_2_impl::run_floor(x); +} + +// Implementation of is* functions + +template +EIGEN_DEVICE_FUNC std::enable_if_t::has_infinity || std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN), + bool> +isfinite_impl(const T&) { + return true; +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t<(std::numeric_limits::has_infinity || std::numeric_limits::has_quiet_NaN || + std::numeric_limits::has_signaling_NaN) && + (!NumTraits::IsComplex), + bool> +isfinite_impl(const T& x) { + EIGEN_USING_STD(isfinite); + return isfinite EIGEN_NOT_A_MACRO(x); +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t::has_infinity, bool> isinf_impl(const T&) { + return false; +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t<(std::numeric_limits::has_infinity && !NumTraits::IsComplex), bool> isinf_impl( + const T& x) { + EIGEN_USING_STD(isinf); + return isinf EIGEN_NOT_A_MACRO(x); +} + +template +EIGEN_DEVICE_FUNC + std::enable_if_t::has_quiet_NaN || std::numeric_limits::has_signaling_NaN), bool> + isnan_impl(const T&) { + return false; +} + +template +EIGEN_DEVICE_FUNC std::enable_if_t< + (std::numeric_limits::has_quiet_NaN || std::numeric_limits::has_signaling_NaN) && (!NumTraits::IsComplex), + bool> +isnan_impl(const T& x) { + EIGEN_USING_STD(isnan); + return isnan EIGEN_NOT_A_MACRO(x); +} + +// The following overload are defined at the end of this file +template +EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex& x); +template +EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex& x); +template +EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex& x); +template +EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS T ptanh_float(const T& a_x); + +/**************************************************************************** + * Implementation of sign * + ****************************************************************************/ +template ::IsComplex != 0), + bool IsInteger = (NumTraits::IsInteger != 0)> +struct sign_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& a) { return Scalar((a > Scalar(0)) - (a < Scalar(0))); } +}; + +template +struct sign_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& a) { + return (isnan_impl)(a) ? a : Scalar((a > Scalar(0)) - (a < Scalar(0))); + } +}; + +template +struct sign_impl { + EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& a) { + using real_type = typename NumTraits::Real; + EIGEN_USING_STD(abs); + real_type aa = abs(a); + if (aa == real_type(0)) return Scalar(0); + aa = real_type(1) / aa; + return Scalar(numext::real(a) * aa, numext::imag(a) * aa); + } +}; + +// The sign function for bool is the identity. +template <> +struct sign_impl { + EIGEN_DEVICE_FUNC static inline bool run(const bool& a) { return a; } +}; + +template +struct sign_retval { + typedef Scalar type; +}; + +// suppress "unary minus operator applied to unsigned type, result still unsigned" warnings on MSVC +// note: `0 - a` is distinct from `-a` when Scalar is a floating point type and `a` is zero + +template ::IsInteger> +struct negate_impl { + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar run(const Scalar& a) { return -a; } +}; + +template +struct negate_impl { + EIGEN_STATIC_ASSERT((!is_same::value), NEGATE IS NOT DEFINED FOR BOOLEAN TYPES) + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar run(const Scalar& a) { return Scalar(0) - a; } +}; + +template +struct negate_retval { + typedef Scalar type; +}; + +template ::type>::IsInteger> +struct nearest_integer_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_floor(const Scalar& x) { + EIGEN_USING_STD(floor) return floor(x); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_ceil(const Scalar& x) { + EIGEN_USING_STD(ceil) return ceil(x); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_rint(const Scalar& x) { + EIGEN_USING_STD(rint) return rint(x); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_round(const Scalar& x) { + EIGEN_USING_STD(round) return round(x); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_trunc(const Scalar& x) { + EIGEN_USING_STD(trunc) return trunc(x); + } +}; +template +struct nearest_integer_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_floor(const Scalar& x) { return x; } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_ceil(const Scalar& x) { return x; } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_rint(const Scalar& x) { return x; } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_round(const Scalar& x) { return x; } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_trunc(const Scalar& x) { return x; } +}; + +// Extra namespace to prevent leaking std::fma into Eigen::internal. +namespace has_fma_detail { + +template +struct has_fma_impl : public std::false_type {}; + +using std::fma; + +template +struct has_fma_impl< + T, std::enable_if_t(), std::declval(), std::declval()))>::value>> + : public std::true_type {}; + +} // namespace has_fma_detail + +template +struct has_fma : public has_fma_detail::has_fma_impl {}; + +// Default implementation. +template +struct fma_impl { + static_assert(has_fma::value, "No function fma(...) for type. Please provide an implementation."); +}; + +// STD or ADL version if it exists. +template +struct fma_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T run(const T& a, const T& b, const T& c) { + using std::fma; + return fma(a, b, c); + } +}; + +#if defined(EIGEN_GPUCC) +template <> +struct has_fma : public true_type {}; + +template <> +struct fma_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float run(const float& a, const float& b, const float& c) { + return ::fmaf(a, b, c); + } +}; + +template <> +struct has_fma : public true_type {}; + +template <> +struct fma_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double run(const double& a, const double& b, const double& c) { + return ::fma(a, b, c); + } +}; +#endif + +// Basic multiply-add. +template +struct madd_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) { + return x * y + z; + } +}; + +#if EIGEN_SCALAR_MADD_USE_FMA +template +struct madd_impl::value>> { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) { + return fma_impl::run(x, y, z); + } +}; +#endif + +} // end namespace internal + +/**************************************************************************** + * Generic math functions * + ****************************************************************************/ + +namespace numext { + +#if (!defined(EIGEN_GPUCC) || defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC)) +template +EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) { + EIGEN_USING_STD(min) + return min EIGEN_NOT_A_MACRO(x, y); +} + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) { + EIGEN_USING_STD(max) + return max EIGEN_NOT_A_MACRO(x, y); +} +#else +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) { + return y < x ? y : x; +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float mini(const float& x, const float& y) { + return fminf(x, y); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double mini(const double& x, const double& y) { + return fmin(x, y); +} + +#ifndef EIGEN_GPU_COMPILE_PHASE +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE long double mini(const long double& x, const long double& y) { +#if defined(EIGEN_HIPCC) + // no "fminl" on HIP yet + return (x < y) ? x : y; +#else + return fminl(x, y); +#endif +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) { + return x < y ? y : x; +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float maxi(const float& x, const float& y) { + return fmaxf(x, y); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double maxi(const double& x, const double& y) { + return fmax(x, y); +} +#ifndef EIGEN_GPU_COMPILE_PHASE +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE long double maxi(const long double& x, const long double& y) { +#if defined(EIGEN_HIPCC) + // no "fmaxl" on HIP yet + return (x > y) ? x : y; +#else + return fmaxl(x, y); +#endif +} +#endif +#endif + +#if defined(SYCL_DEVICE_ONLY) + +#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_long) +#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_long) +#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong) +#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong) +#define SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(NAME, FUNC) \ + SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \ + SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) +#define SYCL_SPECIALIZE_INTEGER_TYPES_UNARY(NAME, FUNC) \ + SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \ + SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) +#define SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(NAME, FUNC) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \ + SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_double) +#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(NAME, FUNC) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \ + SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_double) +#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(NAME, FUNC, RET_TYPE) \ + SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_float) \ + SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_double) + +#define SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \ + template <> \ + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE& x) { \ + return cl::sycl::FUNC(x); \ + } + +#define SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, TYPE) SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, TYPE, TYPE) + +#define SYCL_SPECIALIZE_GEN1_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \ + template <> \ + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE1& x, const ARG_TYPE2& y) { \ + return cl::sycl::FUNC(x, y); \ + } + +#define SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \ + SYCL_SPECIALIZE_GEN1_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE, ARG_TYPE) + +#define SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, TYPE) SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, TYPE, TYPE) + +SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(mini, min) +SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(mini, fmin) +SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(maxi, max) +SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(maxi, fmax) + +#endif + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline internal::add_const_on_value_type_t imag_ref( + const Scalar& x) { + return internal::imag_ref_impl::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) { + return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(sign, Scalar) sign(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(sign, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(negate, Scalar) negate(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(negate, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); +} + +EIGEN_DEVICE_FUNC inline bool abs2(bool x) { return x; } + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T absdiff(const T& x, const T& y) { + return x > y ? x - y : y - x; +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float absdiff(const float& x, const float& y) { + return fabsf(x - y); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double absdiff(const double& x, const double& y) { + return fabs(x - y); +} + +// HIP and CUDA do not support long double. +#ifndef EIGEN_GPU_COMPILE_PHASE +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE long double absdiff(const long double& x, const long double& y) { + return fabsl(x - y); +} +#endif + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); +} + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) { + return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(hypot, hypot) +#endif + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(log1p, log1p) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float log1p(const float& x) { + return ::log1pf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double log1p(const double& x) { + return ::log1p(x); +} +#endif + +template +EIGEN_DEVICE_FUNC inline typename internal::pow_impl::result_type pow(const ScalarX& x, + const ScalarY& y) { + return internal::pow_impl::run(x, y); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(pow, pow) +#endif + +template +EIGEN_DEVICE_FUNC bool(isnan)(const T& x) { + return internal::isnan_impl(x); +} +template +EIGEN_DEVICE_FUNC bool(isinf)(const T& x) { + return internal::isinf_impl(x); +} +template +EIGEN_DEVICE_FUNC bool(isfinite)(const T& x) { + return internal::isfinite_impl(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isnan, isnan, bool) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isinf, isinf, bool) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isfinite, isfinite, bool) +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar rint(const Scalar& x) { + return internal::nearest_integer_impl::run_rint(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar round(const Scalar& x) { + return internal::nearest_integer_impl::run_round(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar(floor)(const Scalar& x) { + return internal::nearest_integer_impl::run_floor(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar(ceil)(const Scalar& x) { + return internal::nearest_integer_impl::run_ceil(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar(trunc)(const Scalar& x) { + return internal::nearest_integer_impl::run_trunc(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(round, round) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(floor, floor) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(ceil, ceil) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(trunc, trunc) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float floor(const float& x) { + return ::floorf(x); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double floor(const double& x) { + return ::floor(x); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float ceil(const float& x) { + return ::ceilf(x); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double ceil(const double& x) { + return ::ceil(x); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float trunc(const float& x) { + return ::truncf(x); +} +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double trunc(const double& x) { + return ::trunc(x); +} +#endif + +// Integer division with rounding up. +// T is assumed to be an integer type with a>=0, and b>0 +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr T div_ceil(T a, T b) { + using UnsignedT = typename internal::make_unsigned::type; + EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) + // Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations + const UnsignedT ua = UnsignedT(a); + const UnsignedT ub = UnsignedT(b); + // Note: This form is used because it cannot overflow. + return ua == 0 ? 0 : (ua - 1) / ub + 1; +} + +// Integer round down to nearest power of b +// T is assumed to be an integer type with a>=0, and b>0 +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE constexpr T round_down(T a, U b) { + using UnsignedT = typename internal::make_unsigned::type; + using UnsignedU = typename internal::make_unsigned::type; + EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) + EIGEN_STATIC_ASSERT((NumTraits::IsInteger), THIS FUNCTION IS FOR INTEGER TYPES) + // Note: explicitly declaring a and b as non-negative values allows the compiler to use better optimizations + const UnsignedT ua = UnsignedT(a); + const UnsignedU ub = UnsignedU(b); + return ub * (ua / ub); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T log2(T x) { + EIGEN_USING_STD(log2); + return log2(x); +} + +/** Log base 2 for 32 bits positive integers. + * Conveniently returns 0 for x==0. */ +constexpr int log2(int x) { + unsigned int v(x); + constexpr int table[32] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return table[(v * 0x07C4ACDDU) >> 27]; +} + +/** \returns the square root of \a x. + * + * It is essentially equivalent to + * \code using std::sqrt; return sqrt(x); \endcode + * but slightly faster for float/double and some compilers (e.g., gcc), thanks to + * specializations when SSE is enabled. + * + * It's usage is justified in performance critical functions, like norm/normalize. + */ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x); +} + +// Boolean specialization, avoids implicit float to bool conversion (-Wimplicit-conversion-floating-point-to-bool). +template <> +EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_DEVICE_FUNC bool sqrt(const bool& x) { + return x; +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sqrt, sqrt) +#endif + +/** \returns the cube root of \a x. **/ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t::IsComplex, T> cbrt(const T& x) { + EIGEN_USING_STD(cbrt); + return static_cast(cbrt(x)); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::enable_if_t::IsComplex, T> cbrt(const T& x) { + EIGEN_USING_STD(pow); + return pow(x, typename NumTraits::Real(1.0 / 3.0)); +} + +/** \returns the reciprocal square root of \a x. **/ +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T rsqrt(const T& x) { + return internal::rsqrt_impl::run(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T log(const T& x) { + return internal::log_impl::run(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(log, log) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float log(const float& x) { + return ::logf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double log(const double& x) { + return ::log(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE + std::enable_if_t::IsSigned || NumTraits::IsComplex, typename NumTraits::Real> + abs(const T& x) { + EIGEN_USING_STD(abs); + return abs(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE + std::enable_if_t::IsSigned || NumTraits::IsComplex), typename NumTraits::Real> + abs(const T& x) { + return x; +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_INTEGER_TYPES_UNARY(abs, abs) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(abs, fabs) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float abs(const float& x) { + return ::fabsf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double abs(const double& x) { + return ::fabs(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float abs(const std::complex& x) { + return ::hypotf(x.real(), x.imag()); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double abs(const std::complex& x) { + return ::hypot(x.real(), x.imag()); +} +#endif + +template ::IsInteger, bool IsSigned = NumTraits::IsSigned> +struct signbit_impl; +template +struct signbit_impl { + static constexpr size_t Size = sizeof(Scalar); + static constexpr size_t Shift = (CHAR_BIT * Size) - 1; + using intSize_t = typename get_integer_by_size::signed_type; + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static Scalar run(const Scalar& x) { + intSize_t a = bit_cast(x); + a = a >> Shift; + Scalar result = bit_cast(a); + return result; + } +}; +template +struct signbit_impl { + static constexpr size_t Size = sizeof(Scalar); + static constexpr size_t Shift = (CHAR_BIT * Size) - 1; + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static constexpr Scalar run(const Scalar& x) { return x >> Shift; } +}; +template +struct signbit_impl { + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static constexpr Scalar run(const Scalar&) { return Scalar(0); } +}; +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static constexpr Scalar signbit(const Scalar& x) { + return signbit_impl::run(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T exp(const T& x) { + EIGEN_USING_STD(exp); + return exp(x); +} + +// MSVC screws up some edge-cases for std::exp(complex). +#ifdef EIGEN_COMP_MSVC +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp(const std::complex& x) { + EIGEN_USING_STD(exp); + // If z is (x,±∞) (for any finite x), the result is (NaN,NaN) and FE_INVALID is raised. + // If z is (x,NaN) (for any finite x), the result is (NaN,NaN) and FE_INVALID may be raised. + if ((isfinite)(real_ref(x)) && !(isfinite)(imag_ref(x))) { + return std::complex(NumTraits::quiet_NaN(), NumTraits::quiet_NaN()); + } + // If z is (+∞,±∞), the result is (±∞,NaN) and FE_INVALID is raised (the sign of the real part is unspecified) + // If z is (+∞,NaN), the result is (±∞,NaN) (the sign of the real part is unspecified) + if ((real_ref(x) == NumTraits::infinity() && !(isfinite)(imag_ref(x)))) { + return std::complex(NumTraits::infinity(), NumTraits::quiet_NaN()); + } + return exp(x); +} +#endif + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(exp, exp) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float exp(const float& x) { + return ::expf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double exp(const double& x) { + return ::exp(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp(const std::complex& x) { + float com = ::expf(x.real()); + float res_real = com * ::cosf(x.imag()); + float res_imag = com * ::sinf(x.imag()); + return std::complex(res_real, res_imag); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp(const std::complex& x) { + double com = ::exp(x.real()); + double res_real = com * ::cos(x.imag()); + double res_imag = com * ::sin(x.imag()); + return std::complex(res_real, res_imag); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T exp2(const T& x) { + EIGEN_USING_STD(exp2); + return exp2(x); +} + +// MSVC screws up some edge-cases for std::exp2(complex). +#ifdef EIGEN_COMP_MSVC +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp2(const std::complex& x) { + EIGEN_USING_STD(exp); + // If z is (x,±∞) (for any finite x), the result is (NaN,NaN) and FE_INVALID is raised. + // If z is (x,NaN) (for any finite x), the result is (NaN,NaN) and FE_INVALID may be raised. + if ((isfinite)(real_ref(x)) && !(isfinite)(imag_ref(x))) { + return std::complex(NumTraits::quiet_NaN(), NumTraits::quiet_NaN()); + } + // If z is (+∞,±∞), the result is (±∞,NaN) and FE_INVALID is raised (the sign of the real part is unspecified) + // If z is (+∞,NaN), the result is (±∞,NaN) (the sign of the real part is unspecified) + if ((real_ref(x) == NumTraits::infinity() && !(isfinite)(imag_ref(x)))) { + return std::complex(NumTraits::infinity(), NumTraits::quiet_NaN()); + } + return exp2(x); +} +#endif + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(exp2, exp2) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float exp2(const float& x) { + return ::exp2f(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double exp2(const double& x) { + return ::exp2(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp2(const std::complex& x) { + float com = ::exp2f(x.real()); + float res_real = com * ::cosf(static_cast(EIGEN_LN2) * x.imag()); + float res_imag = com * ::sinf(static_cast(EIGEN_LN2) * x.imag()); + return std::complex(res_real, res_imag); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::complex exp2(const std::complex& x) { + double com = ::exp2(x.real()); + double res_real = com * ::cos(static_cast(EIGEN_LN2) * x.imag()); + double res_imag = com * ::sin(static_cast(EIGEN_LN2) * x.imag()); + return std::complex(res_real, res_imag); +} +#endif + +template +EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(expm1, Scalar) expm1(const Scalar& x) { + return EIGEN_MATHFUNC_IMPL(expm1, Scalar)::run(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(expm1, expm1) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float expm1(const float& x) { + return ::expm1f(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double expm1(const double& x) { + return ::expm1(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T cos(const T& x) { + EIGEN_USING_STD(cos); + return cos(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(cos, cos) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float cos(const float& x) { + return ::cosf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double cos(const double& x) { + return ::cos(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T sin(const T& x) { + EIGEN_USING_STD(sin); + return sin(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sin, sin) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float sin(const float& x) { + return ::sinf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double sin(const double& x) { + return ::sin(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T tan(const T& x) { + EIGEN_USING_STD(tan); + return tan(x); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(tan, tan) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float tan(const float& x) { + return ::tanf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double tan(const double& x) { + return ::tan(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T acos(const T& x) { + EIGEN_USING_STD(acos); + return acos(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T acosh(const T& x) { + EIGEN_USING_STD(acosh); + return static_cast(acosh(x)); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(acos, acos) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(acosh, acosh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float acos(const float& x) { + return ::acosf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double acos(const double& x) { + return ::acos(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T asin(const T& x) { + EIGEN_USING_STD(asin); + return asin(x); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T asinh(const T& x) { + EIGEN_USING_STD(asinh); + return static_cast(asinh(x)); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(asin, asin) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(asinh, asinh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float asin(const float& x) { + return ::asinf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double asin(const double& x) { + return ::asin(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T atan(const T& x) { + EIGEN_USING_STD(atan); + return static_cast(atan(x)); +} + +template ::IsComplex, int> = 0> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T atan2(const T& y, const T& x) { + EIGEN_USING_STD(atan2); + return static_cast(atan2(y, x)); +} + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T atanh(const T& x) { + EIGEN_USING_STD(atanh); + return static_cast(atanh(x)); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(atan, atan) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(atanh, atanh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float atan(const float& x) { + return ::atanf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double atan(const double& x) { + return ::atan(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T cosh(const T& x) { + EIGEN_USING_STD(cosh); + return static_cast(cosh(x)); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(cosh, cosh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float cosh(const float& x) { + return ::coshf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double cosh(const double& x) { + return ::cosh(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T sinh(const T& x) { + EIGEN_USING_STD(sinh); + return static_cast(sinh(x)); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sinh, sinh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float sinh(const float& x) { + return ::sinhf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double sinh(const double& x) { + return ::sinh(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T tanh(const T& x) { + EIGEN_USING_STD(tanh); + return tanh(x); +} + +#if (!defined(EIGEN_GPUCC)) && EIGEN_FAST_MATH && !defined(SYCL_DEVICE_ONLY) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float tanh(float x) { return internal::ptanh_float(x); } +#endif + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(tanh, tanh) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float tanh(const float& x) { + return ::tanhf(x); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double tanh(const double& x) { + return ::tanh(x); +} +#endif + +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T fmod(const T& a, const T& b) { + EIGEN_USING_STD(fmod); + return fmod(a, b); +} + +#if defined(SYCL_DEVICE_ONLY) +SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(fmod, fmod) +#endif + +#if defined(EIGEN_GPUCC) +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float fmod(const float& a, const float& b) { + return ::fmodf(a, b); +} + +template <> +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double fmod(const double& a, const double& b) { + return ::fmod(a, b); +} +#endif + +#if defined(SYCL_DEVICE_ONLY) +#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY +#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY +#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY +#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY +#undef SYCL_SPECIALIZE_INTEGER_TYPES_BINARY +#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY +#undef SYCL_SPECIALIZE_FLOATING_TYPES_BINARY +#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY +#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE +#undef SYCL_SPECIALIZE_GEN_UNARY_FUNC +#undef SYCL_SPECIALIZE_UNARY_FUNC +#undef SYCL_SPECIALIZE_GEN1_BINARY_FUNC +#undef SYCL_SPECIALIZE_GEN2_BINARY_FUNC +#undef SYCL_SPECIALIZE_BINARY_FUNC +#endif + +template ::value>> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar logical_shift_left(const Scalar& a, int n) { + return a << n; +} + +template ::value>> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar logical_shift_right(const Scalar& a, int n) { + using UnsignedScalar = typename numext::get_integer_by_size::unsigned_type; + return bit_cast(bit_cast(a) >> n); +} + +template ::value>> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar& a, int n) { + using SignedScalar = typename numext::get_integer_by_size::signed_type; + return bit_cast(bit_cast(a) >> n); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) { + return internal::fma_impl::run(x, y, z); +} + +// Multiply-add. +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar madd(const Scalar& x, const Scalar& y, const Scalar& z) { + return internal::madd_impl::run(x, y, z); +} + +} // end namespace numext + +namespace internal { + +template +EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex& x) { + return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x)); +} + +template +EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex& x) { + return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x)); +} + +template +EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex& x) { + return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x)); +} + +/**************************************************************************** + * Implementation of fuzzy comparisons * + ****************************************************************************/ + +template +struct scalar_fuzzy_default_impl {}; + +template +struct scalar_fuzzy_default_impl { + typedef typename NumTraits::Real RealScalar; + template + EIGEN_DEVICE_FUNC static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, + const RealScalar& prec) { + return numext::abs(x) <= numext::abs(y) * prec; + } + EIGEN_DEVICE_FUNC static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) { + return numext::abs(x - y) <= numext::mini(numext::abs(x), numext::abs(y)) * prec; + } + EIGEN_DEVICE_FUNC static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) { + return x <= y || isApprox(x, y, prec); + } +}; + +template +struct scalar_fuzzy_default_impl { + typedef typename NumTraits::Real RealScalar; + template + EIGEN_DEVICE_FUNC static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) { + return x == Scalar(0); + } + EIGEN_DEVICE_FUNC static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) { return x == y; } + EIGEN_DEVICE_FUNC static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) { + return x <= y; + } +}; + +template +struct scalar_fuzzy_default_impl { + typedef typename NumTraits::Real RealScalar; + template + EIGEN_DEVICE_FUNC static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, + const RealScalar& prec) { + return numext::abs2(x) <= numext::abs2(y) * prec * prec; + } + EIGEN_DEVICE_FUNC static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) { + return numext::abs2(x - y) <= numext::mini(numext::abs2(x), numext::abs2(y)) * prec * prec; + } +}; + +template +struct scalar_fuzzy_impl + : scalar_fuzzy_default_impl::IsComplex, NumTraits::IsInteger> {}; + +template +EIGEN_DEVICE_FUNC inline bool isMuchSmallerThan( + const Scalar& x, const OtherScalar& y, + const typename NumTraits::Real& precision = NumTraits::dummy_precision()) { + return scalar_fuzzy_impl::template isMuchSmallerThan(x, y, precision); +} + +template +EIGEN_DEVICE_FUNC inline bool isApprox( + const Scalar& x, const Scalar& y, + const typename NumTraits::Real& precision = NumTraits::dummy_precision()) { + return scalar_fuzzy_impl::isApprox(x, y, precision); +} + +template +EIGEN_DEVICE_FUNC inline bool isApproxOrLessThan( + const Scalar& x, const Scalar& y, + const typename NumTraits::Real& precision = NumTraits::dummy_precision()) { + return scalar_fuzzy_impl::isApproxOrLessThan(x, y, precision); +} + +/****************************************** +*** The special case of the bool type *** +******************************************/ + +template <> +struct scalar_fuzzy_impl { + typedef bool RealScalar; + + template + EIGEN_DEVICE_FUNC static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) { + return !x; + } + + EIGEN_DEVICE_FUNC static inline bool isApprox(bool x, bool y, bool) { return x == y; } + + EIGEN_DEVICE_FUNC static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) { + return (!x) || y; + } +}; + +} // end namespace internal + +// Default implementations that rely on other numext implementations +namespace internal { + +// Specialization for complex types that are not supported by std::expm1. +template +struct expm1_impl> { + EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar) + + EIGEN_DEVICE_FUNC static inline std::complex run(const std::complex& x) { + RealScalar xr = x.real(); + RealScalar xi = x.imag(); + // expm1(z) = exp(z) - 1 + // = exp(x + i * y) - 1 + // = exp(x) * (cos(y) + i * sin(y)) - 1 + // = exp(x) * cos(y) - 1 + i * exp(x) * sin(y) + // Imag(expm1(z)) = exp(x) * sin(y) + // Real(expm1(z)) = exp(x) * cos(y) - 1 + // = exp(x) * cos(y) - 1. + // = expm1(x) + exp(x) * (cos(y) - 1) + // = expm1(x) + exp(x) * (2 * sin(y / 2) ** 2) + RealScalar erm1 = numext::expm1(xr); + RealScalar er = erm1 + RealScalar(1.); + RealScalar sin2 = numext::sin(xi / RealScalar(2.)); + sin2 = sin2 * sin2; + RealScalar s = numext::sin(xi); + RealScalar real_part = erm1 - RealScalar(2.) * er * sin2; + return std::complex(real_part, er * s); + } +}; + +template +struct rsqrt_impl { + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE T run(const T& x) { return T(1) / numext::sqrt(x); } +}; + +#if defined(EIGEN_GPU_COMPILE_PHASE) +template +struct conj_impl, true> { + EIGEN_DEVICE_FUNC static inline std::complex run(const std::complex& x) { + return std::complex(numext::real(x), -numext::imag(x)); + } +}; +#endif + +// Complex multiply and division operators. +// Note that these do not handle the case if inf+NaNi, which is considered an infinity. +// This is for consistency with our standard pmul, pdiv implementations. +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex complex_multiply(const std::complex& a, + const std::complex& b) { + const T a_real = numext::real(a); + const T a_imag = numext::imag(a); + const T b_real = numext::real(b); + const T b_imag = numext::imag(b); + return std::complex(a_real * b_real - a_imag * b_imag, a_imag * b_real + a_real * b_imag); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex complex_divide_fast(const std::complex& a, + const std::complex& b) { + const T a_real = numext::real(a); + const T a_imag = numext::imag(a); + const T b_real = numext::real(b); + const T b_imag = numext::imag(b); + const T norm = (b_real * b_real + b_imag * b_imag); + return std::complex((a_real * b_real + a_imag * b_imag) / norm, (a_imag * b_real - a_real * b_imag) / norm); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex complex_divide_smith(const std::complex& a, + const std::complex& b) { + const T a_real = numext::real(a); + const T a_imag = numext::imag(a); + const T b_real = numext::real(b); + const T b_imag = numext::imag(b); + // Smith's complex division (https://arxiv.org/pdf/1210.4539.pdf), + // guards against over/under-flow. + const bool scale_imag = numext::abs(b_imag) <= numext::abs(b_real); + const T rscale = scale_imag ? T(1) : b_real / b_imag; + const T iscale = scale_imag ? b_imag / b_real : T(1); + const T denominator = b_real * rscale + b_imag * iscale; + return std::complex((a_real * rscale + a_imag * iscale) / denominator, + (a_imag * rscale - a_real * iscale) / denominator); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex complex_divide(const std::complex& a, + const std::complex& b) { +#if EIGEN_FAST_MATH + return complex_divide_fast(a, b); +#else + return complex_divide_smith(a, b); +#endif +} + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_MATHFUNCTIONS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctionsImpl.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctionsImpl.h new file mode 100644 index 0000000..b8760e0 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MathFunctionsImpl.h @@ -0,0 +1,265 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2014 Pedro Gonnet (pedro.gonnet@gmail.com) +// Copyright (C) 2016 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MATHFUNCTIONSIMPL_H +#define EIGEN_MATHFUNCTIONSIMPL_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/** \internal Fast reciprocal using Newton-Raphson's method. + + Preconditions: + 1. The starting guess provided in approx_a_recip must have at least half + the leading mantissa bits in the correct result, such that a single + Newton-Raphson step is sufficient to get within 1-2 ulps of the correct + result. + 2. If a is zero, approx_a_recip must be infinite with the same sign as a. + 3. If a is infinite, approx_a_recip must be zero with the same sign as a. + + If the preconditions are satisfied, which they are for the _*_rcp_ps + instructions on x86, the result has a maximum relative error of 2 ulps, + and correctly handles reciprocals of zero, infinity, and NaN. +*/ +template +struct generic_reciprocal_newton_step { + static_assert(Steps > 0, "Steps must be at least 1."); + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& a, const Packet& approx_a_recip) { + using Scalar = typename unpacket_traits::type; + const Packet one = pset1(Scalar(1)); + // Refine the approximation using one Newton-Raphson step: + // x_{i} = x_{i-1} * (2 - a * x_{i-1}) + const Packet x = generic_reciprocal_newton_step::run(a, approx_a_recip); + const Packet tmp = pnmadd(a, x, one); + // If tmp is NaN, it means that a is either +/-0 or +/-Inf. + // In this case return the approximation directly. + const Packet is_not_nan = pcmp_eq(tmp, tmp); + // Use two FMAs instead of FMA+FMUL to improve precision. + return pselect(is_not_nan, pmadd(x, tmp, x), x); + } +}; + +template +struct generic_reciprocal_newton_step { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& /*unused*/, const Packet& approx_rsqrt) { + return approx_rsqrt; + } +}; + +/** \internal Fast reciprocal sqrt using Newton-Raphson's method. + + Preconditions: + 1. The starting guess provided in approx_a_recip must have at least half + the leading mantissa bits in the correct result, such that a single + Newton-Raphson step is sufficient to get within 1-2 ulps of the correct + result. + 2. If a is zero, approx_a_recip must be infinite with the same sign as a. + 3. If a is infinite, approx_a_recip must be zero with the same sign as a. + + If the preconditions are satisfied, which they are for the _*_rcp_ps + instructions on x86, the result has a maximum relative error of 2 ulps, + and correctly handles zero, infinity, and NaN. Positive denormals are + treated as zero. +*/ +template +struct generic_rsqrt_newton_step { + static_assert(Steps > 0, "Steps must be at least 1."); + using Scalar = typename unpacket_traits::type; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& a, const Packet& approx_rsqrt) { + const Scalar kMinusHalf = Scalar(-1) / Scalar(2); + const Packet cst_minus_half = pset1(kMinusHalf); + const Packet cst_minus_one = pset1(Scalar(-1)); + + Packet inv_sqrt = approx_rsqrt; + for (int step = 0; step < Steps; ++step) { + // Refine the approximation using one Newton-Raphson step: + // h_n = (x * inv_sqrt) * inv_sqrt - 1 (so that h_n is nearly 0). + // inv_sqrt = inv_sqrt - 0.5 * inv_sqrt * h_n + Packet r2 = pmul(a, inv_sqrt); + Packet half_r = pmul(inv_sqrt, cst_minus_half); + Packet h_n = pmadd(r2, inv_sqrt, cst_minus_one); + inv_sqrt = pmadd(half_r, h_n, inv_sqrt); + } + + // If x is NaN, then either: + // 1) the input is NaN + // 2) zero and infinity were multiplied + // In either of these cases, return approx_rsqrt + return pselect(pisnan(inv_sqrt), approx_rsqrt, inv_sqrt); + } +}; + +template +struct generic_rsqrt_newton_step { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& /*unused*/, const Packet& approx_rsqrt) { + return approx_rsqrt; + } +}; + +/** \internal Fast sqrt using Newton-Raphson's method. + + Preconditions: + 1. The starting guess for the reciprocal sqrt provided in approx_rsqrt must + have at least half the leading mantissa bits in the correct result, such + that a single Newton-Raphson step is sufficient to get within 1-2 ulps of + the correct result. + 2. If a is zero, approx_rsqrt must be infinite. + 3. If a is infinite, approx_rsqrt must be zero. + + If the preconditions are satisfied, which they are for the _*_rsqrt_ps + instructions on x86, the result has a maximum relative error of 2 ulps, + and correctly handles zero and infinity, and NaN. Positive denormal inputs + are treated as zero. +*/ +template +struct generic_sqrt_newton_step { + static_assert(Steps > 0, "Steps must be at least 1."); + + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Packet run(const Packet& a, const Packet& approx_rsqrt) { + using Scalar = typename unpacket_traits::type; + const Packet one_point_five = pset1(Scalar(1.5)); + const Packet minus_half = pset1(Scalar(-0.5)); + // If a is inf or zero, return a directly. + const Packet inf_mask = pcmp_eq(a, pset1(NumTraits::infinity())); + const Packet return_a = por(pcmp_eq(a, pzero(a)), inf_mask); + // Do a single step of Newton's iteration for reciprocal square root: + // x_{n+1} = x_n * (1.5 + (-0.5 * x_n) * (a * x_n))). + // The Newton's step is computed this way to avoid over/under-flows. + Packet rsqrt = pmul(approx_rsqrt, pmadd(pmul(minus_half, approx_rsqrt), pmul(a, approx_rsqrt), one_point_five)); + for (int step = 1; step < Steps; ++step) { + rsqrt = pmul(rsqrt, pmadd(pmul(minus_half, rsqrt), pmul(a, rsqrt), one_point_five)); + } + + // Return sqrt(x) = x * rsqrt(x) for non-zero finite positive arguments. + // Return a itself for 0 or +inf, NaN for negative arguments. + return pselect(return_a, a, pmul(a, rsqrt)); + } +}; + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE RealScalar positive_real_hypot(const RealScalar& x, + const RealScalar& y) { + // IEEE IEC 6059 special cases. + if ((numext::isinf)(x) || (numext::isinf)(y)) return NumTraits::infinity(); + if ((numext::isnan)(x) || (numext::isnan)(y)) return NumTraits::quiet_NaN(); + + EIGEN_USING_STD(sqrt); + RealScalar p, qp; + p = numext::maxi(x, y); + if (numext::is_exactly_zero(p)) return RealScalar(0); + qp = numext::mini(y, x) / p; + return p * sqrt(RealScalar(1) + qp * qp); +} + +template +struct hypot_impl { + typedef typename NumTraits::Real RealScalar; + static EIGEN_DEVICE_FUNC inline RealScalar run(const Scalar& x, const Scalar& y) { + EIGEN_USING_STD(abs); + return positive_real_hypot(abs(x), abs(y)); + } +}; + +// Generic complex sqrt implementation that correctly handles corner cases +// according to https://en.cppreference.com/w/cpp/numeric/complex/sqrt +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_sqrt(const ComplexT& z) { + // Computes the principal sqrt of the input. + // + // For a complex square root of the number x + i*y. We want to find real + // numbers u and v such that + // (u + i*v)^2 = x + i*y <=> + // u^2 - v^2 + i*2*u*v = x + i*v. + // By equating the real and imaginary parts we get: + // u^2 - v^2 = x + // 2*u*v = y. + // + // For x >= 0, this has the numerically stable solution + // u = sqrt(0.5 * (x + sqrt(x^2 + y^2))) + // v = y / (2 * u) + // and for x < 0, + // v = sign(y) * sqrt(0.5 * (-x + sqrt(x^2 + y^2))) + // u = y / (2 * v) + // + // Letting w = sqrt(0.5 * (|x| + |z|)), + // if x == 0: u = w, v = sign(y) * w + // if x > 0: u = w, v = y / (2 * w) + // if x < 0: u = |y| / (2 * w), v = sign(y) * w + using T = typename NumTraits::Real; + const T x = numext::real(z); + const T y = numext::imag(z); + const T zero = T(0); + const T w = numext::sqrt(T(0.5) * (numext::abs(x) + numext::hypot(x, y))); + + return (numext::isinf)(y) ? ComplexT(NumTraits::infinity(), y) + : numext::is_exactly_zero(x) ? ComplexT(w, y < zero ? -w : w) + : x > zero ? ComplexT(w, y / (2 * w)) + : ComplexT(numext::abs(y) / (2 * w), y < zero ? -w : w); +} + +// Generic complex rsqrt implementation. +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_rsqrt(const ComplexT& z) { + // Computes the principal reciprocal sqrt of the input. + // + // For a complex reciprocal square root of the number z = x + i*y. We want to + // find real numbers u and v such that + // (u + i*v)^2 = 1 / (x + i*y) <=> + // u^2 - v^2 + i*2*u*v = x/|z|^2 - i*v/|z|^2. + // By equating the real and imaginary parts we get: + // u^2 - v^2 = x/|z|^2 + // 2*u*v = y/|z|^2. + // + // For x >= 0, this has the numerically stable solution + // u = sqrt(0.5 * (x + |z|)) / |z| + // v = -y / (2 * u * |z|) + // and for x < 0, + // v = -sign(y) * sqrt(0.5 * (-x + |z|)) / |z| + // u = -y / (2 * v * |z|) + // + // Letting w = sqrt(0.5 * (|x| + |z|)), + // if x == 0: u = w / |z|, v = -sign(y) * w / |z| + // if x > 0: u = w / |z|, v = -y / (2 * w * |z|) + // if x < 0: u = |y| / (2 * w * |z|), v = -sign(y) * w / |z| + using T = typename NumTraits::Real; + const T x = numext::real(z); + const T y = numext::imag(z); + const T zero = T(0); + + const T abs_z = numext::hypot(x, y); + const T w = numext::sqrt(T(0.5) * (numext::abs(x) + abs_z)); + const T woz = w / abs_z; + // Corner cases consistent with 1/sqrt(z) on gcc/clang. + return numext::is_exactly_zero(abs_z) ? ComplexT(NumTraits::infinity(), NumTraits::quiet_NaN()) + : ((numext::isinf)(x) || (numext::isinf)(y)) ? ComplexT(zero, zero) + : numext::is_exactly_zero(x) ? ComplexT(woz, y < zero ? woz : -woz) + : x > zero ? ComplexT(woz, -y / (2 * w * abs_z)) + : ComplexT(numext::abs(y) / (2 * w * abs_z), y < zero ? woz : -woz); +} + +template +EIGEN_DEVICE_FUNC constexpr ComplexT complex_log(const ComplexT& z) { + // Computes complex log. + using T = typename NumTraits::Real; + T a = numext::abs(z); + EIGEN_USING_STD(atan2); + T b = atan2(z.imag(), z.real()); + return ComplexT(numext::log(a), b); +} + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_MATHFUNCTIONSIMPL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Matrix.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Matrix.h new file mode 100644 index 0000000..ca8f622 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Matrix.h @@ -0,0 +1,536 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// Copyright (C) 2008-2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MATRIX_H +#define EIGEN_MATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits> { + private: + constexpr static int size = internal::size_at_compile_time(Rows_, Cols_); + typedef typename find_best_packet::type PacketScalar; + enum { + row_major_bit = Options_ & RowMajor ? RowMajorBit : 0, + is_dynamic_size_storage = MaxRows_ == Dynamic || MaxCols_ == Dynamic, + max_size = is_dynamic_size_storage ? Dynamic : MaxRows_ * MaxCols_, + default_alignment = compute_default_alignment::value, + actual_alignment = ((Options_ & DontAlign) == 0) ? default_alignment : 0, + required_alignment = unpacket_traits::alignment, + packet_access_bit = (packet_traits::Vectorizable && + (EIGEN_UNALIGNED_VECTORIZE || (int(actual_alignment) >= int(required_alignment)))) + ? PacketAccessBit + : 0 + }; + + public: + typedef Scalar_ Scalar; + typedef Dense StorageKind; + typedef Eigen::Index StorageIndex; + typedef MatrixXpr XprKind; + enum { + RowsAtCompileTime = Rows_, + ColsAtCompileTime = Cols_, + MaxRowsAtCompileTime = MaxRows_, + MaxColsAtCompileTime = MaxCols_, + Flags = compute_matrix_flags(Options_), + Options = Options_, + InnerStrideAtCompileTime = 1, + OuterStrideAtCompileTime = (int(Options) & int(RowMajor)) ? ColsAtCompileTime : RowsAtCompileTime, + + // FIXME, the following flag in only used to define NeedsToAlign in PlainObjectBase + EvaluatorFlags = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit, + Alignment = actual_alignment + }; +}; +} // namespace internal + +/** \class Matrix + * \ingroup Core_Module + * + * \brief The matrix class, also used for vectors and row-vectors + * + * The %Matrix class is the work-horse for all \em dense (\ref dense "note") matrices and vectors within Eigen. + * Vectors are matrices with one column, and row-vectors are matrices with one row. + * + * The %Matrix class encompasses \em both fixed-size and dynamic-size objects (\ref fixedsize "note"). + * + * The first three template parameters are required: + * \tparam Scalar_ Numeric type, e.g. float, double, int or std::complex. + * User defined scalar types are supported as well (see \ref user_defined_scalars "here"). + * \tparam Rows_ Number of rows, or \b Dynamic + * \tparam Cols_ Number of columns, or \b Dynamic + * + * The remaining template parameters are optional -- in most cases you don't have to worry about them. + * \tparam Options_ A combination of either \b #RowMajor or \b #ColMajor, and of either + * \b #AutoAlign or \b #DontAlign. + * The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter + * controls alignment, which is required for vectorization. It defaults to aligning matrices except for fixed sizes that + * aren't a multiple of the packet size. \tparam MaxRows_ Maximum number of rows. Defaults to \a Rows_ (\ref maxrows + * "note"). \tparam MaxCols_ Maximum number of columns. Defaults to \a Cols_ (\ref maxrows "note"). + * + * Eigen provides a number of typedefs covering the usual cases. Here are some examples: + * + * \li \c Matrix2d is a 2x2 square matrix of doubles (\c Matrix) + * \li \c Vector4f is a vector of 4 floats (\c Matrix) + * \li \c RowVector3i is a row-vector of 3 ints (\c Matrix) + * + * \li \c MatrixXf is a dynamic-size matrix of floats (\c Matrix) + * \li \c VectorXf is a dynamic-size vector of floats (\c Matrix) + * + * \li \c Matrix2Xf is a partially fixed-size (dynamic-size) matrix of floats (\c Matrix) + * \li \c MatrixX3d is a partially dynamic-size (fixed-size) matrix of double (\c Matrix) + * + * See \link matrixtypedefs this page \endlink for a complete list of predefined \em %Matrix and \em Vector typedefs. + * + * You can access elements of vectors and matrices using normal subscripting: + * + * \code + * Eigen::VectorXd v(10); + * v[0] = 0.1; + * v[1] = 0.2; + * v(0) = 0.3; + * v(1) = 0.4; + * + * Eigen::MatrixXi m(10, 10); + * m(0, 1) = 1; + * m(0, 2) = 2; + * m(0, 3) = 3; + * \endcode + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_MATRIX_PLUGIN. + * + * Some notes: + * + *
+ *
\anchor dense Dense versus sparse:
+ *
This %Matrix class handles dense, not sparse matrices and vectors. For sparse matrices and vectors, see the + * Sparse module. + * + * Dense matrices and vectors are plain usual arrays of coefficients. All the coefficients are stored, in an ordinary + * contiguous array. This is unlike Sparse matrices and vectors where the coefficients are stored as a list of nonzero + * coefficients.
+ * + *
\anchor fixedsize Fixed-size versus dynamic-size:
+ *
Fixed-size means that the numbers of rows and columns are known at compile-time. In this case, Eigen allocates + * the array of coefficients as a fixed-size array, as a class member. This makes sense for very small matrices, + * typically up to 4x4, sometimes up to 16x16. Larger matrices should be declared as dynamic-size even if one happens to + * know their size at compile-time. + * + * Dynamic-size means that the numbers of rows or columns are not necessarily known at compile-time. In this case they + * are runtime variables, and the array of coefficients is allocated dynamically on the heap. + * + * Note that \em dense matrices, be they Fixed-size or Dynamic-size, do not expand dynamically in the sense of + * a std::map. If you want this behavior, see the Sparse module.
+ * + *
\anchor maxrows MaxRows_ and MaxCols_:
+ *
In most cases, one just leaves these parameters to the default values. + * These parameters mean the maximum size of rows and columns that the matrix may have. They are useful in cases + * when the exact numbers of rows and columns are not known at compile-time, but it is known at compile-time that they + * cannot exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case + * MaxRows_ and MaxCols_ are the dimensions of the original matrix, while Rows_ and Cols_ are Dynamic.
+ *
+ * + * ABI and storage layout + * + * The table below summarizes the ABI of some possible Matrix instances which is fixed thorough the lifetime of Eigen 3. + * + * + * + * + * + * + *
Matrix typeEquivalent C structure
\code Matrix \endcode\code + * struct { + * T *data; // with (size_t(data)%EIGEN_MAX_ALIGN_BYTES)==0 + * Eigen::Index rows, cols; + * }; + * \endcode
\code + * Matrix + * Matrix \endcode\code + * struct { + * T *data; // with (size_t(data)%EIGEN_MAX_ALIGN_BYTES)==0 + * Eigen::Index size; + * }; + * \endcode
\code Matrix \endcode\code + * struct { + * T data[Rows*Cols]; // with (size_t(data)%A(Rows*Cols*sizeof(T)))==0 + * }; + * \endcode
\code Matrix \endcode\code + * struct { + * T data[MaxRows*MaxCols]; // with (size_t(data)%A(MaxRows*MaxCols*sizeof(T)))==0 + * Eigen::Index rows, cols; + * }; + * \endcode
+ * Note that in this table Rows, Cols, MaxRows and MaxCols are all positive integers. A(S) is defined to the largest + * possible power-of-two smaller to EIGEN_MAX_STATIC_ALIGN_BYTES. + * + * \see MatrixBase for the majority of the API methods for matrices, \ref TopicClassHierarchy, + * \ref TopicStorageOrders + */ + +template +class Matrix : public PlainObjectBase> { + public: + /** \brief Base class typedef. + * \sa PlainObjectBase + */ + typedef PlainObjectBase Base; + + enum { Options = Options_ }; + + EIGEN_DENSE_PUBLIC_INTERFACE(Matrix) + + typedef typename Base::PlainObject PlainObject; + + using Base::base; + using Base::coeffRef; + + /** + * \brief Assigns matrices to each other. + * + * \note This is a special case of the templated operator=. Its purpose is + * to prevent a default operator= from hiding the templated operator=. + * + * \callgraph + */ + EIGEN_DEVICE_FUNC constexpr Matrix& operator=(const Matrix& other) { return Base::_set(other); } + + /** \internal + * \brief Copies the value of the expression \a other into \c *this with automatic resizing. + * + * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), + * it will be initialized. + * + * Note that copying a row-vector into a vector (and conversely) is allowed. + * The resizing, if any, is then done in the appropriate way so that row-vectors + * remain row-vectors and vectors remain vectors. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix& operator=(const DenseBase& other) { + return Base::_set(other); + } + + /** + * \brief Copies the generic expression \a other into *this. + * \copydetails DenseBase::operator=(const EigenBase &other) + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix& operator=(const EigenBase& other) { + return Base::operator=(other); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix& operator=(const ReturnByValue& func) { + return Base::operator=(func); + } + + /** \brief Default constructor. + * + * For fixed-size matrices, does nothing. + * + * For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix + * is called a null matrix. This constructor is the unique way to create null matrices: resizing + * a matrix to 0 is not supported. + * + * \sa resize(Index,Index) + */ +#if defined(EIGEN_INITIALIZE_COEFFS) + EIGEN_DEVICE_FUNC constexpr Matrix() { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED } +#else + EIGEN_DEVICE_FUNC constexpr Matrix() = default; +#endif + /** \brief Move constructor */ + EIGEN_DEVICE_FUNC constexpr Matrix(Matrix&&) = default; + /** \brief Moves the matrix into the other one. + * + */ + EIGEN_DEVICE_FUNC constexpr Matrix& operator=(Matrix&& other) noexcept( + std::is_nothrow_move_assignable::value) { + Base::operator=(std::move(other)); + return *this; + } + + /** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients. + * + * \only_for_vectors + * + * This constructor is for 1D array or vectors with more than 4 coefficients. + * + * \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this + * constructor must match the fixed number of rows (resp. columns) of \c *this. + * + * + * Example: \include Matrix_variadic_ctor_cxx11.cpp + * Output: \verbinclude Matrix_variadic_ctor_cxx11.out + * + * \sa Matrix(const std::initializer_list>&) + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, + const ArgTypes&... args) + : Base(a0, a1, a2, a3, args...) {} + + /** \brief Constructs a Matrix and initializes it from the coefficients given as initializer-lists grouped by row. + * \cpp11 + * \anchor matrix_initializer_list + * + * In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients: + * + * Example: \include Matrix_initializer_list_23_cxx11.cpp + * Output: \verbinclude Matrix_initializer_list_23_cxx11.out + * + * Each of the inner initializer lists must contain the exact same number of elements, otherwise an assertion is + * triggered. + * + * In the case of a compile-time column vector, implicit transposition from a single row is allowed. + * Therefore VectorXd{{1,2,3,4,5}} is legal and the more verbose syntax + * RowVectorXd{{1},{2},{3},{4},{5}} can be avoided: + * + * Example: \include Matrix_initializer_list_vector_cxx11.cpp + * Output: \verbinclude Matrix_initializer_list_vector_cxx11.out + * + * In the case of fixed-sized matrices, the initializer list sizes must exactly match the matrix sizes, + * and implicit transposition is allowed for compile-time vectors only. + * + * \sa Matrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) + */ + EIGEN_DEVICE_FUNC explicit constexpr EIGEN_STRONG_INLINE Matrix( + const std::initializer_list>& list) + : Base(list) {} + +#ifndef EIGEN_PARSED_BY_DOXYGEN + + // This constructor is for both 1x1 matrices and dynamic vectors + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE explicit Matrix(const T& x) { + Base::template _init1(x); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Matrix(const T0& x, const T1& y) { + Base::template _init2(x, y); + } + +#else + /** \brief Constructs a fixed-sized matrix initialized with coefficients starting at \a data */ + EIGEN_DEVICE_FUNC explicit Matrix(const Scalar* data); + + /** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors + * + * This is useful for dynamic-size vectors. For fixed-size vectors, + * it is redundant to pass these parameters, so one should use the default constructor + * Matrix() instead. + * + * \warning This constructor is disabled for fixed-size \c 1x1 matrices. For instance, + * calling Matrix(1) will call the initialization constructor: Matrix(const Scalar&). + * For fixed-size \c 1x1 matrices it is therefore recommended to use the default + * constructor Matrix() instead, especially when using one of the non standard + * \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives). + */ + EIGEN_STRONG_INLINE explicit Matrix(Index dim); + /** \brief Constructs an initialized 1x1 matrix with the given coefficient + * \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) */ + Matrix(const Scalar& x); + /** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns. + * + * This is useful for dynamic-size matrices. For fixed-size matrices, + * it is redundant to pass these parameters, so one should use the default constructor + * Matrix() instead. + * + * \warning This constructor is disabled for fixed-size \c 1x2 and \c 2x1 vectors. For instance, + * calling Matrix2f(2,1) will call the initialization constructor: Matrix(const Scalar& x, const Scalar& y). + * For fixed-size \c 1x2 or \c 2x1 vectors it is therefore recommended to use the default + * constructor Matrix() instead, especially when using one of the non standard + * \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives). + */ + EIGEN_DEVICE_FUNC Matrix(Index rows, Index cols); + + /** \brief Constructs an initialized 2D vector with given coefficients + * \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) */ + Matrix(const Scalar& x, const Scalar& y); +#endif // end EIGEN_PARSED_BY_DOXYGEN + + /** \brief Constructs an initialized 3D vector with given coefficients + * \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3) + m_storage.data()[0] = x; + m_storage.data()[1] = y; + m_storage.data()[2] = z; + } + /** \brief Constructs an initialized 4D vector with given coefficients + * \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, + const Scalar& w) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4) + m_storage.data()[0] = x; + m_storage.data()[1] = y; + m_storage.data()[2] = z; + m_storage.data()[3] = w; + } + + /** \brief Copy constructor */ + EIGEN_DEVICE_FUNC constexpr Matrix(const Matrix&) = default; + + /** \brief Copy constructor for generic expressions. + * \sa MatrixBase::operator=(const EigenBase&) + */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Matrix(const EigenBase& other) + : Base(other.derived()) {} + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return 1; } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return this->innerSize(); } + + /////////// Geometry module /////////// + + template + EIGEN_DEVICE_FUNC explicit Matrix(const RotationBase& r); + template + EIGEN_DEVICE_FUNC Matrix& operator=(const RotationBase& r); + +// allow to extend Matrix outside Eigen +#ifdef EIGEN_MATRIX_PLUGIN +#include EIGEN_MATRIX_PLUGIN +#endif + + protected: + template + friend struct internal::conservative_resize_like_impl; + + using Base::m_storage; +}; + +/** \defgroup matrixtypedefs Global matrix typedefs + * + * \ingroup Core_Module + * + * %Eigen defines several typedef shortcuts for most common matrix and vector types. + * + * The general patterns are the following: + * + * \c MatrixSizeType where \c Size can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size, + * and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd + * for complex double. + * + * For example, \c Matrix3d is a fixed-size 3x3 matrix type of doubles, and \c MatrixXf is a dynamic-size matrix of + * floats. + * + * There are also \c VectorSizeType and \c RowVectorSizeType which are self-explanatory. For example, \c Vector4cf is + * a fixed-size vector of 4 complex floats. + * + * With \cpp11, template alias are also defined for common sizes. + * They follow the same pattern as above except that the scalar type suffix is replaced by a + * template parameter, i.e.: + * - `MatrixSize` where `Size` can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size. + * - `MatrixXSize` and `MatrixSizeX` where `Size` can be \c 2,\c 3,\c 4 for hybrid dynamic/fixed matrices. + * - `VectorSize` and `RowVectorSize` for column and row vectors. + * + * With \cpp11, you can also use fully generic column and row vector types: `Vector` and + * `RowVector`. + * + * \sa class Matrix + */ + +#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ + /** \ingroup matrixtypedefs */ \ + /** \brief `Size`×`Size` matrix of type `Type`. */ \ + typedef Matrix Matrix##SizeSuffix##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief `Size`×`1` vector of type `Type`. */ \ + typedef Matrix Vector##SizeSuffix##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief `1`×`Size` vector of type `Type`. */ \ + typedef Matrix RowVector##SizeSuffix##TypeSuffix; + +#define EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \ + /** \ingroup matrixtypedefs */ \ + /** \brief `Size`×`Dynamic` matrix of type `Type`. */ \ + typedef Matrix Matrix##Size##X##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief `Dynamic`×`Size` matrix of type `Type`. */ \ + typedef Matrix Matrix##X##Size##TypeSuffix; + +#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 4) + +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex, cf) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex, cd) + +#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES +#undef EIGEN_MAKE_TYPEDEFS +#undef EIGEN_MAKE_FIXED_TYPEDEFS + +#define EIGEN_MAKE_TYPEDEFS(Size, SizeSuffix) \ + /** \ingroup matrixtypedefs */ \ + /** \brief \cpp11 `Size`×`Size` matrix of type `Type`.*/ \ + template \ + using Matrix##SizeSuffix = Matrix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief \cpp11 `Size`×`1` vector of type `Type`.*/ \ + template \ + using Vector##SizeSuffix = Matrix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief \cpp11 `1`×`Size` vector of type `Type`.*/ \ + template \ + using RowVector##SizeSuffix = Matrix; + +#define EIGEN_MAKE_FIXED_TYPEDEFS(Size) \ + /** \ingroup matrixtypedefs */ \ + /** \brief \cpp11 `Size`×`Dynamic` matrix of type `Type` */ \ + template \ + using Matrix##Size##X = Matrix; \ + /** \ingroup matrixtypedefs */ \ + /** \brief \cpp11 `Dynamic`×`Size` matrix of type `Type`. */ \ + template \ + using Matrix##X##Size = Matrix; + +EIGEN_MAKE_TYPEDEFS(2, 2) +EIGEN_MAKE_TYPEDEFS(3, 3) +EIGEN_MAKE_TYPEDEFS(4, 4) +EIGEN_MAKE_TYPEDEFS(Dynamic, X) +EIGEN_MAKE_FIXED_TYPEDEFS(2) +EIGEN_MAKE_FIXED_TYPEDEFS(3) +EIGEN_MAKE_FIXED_TYPEDEFS(4) + +/** \ingroup matrixtypedefs + * \brief \cpp11 `Size`×`1` vector of type `Type`. */ +template +using Vector = Matrix; + +/** \ingroup matrixtypedefs + * \brief \cpp11 `1`×`Size` vector of type `Type`. */ +template +using RowVector = Matrix; + +#undef EIGEN_MAKE_TYPEDEFS +#undef EIGEN_MAKE_FIXED_TYPEDEFS + +} // end namespace Eigen + +#endif // EIGEN_MATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MatrixBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MatrixBase.h new file mode 100644 index 0000000..ff1a2c2 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/MatrixBase.h @@ -0,0 +1,557 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2009 Benoit Jacob +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MATRIXBASE_H +#define EIGEN_MATRIXBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class MatrixBase + * \ingroup Core_Module + * + * \brief Base class for all dense matrices, vectors, and expressions + * + * This class is the base that is inherited by all matrix, vector, and related expression + * types. Most of the Eigen API is contained in this class, and its base classes. Other important + * classes for the Eigen API are Matrix, and VectorwiseOp. + * + * Note that some methods are defined in other modules such as the \ref LU_Module LU module + * for all functions related to matrix inversions. + * + * \tparam Derived is the derived type, e.g. a matrix type, or an expression, etc. + * + * When writing a function taking Eigen objects as argument, if you want your function + * to take as argument any matrix, vector, or expression, just let it take a + * MatrixBase argument. As an example, here is a function printFirstRow which, given + * a matrix, vector, or expression \a x, prints the first row of \a x. + * + * \code + template + void printFirstRow(const Eigen::MatrixBase& x) + { + cout << x.row(0) << endl; + } + * \endcode + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_MATRIXBASE_PLUGIN. + * + * \sa \blank \ref TopicClassHierarchy + */ +template +class MatrixBase : public DenseBase { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef MatrixBase StorageBaseType; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::packet_traits::type PacketScalar; + typedef typename NumTraits::Real RealScalar; + + typedef DenseBase Base; + using Base::ColsAtCompileTime; + using Base::Flags; + using Base::IsVectorAtCompileTime; + using Base::MaxColsAtCompileTime; + using Base::MaxRowsAtCompileTime; + using Base::MaxSizeAtCompileTime; + using Base::RowsAtCompileTime; + using Base::SizeAtCompileTime; + + using Base::coeff; + using Base::coeffRef; + using Base::cols; + using Base::const_cast_derived; + using Base::derived; + using Base::eval; + using Base::lazyAssign; + using Base::rows; + using Base::size; + using Base::operator-; + using Base::operator+=; + using Base::operator-=; + using Base::operator*=; + using Base::operator/=; + + typedef typename Base::CoeffReturnType CoeffReturnType; + typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType; + typedef typename Base::RowXpr RowXpr; + typedef typename Base::ColXpr ColXpr; +#endif // not EIGEN_PARSED_BY_DOXYGEN + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** type of the equivalent square matrix */ + typedef Matrix + SquareMatrixType; +#endif // not EIGEN_PARSED_BY_DOXYGEN + + /** \returns the size of the main diagonal, which is min(rows(),cols()). + * \sa rows(), cols(), SizeAtCompileTime. */ + EIGEN_DEVICE_FUNC constexpr Index diagonalSize() const { return (numext::mini)(rows(), cols()); } + + typedef typename Base::PlainObject PlainObject; + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal Represents a matrix with all coefficients equal to one another*/ + typedef CwiseNullaryOp, PlainObject> ConstantReturnType; + /** \internal the return type of MatrixBase::adjoint() */ + typedef std::conditional_t::IsComplex, + CwiseUnaryOp, ConstTransposeReturnType>, + ConstTransposeReturnType> + AdjointReturnType; + /** \internal Return type of eigenvalues() */ + typedef Matrix, internal::traits::ColsAtCompileTime, 1, ColMajor> + EigenvaluesReturnType; + /** \internal the return type of identity */ + typedef CwiseNullaryOp, PlainObject> IdentityReturnType; + /** \internal the return type of unit vectors */ + typedef Block, SquareMatrixType>, + internal::traits::RowsAtCompileTime, internal::traits::ColsAtCompileTime> + BasisReturnType; +#endif // not EIGEN_PARSED_BY_DOXYGEN + +#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase +#define EIGEN_DOC_UNARY_ADDONS(X, Y) +#include "../plugins/CommonCwiseBinaryOps.inc" +#include "../plugins/MatrixCwiseUnaryOps.inc" +#include "../plugins/MatrixCwiseBinaryOps.inc" +#ifdef EIGEN_MATRIXBASE_PLUGIN +#include EIGEN_MATRIXBASE_PLUGIN +#endif +#undef EIGEN_CURRENT_STORAGE_BASE_CLASS +#undef EIGEN_DOC_UNARY_ADDONS + + /** Special case of the template operator=, in order to prevent the compiler + * from generating a default operator= (issue hit with g++ 4.1) + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator=(const MatrixBase& other); + + // We cannot inherit here via Base::operator= since it is causing + // trouble with MSVC. + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& operator=(const DenseBase& other); + + template + EIGEN_DEVICE_FUNC constexpr Derived& operator=(const EigenBase& other); + + template + EIGEN_DEVICE_FUNC constexpr Derived& operator=(const ReturnByValue& other); + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator+=(const MatrixBase& other); + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const MatrixBase& other); + + template + EIGEN_DEVICE_FUNC const Product operator*(const MatrixBase& other) const; + + template + EIGEN_DEVICE_FUNC const Product lazyProduct( + const MatrixBase& other) const; + + template + Derived& operator*=(const EigenBase& other); + + template + void applyOnTheLeft(const EigenBase& other); + + template + void applyOnTheRight(const EigenBase& other); + + template + EIGEN_DEVICE_FUNC const Product operator*( + const DiagonalBase& diagonal) const; + + template + EIGEN_DEVICE_FUNC const Product operator*( + const SkewSymmetricBase& skew) const; + + template + EIGEN_DEVICE_FUNC constexpr typename ScalarBinaryOpTraits::Scalar, + typename internal::traits::Scalar>::ReturnType + dot(const MatrixBase& other) const; + + EIGEN_DEVICE_FUNC constexpr RealScalar squaredNorm() const; + EIGEN_DEVICE_FUNC RealScalar norm() const; + RealScalar stableNorm() const; + RealScalar blueNorm() const; + RealScalar hypotNorm() const; + EIGEN_DEVICE_FUNC const PlainObject normalized() const; + EIGEN_DEVICE_FUNC const PlainObject stableNormalized() const; + EIGEN_DEVICE_FUNC void normalize(); + EIGEN_DEVICE_FUNC void stableNormalize(); + + EIGEN_DEVICE_FUNC constexpr const AdjointReturnType adjoint() const; + EIGEN_DEVICE_FUNC void adjointInPlace(); + + typedef Diagonal DiagonalReturnType; + EIGEN_DEVICE_FUNC constexpr DiagonalReturnType diagonal(); + + typedef Diagonal ConstDiagonalReturnType; + EIGEN_DEVICE_FUNC constexpr const ConstDiagonalReturnType diagonal() const; + + template + EIGEN_DEVICE_FUNC constexpr Diagonal diagonal(); + + template + EIGEN_DEVICE_FUNC constexpr const Diagonal diagonal() const; + + EIGEN_DEVICE_FUNC constexpr Diagonal diagonal(Index index); + EIGEN_DEVICE_FUNC constexpr const Diagonal diagonal(Index index) const; + + template + struct TriangularViewReturnType { + typedef TriangularView Type; + }; + template + struct ConstTriangularViewReturnType { + typedef const TriangularView Type; + }; + + template + EIGEN_DEVICE_FUNC constexpr typename TriangularViewReturnType::Type triangularView(); + template + EIGEN_DEVICE_FUNC constexpr typename ConstTriangularViewReturnType::Type triangularView() const; + + template + struct SelfAdjointViewReturnType { + typedef SelfAdjointView Type; + }; + template + struct ConstSelfAdjointViewReturnType { + typedef const SelfAdjointView Type; + }; + + template + EIGEN_DEVICE_FUNC constexpr typename SelfAdjointViewReturnType::Type selfadjointView(); + template + EIGEN_DEVICE_FUNC constexpr typename ConstSelfAdjointViewReturnType::Type selfadjointView() const; + + const SparseView sparseView( + const Scalar& m_reference = Scalar(0), + const typename NumTraits::Real& m_epsilon = NumTraits::dummy_precision()) const; + EIGEN_DEVICE_FUNC static const IdentityReturnType Identity(); + EIGEN_DEVICE_FUNC static const IdentityReturnType Identity(Index rows, Index cols); + EIGEN_DEVICE_FUNC static const BasisReturnType Unit(Index size, Index i); + EIGEN_DEVICE_FUNC static const BasisReturnType Unit(Index i); + EIGEN_DEVICE_FUNC static const BasisReturnType UnitX(); + EIGEN_DEVICE_FUNC static const BasisReturnType UnitY(); + EIGEN_DEVICE_FUNC static const BasisReturnType UnitZ(); + EIGEN_DEVICE_FUNC static const BasisReturnType UnitW(); + + EIGEN_DEVICE_FUNC constexpr const DiagonalWrapper asDiagonal() const; + const PermutationWrapper asPermutation() const; + EIGEN_DEVICE_FUNC constexpr const SkewSymmetricWrapper asSkewSymmetric() const; + + EIGEN_DEVICE_FUNC Derived& setIdentity(); + EIGEN_DEVICE_FUNC Derived& setIdentity(Index rows, Index cols); + EIGEN_DEVICE_FUNC Derived& setUnit(Index i); + EIGEN_DEVICE_FUNC Derived& setUnit(Index newSize, Index i); + + bool isIdentity(const RealScalar& prec = NumTraits::dummy_precision()) const; + bool isDiagonal(const RealScalar& prec = NumTraits::dummy_precision()) const; + + bool isUpperTriangular(const RealScalar& prec = NumTraits::dummy_precision()) const; + bool isLowerTriangular(const RealScalar& prec = NumTraits::dummy_precision()) const; + + bool isSkewSymmetric(const RealScalar& prec = NumTraits::dummy_precision()) const; + + template + bool isOrthogonal(const MatrixBase& other, + const RealScalar& prec = NumTraits::dummy_precision()) const; + bool isUnitary(const RealScalar& prec = NumTraits::dummy_precision()) const; + + /* diagonalView */ + template + EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> diagonalView(); + + template + EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> diagonalView() const; + + EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> diagonalView(Index index); + + EIGEN_DEVICE_FUNC constexpr DiagonalWrapper> diagonalView(Index index) const; + + /** \returns true if each coefficients of \c *this and \a other are all exactly equal. + * \warning When using floating point scalar values you probably should rather use a + * fuzzy comparison such as isApprox() + * \sa isApprox(), operator!= */ + template + EIGEN_DEVICE_FUNC inline bool operator==(const MatrixBase& other) const { + return (this->rows() == other.rows()) && (this->cols() == other.cols()) && cwiseEqual(other).all(); + } + + /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other. + * \warning When using floating point scalar values you probably should rather use a + * fuzzy comparison such as isApprox() + * \sa isApprox(), operator== */ + template + EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase& other) const { + return !(*this == other); + } + + NoAlias EIGEN_DEVICE_FUNC noalias(); + + // TODO forceAlignedAccess is temporarily disabled + // Need to find a nicer workaround. + constexpr const Derived& forceAlignedAccess() const { return derived(); } + constexpr Derived& forceAlignedAccess() { return derived(); } + template + constexpr const Derived& forceAlignedAccessIf() const { + return derived(); + } + template + constexpr Derived& forceAlignedAccessIf() { + return derived(); + } + + EIGEN_DEVICE_FUNC Scalar trace() const; + + template + EIGEN_DEVICE_FUNC RealScalar lpNorm() const; + + EIGEN_DEVICE_FUNC constexpr MatrixBase& matrix() { return *this; } + EIGEN_DEVICE_FUNC constexpr const MatrixBase& matrix() const { return *this; } + + /** \returns an \link Eigen::ArrayBase Array \endlink expression of this matrix + * \sa ArrayBase::matrix() */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE ArrayWrapper array() { + return ArrayWrapper(derived()); + } + /** \returns a const \link Eigen::ArrayBase Array \endlink expression of this matrix + * \sa ArrayBase::matrix() */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const ArrayWrapper array() const { + return ArrayWrapper(derived()); + } + + /////////// LU module /////////// + + template + inline FullPivLU fullPivLu() const; + template + inline PartialPivLU partialPivLu() const; + + template + inline PartialPivLU lu() const; + + EIGEN_DEVICE_FUNC inline Inverse inverse() const; + + template + inline void computeInverseAndDetWithCheck( + ResultType& inverse, typename ResultType::Scalar& determinant, bool& invertible, + const RealScalar& absDeterminantThreshold = NumTraits::dummy_precision()) const; + + template + inline void computeInverseWithCheck( + ResultType& inverse, bool& invertible, + const RealScalar& absDeterminantThreshold = NumTraits::dummy_precision()) const; + + EIGEN_DEVICE_FUNC Scalar determinant() const; + + /////////// Cholesky module /////////// + + inline LLT llt() const; + inline LDLT ldlt() const; + + /////////// QR module /////////// + + inline HouseholderQR householderQr() const; + template + inline ColPivHouseholderQR colPivHouseholderQr() const; + template + inline FullPivHouseholderQR fullPivHouseholderQr() const; + template + inline CompleteOrthogonalDecomposition completeOrthogonalDecomposition() const; + + /////////// Eigenvalues module /////////// + + inline EigenvaluesReturnType eigenvalues() const; + inline RealScalar operatorNorm() const; + + /////////// SVD module /////////// + + template + inline JacobiSVD jacobiSvd() const; + template + EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.") + inline JacobiSVD jacobiSvd(unsigned int computationOptions) const; + + template + inline BDCSVD bdcSvd() const; + template + EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.") + inline BDCSVD bdcSvd(unsigned int computationOptions) const; + + /////////// Geometry module /////////// + + template + EIGEN_DEVICE_FUNC inline typename internal::cross_impl::return_type cross( + const MatrixBase& other) const; + + template + EIGEN_DEVICE_FUNC inline PlainObject cross3(const MatrixBase& other) const; + + EIGEN_DEVICE_FUNC inline PlainObject unitOrthogonal(void) const; + + EIGEN_DEPRECATED_WITH_REASON("Use .canonicalEulerAngles() instead.") + EIGEN_DEVICE_FUNC inline Matrix eulerAngles(Index a0, Index a1, Index a2) const; + + EIGEN_DEVICE_FUNC inline Matrix canonicalEulerAngles(Index a0, Index a1, Index a2) const; + + enum { + HomogeneousReturnTypeDirection = + ColsAtCompileTime == 1 && RowsAtCompileTime == 1 + ? ((internal::traits::Flags & RowMajorBit) == RowMajorBit ? Horizontal : Vertical) + : ColsAtCompileTime == 1 ? Vertical + : Horizontal + }; + typedef Homogeneous HomogeneousReturnType; + EIGEN_DEVICE_FUNC inline HomogeneousReturnType homogeneous() const; + + enum { SizeMinusOne = SizeAtCompileTime == Dynamic ? Dynamic : SizeAtCompileTime - 1 }; + typedef Block::ColsAtCompileTime == 1 ? SizeMinusOne : 1, + internal::traits::ColsAtCompileTime == 1 ? 1 : SizeMinusOne> + ConstStartMinusOne; + typedef EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(ConstStartMinusOne, Scalar, quotient) HNormalizedReturnType; + EIGEN_DEVICE_FUNC inline const HNormalizedReturnType hnormalized() const; + + ////////// Householder module /////////// + + EIGEN_DEVICE_FUNC void makeHouseholderInPlace(Scalar& tau, RealScalar& beta); + template + EIGEN_DEVICE_FUNC void makeHouseholder(EssentialPart& essential, Scalar& tau, RealScalar& beta) const; + template + EIGEN_DEVICE_FUNC void applyHouseholderOnTheLeft(const EssentialPart& essential, const Scalar& tau, + Scalar* workspace); + template + EIGEN_DEVICE_FUNC void applyHouseholderOnTheRight(const EssentialPart& essential, const Scalar& tau, + Scalar* workspace); + + ///////// Jacobi module ///////// + + template + EIGEN_DEVICE_FUNC void applyOnTheLeft(Index p, Index q, const JacobiRotation& j); + template + EIGEN_DEVICE_FUNC void applyOnTheRight(Index p, Index q, const JacobiRotation& j); + + ///////// SparseCore module ///////// + + template + EIGEN_STRONG_INLINE const typename SparseMatrixBase::template CwiseProductDenseReturnType::Type + cwiseProduct(const SparseMatrixBase& other) const { + return other.cwiseProduct(derived()); + } + + ///////// MatrixFunctions module ///////// + + typedef typename internal::stem_function::type StemFunction; +#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the \ + * coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name() const; +#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the \ + * coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name(Argument) const; + + EIGEN_MATRIX_FUNCTION(MatrixExponentialReturnValue, exp, exponential) + /** \brief Helper function for the unsupported + * MatrixFunctions module.*/ + const MatrixFunctionReturnValue matrixFunction(StemFunction f) const; + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cosh, hyperbolic cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sinh, hyperbolic sine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, atanh, inverse hyperbolic cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, acosh, inverse hyperbolic cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, asinh, inverse hyperbolic sine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cos, cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sin, sine) + EIGEN_MATRIX_FUNCTION(MatrixSquareRootReturnValue, sqrt, square root) + EIGEN_MATRIX_FUNCTION(MatrixLogarithmReturnValue, log, logarithm) + EIGEN_MATRIX_FUNCTION_1(MatrixPowerReturnValue, pow, power to \c p, const RealScalar& p) + EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const internal::make_complex_t& p) + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MatrixBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MatrixBase) + + private: + EIGEN_DEVICE_FUNC explicit MatrixBase(int); + EIGEN_DEVICE_FUNC MatrixBase(int, int); + template + EIGEN_DEVICE_FUNC explicit MatrixBase(const MatrixBase&); + + protected: + // mixing arrays and matrices is not legal + template + Derived& operator+=(const ArrayBase&) { + EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar)) == -1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); + return *this; + } + // mixing arrays and matrices is not legal + template + Derived& operator-=(const ArrayBase&) { + EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar)) == -1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); + return *this; + } +}; + +/*************************************************************************** + * Implementation of matrix base methods + ***************************************************************************/ + +/** replaces \c *this by \c *this * \a other. + * + * \returns a reference to \c *this + * + * Example: \include MatrixBase_applyOnTheRight.cpp + * Output: \verbinclude MatrixBase_applyOnTheRight.out + */ +template +template +inline Derived& MatrixBase::operator*=(const EigenBase& other) { + other.derived().applyThisOnTheRight(derived()); + return derived(); +} + +/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=(). + * + * Example: \include MatrixBase_applyOnTheRight.cpp + * Output: \verbinclude MatrixBase_applyOnTheRight.out + */ +template +template +inline void MatrixBase::applyOnTheRight(const EigenBase& other) { + other.derived().applyThisOnTheRight(derived()); +} + +/** replaces \c *this by \a other * \c *this. + * + * Example: \include MatrixBase_applyOnTheLeft.cpp + * Output: \verbinclude MatrixBase_applyOnTheLeft.out + */ +template +template +inline void MatrixBase::applyOnTheLeft(const EigenBase& other) { + other.derived().applyThisOnTheLeft(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_MATRIXBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NestByValue.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NestByValue.h new file mode 100644 index 0000000..f18559b --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NestByValue.h @@ -0,0 +1,91 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_NESTBYVALUE_H +#define EIGEN_NESTBYVALUE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : public traits { + enum { Flags = traits::Flags & ~NestByRefBit }; +}; +} // namespace internal + +/** \class NestByValue + * \ingroup Core_Module + * + * \brief Expression which must be nested by value + * + * \tparam ExpressionType the type of the object of which we are requiring nesting-by-value + * + * This class is the return type of MatrixBase::nestByValue() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::nestByValue() + */ +template +class NestByValue : public internal::dense_xpr_base >::type { + public: + typedef typename internal::dense_xpr_base::type Base; + static constexpr bool HasDirectAccess = internal::has_direct_access::ret; + + EIGEN_DENSE_PUBLIC_INTERFACE(NestByValue) + + EIGEN_DEVICE_FUNC constexpr explicit inline NestByValue(const ExpressionType& matrix) : m_expression(matrix) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_expression.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_expression.cols(); } + + EIGEN_DEVICE_FUNC constexpr operator const ExpressionType&() const { return m_expression; } + + EIGEN_DEVICE_FUNC constexpr const ExpressionType& nestedExpression() const { return m_expression; } + + EIGEN_DEVICE_FUNC constexpr std::enable_if_t data() const { + return m_expression.data(); + } + + EIGEN_DEVICE_FUNC constexpr std::enable_if_t innerStride() const { + return m_expression.innerStride(); + } + + EIGEN_DEVICE_FUNC constexpr std::enable_if_t outerStride() const { + return m_expression.outerStride(); + } + + protected: + const ExpressionType m_expression; +}; + +/** \returns an expression of the temporary version of *this. + */ +template +EIGEN_DEVICE_FUNC constexpr inline const NestByValue DenseBase::nestByValue() const { + return NestByValue(derived()); +} + +namespace internal { + +// Evaluator of Solve -> eval into a temporary +template +struct evaluator > : public evaluator { + typedef evaluator Base; + + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const NestByValue& xpr) : Base(xpr.nestedExpression()) {} +}; +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_NESTBYVALUE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NoAlias.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NoAlias.h new file mode 100644 index 0000000..6a88201 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NoAlias.h @@ -0,0 +1,102 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_NOALIAS_H +#define EIGEN_NOALIAS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class NoAlias + * \ingroup Core_Module + * + * \brief Pseudo expression providing an operator = assuming no aliasing + * + * \tparam ExpressionType the type of the object on which to do the lazy assignment + * + * This class represents an expression with special assignment operators + * assuming no aliasing between the target expression and the source expression. + * More precisely it alloas to bypass the EvalBeforeAssignBit flag of the source expression. + * It is the return type of MatrixBase::noalias() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::noalias() + */ +template class StorageBase> +class NoAlias { + public: + typedef typename ExpressionType::Scalar Scalar; + + EIGEN_DEVICE_FUNC constexpr explicit NoAlias(ExpressionType& expression) : m_expression(expression) {} + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase& other) { + call_assignment_no_alias(m_expression, other.derived(), + internal::assign_op()); + return m_expression; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase& other) { + call_assignment_no_alias(m_expression, other.derived(), + internal::add_assign_op()); + return m_expression; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase& other) { + call_assignment_no_alias(m_expression, other.derived(), + internal::sub_assign_op()); + return m_expression; + } + + EIGEN_DEVICE_FUNC constexpr ExpressionType& expression() const { return m_expression; } + + protected: + ExpressionType& m_expression; +}; + +/** \returns a pseudo expression of \c *this with an operator= assuming + * no aliasing between \c *this and the source expression. + * + * More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag. + * Currently, even though several expressions may alias, only product + * expressions have this flag. Therefore, noalias() is only useful when + * the source expression contains a matrix product. + * + * Here are some examples where noalias is useful: + * \code + * D.noalias() = A * B; + * D.noalias() += A.transpose() * B; + * D.noalias() -= 2 * A * B.adjoint(); + * \endcode + * + * On the other hand the following example will lead to a \b wrong result: + * \code + * A.noalias() = A * B; + * \endcode + * because the result matrix A is also an operand of the matrix product. Therefore, + * there is no alternative than evaluating A * B in a temporary, that is the default + * behavior when you write: + * \code + * A = A * B; + * \endcode + * + * \sa class NoAlias + */ +template +NoAlias EIGEN_DEVICE_FUNC MatrixBase::noalias() { + return NoAlias(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_NOALIAS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NumTraits.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NumTraits.h new file mode 100644 index 0000000..2bb1eed --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/NumTraits.h @@ -0,0 +1,335 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_NUMTRAITS_H +#define EIGEN_NUMTRAITS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// default implementation of digits(), based on numeric_limits if specialized, +// 0 for integer types, and log2(epsilon()) otherwise. +template ::is_specialized, + bool is_integer = NumTraits::IsInteger> +struct default_digits_impl { + EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits::digits; } +}; + +template +struct default_digits_impl // Floating point +{ + EIGEN_DEVICE_FUNC constexpr static int run() { + using std::ceil; + using std::log2; + typedef typename NumTraits::Real Real; + return int(ceil(-log2(NumTraits::epsilon()))); + } +}; + +template +struct default_digits_impl // Integer +{ + EIGEN_DEVICE_FUNC constexpr static int run() { return 0; } +}; + +// default implementation of digits10(), based on numeric_limits if specialized, +// 0 for integer types, and floor((digits()-1)*log10(2)) otherwise. +template ::is_specialized, + bool is_integer = NumTraits::IsInteger> +struct default_digits10_impl { + EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits::digits10; } +}; + +template +struct default_digits10_impl // Floating point +{ + EIGEN_DEVICE_FUNC constexpr static int run() { + using std::floor; + using std::log10; + typedef typename NumTraits::Real Real; + return int(floor((internal::default_digits_impl::run() - 1) * log10(2))); + } +}; + +template +struct default_digits10_impl // Integer +{ + EIGEN_DEVICE_FUNC constexpr static int run() { return 0; } +}; + +// default implementation of max_digits10(), based on numeric_limits if specialized, +// 0 for integer types, and log10(2) * digits() + 1 otherwise. +template ::is_specialized, + bool is_integer = NumTraits::IsInteger> +struct default_max_digits10_impl { + EIGEN_DEVICE_FUNC constexpr static int run() { return std::numeric_limits::max_digits10; } +}; + +template +struct default_max_digits10_impl // Floating point +{ + EIGEN_DEVICE_FUNC constexpr static int run() { + using std::ceil; + using std::log10; + typedef typename NumTraits::Real Real; + return int(ceil(internal::default_digits_impl::run() * log10(2) + 1)); + } +}; + +template +struct default_max_digits10_impl // Integer +{ + EIGEN_DEVICE_FUNC constexpr static int run() { return 0; } +}; + +} // end namespace internal + +namespace numext { + +/** \internal bit-wise cast without changing the underlying bit representation. */ +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +template +EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) { + return std::bit_cast(src); +} +#elif EIGEN_HAS_BUILTIN(__builtin_bit_cast) +template +EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) { + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value, THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value, THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED) + return __builtin_bit_cast(Tgt, src); +} +#else +template +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) { + // The behaviour of memcpy is not specified for non-trivially copyable types + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value, THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(std::is_trivially_copyable::value && std::is_default_constructible::value, + THIS_TYPE_IS_NOT_SUPPORTED) + EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED) + + Tgt tgt; + // Load src into registers first. This allows the memcpy to be elided by CUDA. + const Src staged = src; + EIGEN_USING_STD(memcpy) + memcpy(static_cast(&tgt), static_cast(&staged), sizeof(Tgt)); + return tgt; +} +#endif +} // namespace numext + +// clang-format off +/** \class NumTraits + * \ingroup Core_Module + * + * \brief Holds information about the various numeric (i.e. scalar) types allowed by Eigen. + * + * \tparam T the numeric type at hand + * + * This class stores enums, typedefs and static methods giving information about a numeric type. + * + * The provided data consists of: + * \li A typedef \c Real, giving the "real part" type of \a T. If \a T is already real, + * then \c Real is just a typedef to \a T. If \a T is `std::complex` then \c Real + * is a typedef to \a U. + * \li A typedef \c NonInteger, giving the type that should be used for operations producing non-integral values, + * such as quotients, square roots, etc. If \a T is a floating-point type, then this typedef just gives + * \a T again. Note however that many Eigen functions such as internal::sqrt simply refuse to + * take integers. Outside of a few cases, Eigen doesn't do automatic type promotion. Thus, this typedef is + * only intended as a helper for code that needs to explicitly promote types. + * \li A typedef \c Literal giving the type to use for numeric literals such as "2" or "0.5". For instance, for + * `std::complex`, Literal is defined as \a U. Of course, this type must be fully compatible with \a T. In doubt, + * just use \a T here. + * \li A typedef \c Nested giving the type to use to nest a value inside of the expression tree. If you don't know what + * this means, just use \a T here. + * \li An enum value \c IsComplex. It is equal to 1 if \a T is a \c std::complex type, and to 0 otherwise. + * \li An enum value \c IsInteger. It is equal to \c 1 if \a T is an integer type such as \c int, and to \c 0 otherwise. + * \li Enum values \c ReadCost, \c AddCost and \c MulCost representing a rough estimate of the number of CPU cycles needed to by + * move / add / mul instructions respectively, assuming the data is already stored in CPU registers. Stay vague here. + * No need to do architecture-specific stuff. If you don't know what this means, just use \c Eigen::HugeCost. + * \li An enum value \c IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned. + * \li An enum value \c RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must be + * called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise. + * \li An epsilon() function which, unlike + * `std::numeric_limits::epsilon()`, it returns a \c Real instead of a \a T. + * \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default value by the fuzzy + * comparison operators. + * \li highest() and lowest() functions returning the highest and lowest possible values respectively. + * \li digits() function returning the number of radix digits (non-sign digits for integers, mantissa for floating-point). + * This is the analogue of + * `std::numeric_limits::digits` which is used as the default implementation if specialized. + * \li digits10() function returning the number of decimal digits that can be represented without change. This is the + * analogue of + * `std::numeric_limits::digits10` which is used as the default implementation if specialized. + * \li max_digits10() function returning the number of decimal digits required to uniquely represent all distinct values + * of the type. This is the analogue of `std::numeric_limits::max_digits10` + * which is used as the default implementation if specialized. + * \li min_exponent() and max_exponent() functions returning the highest and lowest possible values, respectively, + * such that the radix raised to the power exponent-1 is a normalized floating-point number. These are equivalent + * to + * `std::numeric_limits::min_exponent`/`std::numeric_limits::max_exponent`. + * \li infinity() function returning a representation of positive infinity, if available. + * \li quiet_NaN() function returning a non-signaling "not-a-number", if available. + */ +// clang-format on +template +struct GenericNumTraits { + enum { + IsInteger = std::numeric_limits::is_integer, + IsSigned = std::numeric_limits::is_signed, + IsComplex = 0, + RequireInitialization = internal::is_arithmetic::value ? 0 : 1, + ReadCost = 1, + AddCost = 1, + MulCost = 1 + }; + + typedef T Real; + typedef std::conditional_t, T> NonInteger; + typedef T Nested; + typedef T Literal; + + EIGEN_DEVICE_FUNC constexpr static Real epsilon() { return numext::numeric_limits::epsilon(); } + + EIGEN_DEVICE_FUNC constexpr static int digits10() { return internal::default_digits10_impl::run(); } + + EIGEN_DEVICE_FUNC constexpr static int max_digits10() { return internal::default_max_digits10_impl::run(); } + + EIGEN_DEVICE_FUNC constexpr static int digits() { return internal::default_digits_impl::run(); } + + EIGEN_DEVICE_FUNC constexpr static int min_exponent() { return numext::numeric_limits::min_exponent; } + + EIGEN_DEVICE_FUNC constexpr static int max_exponent() { return numext::numeric_limits::max_exponent; } + + EIGEN_DEVICE_FUNC constexpr static Real dummy_precision() { + // make sure to override this for floating-point types + return Real(0); + } + + EIGEN_DEVICE_FUNC constexpr static T highest() { return (numext::numeric_limits::max)(); } + + EIGEN_DEVICE_FUNC constexpr static T lowest() { return (numext::numeric_limits::lowest)(); } + + EIGEN_DEVICE_FUNC constexpr static T infinity() { return numext::numeric_limits::infinity(); } + + EIGEN_DEVICE_FUNC constexpr static T quiet_NaN() { return numext::numeric_limits::quiet_NaN(); } +}; + +template +struct NumTraits : GenericNumTraits {}; + +template <> +struct NumTraits : GenericNumTraits { + EIGEN_DEVICE_FUNC constexpr static float dummy_precision() { return 1e-5f; } +}; + +template <> +struct NumTraits : GenericNumTraits { + EIGEN_DEVICE_FUNC constexpr static double dummy_precision() { return 1e-12; } +}; + +// GPU devices treat `long double` as `double`. +#ifndef EIGEN_GPU_COMPILE_PHASE +template <> +struct NumTraits : GenericNumTraits { + EIGEN_DEVICE_FUNC constexpr static long double dummy_precision() { return static_cast(1e-15l); } + +#if defined(EIGEN_ARCH_PPC) && (__LDBL_MANT_DIG__ == 106) + // PowerPC double double causes issues with some values + EIGEN_DEVICE_FUNC constexpr static long double epsilon() { + // 2^(-(__LDBL_MANT_DIG__)+1) + return static_cast(2.4651903288156618919116517665087e-32l); + } +#endif +}; +#endif + +template +struct NumTraits > : GenericNumTraits > { + typedef Real_ Real; + typedef typename NumTraits::Literal Literal; + enum { + IsComplex = 1, + IsSigned = NumTraits::IsSigned, + RequireInitialization = NumTraits::RequireInitialization, + ReadCost = 2 * NumTraits::ReadCost, + AddCost = 2 * NumTraits::AddCost, + MulCost = 4 * NumTraits::MulCost + 2 * NumTraits::AddCost + }; + + EIGEN_DEVICE_FUNC constexpr static Real epsilon() { return NumTraits::epsilon(); } + EIGEN_DEVICE_FUNC constexpr static Real dummy_precision() { return NumTraits::dummy_precision(); } + EIGEN_DEVICE_FUNC constexpr static int digits10() { return NumTraits::digits10(); } + EIGEN_DEVICE_FUNC constexpr static int max_digits10() { return NumTraits::max_digits10(); } +}; + +template +struct NumTraits > { + typedef Array ArrayType; + typedef typename NumTraits::Real RealScalar; + typedef Array Real; + typedef typename NumTraits::NonInteger NonIntegerScalar; + typedef Array NonInteger; + typedef ArrayType& Nested; + typedef typename NumTraits::Literal Literal; + + enum { + IsComplex = NumTraits::IsComplex, + IsInteger = NumTraits::IsInteger, + IsSigned = NumTraits::IsSigned, + RequireInitialization = 1, + ReadCost = ArrayType::SizeAtCompileTime == Dynamic + ? HugeCost + : ArrayType::SizeAtCompileTime * int(NumTraits::ReadCost), + AddCost = ArrayType::SizeAtCompileTime == Dynamic ? HugeCost + : ArrayType::SizeAtCompileTime * int(NumTraits::AddCost), + MulCost = ArrayType::SizeAtCompileTime == Dynamic ? HugeCost + : ArrayType::SizeAtCompileTime * int(NumTraits::MulCost) + }; + + EIGEN_DEVICE_FUNC constexpr static RealScalar epsilon() { return NumTraits::epsilon(); } + EIGEN_DEVICE_FUNC constexpr static RealScalar dummy_precision() { return NumTraits::dummy_precision(); } + + constexpr static int digits10() { return NumTraits::digits10(); } + constexpr static int max_digits10() { return NumTraits::max_digits10(); } +}; + +template <> +struct NumTraits : GenericNumTraits { + enum { RequireInitialization = 1, ReadCost = HugeCost, AddCost = HugeCost, MulCost = HugeCost }; + + constexpr static int digits10() { return 0; } + constexpr static int max_digits10() { return 0; } + + private: + static inline std::string epsilon(); + static inline std::string dummy_precision(); + static inline std::string lowest(); + static inline std::string highest(); + static inline std::string infinity(); + static inline std::string quiet_NaN(); +}; + +// Empty specialization for void to allow template specialization based on NumTraits::Real with T==void and SFINAE. +template <> +struct NumTraits {}; + +template <> +struct NumTraits : GenericNumTraits {}; + +} // end namespace Eigen + +#endif // EIGEN_NUMTRAITS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PartialReduxEvaluator.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PartialReduxEvaluator.h new file mode 100644 index 0000000..1f638f9 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PartialReduxEvaluator.h @@ -0,0 +1,253 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011-2018 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PARTIALREDUX_H +#define EIGEN_PARTIALREDUX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/*************************************************************************** + * + * This file provides evaluators for partial reductions. + * There are two modes: + * + * - scalar path: simply calls the respective function on the column or row. + * -> nothing special here, all the tricky part is handled by the return + * types of VectorwiseOp's members. They embed the functor calling the + * respective DenseBase's member function. + * + * - vectorized path: implements a packet-wise reductions followed by + * some (optional) processing of the outcome, e.g., division by n for mean. + * + * For the vectorized path let's observe that the packet-size and outer-unrolling + * are both decided by the assignment logic. So all we have to do is to decide + * on the inner unrolling. + * + * For the unrolling, we can reuse "internal::redux_vec_unroller" from Redux.h, + * but be need to be careful to specify correct increment. + * + ***************************************************************************/ + +/* logic deciding a strategy for unrolling of vectorized paths */ +template +struct packetwise_redux_traits { + enum { + OuterSize = int(Evaluator::IsRowMajor) ? Evaluator::RowsAtCompileTime : Evaluator::ColsAtCompileTime, + Cost = OuterSize == Dynamic ? HugeCost + : OuterSize * Evaluator::CoeffReadCost + (OuterSize - 1) * functor_traits::Cost, + Unrolling = Cost <= EIGEN_UNROLLING_LIMIT ? CompleteUnrolling : NoUnrolling + }; +}; + +/* Value to be returned when size==0 , by default let's return 0 */ +template +EIGEN_DEVICE_FUNC PacketType packetwise_redux_empty_value(const Func&) { + const typename unpacket_traits::type zero(0); + return pset1(zero); +} + +/* For products the default is 1 */ +template +EIGEN_DEVICE_FUNC PacketType packetwise_redux_empty_value(const scalar_product_op&) { + return pset1(Scalar(1)); +} + +/* Perform the actual reduction */ +template ::Unrolling> +struct packetwise_redux_impl; + +/* Perform the actual reduction with unrolling */ +template +struct packetwise_redux_impl { + typedef redux_novec_unroller Base; + typedef typename Evaluator::Scalar Scalar; + + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator& eval, const Func& func, Index /*size*/) { + return redux_vec_unroller::OuterSize>::template run(eval, + func); + } +}; + +/* Add a specialization of redux_vec_unroller for size==0 at compiletime. + * This specialization is not required for general reductions, which is + * why it is defined here. + */ +template +struct redux_vec_unroller { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator&, const Func& f) { + return packetwise_redux_empty_value(f); + } +}; + +/* Perform the actual reduction for dynamic sizes */ +template +struct packetwise_redux_impl { + typedef typename Evaluator::Scalar Scalar; + typedef typename redux_traits::PacketType PacketScalar; + + template + EIGEN_DEVICE_FUNC static PacketType run(const Evaluator& eval, const Func& func, Index size) { + if (size == 0) return packetwise_redux_empty_value(func); + + const Index size4 = 1 + numext::round_down(size - 1, 4); + PacketType p = eval.template packetByOuterInner(0, 0); + // This loop is optimized for instruction pipelining: + // - each iteration generates two independent instructions + // - thanks to branch prediction and out-of-order execution we have independent instructions across loops + for (Index i = 1; i < size4; i += 4) + p = func.packetOp( + p, func.packetOp(func.packetOp(eval.template packetByOuterInner(i + 0, 0), + eval.template packetByOuterInner(i + 1, 0)), + func.packetOp(eval.template packetByOuterInner(i + 2, 0), + eval.template packetByOuterInner(i + 3, 0)))); + for (Index i = size4; i < size; ++i) + p = func.packetOp(p, eval.template packetByOuterInner(i, 0)); + return p; + } +}; + +template +struct packetwise_segment_redux_impl { + typedef typename Evaluator::Scalar Scalar; + typedef typename redux_traits::PacketType PacketScalar; + + template + EIGEN_DEVICE_FUNC static PacketType run(const Evaluator& eval, const Func& func, Index size, Index begin, + Index count) { + if (size == 0) return packetwise_redux_empty_value(func); + + PacketType p = eval.template packetSegmentByOuterInner(0, 0, begin, count); + for (Index i = 1; i < size; ++i) + p = func.packetOp(p, eval.template packetSegmentByOuterInner(i, 0, begin, count)); + return p; + } +}; + +template +struct evaluator > + : evaluator_base > { + typedef PartialReduxExpr XprType; + typedef typename internal::nested_eval::type ArgTypeNested; + typedef add_const_on_value_type_t ConstArgTypeNested; + typedef internal::remove_all_t ArgTypeNestedCleaned; + typedef typename ArgType::Scalar InputScalar; + typedef typename XprType::Scalar Scalar; + enum { + TraversalSize = Direction == int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(ArgType::ColsAtCompileTime) + }; + typedef typename MemberOp::template Cost CostOpType; + enum { + CoeffReadCost = TraversalSize == Dynamic ? HugeCost + : TraversalSize == 0 + ? 1 + : int(TraversalSize) * int(evaluator::CoeffReadCost) + int(CostOpType::value), + + ArgFlags_ = evaluator::Flags, + + Vectorizable_ = bool(int(ArgFlags_) & PacketAccessBit) && bool(MemberOp::Vectorizable) && + (Direction == int(Vertical) ? bool(ArgFlags_ & RowMajorBit) : (ArgFlags_ & RowMajorBit) == 0) && + (TraversalSize != 0), + + Flags = (traits::Flags & RowMajorBit) | (evaluator::Flags & (HereditaryBits & (~RowMajorBit))) | + (Vectorizable_ ? PacketAccessBit : 0) | LinearAccessBit, + + Alignment = 0 // FIXME this will need to be improved once PartialReduxExpr is vectorized + }; + + EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr) : m_arg(xpr.nestedExpression()), m_functor(xpr.functor()) { + EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize == Dynamic ? HugeCost + : (TraversalSize == 0 ? 1 : int(CostOpType::value))); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index i, Index j) const { + return coeff(Direction == Vertical ? j : i); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index index) const { + return m_functor(m_arg.template subVector(index)); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index i, Index j) const { + return packet(Direction == Vertical ? j : i); + } + + template + EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC PacketType packet(Index idx) const { + static constexpr int PacketSize = internal::unpacket_traits::size; + static constexpr int PanelRows = Direction == Vertical ? ArgType::RowsAtCompileTime : PacketSize; + static constexpr int PanelCols = Direction == Vertical ? PacketSize : ArgType::ColsAtCompileTime; + using PanelType = Block; + using PanelEvaluator = typename internal::redux_evaluator; + using BinaryOp = typename MemberOp::BinaryOp; + using Impl = internal::packetwise_redux_impl; + + // FIXME + // See bug 1612, currently if PacketSize==1 (i.e. complex with 128bits registers) then the storage-order of + // panel get reversed and methods like packetByOuterInner do not make sense anymore in this context. So let's just + // by pass "vectorization" in this case: + if (PacketSize == 1) return internal::pset1(coeff(idx)); + + Index startRow = Direction == Vertical ? 0 : idx; + Index startCol = Direction == Vertical ? idx : 0; + Index numRows = Direction == Vertical ? m_arg.rows() : PacketSize; + Index numCols = Direction == Vertical ? PacketSize : m_arg.cols(); + + PanelType panel(m_arg, startRow, startCol, numRows, numCols); + PanelEvaluator panel_eval(panel); + PacketType p = Impl::template run(panel_eval, m_functor.binaryFunc(), m_arg.outerSize()); + return p; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index i, Index j, Index begin, Index count) const { + return packetSegment(Direction == Vertical ? j : i, begin, count); + } + + template + EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC PacketType packetSegment(Index idx, Index begin, Index count) const { + static constexpr int PanelRows = Direction == Vertical ? ArgType::RowsAtCompileTime : Dynamic; + static constexpr int PanelCols = Direction == Vertical ? Dynamic : ArgType::ColsAtCompileTime; + using PanelType = Block; + using PanelEvaluator = typename internal::redux_evaluator; + using BinaryOp = typename MemberOp::BinaryOp; + using Impl = internal::packetwise_segment_redux_impl; + + Index startRow = Direction == Vertical ? 0 : idx; + Index startCol = Direction == Vertical ? idx : 0; + Index numRows = Direction == Vertical ? m_arg.rows() : begin + count; + Index numCols = Direction == Vertical ? begin + count : m_arg.cols(); + + PanelType panel(m_arg, startRow, startCol, numRows, numCols); + PanelEvaluator panel_eval(panel); + PacketType p = Impl::template run(panel_eval, m_functor.binaryFunc(), m_arg.outerSize(), begin, count); + return p; + } + + protected: + ConstArgTypeNested m_arg; + const MemberOp m_functor; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PARTIALREDUX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PermutationMatrix.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PermutationMatrix.h new file mode 100644 index 0000000..7713354 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PermutationMatrix.h @@ -0,0 +1,555 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Benoit Jacob +// Copyright (C) 2009-2015 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PERMUTATIONMATRIX_H +#define EIGEN_PERMUTATIONMATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +enum PermPermProduct_t { PermPermProduct }; + +} // end namespace internal + +/** \class PermutationBase + * \ingroup Core_Module + * + * \brief Base class for permutations + * + * \tparam Derived the derived class + * + * This class is the base class for all expressions representing a permutation matrix, + * internally stored as a vector of integers. + * The convention followed here is that if \f$ \sigma \f$ is a permutation, the corresponding permutation matrix + * \f$ P_\sigma \f$ is such that if \f$ (e_1,\ldots,e_p) \f$ is the canonical basis, we have: + * \f[ P_\sigma(e_i) = e_{\sigma(i)}. \f] + * This convention ensures that for any two permutations \f$ \sigma, \tau \f$, we have: + * \f[ P_{\sigma\circ\tau} = P_\sigma P_\tau. \f] + * + * Permutation matrices are square and invertible. + * + * Notice that in addition to the member functions and operators listed here, there also are non-member + * operator* to multiply any kind of permutation object with any kind of matrix expression (MatrixBase) + * on either side. + * + * \sa class PermutationMatrix, class PermutationWrapper + */ +template +class PermutationBase : public EigenBase { + typedef internal::traits Traits; + typedef EigenBase Base; + + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename Traits::IndicesType IndicesType; + enum { + Flags = Traits::Flags, + RowsAtCompileTime = Traits::RowsAtCompileTime, + ColsAtCompileTime = Traits::ColsAtCompileTime, + MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = Traits::MaxColsAtCompileTime + }; + typedef typename Traits::StorageIndex StorageIndex; + typedef Matrix + DenseMatrixType; + typedef PermutationMatrix + PlainPermutationType; + typedef PlainPermutationType PlainObject; + using Base::derived; + typedef Inverse InverseReturnType; + typedef void Scalar; +#endif + + /** Copies the other permutation into *this */ + template + Derived& operator=(const PermutationBase& other) { + indices() = other.indices(); + return derived(); + } + + /** Assignment from the Transpositions \a tr */ + template + Derived& operator=(const TranspositionsBase& tr) { + setIdentity(tr.size()); + for (Index k = size() - 1; k >= 0; --k) applyTranspositionOnTheRight(k, tr.coeff(k)); + return derived(); + } + + /** \returns the number of rows */ + inline EIGEN_DEVICE_FUNC Index rows() const { return Index(indices().size()); } + + /** \returns the number of columns */ + inline EIGEN_DEVICE_FUNC Index cols() const { return Index(indices().size()); } + + /** \returns the size of a side of the respective square matrix, i.e., the number of indices */ + inline EIGEN_DEVICE_FUNC Index size() const { return Index(indices().size()); } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + void evalTo(MatrixBase& other) const { + other.setZero(); + for (Index i = 0; i < rows(); ++i) other.coeffRef(indices().coeff(i), i) = typename DenseDerived::Scalar(1); + } +#endif + + /** \returns a Matrix object initialized from this permutation matrix. Notice that it + * is inefficient to return this Matrix object by value. For efficiency, favor using + * the Matrix constructor taking EigenBase objects. + */ + DenseMatrixType toDenseMatrix() const { return derived(); } + + /** \returns the plain matrix representation of the permutation. */ + DenseMatrixType eval() const { return toDenseMatrix(); } + + /** const version of indices(). */ + const IndicesType& indices() const { return derived().indices(); } + /** \returns a reference to the stored array representing the permutation. */ + IndicesType& indices() { return derived().indices(); } + + /** Resizes to given size. + */ + inline void resize(Index newSize) { indices().resize(newSize); } + + /** Sets *this to be the identity permutation matrix */ + void setIdentity() { + StorageIndex n = StorageIndex(size()); + for (StorageIndex i = 0; i < n; ++i) indices().coeffRef(i) = i; + } + + /** Sets *this to be the identity permutation matrix of given size. + */ + void setIdentity(Index newSize) { + resize(newSize); + setIdentity(); + } + + /** Multiplies *this by the transposition \f$(ij)\f$ on the left. + * + * \returns a reference to *this. + * + * \warning This is much slower than applyTranspositionOnTheRight(Index,Index): + * this has linear complexity and requires a lot of branching. + * + * \sa applyTranspositionOnTheRight(Index,Index) + */ + Derived& applyTranspositionOnTheLeft(Index i, Index j) { + eigen_assert(i >= 0 && j >= 0 && i < size() && j < size()); + for (Index k = 0; k < size(); ++k) { + if (indices().coeff(k) == i) + indices().coeffRef(k) = StorageIndex(j); + else if (indices().coeff(k) == j) + indices().coeffRef(k) = StorageIndex(i); + } + return derived(); + } + + /** Multiplies *this by the transposition \f$(ij)\f$ on the right. + * + * \returns a reference to *this. + * + * This is a fast operation, it only consists in swapping two indices. + * + * \sa applyTranspositionOnTheLeft(Index,Index) + */ + Derived& applyTranspositionOnTheRight(Index i, Index j) { + eigen_assert(i >= 0 && j >= 0 && i < size() && j < size()); + std::swap(indices().coeffRef(i), indices().coeffRef(j)); + return derived(); + } + + /** \returns the inverse permutation matrix. + * + * \note \blank \note_try_to_help_rvo + */ + inline InverseReturnType inverse() const { return InverseReturnType(derived()); } + /** \returns the transpose permutation matrix. + * + * \note \blank \note_try_to_help_rvo + */ + inline InverseReturnType transpose() const { return InverseReturnType(derived()); } + + /**** multiplication helpers to hopefully get RVO ****/ + +#ifndef EIGEN_PARSED_BY_DOXYGEN + protected: + template + void assignTranspose(const PermutationBase& other) { + for (Index i = 0; i < rows(); ++i) indices().coeffRef(other.indices().coeff(i)) = i; + } + template + void assignProduct(const Lhs& lhs, const Rhs& rhs) { + eigen_assert(lhs.cols() == rhs.rows()); + for (Index i = 0; i < rows(); ++i) indices().coeffRef(i) = lhs.indices().coeff(rhs.indices().coeff(i)); + } +#endif + + public: + /** \returns the product permutation matrix. + * + * \note \blank \note_try_to_help_rvo + */ + template + inline PlainPermutationType operator*(const PermutationBase& other) const { + return PlainPermutationType(internal::PermPermProduct, derived(), other.derived()); + } + + /** \returns the product of a permutation with another inverse permutation. + * + * \note \blank \note_try_to_help_rvo + */ + template + inline PlainPermutationType operator*(const InverseImpl& other) const { + return PlainPermutationType(internal::PermPermProduct, *this, other.eval()); + } + + /** \returns the product of an inverse permutation with another permutation. + * + * \note \blank \note_try_to_help_rvo + */ + template + friend inline PlainPermutationType operator*(const InverseImpl& other, + const PermutationBase& perm) { + return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); + } + + /** \returns the determinant of the permutation matrix, which is either 1 or -1 depending on the parity of the + * permutation. + * + * This function is O(\c n) procedure allocating a buffer of \c n booleans. + */ + Index determinant() const { + Index res = 1; + Index n = size(); + Matrix mask(n); + mask.fill(false); + Index r = 0; + while (r < n) { + // search for the next seed + while (r < n && mask[r]) r++; + if (r >= n) break; + // we got one, let's follow it until we are back to the seed + Index k0 = r++; + mask.coeffRef(k0) = true; + for (Index k = indices().coeff(k0); k != k0; k = indices().coeff(k)) { + mask.coeffRef(k) = true; + res = -res; + } + } + return res; + } + + protected: +}; + +namespace internal { +template +struct traits > + : traits< + Matrix > { + typedef PermutationStorage StorageKind; + typedef Matrix IndicesType; + typedef StorageIndex_ StorageIndex; + typedef void Scalar; +}; +} // namespace internal + +/** \class PermutationMatrix + * \ingroup Core_Module + * + * \brief Permutation matrix + * + * \tparam SizeAtCompileTime the number of rows/cols, or Dynamic + * \tparam MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to + * SizeAtCompileTime. Most of the time, you should not have to specify it. \tparam StorageIndex_ the integer type of the + * indices + * + * This class represents a permutation matrix, internally stored as a vector of integers. + * + * \sa class PermutationBase, class PermutationWrapper, class DiagonalMatrix + */ +template +class PermutationMatrix + : public PermutationBase > { + typedef PermutationBase Base; + typedef internal::traits Traits; + + public: + typedef const PermutationMatrix& Nested; + +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename Traits::IndicesType IndicesType; + typedef typename Traits::StorageIndex StorageIndex; +#endif + + inline PermutationMatrix() {} + + /** Constructs an uninitialized permutation matrix of given size. + */ + explicit inline PermutationMatrix(Index size) : m_indices(size) { + eigen_internal_assert(size <= NumTraits::highest()); + } + + /** Copy constructor. */ + template + inline PermutationMatrix(const PermutationBase& other) : m_indices(other.indices()) {} + + /** Generic constructor from expression of the indices. The indices + * array has the meaning that the permutations sends each integer i to indices[i]. + * + * \warning It is your responsibility to check that the indices array that you passes actually + * describes a permutation, i.e., each value between 0 and n-1 occurs exactly once, where n is the + * array's size. + */ + template + explicit inline PermutationMatrix(const MatrixBase& indices) : m_indices(indices) {} + + /** Convert the Transpositions \a tr to a permutation matrix */ + template + explicit PermutationMatrix(const TranspositionsBase& tr) : m_indices(tr.size()) { + *this = tr; + } + + /** Copies the other permutation into *this */ + template + PermutationMatrix& operator=(const PermutationBase& other) { + m_indices = other.indices(); + return *this; + } + + /** Assignment from the Transpositions \a tr */ + template + PermutationMatrix& operator=(const TranspositionsBase& tr) { + return Base::operator=(tr.derived()); + } + + /** const version of indices(). */ + const IndicesType& indices() const { return m_indices; } + /** \returns a reference to the stored array representing the permutation. */ + IndicesType& indices() { return m_indices; } + + /**** multiplication helpers to hopefully get RVO ****/ + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + PermutationMatrix(const InverseImpl& other) + : m_indices(other.derived().nestedExpression().size()) { + eigen_internal_assert(m_indices.size() <= NumTraits::highest()); + StorageIndex end = StorageIndex(m_indices.size()); + for (StorageIndex i = 0; i < end; ++i) + m_indices.coeffRef(other.derived().nestedExpression().indices().coeff(i)) = i; + } + template + PermutationMatrix(internal::PermPermProduct_t, const Lhs& lhs, const Rhs& rhs) : m_indices(lhs.indices().size()) { + Base::assignProduct(lhs, rhs); + } +#endif + + protected: + IndicesType m_indices; +}; + +namespace internal { +template +struct traits, PacketAccess_> > + : traits< + Matrix > { + typedef PermutationStorage StorageKind; + typedef Map, PacketAccess_> IndicesType; + typedef StorageIndex_ StorageIndex; + typedef void Scalar; +}; +} // namespace internal + +template +class Map, PacketAccess_> + : public PermutationBase< + Map, PacketAccess_> > { + typedef PermutationBase Base; + typedef internal::traits Traits; + + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename Traits::IndicesType IndicesType; + typedef typename IndicesType::Scalar StorageIndex; +#endif + + inline Map(const StorageIndex* indicesPtr) : m_indices(indicesPtr) {} + + inline Map(const StorageIndex* indicesPtr, Index size) : m_indices(indicesPtr, size) {} + + /** Copies the other permutation into *this */ + template + Map& operator=(const PermutationBase& other) { + return Base::operator=(other.derived()); + } + + /** Assignment from the Transpositions \a tr */ + template + Map& operator=(const TranspositionsBase& tr) { + return Base::operator=(tr.derived()); + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + Map& operator=(const Map& other) { + m_indices = other.m_indices; + return *this; + } +#endif + + /** const version of indices(). */ + const IndicesType& indices() const { return m_indices; } + /** \returns a reference to the stored array representing the permutation. */ + IndicesType& indices() { return m_indices; } + + protected: + IndicesType m_indices; +}; + +template +class TranspositionsWrapper; +namespace internal { +template +struct traits > { + typedef PermutationStorage StorageKind; + typedef void Scalar; + typedef typename IndicesType_::Scalar StorageIndex; + typedef IndicesType_ IndicesType; + enum { + RowsAtCompileTime = IndicesType_::SizeAtCompileTime, + ColsAtCompileTime = IndicesType_::SizeAtCompileTime, + MaxRowsAtCompileTime = IndicesType::MaxSizeAtCompileTime, + MaxColsAtCompileTime = IndicesType::MaxSizeAtCompileTime, + Flags = 0 + }; +}; +} // namespace internal + +/** \class PermutationWrapper + * \ingroup Core_Module + * + * \brief Class to view a vector of integers as a permutation matrix + * + * \tparam IndicesType_ the type of the vector of integer (can be any compatible expression) + * + * This class allows to view any vector expression of integers as a permutation matrix. + * + * \sa class PermutationBase, class PermutationMatrix + */ +template +class PermutationWrapper : public PermutationBase > { + typedef PermutationBase Base; + typedef internal::traits Traits; + + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename Traits::IndicesType IndicesType; +#endif + + inline PermutationWrapper(const IndicesType& indices) : m_indices(indices) {} + + /** const version of indices(). */ + const internal::remove_all_t& indices() const { return m_indices; } + + protected: + typename IndicesType::Nested m_indices; +}; + +/** \returns the matrix with the permutation applied to the columns. + */ +template +EIGEN_DEVICE_FUNC const Product operator*( + const MatrixBase& matrix, const PermutationBase& permutation) { + return Product(matrix.derived(), permutation.derived()); +} + +/** \returns the matrix with the permutation applied to the rows. + */ +template +EIGEN_DEVICE_FUNC const Product operator*( + const PermutationBase& permutation, const MatrixBase& matrix) { + return Product(permutation.derived(), matrix.derived()); +} + +template +class InverseImpl : public EigenBase > { + typedef typename PermutationType::PlainPermutationType PlainPermutationType; + typedef internal::traits PermTraits; + + protected: + InverseImpl() {} + + public: + typedef Inverse InverseType; + using EigenBase >::derived; + +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename PermutationType::DenseMatrixType DenseMatrixType; + enum { + RowsAtCompileTime = PermTraits::RowsAtCompileTime, + ColsAtCompileTime = PermTraits::ColsAtCompileTime, + MaxRowsAtCompileTime = PermTraits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = PermTraits::MaxColsAtCompileTime + }; +#endif + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + void evalTo(MatrixBase& other) const { + other.setZero(); + for (Index i = 0; i < derived().rows(); ++i) + other.coeffRef(i, derived().nestedExpression().indices().coeff(i)) = typename DenseDerived::Scalar(1); + } +#endif + + /** \return the equivalent permutation matrix */ + PlainPermutationType eval() const { return derived(); } + + DenseMatrixType toDenseMatrix() const { return derived(); } + + /** \returns the matrix with the inverse permutation applied to the columns. + */ + template + friend const Product operator*(const MatrixBase& matrix, + const InverseType& trPerm) { + return Product(matrix.derived(), trPerm.derived()); + } + + /** \returns the matrix with the inverse permutation applied to the rows. + */ + template + const Product operator*(const MatrixBase& matrix) const { + return Product(derived(), matrix.derived()); + } +}; + +template +const PermutationWrapper MatrixBase::asPermutation() const { + return derived(); +} + +namespace internal { + +template <> +struct AssignmentKind { + typedef EigenBase2EigenBase Kind; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PERMUTATIONMATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PlainObjectBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PlainObjectBase.h new file mode 100644 index 0000000..1544a58 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/PlainObjectBase.h @@ -0,0 +1,1008 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_DENSESTORAGEBASE_H +#define EIGEN_DENSESTORAGEBASE_H + +#if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO) +#define EIGEN_INITIALIZE_COEFFS +#define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED \ + for (Index i = 0; i < base().size(); ++i) coeffRef(i) = Scalar(0); +#elif defined(EIGEN_INITIALIZE_MATRICES_BY_NAN) +#define EIGEN_INITIALIZE_COEFFS +#define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED \ + for (Index i = 0; i < base().size(); ++i) coeffRef(i) = std::numeric_limits::quiet_NaN(); +#else +#undef EIGEN_INITIALIZE_COEFFS +#define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED +#endif + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +#ifndef EIGEN_NO_DEBUG +template +struct check_rows_cols_for_overflow { + EIGEN_STATIC_ASSERT(MaxRowsAtCompileTime* MaxColsAtCompileTime == MaxSizeAtCompileTime, + YOU MADE A PROGRAMMING MISTAKE) + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index) {} +}; + +template +struct check_rows_cols_for_overflow { + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index cols) { + constexpr Index MaxIndex = NumTraits::highest(); + bool error = cols > (MaxIndex / MaxRowsAtCompileTime); + if (error) throw_std_bad_alloc(); + } +}; + +template +struct check_rows_cols_for_overflow { + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index) { + constexpr Index MaxIndex = NumTraits::highest(); + bool error = rows > (MaxIndex / MaxColsAtCompileTime); + if (error) throw_std_bad_alloc(); + } +}; + +template <> +struct check_rows_cols_for_overflow { + template + EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index cols) { + constexpr Index MaxIndex = NumTraits::highest(); + bool error = cols == 0 ? false : (rows > (MaxIndex / cols)); + if (error) throw_std_bad_alloc(); + } +}; +#endif + +template +struct conservative_resize_like_impl; + +template +struct matrix_swap_impl; + +} // end namespace internal + +/** \class PlainObjectBase + * \ingroup Core_Module + * \brief %Dense storage base class for matrices and arrays. + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN. + * + * \tparam Derived is the derived type, e.g., a Matrix or Array + * + * \sa \ref TopicClassHierarchy + */ +template +class PlainObjectBase : public internal::dense_xpr_base::type { + public: + enum { Options = internal::traits::Options }; + typedef typename internal::dense_xpr_base::type Base; + + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::Scalar Scalar; + + typedef typename internal::packet_traits::type PacketScalar; + typedef typename NumTraits::Real RealScalar; + typedef Derived DenseType; + + using Base::ColsAtCompileTime; + using Base::Flags; + using Base::IsVectorAtCompileTime; + using Base::MaxColsAtCompileTime; + using Base::MaxRowsAtCompileTime; + using Base::MaxSizeAtCompileTime; + using Base::RowsAtCompileTime; + using Base::SizeAtCompileTime; + + typedef Eigen::Map MapType; + typedef const Eigen::Map ConstMapType; + typedef Eigen::Map AlignedMapType; + typedef const Eigen::Map ConstAlignedMapType; + template + struct StridedMapType { + typedef Eigen::Map type; + }; + template + struct StridedConstMapType { + typedef Eigen::Map type; + }; + template + struct StridedAlignedMapType { + typedef Eigen::Map type; + }; + template + struct StridedConstAlignedMapType { + typedef Eigen::Map type; + }; + + protected: + DenseStorage m_storage; + + public: + enum { NeedsToAlign = (SizeAtCompileTime != Dynamic) && (internal::traits::Alignment > 0) }; + EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) + + EIGEN_STATIC_ASSERT(internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1, + (int(Options) & RowMajor) == RowMajor), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT(internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1, + (int(Options) & RowMajor) == 0), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0), INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0), INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime == Dynamic), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT((MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime == Dynamic), + INVALID_MATRIX_TEMPLATE_PARAMETERS) + EIGEN_STATIC_ASSERT(((Options & (DontAlign | RowMajor)) == Options), INVALID_MATRIX_TEMPLATE_PARAMETERS) + + EIGEN_DEVICE_FUNC constexpr Base& base() { return *static_cast(this); } + EIGEN_DEVICE_FUNC constexpr const Base& base() const { return *static_cast(this); } + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_storage.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_storage.cols(); } + + /** This is an overloaded version of DenseCoeffsBase::coeff(Index,Index) const + * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. + * + * See DenseCoeffsBase::coeff(Index) const for details. */ + EIGEN_DEVICE_FUNC constexpr const Scalar& coeff(Index rowId, Index colId) const { + if (Flags & RowMajorBit) + return m_storage.data()[colId + rowId * m_storage.cols()]; + else // column-major + return m_storage.data()[rowId + colId * m_storage.rows()]; + } + + /** This is an overloaded version of DenseCoeffsBase::coeff(Index) const + * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. + * + * See DenseCoeffsBase::coeff(Index) const for details. */ + EIGEN_DEVICE_FUNC constexpr const Scalar& coeff(Index index) const { return m_storage.data()[index]; } + + /** This is an overloaded version of DenseCoeffsBase::coeffRef(Index,Index) const + * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. + * + * See DenseCoeffsBase::coeffRef(Index,Index) const for details. */ + EIGEN_DEVICE_FUNC constexpr Scalar& coeffRef(Index rowId, Index colId) { + if (Flags & RowMajorBit) + return m_storage.data()[colId + rowId * m_storage.cols()]; + else // column-major + return m_storage.data()[rowId + colId * m_storage.rows()]; + } + + /** This is an overloaded version of DenseCoeffsBase::coeffRef(Index) const + * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. + * + * See DenseCoeffsBase::coeffRef(Index) const for details. */ + EIGEN_DEVICE_FUNC constexpr Scalar& coeffRef(Index index) { return m_storage.data()[index]; } + + /** This is the const version of coeffRef(Index,Index) which is thus synonym of coeff(Index,Index). + * It is provided for convenience. */ + EIGEN_DEVICE_FUNC constexpr const Scalar& coeffRef(Index rowId, Index colId) const { + if (Flags & RowMajorBit) + return m_storage.data()[colId + rowId * m_storage.cols()]; + else // column-major + return m_storage.data()[rowId + colId * m_storage.rows()]; + } + + /** This is the const version of coeffRef(Index) which is thus synonym of coeff(Index). + * It is provided for convenience. */ + EIGEN_DEVICE_FUNC constexpr const Scalar& coeffRef(Index index) const { return m_storage.data()[index]; } + + /** \internal */ + template + EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const { + return internal::ploadt( + m_storage.data() + (Flags & RowMajorBit ? colId + rowId * m_storage.cols() : rowId + colId * m_storage.rows())); + } + + /** \internal */ + template + EIGEN_STRONG_INLINE PacketScalar packet(Index index) const { + return internal::ploadt(m_storage.data() + index); + } + + /** \internal */ + template + EIGEN_STRONG_INLINE void writePacket(Index rowId, Index colId, const PacketScalar& val) { + internal::pstoret( + m_storage.data() + (Flags & RowMajorBit ? colId + rowId * m_storage.cols() : rowId + colId * m_storage.rows()), + val); + } + + /** \internal */ + template + EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& val) { + internal::pstoret(m_storage.data() + index, val); + } + + /** \returns a const pointer to the data array of this matrix */ + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_storage.data(); } + + /** \returns a pointer to the data array of this matrix */ + EIGEN_DEVICE_FUNC constexpr Scalar* data() { return m_storage.data(); } + + /** Resizes \c *this to a \a rows x \a cols matrix. + * + * This method is intended for dynamic-size matrices, although it is legal to call it on any + * matrix as long as fixed dimensions are left unchanged. If you only want to change the number + * of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t). + * + * If the current number of coefficients of \c *this exactly matches the + * product \a rows * \a cols, then no memory allocation is performed and + * the current values are left unchanged. In all other cases, including + * shrinking, the data is reallocated and all previous values are lost. + * + * Example: \include Matrix_resize_int_int.cpp + * Output: \verbinclude Matrix_resize_int_int.out + * + * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t) + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index rows, Index cols) { + eigen_assert(internal::check_implication(RowsAtCompileTime != Dynamic, rows == RowsAtCompileTime) && + internal::check_implication(ColsAtCompileTime != Dynamic, cols == ColsAtCompileTime) && + internal::check_implication(RowsAtCompileTime == Dynamic && MaxRowsAtCompileTime != Dynamic, + rows <= MaxRowsAtCompileTime) && + internal::check_implication(ColsAtCompileTime == Dynamic && MaxColsAtCompileTime != Dynamic, + cols <= MaxColsAtCompileTime) && + rows >= 0 && cols >= 0 && "Invalid sizes when resizing a matrix or array."); +#ifndef EIGEN_NO_DEBUG + internal::check_rows_cols_for_overflow::run(rows, + cols); +#endif +#ifdef EIGEN_INITIALIZE_COEFFS + Index size = rows * cols; + bool size_changed = size != this->size(); + m_storage.resize(size, rows, cols); + if (size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED +#else + m_storage.resize(rows * cols, rows, cols); +#endif + } + + /** Resizes \c *this to a vector of length \a size + * + * \only_for_vectors. This method does not work for + * partially dynamic matrices when the static dimension is anything other + * than 1. For example it will not work with Matrix. + * + * Example: \include Matrix_resize_int.cpp + * Output: \verbinclude Matrix_resize_int.out + * + * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t) + */ + EIGEN_DEVICE_FUNC constexpr void resize(Index size) { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase) + eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime == Dynamic || size <= MaxSizeAtCompileTime)) || + SizeAtCompileTime == size) && + size >= 0); +#ifdef EIGEN_INITIALIZE_COEFFS + bool size_changed = size != this->size(); +#endif + if (RowsAtCompileTime == 1) + m_storage.resize(size, 1, size); + else + m_storage.resize(size, size, 1); +#ifdef EIGEN_INITIALIZE_COEFFS + if (size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED +#endif + } + + /** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the + * special value \c NoChange as in the example below. + * + * Example: \include Matrix_resize_NoChange_int.cpp + * Output: \verbinclude Matrix_resize_NoChange_int.out + * + * \sa resize(Index,Index) + */ + EIGEN_DEVICE_FUNC constexpr void resize(NoChange_t, Index cols) { resize(rows(), cols); } + + /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special + * value \c NoChange as in the example below. + * + * Example: \include Matrix_resize_int_NoChange.cpp + * Output: \verbinclude Matrix_resize_int_NoChange.out + * + * \sa resize(Index,Index) + */ + EIGEN_DEVICE_FUNC constexpr void resize(Index rows, NoChange_t) { resize(rows, cols()); } + + /** Resizes \c *this to have the same dimensions as \a other. + * Takes care of doing all the checking that's needed. + * + * Note that copying a row-vector into a vector (and conversely) is allowed. + * The resizing, if any, is then done in the appropriate way so that row-vectors + * remain row-vectors and vectors remain vectors. + */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resizeLike(const EigenBase& _other) { + const OtherDerived& other = _other.derived(); +#ifndef EIGEN_NO_DEBUG + internal::check_rows_cols_for_overflow::run( + other.rows(), other.cols()); +#endif + const Index othersize = other.rows() * other.cols(); + if (RowsAtCompileTime == 1) { + eigen_assert(other.rows() == 1 || other.cols() == 1); + resize(1, othersize); + } else if (ColsAtCompileTime == 1) { + eigen_assert(other.rows() == 1 || other.cols() == 1); + resize(othersize, 1); + } else + resize(other.rows(), other.cols()); + } + + /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. + * + * The method is intended for matrices of dynamic size. If you only want to change the number + * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or + * conservativeResize(Index, NoChange_t). + * + * Matrices are resized relative to the top-left element. In case values need to be + * appended to the matrix they will be uninitialized. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols) { + internal::conservative_resize_like_impl::run(*this, rows, cols); + } + + /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. + * + * As opposed to conservativeResize(Index rows, Index cols), this version leaves + * the number of columns unchanged. + * + * In case the matrix is growing, new rows will be uninitialized. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t) { + // Note: see the comment in conservativeResize(Index,Index) + conservativeResize(rows, cols()); + } + + /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. + * + * As opposed to conservativeResize(Index rows, Index cols), this version leaves + * the number of rows unchanged. + * + * In case the matrix is growing, new columns will be uninitialized. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols) { + // Note: see the comment in conservativeResize(Index,Index) + conservativeResize(rows(), cols); + } + + /** Resizes the vector to \a size while retaining old values. + * + * \only_for_vectors. This method does not work for + * partially dynamic matrices when the static dimension is anything other + * than 1. For example it will not work with Matrix. + * + * When values are appended, they will be uninitialized. + */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index size) { + internal::conservative_resize_like_impl::run(*this, size); + } + + /** Resizes the matrix to \a rows x \a cols of \c other, while leaving old values untouched. + * + * The method is intended for matrices of dynamic size. If you only want to change the number + * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or + * conservativeResize(Index, NoChange_t). + * + * Matrices are resized relative to the top-left element. In case values need to be + * appended to the matrix they will copied from \c other. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase& other) { + internal::conservative_resize_like_impl::run(*this, other); + } + + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + EIGEN_DEVICE_FUNC constexpr Derived& operator=(const PlainObjectBase& other) { return _set(other); } + + /** \sa MatrixBase::lazyAssign() */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase& other) { + _resize_to_match(other); + return Base::lazyAssign(other.derived()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue& func) { + resize(func.rows(), func.cols()); + return Base::operator=(func); + } + + // Prevent user from trying to instantiate PlainObjectBase objects + // by making all its constructor protected. See bug 1074. + protected: + EIGEN_DEVICE_FUNC constexpr PlainObjectBase() = default; + /** \brief Move constructor */ + EIGEN_DEVICE_FUNC constexpr PlainObjectBase(PlainObjectBase&&) = default; + /** \brief Move assignment operator */ + EIGEN_DEVICE_FUNC constexpr PlainObjectBase& operator=(PlainObjectBase&& other) noexcept { + m_storage = std::move(other.m_storage); + return *this; + } + + /** Copy constructor */ + EIGEN_DEVICE_FUNC constexpr PlainObjectBase(const PlainObjectBase&) = default; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols) + : m_storage(size, rows, cols) {} + + /** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients. + * + * \only_for_vectors + * + * This constructor is for 1D array or vectors with more than 4 coefficients. + * + * \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this + * constructor must match the fixed number of rows (resp. columns) of \c *this. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2, + const Scalar& a3, const ArgTypes&... args) + : m_storage() { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, sizeof...(args) + 4); + m_storage.data()[0] = a0; + m_storage.data()[1] = a1; + m_storage.data()[2] = a2; + m_storage.data()[3] = a3; + Index i = 4; + auto x = {(m_storage.data()[i++] = args, 0)...}; + static_cast(x); + } + + /** \brief Constructs a Matrix or Array and initializes it by elements given by an initializer list of initializer + * lists + */ + EIGEN_DEVICE_FUNC explicit constexpr EIGEN_STRONG_INLINE PlainObjectBase( + const std::initializer_list>& list) + : m_storage() { + size_t list_size = 0; + if (list.begin() != list.end()) { + list_size = list.begin()->size(); + } + + // This is to allow syntax like VectorXi {{1, 2, 3, 4}} + if (ColsAtCompileTime == 1 && list.size() == 1) { + eigen_assert(list_size == static_cast(RowsAtCompileTime) || RowsAtCompileTime == Dynamic); + resize(list_size, ColsAtCompileTime); + if (list.begin()->begin() != nullptr) { + Index index = 0; + for (const Scalar& e : *list.begin()) { + coeffRef(index++) = e; + } + } + } else { + eigen_assert(list.size() == static_cast(RowsAtCompileTime) || RowsAtCompileTime == Dynamic); + eigen_assert(list_size == static_cast(ColsAtCompileTime) || ColsAtCompileTime == Dynamic); + resize(list.size(), list_size); + + Index row_index = 0; + for (const std::initializer_list& row : list) { + eigen_assert(list_size == row.size()); + Index col_index = 0; + for (const Scalar& e : row) { + coeffRef(row_index, col_index) = e; + ++col_index; + } + ++row_index; + } + } + } + + /** \sa PlainObjectBase::operator=(const EigenBase&) */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase& other) : m_storage() { + resizeLike(other); + _set_noalias(other); + } + + /** \sa PlainObjectBase::operator=(const EigenBase&) */ + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase& other) : m_storage() { + resizeLike(other); + *this = other.derived(); + } + /** \brief Copy constructor with in-place evaluation */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const ReturnByValue& other) { + // FIXME this does not automatically transpose vectors if necessary + resize(other.rows(), other.cols()); + other.evalTo(this->derived()); + } + + public: + /** \brief Copies the generic expression \a other into *this. + * \copydetails DenseBase::operator=(const EigenBase &other) + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const EigenBase& other) { + _resize_to_match(other); + Base::operator=(other.derived()); + return this->derived(); + } + + /** \name Map + * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects, + * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned + * \a data pointers. + * + * Here is an example using strides: + * \include Matrix_Map_stride.cpp + * Output: \verbinclude Matrix_Map_stride.out + * + * \see class Map + */ + ///@{ + static inline ConstMapType Map(const Scalar* data) { return ConstMapType(data); } + static inline MapType Map(Scalar* data) { return MapType(data); } + static inline ConstMapType Map(const Scalar* data, Index size) { return ConstMapType(data, size); } + static inline MapType Map(Scalar* data, Index size) { return MapType(data, size); } + static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) { return ConstMapType(data, rows, cols); } + static inline MapType Map(Scalar* data, Index rows, Index cols) { return MapType(data, rows, cols); } + + static inline ConstAlignedMapType MapAligned(const Scalar* data) { return ConstAlignedMapType(data); } + static inline AlignedMapType MapAligned(Scalar* data) { return AlignedMapType(data); } + static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) { + return ConstAlignedMapType(data, size); + } + static inline AlignedMapType MapAligned(Scalar* data, Index size) { return AlignedMapType(data, size); } + static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) { + return ConstAlignedMapType(data, rows, cols); + } + static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) { + return AlignedMapType(data, rows, cols); + } + + template + static inline typename StridedConstMapType>::type Map(const Scalar* data, + const Stride& stride) { + return typename StridedConstMapType>::type(data, stride); + } + template + static inline typename StridedMapType>::type Map(Scalar* data, + const Stride& stride) { + return typename StridedMapType>::type(data, stride); + } + template + static inline typename StridedConstMapType>::type Map(const Scalar* data, Index size, + const Stride& stride) { + return typename StridedConstMapType>::type(data, size, stride); + } + template + static inline typename StridedMapType>::type Map(Scalar* data, Index size, + const Stride& stride) { + return typename StridedMapType>::type(data, size, stride); + } + template + static inline typename StridedConstMapType>::type Map(const Scalar* data, Index rows, Index cols, + const Stride& stride) { + return typename StridedConstMapType>::type(data, rows, cols, stride); + } + template + static inline typename StridedMapType>::type Map(Scalar* data, Index rows, Index cols, + const Stride& stride) { + return typename StridedMapType>::type(data, rows, cols, stride); + } + + template + static inline typename StridedConstAlignedMapType>::type MapAligned( + const Scalar* data, const Stride& stride) { + return typename StridedConstAlignedMapType>::type(data, stride); + } + template + static inline typename StridedAlignedMapType>::type MapAligned( + Scalar* data, const Stride& stride) { + return typename StridedAlignedMapType>::type(data, stride); + } + template + static inline typename StridedConstAlignedMapType>::type MapAligned( + const Scalar* data, Index size, const Stride& stride) { + return typename StridedConstAlignedMapType>::type(data, size, stride); + } + template + static inline typename StridedAlignedMapType>::type MapAligned( + Scalar* data, Index size, const Stride& stride) { + return typename StridedAlignedMapType>::type(data, size, stride); + } + template + static inline typename StridedConstAlignedMapType>::type MapAligned( + const Scalar* data, Index rows, Index cols, const Stride& stride) { + return typename StridedConstAlignedMapType>::type(data, rows, cols, stride); + } + template + static inline typename StridedAlignedMapType>::type MapAligned( + Scalar* data, Index rows, Index cols, const Stride& stride) { + return typename StridedAlignedMapType>::type(data, rows, cols, stride); + } + ///@} + + using Base::setConstant; + EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& val); + EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& val); + EIGEN_DEVICE_FUNC Derived& setConstant(NoChange_t, Index cols, const Scalar& val); + EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, NoChange_t, const Scalar& val); + + using Base::setZero; + EIGEN_DEVICE_FUNC Derived& setZero(Index size); + EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols); + EIGEN_DEVICE_FUNC Derived& setZero(NoChange_t, Index cols); + EIGEN_DEVICE_FUNC Derived& setZero(Index rows, NoChange_t); + + using Base::setOnes; + EIGEN_DEVICE_FUNC Derived& setOnes(Index size); + EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols); + EIGEN_DEVICE_FUNC Derived& setOnes(NoChange_t, Index cols); + EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, NoChange_t); + + using Base::setRandom; + Derived& setRandom(Index size); + Derived& setRandom(Index rows, Index cols); + Derived& setRandom(NoChange_t, Index cols); + Derived& setRandom(Index rows, NoChange_t); + +#ifdef EIGEN_PLAINOBJECTBASE_PLUGIN +#include EIGEN_PLAINOBJECTBASE_PLUGIN +#endif + + protected: + /** \internal Resizes *this in preparation for assigning \a other to it. + * Takes care of doing all the checking that's needed. + * + * Note that copying a row-vector into a vector (and conversely) is allowed. + * The resizing, if any, is then done in the appropriate way so that row-vectors + * remain row-vectors and vectors remain vectors. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase& other) { +#ifdef EIGEN_NO_AUTOMATIC_RESIZING + eigen_assert((this->size() == 0 || (IsVectorAtCompileTime ? (this->size() == other.size()) + : (rows() == other.rows() && cols() == other.cols()))) && + "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined"); + EIGEN_ONLY_USED_FOR_DEBUG(other); +#else + resizeLike(other); +#endif + } + + /** + * \brief Copies the value of the expression \a other into \c *this with automatic resizing. + * + * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), + * it will be initialized. + * + * Note that copying a row-vector into a vector (and conversely) is allowed. + * The resizing, if any, is then done in the appropriate way so that row-vectors + * remain row-vectors and vectors remain vectors. + * + * \sa operator=(const MatrixBase&), _set_noalias() + * + * \internal + */ + // aliasing is dealt once in internal::call_assignment + // so at this stage we have to assume aliasing... and resising has to be done later. + template + EIGEN_DEVICE_FUNC constexpr Derived& _set(const DenseBase& other) { + internal::call_assignment(this->derived(), other.derived()); + return this->derived(); + } + + /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which + * is the case when creating a new matrix) so one can enforce lazy evaluation. + * + * \sa operator=(const MatrixBase&), _set() + */ + template + EIGEN_DEVICE_FUNC constexpr Derived& _set_noalias(const DenseBase& other) { + // I don't think we need this resize call since the lazyAssign will anyways resize + // and lazyAssign will be called by the assign selector. + //_resize_to_match(other); + // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because + // it wouldn't allow to copy a row-vector into a column-vector. + internal::call_assignment_no_alias(this->derived(), other.derived(), + internal::assign_op()); + return this->derived(); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, + std::enable_if_t* = 0) { + EIGEN_STATIC_ASSERT(internal::is_valid_index_type::value && internal::is_valid_index_type::value, + T0 AND T1 MUST BE INTEGER TYPES) + resize(rows, cols); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init2(const T0& val0, const T1& val1, + std::enable_if_t* = 0) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) + m_storage.data()[0] = Scalar(val0); + m_storage.data()[1] = Scalar(val1); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init2( + const Index& val0, const Index& val1, + std::enable_if_t<(!internal::is_same::value) && (internal::is_same::value) && + (internal::is_same::value) && Base::SizeAtCompileTime == 2, + T1>* = 0) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) + m_storage.data()[0] = Scalar(val0); + m_storage.data()[1] = Scalar(val1); + } + + // The argument is convertible to the Index type and we either have a non 1x1 Matrix, or a dynamic-sized Array, + // then the argument is meant to be the size of the object. + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1( + Index size, + std::enable_if_t<(Base::SizeAtCompileTime != 1 || !internal::is_convertible::value) && + ((!internal::is_same::XprKind, ArrayXpr>::value || + Base::SizeAtCompileTime == Dynamic)), + T>* = 0) { + // NOTE MSVC 2008 complains if we directly put bool(NumTraits::IsInteger) as the EIGEN_STATIC_ASSERT argument. + const bool is_integer_alike = internal::is_valid_index_type::value; + EIGEN_UNUSED_VARIABLE(is_integer_alike); + EIGEN_STATIC_ASSERT(is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) + resize(size); + } + + // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar + // type can be implicitly converted) + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1( + const Scalar& val0, + std::enable_if_t::value, T>* = 0) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) + m_storage.data()[0] = val0; + } + + // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar + // type match the index type) + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1( + const Index& val0, + std::enable_if_t<(!internal::is_same::value) && (internal::is_same::value) && + Base::SizeAtCompileTime == 1 && internal::is_convertible::value, + T*>* = 0) { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) + m_storage.data()[0] = Scalar(val0); + } + + // Initialize a fixed size matrix from a pointer to raw data + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const Scalar* data) { + this->_set_noalias(ConstMapType(data)); + } + + // Initialize an arbitrary matrix from a dense expression + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const DenseBase& other) { + this->_set_noalias(other); + } + + // Initialize an arbitrary matrix from an object convertible to the Derived type. + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const Derived& other) { + this->_set_noalias(other); + } + + // Initialize an arbitrary matrix from a generic Eigen expression + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const EigenBase& other) { + this->derived() = other; + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const ReturnByValue& other) { + resize(other.rows(), other.cols()); + other.evalTo(this->derived()); + } + + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1(const RotationBase& r) { + this->derived() = r; + } + + // For fixed-size Array + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1( + const Scalar& val0, + std::enable_if_t::value && + internal::is_same::XprKind, ArrayXpr>::value, + T>* = 0) { + Base::setConstant(val0); + } + + // For fixed-size Array + template + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void _init1( + const Index& val0, + std::enable_if_t<(!internal::is_same::value) && (internal::is_same::value) && + Base::SizeAtCompileTime != Dynamic && Base::SizeAtCompileTime != 1 && + internal::is_convertible::value && + internal::is_same::XprKind, ArrayXpr>::value, + T*>* = 0) { + Base::setConstant(val0); + } + + template + friend struct internal::matrix_swap_impl; + + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal + * \brief Override DenseBase::swap() since for dynamic-sized matrices + * of same type it is enough to swap the data pointers. + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseBase& other) { + enum {SwapPointers = internal::is_same::value && Base::SizeAtCompileTime == Dynamic}; + internal::matrix_swap_impl::run(this->derived(), other.derived()); + } + + /** \internal + * \brief const version forwarded to DenseBase::swap + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseBase const& other) { + Base::swap(other.derived()); + } + + enum {IsPlainObjectBase = 1}; +#endif + public: + // These apparently need to be down here for nvcc+icc to prevent duplicate + // Map symbol. + template + friend class Eigen::Map; + friend class Eigen::Map; + friend class Eigen::Map; +#if EIGEN_MAX_ALIGN_BYTES > 0 + // for EIGEN_MAX_ALIGN_BYTES==0, AlignedMax==Unaligned, and many compilers generate warnings for friend-ing a class + // twice. + friend class Eigen::Map; + friend class Eigen::Map; +#endif +}; + +namespace internal { + +template +struct conservative_resize_like_impl { + static constexpr bool IsRelocatable = std::is_trivially_copyable::value; + static void run(DenseBase& _this, Index rows, Index cols) { + if (_this.rows() == rows && _this.cols() == cols) return; + EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) + + if (IsRelocatable && + ((Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows + (!Derived::IsRowMajor && _this.rows() == rows))) // column-major and we change only the number of columns + { +#ifndef EIGEN_NO_DEBUG + internal::check_rows_cols_for_overflow::run(rows, cols); +#endif + _this.derived().m_storage.conservativeResize(rows * cols, rows, cols); + } else { + // The storage order does not allow us to use reallocation. + Derived tmp(rows, cols); + const Index common_rows = numext::mini(rows, _this.rows()); + const Index common_cols = numext::mini(cols, _this.cols()); + tmp.block(0, 0, common_rows, common_cols) = _this.block(0, 0, common_rows, common_cols); + _this.derived().swap(tmp); + } + } + + static void run(DenseBase& _this, const DenseBase& other) { + if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; + + // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index), + // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the + // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or + // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like + // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good. + EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) + EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived) + + if (IsRelocatable && + ((Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows + (!Derived::IsRowMajor && + _this.rows() == other.rows()))) // column-major and we change only the number of columns + { + const Index new_rows = other.rows() - _this.rows(); + const Index new_cols = other.cols() - _this.cols(); + _this.derived().m_storage.conservativeResize(other.size(), other.rows(), other.cols()); + if (new_rows > 0) + _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); + else if (new_cols > 0) + _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); + } else { + // The storage order does not allow us to use reallocation. + Derived tmp(other); + const Index common_rows = numext::mini(tmp.rows(), _this.rows()); + const Index common_cols = numext::mini(tmp.cols(), _this.cols()); + tmp.block(0, 0, common_rows, common_cols) = _this.block(0, 0, common_rows, common_cols); + _this.derived().swap(tmp); + } + } +}; + +// Here, the specialization for vectors inherits from the general matrix case +// to allow calling .conservativeResize(rows,cols) on vectors. +template +struct conservative_resize_like_impl + : conservative_resize_like_impl { + typedef conservative_resize_like_impl Base; + using Base::IsRelocatable; + using Base::run; + + static void run(DenseBase& _this, Index size) { + const Index new_rows = Derived::RowsAtCompileTime == 1 ? 1 : size; + const Index new_cols = Derived::RowsAtCompileTime == 1 ? size : 1; + if (IsRelocatable) + _this.derived().m_storage.conservativeResize(size, new_rows, new_cols); + else + Base::run(_this.derived(), new_rows, new_cols); + } + + static void run(DenseBase& _this, const DenseBase& other) { + if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; + + const Index num_new_elements = other.size() - _this.size(); + + const Index new_rows = Derived::RowsAtCompileTime == 1 ? 1 : other.rows(); + const Index new_cols = Derived::RowsAtCompileTime == 1 ? other.cols() : 1; + if (IsRelocatable) + _this.derived().m_storage.conservativeResize(other.size(), new_rows, new_cols); + else + Base::run(_this.derived(), new_rows, new_cols); + + if (num_new_elements > 0) _this.tail(num_new_elements) = other.tail(num_new_elements); + } +}; + +template +struct matrix_swap_impl { + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(MatrixTypeA& a, MatrixTypeB& b) { a.base().swap(b); } +}; + +template +struct matrix_swap_impl { + EIGEN_DEVICE_FUNC static inline void run(MatrixTypeA& a, MatrixTypeB& b) { + static_cast(a).m_storage.swap(static_cast(b).m_storage); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_DENSESTORAGEBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Product.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Product.h new file mode 100644 index 0000000..bc8b9da --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Product.h @@ -0,0 +1,307 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PRODUCT_H +#define EIGEN_PRODUCT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +class ProductImpl; + +namespace internal { + +template +struct traits> { + typedef remove_all_t LhsCleaned; + typedef remove_all_t RhsCleaned; + typedef traits LhsTraits; + typedef traits RhsTraits; + + typedef MatrixXpr XprKind; + + typedef typename ScalarBinaryOpTraits::Scalar, + typename traits::Scalar>::ReturnType Scalar; + typedef typename product_promote_storage_type::ret>::ret StorageKind; + typedef typename promote_index_type::type + StorageIndex; + + enum { + RowsAtCompileTime = LhsTraits::RowsAtCompileTime, + ColsAtCompileTime = RhsTraits::ColsAtCompileTime, + MaxRowsAtCompileTime = LhsTraits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = RhsTraits::MaxColsAtCompileTime, + + // FIXME: only needed by GeneralMatrixMatrixTriangular + InnerSize = min_size_prefer_fixed(LhsTraits::ColsAtCompileTime, RhsTraits::RowsAtCompileTime), + + // The storage order is somewhat arbitrary here. The correct one will be determined through the evaluator. + Flags = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? RowMajorBit + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0 + : (((LhsTraits::Flags & NoPreferredStorageOrderBit) && (RhsTraits::Flags & RowMajorBit)) || + ((RhsTraits::Flags & NoPreferredStorageOrderBit) && (LhsTraits::Flags & RowMajorBit))) + ? RowMajorBit + : NoPreferredStorageOrderBit + }; +}; + +struct TransposeProductEnum { + // convenience enumerations to specialize transposed products + enum : int { + Default = 0x00, + Matrix = 0x01, + Permutation = 0x02, + MatrixMatrix = (Matrix << 8) | Matrix, + MatrixPermutation = (Matrix << 8) | Permutation, + PermutationMatrix = (Permutation << 8) | Matrix + }; +}; +template +struct TransposeKind { + static constexpr int Kind = is_matrix_base_xpr::value ? TransposeProductEnum::Matrix + : is_permutation_base_xpr::value ? TransposeProductEnum::Permutation + : TransposeProductEnum::Default; +}; + +template +struct TransposeProductKind { + static constexpr int Kind = (TransposeKind::Kind << 8) | TransposeKind::Kind; +}; + +template ::Kind> +struct product_transpose_helper { + // by default, don't optimize the transposed product + using Derived = Product; + using Scalar = typename Derived::Scalar; + using TransposeType = Transpose; + using ConjugateTransposeType = CwiseUnaryOp, TransposeType>; + using AdjointType = std::conditional_t::IsComplex, ConjugateTransposeType, TransposeType>; + + // return (lhs * rhs)^T + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) { + return TransposeType(derived); + } + // return (lhs * rhs)^H + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) { + return AdjointType(TransposeType(derived)); + } +}; + +template +struct product_transpose_helper { + // expand the transposed matrix-matrix product + using Derived = Product; + + using LhsScalar = typename traits::Scalar; + using LhsTransposeType = typename DenseBase::ConstTransposeReturnType; + using LhsConjugateTransposeType = CwiseUnaryOp, LhsTransposeType>; + using LhsAdjointType = + std::conditional_t::IsComplex, LhsConjugateTransposeType, LhsTransposeType>; + + using RhsScalar = typename traits::Scalar; + using RhsTransposeType = typename DenseBase::ConstTransposeReturnType; + using RhsConjugateTransposeType = CwiseUnaryOp, RhsTransposeType>; + using RhsAdjointType = + std::conditional_t::IsComplex, RhsConjugateTransposeType, RhsTransposeType>; + + using TransposeType = Product; + using AdjointType = Product; + + // return rhs^T * lhs^T + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) { + return TransposeType(RhsTransposeType(derived.rhs()), LhsTransposeType(derived.lhs())); + } + // return rhs^H * lhs^H + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) { + return AdjointType(RhsAdjointType(RhsTransposeType(derived.rhs())), + LhsAdjointType(LhsTransposeType(derived.lhs()))); + } +}; +template +struct product_transpose_helper { + // expand the transposed permutation-matrix product + using Derived = Product; + + using LhsInverseType = typename PermutationBase::InverseReturnType; + + using RhsScalar = typename traits::Scalar; + using RhsTransposeType = typename DenseBase::ConstTransposeReturnType; + using RhsConjugateTransposeType = CwiseUnaryOp, RhsTransposeType>; + using RhsAdjointType = + std::conditional_t::IsComplex, RhsConjugateTransposeType, RhsTransposeType>; + + using TransposeType = Product; + using AdjointType = Product; + + // return rhs^T * lhs^-1 + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) { + return TransposeType(RhsTransposeType(derived.rhs()), LhsInverseType(derived.lhs())); + } + // return rhs^H * lhs^-1 + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) { + return AdjointType(RhsAdjointType(RhsTransposeType(derived.rhs())), LhsInverseType(derived.lhs())); + } +}; +template +struct product_transpose_helper { + // expand the transposed matrix-permutation product + using Derived = Product; + + using LhsScalar = typename traits::Scalar; + using LhsTransposeType = typename DenseBase::ConstTransposeReturnType; + using LhsConjugateTransposeType = CwiseUnaryOp, LhsTransposeType>; + using LhsAdjointType = + std::conditional_t::IsComplex, LhsConjugateTransposeType, LhsTransposeType>; + + using RhsInverseType = typename PermutationBase::InverseReturnType; + + using TransposeType = Product; + using AdjointType = Product; + + // return rhs^-1 * lhs^T + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeType run_transpose(const Derived& derived) { + return TransposeType(RhsInverseType(derived.rhs()), LhsTransposeType(derived.lhs())); + } + // return rhs^-1 * lhs^H + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointType run_adjoint(const Derived& derived) { + return AdjointType(RhsInverseType(derived.rhs()), LhsAdjointType(LhsTransposeType(derived.lhs()))); + } +}; + +} // end namespace internal + +/** \class Product + * \ingroup Core_Module + * + * \brief Expression of the product of two arbitrary matrices or vectors + * + * \tparam Lhs_ the type of the left-hand side expression + * \tparam Rhs_ the type of the right-hand side expression + * + * This class represents an expression of the product of two arbitrary matrices. + * + * The other template parameters are: + * \tparam Option can be DefaultProduct, AliasFreeProduct, or LazyProduct + * + */ +template +class Product + : public ProductImpl::StorageKind, typename internal::traits::StorageKind, + internal::product_type::ret>::ret> { + public: + typedef Lhs_ Lhs; + typedef Rhs_ Rhs; + + typedef + typename ProductImpl::StorageKind, typename internal::traits::StorageKind, + internal::product_type::ret>::ret>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(Product) + + typedef typename internal::ref_selector::type LhsNested; + typedef typename internal::ref_selector::type RhsNested; + typedef internal::remove_all_t LhsNestedCleaned; + typedef internal::remove_all_t RhsNestedCleaned; + + using TransposeReturnType = typename internal::product_transpose_helper::TransposeType; + using AdjointReturnType = typename internal::product_transpose_helper::AdjointType; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) { + eigen_assert(lhs.cols() == rhs.rows() && "invalid matrix product" && + "if you wanted a coeff-wise or a dot product use the respective explicit functions"); + } + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_lhs.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_rhs.cols(); } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const LhsNestedCleaned& lhs() const { return m_lhs; } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const RhsNestedCleaned& rhs() const { return m_rhs; } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TransposeReturnType transpose() const { + return internal::product_transpose_helper::run_transpose(*this); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE AdjointReturnType adjoint() const { + return internal::product_transpose_helper::run_adjoint(*this); + } + + protected: + LhsNested m_lhs; + RhsNested m_rhs; +}; + +namespace internal { + +template ::ret> +class dense_product_base : public internal::dense_xpr_base>::type {}; + +/** Conversion to scalar for inner-products */ +template +class dense_product_base + : public internal::dense_xpr_base>::type { + typedef Product ProductXpr; + typedef typename internal::dense_xpr_base::type Base; + + public: + using Base::derived; + typedef typename Base::Scalar Scalar; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator const Scalar() const { + return internal::evaluator(derived()).coeff(0, 0); + } +}; + +} // namespace internal + +// Generic API dispatcher +template +class ProductImpl : public internal::generic_xpr_base, MatrixXpr, StorageKind>::type { + public: + typedef typename internal::generic_xpr_base, MatrixXpr, StorageKind>::type Base; +}; + +template +class ProductImpl : public internal::dense_product_base { + typedef Product Derived; + + public: + typedef typename internal::dense_product_base Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Derived) + protected: + enum { + IsOneByOne = (RowsAtCompileTime == 1 || RowsAtCompileTime == Dynamic) && + (ColsAtCompileTime == 1 || ColsAtCompileTime == Dynamic), + EnableCoeff = IsOneByOne || Option == LazyProduct + }; + + public: + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { + EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); + eigen_assert((Option == LazyProduct) || (this->rows() == 1 && this->cols() == 1)); + + return internal::evaluator(derived()).coeff(row, col); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const { + EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); + eigen_assert((Option == LazyProduct) || (this->rows() == 1 && this->cols() == 1)); + + return internal::evaluator(derived()).coeff(i); + } +}; + +} // end namespace Eigen + +#endif // EIGEN_PRODUCT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ProductEvaluators.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ProductEvaluators.h new file mode 100644 index 0000000..ae860e2 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ProductEvaluators.h @@ -0,0 +1,1275 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008-2010 Gael Guennebaud +// Copyright (C) 2011 Jitse Niesen +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PRODUCTEVALUATORS_H +#define EIGEN_PRODUCTEVALUATORS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/** \internal + * Evaluator of a product expression. + * Since products require special treatments to handle all possible cases, + * we simply defer the evaluation logic to a product_evaluator class + * which offers more partial specialization possibilities. + * + * \sa class product_evaluator + */ +template +struct evaluator> : public product_evaluator> { + typedef Product XprType; + typedef product_evaluator Base; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} +}; + +// Catch "scalar * ( A * B )" and transform it to "(A*scalar) * B" +// TODO: we should apply that rule only if that's really helpful +template +struct evaluator_assume_aliasing, + const CwiseNullaryOp, Plain1>, + const Product>> { + static const bool value = true; +}; +template +struct evaluator, + const CwiseNullaryOp, Plain1>, + const Product>> + : public evaluator> { + typedef CwiseBinaryOp, + const CwiseNullaryOp, Plain1>, + const Product> + XprType; + typedef evaluator> Base; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) + : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {} +}; + +template +struct evaluator, DiagIndex>> + : public evaluator, DiagIndex>> { + typedef Diagonal, DiagIndex> XprType; + typedef evaluator, DiagIndex>> Base; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) + : Base(Diagonal, DiagIndex>( + Product(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index())) {} +}; + +// Helper class to perform a matrix product with the destination at hand. +// Depending on the sizes of the factors, there are different evaluation strategies +// as controlled by internal::product_type. +template ::Shape, + typename RhsShape = typename evaluator_traits::Shape, + int ProductType = internal::product_type::value> +struct generic_product_impl; + +template +struct evaluator_assume_aliasing> { + static const bool value = true; +}; + +// This is the default evaluator implementation for products: +// It creates a temporary and call generic_product_impl +template +struct product_evaluator, ProductTag, LhsShape, RhsShape> + : public evaluator::PlainObject> { + typedef Product XprType; + typedef typename XprType::PlainObject PlainObject; + typedef evaluator Base; + enum { Flags = Base::Flags | EvalBeforeNestingBit }; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit product_evaluator(const XprType& xpr) + : m_result(xpr.rows(), xpr.cols()) { + internal::construct_at(this, m_result); + + // FIXME shall we handle nested_eval here?, + // if so, then we must take care at removing the call to nested_eval in the specializations (e.g., in + // permutation_matrix_product, transposition_matrix_product, etc.) + // typedef typename internal::nested_eval::type LhsNested; + // typedef typename internal::nested_eval::type RhsNested; + // typedef internal::remove_all_t LhsNestedCleaned; + // typedef internal::remove_all_t RhsNestedCleaned; + // + // const LhsNested lhs(xpr.lhs()); + // const RhsNested rhs(xpr.rhs()); + // + // generic_product_impl::evalTo(m_result, lhs, rhs); + + generic_product_impl::evalTo(m_result, xpr.lhs(), xpr.rhs()); + } + + protected: + PlainObject m_result; +}; + +// The following three shortcuts are enabled only if the scalar types match exactly. +// TODO: we could enable them for different scalar types when the product is not vectorized. + +// Dense = Product +template +struct Assignment, internal::assign_op, Dense2Dense, + std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> { + typedef Product SrcXprType; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const internal::assign_op&) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + // FIXME shall we handle nested_eval here? + generic_product_impl::evalTo(dst, src.lhs(), src.rhs()); + } +}; + +// Dense += Product +template +struct Assignment, internal::add_assign_op, Dense2Dense, + std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> { + typedef Product SrcXprType; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const internal::add_assign_op&) { + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + // FIXME shall we handle nested_eval here? + generic_product_impl::addTo(dst, src.lhs(), src.rhs()); + } +}; + +// Dense -= Product +template +struct Assignment, internal::sub_assign_op, Dense2Dense, + std::enable_if_t<(Options == DefaultProduct || Options == AliasFreeProduct)>> { + typedef Product SrcXprType; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const internal::sub_assign_op&) { + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + // FIXME shall we handle nested_eval here? + generic_product_impl::subTo(dst, src.lhs(), src.rhs()); + } +}; + +// Dense ?= scalar * Product +// TODO: we should apply that rule if that's really helpful +// for instance, this is not good for inner products +template +struct Assignment, + const CwiseNullaryOp, Plain>, + const Product>, + AssignFunc, Dense2Dense> { + typedef CwiseBinaryOp, + const CwiseNullaryOp, Plain>, + const Product> + SrcXprType; + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const AssignFunc& func) { + call_assignment_no_alias(dst, (src.lhs().functor().m_other * src.rhs().lhs()) * src.rhs().rhs(), func); + } +}; + +//---------------------------------------- +// Catch "Dense ?= xpr + Product<>" expression to save one temporary +// FIXME: consider enabling these rules for all product types, not only Dense and DefaultProduct. + +template +struct evaluator_assume_aliasing< + CwiseBinaryOp< + internal::scalar_sum_op::Scalar>, + const OtherXpr, const Product>, + DenseShape> { + static const bool value = true; +}; + +template +struct evaluator_assume_aliasing< + CwiseBinaryOp< + internal::scalar_difference_op::Scalar>, + const OtherXpr, const Product>, + DenseShape> { + static const bool value = true; +}; + +template +struct assignment_from_xpr_op_product { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType& dst, const SrcXprType& src, + const InitialFunc& /*func*/) { + call_assignment_no_alias(dst, src.lhs(), Func1()); + call_assignment_no_alias(dst, src.rhs(), Func2()); + } +}; + +#define EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(ASSIGN_OP, BINOP, ASSIGN_OP2) \ + template \ + struct Assignment, const OtherXpr, \ + const Product>, \ + internal::ASSIGN_OP, Dense2Dense> \ + : assignment_from_xpr_op_product, \ + internal::ASSIGN_OP, \ + internal::ASSIGN_OP2> {} + +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_sum_op, add_assign_op); +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_sum_op, add_assign_op); +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_sum_op, sub_assign_op); + +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(assign_op, scalar_difference_op, sub_assign_op); +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(add_assign_op, scalar_difference_op, sub_assign_op); +EIGEN_CATCH_ASSIGN_XPR_OP_PRODUCT(sub_assign_op, scalar_difference_op, add_assign_op); + +//---------------------------------------- + +template +struct generic_product_impl { + using impl = default_inner_product_impl; + template + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + dst.coeffRef(0, 0) = impl::run(lhs, rhs); + } + + template + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + dst.coeffRef(0, 0) += impl::run(lhs, rhs); + } + + template + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + dst.coeffRef(0, 0) -= impl::run(lhs, rhs); + } +}; + +/*********************************************************************** + * Implementation of outer dense * dense vector product + ***********************************************************************/ + +// Column major result +template +void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Func& func, + const false_type&) { + evaluator rhsEval(rhs); + ei_declare_local_nested_eval(Lhs, lhs, Rhs::SizeAtCompileTime, actual_lhs); + // FIXME if cols is large enough, then it might be useful to make sure that lhs is sequentially stored + // FIXME not very good if rhs is real and lhs complex while alpha is real too + const Index cols = dst.cols(); + for (Index j = 0; j < cols; ++j) func(dst.col(j), rhsEval.coeff(Index(0), j) * actual_lhs); +} + +// Row major result +template +void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Func& func, + const true_type&) { + evaluator lhsEval(lhs); + ei_declare_local_nested_eval(Rhs, rhs, Lhs::SizeAtCompileTime, actual_rhs); + // FIXME if rows is large enough, then it might be useful to make sure that rhs is sequentially stored + // FIXME not very good if lhs is real and rhs complex while alpha is real too + const Index rows = dst.rows(); + for (Index i = 0; i < rows; ++i) func(dst.row(i), lhsEval.coeff(i, Index(0)) * actual_rhs); +} + +template +struct generic_product_impl { + template + struct is_row_major : bool_constant<(int(T::Flags) & RowMajorBit)> {}; + typedef typename Product::Scalar Scalar; + + // TODO: it would be nice to be able to exploit our *_assign_op functors for that purpose + struct set { + template + EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { + dst.const_cast_derived() = src; + } + }; + struct add { + /** Add to dst. */ + template + EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { + dst.const_cast_derived() += src; + } + }; + struct sub { + template + EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { + dst.const_cast_derived() -= src; + } + }; + /** Scaled add. */ + struct adds { + Scalar m_scale; + /** Constructor */ + explicit adds(const Scalar& s) : m_scale(s) {} + /** Scaled add to dst. */ + template + void EIGEN_DEVICE_FUNC operator()(const Dst& dst, const Src& src) const { + dst.const_cast_derived() += m_scale * src; + } + }; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major()); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major()); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major()); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, + const Scalar& alpha) { + internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major()); + } +}; + +// This base class provides default implementations for evalTo, addTo, subTo, in terms of scaleAndAddTo +template +struct generic_product_impl_base { + typedef typename Product::Scalar Scalar; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + dst.setZero(); + scaleAndAddTo(dst, lhs, rhs, Scalar(1)); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + scaleAndAddTo(dst, lhs, rhs, Scalar(1)); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + scaleAndAddTo(dst, lhs, rhs, Scalar(-1)); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, + const Scalar& alpha) { + Derived::scaleAndAddTo(dst, lhs, rhs, alpha); + } +}; + +template +struct generic_product_impl + : generic_product_impl_base> { + typedef typename nested_eval::type LhsNested; + typedef typename nested_eval::type RhsNested; + typedef typename Product::Scalar Scalar; + enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight }; + typedef internal::remove_all_t> MatrixType; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, + const Scalar& alpha) { + // Fallback to inner product if both the lhs and rhs is a runtime vector. + if (lhs.rows() == 1 && rhs.cols() == 1) { + dst.coeffRef(0, 0) += alpha * lhs.row(0).conjugate().dot(rhs.col(0)); + return; + } + LhsNested actual_lhs(lhs); + RhsNested actual_rhs(rhs); + internal::gemv_dense_selector::HasUsableDirectAccess)>::run(actual_lhs, + actual_rhs, dst, + alpha); + } +}; + +template +struct generic_product_impl { + typedef typename Product::Scalar Scalar; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + // Same as: dst.noalias() = lhs.lazyProduct(rhs); + // but easier on the compiler side + call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op()); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + // dst.noalias() += lhs.lazyProduct(rhs); + call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::add_assign_op()); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { + // dst.noalias() -= lhs.lazyProduct(rhs); + call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::sub_assign_op()); + } + + // This is a special evaluation path called from generic_product_impl<...,GemmProduct> in file GeneralMatrixMatrix.h + // This variant tries to extract scalar multiples from both the LHS and RHS and factor them out. For instance: + // dst {,+,-}= (s1*A)*(B*s2) + // will be rewritten as: + // dst {,+,-}= (s1*s2) * (A.lazyProduct(B)) + // There are at least four benefits of doing so: + // 1 - huge performance gain for heap-allocated matrix types as it save costly allocations. + // 2 - it is faster than simply by-passing the heap allocation through stack allocation. + // 3 - it makes this fallback consistent with the heavy GEMM routine. + // 4 - it fully by-passes huge stack allocation attempts when multiplying huge fixed-size matrices. + // (see https://stackoverflow.com/questions/54738495) + // For small fixed sizes matrices, however, the gains are less obvious, it is sometimes x2 faster, but sometimes x3 + // slower, and the behavior depends also a lot on the compiler... This is why this re-writing strategy is currently + // enabled only when falling back from the main GEMM. + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eval_dynamic(Dst& dst, const Lhs& lhs, const Rhs& rhs, + const Func& func) { + enum { + HasScalarFactor = blas_traits::HasScalarFactor || blas_traits::HasScalarFactor, + ConjLhs = blas_traits::NeedToConjugate, + ConjRhs = blas_traits::NeedToConjugate + }; + // FIXME: in c++11 this should be auto, and extractScalarFactor should also return auto + // this is important for real*complex_mat + Scalar actualAlpha = combine_scalar_factors(lhs, rhs); + + eval_dynamic_impl(dst, blas_traits::extract(lhs).template conjugateIf(), + blas_traits::extract(rhs).template conjugateIf(), func, actualAlpha, + bool_constant()); + } + + protected: + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eval_dynamic_impl(Dst& dst, const LhsT& lhs, const RhsT& rhs, + const Func& func, const Scalar& s /* == 1 */, + false_type) { + EIGEN_UNUSED_VARIABLE(s); + eigen_internal_assert(numext::is_exactly_one(s)); + call_restricted_packet_assignment_no_alias(dst, lhs.lazyProduct(rhs), func); + } + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eval_dynamic_impl(Dst& dst, const LhsT& lhs, const RhsT& rhs, + const Func& func, const Scalar& s, true_type) { + call_restricted_packet_assignment_no_alias(dst, s * lhs.lazyProduct(rhs), func); + } +}; + +// This specialization enforces the use of a coefficient-based evaluation strategy +template +struct generic_product_impl + : generic_product_impl {}; + +// Case 2: Evaluate coeff by coeff +// +// This is mostly taken from CoeffBasedProduct.h +// The main difference is that we add an extra argument to the etor_product_*_impl::run() function +// for the inner dimension of the product, because evaluator object do not know their size. + +template +struct etor_product_coeff_impl; + +template +struct etor_product_packet_impl; + +template +struct product_evaluator, ProductTag, DenseShape, DenseShape> + : evaluator_base> { + typedef Product XprType; + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit product_evaluator(const XprType& xpr) + : m_lhs(xpr.lhs()), + m_rhs(xpr.rhs()), + m_lhsImpl(m_lhs), // FIXME the creation of the evaluator objects should result in a no-op, but check that! + m_rhsImpl(m_rhs), // Moreover, they are only useful for the packet path, so we could completely disable + // them when not needed, or perhaps declare them on the fly on the packet method... We + // have experiment to check what's best. + m_innerDim(xpr.lhs().cols()) { + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::MulCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::AddCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + // Everything below here is taken from CoeffBasedProduct.h + + typedef typename internal::nested_eval::type LhsNested; + typedef typename internal::nested_eval::type RhsNested; + + typedef internal::remove_all_t LhsNestedCleaned; + typedef internal::remove_all_t RhsNestedCleaned; + + typedef evaluator LhsEtorType; + typedef evaluator RhsEtorType; + + enum { + RowsAtCompileTime = LhsNestedCleaned::RowsAtCompileTime, + ColsAtCompileTime = RhsNestedCleaned::ColsAtCompileTime, + InnerSize = min_size_prefer_fixed(LhsNestedCleaned::ColsAtCompileTime, RhsNestedCleaned::RowsAtCompileTime), + MaxRowsAtCompileTime = LhsNestedCleaned::MaxRowsAtCompileTime, + MaxColsAtCompileTime = RhsNestedCleaned::MaxColsAtCompileTime + }; + + typedef typename find_best_packet::type LhsVecPacketType; + typedef typename find_best_packet::type RhsVecPacketType; + + enum { + + LhsCoeffReadCost = LhsEtorType::CoeffReadCost, + RhsCoeffReadCost = RhsEtorType::CoeffReadCost, + CoeffReadCost = InnerSize == 0 ? NumTraits::ReadCost + : InnerSize == Dynamic + ? HugeCost + : InnerSize * (NumTraits::MulCost + int(LhsCoeffReadCost) + int(RhsCoeffReadCost)) + + (InnerSize - 1) * NumTraits::AddCost, + + Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT, + + LhsFlags = LhsEtorType::Flags, + RhsFlags = RhsEtorType::Flags, + + LhsRowMajor = LhsFlags & RowMajorBit, + RhsRowMajor = RhsFlags & RowMajorBit, + + LhsVecPacketSize = unpacket_traits::size, + RhsVecPacketSize = unpacket_traits::size, + + // Here, we don't care about alignment larger than the usable packet size. + LhsAlignment = + plain_enum_min(LhsEtorType::Alignment, LhsVecPacketSize* int(sizeof(typename LhsNestedCleaned::Scalar))), + RhsAlignment = + plain_enum_min(RhsEtorType::Alignment, RhsVecPacketSize* int(sizeof(typename RhsNestedCleaned::Scalar))), + + SameType = is_same::value, + + CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit) && (ColsAtCompileTime != 1), + CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit) && (RowsAtCompileTime != 1), + + EvalToRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1) ? 1 + : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) + ? 0 + : (bool(RhsRowMajor) && !CanVectorizeLhs), + + Flags = ((int(LhsFlags) | int(RhsFlags)) & HereditaryBits & ~RowMajorBit) | + (EvalToRowMajor ? RowMajorBit : 0) + // TODO: enable vectorization for mixed types + | (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0) | + (XprType::IsVectorAtCompileTime ? LinearAccessBit : 0), + + LhsOuterStrideBytes = + int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename LhsNestedCleaned::Scalar)), + RhsOuterStrideBytes = + int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename RhsNestedCleaned::Scalar)), + + Alignment = bool(CanVectorizeLhs) + ? (LhsOuterStrideBytes <= 0 || (int(LhsOuterStrideBytes) % plain_enum_max(1, LhsAlignment)) != 0 + ? 0 + : LhsAlignment) + : bool(CanVectorizeRhs) + ? (RhsOuterStrideBytes <= 0 || (int(RhsOuterStrideBytes) % plain_enum_max(1, RhsAlignment)) != 0 + ? 0 + : RhsAlignment) + : 0, + + /* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside + * of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner + * loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect + * the Flags, it is safe to make this value depend on ActualPacketAccessBit, that doesn't affect the ABI. + */ + CanVectorizeInner = SameType && LhsRowMajor && (!RhsRowMajor) && + (int(LhsFlags) & int(RhsFlags) & ActualPacketAccessBit) && + (int(InnerSize) % packet_traits::size == 0) + }; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const { + return (m_lhs.row(row).transpose().cwiseProduct(m_rhs.col(col))).sum(); + } + + /* Allow index-based non-packet access. It is impossible though to allow index-based packed access, + * which is why we don't set the LinearAccessBit. + * TODO: this seems possible when the result is a vector + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index index) const { + const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index; + const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0; + return (m_lhs.row(row).transpose().cwiseProduct(m_rhs.col(col))).sum(); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packet(Index row, Index col) const { + PacketType res; + typedef etor_product_packet_impl + PacketImpl; + PacketImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res); + return res; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packet(Index index) const { + const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index; + const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0; + return packet(row, col); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetSegment(Index row, Index col, Index begin, + Index count) const { + PacketType res; + typedef etor_product_packet_impl + PacketImpl; + PacketImpl::run_segment(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res, begin, count); + return res; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetSegment(Index index, Index begin, Index count) const { + const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? 0 : index; + const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime == 1) ? index : 0; + return packetSegment(row, col, begin, count); + } + + protected: + add_const_on_value_type_t m_lhs; + add_const_on_value_type_t m_rhs; + + LhsEtorType m_lhsImpl; + RhsEtorType m_rhsImpl; + + // TODO: Get rid of m_innerDim if known at compile time + Index m_innerDim; +}; + +template +struct product_evaluator, LazyCoeffBasedProductMode, DenseShape, DenseShape> + : product_evaluator, CoeffBasedProductMode, DenseShape, DenseShape> { + typedef Product XprType; + typedef Product BaseProduct; + typedef product_evaluator Base; + enum { Flags = Base::Flags | EvalBeforeNestingBit }; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit product_evaluator(const XprType& xpr) + : Base(BaseProduct(xpr.lhs(), xpr.rhs())) {} +}; + +/**************************************** +*** Coeff based product, Packet path *** +****************************************/ + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res) { + etor_product_packet_impl::run(row, col, lhs, rhs, + innerDim, res); + res = pmadd(pset1(lhs.coeff(row, Index(UnrollingIndex - 1))), + rhs.template packet(Index(UnrollingIndex - 1), col), res); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res, Index begin, Index count) { + etor_product_packet_impl::run_segment( + row, col, lhs, rhs, innerDim, res, begin, count); + res = pmadd(pset1(lhs.coeff(row, Index(UnrollingIndex - 1))), + rhs.template packetSegment(Index(UnrollingIndex - 1), col, begin, count), res); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res) { + etor_product_packet_impl::run(row, col, lhs, rhs, + innerDim, res); + res = pmadd(lhs.template packet(row, Index(UnrollingIndex - 1)), + pset1(rhs.coeff(Index(UnrollingIndex - 1), col)), res); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res, Index begin, Index count) { + etor_product_packet_impl::run_segment( + row, col, lhs, rhs, innerDim, res, begin, count); + res = pmadd(lhs.template packetSegment(row, Index(UnrollingIndex - 1), begin, count), + pset1(rhs.coeff(Index(UnrollingIndex - 1), col)), res); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index /*innerDim*/, Packet& res) { + res = pmul(pset1(lhs.coeff(row, Index(0))), rhs.template packet(Index(0), col)); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index /*innerDim*/, Packet& res, Index begin, + Index count) { + res = pmul(pset1(lhs.coeff(row, Index(0))), + rhs.template packetSegment(Index(0), col, begin, count)); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index /*innerDim*/, Packet& res) { + res = pmul(lhs.template packet(row, Index(0)), pset1(rhs.coeff(Index(0), col))); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index /*innerDim*/, Packet& res, Index begin, + Index count) { + res = pmul(lhs.template packetSegment(row, Index(0), begin, count), + pset1(rhs.coeff(Index(0), col))); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, + const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res) { + res = pset1(typename unpacket_traits::type(0)); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, + const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res, + Index /*begin*/, Index /*count*/) { + res = pset1(typename unpacket_traits::type(0)); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, + const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res) { + res = pset1(typename unpacket_traits::type(0)); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, + const Rhs& /*rhs*/, Index /*innerDim*/, Packet& res, + Index /*begin*/, Index /*count*/) { + res = pset1(typename unpacket_traits::type(0)); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res) { + res = pset1(typename unpacket_traits::type(0)); + for (Index i = 0; i < innerDim; ++i) + res = pmadd(pset1(lhs.coeff(row, i)), rhs.template packet(i, col), res); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res, Index begin, Index count) { + res = pset1(typename unpacket_traits::type(0)); + for (Index i = 0; i < innerDim; ++i) + res = pmadd(pset1(lhs.coeff(row, i)), rhs.template packetSegment(i, col, begin, count), + res); + } +}; + +template +struct etor_product_packet_impl { + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res) { + res = pset1(typename unpacket_traits::type(0)); + for (Index i = 0; i < innerDim; ++i) + res = pmadd(lhs.template packet(row, i), pset1(rhs.coeff(i, col)), res); + } + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run_segment(Index row, Index col, const Lhs& lhs, const Rhs& rhs, + Index innerDim, Packet& res, Index begin, Index count) { + res = pset1(typename unpacket_traits::type(0)); + for (Index i = 0; i < innerDim; ++i) + res = pmadd(lhs.template packetSegment(row, i, begin, count), pset1(rhs.coeff(i, col)), + res); + } +}; + +/*************************************************************************** + * Triangular products + ***************************************************************************/ +template +struct triangular_product_impl; + +template +struct generic_product_impl + : generic_product_impl_base> { + typedef typename Product::Scalar Scalar; + + template + static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { + triangular_product_impl::run( + dst, lhs.nestedExpression(), rhs, alpha); + } +}; + +template +struct generic_product_impl + : generic_product_impl_base> { + typedef typename Product::Scalar Scalar; + + template + static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { + triangular_product_impl::run( + dst, lhs, rhs.nestedExpression(), alpha); + } +}; + +/*************************************************************************** + * SelfAdjoint products + ***************************************************************************/ +template +struct selfadjoint_product_impl; + +template +struct generic_product_impl + : generic_product_impl_base> { + typedef typename Product::Scalar Scalar; + + template + static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { + selfadjoint_product_impl::run( + dst, lhs.nestedExpression(), rhs, alpha); + } +}; + +template +struct generic_product_impl + : generic_product_impl_base> { + typedef typename Product::Scalar Scalar; + + template + static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { + selfadjoint_product_impl::run( + dst, lhs, rhs.nestedExpression(), alpha); + } +}; + +/*************************************************************************** + * Diagonal products + ***************************************************************************/ + +template +struct diagonal_product_evaluator_base : evaluator_base { + typedef typename ScalarBinaryOpTraits::ReturnType Scalar; + + public: + enum { + CoeffReadCost = int(NumTraits::MulCost) + int(evaluator::CoeffReadCost) + + int(evaluator::CoeffReadCost), + + MatrixFlags = evaluator::Flags, + DiagFlags = evaluator::Flags, + + StorageOrder_ = (Derived::MaxRowsAtCompileTime == 1 && Derived::MaxColsAtCompileTime != 1) ? RowMajor + : (Derived::MaxColsAtCompileTime == 1 && Derived::MaxRowsAtCompileTime != 1) ? ColMajor + : MatrixFlags & RowMajorBit ? RowMajor + : ColMajor, + SameStorageOrder_ = int(StorageOrder_) == ((MatrixFlags & RowMajorBit) ? RowMajor : ColMajor), + + ScalarAccessOnDiag_ = !((int(StorageOrder_) == ColMajor && int(ProductOrder) == OnTheLeft) || + (int(StorageOrder_) == RowMajor && int(ProductOrder) == OnTheRight)), + SameTypes_ = is_same::value, + // FIXME currently we need same types, but in the future the next rule should be the one + // Vectorizable_ = bool(int(MatrixFlags)&PacketAccessBit) && ((!_PacketOnDiag) || (SameTypes_ && + // bool(int(DiagFlags)&PacketAccessBit))), + Vectorizable_ = bool(int(MatrixFlags) & PacketAccessBit) && SameTypes_ && + (SameStorageOrder_ || (MatrixFlags & LinearAccessBit) == LinearAccessBit) && + (ScalarAccessOnDiag_ || (bool(int(DiagFlags) & PacketAccessBit))), + LinearAccessMask_ = + (MatrixType::RowsAtCompileTime == 1 || MatrixType::ColsAtCompileTime == 1) ? LinearAccessBit : 0, + Flags = + ((HereditaryBits | LinearAccessMask_) & (unsigned int)(MatrixFlags)) | (Vectorizable_ ? PacketAccessBit : 0), + Alignment = evaluator::Alignment, + + AsScalarProduct = + (DiagonalType::SizeAtCompileTime == 1) || + (DiagonalType::SizeAtCompileTime == Dynamic && MatrixType::RowsAtCompileTime == 1 && + ProductOrder == OnTheLeft) || + (DiagonalType::SizeAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == 1 && ProductOrder == OnTheRight) + }; + + EIGEN_DEVICE_FUNC diagonal_product_evaluator_base(const MatrixType& mat, const DiagonalType& diag) + : m_diagImpl(diag), m_matImpl(mat) { + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::MulCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const { + if (AsScalarProduct) + return m_diagImpl.coeff(0) * m_matImpl.coeff(idx); + else + return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); + } + + protected: + template + EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index id, internal::true_type) const { + return internal::pmul(m_matImpl.template packet(row, col), + internal::pset1(m_diagImpl.coeff(id))); + } + + template + EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index id, internal::false_type) const { + enum { + InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime, + DiagonalPacketLoadMode = plain_enum_min( + LoadMode, + ((InnerSize % 16) == 0) ? int(Aligned16) : int(evaluator::Alignment)) // FIXME hardcoded 16!! + }; + return internal::pmul(m_matImpl.template packet(row, col), + m_diagImpl.template packet(id)); + } + + template + EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index id, Index begin, Index count, + internal::true_type) const { + return internal::pmul(m_matImpl.template packetSegment(row, col, begin, count), + internal::pset1(m_diagImpl.coeff(id))); + } + + template + EIGEN_STRONG_INLINE PacketType packet_segment_impl(Index row, Index col, Index id, Index begin, Index count, + internal::false_type) const { + enum { + InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime, + DiagonalPacketLoadMode = plain_enum_min( + LoadMode, + ((InnerSize % 16) == 0) ? int(Aligned16) : int(evaluator::Alignment)) // FIXME hardcoded 16!! + }; + return internal::pmul(m_matImpl.template packetSegment(row, col, begin, count), + m_diagImpl.template packetSegment(id, begin, count)); + } + + evaluator m_diagImpl; + evaluator m_matImpl; +}; + +// diagonal * dense +template +struct product_evaluator, ProductTag, DiagonalShape, DenseShape> + : diagonal_product_evaluator_base, + OnTheLeft> { + typedef diagonal_product_evaluator_base, + OnTheLeft> + Base; + using Base::coeff; + using Base::m_diagImpl; + using Base::m_matImpl; + typedef typename Base::Scalar Scalar; + + typedef Product XprType; + typedef typename XprType::PlainObject PlainObject; + typedef typename Lhs::DiagonalVectorType DiagonalType; + + static constexpr int StorageOrder = Base::StorageOrder_; + using IsRowMajor_t = bool_constant; + + EIGEN_DEVICE_FUNC constexpr explicit product_evaluator(const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {} + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const { + return m_diagImpl.coeff(row) * m_matImpl.coeff(row, col); + } + +#ifndef EIGEN_GPUCC + template + EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + // FIXME: NVCC used to complain about the template keyword, but we have to check whether this is still the case. + // See also similar calls below. + return this->template packet_impl(row, col, row, IsRowMajor_t()); + } + + template + EIGEN_STRONG_INLINE PacketType packet(Index idx) const { + return packet(int(StorageOrder) == ColMajor ? idx : 0, + int(StorageOrder) == ColMajor ? 0 : idx); + } + + template + EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + // FIXME: NVCC used to complain about the template keyword, but we have to check whether this is still the case. + // See also similar calls below. + return this->template packet_segment_impl(row, col, row, begin, count, IsRowMajor_t()); + } + + template + EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count) const { + return packetSegment(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx, + begin, count); + } +#endif +}; + +// dense * diagonal +template +struct product_evaluator, ProductTag, DenseShape, DiagonalShape> + : diagonal_product_evaluator_base, + OnTheRight> { + typedef diagonal_product_evaluator_base, + OnTheRight> + Base; + using Base::coeff; + using Base::m_diagImpl; + using Base::m_matImpl; + typedef typename Base::Scalar Scalar; + + typedef Product XprType; + typedef typename XprType::PlainObject PlainObject; + + static constexpr int StorageOrder = Base::StorageOrder_; + using IsColMajor_t = bool_constant; + + EIGEN_DEVICE_FUNC constexpr explicit product_evaluator(const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal()) {} + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const { + return m_matImpl.coeff(row, col) * m_diagImpl.coeff(col); + } + +#ifndef EIGEN_GPUCC + template + EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + return this->template packet_impl(row, col, col, IsColMajor_t()); + } + + template + EIGEN_STRONG_INLINE PacketType packet(Index idx) const { + return packet(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx); + } + + template + EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + return this->template packet_segment_impl(row, col, col, begin, count, IsColMajor_t()); + } + + template + EIGEN_STRONG_INLINE PacketType packetSegment(Index idx, Index begin, Index count) const { + return packetSegment(StorageOrder == ColMajor ? idx : 0, StorageOrder == ColMajor ? 0 : idx, + begin, count); + } +#endif +}; + +/*************************************************************************** + * Products with permutation matrices + ***************************************************************************/ + +/** \internal + * \class permutation_matrix_product + * Internal helper class implementing the product between a permutation matrix and a matrix. + * This class is specialized for DenseShape below and for SparseShape in SparseCore/SparsePermutation.h + */ +template +struct permutation_matrix_product; + +template +struct permutation_matrix_product { + typedef typename nested_eval::type MatrixType; + typedef remove_all_t MatrixTypeCleaned; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Dest& dst, const PermutationType& perm, + const ExpressionType& xpr) { + MatrixType mat(xpr); + const Index n = Side == OnTheLeft ? mat.rows() : mat.cols(); + // FIXME we need an is_same for expression that is not sensitive to constness. For instance + // is_same_xpr, Block >::value should be true. + // if(is_same::value && extract_data(dst) == extract_data(mat)) + if (is_same_dense(dst, mat)) { + // apply the permutation inplace + Matrix mask(perm.size()); + mask.fill(false); + Index r = 0; + while (r < perm.size()) { + // search for the next seed + while (r < perm.size() && mask[r]) r++; + if (r >= perm.size()) break; + // we got one, let's follow it until we are back to the seed + Index k0 = r++; + Index kPrev = k0; + mask.coeffRef(k0) = true; + for (Index k = perm.indices().coeff(k0); k != k0; k = perm.indices().coeff(k)) { + Block(dst, k) + .swap(Block < Dest, Side == OnTheLeft ? 1 : Dest::RowsAtCompileTime, + Side == OnTheRight + ? 1 + : Dest::ColsAtCompileTime > (dst, ((Side == OnTheLeft) ^ Transposed) ? k0 : kPrev)); + + mask.coeffRef(k) = true; + kPrev = k; + } + } + } else { + for (Index i = 0; i < n; ++i) { + Block( + dst, ((Side == OnTheLeft) ^ Transposed) ? perm.indices().coeff(i) : i) + + = + + Block < const MatrixTypeCleaned, + Side == OnTheLeft ? 1 : MatrixTypeCleaned::RowsAtCompileTime, + Side == OnTheRight ? 1 + : MatrixTypeCleaned::ColsAtCompileTime > + (mat, ((Side == OnTheRight) ^ Transposed) ? perm.indices().coeff(i) : i); + } + } + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + permutation_matrix_product::run(dst, lhs, rhs); + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + permutation_matrix_product::run(dst, rhs, lhs); + } +}; + +template +struct generic_product_impl, Rhs, PermutationShape, MatrixShape, ProductTag> { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Inverse& lhs, const Rhs& rhs) { + permutation_matrix_product::run(dst, lhs.nestedExpression(), rhs); + } +}; + +template +struct generic_product_impl, MatrixShape, PermutationShape, ProductTag> { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Inverse& rhs) { + permutation_matrix_product::run(dst, rhs.nestedExpression(), lhs); + } +}; + +/*************************************************************************** + * Products with transpositions matrices + ***************************************************************************/ + +// FIXME: consider unifying Transpositions and Permutation into a single shape. + +/** \internal + * \class transposition_matrix_product + * Internal helper class implementing the product between a permutation matrix and a matrix. + */ +template +struct transposition_matrix_product { + typedef typename nested_eval::type MatrixType; + typedef remove_all_t MatrixTypeCleaned; + + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Dest& dst, const TranspositionType& tr, + const ExpressionType& xpr) { + MatrixType mat(xpr); + typedef typename TranspositionType::StorageIndex StorageIndex; + const Index size = tr.size(); + StorageIndex j = 0; + + if (!is_same_dense(dst, mat)) dst = mat; + + for (Index k = (Transposed ? size - 1 : 0); Transposed ? k >= 0 : k < size; Transposed ? --k : ++k) + if (Index(j = tr.coeff(k)) != k) { + if (Side == OnTheLeft) + dst.row(k).swap(dst.row(j)); + else if (Side == OnTheRight) + dst.col(k).swap(dst.col(j)); + } + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + transposition_matrix_product::run(dst, lhs, rhs); + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + transposition_matrix_product::run(dst, rhs, lhs); + } +}; + +template +struct generic_product_impl, Rhs, TranspositionsShape, MatrixShape, ProductTag> { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Transpose& lhs, const Rhs& rhs) { + transposition_matrix_product::run(dst, lhs.nestedExpression(), rhs); + } +}; + +template +struct generic_product_impl, MatrixShape, TranspositionsShape, ProductTag> { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Transpose& rhs) { + transposition_matrix_product::run(dst, rhs.nestedExpression(), lhs); + } +}; + +/*************************************************************************** + * skew symmetric products + * for now we just call the generic implementation + ***************************************************************************/ +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + generic_product_impl::evalTo(dst, lhs, + rhs); + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + generic_product_impl::evalTo(dst, lhs, + rhs); + } +}; + +template +struct generic_product_impl { + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { + generic_product_impl::evalTo(dst, lhs, rhs); + } +}; + +template +struct generic_product_impl + : generic_product_impl {}; + +template +struct generic_product_impl + : generic_product_impl {}; + +template +struct generic_product_impl + : generic_product_impl {}; + +template +struct generic_product_impl + : generic_product_impl {}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PRODUCT_EVALUATORS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Random.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Random.h new file mode 100644 index 0000000..532ca0e --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Random.h @@ -0,0 +1,207 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_RANDOM_H +#define EIGEN_RANDOM_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct scalar_random_op { + inline Scalar operator()() const { return random(); } +}; + +template +struct functor_traits > { + enum { Cost = 5 * NumTraits::MulCost, PacketAccess = false, IsRepeatable = false }; +}; + +} // end namespace internal + +/** \returns a random matrix expression + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * The parameters \a rows and \a cols are the number of rows and of columns of + * the returned matrix. Must be compatible with this MatrixBase type. + * + * \not_reentrant + * + * This variant is meant to be used for dynamic-size matrix types. For fixed-size types, + * it is redundant to pass \a rows and \a cols as arguments, so Random() should be used + * instead. + * + * + * Example: \include MatrixBase_random_int_int.cpp + * Output: \verbinclude MatrixBase_random_int_int.out + * + * This expression has the "evaluate before nesting" flag so that it will be evaluated into + * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected + * behavior with expressions involving random matrices. + * + * See DenseBase::NullaryExpr(Index, const CustomNullaryOp&) for an example using C++11 random generators. + * + * \sa DenseBase::setRandom(), DenseBase::Random(Index), DenseBase::Random() + */ +template +inline const typename DenseBase::RandomReturnType DenseBase::Random(Index rows, Index cols) { + return NullaryExpr(rows, cols, internal::scalar_random_op()); +} + +/** \returns a random vector expression + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * The parameter \a size is the size of the returned vector. + * Must be compatible with this MatrixBase type. + * + * \only_for_vectors + * \not_reentrant + * + * This variant is meant to be used for dynamic-size vector types. For fixed-size types, + * it is redundant to pass \a size as argument, so Random() should be used + * instead. + * + * Example: \include MatrixBase_random_int.cpp + * Output: \verbinclude MatrixBase_random_int.out + * + * This expression has the "evaluate before nesting" flag so that it will be evaluated into + * a temporary vector whenever it is nested in a larger expression. This prevents unexpected + * behavior with expressions involving random matrices. + * + * \sa DenseBase::setRandom(), DenseBase::Random(Index,Index), DenseBase::Random() + */ +template +inline const typename DenseBase::RandomReturnType DenseBase::Random(Index size) { + return NullaryExpr(size, internal::scalar_random_op()); +} + +/** \returns a fixed-size random matrix or vector expression + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you + * need to use the variants taking size arguments. + * + * Example: \include MatrixBase_random.cpp + * Output: \verbinclude MatrixBase_random.out + * + * This expression has the "evaluate before nesting" flag so that it will be evaluated into + * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected + * behavior with expressions involving random matrices. + * + * \not_reentrant + * + * \sa DenseBase::setRandom(), DenseBase::Random(Index,Index), DenseBase::Random(Index) + */ +template +inline const typename DenseBase::RandomReturnType DenseBase::Random() { + return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_random_op()); +} + +/** Sets all coefficients in this expression to random values. + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * \not_reentrant + * + * Example: \include MatrixBase_setRandom.cpp + * Output: \verbinclude MatrixBase_setRandom.out + * + * \sa class CwiseNullaryOp, setRandom(Index), setRandom(Index,Index) + */ +template +EIGEN_DEVICE_FUNC inline Derived& DenseBase::setRandom() { + return *this = Random(rows(), cols()); +} + +/** Resizes to the given \a newSize, and sets all coefficients in this expression to random values. + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * \only_for_vectors + * \not_reentrant + * + * Example: \include Matrix_setRandom_int.cpp + * Output: \verbinclude Matrix_setRandom_int.out + * + * \sa DenseBase::setRandom(), setRandom(Index,Index), class CwiseNullaryOp, DenseBase::Random() + */ +template +EIGEN_STRONG_INLINE Derived& PlainObjectBase::setRandom(Index newSize) { + resize(newSize); + return setRandom(); +} + +/** Resizes to the given size, and sets all coefficients in this expression to random values. + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * \not_reentrant + * + * \param rows the new number of rows + * \param cols the new number of columns + * + * Example: \include Matrix_setRandom_int_int.cpp + * Output: \verbinclude Matrix_setRandom_int_int.out + * + * \sa DenseBase::setRandom(), setRandom(Index), class CwiseNullaryOp, DenseBase::Random() + */ +template +EIGEN_STRONG_INLINE Derived& PlainObjectBase::setRandom(Index rows, Index cols) { + resize(rows, cols); + return setRandom(); +} + +/** Resizes to the given size, changing only the number of columns, and sets all + * coefficients in this expression to random values. For the parameter of type + * NoChange_t, just pass the special value \c NoChange. + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * \not_reentrant + * + * \sa DenseBase::setRandom(), setRandom(Index), setRandom(Index, NoChange_t), class CwiseNullaryOp, DenseBase::Random() + */ +template +EIGEN_STRONG_INLINE Derived& PlainObjectBase::setRandom(NoChange_t, Index cols) { + return setRandom(rows(), cols); +} + +/** Resizes to the given size, changing only the number of rows, and sets all + * coefficients in this expression to random values. For the parameter of type + * NoChange_t, just pass the special value \c NoChange. + * + * Numbers are uniformly spread through their whole definition range for integer types, + * and in the [-1:1] range for floating point scalar types. + * + * \not_reentrant + * + * \sa DenseBase::setRandom(), setRandom(Index), setRandom(NoChange_t, Index), class CwiseNullaryOp, DenseBase::Random() + */ +template +EIGEN_STRONG_INLINE Derived& PlainObjectBase::setRandom(Index rows, NoChange_t) { + return setRandom(rows, cols()); +} + +} // end namespace Eigen + +#endif // EIGEN_RANDOM_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RandomImpl.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RandomImpl.h new file mode 100644 index 0000000..4a622fc --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RandomImpl.h @@ -0,0 +1,265 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2024 Charles Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_RANDOM_IMPL_H +#define EIGEN_RANDOM_IMPL_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +/**************************************************************************** + * Implementation of random * + ****************************************************************************/ + +template +struct random_default_impl {}; + +template +struct random_impl : random_default_impl::IsComplex, NumTraits::IsInteger> {}; + +template +struct random_retval { + typedef Scalar type; +}; + +template +inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) { + return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); +} + +template +inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() { + return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); +} + +// TODO: replace or provide alternatives to this, e.g. std::random_device +struct eigen_random_device { + using ReturnType = int; + static constexpr int Entropy = meta_floor_log2<(unsigned int)(RAND_MAX) + 1>::value; + static constexpr ReturnType Highest = RAND_MAX; + static EIGEN_DEVICE_FUNC inline ReturnType run() { return std::rand(); } +}; + +// Fill a built-in unsigned integer with numRandomBits beginning with the least significant bit +template +struct random_bits_impl { + EIGEN_STATIC_ASSERT(std::is_unsigned::value, SCALAR MUST BE A BUILT - IN UNSIGNED INTEGER) + using RandomDevice = eigen_random_device; + using RandomReturnType = typename RandomDevice::ReturnType; + static constexpr int kTotalBits = sizeof(Scalar) * CHAR_BIT; + static constexpr int kEntropy = plain_enum_min(kTotalBits, RandomDevice::Entropy); + // return a Scalar filled with numRandomBits beginning from the least significant bit + static EIGEN_DEVICE_FUNC inline Scalar run(int numRandomBits) { + eigen_assert((numRandomBits >= 0) && (numRandomBits <= kTotalBits)); + Scalar randomBits = 0; + for (int filledBits = 0; filledBits < numRandomBits; filledBits += kEntropy) { + Scalar r = static_cast(RandomDevice::run()); + int remainingBits = numRandomBits - filledBits; + if (remainingBits < kEntropy) { + // clear the excess bits to avoid UB and rounding bias + r >>= kEntropy - remainingBits; + } + randomBits |= r << filledBits; + } + return randomBits; + } +}; + +template +EIGEN_DEVICE_FUNC inline BitsType getRandomBits(int numRandomBits) { + return random_bits_impl::run(numRandomBits); +} + +// random implementation for a built-in floating point type +template ::value> +struct random_float_impl { + using BitsType = typename numext::get_integer_by_size::unsigned_type; + static constexpr EIGEN_DEVICE_FUNC inline int mantissaBits() { + const int digits = NumTraits::digits(); + return digits - 1; + } + static EIGEN_DEVICE_FUNC inline Scalar run(int numRandomBits) { + eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits()); + BitsType randomBits = getRandomBits(numRandomBits); + // if fewer than MantissaBits is requested, shift them to the left + randomBits <<= (mantissaBits() - numRandomBits); + // randomBits is in the half-open interval [2,4) + randomBits |= numext::bit_cast(Scalar(2)); + // result is in the half-open interval [-1,1) + Scalar result = numext::bit_cast(randomBits) - Scalar(3); + return result; + } +}; +// random implementation for a custom floating point type +// uses double as the implementation with a mantissa with a size equal to either the target scalar's mantissa or that of +// double, whichever is smaller +template +struct random_float_impl { + static EIGEN_DEVICE_FUNC inline int mantissaBits() { + const int digits = NumTraits::digits(); + constexpr int kDoubleDigits = NumTraits::digits(); + return numext::mini(digits, kDoubleDigits) - 1; + } + static EIGEN_DEVICE_FUNC inline Scalar run(int numRandomBits) { + eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits()); + Scalar result = static_cast(random_float_impl::run(numRandomBits)); + return result; + } +}; + +#if !EIGEN_COMP_NVCC +// random implementation for long double +// this specialization is not compatible with double-double scalars +template ::digits != (2 * std::numeric_limits::digits)))> +struct random_longdouble_impl { + static constexpr int Size = sizeof(long double); + static constexpr EIGEN_DEVICE_FUNC int mantissaBits() { return NumTraits::digits() - 1; } + static EIGEN_DEVICE_FUNC inline long double run(int numRandomBits) { + eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits()); + EIGEN_USING_STD(memcpy); + int numLowBits = numext::mini(numRandomBits, 64); + int numHighBits = numext::maxi(numRandomBits - 64, 0); + uint64_t randomBits[2]; + long double result = 2.0L; + memcpy(&randomBits, &result, Size); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + randomBits[0] |= getRandomBits(numLowBits); + randomBits[1] |= getRandomBits(numHighBits); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + randomBits[0] |= getRandomBits(numHighBits); + randomBits[1] |= getRandomBits(numLowBits); +#else +#error Unexpected or undefined __BYTE_ORDER__ +#endif + memcpy(&result, &randomBits, Size); + result -= 3.0L; + return result; + } +}; +template <> +struct random_longdouble_impl { + static constexpr EIGEN_DEVICE_FUNC int mantissaBits() { return NumTraits::digits() - 1; } + static EIGEN_DEVICE_FUNC inline long double run(int numRandomBits) { + return static_cast(random_float_impl::run(numRandomBits)); + } +}; +template <> +struct random_float_impl : random_longdouble_impl<> {}; +#endif + +template +struct random_default_impl { + using Impl = random_float_impl; + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y, int numRandomBits) { + Scalar half_x = Scalar(0.5) * x; + Scalar half_y = Scalar(0.5) * y; + Scalar result = (half_x + half_y) + (half_y - half_x) * run(numRandomBits); + // result is in the half-open interval [x, y) -- provided that x < y + return result; + } + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y) { + return run(x, y, Impl::mantissaBits()); + } + static EIGEN_DEVICE_FUNC inline Scalar run(int numRandomBits) { return Impl::run(numRandomBits); } + static EIGEN_DEVICE_FUNC inline Scalar run() { return run(Impl::mantissaBits()); } +}; + +template ::IsSigned, bool BuiltIn = std::is_integral::value> +struct random_int_impl; + +// random implementation for a built-in unsigned integer type +template +struct random_int_impl { + static constexpr int kTotalBits = sizeof(Scalar) * CHAR_BIT; + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y) { + if (y <= x) return x; + Scalar range = y - x; + // handle edge case where [x,y] spans the entire range of Scalar + if (range == NumTraits::highest()) return run(); + Scalar count = range + 1; + // calculate the number of random bits needed to fill range + int numRandomBits = log2_ceil(count); + Scalar randomBits; + do { + randomBits = getRandomBits(numRandomBits); + // if the random draw is outside [0, range), try again (rejection sampling) + // in the worst-case scenario, the probability of rejection is: 1/2 - 1/2^numRandomBits < 50% + } while (randomBits >= count); + Scalar result = x + randomBits; + return result; + } + static EIGEN_DEVICE_FUNC inline Scalar run() { return getRandomBits(kTotalBits); } +}; + +// random implementation for a built-in signed integer type +template +struct random_int_impl { + static constexpr int kTotalBits = sizeof(Scalar) * CHAR_BIT; + // avoid implicit integral promotion to `int` + using BitsType = std::conditional_t<(sizeof(Scalar) < sizeof(int)), unsigned int, std::make_unsigned_t >; + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y) { + if (y <= x) return x; + // Avoid overflow by representing `range` as an unsigned type + BitsType range = static_cast(y) - static_cast(x); + BitsType randomBits = random_int_impl::run(0, range); + // Avoid overflow in the case where `x` is negative and there is a large range so + // `randomBits` would also be negative if cast to `Scalar` first. + Scalar result = static_cast(static_cast(x) + randomBits); + return result; + } + static EIGEN_DEVICE_FUNC inline Scalar run() { return static_cast(getRandomBits(kTotalBits)); } +}; + +// todo: custom integers +template +struct random_int_impl { + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar&, const Scalar&) { return run(); } + static EIGEN_DEVICE_FUNC inline Scalar run() { + eigen_assert(std::false_type::value && "RANDOM FOR CUSTOM INTEGERS NOT YET SUPPORTED"); + return Scalar(0); + } +}; + +template +struct random_default_impl : random_int_impl {}; + +template <> +struct random_impl { + static EIGEN_DEVICE_FUNC inline bool run(const bool& x, const bool& y) { + if (y <= x) return x; + return run(); + } + static EIGEN_DEVICE_FUNC inline bool run() { return getRandomBits(1) ? true : false; } +}; + +template +struct random_default_impl { + typedef typename NumTraits::Real RealScalar; + using Impl = random_impl; + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y, int numRandomBits) { + return Scalar(Impl::run(x.real(), y.real(), numRandomBits), Impl::run(x.imag(), y.imag(), numRandomBits)); + } + static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y) { + return Scalar(Impl::run(x.real(), y.real()), Impl::run(x.imag(), y.imag())); + } + static EIGEN_DEVICE_FUNC inline Scalar run(int numRandomBits) { + return Scalar(Impl::run(numRandomBits), Impl::run(numRandomBits)); + } + static EIGEN_DEVICE_FUNC inline Scalar run() { return Scalar(Impl::run(), Impl::run()); } +}; + +} // namespace internal +} // namespace Eigen + +#endif // EIGEN_RANDOM_IMPL_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RealView.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RealView.h new file mode 100644 index 0000000..3be5556 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/RealView.h @@ -0,0 +1,292 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2025 Charlie Schlosser +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_REALVIEW_H +#define EIGEN_REALVIEW_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// Write access and vectorization requires array-oriented access to the real and imaginary components. +// From https://en.cppreference.com/w/cpp/numeric/complex.html: +// For any pointer to an element of an array of std::complex named p and any valid array index i, +// reinterpret_cast(p)[2 * i] is the real part of the complex number p[i], and +// reinterpret_cast(p)[2 * i + 1] is the imaginary part of the complex number p[i]. + +template +struct complex_array_access : std::false_type {}; +template +struct complex_array_access> : std::true_type {}; + +template +struct traits> : public traits { + template + static constexpr int double_size(T size, bool times_two) { + int size_as_int = int(size); + if (size_as_int == Dynamic) return Dynamic; + return times_two ? (2 * size_as_int) : size_as_int; + } + + using Base = traits; + using ComplexScalar = typename Base::Scalar; + using Scalar = typename NumTraits::Real; + + static constexpr bool ArrayAccess = complex_array_access::value; + static constexpr int ActualDirectAccessBit = ArrayAccess ? DirectAccessBit : 0; + static constexpr int ActualLvaluebit = !std::is_const::value && ArrayAccess ? LvalueBit : 0; + static constexpr int ActualPacketAccessBit = packet_traits::Vectorizable ? PacketAccessBit : 0; + static constexpr int FlagMask = + ActualDirectAccessBit | ActualLvaluebit | ActualPacketAccessBit | HereditaryBits | LinearAccessBit; + static constexpr int BaseFlags = int(evaluator::Flags) | int(Base::Flags); + static constexpr int Flags = BaseFlags & FlagMask; + static constexpr bool IsRowMajor = Flags & RowMajorBit; + static constexpr int RowsAtCompileTime = double_size(Base::RowsAtCompileTime, !IsRowMajor); + static constexpr int ColsAtCompileTime = double_size(Base::ColsAtCompileTime, IsRowMajor); + static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime); + static constexpr int MaxRowsAtCompileTime = double_size(Base::MaxRowsAtCompileTime, !IsRowMajor); + static constexpr int MaxColsAtCompileTime = double_size(Base::MaxColsAtCompileTime, IsRowMajor); + static constexpr int MaxSizeAtCompileTime = size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime); + static constexpr int OuterStrideAtCompileTime = double_size(outer_stride_at_compile_time::ret, true); + static constexpr int InnerStrideAtCompileTime = inner_stride_at_compile_time::ret; +}; + +template +struct evaluator> : private evaluator { + using BaseEvaluator = evaluator; + using XprType = RealView; + using ExpressionTraits = traits; + using ComplexScalar = typename ExpressionTraits::ComplexScalar; + using Scalar = typename ExpressionTraits::Scalar; + + static constexpr int Flags = ExpressionTraits::Flags; + static constexpr int CoeffReadCost = BaseEvaluator::CoeffReadCost; + static constexpr int Alignment = BaseEvaluator::Alignment; + static constexpr bool IsRowMajor = ExpressionTraits::IsRowMajor; + static constexpr bool DirectAccess = Flags & DirectAccessBit; + + using ComplexCoeffReturnType = std::conditional_t; + using CoeffReturnType = std::conditional_t; + + EIGEN_DEVICE_FUNC explicit evaluator(XprType realView) : BaseEvaluator(realView.m_xpr) {} + + template = true> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { + Index r = IsRowMajor ? row : row / 2; + Index c = IsRowMajor ? col / 2 : col; + bool p = (IsRowMajor ? col : row) & 1; + ComplexScalar ccoeff = BaseEvaluator::coeff(r, c); + return p ? numext::imag(ccoeff) : numext::real(ccoeff); + } + template = true> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { + Index r = IsRowMajor ? row : row / 2; + Index c = IsRowMajor ? col / 2 : col; + Index p = (IsRowMajor ? col : row) & 1; + ComplexCoeffReturnType ccoeff = BaseEvaluator::coeff(r, c); + return reinterpret_cast(ccoeff)[p]; + } + template = true> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const { + ComplexScalar ccoeff = BaseEvaluator::coeff(index / 2); + bool p = index & 1; + return p ? numext::imag(ccoeff) : numext::real(ccoeff); + } + template = true> + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { + ComplexCoeffReturnType ccoeff = BaseEvaluator::coeff(index / 2); + Index p = index & 1; + return reinterpret_cast(ccoeff)[p]; + } + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { + Index r = IsRowMajor ? row : row / 2; + Index c = IsRowMajor ? col / 2 : col; + Index p = (IsRowMajor ? col : row) & 1; + ComplexScalar& ccoeffRef = BaseEvaluator::coeffRef(r, c); + return reinterpret_cast(ccoeffRef)[p]; + } + constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { + ComplexScalar& ccoeffRef = BaseEvaluator::coeffRef(index / 2); + Index p = index & 1; + return reinterpret_cast(ccoeffRef)[p]; + } + + // If the first index is odd (imaginary), discard the first scalar + // in 'result' and assign the missing scalar. + // This operation is safe as the real component of the first scalar must exist. + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + Index r = IsRowMajor ? row : row / 2; + Index c = IsRowMajor ? col / 2 : col; + bool p = (IsRowMajor ? col : row) & 1; + ComplexPacket cresult = BaseEvaluator::template packet(r, c); + PacketType result = preinterpret(cresult); + if (p) { + Scalar aux[RealPacketSize + 1]; + pstoreu(aux, result); + Index lastr = IsRowMajor ? row : row + RealPacketSize - 1; + Index lastc = IsRowMajor ? col + RealPacketSize - 1 : col; + aux[RealPacketSize] = coeff(lastr, lastc); + result = ploadu(aux + 1); + } + return result; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + ComplexPacket cresult = BaseEvaluator::template packet(index / 2); + PacketType result = preinterpret(cresult); + bool p = index & 1; + if (p) { + Scalar aux[RealPacketSize + 1]; + pstoreu(aux, result); + aux[RealPacketSize] = coeff(index + RealPacketSize - 1); + result = ploadu(aux + 1); + } + return result; + } + + // The requested real packet segment forms the half-open interval [begin, end), where 'end' = 'begin' + 'count'. + // In order to access the underlying complex array, even indices must be aligned with the real components + // of the complex scalars. 'begin' and 'count' must be modified as follows: + // a) 'begin' must be rounded down to the nearest even number; and + // b) 'end' must be rounded up to the nearest even number. + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + Index actualBegin = numext::round_down(begin, 2); + Index actualEnd = numext::round_down(begin + count + 1, 2); + Index actualCount = actualEnd - actualBegin; + Index r = IsRowMajor ? row : row / 2; + Index c = IsRowMajor ? col / 2 : col; + ComplexPacket cresult = + BaseEvaluator::template packetSegment(r, c, actualBegin / 2, actualCount / 2); + PacketType result = preinterpret(cresult); + bool p = (IsRowMajor ? col : row) & 1; + if (p) { + Scalar aux[RealPacketSize + 1] = {}; + pstoreu(aux, result); + Index lastr = IsRowMajor ? row : row + actualEnd - 1; + Index lastc = IsRowMajor ? col + actualEnd - 1 : col; + aux[actualEnd] = coeff(lastr, lastc); + result = ploadu(aux + 1); + } + return result; + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const { + constexpr int RealPacketSize = unpacket_traits::size; + using ComplexPacket = typename find_packet_by_size::type; + EIGEN_STATIC_ASSERT((find_packet_by_size::value), + MISSING COMPATIBLE COMPLEX PACKET TYPE) + Index actualBegin = numext::round_down(begin, 2); + Index actualEnd = numext::round_down(begin + count + 1, 2); + Index actualCount = actualEnd - actualBegin; + ComplexPacket cresult = + BaseEvaluator::template packetSegment(index / 2, actualBegin / 2, actualCount / 2); + PacketType result = preinterpret(cresult); + bool p = index & 1; + if (p) { + Scalar aux[RealPacketSize + 1] = {}; + pstoreu(aux, result); + aux[actualEnd] = coeff(index + actualEnd - 1); + result = ploadu(aux + 1); + } + return result; + } +}; + +} // namespace internal + +template +class RealView : public internal::dense_xpr_base>::type { + using ExpressionTraits = internal::traits; + EIGEN_STATIC_ASSERT(NumTraits::IsComplex, SCALAR MUST BE COMPLEX) + public: + using Scalar = typename ExpressionTraits::Scalar; + using Nested = RealView; + + EIGEN_DEVICE_FUNC explicit RealView(Xpr& xpr) : m_xpr(xpr) {} + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return Xpr::IsRowMajor ? m_xpr.rows() : 2 * m_xpr.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return Xpr::IsRowMajor ? 2 * m_xpr.cols() : m_xpr.cols(); } + EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return 2 * m_xpr.size(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_xpr.innerStride(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 2 * m_xpr.outerStride(); } + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { + m_xpr.resize(Xpr::IsRowMajor ? rows : rows / 2, Xpr::IsRowMajor ? cols / 2 : cols); + } + EIGEN_DEVICE_FUNC void resize(Index size) { m_xpr.resize(size / 2); } + EIGEN_DEVICE_FUNC Scalar* data() { return reinterpret_cast(m_xpr.data()); } + EIGEN_DEVICE_FUNC const Scalar* data() const { return reinterpret_cast(m_xpr.data()); } + + EIGEN_DEVICE_FUNC RealView(const RealView&) = default; + + EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other); + + template + EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other); + + template + EIGEN_DEVICE_FUNC RealView& operator=(const DenseBase& other); + + protected: + friend struct internal::evaluator; + Xpr& m_xpr; +}; + +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const RealView& other) { + internal::call_assignment(*this, other); + return *this; +} + +template +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const RealView& other) { + internal::call_assignment(*this, other); + return *this; +} + +template +template +EIGEN_DEVICE_FUNC RealView& RealView::operator=(const DenseBase& other) { + internal::call_assignment(*this, other.derived()); + return *this; +} + +template +EIGEN_DEVICE_FUNC typename DenseBase::RealViewReturnType DenseBase::realView() { + return RealViewReturnType(derived()); +} + +template +EIGEN_DEVICE_FUNC typename DenseBase::ConstRealViewReturnType DenseBase::realView() const { + return ConstRealViewReturnType(derived()); +} + +} // namespace Eigen + +#endif // EIGEN_REALVIEW_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Redux.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Redux.h new file mode 100644 index 0000000..fefb4c9 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Redux.h @@ -0,0 +1,535 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_REDUX_H +#define EIGEN_REDUX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// TODO +// * implement other kind of vectorization +// * factorize code + +/*************************************************************************** + * Part 1 : the logic deciding a strategy for vectorization and unrolling + ***************************************************************************/ + +template +struct redux_traits { + public: + typedef typename find_best_packet::type PacketType; + enum { + PacketSize = unpacket_traits::size, + InnerMaxSize = int(Evaluator::IsRowMajor) ? Evaluator::MaxColsAtCompileTime : Evaluator::MaxRowsAtCompileTime, + OuterMaxSize = int(Evaluator::IsRowMajor) ? Evaluator::MaxRowsAtCompileTime : Evaluator::MaxColsAtCompileTime, + SliceVectorizedWork = int(InnerMaxSize) == Dynamic ? Dynamic + : int(OuterMaxSize) == Dynamic ? (int(InnerMaxSize) >= int(PacketSize) ? Dynamic : 0) + : (int(InnerMaxSize) / int(PacketSize)) * int(OuterMaxSize) + }; + + enum { + MayLinearize = (int(Evaluator::Flags) & LinearAccessBit), + MightVectorize = (int(Evaluator::Flags) & ActualPacketAccessBit) && (functor_traits::PacketAccess), + MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize), + MaySliceVectorize = bool(MightVectorize) && (int(SliceVectorizedWork) == Dynamic || int(SliceVectorizedWork) >= 3) + }; + + public: + enum { + Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal) + : int(MaySliceVectorize) ? int(SliceVectorizedTraversal) + : int(MayLinearize) ? int(LinearTraversal) + : int(DefaultTraversal) + }; + + public: + enum { + Cost = Evaluator::SizeAtCompileTime == Dynamic + ? HugeCost + : int(Evaluator::SizeAtCompileTime) * int(Evaluator::CoeffReadCost) + + (Evaluator::SizeAtCompileTime - 1) * functor_traits::Cost, + UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize)) + }; + + public: + enum { Unrolling = Cost <= UnrollingLimit ? CompleteUnrolling : NoUnrolling }; + +#ifdef EIGEN_DEBUG_ASSIGN + static void debug() { + std::cerr << "Xpr: " << typeid(typename Evaluator::XprType).name() << std::endl; + std::cerr.setf(std::ios::hex, std::ios::basefield); + EIGEN_DEBUG_VAR(Evaluator::Flags) + std::cerr.unsetf(std::ios::hex); + EIGEN_DEBUG_VAR(InnerMaxSize) + EIGEN_DEBUG_VAR(OuterMaxSize) + EIGEN_DEBUG_VAR(SliceVectorizedWork) + EIGEN_DEBUG_VAR(PacketSize) + EIGEN_DEBUG_VAR(MightVectorize) + EIGEN_DEBUG_VAR(MayLinearVectorize) + EIGEN_DEBUG_VAR(MaySliceVectorize) + std::cerr << "Traversal" + << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl; + EIGEN_DEBUG_VAR(UnrollingLimit) + std::cerr << "Unrolling" + << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl; + std::cerr << std::endl; + } +#endif +}; + +/*************************************************************************** + * Part 2 : unrollers + ***************************************************************************/ + +/*** no vectorization ***/ + +template +struct redux_novec_unroller { + static constexpr Index HalfLength = Length / 2; + + typedef typename Evaluator::Scalar Scalar; + + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func) { + return func(redux_novec_unroller::run(eval, func), + redux_novec_unroller::run(eval, func)); + } +}; + +template +struct redux_novec_unroller { + static constexpr Index outer = Start / Evaluator::InnerSizeAtCompileTime; + static constexpr Index inner = Start % Evaluator::InnerSizeAtCompileTime; + + typedef typename Evaluator::Scalar Scalar; + + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func&) { + return eval.coeffByOuterInner(outer, inner); + } +}; + +// This is actually dead code and will never be called. It is required +// to prevent false warnings regarding failed inlining though +// for 0 length run() will never be called at all. +template +struct redux_novec_unroller { + typedef typename Evaluator::Scalar Scalar; + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator&, const Func&) { return Scalar(); } +}; + +template +struct redux_novec_linear_unroller { + static constexpr Index HalfLength = Length / 2; + + typedef typename Evaluator::Scalar Scalar; + + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func) { + return func(redux_novec_linear_unroller::run(eval, func), + redux_novec_linear_unroller::run(eval, func)); + } +}; + +template +struct redux_novec_linear_unroller { + typedef typename Evaluator::Scalar Scalar; + + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func&) { + return eval.coeff(Start); + } +}; + +// This is actually dead code and will never be called. It is required +// to prevent false warnings regarding failed inlining though +// for 0 length run() will never be called at all. +template +struct redux_novec_linear_unroller { + typedef typename Evaluator::Scalar Scalar; + EIGEN_DEVICE_FUNC static constexpr EIGEN_STRONG_INLINE Scalar run(const Evaluator&, const Func&) { return Scalar(); } +}; + +/*** vectorization ***/ + +template +struct redux_vec_unroller { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator& eval, const Func& func) { + constexpr Index HalfLength = Length / 2; + + return func.packetOp( + redux_vec_unroller::template run(eval, func), + redux_vec_unroller::template run(eval, + func)); + } +}; + +template +struct redux_vec_unroller { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator& eval, const Func&) { + constexpr Index PacketSize = unpacket_traits::size; + constexpr Index index = Start * PacketSize; + constexpr Index outer = index / int(Evaluator::InnerSizeAtCompileTime); + constexpr Index inner = index % int(Evaluator::InnerSizeAtCompileTime); + constexpr int alignment = Evaluator::Alignment; + + return eval.template packetByOuterInner(outer, inner); + } +}; + +template +struct redux_vec_linear_unroller { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator& eval, const Func& func) { + constexpr Index HalfLength = Length / 2; + + return func.packetOp( + redux_vec_linear_unroller::template run(eval, func), + redux_vec_linear_unroller::template run( + eval, func)); + } +}; + +template +struct redux_vec_linear_unroller { + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE PacketType run(const Evaluator& eval, const Func&) { + constexpr Index PacketSize = unpacket_traits::size; + constexpr Index index = (Start * PacketSize); + constexpr int alignment = Evaluator::Alignment; + return eval.template packet(index); + } +}; + +/*************************************************************************** + * Part 3 : implementation of all cases + ***************************************************************************/ + +template ::Traversal, + int Unrolling = redux_traits::Unrolling> +struct redux_impl; + +template +struct redux_impl { + typedef typename Evaluator::Scalar Scalar; + + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func, const XprType& xpr) { + eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 && "you are using an empty matrix"); + Scalar res = eval.coeffByOuterInner(0, 0); + for (Index i = 1; i < xpr.innerSize(); ++i) res = func(res, eval.coeffByOuterInner(0, i)); + for (Index i = 1; i < xpr.outerSize(); ++i) + for (Index j = 0; j < xpr.innerSize(); ++j) res = func(res, eval.coeffByOuterInner(i, j)); + return res; + } +}; + +template +struct redux_impl { + typedef typename Evaluator::Scalar Scalar; + + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func, const XprType& xpr) { + eigen_assert(xpr.size() > 0 && "you are using an empty matrix"); + Scalar res = eval.coeff(0); + for (Index k = 1; k < xpr.size(); ++k) res = func(res, eval.coeff(k)); + return res; + } +}; + +template +struct redux_impl + : redux_novec_unroller { + typedef redux_novec_unroller Base; + typedef typename Evaluator::Scalar Scalar; + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func, + const XprType& /*xpr*/) { + return Base::run(eval, func); + } +}; + +template +struct redux_impl + : redux_novec_linear_unroller { + typedef redux_novec_linear_unroller Base; + typedef typename Evaluator::Scalar Scalar; + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func, + const XprType& /*xpr*/) { + return Base::run(eval, func); + } +}; + +template +struct redux_impl { + typedef typename Evaluator::Scalar Scalar; + typedef typename redux_traits::PacketType PacketScalar; + + template + static Scalar run(const Evaluator& eval, const Func& func, const XprType& xpr) { + const Index size = xpr.size(); + + constexpr Index packetSize = redux_traits::PacketSize; + constexpr int packetAlignment = unpacket_traits::alignment; + constexpr int alignment0 = + (bool(Evaluator::Flags & DirectAccessBit) && bool(packet_traits::AlignedOnScalar)) + ? int(packetAlignment) + : int(Unaligned); + constexpr int alignment = plain_enum_max(alignment0, Evaluator::Alignment); + const Index alignedStart = internal::first_default_aligned(xpr); + const Index alignedSize2 = ((size - alignedStart) / (2 * packetSize)) * (2 * packetSize); + const Index alignedSize = ((size - alignedStart) / (packetSize)) * (packetSize); + const Index alignedEnd2 = alignedStart + alignedSize2; + const Index alignedEnd = alignedStart + alignedSize; + Scalar res; + if (alignedSize) { + PacketScalar packet_res0 = eval.template packet(alignedStart); + if (alignedSize > packetSize) // we have at least two packets to partly unroll the loop + { + PacketScalar packet_res1 = eval.template packet(alignedStart + packetSize); + for (Index index = alignedStart + 2 * packetSize; index < alignedEnd2; index += 2 * packetSize) { + packet_res0 = func.packetOp(packet_res0, eval.template packet(index)); + packet_res1 = func.packetOp(packet_res1, eval.template packet(index + packetSize)); + } + + packet_res0 = func.packetOp(packet_res0, packet_res1); + if (alignedEnd > alignedEnd2) + packet_res0 = func.packetOp(packet_res0, eval.template packet(alignedEnd2)); + } + res = func.predux(packet_res0); + + for (Index index = 0; index < alignedStart; ++index) res = func(res, eval.coeff(index)); + + for (Index index = alignedEnd; index < size; ++index) res = func(res, eval.coeff(index)); + } else // too small to vectorize anything. + // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize. + { + res = eval.coeff(0); + for (Index index = 1; index < size; ++index) res = func(res, eval.coeff(index)); + } + + return res; + } +}; + +// NOTE: for SliceVectorizedTraversal we simply bypass unrolling +template +struct redux_impl { + typedef typename Evaluator::Scalar Scalar; + typedef typename redux_traits::PacketType PacketType; + + template + EIGEN_DEVICE_FUNC static Scalar run(const Evaluator& eval, const Func& func, const XprType& xpr) { + eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 && "you are using an empty matrix"); + constexpr Index packetSize = redux_traits::PacketSize; + const Index innerSize = xpr.innerSize(); + const Index outerSize = xpr.outerSize(); + const Index packetedInnerSize = ((innerSize) / packetSize) * packetSize; + Scalar res; + if (packetedInnerSize) { + PacketType packet_res = eval.template packet(0, 0); + for (Index j = 0; j < outerSize; ++j) + for (Index i = (j == 0 ? packetSize : 0); i < packetedInnerSize; i += Index(packetSize)) + packet_res = func.packetOp(packet_res, eval.template packetByOuterInner(j, i)); + + res = func.predux(packet_res); + for (Index j = 0; j < outerSize; ++j) + for (Index i = packetedInnerSize; i < innerSize; ++i) res = func(res, eval.coeffByOuterInner(j, i)); + } else // too small to vectorize anything. + // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize. + { + res = redux_impl::run(eval, func, xpr); + } + + return res; + } +}; + +template +struct redux_impl { + typedef typename Evaluator::Scalar Scalar; + + typedef typename redux_traits::PacketType PacketType; + static constexpr Index PacketSize = redux_traits::PacketSize; + static constexpr Index Size = Evaluator::SizeAtCompileTime; + static constexpr Index VectorizedSize = (int(Size) / int(PacketSize)) * int(PacketSize); + + template + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Evaluator& eval, const Func& func, const XprType& xpr) { + EIGEN_ONLY_USED_FOR_DEBUG(xpr) + eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 && "you are using an empty matrix"); + if (VectorizedSize > 0) { + Scalar res = func.predux( + redux_vec_linear_unroller::template run(eval, func)); + if (VectorizedSize != Size) + res = func( + res, redux_novec_linear_unroller::run(eval, func)); + return res; + } else { + return redux_novec_linear_unroller::run(eval, func); + } + } +}; + +// evaluator adaptor +template +class redux_evaluator : public internal::evaluator { + typedef internal::evaluator Base; + + public: + typedef XprType_ XprType; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit redux_evaluator(const XprType& xpr) : Base(xpr) {} + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + typedef typename XprType::PacketScalar PacketScalar; + + enum { + MaxRowsAtCompileTime = XprType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = XprType::MaxColsAtCompileTime, + // TODO: we should not remove DirectAccessBit and rather find an elegant way to query the alignment offset at + // runtime from the evaluator + Flags = Base::Flags & ~DirectAccessBit, + IsRowMajor = XprType::IsRowMajor, + SizeAtCompileTime = XprType::SizeAtCompileTime, + InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime + }; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const { + return Base::coeff(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetByOuterInner(Index outer, Index inner) const { + return Base::template packet(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegmentByOuterInner(Index outer, Index inner, Index begin, + Index count) const { + return Base::template packetSegment(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer, + begin, count); + } +}; + +} // end namespace internal + +/*************************************************************************** + * Part 4 : public API + ***************************************************************************/ + +/** \returns the result of a full redux operation on the whole matrix or vector using \a func + * + * The template parameter \a BinaryOp is the type of the functor \a func which must be + * an associative operator. Both current C++98 and C++11 functor styles are handled. + * + * \warning the matrix must be not empty, otherwise an assertion is triggered. + * + * \sa DenseBase::sum(), DenseBase::minCoeff(), DenseBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise() + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::redux( + const Func& func) const { + eigen_assert(this->rows() > 0 && this->cols() > 0 && "you are using an empty matrix"); + + typedef typename internal::redux_evaluator ThisEvaluator; + ThisEvaluator thisEval(derived()); + + // The initial expression is passed to the reducer as an additional argument instead of + // passing it as a member of redux_evaluator to help + return internal::redux_impl::run(thisEval, func, derived()); +} + +/** \returns the minimum of all coefficients of \c *this. + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is minimum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::minCoeff() const { + return derived().redux(Eigen::internal::scalar_min_op()); +} + +/** \returns the maximum of all coefficients of \c *this. + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN + * \warning the matrix must be not empty, otherwise an assertion is triggered. + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::maxCoeff() const { + return derived().redux(Eigen::internal::scalar_max_op()); +} + +/** \returns the sum of all coefficients of \c *this + * + * If \c *this is empty, then the value 0 is returned. + * + * \sa trace(), prod(), mean() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::sum() const { + if (SizeAtCompileTime == 0 || (SizeAtCompileTime == Dynamic && size() == 0)) return Scalar(0); + return derived().redux(Eigen::internal::scalar_sum_op()); +} + +/** \returns the mean of all coefficients of *this + * + * \sa trace(), prod(), sum() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::mean() const { +#ifdef __INTEL_COMPILER +#pragma warning push +#pragma warning(disable : 2259) +#endif + return Scalar(derived().redux(Eigen::internal::scalar_sum_op())) / Scalar(this->size()); +#ifdef __INTEL_COMPILER +#pragma warning pop +#endif +} + +/** \returns the product of all coefficients of *this + * + * Example: \include MatrixBase_prod.cpp + * Output: \verbinclude MatrixBase_prod.out + * + * \sa sum(), mean(), trace() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::prod() const { + if (SizeAtCompileTime == 0 || (SizeAtCompileTime == Dynamic && size() == 0)) return Scalar(1); + return derived().redux(Eigen::internal::scalar_product_op()); +} + +/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal. + * + * \c *this can be any matrix, not necessarily square. + * + * \sa diagonal(), sum() + */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar MatrixBase::trace() const { + return derived().diagonal().sum(); +} + +} // end namespace Eigen + +#endif // EIGEN_REDUX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Ref.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Ref.h new file mode 100644 index 0000000..c845462 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Ref.h @@ -0,0 +1,384 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_REF_H +#define EIGEN_REF_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct traits > + : public traits > { + typedef PlainObjectType_ PlainObjectType; + typedef StrideType_ StrideType; + enum { + Options = Options_, + Flags = traits >::Flags | NestByRefBit, + Alignment = traits >::Alignment, + InnerStrideAtCompileTime = traits >::InnerStrideAtCompileTime, + OuterStrideAtCompileTime = traits >::OuterStrideAtCompileTime + }; + + template + struct match { + enum { + IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime, + HasDirectAccess = internal::has_direct_access::ret, + StorageOrderMatch = + IsVectorAtCompileTime || ((PlainObjectType::Flags & RowMajorBit) == (Derived::Flags & RowMajorBit)), + InnerStrideMatch = int(InnerStrideAtCompileTime) == int(Dynamic) || + int(InnerStrideAtCompileTime) == int(Derived::InnerStrideAtCompileTime) || + (int(InnerStrideAtCompileTime) == 0 && int(Derived::InnerStrideAtCompileTime) == 1), + OuterStrideMatch = IsVectorAtCompileTime || int(OuterStrideAtCompileTime) == int(Dynamic) || + int(OuterStrideAtCompileTime) == int(Derived::OuterStrideAtCompileTime), + // NOTE, this indirection of evaluator::Alignment is needed + // to work around an MSVC bug related to the instantiation + // of has_*ary_operator in evaluator. + // This line is surprisingly very sensitive. For instance, simply adding parenthesis + // as "DerivedAlignment = (int(evaluator::Alignment))," will make MSVC fail... + DerivedAlignment = int(evaluator::Alignment), + AlignmentMatch = (int(traits::Alignment) == int(Unaligned)) || + (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should + // be replaced by the required alignment + ScalarTypeMatch = internal::is_same::value, + MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && + AlignmentMatch && ScalarTypeMatch + }; + typedef std::conditional_t type; + }; +}; + +template +struct traits > : public traits {}; + +} // namespace internal + +template +class RefBase : public MapBase { + typedef typename internal::traits::PlainObjectType PlainObjectType; + typedef typename internal::traits::StrideType StrideType; + + public: + typedef MapBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(RefBase) + + EIGEN_DEVICE_FUNC constexpr Index innerStride() const { + return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; + } + + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { + return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() + : IsVectorAtCompileTime ? this->size() + : int(Flags) & RowMajorBit ? this->cols() + : this->rows(); + } + + EIGEN_DEVICE_FUNC RefBase() + : Base(0, RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime, + ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime), + // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values: + m_stride(StrideType::OuterStrideAtCompileTime == Dynamic ? 0 : StrideType::OuterStrideAtCompileTime, + StrideType::InnerStrideAtCompileTime == Dynamic ? 0 : StrideType::InnerStrideAtCompileTime) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase) + + protected: + typedef Stride StrideBase; + + // Resolves inner stride if default 0. + static EIGEN_DEVICE_FUNC constexpr Index resolveInnerStride(Index inner) { return inner == 0 ? 1 : inner; } + + // Resolves outer stride if default 0. + static EIGEN_DEVICE_FUNC constexpr Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols, + bool isVectorAtCompileTime, bool isRowMajor) { + return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols : isRowMajor ? inner * cols : inner * rows : outer; + } + + // Returns true if construction is valid, false if there is a stride mismatch, + // and fails if there is a size mismatch. + template + EIGEN_DEVICE_FUNC bool construct(Expression& expr) { + // Check matrix sizes. If this is a compile-time vector, we do allow + // implicitly transposing. + EIGEN_STATIC_ASSERT(EIGEN_PREDICATE_SAME_MATRIX_SIZE(PlainObjectType, Expression) + // If it is a vector, the transpose sizes might match. + || (PlainObjectType::IsVectorAtCompileTime && + ((int(PlainObjectType::RowsAtCompileTime) == Eigen::Dynamic || + int(Expression::ColsAtCompileTime) == Eigen::Dynamic || + int(PlainObjectType::RowsAtCompileTime) == int(Expression::ColsAtCompileTime)) && + (int(PlainObjectType::ColsAtCompileTime) == Eigen::Dynamic || + int(Expression::RowsAtCompileTime) == Eigen::Dynamic || + int(PlainObjectType::ColsAtCompileTime) == int(Expression::RowsAtCompileTime)))), + YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES) + + // Determine runtime rows and columns. + Index rows = expr.rows(); + Index cols = expr.cols(); + if (PlainObjectType::RowsAtCompileTime == 1) { + eigen_assert(expr.rows() == 1 || expr.cols() == 1); + rows = 1; + cols = expr.size(); + } else if (PlainObjectType::ColsAtCompileTime == 1) { + eigen_assert(expr.rows() == 1 || expr.cols() == 1); + rows = expr.size(); + cols = 1; + } + // Verify that the sizes are valid. + eigen_assert((PlainObjectType::RowsAtCompileTime == Dynamic) || (PlainObjectType::RowsAtCompileTime == rows)); + eigen_assert((PlainObjectType::ColsAtCompileTime == Dynamic) || (PlainObjectType::ColsAtCompileTime == cols)); + + // If this is a vector, we might be transposing, which means that stride should swap. + const bool transpose = PlainObjectType::IsVectorAtCompileTime && (rows != expr.rows()); + // If the storage format differs, we also need to swap the stride. + const bool row_major = ((PlainObjectType::Flags)&RowMajorBit) != 0; + const bool expr_row_major = (Expression::Flags & RowMajorBit) != 0; + const bool storage_differs = (row_major != expr_row_major); + + const bool swap_stride = (transpose != storage_differs); + + // Determine expr's actual strides, resolving any defaults if zero. + const Index expr_inner_actual = resolveInnerStride(expr.innerStride()); + const Index expr_outer_actual = resolveOuterStride(expr_inner_actual, expr.outerStride(), expr.rows(), expr.cols(), + Expression::IsVectorAtCompileTime != 0, expr_row_major); + + // If this is a column-major row vector or row-major column vector, the inner-stride + // is arbitrary, so set it to either the compile-time inner stride or 1. + const bool row_vector = (rows == 1); + const bool col_vector = (cols == 1); + const Index inner_stride = + ((!row_major && row_vector) || (row_major && col_vector)) + ? (StrideType::InnerStrideAtCompileTime > 0 ? Index(StrideType::InnerStrideAtCompileTime) : 1) + : swap_stride ? expr_outer_actual + : expr_inner_actual; + + // If this is a column-major column vector or row-major row vector, the outer-stride + // is arbitrary, so set it to either the compile-time outer stride or vector size. + const Index outer_stride = + ((!row_major && col_vector) || (row_major && row_vector)) + ? (StrideType::OuterStrideAtCompileTime > 0 ? Index(StrideType::OuterStrideAtCompileTime) + : rows * cols * inner_stride) + : swap_stride ? expr_inner_actual + : expr_outer_actual; + + // Check if given inner/outer strides are compatible with compile-time strides. + const bool inner_valid = (StrideType::InnerStrideAtCompileTime == Dynamic) || + (resolveInnerStride(Index(StrideType::InnerStrideAtCompileTime)) == inner_stride); + if (!inner_valid) { + return false; + } + + const bool outer_valid = + (StrideType::OuterStrideAtCompileTime == Dynamic) || + (resolveOuterStride(inner_stride, Index(StrideType::OuterStrideAtCompileTime), rows, cols, + PlainObjectType::IsVectorAtCompileTime != 0, row_major) == outer_stride); + if (!outer_valid) { + return false; + } + + internal::construct_at(this, expr.data(), rows, cols); + internal::construct_at(&m_stride, (StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride, + (StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride); + return true; + } + + StrideBase m_stride; +}; + +/** \class Ref + * \ingroup Core_Module + * + * \brief A matrix or vector expression mapping an existing expression + * + * \tparam PlainObjectType the equivalent matrix type of the mapped data + * \tparam Options specifies the pointer alignment in bytes. It can be: \c #Aligned128, , \c #Aligned64, \c #Aligned32, + * \c #Aligned16, \c #Aligned8 or \c #Unaligned. The default is \c #Unaligned. \tparam StrideType optionally specifies + * strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1), but accepts a + * variable outer stride (leading dimension). This can be overridden by specifying strides. The type passed here must be + * a specialization of the Stride template, see examples below. + * + * This class provides a way to write non-template functions taking Eigen objects as parameters while limiting the + * number of copies. A Ref<> object can represent either a const expression or a l-value: \code + * // in-out argument: + * void foo1(Ref x); + * + * // read-only const argument: + * void foo2(const Ref& x); + * \endcode + * + * In the in-out case, the input argument must satisfy the constraints of the actual Ref<> type, otherwise a compilation + * issue will be triggered. By default, a Ref can reference any dense vector expression of float having a + * contiguous memory layout. Likewise, a Ref can reference any column-major dense matrix expression of float + * whose column's elements are contiguously stored with the possibility to have a constant space in-between each column, + * i.e. the inner stride must be equal to 1, but the outer stride (or leading dimension) can be greater than the number + * of rows. + * + * In the const case, if the input expression does not match the above requirement, then it is evaluated into a + * temporary before being passed to the function. Here are some examples: \code MatrixXf A; VectorXf a; foo1(a.head()); + * // OK foo1(A.col()); // OK foo1(A.row()); // Compilation error because here innerstride!=1 + * foo2(A.row()); // Compilation error because A.row() is a 1xN object while foo2 is expecting a Nx1 object + * foo2(A.row().transpose()); // The row is copied into a contiguous temporary + * foo2(2*a); // The expression is evaluated into a temporary + * foo2(A.col().segment(2,4)); // No temporary + * \endcode + * + * The range of inputs that can be referenced without temporary can be enlarged using the last two template parameters. + * Here is an example accepting an innerstride!=1: + * \code + * // in-out argument: + * void foo3(Ref > x); + * foo3(A.row()); // OK + * \endcode + * The downside here is that the function foo3 might be significantly slower than foo1 because it won't be able to + * exploit vectorization, and will involve more expensive address computations even if the input is contiguously stored + * in memory. To overcome this issue, one might propose to overload internally calling a template function, e.g.: \code + * // in the .h: + * void foo(const Ref& A); + * void foo(const Ref >& A); + * + * // in the .cpp: + * template void foo_impl(const TypeOfA& A) { + * ... // crazy code goes here + * } + * void foo(const Ref& A) { foo_impl(A); } + * void foo(const Ref >& A) { foo_impl(A); } + * \endcode + * + * See also the following stackoverflow questions for further references: + * - Correct usage of the + * Eigen::Ref<> class + * + * \sa PlainObjectBase::Map(), \ref TopicStorageOrders + */ +template +class Ref : public RefBase > { + private: + typedef internal::traits Traits; + template + EIGEN_DEVICE_FUNC constexpr inline Ref( + const PlainObjectBase& expr, + std::enable_if_t::MatchAtCompileTime), Derived>* = 0); + + public: + typedef RefBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Ref) + +#ifndef EIGEN_PARSED_BY_DOXYGEN + template + EIGEN_DEVICE_FUNC constexpr inline Ref( + PlainObjectBase& expr, + std::enable_if_t::MatchAtCompileTime), Derived>* = 0) { + EIGEN_STATIC_ASSERT(bool(Traits::template match::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); + // Construction must pass since we will not create temporary storage in the non-const case. + const bool success = Base::construct(expr.derived()); + EIGEN_UNUSED_VARIABLE(success) + eigen_assert(success); + } + template + EIGEN_DEVICE_FUNC constexpr inline Ref( + const DenseBase& expr, + std::enable_if_t::MatchAtCompileTime), Derived>* = 0) +#else + /** Implicit constructor from any dense expression */ + template + inline Ref(DenseBase& expr) +#endif + { + EIGEN_STATIC_ASSERT(bool(internal::is_lvalue::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); + EIGEN_STATIC_ASSERT(bool(Traits::template match::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); + EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase, THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); + // Construction must pass since we will not create temporary storage in the non-const case. + const bool success = Base::construct(expr.const_cast_derived()); + EIGEN_UNUSED_VARIABLE(success) + eigen_assert(success); + } + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref) +}; + +// this is the const ref version +template +class Ref + : public RefBase > { + typedef internal::traits Traits; + + static constexpr bool may_map_m_object_successfully = + (static_cast(StrideType::InnerStrideAtCompileTime) == 0 || + static_cast(StrideType::InnerStrideAtCompileTime) == 1 || + static_cast(StrideType::InnerStrideAtCompileTime) == Dynamic) && + (TPlainObjectType::IsVectorAtCompileTime || static_cast(StrideType::OuterStrideAtCompileTime) == 0 || + static_cast(StrideType::OuterStrideAtCompileTime) == Dynamic || + static_cast(StrideType::OuterStrideAtCompileTime) == + static_cast(TPlainObjectType::InnerSizeAtCompileTime) || + static_cast(TPlainObjectType::InnerSizeAtCompileTime) == Dynamic); + + public: + typedef RefBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Ref) + + template + EIGEN_DEVICE_FUNC constexpr inline Ref( + const DenseBase& expr, + std::enable_if_t::ScalarTypeMatch), Derived>* = 0) { + // std::cout << match_helper::HasDirectAccess << "," << match_helper::OuterStrideMatch << "," + // << match_helper::InnerStrideMatch << "\n"; std::cout << int(StrideType::OuterStrideAtCompileTime) + // << " - " << int(Derived::OuterStrideAtCompileTime) << "\n"; std::cout << + // int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n"; + EIGEN_STATIC_ASSERT(Traits::template match::type::value || may_map_m_object_successfully, + STORAGE_LAYOUT_DOES_NOT_MATCH); + construct(expr.derived(), typename Traits::template match::type()); + } + + EIGEN_DEVICE_FUNC constexpr inline Ref(const Ref& other) : Base(other) { + // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy + } + + EIGEN_DEVICE_FUNC constexpr inline Ref(Ref&& other) { + if (other.data() == other.m_object.data()) { + m_object = std::move(other.m_object); + Base::construct(m_object); + } else + Base::construct(other); + } + + template + EIGEN_DEVICE_FUNC constexpr inline Ref(const RefBase& other) { + EIGEN_STATIC_ASSERT(Traits::template match::type::value || may_map_m_object_successfully, + STORAGE_LAYOUT_DOES_NOT_MATCH); + construct(other.derived(), typename Traits::template match::type()); + } + + protected: + template + EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::true_type) { + // Check if we can use the underlying expr's storage directly, otherwise call the copy version. + if (!Base::construct(expr)) { + construct(expr, internal::false_type()); + } + } + + template + EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::false_type) { + internal::call_assignment_no_alias(m_object, expr, internal::assign_op()); + const bool success = Base::construct(m_object); + EIGEN_ONLY_USED_FOR_DEBUG(success) + eigen_assert(success); + } + + protected: + TPlainObjectType m_object; +}; + +} // end namespace Eigen + +#endif // EIGEN_REF_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Replicate.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Replicate.h new file mode 100644 index 0000000..9bdc725 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Replicate.h @@ -0,0 +1,130 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_REPLICATE_H +#define EIGEN_REPLICATE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : traits { + typedef typename MatrixType::Scalar Scalar; + typedef typename traits::StorageKind StorageKind; + typedef typename traits::XprKind XprKind; + typedef typename ref_selector::type MatrixTypeNested; + typedef std::remove_reference_t MatrixTypeNested_; + enum { + RowsAtCompileTime = RowFactor == Dynamic || int(MatrixType::RowsAtCompileTime) == Dynamic + ? Dynamic + : RowFactor * MatrixType::RowsAtCompileTime, + ColsAtCompileTime = ColFactor == Dynamic || int(MatrixType::ColsAtCompileTime) == Dynamic + ? Dynamic + : ColFactor * MatrixType::ColsAtCompileTime, + // FIXME: propagate MaxRowsAtCompileTime and MaxColsAtCompileTime. + MaxRowsAtCompileTime = RowsAtCompileTime, + MaxColsAtCompileTime = ColsAtCompileTime, + IsRowMajor = MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1 ? 1 + : MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1 ? 0 + : (MatrixType::Flags & RowMajorBit) ? 1 + : 0, + + // FIXME: consider enabling DirectAccess with negative strides. + Flags = IsRowMajor ? RowMajorBit : 0 + }; +}; +} // namespace internal + +/** + * \class Replicate + * \ingroup Core_Module + * + * \brief Expression of the multiple replication of a matrix or vector + * + * \tparam MatrixType the type of the object we are replicating + * \tparam RowFactor number of repetitions at compile time along the vertical direction, can be Dynamic. + * \tparam ColFactor number of repetitions at compile time along the horizontal direction, can be Dynamic. + * + * This class represents an expression of the multiple replication of a matrix or vector. + * It is the return type of DenseBase::replicate() and most of the time + * this is the only way it is used. + * + * \sa DenseBase::replicate() + */ +template +class Replicate : public internal::dense_xpr_base >::type { + typedef typename internal::traits::MatrixTypeNested MatrixTypeNested; + typedef typename internal::traits::MatrixTypeNested_ MatrixTypeNested_; + + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Replicate) + typedef internal::remove_all_t NestedExpression; + + template + EIGEN_DEVICE_FUNC constexpr inline explicit Replicate(const OriginalMatrixType& matrix) + : m_matrix(matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor) { + EIGEN_STATIC_ASSERT((internal::is_same, OriginalMatrixType>::value), + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) + eigen_assert(RowFactor != Dynamic && ColFactor != Dynamic); + } + + template + EIGEN_DEVICE_FUNC constexpr inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor) + : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor) { + EIGEN_STATIC_ASSERT((internal::is_same, OriginalMatrixType>::value), + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) + } + + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_matrix.rows() * m_rowFactor.value(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_matrix.cols() * m_colFactor.value(); } + + EIGEN_DEVICE_FUNC constexpr const MatrixTypeNested_& nestedExpression() const { return m_matrix; } + + protected: + MatrixTypeNested m_matrix; + const internal::variable_if_dynamic m_rowFactor; + const internal::variable_if_dynamic m_colFactor; +}; + +/** + * \return an expression of the replication of \c *this + * + * Example: \include MatrixBase_replicate.cpp + * Output: \verbinclude MatrixBase_replicate.out + * + * \sa VectorwiseOp::replicate(), DenseBase::replicate(Index,Index), class Replicate + */ +template +template +EIGEN_DEVICE_FUNC const Replicate DenseBase::replicate() const { + return Replicate(derived()); +} + +/** + * \return an expression of the replication of each column (or row) of \c *this + * + * Example: \include DirectionWise_replicate_int.cpp + * Output: \verbinclude DirectionWise_replicate_int.out + * + * \sa VectorwiseOp::replicate(), DenseBase::replicate(), class Replicate + */ +template +EIGEN_DEVICE_FUNC const typename VectorwiseOp::ReplicateReturnType +VectorwiseOp::replicate(Index factor) const { + return typename VectorwiseOp::ReplicateReturnType( + _expression(), Direction == Vertical ? factor : 1, Direction == Horizontal ? factor : 1); +} + +} // end namespace Eigen + +#endif // EIGEN_REPLICATE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reshaped.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reshaped.h new file mode 100644 index 0000000..5763d6a --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reshaped.h @@ -0,0 +1,363 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2017 Gael Guennebaud +// Copyright (C) 2014 yoco +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_RESHAPED_H +#define EIGEN_RESHAPED_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class Reshaped + * \ingroup Core_Module + * + * \brief Expression of a fixed-size or dynamic-size reshape + * + * \tparam XprType the type of the expression in which we are taking a reshape + * \tparam Rows the number of rows of the reshape we are taking at compile time (optional) + * \tparam Cols the number of columns of the reshape we are taking at compile time (optional) + * \tparam Order can be ColMajor or RowMajor, default is ColMajor. + * + * This class represents an expression of either a fixed-size or dynamic-size reshape. + * It is the return type of DenseBase::reshaped(NRowsType,NColsType) and + * most of the time this is the only way it is used. + * + * If you want to directly manipulate reshaped expressions, + * for instance if you want to write a function returning such an expression, + * it is advised to use the \em auto keyword for such use cases. + * + * Here is an example illustrating the dynamic case: + * \include class_Reshaped.cpp + * Output: \verbinclude class_Reshaped.out + * + * Here is an example illustrating the fixed-size case: + * \include class_FixedReshaped.cpp + * Output: \verbinclude class_FixedReshaped.out + * + * \sa DenseBase::reshaped(NRowsType,NColsType) + */ + +namespace internal { + +template +struct traits > : traits { + typedef typename traits::Scalar Scalar; + typedef typename traits::StorageKind StorageKind; + typedef typename traits::XprKind XprKind; + enum { + MatrixRows = traits::RowsAtCompileTime, + MatrixCols = traits::ColsAtCompileTime, + RowsAtCompileTime = Rows, + ColsAtCompileTime = Cols, + MaxRowsAtCompileTime = Rows, + MaxColsAtCompileTime = Cols, + XpxStorageOrder = ((int(traits::Flags) & RowMajorBit) == RowMajorBit) ? RowMajor : ColMajor, + ReshapedStorageOrder = (RowsAtCompileTime == 1 && ColsAtCompileTime != 1) ? RowMajor + : (ColsAtCompileTime == 1 && RowsAtCompileTime != 1) ? ColMajor + : XpxStorageOrder, + HasSameStorageOrderAsXprType = (ReshapedStorageOrder == XpxStorageOrder), + InnerSize = (ReshapedStorageOrder == int(RowMajor)) ? int(ColsAtCompileTime) : int(RowsAtCompileTime), + InnerStrideAtCompileTime = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time::ret) : Dynamic, + OuterStrideAtCompileTime = Dynamic, + + HasDirectAccess = internal::has_direct_access::ret && (Order == int(XpxStorageOrder)) && + ((evaluator::Flags & LinearAccessBit) == LinearAccessBit), + + MaskPacketAccessBit = + (InnerSize == Dynamic || (InnerSize % packet_traits::size) == 0) && (InnerStrideAtCompileTime == 1) + ? PacketAccessBit + : 0, + // MaskAlignedBit = ((OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) + // == 0)) ? AlignedBit : 0, + FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + FlagsRowMajorBit = (ReshapedStorageOrder == int(RowMajor)) ? RowMajorBit : 0, + FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0, + Flags0 = traits::Flags & ((HereditaryBits & ~RowMajorBit) | MaskPacketAccessBit), + + Flags = (Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit | FlagsDirectAccessBit) + }; +}; + +template +class ReshapedImpl_dense; + +} // end namespace internal + +template +class ReshapedImpl; + +template +class Reshaped : public ReshapedImpl::StorageKind> { + typedef ReshapedImpl::StorageKind> Impl; + + public: + // typedef typename Impl::Base Base; + typedef Impl Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(Reshaped) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reshaped) + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline Reshaped(XprType& xpr) : Impl(xpr) { + EIGEN_STATIC_ASSERT(RowsAtCompileTime != Dynamic && ColsAtCompileTime != Dynamic, + THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) + eigen_assert(Rows * Cols == xpr.rows() * xpr.cols()); + } + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline Reshaped(XprType& xpr, Index reshapeRows, Index reshapeCols) + : Impl(xpr, reshapeRows, reshapeCols) { + eigen_assert((RowsAtCompileTime == Dynamic || RowsAtCompileTime == reshapeRows) && + (ColsAtCompileTime == Dynamic || ColsAtCompileTime == reshapeCols)); + eigen_assert(reshapeRows * reshapeCols == xpr.rows() * xpr.cols()); + } +}; + +// The generic default implementation for dense reshape simply forward to the internal::ReshapedImpl_dense +// that must be specialized for direct and non-direct access... +template +class ReshapedImpl + : public internal::ReshapedImpl_dense >::HasDirectAccess> { + typedef internal::ReshapedImpl_dense >::HasDirectAccess> + Impl; + + public: + typedef Impl Base; + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl) + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl(XprType& xpr) : Impl(xpr) {} + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl(XprType& xpr, Index reshapeRows, Index reshapeCols) + : Impl(xpr, reshapeRows, reshapeCols) {} +}; + +namespace internal { + +/** \internal Internal implementation of dense Reshaped in the general case. */ +template +class ReshapedImpl_dense + : public internal::dense_xpr_base >::type { + typedef Reshaped ReshapedType; + + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense) + + typedef typename internal::ref_selector::non_const_type MatrixTypeNested; + typedef internal::remove_all_t NestedExpression; + + class InnerIterator; + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl_dense(XprType& xpr) : m_xpr(xpr), m_rows(Rows), m_cols(Cols) {} + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols) + : m_xpr(xpr), m_rows(nRows), m_cols(nCols) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const { return m_rows; } + EIGEN_DEVICE_FUNC constexpr Index cols() const { return m_cols; } + +#ifdef EIGEN_PARSED_BY_DOXYGEN + /** \sa MapBase::data() */ + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const; + EIGEN_DEVICE_FUNC inline Index innerStride() const; + EIGEN_DEVICE_FUNC inline Index outerStride() const; +#endif + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { return m_xpr; } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr std::remove_reference_t& nestedExpression() { return m_xpr; } + + protected: + MatrixTypeNested m_xpr; + const internal::variable_if_dynamic m_rows; + const internal::variable_if_dynamic m_cols; +}; + +/** \internal Internal implementation of dense Reshaped in the direct access case. */ +template +class ReshapedImpl_dense : public MapBase > { + typedef Reshaped ReshapedType; + typedef typename internal::ref_selector::non_const_type XprTypeNested; + + public: + typedef MapBase Base; + EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense) + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl_dense(XprType& xpr) : Base(xpr.data()), m_xpr(xpr) {} + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols) + : Base(xpr.data(), nRows, nCols), m_xpr(xpr) {} + + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { return m_xpr; } + + EIGEN_DEVICE_FUNC constexpr XprType& nestedExpression() { return m_xpr; } + + /** \sa MapBase::innerStride() */ + EIGEN_DEVICE_FUNC constexpr Index innerStride() const { return m_xpr.innerStride(); } + + /** \sa MapBase::outerStride() */ + EIGEN_DEVICE_FUNC constexpr Index outerStride() const { + return (((Flags & RowMajorBit) == RowMajorBit) ? this->cols() : this->rows()) * m_xpr.innerStride(); + } + + protected: + XprTypeNested m_xpr; +}; + +// Evaluators +template +struct reshaped_evaluator; + +template +struct evaluator > + : reshaped_evaluator >::HasDirectAccess> { + typedef Reshaped XprType; + typedef typename XprType::Scalar Scalar; + // TODO: should check for smaller packet types + typedef typename packet_traits::type PacketScalar; + + enum { + CoeffReadCost = evaluator::CoeffReadCost, + HasDirectAccess = traits::HasDirectAccess, + + // RowsAtCompileTime = traits::RowsAtCompileTime, + // ColsAtCompileTime = traits::ColsAtCompileTime, + // MaxRowsAtCompileTime = traits::MaxRowsAtCompileTime, + // MaxColsAtCompileTime = traits::MaxColsAtCompileTime, + // + // InnerStrideAtCompileTime = traits::HasSameStorageOrderAsXprType + // ? int(inner_stride_at_compile_time::ret) + // : Dynamic, + // OuterStrideAtCompileTime = Dynamic, + + FlagsLinearAccessBit = + (traits::RowsAtCompileTime == 1 || traits::ColsAtCompileTime == 1 || HasDirectAccess) + ? LinearAccessBit + : 0, + FlagsRowMajorBit = (traits::ReshapedStorageOrder == int(RowMajor)) ? RowMajorBit : 0, + FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0, + Flags0 = evaluator::Flags & (HereditaryBits & ~RowMajorBit), + Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit | FlagsDirectAccessBit, + + PacketAlignment = unpacket_traits::alignment, + Alignment = evaluator::Alignment + }; + typedef reshaped_evaluator reshaped_evaluator_type; + EIGEN_DEVICE_FUNC constexpr explicit evaluator(const XprType& xpr) : reshaped_evaluator_type(xpr) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } +}; + +template +struct reshaped_evaluator + : evaluator_base > { + typedef Reshaped XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost /* TODO + cost of index computations */, + + Flags = (evaluator::Flags & (HereditaryBits /*| LinearAccessBit | DirectAccessBit*/)), + + Alignment = 0 + }; + + EIGEN_DEVICE_FUNC constexpr explicit reshaped_evaluator(const XprType& xpr) + : m_argImpl(xpr.nestedExpression()), m_xpr(xpr) { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + typedef std::pair RowCol; + + EIGEN_DEVICE_FUNC constexpr inline RowCol index_remap(Index rowId, Index colId) const { + if (Order == ColMajor) { + const Index nth_elem_idx = colId * m_xpr.rows() + rowId; + return RowCol(nth_elem_idx % m_xpr.nestedExpression().rows(), nth_elem_idx / m_xpr.nestedExpression().rows()); + } else { + const Index nth_elem_idx = colId + rowId * m_xpr.cols(); + return RowCol(nth_elem_idx / m_xpr.nestedExpression().cols(), nth_elem_idx % m_xpr.nestedExpression().cols()); + } + } + + EIGEN_DEVICE_FUNC constexpr inline Scalar& coeffRef(Index rowId, Index colId) { + EIGEN_STATIC_ASSERT_LVALUE(XprType) + const RowCol row_col = index_remap(rowId, colId); + return m_argImpl.coeffRef(row_col.first, row_col.second); + } + + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeffRef(Index rowId, Index colId) const { + const RowCol row_col = index_remap(rowId, colId); + return m_argImpl.coeffRef(row_col.first, row_col.second); + } + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const { + const RowCol row_col = index_remap(rowId, colId); + return m_argImpl.coeff(row_col.first, row_col.second); + } + + EIGEN_DEVICE_FUNC constexpr inline Scalar& coeffRef(Index index) { + EIGEN_STATIC_ASSERT_LVALUE(XprType) + const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0); + return m_argImpl.coeffRef(row_col.first, row_col.second); + } + + EIGEN_DEVICE_FUNC constexpr inline const Scalar& coeffRef(Index index) const { + const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0); + return m_argImpl.coeffRef(row_col.first, row_col.second); + } + + EIGEN_DEVICE_FUNC constexpr inline const CoeffReturnType coeff(Index index) const { + const RowCol row_col = index_remap(Rows == 1 ? 0 : index, Rows == 1 ? index : 0); + return m_argImpl.coeff(row_col.first, row_col.second); + } + + protected: + evaluator m_argImpl; + const XprType& m_xpr; +}; + +template +struct reshaped_evaluator + : mapbase_evaluator, + typename Reshaped::PlainObject> { + typedef Reshaped XprType; + typedef typename XprType::Scalar Scalar; + + EIGEN_DEVICE_FUNC constexpr explicit reshaped_evaluator(const XprType& xpr) + : mapbase_evaluator(xpr) { + // TODO: for the 3.4 release, this should be turned to an internal assertion, but let's keep it as is for the beta + // lifetime + eigen_assert(((std::uintptr_t(xpr.data()) % plain_enum_max(1, evaluator::Alignment)) == 0) && + "data is not aligned"); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_RESHAPED_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ReturnByValue.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ReturnByValue.h new file mode 100644 index 0000000..410b77d --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/ReturnByValue.h @@ -0,0 +1,111 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// Copyright (C) 2009-2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_RETURNBYVALUE_H +#define EIGEN_RETURNBYVALUE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct traits > : public traits::ReturnType> { + enum { + // We're disabling the DirectAccess because e.g. the constructor of + // the Block-with-DirectAccess expression requires to have a coeffRef method. + // Also, this avoids having to implement stride support. + Flags = (traits::ReturnType>::Flags | EvalBeforeNestingBit) & ~DirectAccessBit + }; +}; + +/* The ReturnByValue object doesn't even have a coeff() method. + * So the only way that nesting it in an expression can work, is by evaluating it into a plain matrix. + * So internal::nested always gives the plain return matrix type. + * + * FIXME: this specialization may be redundant with EvalBeforeNestingBit. + * Answer: EvalBeforeNestingBit should be deprecated since we have the evaluators + */ +template +struct nested_eval, n, PlainObject> { + typedef typename traits::ReturnType type; +}; + +} // end namespace internal + +/** \class ReturnByValue + * \ingroup Core_Module + * + */ +template +class ReturnByValue : public internal::dense_xpr_base >::type, internal::no_assignment_operator { + public: + typedef typename internal::traits::ReturnType ReturnType; + + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(ReturnByValue) + + template + EIGEN_DEVICE_FUNC inline void evalTo(Dest& dst) const { + static_cast(this)->evalTo(dst); + } + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return static_cast(this)->rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return static_cast(this)->cols(); } + +#ifndef EIGEN_PARSED_BY_DOXYGEN +#define Unusable \ + YOU_ARE_TRYING_TO_ACCESS_A_SINGLE_COEFFICIENT_IN_A_SPECIAL_EXPRESSION_WHERE_THAT_IS_NOT_ALLOWED_BECAUSE_THAT_WOULD_BE_INEFFICIENT + class Unusable { + Unusable(const Unusable&) {} + Unusable& operator=(const Unusable&) { return *this; } + }; + const Unusable& coeff(Index) const { return *reinterpret_cast(this); } + const Unusable& coeff(Index, Index) const { return *reinterpret_cast(this); } + Unusable& coeffRef(Index) { return *reinterpret_cast(this); } + Unusable& coeffRef(Index, Index) { return *reinterpret_cast(this); } +#undef Unusable +#endif +}; + +template +template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator=(const ReturnByValue& other) { + other.evalTo(derived()); + return derived(); +} + +namespace internal { + +// Expression is evaluated in a temporary; default implementation of Assignment is bypassed so that +// when a ReturnByValue expression is assigned, the evaluator is not constructed. +// TODO: Finalize port to new regime; ReturnByValue should not exist in the expression world + +template +struct evaluator > : public evaluator::ReturnType> { + typedef ReturnByValue XprType; + typedef typename internal::traits::ReturnType PlainObject; + typedef evaluator Base; + + EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : m_result(xpr.rows(), xpr.cols()) { + internal::construct_at(this, m_result); + xpr.evalTo(m_result); + } + + protected: + PlainObject m_result; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_RETURNBYVALUE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reverse.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reverse.h new file mode 100644 index 0000000..a4af8d1 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Reverse.h @@ -0,0 +1,202 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2009 Ricard Marxer +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_REVERSE_H +#define EIGEN_REVERSE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct traits > : traits { + typedef typename MatrixType::Scalar Scalar; + typedef typename traits::StorageKind StorageKind; + typedef typename traits::XprKind XprKind; + typedef typename ref_selector::type MatrixTypeNested; + typedef std::remove_reference_t MatrixTypeNested_; + enum { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, + Flags = MatrixTypeNested_::Flags & (RowMajorBit | LvalueBit) + }; +}; + +template +struct reverse_packet_cond { + static inline PacketType run(const PacketType& x) { return preverse(x); } +}; + +template +struct reverse_packet_cond { + static inline PacketType run(const PacketType& x) { return x; } +}; + +} // end namespace internal + +/** \class Reverse + * \ingroup Core_Module + * + * \brief Expression of the reverse of a vector or matrix + * + * \tparam MatrixType the type of the object of which we are taking the reverse + * \tparam Direction defines the direction of the reverse operation, can be Vertical, Horizontal, or BothDirections + * + * This class represents an expression of the reverse of a vector. + * It is the return type of MatrixBase::reverse() and VectorwiseOp::reverse() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::reverse(), VectorwiseOp::reverse() + */ +template +class Reverse : public internal::dense_xpr_base >::type { + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Reverse) + typedef internal::remove_all_t NestedExpression; + using Base::IsRowMajor; + + protected: + enum { + PacketSize = internal::packet_traits::size, + IsColMajor = !IsRowMajor, + ReverseRow = (Direction == Vertical) || (Direction == BothDirections), + ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), + OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1, + OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, + ReversePacket = (Direction == BothDirections) || ((Direction == Vertical) && IsColMajor) || + ((Direction == Horizontal) && IsRowMajor) + }; + typedef internal::reverse_packet_cond reverse_packet; + + public: + EIGEN_DEVICE_FUNC constexpr explicit inline Reverse(const MatrixType& matrix) : m_matrix(matrix) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse) + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); } + + EIGEN_DEVICE_FUNC inline Index innerStride() const { return -m_matrix.innerStride(); } + + EIGEN_DEVICE_FUNC constexpr const internal::remove_all_t& nestedExpression() const { + return m_matrix; + } + + protected: + typename MatrixType::Nested m_matrix; +}; + +/** \returns an expression of the reverse of *this. + * + * Example: \include MatrixBase_reverse.cpp + * Output: \verbinclude MatrixBase_reverse.out + * + */ +template +EIGEN_DEVICE_FUNC inline typename DenseBase::ReverseReturnType DenseBase::reverse() { + return ReverseReturnType(derived()); +} + +// reverse const overload moved DenseBase.h due to a CUDA compiler bug + +/** This is the "in place" version of reverse: it reverses \c *this. + * + * In most cases it is probably better to simply use the reversed expression + * of a matrix. However, when reversing the matrix data itself is really needed, + * then this "in-place" version is probably the right choice because it provides + * the following additional benefits: + * - less error prone: doing the same operation with .reverse() requires special care: + * \code m = m.reverse().eval(); \endcode + * - this API enables reverse operations without the need for a temporary + * - it allows future optimizations (cache friendliness, etc.) + * + * \sa VectorwiseOp::reverseInPlace(), reverse() */ +template +EIGEN_DEVICE_FUNC inline void DenseBase::reverseInPlace() { + constexpr int HalfRowsAtCompileTime = RowsAtCompileTime == Dynamic ? Dynamic : RowsAtCompileTime / 2; + constexpr int HalfColsAtCompileTime = ColsAtCompileTime == Dynamic ? Dynamic : ColsAtCompileTime / 2; + if (cols() > rows()) { + Index half = cols() / 2; + this->template leftCols(half).swap( + this->template rightCols(half).reverse()); + if ((cols() % 2) == 1) { + Index half2 = rows() / 2; + col(half).template head(half2).swap( + col(half).template tail(half2).reverse()); + } + } else { + Index half = rows() / 2; + this->template topRows(half).swap( + this->template bottomRows(half).reverse()); + if ((rows() % 2) == 1) { + Index half2 = cols() / 2; + row(half).template head(half2).swap( + row(half).template tail(half2).reverse()); + } + } +} + +namespace internal { + +template +struct vectorwise_reverse_inplace_impl; + +template <> +struct vectorwise_reverse_inplace_impl { + template + static void run(ExpressionType& xpr) { + constexpr Index HalfAtCompileTime = + ExpressionType::RowsAtCompileTime == Dynamic ? Dynamic : ExpressionType::RowsAtCompileTime / 2; + Index half = xpr.rows() / 2; + xpr.template topRows(half).swap( + xpr.template bottomRows(half).colwise().reverse()); + } +}; + +template <> +struct vectorwise_reverse_inplace_impl { + template + static void run(ExpressionType& xpr) { + constexpr Index HalfAtCompileTime = + ExpressionType::ColsAtCompileTime == Dynamic ? Dynamic : ExpressionType::ColsAtCompileTime / 2; + Index half = xpr.cols() / 2; + xpr.template leftCols(half).swap( + xpr.template rightCols(half).rowwise().reverse()); + } +}; + +} // end namespace internal + +/** This is the "in place" version of VectorwiseOp::reverse: it reverses each column or row of \c *this. + * + * In most cases it is probably better to simply use the reversed expression + * of a matrix. However, when reversing the matrix data itself is really needed, + * then this "in-place" version is probably the right choice because it provides + * the following additional benefits: + * - less error prone: doing the same operation with .reverse() requires special care: + * \code m = m.reverse().eval(); \endcode + * - this API enables reverse operations without the need for a temporary + * + * \sa DenseBase::reverseInPlace(), reverse() */ +template +EIGEN_DEVICE_FUNC void VectorwiseOp::reverseInPlace() { + internal::vectorwise_reverse_inplace_impl::run(m_matrix); +} + +} // end namespace Eigen + +#endif // EIGEN_REVERSE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Select.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Select.h new file mode 100644 index 0000000..6ad290f --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Select.h @@ -0,0 +1,92 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SELECT_H +#define EIGEN_SELECT_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \typedef Select + * \ingroup Core_Module + * + * \brief Expression of a coefficient wise version of the C++ ternary operator ?: + * + * \tparam ConditionMatrixType the type of the \em condition expression which must be a boolean matrix + * \tparam ThenMatrixType the type of the \em then expression + * \tparam ElseMatrixType the type of the \em else expression + * + * This type represents an expression of a coefficient wise version of the C++ ternary operator ?:. + * It is the return type of DenseBase::select() and most of the time this is the only way it is used. + * + * \sa DenseBase::select(const DenseBase&, const DenseBase&) const + */ +template +using Select = CwiseTernaryOp::Scalar, + typename DenseBase::Scalar, + typename DenseBase::Scalar>, + ThenMatrixType, ElseMatrixType, ConditionMatrixType>; + +/** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j) + * if \c *this(i,j) != Scalar(0), and \a elseMatrix(i,j) otherwise. + * + * Example: \include MatrixBase_select.cpp + * Output: \verbinclude MatrixBase_select.out + * + * \sa typedef Select + */ +template +template +inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, typename DenseBase::Scalar, + typename DenseBase::Scalar>, + ThenDerived, ElseDerived, Derived> +DenseBase::select(const DenseBase& thenMatrix, const DenseBase& elseMatrix) const { + return Select(thenMatrix.derived(), elseMatrix.derived(), derived()); +} +/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with + * the \em else expression being a scalar value. + * + * \sa typedef Select + */ +template +template +inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, typename DenseBase::Scalar, + typename DenseBase::Scalar>, + ThenDerived, typename DenseBase::ConstantReturnType, Derived> +DenseBase::select(const DenseBase& thenMatrix, + const typename DenseBase::Scalar& elseScalar) const { + using ElseConstantType = typename DenseBase::ConstantReturnType; + return Select(thenMatrix.derived(), + ElseConstantType(rows(), cols(), elseScalar), derived()); +} +/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with + * the \em then expression being a scalar value. + * + * \sa typedef Select + */ +template +template +inline EIGEN_DEVICE_FUNC constexpr CwiseTernaryOp< + internal::scalar_boolean_select_op::Scalar, typename DenseBase::Scalar, + typename DenseBase::Scalar>, + typename DenseBase::ConstantReturnType, ElseDerived, Derived> +DenseBase::select(const typename DenseBase::Scalar& thenScalar, + const DenseBase& elseMatrix) const { + using ThenConstantType = typename DenseBase::ConstantReturnType; + return Select(ThenConstantType(rows(), cols(), thenScalar), + elseMatrix.derived(), derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_SELECT_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfAdjointView.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfAdjointView.h new file mode 100644 index 0000000..62d0729 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfAdjointView.h @@ -0,0 +1,329 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SELFADJOINTMATRIX_H +#define EIGEN_SELFADJOINTMATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class SelfAdjointView + * \ingroup Core_Module + * + * + * \brief Expression of a selfadjoint matrix from a triangular part of a dense matrix + * + * \tparam MatrixType the type of the dense matrix storing the coefficients + * \tparam TriangularPart can be either \c #Lower or \c #Upper + * + * This class is an expression of a sefladjoint matrix from a triangular part of a matrix + * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView() + * and most of the time this is the only way that it is used. + * + * \sa class TriangularBase, MatrixBase::selfadjointView() + */ + +namespace internal { +template +struct traits > : traits { + typedef typename ref_selector::non_const_type MatrixTypeNested; + typedef remove_all_t MatrixTypeNestedCleaned; + typedef MatrixType ExpressionType; + typedef typename MatrixType::PlainObject FullMatrixType; + enum { + Mode = UpLo | SelfAdjoint, + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + Flags = MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) & + (~(PacketAccessBit | DirectAccessBit | LinearAccessBit)) // FIXME these flags should be preserved + }; +}; +} // namespace internal + +template +class SelfAdjointView : public TriangularBase > { + public: + EIGEN_STATIC_ASSERT(UpLo == Lower || UpLo == Upper, SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY) + + typedef MatrixType_ MatrixType; + typedef TriangularBase Base; + typedef typename internal::traits::MatrixTypeNested MatrixTypeNested; + typedef typename internal::traits::MatrixTypeNestedCleaned MatrixTypeNestedCleaned; + typedef MatrixTypeNestedCleaned NestedExpression; + + /** \brief The type of coefficients in this matrix */ + typedef typename internal::traits::Scalar Scalar; + typedef typename MatrixType::StorageIndex StorageIndex; + typedef internal::remove_all_t MatrixConjugateReturnType; + typedef SelfAdjointView, UpLo> ConstSelfAdjointView; + + enum { + Mode = internal::traits::Mode, + Flags = internal::traits::Flags, + TransposeMode = ((int(Mode) & int(Upper)) ? Lower : 0) | ((int(Mode) & int(Lower)) ? Upper : 0) + }; + typedef typename MatrixType::PlainObject PlainObject; + + EIGEN_DEVICE_FUNC explicit inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return m_matrix.outerStride(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_matrix.innerStride(); } + + /** \sa MatrixBase::coeff() + * \warning the coordinates must fit into the referenced triangular part + */ + EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const { + Base::check_coordinates_internal(row, col); + return m_matrix.coeff(row, col); + } + + /** \sa MatrixBase::coeffRef() + * \warning the coordinates must fit into the referenced triangular part + */ + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) { + EIGEN_STATIC_ASSERT_LVALUE(SelfAdjointView); + Base::check_coordinates_internal(row, col); + return m_matrix.coeffRef(row, col); + } + + /** \internal */ + EIGEN_DEVICE_FUNC const MatrixTypeNestedCleaned& _expression() const { return m_matrix; } + + EIGEN_DEVICE_FUNC const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } + EIGEN_DEVICE_FUNC MatrixTypeNestedCleaned& nestedExpression() { return m_matrix; } + + /** Efficient triangular matrix times vector/matrix product */ + template + EIGEN_DEVICE_FUNC const Product operator*(const MatrixBase& rhs) const { + return Product(*this, rhs.derived()); + } + + /** Efficient vector/matrix times triangular matrix product */ + template + friend EIGEN_DEVICE_FUNC const Product operator*(const MatrixBase& lhs, + const SelfAdjointView& rhs) { + return Product(lhs.derived(), rhs); + } + + friend EIGEN_DEVICE_FUNC const + SelfAdjointView + operator*(const Scalar& s, const SelfAdjointView& mat) { + return (s * mat.nestedExpression()).template selfadjointView(); + } + + /** Perform a symmetric rank 2 update of the selfadjoint matrix \c *this: + * \f$ this = this + \alpha u v^* + conj(\alpha) v u^* \f$ + * \returns a reference to \c *this + * + * The vectors \a u and \c v \b must be column vectors, however they can be + * a adjoint expression without any overhead. Only the meaningful triangular + * part of the matrix is updated, the rest is left unchanged. + * + * \sa rankUpdate(const MatrixBase&, Scalar) + */ + template + EIGEN_DEVICE_FUNC SelfAdjointView& rankUpdate(const MatrixBase& u, const MatrixBase& v, + const Scalar& alpha = Scalar(1)); + + /** Perform a symmetric rank K update of the selfadjoint matrix \c *this: + * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix. + * + * \returns a reference to \c *this + * + * Note that to perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply + * call this function with u.adjoint(). + * + * \sa rankUpdate(const MatrixBase&, const MatrixBase&, Scalar) + */ + template + EIGEN_DEVICE_FUNC SelfAdjointView& rankUpdate(const MatrixBase& u, const Scalar& alpha = Scalar(1)); + + /** \returns an expression of a triangular view extracted from the current selfadjoint view of a given triangular part + * + * The parameter \a TriMode can have the following values: \c #Upper, \c #StrictlyUpper, \c #UnitUpper, + * \c #Lower, \c #StrictlyLower, \c #UnitLower. + * + * If \c TriMode references the same triangular part than \c *this, then this method simply return a \c TriangularView + * of the nested expression, otherwise, the nested expression is first transposed, thus returning a \c + * TriangularView> object. + * + * \sa MatrixBase::triangularView(), class TriangularView + */ + template + EIGEN_DEVICE_FUNC + std::conditional_t<(TriMode & (Upper | Lower)) == (UpLo & (Upper | Lower)), TriangularView, + TriangularView > + triangularView() const { + std::conditional_t<(TriMode & (Upper | Lower)) == (UpLo & (Upper | Lower)), MatrixType&, + typename MatrixType::ConstTransposeReturnType> + tmp1(m_matrix); + std::conditional_t<(TriMode & (Upper | Lower)) == (UpLo & (Upper | Lower)), MatrixType&, + typename MatrixType::AdjointReturnType> + tmp2(tmp1); + return std::conditional_t<(TriMode & (Upper | Lower)) == (UpLo & (Upper | Lower)), + TriangularView, + TriangularView >(tmp2); + } + + typedef SelfAdjointView ConjugateReturnType; + /** \sa MatrixBase::conjugate() const */ + EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const { + return ConjugateReturnType(m_matrix.conjugate()); + } + + /** \returns an expression of the complex conjugate of \c *this if Cond==true, + * returns \c *this otherwise. + */ + template + EIGEN_DEVICE_FUNC inline std::conditional_t conjugateIf() const { + typedef std::conditional_t ReturnType; + return ReturnType(m_matrix.template conjugateIf()); + } + + typedef SelfAdjointView AdjointReturnType; + /** \sa MatrixBase::adjoint() const */ + EIGEN_DEVICE_FUNC inline const AdjointReturnType adjoint() const { return AdjointReturnType(m_matrix.adjoint()); } + + typedef SelfAdjointView TransposeReturnType; + /** \sa MatrixBase::transpose() */ + template + EIGEN_DEVICE_FUNC inline TransposeReturnType transpose( + std::enable_if_t::value, Dummy*> = nullptr) { + typename MatrixType::TransposeReturnType tmp(m_matrix); + return TransposeReturnType(tmp); + } + + typedef SelfAdjointView ConstTransposeReturnType; + /** \sa MatrixBase::transpose() const */ + EIGEN_DEVICE_FUNC inline const ConstTransposeReturnType transpose() const { + return ConstTransposeReturnType(m_matrix.transpose()); + } + + /** \returns a const expression of the main diagonal of the matrix \c *this + * + * This method simply returns the diagonal of the nested expression, thus by-passing the SelfAdjointView decorator. + * + * \sa MatrixBase::diagonal(), class Diagonal */ + EIGEN_DEVICE_FUNC typename MatrixType::ConstDiagonalReturnType diagonal() const { + return typename MatrixType::ConstDiagonalReturnType(m_matrix); + } + + /////////// Cholesky module /////////// + + LLT llt() const; + LDLT ldlt() const; + + /////////// Eigenvalue module /////////// + + /** Real part of #Scalar */ + typedef typename NumTraits::Real RealScalar; + /** Return type of eigenvalues() */ + typedef Matrix::ColsAtCompileTime, 1> EigenvaluesReturnType; + + EIGEN_DEVICE_FUNC EigenvaluesReturnType eigenvalues() const; + EIGEN_DEVICE_FUNC RealScalar operatorNorm() const; + + protected: + MatrixTypeNested m_matrix; +}; + +// selfadjoint to dense matrix + +namespace internal { + +// TODO currently a selfadjoint expression has the form SelfAdjointView<.,.> +// in the future selfadjoint-ness should be defined by the expression traits +// such that Transpose > is valid. (currently TriangularBase::transpose() is overloaded to +// make it work) +template +struct evaluator_traits > { + typedef typename storage_kind_to_evaluator_kind::Kind Kind; + typedef SelfAdjointShape Shape; +}; + +template +class triangular_dense_assignment_kernel + : public generic_dense_assignment_kernel { + protected: + typedef generic_dense_assignment_kernel Base; + typedef typename Base::DstXprType DstXprType; + typedef typename Base::SrcXprType SrcXprType; + using Base::m_dst; + using Base::m_functor; + using Base::m_src; + + public: + typedef typename Base::DstEvaluatorType DstEvaluatorType; + typedef typename Base::SrcEvaluatorType SrcEvaluatorType; + typedef typename Base::Scalar Scalar; + typedef typename Base::AssignmentTraits AssignmentTraits; + + EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst, const SrcEvaluatorType& src, + const Functor& func, DstXprType& dstExpr) + : Base(dst, src, func, dstExpr) {} + + EIGEN_DEVICE_FUNC void assignCoeff(Index row, Index col) { + eigen_internal_assert(row != col); + Scalar tmp = m_src.coeff(row, col); + m_functor.assignCoeff(m_dst.coeffRef(row, col), tmp); + m_functor.assignCoeff(m_dst.coeffRef(col, row), numext::conj(tmp)); + } + + // Override to ensure the SelfAdjoint assignCoeff (which mirrors conjugates) is called, + // not the base class version (which is a plain copy). + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner) { + Index row = Base::rowIndexByOuterInner(outer, inner); + Index col = Base::colIndexByOuterInner(outer, inner); + assignCoeff(row, col); + } + + EIGEN_DEVICE_FUNC void assignDiagonalCoeff(Index id) { Base::assignCoeff(id, id); } + + EIGEN_DEVICE_FUNC void assignOppositeCoeff(Index, Index) { eigen_internal_assert(false && "should never be called"); } +}; + +} // end namespace internal + +/*************************************************************************** + * Implementation of MatrixBase methods + ***************************************************************************/ + +/** This is the const version of MatrixBase::selfadjointView() */ +template +template +EIGEN_DEVICE_FUNC constexpr typename MatrixBase::template ConstSelfAdjointViewReturnType::Type +MatrixBase::selfadjointView() const { + return typename ConstSelfAdjointViewReturnType::Type(derived()); +} + +/** \returns an expression of a symmetric/self-adjoint view extracted from the upper or lower triangular part of the + * current matrix + * + * The parameter \a UpLo can be either \c #Upper or \c #Lower + * + * Example: \include MatrixBase_selfadjointView.cpp + * Output: \verbinclude MatrixBase_selfadjointView.out + * + * \sa class SelfAdjointView + */ +template +template +EIGEN_DEVICE_FUNC constexpr typename MatrixBase::template SelfAdjointViewReturnType::Type +MatrixBase::selfadjointView() { + return typename SelfAdjointViewReturnType::Type(derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_SELFADJOINTMATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h new file mode 100644 index 0000000..a887ad2 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h @@ -0,0 +1,50 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SELFCWISEBINARYOP_H +#define EIGEN_SELFCWISEBINARYOP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) { + using ConstantExpr = typename internal::plain_constant_type::type; + using Op = internal::mul_assign_op; + internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const RealScalar& other) { + realView() *= other; + return derived(); +} + +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) { + using ConstantExpr = typename internal::plain_constant_type::type; + using Op = internal::div_assign_op; + internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const RealScalar& other) { + realView() /= other; + return derived(); +} + +} // end namespace Eigen + +#endif // EIGEN_SELFCWISEBINARYOP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SkewSymmetricMatrix3.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SkewSymmetricMatrix3.h new file mode 100644 index 0000000..a6ad143 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SkewSymmetricMatrix3.h @@ -0,0 +1,382 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// Copyright (C) 2007-2009 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SKEWSYMMETRICMATRIX3_H +#define EIGEN_SKEWSYMMETRICMATRIX3_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class SkewSymmetricBase + * \ingroup Core_Module + * + * \brief Base class for skew symmetric matrices and expressions + * + * This is the base class that is inherited by SkewSymmetricMatrix3 and related expression + * types, which internally use a three vector for storing the entries. SkewSymmetric + * types always represent square three times three matrices. + * + * This implementations follows class DiagonalMatrix + * + * \tparam Derived is the derived type, a SkewSymmetricMatrix3 or SkewSymmetricWrapper. + * + * \sa class SkewSymmetricMatrix3, class SkewSymmetricWrapper + */ +template +class SkewSymmetricBase : public EigenBase { + public: + typedef typename internal::traits::SkewSymmetricVectorType SkewSymmetricVectorType; + typedef typename SkewSymmetricVectorType::Scalar Scalar; + typedef typename SkewSymmetricVectorType::RealScalar RealScalar; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; + + enum { + RowsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, + ColsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, + MaxRowsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, + MaxColsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, + IsVectorAtCompileTime = 0, + Flags = NoPreferredStorageOrderBit + }; + + typedef Matrix + DenseMatrixType; + typedef DenseMatrixType DenseType; + typedef SkewSymmetricMatrix3 PlainObject; + + /** \returns a reference to the derived object. */ + EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast(this); } + /** \returns a const reference to the derived object. */ + EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast(this); } + + /** + * Constructs a dense matrix from \c *this. Note, this directly returns a dense matrix type, + * not an expression. + * \returns A dense matrix, with its entries set from the derived object. */ + EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); } + + /** Determinant vanishes */ + EIGEN_DEVICE_FUNC constexpr Scalar determinant() const { return 0; } + + /** A.transpose() = -A */ + EIGEN_DEVICE_FUNC PlainObject transpose() const { return (-vector()).asSkewSymmetric(); } + + /** \returns the exponential of this matrix using Rodrigues’ formula */ + EIGEN_DEVICE_FUNC DenseMatrixType exponential() const { + DenseMatrixType retVal = DenseMatrixType::Identity(); + const SkewSymmetricVectorType& v = vector(); + if (v.isZero()) { + return retVal; + } + const Scalar norm2 = v.squaredNorm(); + const Scalar norm = numext::sqrt(norm2); + retVal += ((((1 - numext::cos(norm)) / norm2) * derived()) * derived()) + + (numext::sin(norm) / norm) * derived().toDenseMatrix(); + return retVal; + } + + /** \returns a reference to the derived object's vector of coefficients. */ + EIGEN_DEVICE_FUNC inline const SkewSymmetricVectorType& vector() const { return derived().vector(); } + /** \returns a const reference to the derived object's vector of coefficients. */ + EIGEN_DEVICE_FUNC inline SkewSymmetricVectorType& vector() { return derived().vector(); } + + /** \returns the number of rows. */ + EIGEN_DEVICE_FUNC constexpr Index rows() const { return 3; } + /** \returns the number of columns. */ + EIGEN_DEVICE_FUNC constexpr Index cols() const { return 3; } + + /** \returns the matrix product of \c *this by the dense matrix, \a matrix */ + template + EIGEN_DEVICE_FUNC Product operator*( + const MatrixBase& matrix) const { + return Product(derived(), matrix.derived()); + } + + /** \returns the matrix product of \c *this by the skew symmetric matrix, \a matrix */ + template + EIGEN_DEVICE_FUNC Product operator*( + const SkewSymmetricBase& matrix) const { + return Product(derived(), matrix.derived()); + } + + template + using SkewSymmetricProductReturnType = SkewSymmetricWrapper; + + /** \returns the wedge product of \c *this by the skew symmetric matrix \a other + * A wedge B = AB - BA */ + template + EIGEN_DEVICE_FUNC SkewSymmetricProductReturnType wedge( + const SkewSymmetricBase& other) const { + return vector().cross(other.vector()).asSkewSymmetric(); + } + + using SkewSymmetricScaleReturnType = + SkewSymmetricWrapper; + + /** \returns the product of \c *this by the scalar \a scalar */ + EIGEN_DEVICE_FUNC inline SkewSymmetricScaleReturnType operator*(const Scalar& scalar) const { + return (vector() * scalar).asSkewSymmetric(); + } + + using ScaleSkewSymmetricReturnType = + SkewSymmetricWrapper; + + /** \returns the product of a scalar and the skew symmetric matrix \a other */ + EIGEN_DEVICE_FUNC friend inline ScaleSkewSymmetricReturnType operator*(const Scalar& scalar, + const SkewSymmetricBase& other) { + return (scalar * other.vector()).asSkewSymmetric(); + } + + template + using SkewSymmetricSumReturnType = SkewSymmetricWrapper; + + /** \returns the sum of \c *this and the skew symmetric matrix \a other */ + template + EIGEN_DEVICE_FUNC inline SkewSymmetricSumReturnType operator+( + const SkewSymmetricBase& other) const { + return (vector() + other.vector()).asSkewSymmetric(); + } + + template + using SkewSymmetricDifferenceReturnType = SkewSymmetricWrapper; + + /** \returns the difference of \c *this and the skew symmetric matrix \a other */ + template + EIGEN_DEVICE_FUNC inline SkewSymmetricDifferenceReturnType operator-( + const SkewSymmetricBase& other) const { + return (vector() - other.vector()).asSkewSymmetric(); + } +}; + +/** \class SkewSymmetricMatrix3 + * \ingroup Core_Module + * + * \brief Represents a 3x3 skew symmetric matrix with its storage + * + * \tparam Scalar_ the type of coefficients + * + * \sa class SkewSymmetricBase, class SkewSymmetricWrapper + */ + +namespace internal { +template +struct traits> : traits> { + typedef Matrix SkewSymmetricVectorType; + typedef SkewSymmetricShape StorageKind; + enum { Flags = LvalueBit | NoPreferredStorageOrderBit | NestByRefBit }; +}; +} // namespace internal +template +class SkewSymmetricMatrix3 : public SkewSymmetricBase> { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename internal::traits::SkewSymmetricVectorType SkewSymmetricVectorType; + typedef const SkewSymmetricMatrix3& Nested; + typedef Scalar_ Scalar; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; +#endif + + protected: + SkewSymmetricVectorType m_vector; + + public: + /** const version of vector(). */ + EIGEN_DEVICE_FUNC inline const SkewSymmetricVectorType& vector() const { return m_vector; } + /** \returns a reference to the stored vector of coefficients. */ + EIGEN_DEVICE_FUNC inline SkewSymmetricVectorType& vector() { return m_vector; } + + /** Default constructor without initialization */ + EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3() {} + + /** Constructor from three scalars */ + EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3(const Scalar& x, const Scalar& y, const Scalar& z) + : m_vector(x, y, z) {} + + /** \brief Constructs a SkewSymmetricMatrix3 from an r-value vector type */ + EIGEN_DEVICE_FUNC explicit inline SkewSymmetricMatrix3(SkewSymmetricVectorType&& vec) : m_vector(std::move(vec)) {} + + /** generic constructor from expression of the coefficients */ + template + EIGEN_DEVICE_FUNC explicit inline SkewSymmetricMatrix3(const MatrixBase& other) : m_vector(other) {} + + /** Copy constructor. */ + template + EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3(const SkewSymmetricBase& other) + : m_vector(other.vector()) {} + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */ + inline SkewSymmetricMatrix3(const SkewSymmetricMatrix3& other) : m_vector(other.vector()) {} +#endif + + /** Copy operator. */ + template + EIGEN_DEVICE_FUNC SkewSymmetricMatrix3& operator=(const SkewSymmetricBase& other) { + m_vector = other.vector(); + return *this; + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + EIGEN_DEVICE_FUNC SkewSymmetricMatrix3& operator=(const SkewSymmetricMatrix3& other) { + m_vector = other.vector(); + return *this; + } +#endif + + typedef SkewSymmetricWrapper, SkewSymmetricVectorType>> + InitializeReturnType; + + /** Initializes a skew symmetric matrix with coefficients set to zero */ + EIGEN_DEVICE_FUNC static InitializeReturnType Zero() { return SkewSymmetricVectorType::Zero().asSkewSymmetric(); } + + /** Sets all coefficients to zero. */ + EIGEN_DEVICE_FUNC inline void setZero() { m_vector.setZero(); } +}; + +/** \class SkewSymmetricWrapper + * \ingroup Core_Module + * + * \brief Expression of a skew symmetric matrix + * + * \tparam SkewSymmetricVectorType_ the type of the vector of coefficients + * + * This class is an expression of a skew symmetric matrix, but not storing its own vector of coefficients, + * instead wrapping an existing vector expression. It is the return type of MatrixBase::asSkewSymmetric() + * and most of the time this is the only way that it is used. + * + * \sa class SkewSymmetricMatrix3, class SkewSymmetricBase, MatrixBase::asSkewSymmetric() + */ + +namespace internal { +template +struct traits> { + typedef SkewSymmetricVectorType_ SkewSymmetricVectorType; + typedef typename SkewSymmetricVectorType::Scalar Scalar; + typedef typename SkewSymmetricVectorType::StorageIndex StorageIndex; + typedef SkewSymmetricShape StorageKind; + typedef typename traits::XprKind XprKind; + enum { + RowsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, + ColsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, + MaxRowsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, + MaxColsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, + Flags = (traits::Flags & LvalueBit) | NoPreferredStorageOrderBit + }; +}; +} // namespace internal + +template +class SkewSymmetricWrapper : public SkewSymmetricBase>, + internal::no_assignment_operator { + public: +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef SkewSymmetricVectorType_ SkewSymmetricVectorType; + typedef SkewSymmetricWrapper Nested; +#endif + + /** Constructor from expression of coefficients to wrap. */ + EIGEN_DEVICE_FUNC explicit inline SkewSymmetricWrapper(SkewSymmetricVectorType& a_vector) : m_vector(a_vector) {} + + /** \returns a const reference to the wrapped expression of coefficients. */ + EIGEN_DEVICE_FUNC const SkewSymmetricVectorType& vector() const { return m_vector; } + + protected: + typename SkewSymmetricVectorType::Nested m_vector; +}; + +/** \returns a pseudo-expression of a skew symmetric matrix with *this as vector of coefficients + * + * \only_for_vectors + * + * \sa class SkewSymmetricWrapper, class SkewSymmetricMatrix3, vector(), isSkewSymmetric() + **/ +template +EIGEN_DEVICE_FUNC constexpr const SkewSymmetricWrapper MatrixBase::asSkewSymmetric() const { + return SkewSymmetricWrapper(derived()); +} + +/** \returns true if *this is approximately equal to a skew symmetric matrix, + * within the precision given by \a prec. + */ +template +bool MatrixBase::isSkewSymmetric(const RealScalar& prec) const { + if (cols() != rows()) return false; + return (this->transpose() + *this).isZero(prec); +} + +/** \returns the matrix product of \c *this by the skew symmetric matrix \a skew. + */ +template +template +EIGEN_DEVICE_FUNC inline const Product MatrixBase::operator*( + const SkewSymmetricBase& skew) const { + return Product(derived(), skew.derived()); +} + +namespace internal { + +template <> +struct storage_kind_to_shape { + typedef SkewSymmetricShape Shape; +}; + +struct SkewSymmetric2Dense {}; + +template <> +struct AssignmentKind { + typedef SkewSymmetric2Dense Kind; +}; + +// SkewSymmetric matrix to Dense assignment +template +struct Assignment { + EIGEN_DEVICE_FUNC static void run( + DstXprType& dst, const SrcXprType& src, + const internal::assign_op& /*func*/) { + if ((dst.rows() != 3) || (dst.cols() != 3)) { + dst.resize(3, 3); + } + dst.diagonal().setZero(); + const typename SrcXprType::SkewSymmetricVectorType v = src.vector(); + dst(0, 1) = -v(2); + dst(1, 0) = v(2); + dst(0, 2) = v(1); + dst(2, 0) = -v(1); + dst(1, 2) = -v(0); + dst(2, 1) = v(0); + } + EIGEN_DEVICE_FUNC static void run( + DstXprType& dst, const SrcXprType& src, + const internal::add_assign_op& /*func*/) { + dst.vector() += src.vector(); + } + + EIGEN_DEVICE_FUNC static void run( + DstXprType& dst, const SrcXprType& src, + const internal::sub_assign_op& /*func*/) { + dst.vector() -= src.vector(); + } +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SKEWSYMMETRICMATRIX3_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Solve.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Solve.h new file mode 100644 index 0000000..030b934 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Solve.h @@ -0,0 +1,174 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2014 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SOLVE_H +#define EIGEN_SOLVE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +class SolveImpl; + +/** \class Solve + * \ingroup Core_Module + * + * \brief Pseudo expression representing a solving operation + * + * \tparam Decomposition the type of the matrix or decomposition object + * \tparam Rhstype the type of the right-hand side + * + * This class represents an expression of A.solve(B) + * and most of the time this is the only way it is used. + * + */ +namespace internal { + +// this solve_traits class permits to determine the evaluation type with respect to storage kind (Dense vs Sparse) +template +struct solve_traits; + +template +struct solve_traits { + typedef typename make_proper_matrix_type::type + PlainObject; +}; + +template +struct traits > + : traits< + typename solve_traits::StorageKind>::PlainObject> { + typedef typename solve_traits::StorageKind>::PlainObject + PlainObject; + typedef typename promote_index_type::type + StorageIndex; + typedef traits BaseTraits; + enum { Flags = BaseTraits::Flags & RowMajorBit, CoeffReadCost = HugeCost }; +}; + +} // namespace internal + +template +class Solve : public SolveImpl::StorageKind> { + public: + typedef typename internal::traits::PlainObject PlainObject; + typedef typename internal::traits::StorageIndex StorageIndex; + + Solve(const Decomposition &dec, const RhsType &rhs) : m_dec(dec), m_rhs(rhs) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_dec.cols(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_rhs.cols(); } + + EIGEN_DEVICE_FUNC constexpr const Decomposition &dec() const { return m_dec; } + EIGEN_DEVICE_FUNC constexpr const RhsType &rhs() const { return m_rhs; } + + protected: + const Decomposition &m_dec; + const typename internal::ref_selector::type m_rhs; +}; + +// Specialization of the Solve expression for dense results +template +class SolveImpl : public MatrixBase > { + typedef Solve Derived; + + public: + typedef MatrixBase > Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Derived) + + private: + Scalar coeff(Index row, Index col) const; + Scalar coeff(Index i) const; +}; + +// Generic API dispatcher +template +class SolveImpl : public internal::generic_xpr_base, MatrixXpr, StorageKind>::type { + public: + typedef typename internal::generic_xpr_base, MatrixXpr, StorageKind>::type Base; +}; + +namespace internal { + +// Evaluator of Solve -> eval into a temporary +template +struct evaluator > + : public evaluator::PlainObject> { + typedef Solve SolveType; + typedef typename SolveType::PlainObject PlainObject; + typedef evaluator Base; + + enum { Flags = Base::Flags | EvalBeforeNestingBit }; + + EIGEN_DEVICE_FUNC explicit evaluator(const SolveType &solve) : m_result(solve.rows(), solve.cols()) { + internal::construct_at(this, m_result); + solve.dec()._solve_impl(solve.rhs(), m_result); + } + + protected: + PlainObject m_result; +}; + +// Specialization for "dst = dec.solve(rhs)" +// NOTE we need to specialize it for Dense2Dense to avoid ambiguous specialization error and a Sparse2Sparse +// specialization must exist somewhere +template +struct Assignment, internal::assign_op, Dense2Dense> { + typedef Solve SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + src.dec()._solve_impl(src.rhs(), dst); + } +}; + +// Specialization for "dst = dec.transpose().solve(rhs)" +template +struct Assignment, RhsType>, internal::assign_op, + Dense2Dense> { + typedef Solve, RhsType> SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + src.dec().nestedExpression().template _solve_impl_transposed(src.rhs(), dst); + } +}; + +// Specialization for "dst = dec.adjoint().solve(rhs)" +template +struct Assignment< + DstXprType, + Solve, const Transpose >, + RhsType>, + internal::assign_op, Dense2Dense> { + typedef Solve, const Transpose >, + RhsType> + SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + src.dec().nestedExpression().nestedExpression().template _solve_impl_transposed(src.rhs(), dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SOLVE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolveTriangular.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolveTriangular.h new file mode 100644 index 0000000..9d31874 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolveTriangular.h @@ -0,0 +1,237 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SOLVETRIANGULAR_H +#define EIGEN_SOLVETRIANGULAR_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// Forward declarations: +// The following two routines are implemented in the products/TriangularSolver*.h files +template +struct triangular_solve_vector; + +template +struct triangular_solve_matrix; + +// small helper struct extracting some traits on the underlying solver operation +template +class trsolve_traits { + private: + enum { RhsIsVectorAtCompileTime = (Side == OnTheLeft ? Rhs::ColsAtCompileTime : Rhs::RowsAtCompileTime) == 1 }; + + public: + enum { + Unrolling = (RhsIsVectorAtCompileTime && Rhs::SizeAtCompileTime != Dynamic && Rhs::SizeAtCompileTime <= 8) + ? CompleteUnrolling + : NoUnrolling, + RhsVectors = RhsIsVectorAtCompileTime ? 1 : Dynamic + }; +}; + +template ::Unrolling, + int RhsVectors = trsolve_traits::RhsVectors> +struct triangular_solver_selector; + +template +struct triangular_solver_selector { + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef blas_traits LhsProductTraits; + typedef typename LhsProductTraits::ExtractType ActualLhsType; + typedef Map, Aligned> MappedRhs; + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, Rhs& rhs) { + ActualLhsType actualLhs = LhsProductTraits::extract(lhs); + + // FIXME find a way to allow an inner stride if packet_traits::size==1 + + bool useRhsDirectly = Rhs::InnerStrideAtCompileTime == 1 || rhs.innerStride() == 1; + + ei_declare_aligned_stack_constructed_variable(RhsScalar, actualRhs, rhs.size(), (useRhsDirectly ? rhs.data() : 0)); + + if (!useRhsDirectly) MappedRhs(actualRhs, rhs.size()) = rhs; + + triangular_solve_vector::run(actualLhs.cols(), + actualLhs.data(), + actualLhs.outerStride(), + actualRhs); + + if (!useRhsDirectly) rhs = MappedRhs(actualRhs, rhs.size()); + } +}; + +// the rhs is a matrix +template +struct triangular_solver_selector { + typedef typename Rhs::Scalar Scalar; + typedef blas_traits LhsProductTraits; + typedef typename LhsProductTraits::DirectLinearAccessType ActualLhsType; + + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, Rhs& rhs) { + add_const_on_value_type_t actualLhs = LhsProductTraits::extract(lhs); + + const Index size = lhs.rows(); + const Index othersize = Side == OnTheLeft ? rhs.cols() : rhs.rows(); + + typedef internal::gemm_blocking_space<(Rhs::Flags & RowMajorBit) ? RowMajor : ColMajor, Scalar, Scalar, + Rhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, + Lhs::MaxRowsAtCompileTime, 4> + BlockingType; + + // Nothing to solve. + if (actualLhs.size() == 0 || rhs.size() == 0) { + return; + } + + BlockingType blocking(rhs.rows(), rhs.cols(), size, 1, false); + + triangular_solve_matrix::run(size, othersize, &actualLhs.coeffRef(0, 0), + actualLhs.outerStride(), &rhs.coeffRef(0, 0), + rhs.innerStride(), rhs.outerStride(), blocking); + } +}; + +/*************************************************************************** + * meta-unrolling implementation + ***************************************************************************/ + +template +struct triangular_solver_unroller; + +template +struct triangular_solver_unroller { + enum { + IsLower = ((Mode & Lower) == Lower), + DiagIndex = IsLower ? LoopIndex : Size - LoopIndex - 1, + StartIndex = IsLower ? 0 : DiagIndex + 1 + }; + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, Rhs& rhs) { + if (LoopIndex > 0) + rhs.coeffRef(DiagIndex) -= lhs.row(DiagIndex) + .template segment(StartIndex) + .transpose() + .cwiseProduct(rhs.template segment(StartIndex)) + .sum(); + + if (!(Mode & UnitDiag)) rhs.coeffRef(DiagIndex) /= lhs.coeff(DiagIndex, DiagIndex); + + triangular_solver_unroller::run(lhs, rhs); + } +}; + +template +struct triangular_solver_unroller { + static EIGEN_DEVICE_FUNC void run(const Lhs&, Rhs&) {} +}; + +template +struct triangular_solver_selector { + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, Rhs& rhs) { + triangular_solver_unroller::run(lhs, rhs); + } +}; + +template +struct triangular_solver_selector { + static EIGEN_DEVICE_FUNC void run(const Lhs& lhs, Rhs& rhs) { + Transpose trLhs(lhs); + Transpose trRhs(rhs); + + triangular_solver_unroller, Transpose, + ((Mode & Upper) == Upper ? Lower : Upper) | (Mode & UnitDiag), 0, + Rhs::SizeAtCompileTime>::run(trLhs, trRhs); + } +}; + +} // end namespace internal + +/*************************************************************************** + * TriangularView methods + ***************************************************************************/ + +#ifndef EIGEN_PARSED_BY_DOXYGEN +template +template +EIGEN_DEVICE_FUNC void TriangularViewImpl::solveInPlace( + const MatrixBase& _other) const { + OtherDerived& other = _other.const_cast_derived(); + eigen_assert(derived().cols() == derived().rows() && ((Side == OnTheLeft && derived().cols() == other.rows()) || + (Side == OnTheRight && derived().cols() == other.cols()))); + eigen_assert((!(int(Mode) & int(ZeroDiag))) && bool(int(Mode) & (int(Upper) | int(Lower)))); + // If solving for a 0x0 matrix, nothing to do, simply return. + if (derived().cols() == 0) return; + + enum { + copy = (internal::traits::Flags & RowMajorBit) && OtherDerived::IsVectorAtCompileTime && + OtherDerived::SizeAtCompileTime != 1 + }; + typedef std::conditional_t::type, OtherDerived&> + OtherCopy; + OtherCopy otherCopy(other); + + internal::triangular_solver_selector, Side, Mode>::run( + derived().nestedExpression(), otherCopy); + + if (copy) other = otherCopy; +} + +template +template +const internal::triangular_solve_retval, Other> +TriangularViewImpl::solve(const MatrixBase& other) const { + return internal::triangular_solve_retval(derived(), other.derived()); +} +#endif + +namespace internal { + +template +struct traits > { + typedef typename internal::plain_matrix_type_column_major::type ReturnType; +}; + +template +struct triangular_solve_retval : public ReturnByValue > { + typedef remove_all_t RhsNestedCleaned; + typedef ReturnByValue Base; + + triangular_solve_retval(const TriangularType& tri, const Rhs& rhs) : m_triangularMatrix(tri), m_rhs(rhs) {} + + constexpr Index rows() const noexcept { return m_rhs.rows(); } + constexpr Index cols() const noexcept { return m_rhs.cols(); } + + template + inline void evalTo(Dest& dst) const { + if (!is_same_dense(dst, m_rhs)) dst = m_rhs; + m_triangularMatrix.template solveInPlace(dst); + } + + protected: + const TriangularType& m_triangularMatrix; + typename Rhs::Nested m_rhs; +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SOLVETRIANGULAR_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolverBase.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolverBase.h new file mode 100644 index 0000000..a6ecbc9 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/SolverBase.h @@ -0,0 +1,167 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2015 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SOLVERBASE_H +#define EIGEN_SOLVERBASE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct solve_assertion { + template + static void run(const Derived& solver, const Rhs& b) { + solver.template _check_solve_assertion(b); + } +}; + +template +struct solve_assertion> { + typedef Transpose type; + + template + static void run(const type& transpose, const Rhs& b) { + internal::solve_assertion>::template run(transpose.nestedExpression(), b); + } +}; + +template +struct solve_assertion, const Transpose>> { + typedef CwiseUnaryOp, const Transpose> type; + + template + static void run(const type& adjoint, const Rhs& b) { + internal::solve_assertion>>::template run( + adjoint.nestedExpression(), b); + } +}; +} // end namespace internal + +/** \class SolverBase + * \brief A base class for matrix decomposition and solvers + * + * \tparam Derived the actual type of the decomposition/solver. + * + * Any matrix decomposition inheriting this base class provide the following API: + * + * \code + * MatrixType A, b, x; + * DecompositionType dec(A); + * x = dec.solve(b); // solve A * x = b + * x = dec.transpose().solve(b); // solve A^T * x = b + * x = dec.adjoint().solve(b); // solve A' * x = b + * \endcode + * + * \warning Currently, any other usage of transpose() and adjoint() are not supported and will produce compilation + * errors. + * + * \sa class PartialPivLU, class FullPivLU, class HouseholderQR, class ColPivHouseholderQR, class FullPivHouseholderQR, + * class CompleteOrthogonalDecomposition, class LLT, class LDLT, class SVDBase + */ +template +class SolverBase : public EigenBase { + public: + typedef EigenBase Base; + typedef typename internal::traits::Scalar Scalar; + typedef Scalar CoeffReturnType; + + template + friend struct internal::solve_assertion; + + ComputationInfo info() const { + // CRTP static dispatch: Calls the 'info()' method on the derived class. + // Derived must implement 'ComputationInfo info() const'. + // If not implemented, name lookup falls back to this base method, causing + // infinite recursion (detectable by -Winfinite-recursion). + return derived().info(); + } + + enum { + RowsAtCompileTime = internal::traits::RowsAtCompileTime, + ColsAtCompileTime = internal::traits::ColsAtCompileTime, + SizeAtCompileTime = (internal::size_of_xpr_at_compile_time::ret), + MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = internal::traits::MaxColsAtCompileTime, + MaxSizeAtCompileTime = internal::size_at_compile_time(internal::traits::MaxRowsAtCompileTime, + internal::traits::MaxColsAtCompileTime), + IsVectorAtCompileTime = + internal::traits::MaxRowsAtCompileTime == 1 || internal::traits::MaxColsAtCompileTime == 1, + NumDimensions = int(MaxSizeAtCompileTime) == 1 ? 0 + : bool(IsVectorAtCompileTime) ? 1 + : 2 + }; + + /** Default constructor */ + SolverBase() {} + + ~SolverBase() {} + + using Base::derived; + + /** \returns an expression of the solution x of \f$ A x = b \f$ using the current decomposition of A. + */ + template + inline Solve solve(const MatrixBase& b) const { + internal::solve_assertion>::template run(derived(), b); + return Solve(derived(), b.derived()); + } + + /** \internal the return type of transpose() */ + typedef Transpose ConstTransposeReturnType; + /** \returns an expression of the transposed of the factored matrix. + * + * A typical usage is to solve for the transposed problem A^T x = b: + * \code x = dec.transpose().solve(b); \endcode + * + * \sa adjoint(), solve() + */ + inline const ConstTransposeReturnType transpose() const { return ConstTransposeReturnType(derived()); } + + /** \internal the return type of adjoint() */ + typedef std::conditional_t::IsComplex, + CwiseUnaryOp, const ConstTransposeReturnType>, + const ConstTransposeReturnType> + AdjointReturnType; + /** \returns an expression of the adjoint of the factored matrix + * + * A typical usage is to solve for the adjoint problem A' x = b: + * \code x = dec.adjoint().solve(b); \endcode + * + * For real scalar types, this function is equivalent to transpose(). + * + * \sa transpose(), solve() + */ + inline const AdjointReturnType adjoint() const { return AdjointReturnType(derived().transpose()); } + + protected: + template + void _check_solve_assertion(const Rhs& b) const { + EIGEN_ONLY_USED_FOR_DEBUG(b); + eigen_assert(derived().m_isInitialized && "Solver is not initialized."); + eigen_assert((Transpose_ ? derived().cols() : derived().rows()) == b.rows() && + "SolverBase::solve(): invalid number of rows of the right hand side matrix b"); + } +}; + +namespace internal { + +template +struct generic_xpr_base { + typedef SolverBase type; +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SOLVERBASE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StableNorm.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StableNorm.h new file mode 100644 index 0000000..11abb77 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StableNorm.h @@ -0,0 +1,216 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STABLENORM_H +#define EIGEN_STABLENORM_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale) { + Scalar maxCoeff = bl.cwiseAbs().maxCoeff(); + + if (maxCoeff > scale) { + ssq = ssq * numext::abs2(scale / maxCoeff); + Scalar tmp = Scalar(1) / maxCoeff; + if (tmp > NumTraits::highest()) { + invScale = NumTraits::highest(); + scale = Scalar(1) / invScale; + } else if (maxCoeff > NumTraits::highest()) // we got a INF + { + invScale = Scalar(1); + scale = maxCoeff; + } else { + scale = maxCoeff; + invScale = tmp; + } + } else if (maxCoeff != maxCoeff) // we got a NaN + { + scale = maxCoeff; + } + + // TODO: skip sub-vector when maxCoeff << current scale. + if (scale > Scalar(0)) // if scale==0, then bl is 0 + ssq += (bl * invScale).squaredNorm(); +} + +template +void stable_norm_impl_inner_step(const VectorType& vec, RealScalar& ssq, RealScalar& scale, RealScalar& invScale) { + const Index blockSize = 4096; + + Index n = vec.size(); + Index blockEnd = numext::round_down(n, blockSize); + for (Index i = 0; i < blockEnd; i += blockSize) { + internal::stable_norm_kernel(vec.template segment(i), ssq, scale, invScale); + } + if (n > blockEnd) { + internal::stable_norm_kernel(vec.tail(n - blockEnd), ssq, scale, invScale); + } +} + +template +typename VectorType::RealScalar stable_norm_impl(const VectorType& vec, + std::enable_if_t* = 0) { + using std::abs; + using std::sqrt; + + Index n = vec.size(); + if (EIGEN_PREDICT_FALSE(n == 1)) return abs(vec.coeff(0)); + + typedef typename VectorType::RealScalar RealScalar; + RealScalar scale(0); + RealScalar invScale(1); + RealScalar ssq(0); // sum of squares + + stable_norm_impl_inner_step(vec, ssq, scale, invScale); + + return scale * sqrt(ssq); +} + +template +typename MatrixType::RealScalar stable_norm_impl(const MatrixType& mat, + std::enable_if_t* = 0) { + using std::sqrt; + + typedef typename MatrixType::RealScalar RealScalar; + RealScalar scale(0); + RealScalar invScale(1); + RealScalar ssq(0); // sum of squares + + for (Index j = 0; j < mat.outerSize(); ++j) stable_norm_impl_inner_step(mat.innerVector(j), ssq, scale, invScale); + return scale * sqrt(ssq); +} + +template +inline typename NumTraits::Scalar>::Real blueNorm_impl(const EigenBase& _vec) { + typedef typename Derived::RealScalar RealScalar; + using std::abs; + using std::pow; + using std::sqrt; + + // This program calculates the machine-dependent constants + // bl, b2, slm, s2m, relerr overfl + // from the "basic" machine-dependent numbers + // nbig, ibeta, it, iemin, iemax, rbig. + // The following define the basic machine-dependent constants. + // For portability, the PORT subprograms "ilmaeh" and "rlmach" + // are used. For any specific computer, each of the assignment + // statements can be replaced + static const int ibeta = std::numeric_limits::radix; // base for floating-point numbers + static const int it = NumTraits::digits(); // number of base-beta digits in mantissa + static const int iemin = NumTraits::min_exponent(); // minimum exponent + static const int iemax = NumTraits::max_exponent(); // maximum exponent + static const RealScalar rbig = NumTraits::highest(); // largest floating-point number + static const RealScalar b1 = + RealScalar(pow(RealScalar(ibeta), RealScalar(-((1 - iemin) / 2)))); // lower boundary of midrange + static const RealScalar b2 = + RealScalar(pow(RealScalar(ibeta), RealScalar((iemax + 1 - it) / 2))); // upper boundary of midrange + static const RealScalar s1m = + RealScalar(pow(RealScalar(ibeta), RealScalar((2 - iemin) / 2))); // scaling factor for lower range + static const RealScalar s2m = + RealScalar(pow(RealScalar(ibeta), RealScalar(-((iemax + it) / 2)))); // scaling factor for upper range + static const RealScalar eps = RealScalar(pow(double(ibeta), 1 - it)); + static const RealScalar relerr = sqrt(eps); // tolerance for neglecting asml + + const Derived& vec(_vec.derived()); + Index n = vec.size(); + RealScalar ab2 = b2 / RealScalar(n); + RealScalar asml = RealScalar(0); + RealScalar amed = RealScalar(0); + RealScalar abig = RealScalar(0); + + for (Index j = 0; j < vec.outerSize(); ++j) { + for (typename Derived::InnerIterator iter(vec, j); iter; ++iter) { + RealScalar ax = abs(iter.value()); + if (ax > ab2) + abig += numext::abs2(ax * s2m); + else if (ax < b1) + asml += numext::abs2(ax * s1m); + else + amed += numext::abs2(ax); + } + } + if (amed != amed) return amed; // we got a NaN + if (abig > RealScalar(0)) { + abig = sqrt(abig); + if (abig > rbig) // overflow, or *this contains INF values + return abig; // return INF + if (amed > RealScalar(0)) { + abig = abig / s2m; + amed = sqrt(amed); + } else + return abig / s2m; + } else if (asml > RealScalar(0)) { + if (amed > RealScalar(0)) { + abig = sqrt(amed); + amed = sqrt(asml) / s1m; + } else + return sqrt(asml) / s1m; + } else + return sqrt(amed); + asml = numext::mini(abig, amed); + abig = numext::maxi(abig, amed); + if (asml <= abig * relerr) + return abig; + else + return abig * sqrt(RealScalar(1) + numext::abs2(asml / abig)); +} + +} // end namespace internal + +/** \returns the \em l2 norm of \c *this avoiding underflow and overflow. + * This version use a blockwise two passes algorithm: + * 1 - find the absolute largest coefficient \c s + * 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way + * + * For architecture/scalar types supporting vectorization, this version + * is faster than blueNorm(). Otherwise the blueNorm() is much faster. + * + * \sa norm(), blueNorm(), hypotNorm() + */ +template +inline typename NumTraits::Scalar>::Real MatrixBase::stableNorm() const { + return internal::stable_norm_impl(derived()); +} + +/** \returns the \em l2 norm of \c *this using the Blue's algorithm. + * A Portable Fortran Program to Find the Euclidean Norm of a Vector, + * ACM TOMS, Vol 4, Issue 1, 1978. + * + * For architecture/scalar types without vectorization, this version + * is much faster than stableNorm(). Otherwise the stableNorm() is faster. + * + * \sa norm(), stableNorm(), hypotNorm() + */ +template +inline typename NumTraits::Scalar>::Real MatrixBase::blueNorm() const { + return internal::blueNorm_impl(*this); +} + +/** \returns the \em l2 norm of \c *this avoiding underflow and overflow. + * This version use a concatenation of hypot() calls, and it is very slow. + * + * \sa norm(), stableNorm() + */ +template +inline typename NumTraits::Scalar>::Real MatrixBase::hypotNorm() const { + if (size() == 1) + return numext::abs(coeff(0, 0)); + else + return this->cwiseAbs().redux(internal::scalar_hypot_op()); +} + +} // end namespace Eigen + +#endif // EIGEN_STABLENORM_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StlIterators.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StlIterators.h new file mode 100644 index 0000000..afa2ecb --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/StlIterators.h @@ -0,0 +1,618 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2018 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STLITERATORS_H +#define EIGEN_STLITERATORS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct indexed_based_stl_iterator_traits; + +template +class indexed_based_stl_iterator_base { + protected: + typedef indexed_based_stl_iterator_traits traits; + typedef typename traits::XprType XprType; + typedef indexed_based_stl_iterator_base non_const_iterator; + typedef indexed_based_stl_iterator_base const_iterator; + typedef std::conditional_t::value, non_const_iterator, const_iterator> other_iterator; + + friend class indexed_based_stl_iterator_base; + friend class indexed_based_stl_iterator_base; + + public: + typedef Index difference_type; + typedef std::random_access_iterator_tag iterator_category; + + indexed_based_stl_iterator_base() noexcept : mp_xpr(0), m_index(0) {} + indexed_based_stl_iterator_base(XprType& xpr, Index index) noexcept : mp_xpr(&xpr), m_index(index) {} + + indexed_based_stl_iterator_base(const non_const_iterator& other) noexcept + : mp_xpr(other.mp_xpr), m_index(other.m_index) {} + + indexed_based_stl_iterator_base& operator=(const non_const_iterator& other) { + mp_xpr = other.mp_xpr; + m_index = other.m_index; + return *this; + } + + Derived& operator++() { + ++m_index; + return derived(); + } + Derived& operator--() { + --m_index; + return derived(); + } + + Derived operator++(int) { + Derived prev(derived()); + operator++(); + return prev; + } + Derived operator--(int) { + Derived prev(derived()); + operator--(); + return prev; + } + + friend Derived operator+(const indexed_based_stl_iterator_base& a, Index b) { + Derived ret(a.derived()); + ret += b; + return ret; + } + friend Derived operator-(const indexed_based_stl_iterator_base& a, Index b) { + Derived ret(a.derived()); + ret -= b; + return ret; + } + friend Derived operator+(Index a, const indexed_based_stl_iterator_base& b) { + Derived ret(b.derived()); + ret += a; + return ret; + } + friend Derived operator-(Index a, const indexed_based_stl_iterator_base& b) { + Derived ret(b.derived()); + ret -= a; + return ret; + } + + Derived& operator+=(Index b) { + m_index += b; + return derived(); + } + Derived& operator-=(Index b) { + m_index -= b; + return derived(); + } + + difference_type operator-(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index - other.m_index; + } + + difference_type operator-(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index - other.m_index; + } + + bool operator==(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index == other.m_index; + } + bool operator!=(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index != other.m_index; + } + bool operator<(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index < other.m_index; + } + bool operator<=(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index <= other.m_index; + } + bool operator>(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index > other.m_index; + } + bool operator>=(const indexed_based_stl_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index >= other.m_index; + } + + bool operator==(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index == other.m_index; + } + bool operator!=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index != other.m_index; + } + bool operator<(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index < other.m_index; + } + bool operator<=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index <= other.m_index; + } + bool operator>(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index > other.m_index; + } + bool operator>=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index >= other.m_index; + } + + protected: + Derived& derived() { return static_cast(*this); } + const Derived& derived() const { return static_cast(*this); } + + XprType* mp_xpr; + Index m_index; +}; + +template +class indexed_based_stl_reverse_iterator_base { + protected: + typedef indexed_based_stl_iterator_traits traits; + typedef typename traits::XprType XprType; + typedef indexed_based_stl_reverse_iterator_base non_const_iterator; + typedef indexed_based_stl_reverse_iterator_base const_iterator; + typedef std::conditional_t::value, non_const_iterator, const_iterator> other_iterator; + + friend class indexed_based_stl_reverse_iterator_base; + friend class indexed_based_stl_reverse_iterator_base; + + public: + typedef Index difference_type; + typedef std::random_access_iterator_tag iterator_category; + + indexed_based_stl_reverse_iterator_base() : mp_xpr(0), m_index(0) {} + indexed_based_stl_reverse_iterator_base(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {} + + indexed_based_stl_reverse_iterator_base(const non_const_iterator& other) + : mp_xpr(other.mp_xpr), m_index(other.m_index) {} + + indexed_based_stl_reverse_iterator_base& operator=(const non_const_iterator& other) { + mp_xpr = other.mp_xpr; + m_index = other.m_index; + return *this; + } + + Derived& operator++() { + --m_index; + return derived(); + } + Derived& operator--() { + ++m_index; + return derived(); + } + + Derived operator++(int) { + Derived prev(derived()); + operator++(); + return prev; + } + Derived operator--(int) { + Derived prev(derived()); + operator--(); + return prev; + } + + friend Derived operator+(const indexed_based_stl_reverse_iterator_base& a, Index b) { + Derived ret(a.derived()); + ret += b; + return ret; + } + friend Derived operator-(const indexed_based_stl_reverse_iterator_base& a, Index b) { + Derived ret(a.derived()); + ret -= b; + return ret; + } + friend Derived operator+(Index a, const indexed_based_stl_reverse_iterator_base& b) { + Derived ret(b.derived()); + ret += a; + return ret; + } + friend Derived operator-(Index a, const indexed_based_stl_reverse_iterator_base& b) { + Derived ret(b.derived()); + ret -= a; + return ret; + } + + Derived& operator+=(Index b) { + m_index -= b; + return derived(); + } + Derived& operator-=(Index b) { + m_index += b; + return derived(); + } + + difference_type operator-(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return other.m_index - m_index; + } + + difference_type operator-(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return other.m_index - m_index; + } + + bool operator==(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index == other.m_index; + } + bool operator!=(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index != other.m_index; + } + bool operator<(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index > other.m_index; + } + bool operator<=(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index >= other.m_index; + } + bool operator>(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index < other.m_index; + } + bool operator>=(const indexed_based_stl_reverse_iterator_base& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index <= other.m_index; + } + + bool operator==(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index == other.m_index; + } + bool operator!=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index != other.m_index; + } + bool operator<(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index > other.m_index; + } + bool operator<=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index >= other.m_index; + } + bool operator>(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index < other.m_index; + } + bool operator>=(const other_iterator& other) const { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index <= other.m_index; + } + + protected: + Derived& derived() { return static_cast(*this); } + const Derived& derived() const { return static_cast(*this); } + + XprType* mp_xpr; + Index m_index; +}; + +template +class pointer_based_stl_iterator { + enum { is_lvalue = internal::is_lvalue::value }; + typedef pointer_based_stl_iterator> non_const_iterator; + typedef pointer_based_stl_iterator> const_iterator; + typedef std::conditional_t::value, non_const_iterator, const_iterator> other_iterator; + + friend class pointer_based_stl_iterator>; + friend class pointer_based_stl_iterator>; + + public: + typedef Index difference_type; + typedef typename XprType::Scalar value_type; +#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L + typedef std::conditional_t + iterator_category; +#else + typedef std::random_access_iterator_tag iterator_category; +#endif + typedef std::conditional_t pointer; + typedef std::conditional_t reference; + + pointer_based_stl_iterator() noexcept : m_ptr(0), m_incr(XprType::InnerStrideAtCompileTime) {} + pointer_based_stl_iterator(XprType& xpr, Index index) noexcept + : m_ptr(xpr.data() + index * xpr.innerStride()), m_incr(xpr.innerStride()) {} + + pointer_based_stl_iterator(const non_const_iterator& other) noexcept : m_ptr(other.m_ptr), m_incr(other.m_incr) {} + + pointer_based_stl_iterator& operator=(const non_const_iterator& other) noexcept { + m_ptr = other.m_ptr; + m_incr.setValue(other.m_incr); + return *this; + } + + reference operator*() const { return *m_ptr; } + reference operator[](Index i) const { return *(m_ptr + i * m_incr.value()); } + pointer operator->() const { return m_ptr; } + + pointer_based_stl_iterator& operator++() { + m_ptr += m_incr.value(); + return *this; + } + pointer_based_stl_iterator& operator--() { + m_ptr -= m_incr.value(); + return *this; + } + + pointer_based_stl_iterator operator++(int) { + pointer_based_stl_iterator prev(*this); + operator++(); + return prev; + } + pointer_based_stl_iterator operator--(int) { + pointer_based_stl_iterator prev(*this); + operator--(); + return prev; + } + + friend pointer_based_stl_iterator operator+(const pointer_based_stl_iterator& a, Index b) { + pointer_based_stl_iterator ret(a); + ret += b; + return ret; + } + friend pointer_based_stl_iterator operator-(const pointer_based_stl_iterator& a, Index b) { + pointer_based_stl_iterator ret(a); + ret -= b; + return ret; + } + friend pointer_based_stl_iterator operator+(Index a, const pointer_based_stl_iterator& b) { + pointer_based_stl_iterator ret(b); + ret += a; + return ret; + } + friend pointer_based_stl_iterator operator-(Index a, const pointer_based_stl_iterator& b) { + pointer_based_stl_iterator ret(b); + ret -= a; + return ret; + } + + pointer_based_stl_iterator& operator+=(Index b) { + m_ptr += b * m_incr.value(); + return *this; + } + pointer_based_stl_iterator& operator-=(Index b) { + m_ptr -= b * m_incr.value(); + return *this; + } + + difference_type operator-(const pointer_based_stl_iterator& other) const { + return (m_ptr - other.m_ptr) / m_incr.value(); + } + + difference_type operator-(const other_iterator& other) const { return (m_ptr - other.m_ptr) / m_incr.value(); } + + bool operator==(const pointer_based_stl_iterator& other) const { return m_ptr == other.m_ptr; } + bool operator!=(const pointer_based_stl_iterator& other) const { return m_ptr != other.m_ptr; } + bool operator<(const pointer_based_stl_iterator& other) const { return m_ptr < other.m_ptr; } + bool operator<=(const pointer_based_stl_iterator& other) const { return m_ptr <= other.m_ptr; } + bool operator>(const pointer_based_stl_iterator& other) const { return m_ptr > other.m_ptr; } + bool operator>=(const pointer_based_stl_iterator& other) const { return m_ptr >= other.m_ptr; } + + bool operator==(const other_iterator& other) const { return m_ptr == other.m_ptr; } + bool operator!=(const other_iterator& other) const { return m_ptr != other.m_ptr; } + bool operator<(const other_iterator& other) const { return m_ptr < other.m_ptr; } + bool operator<=(const other_iterator& other) const { return m_ptr <= other.m_ptr; } + bool operator>(const other_iterator& other) const { return m_ptr > other.m_ptr; } + bool operator>=(const other_iterator& other) const { return m_ptr >= other.m_ptr; } + + protected: + pointer m_ptr; + internal::variable_if_dynamic m_incr; +}; + +template +struct indexed_based_stl_iterator_traits> { + typedef XprType_ XprType; + typedef generic_randaccess_stl_iterator> non_const_iterator; + typedef generic_randaccess_stl_iterator> const_iterator; +}; + +template +class generic_randaccess_stl_iterator + : public indexed_based_stl_iterator_base> { + public: + typedef typename XprType::Scalar value_type; + + protected: + enum { + has_direct_access = (internal::traits::Flags & DirectAccessBit) ? 1 : 0, + is_lvalue = internal::is_lvalue::value + }; + + typedef indexed_based_stl_iterator_base Base; + using Base::m_index; + using Base::mp_xpr; + + // TODO: currently const Transpose/Reshape expressions never returns const references, + // so lets return by value too. + // typedef std::conditional_t read_only_ref_t; + typedef const value_type read_only_ref_t; + + public: + typedef std::conditional_t pointer; + typedef std::conditional_t reference; + + generic_randaccess_stl_iterator() : Base() {} + generic_randaccess_stl_iterator(XprType& xpr, Index index) : Base(xpr, index) {} + generic_randaccess_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {} + using Base::operator=; + + reference operator*() const { return (*mp_xpr)(m_index); } + reference operator[](Index i) const { return (*mp_xpr)(m_index + i); } + pointer operator->() const { return &((*mp_xpr)(m_index)); } +}; + +template +struct indexed_based_stl_iterator_traits> { + typedef XprType_ XprType; + typedef subvector_stl_iterator, Direction> non_const_iterator; + typedef subvector_stl_iterator, Direction> const_iterator; +}; + +template +class subvector_stl_iterator : public indexed_based_stl_iterator_base> { + protected: + enum { is_lvalue = internal::is_lvalue::value }; + + typedef indexed_based_stl_iterator_base Base; + using Base::m_index; + using Base::mp_xpr; + + typedef std::conditional_t SubVectorType; + typedef std::conditional_t + ConstSubVectorType; + + public: + typedef std::conditional_t reference; + typedef typename reference::PlainObject value_type; + + private: + class subvector_stl_iterator_ptr { + public: + subvector_stl_iterator_ptr(const reference& subvector) : m_subvector(subvector) {} + reference* operator->() { return &m_subvector; } + + private: + reference m_subvector; + }; + + public: + typedef subvector_stl_iterator_ptr pointer; + + subvector_stl_iterator() : Base() {} + subvector_stl_iterator(XprType& xpr, Index index) : Base(xpr, index) {} + + reference operator*() const { return (*mp_xpr).template subVector(m_index); } + reference operator[](Index i) const { return (*mp_xpr).template subVector(m_index + i); } + pointer operator->() const { return (*mp_xpr).template subVector(m_index); } +}; + +template +struct indexed_based_stl_iterator_traits> { + typedef XprType_ XprType; + typedef subvector_stl_reverse_iterator, Direction> non_const_iterator; + typedef subvector_stl_reverse_iterator, Direction> const_iterator; +}; + +template +class subvector_stl_reverse_iterator + : public indexed_based_stl_reverse_iterator_base> { + protected: + enum { is_lvalue = internal::is_lvalue::value }; + + typedef indexed_based_stl_reverse_iterator_base Base; + using Base::m_index; + using Base::mp_xpr; + + typedef std::conditional_t SubVectorType; + typedef std::conditional_t + ConstSubVectorType; + + public: + typedef std::conditional_t reference; + typedef typename reference::PlainObject value_type; + + private: + class subvector_stl_reverse_iterator_ptr { + public: + subvector_stl_reverse_iterator_ptr(const reference& subvector) : m_subvector(subvector) {} + reference* operator->() { return &m_subvector; } + + private: + reference m_subvector; + }; + + public: + typedef subvector_stl_reverse_iterator_ptr pointer; + + subvector_stl_reverse_iterator() : Base() {} + subvector_stl_reverse_iterator(XprType& xpr, Index index) : Base(xpr, index) {} + + reference operator*() const { return (*mp_xpr).template subVector(m_index); } + reference operator[](Index i) const { return (*mp_xpr).template subVector(m_index + i); } + pointer operator->() const { return (*mp_xpr).template subVector(m_index); } +}; + +} // namespace internal + +/** returns an iterator to the first element of the 1D vector or array + * \only_for_vectors + * \sa end(), cbegin() + */ +template +inline typename DenseBase::iterator DenseBase::begin() { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + return iterator(derived(), 0); +} + +/** const version of begin() */ +template +inline typename DenseBase::const_iterator DenseBase::begin() const { + return cbegin(); +} + +/** returns a read-only const_iterator to the first element of the 1D vector or array + * \only_for_vectors + * \sa cend(), begin() + */ +template +inline typename DenseBase::const_iterator DenseBase::cbegin() const { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + return const_iterator(derived(), 0); +} + +/** returns an iterator to the element following the last element of the 1D vector or array + * \only_for_vectors + * \sa begin(), cend() + */ +template +inline typename DenseBase::iterator DenseBase::end() { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + return iterator(derived(), size()); +} + +/** const version of end() */ +template +inline typename DenseBase::const_iterator DenseBase::end() const { + return cend(); +} + +/** returns a read-only const_iterator to the element following the last element of the 1D vector or array + * \only_for_vectors + * \sa begin(), cend() + */ +template +inline typename DenseBase::const_iterator DenseBase::cend() const { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); + return const_iterator(derived(), size()); +} + +} // namespace Eigen + +#endif // EIGEN_STLITERATORS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Stride.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Stride.h new file mode 100644 index 0000000..8957aa9 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Stride.h @@ -0,0 +1,115 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_STRIDE_H +#define EIGEN_STRIDE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class Stride + * \ingroup Core_Module + * + * \brief Holds strides information for Map + * + * This class holds the strides information for mapping arrays with strides with class Map. + * + * It holds two values: the inner stride and the outer stride. + * + * The inner stride is the pointer increment between two consecutive entries within a given row of a + * row-major matrix or within a given column of a column-major matrix. + * + * The outer stride is the pointer increment between two consecutive rows of a row-major matrix or + * between two consecutive columns of a column-major matrix. + * + * These two values can be passed either at compile-time as template parameters, or at runtime as + * arguments to the constructor. + * + * Indeed, this class takes two template parameters: + * \tparam OuterStrideAtCompileTime_ the outer stride, or Dynamic if you want to specify it at runtime. + * \tparam InnerStrideAtCompileTime_ the inner stride, or Dynamic if you want to specify it at runtime. + * + * Here is an example: + * \include Map_general_stride.cpp + * Output: \verbinclude Map_general_stride.out + * + * Both strides can be negative. However, a negative stride of -1 cannot be specified at compile time + * because of the ambiguity with Dynamic which is defined to -1 (historically, negative strides were + * not allowed). + * + * Note that for compile-time vectors (ColsAtCompileTime==1 or RowsAtCompile==1), + * the inner stride is the pointer increment between two consecutive elements, + * regardless of storage layout. + * + * \sa class InnerStride, class OuterStride, \ref TopicStorageOrders + */ +template +class Stride { + public: + typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 + enum { InnerStrideAtCompileTime = InnerStrideAtCompileTime_, OuterStrideAtCompileTime = OuterStrideAtCompileTime_ }; + + /** Default constructor, for use when strides are fixed at compile time */ + EIGEN_DEVICE_FUNC constexpr Stride() : m_outer(OuterStrideAtCompileTime), m_inner(InnerStrideAtCompileTime) { + // FIXME: for Eigen 4 we should use DynamicIndex instead of Dynamic. + // FIXME: for Eigen 4 we should also unify this API with fix<> + eigen_assert(InnerStrideAtCompileTime != Dynamic && OuterStrideAtCompileTime != Dynamic); + } + + /** Constructor allowing to pass the strides at runtime */ + EIGEN_DEVICE_FUNC constexpr Stride(Index outerStride, Index innerStride) + : m_outer(outerStride), m_inner(innerStride) {} + + /** Copy constructor */ + EIGEN_DEVICE_FUNC constexpr Stride(const Stride& other) : m_outer(other.outer()), m_inner(other.inner()) {} + + /** Copy assignment operator */ + EIGEN_DEVICE_FUNC constexpr Stride& operator=(const Stride& other) { + m_outer.setValue(other.outer()); + m_inner.setValue(other.inner()); + return *this; + } + + /** \returns the outer stride */ + EIGEN_DEVICE_FUNC constexpr Index outer() const { return m_outer.value(); } + /** \returns the inner stride */ + EIGEN_DEVICE_FUNC constexpr Index inner() const { return m_inner.value(); } + + protected: + internal::variable_if_dynamic m_outer; + internal::variable_if_dynamic m_inner; +}; + +/** \brief Convenience specialization of Stride to specify only an inner stride + * See class Map for some examples */ +template +class InnerStride : public Stride<0, Value> { + typedef Stride<0, Value> Base; + + public: + EIGEN_DEVICE_FUNC constexpr InnerStride() : Base() {} + EIGEN_DEVICE_FUNC constexpr InnerStride(Index v) : Base(0, v) {} // FIXME making this explicit could break valid code +}; + +/** \brief Convenience specialization of Stride to specify only an outer stride + * See class Map for some examples */ +template +class OuterStride : public Stride { + typedef Stride Base; + + public: + EIGEN_DEVICE_FUNC constexpr OuterStride() : Base() {} + EIGEN_DEVICE_FUNC constexpr OuterStride(Index v) : Base(v, 0) {} // FIXME making this explicit could break valid code +}; + +} // end namespace Eigen + +#endif // EIGEN_STRIDE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Swap.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Swap.h new file mode 100644 index 0000000..6dc571e --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Swap.h @@ -0,0 +1,100 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SWAP_H +#define EIGEN_SWAP_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +// Overload default assignPacket behavior for swapping them +template +class generic_dense_assignment_kernel, Specialized> + : public generic_dense_assignment_kernel, BuiltIn> { + protected: + typedef generic_dense_assignment_kernel, BuiltIn> + Base; + using Base::m_dst; + using Base::m_functor; + using Base::m_src; + + public: + typedef typename Base::Scalar Scalar; + typedef typename Base::DstXprType DstXprType; + typedef swap_assign_op Functor; + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE generic_dense_assignment_kernel(DstEvaluatorTypeT &dst, + const SrcEvaluatorTypeT &src, + const Functor &func, + DstXprType &dstExpr) + : Base(dst, src, func, dstExpr) {} + + template + EIGEN_STRONG_INLINE void assignPacket(Index row, Index col) { + PacketType tmp = m_src.template packet(row, col); + const_cast(m_src).template writePacket( + row, col, m_dst.template packet(row, col)); + m_dst.template writePacket(row, col, tmp); + } + + template + EIGEN_STRONG_INLINE void assignPacket(Index index) { + PacketType tmp = m_src.template packet(index); + const_cast(m_src).template writePacket( + index, m_dst.template packet(index)); + m_dst.template writePacket(index, tmp); + } + + // TODO: find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I + // mean no CRTP (Gael) + template + EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner) { + Index row = Base::rowIndexByOuterInner(outer, inner); + Index col = Base::colIndexByOuterInner(outer, inner); + assignPacket(row, col); + } + + template + EIGEN_STRONG_INLINE void assignPacketSegment(Index row, Index col, Index begin, Index count) { + PacketType tmp = m_src.template packetSegment(row, col, begin, count); + const_cast(m_src).template writePacketSegment( + row, col, m_dst.template packetSegment(row, col, begin, count), begin, count); + m_dst.template writePacketSegment(row, col, tmp, begin, count); + } + + template + EIGEN_STRONG_INLINE void assignPacketSegment(Index index, Index begin, Index count) { + PacketType tmp = m_src.template packetSegment(index, begin, count); + const_cast(m_src).template writePacketSegment( + index, m_dst.template packetSegment(index, begin, count), begin, count); + m_dst.template writePacketSegment(index, tmp, begin, count); + } + + // TODO: find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I + // mean no CRTP (Gael) + template + EIGEN_STRONG_INLINE void assignPacketSegmentByOuterInner(Index outer, Index inner, Index begin, Index count) { + Index row = Base::rowIndexByOuterInner(outer, inner); + Index col = Base::colIndexByOuterInner(outer, inner); + assignPacketSegment(row, col, begin, count); + } +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SWAP_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpose.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpose.h new file mode 100644 index 0000000..2077c92 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpose.h @@ -0,0 +1,428 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2009-2014 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_TRANSPOSE_H +#define EIGEN_TRANSPOSE_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > : public traits { + typedef typename ref_selector::type MatrixTypeNested; + typedef std::remove_reference_t MatrixTypeNestedPlain; + enum { + RowsAtCompileTime = MatrixType::ColsAtCompileTime, + ColsAtCompileTime = MatrixType::RowsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + Flags0 = traits::Flags & ~(LvalueBit | NestByRefBit), + Flags1 = Flags0 | FlagsLvalueBit, + Flags = Flags1 ^ RowMajorBit, + InnerStrideAtCompileTime = inner_stride_at_compile_time::ret, + OuterStrideAtCompileTime = outer_stride_at_compile_time::ret + }; +}; +} // namespace internal + +template +class TransposeImpl; + +/** \class Transpose + * \ingroup Core_Module + * + * \brief Expression of the transpose of a matrix + * + * \tparam MatrixType the type of the object of which we are taking the transpose + * + * This class represents an expression of the transpose of a matrix. + * It is the return type of MatrixBase::transpose() and MatrixBase::adjoint() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::transpose(), MatrixBase::adjoint() + */ +template +class Transpose : public TransposeImpl::StorageKind> { + public: + typedef typename internal::ref_selector::non_const_type MatrixTypeNested; + + typedef typename TransposeImpl::StorageKind>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose) + typedef internal::remove_all_t NestedExpression; + + EIGEN_DEVICE_FUNC constexpr explicit EIGEN_STRONG_INLINE Transpose(MatrixType& matrix) : m_matrix(matrix) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose) + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.cols(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.rows(); } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE const internal::remove_all_t& nestedExpression() + const { + return m_matrix; + } + + /** \returns the nested expression */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE std::remove_reference_t& nestedExpression() { + return m_matrix; + } + + /** \internal */ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index nrows, Index ncols) { m_matrix.resize(ncols, nrows); } + + protected: + typename internal::ref_selector::non_const_type m_matrix; +}; + +namespace internal { + +template ::ret> +struct TransposeImpl_base { + typedef typename dense_xpr_base >::type type; +}; + +template +struct TransposeImpl_base { + typedef typename dense_xpr_base >::type type; +}; + +} // end namespace internal + +// Generic API dispatcher +template +class TransposeImpl : public internal::generic_xpr_base >::type { + public: + typedef typename internal::generic_xpr_base >::type Base; +}; + +template +class TransposeImpl : public internal::TransposeImpl_base::type { + public: + typedef typename internal::TransposeImpl_base::type Base; + using Base::coeffRef; + EIGEN_DENSE_PUBLIC_INTERFACE(Transpose) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl) + + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index innerStride() const { + return derived().nestedExpression().innerStride(); + } + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE Index outerStride() const { + return derived().nestedExpression().outerStride(); + } + + typedef std::conditional_t::value, Scalar, const Scalar> ScalarWithConstIfNotLvalue; + + EIGEN_DEVICE_FUNC constexpr ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); } + EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return derived().nestedExpression().data(); } + + // FIXME: shall we keep the const version of coeffRef? + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeffRef(Index rowId, Index colId) const { + return derived().nestedExpression().coeffRef(colId, rowId); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const { + return derived().nestedExpression().coeffRef(index); + } + + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TransposeImpl) +}; + +/** \returns an expression of the transpose of *this. + * + * Example: \include MatrixBase_transpose.cpp + * Output: \verbinclude MatrixBase_transpose.out + * + * \warning If you want to replace a matrix by its own transpose, do \b NOT do this: + * \code + * m = m.transpose(); // bug!!! caused by aliasing effect + * \endcode + * Instead, use the transposeInPlace() method: + * \code + * m.transposeInPlace(); + * \endcode + * which gives Eigen good opportunities for optimization, or alternatively you can also do: + * \code + * m = m.transpose().eval(); + * \endcode + * + * \sa transposeInPlace(), adjoint() */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename DenseBase::TransposeReturnType DenseBase::transpose() { + return TransposeReturnType(derived()); +} + +/** This is the const version of transpose(). + * + * Make sure you read the warning for transpose() ! + * + * \sa transposeInPlace(), adjoint() */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstTransposeReturnType +DenseBase::transpose() const { + return ConstTransposeReturnType(derived()); +} + +/** \returns an expression of the adjoint (i.e. conjugate transpose) of *this. + * + * Example: \include MatrixBase_adjoint.cpp + * Output: \verbinclude MatrixBase_adjoint.out + * + * \warning If you want to replace a matrix by its own adjoint, do \b NOT do this: + * \code + * m = m.adjoint(); // bug!!! caused by aliasing effect + * \endcode + * Instead, use the adjointInPlace() method: + * \code + * m.adjointInPlace(); + * \endcode + * which gives Eigen good opportunities for optimization, or alternatively you can also do: + * \code + * m = m.adjoint().eval(); + * \endcode + * + * \sa adjointInPlace(), transpose(), conjugate(), class Transpose, class internal::scalar_conjugate_op */ +template +EIGEN_DEVICE_FUNC constexpr const typename MatrixBase::AdjointReturnType MatrixBase::adjoint() const { + return AdjointReturnType(this->transpose()); +} + +/*************************************************************************** + * "in place" transpose implementation + ***************************************************************************/ + +namespace internal { + +template ::size)) && + (internal::evaluator::Flags & PacketAccessBit)> +struct inplace_transpose_selector; + +template +struct inplace_transpose_selector { // square matrix + static void run(MatrixType& m) { + m.matrix().template triangularView().swap( + m.matrix().transpose().template triangularView()); + } +}; + +template +struct inplace_transpose_selector { // PacketSize x PacketSize + static void run(MatrixType& m) { + typedef typename MatrixType::Scalar Scalar; + typedef typename internal::packet_traits::type Packet; + const Index PacketSize = internal::packet_traits::size; + const Index Alignment = internal::evaluator::Alignment; + PacketBlock A; + for (Index i = 0; i < PacketSize; ++i) A.packet[i] = m.template packetByOuterInner(i, 0); + internal::ptranspose(A); + for (Index i = 0; i < PacketSize; ++i) + m.template writePacket(m.rowIndexByOuterInner(i, 0), m.colIndexByOuterInner(i, 0), A.packet[i]); + } +}; + +template +void BlockedInPlaceTranspose(MatrixType& m) { + typedef typename MatrixType::Scalar Scalar; + typedef typename internal::packet_traits::type Packet; + const Index PacketSize = internal::packet_traits::size; + eigen_assert(m.rows() == m.cols()); + int row_start = 0; + for (; row_start + PacketSize <= m.rows(); row_start += PacketSize) { + for (int col_start = row_start; col_start + PacketSize <= m.cols(); col_start += PacketSize) { + PacketBlock A; + if (row_start == col_start) { + for (Index i = 0; i < PacketSize; ++i) + A.packet[i] = m.template packetByOuterInner(row_start + i, col_start); + internal::ptranspose(A); + for (Index i = 0; i < PacketSize; ++i) + m.template writePacket(m.rowIndexByOuterInner(row_start + i, col_start), + m.colIndexByOuterInner(row_start + i, col_start), A.packet[i]); + } else { + PacketBlock B; + for (Index i = 0; i < PacketSize; ++i) { + A.packet[i] = m.template packetByOuterInner(row_start + i, col_start); + B.packet[i] = m.template packetByOuterInner(col_start + i, row_start); + } + internal::ptranspose(A); + internal::ptranspose(B); + for (Index i = 0; i < PacketSize; ++i) { + m.template writePacket(m.rowIndexByOuterInner(row_start + i, col_start), + m.colIndexByOuterInner(row_start + i, col_start), B.packet[i]); + m.template writePacket(m.rowIndexByOuterInner(col_start + i, row_start), + m.colIndexByOuterInner(col_start + i, row_start), A.packet[i]); + } + } + } + } + for (Index row = row_start; row < m.rows(); ++row) { + m.matrix().row(row).head(row).swap(m.matrix().col(row).head(row).transpose()); + } +} + +template +struct inplace_transpose_selector { // non square or dynamic matrix + static void run(MatrixType& m) { + typedef typename MatrixType::Scalar Scalar; + if (m.rows() == m.cols()) { + const Index PacketSize = internal::packet_traits::size; + if (!NumTraits::IsComplex && m.rows() >= PacketSize) { + if ((m.rows() % PacketSize) == 0) + BlockedInPlaceTranspose::Alignment>(m); + else + BlockedInPlaceTranspose(m); + } else { + m.matrix().template triangularView().swap( + m.matrix().transpose().template triangularView()); + } + } else { + m = m.transpose().eval(); + } + } +}; + +} // end namespace internal + +/** This is the "in place" version of transpose(): it replaces \c *this by its own transpose. + * Thus, doing + * \code + * m.transposeInPlace(); + * \endcode + * has the same effect on m as doing + * \code + * m = m.transpose().eval(); + * \endcode + * and is faster and also safer because in the latter line of code, forgetting the eval() results + * in a bug caused by \ref TopicAliasing "aliasing". + * + * Notice however that this method is only useful if you want to replace a matrix by its own transpose. + * If you just need the transpose of a matrix, use transpose(). + * + * \note if the matrix is not square, then \c *this must be a resizable matrix. + * This excludes (non-square) fixed-size matrices, block-expressions and maps. + * + * \sa transpose(), adjoint(), adjointInPlace() */ +template +EIGEN_DEVICE_FUNC inline void DenseBase::transposeInPlace() { + eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic)) && + "transposeInPlace() called on a non-square non-resizable matrix"); + internal::inplace_transpose_selector::run(derived()); +} + +/*************************************************************************** + * "in place" adjoint implementation + ***************************************************************************/ + +/** This is the "in place" version of adjoint(): it replaces \c *this by its own transpose. + * Thus, doing + * \code + * m.adjointInPlace(); + * \endcode + * has the same effect on m as doing + * \code + * m = m.adjoint().eval(); + * \endcode + * and is faster and also safer because in the latter line of code, forgetting the eval() results + * in a bug caused by aliasing. + * + * Notice however that this method is only useful if you want to replace a matrix by its own adjoint. + * If you just need the adjoint of a matrix, use adjoint(). + * + * \note if the matrix is not square, then \c *this must be a resizable matrix. + * This excludes (non-square) fixed-size matrices, block-expressions and maps. + * + * \sa transpose(), adjoint(), transposeInPlace() */ +template +EIGEN_DEVICE_FUNC inline void MatrixBase::adjointInPlace() { + derived() = adjoint().eval(); +} + +#ifndef EIGEN_NO_DEBUG + +// The following is to detect aliasing problems in most common cases. + +namespace internal { + +template +struct check_transpose_aliasing_compile_time_selector { + enum { ret = bool(blas_traits::IsTransposed) != DestIsTransposed }; +}; + +template +struct check_transpose_aliasing_compile_time_selector > { + enum { + ret = bool(blas_traits::IsTransposed) != DestIsTransposed || + bool(blas_traits::IsTransposed) != DestIsTransposed + }; +}; + +template +struct check_transpose_aliasing_run_time_selector { + EIGEN_DEVICE_FUNC static bool run(const Scalar* dest, const OtherDerived& src) { + return (bool(blas_traits::IsTransposed) != DestIsTransposed) && + (dest != 0 && dest == (const Scalar*)extract_data(src)); + } +}; + +template +struct check_transpose_aliasing_run_time_selector > { + EIGEN_DEVICE_FUNC static bool run(const Scalar* dest, const CwiseBinaryOp& src) { + return ((blas_traits::IsTransposed != DestIsTransposed) && + (dest != 0 && dest == (const Scalar*)extract_data(src.lhs()))) || + ((blas_traits::IsTransposed != DestIsTransposed) && + (dest != 0 && dest == (const Scalar*)extract_data(src.rhs()))); + } +}; + +// the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing, +// is because when the condition controlling the assert is known at compile time, ICC emits a warning. +// This is actually a good warning: in expressions that don't have any transposing, the condition is +// known at compile time to be false, and using that, we can avoid generating the code of the assert again +// and again for all these expressions that don't need it. + +template ::IsTransposed, OtherDerived>::ret> +struct checkTransposeAliasing_impl { + EIGEN_DEVICE_FUNC static void run(const Derived& dst, const OtherDerived& other) { + eigen_assert( + (!check_transpose_aliasing_run_time_selector::IsTransposed, + OtherDerived>::run(extract_data(dst), other)) && + "aliasing detected during transposition, use transposeInPlace() " + "or evaluate the rhs into a temporary using .eval()"); + } +}; + +template +struct checkTransposeAliasing_impl { + EIGEN_DEVICE_FUNC static void run(const Derived&, const OtherDerived&) {} +}; + +template +EIGEN_DEVICE_FUNC inline void check_for_aliasing(const Dst& dst, const Src& src) { + if ((!Dst::IsVectorAtCompileTime) && dst.rows() > 1 && dst.cols() > 1) + internal::checkTransposeAliasing_impl::run(dst, src); +} + +} // end namespace internal + +#endif // EIGEN_NO_DEBUG + +} // end namespace Eigen + +#endif // EIGEN_TRANSPOSE_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpositions.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpositions.h new file mode 100644 index 0000000..f6dd258 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/Transpositions.h @@ -0,0 +1,323 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_TRANSPOSITIONS_H +#define EIGEN_TRANSPOSITIONS_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +template +class TranspositionsBase { + typedef internal::traits Traits; + + public: + typedef typename Traits::IndicesType IndicesType; + typedef typename IndicesType::Scalar StorageIndex; + typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 + + EIGEN_DEVICE_FUNC Derived& derived() { return *static_cast(this); } + EIGEN_DEVICE_FUNC const Derived& derived() const { return *static_cast(this); } + + /** Copies the \a other transpositions into \c *this */ + template + Derived& operator=(const TranspositionsBase& other) { + indices() = other.indices(); + return derived(); + } + + /** \returns the number of transpositions */ + EIGEN_DEVICE_FUNC Index size() const { return indices().size(); } + /** \returns the number of rows of the equivalent permutation matrix */ + EIGEN_DEVICE_FUNC Index rows() const { return indices().size(); } + /** \returns the number of columns of the equivalent permutation matrix */ + EIGEN_DEVICE_FUNC Index cols() const { return indices().size(); } + + /** Direct access to the underlying index vector */ + EIGEN_DEVICE_FUNC inline const StorageIndex& coeff(Index i) const { return indices().coeff(i); } + /** Direct access to the underlying index vector */ + inline StorageIndex& coeffRef(Index i) { return indices().coeffRef(i); } + /** Direct access to the underlying index vector */ + inline const StorageIndex& operator()(Index i) const { return indices()(i); } + /** Direct access to the underlying index vector */ + inline StorageIndex& operator()(Index i) { return indices()(i); } + /** Direct access to the underlying index vector */ + inline const StorageIndex& operator[](Index i) const { return indices()(i); } + /** Direct access to the underlying index vector */ + inline StorageIndex& operator[](Index i) { return indices()(i); } + + /** const version of indices(). */ + EIGEN_DEVICE_FUNC const IndicesType& indices() const { return derived().indices(); } + /** \returns a reference to the stored array representing the transpositions. */ + EIGEN_DEVICE_FUNC IndicesType& indices() { return derived().indices(); } + + /** Resizes to given size. */ + inline void resize(Index newSize) { indices().resize(newSize); } + + /** Sets \c *this to represents an identity transformation */ + void setIdentity() { + for (StorageIndex i = 0; i < indices().size(); ++i) coeffRef(i) = i; + } + + // FIXME: do we want such methods ? + // might be useful when the target matrix expression is complex, e.g.: + // object.matrix().block(..,..,..,..) = trans * object.matrix().block(..,..,..,..); + /* + template + void applyForwardToRows(MatrixType& mat) const + { + for(Index k=0 ; k + void applyBackwardToRows(MatrixType& mat) const + { + for(Index k=size()-1 ; k>=0 ; --k) + if(m_indices(k)!=k) + mat.row(k).swap(mat.row(m_indices(k))); + } + */ + + /** \returns the inverse transformation */ + inline Transpose inverse() const { return Transpose(derived()); } + + /** \returns the transpose transformation */ + inline Transpose transpose() const { return Transpose(derived()); } + + protected: +}; + +namespace internal { +template +struct traits > + : traits > { + typedef Matrix IndicesType; + typedef TranspositionsStorage StorageKind; +}; +} // namespace internal + +/** \class Transpositions + * \ingroup Core_Module + * + * \brief Represents a sequence of transpositions (row/column interchange) + * + * \tparam SizeAtCompileTime the number of transpositions, or Dynamic + * \tparam MaxSizeAtCompileTime the maximum number of transpositions, or Dynamic. This optional parameter defaults to + * SizeAtCompileTime. Most of the time, you should not have to specify it. + * + * This class represents a permutation transformation as a sequence of \em n transpositions + * \f$[T_{n-1} \ldots T_{i} \ldots T_{0}]\f$. It is internally stored as a vector of integers \c indices. + * Each transposition \f$ T_{i} \f$ applied on the left of a matrix (\f$ T_{i} M\f$) interchanges + * the rows \c i and \c indices[i] of the matrix \c M. + * A transposition applied on the right (e.g., \f$ M T_{i}\f$) yields a column interchange. + * + * Compared to the class PermutationMatrix, such a sequence of transpositions is what is + * computed during a decomposition with pivoting, and it is faster when applying the permutation in-place. + * + * To apply a sequence of transpositions to a matrix, simply use the operator * as in the following example: + * \code + * Transpositions tr; + * MatrixXf mat; + * mat = tr * mat; + * \endcode + * In this example, we detect that the matrix appears on both side, and so the transpositions + * are applied in-place without any temporary or extra copy. + * + * \sa class PermutationMatrix + */ + +template +class Transpositions + : public TranspositionsBase > { + typedef internal::traits Traits; + + public: + typedef TranspositionsBase Base; + typedef typename Traits::IndicesType IndicesType; + typedef typename IndicesType::Scalar StorageIndex; + + inline Transpositions() {} + + /** Copy constructor. */ + template + inline Transpositions(const TranspositionsBase& other) : m_indices(other.indices()) {} + + /** Generic constructor from expression of the transposition indices. */ + template + explicit inline Transpositions(const MatrixBase& indices) : m_indices(indices) {} + + /** Copies the \a other transpositions into \c *this */ + template + Transpositions& operator=(const TranspositionsBase& other) { + return Base::operator=(other); + } + + /** Constructs an uninitialized permutation matrix of given size. + */ + inline Transpositions(Index size) : m_indices(size) {} + + /** const version of indices(). */ + EIGEN_DEVICE_FUNC const IndicesType& indices() const { return m_indices; } + /** \returns a reference to the stored array representing the transpositions. */ + EIGEN_DEVICE_FUNC IndicesType& indices() { return m_indices; } + + protected: + IndicesType m_indices; +}; + +namespace internal { +template +struct traits, PacketAccess_> > + : traits > { + typedef Map, PacketAccess_> IndicesType; + typedef StorageIndex_ StorageIndex; + typedef TranspositionsStorage StorageKind; +}; +} // namespace internal + +template +class Map, PacketAccess> + : public TranspositionsBase< + Map, PacketAccess> > { + typedef internal::traits Traits; + + public: + typedef TranspositionsBase Base; + typedef typename Traits::IndicesType IndicesType; + typedef typename IndicesType::Scalar StorageIndex; + + explicit inline Map(const StorageIndex* indicesPtr) : m_indices(indicesPtr) {} + + inline Map(const StorageIndex* indicesPtr, Index size) : m_indices(indicesPtr, size) {} + + /** Copies the \a other transpositions into \c *this */ + template + Map& operator=(const TranspositionsBase& other) { + return Base::operator=(other); + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + Map& operator=(const Map& other) { + m_indices = other.m_indices; + return *this; + } +#endif + + /** const version of indices(). */ + EIGEN_DEVICE_FUNC const IndicesType& indices() const { return m_indices; } + + /** \returns a reference to the stored array representing the transpositions. */ + EIGEN_DEVICE_FUNC IndicesType& indices() { return m_indices; } + + protected: + IndicesType m_indices; +}; + +namespace internal { +template +struct traits > : traits > { + typedef TranspositionsStorage StorageKind; +}; +} // namespace internal + +template +class TranspositionsWrapper : public TranspositionsBase > { + typedef internal::traits Traits; + + public: + typedef TranspositionsBase Base; + typedef typename Traits::IndicesType IndicesType; + typedef typename IndicesType::Scalar StorageIndex; + + explicit inline TranspositionsWrapper(IndicesType& indices) : m_indices(indices) {} + + /** Copies the \a other transpositions into \c *this */ + template + TranspositionsWrapper& operator=(const TranspositionsBase& other) { + return Base::operator=(other); + } + + /** const version of indices(). */ + EIGEN_DEVICE_FUNC const IndicesType& indices() const { return m_indices; } + + /** \returns a reference to the stored array representing the transpositions. */ + EIGEN_DEVICE_FUNC IndicesType& indices() { return m_indices; } + + protected: + typename IndicesType::Nested m_indices; +}; + +/** \returns the \a matrix with the \a transpositions applied to the columns. + */ +template +EIGEN_DEVICE_FUNC const Product operator*( + const MatrixBase& matrix, const TranspositionsBase& transpositions) { + return Product(matrix.derived(), transpositions.derived()); +} + +/** \returns the \a matrix with the \a transpositions applied to the rows. + */ +template +EIGEN_DEVICE_FUNC const Product operator*( + const TranspositionsBase& transpositions, const MatrixBase& matrix) { + return Product(transpositions.derived(), matrix.derived()); +} + +// Template partial specialization for transposed/inverse transpositions + +namespace internal { + +template +struct traits > > : traits {}; + +} // end namespace internal + +template +class Transpose > { + typedef TranspositionsDerived TranspositionType; + typedef typename TranspositionType::IndicesType IndicesType; + + public: + explicit Transpose(const TranspositionType& t) : m_transpositions(t) {} + + EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return m_transpositions.size(); } + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_transpositions.size(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_transpositions.size(); } + + /** \returns the \a matrix with the inverse transpositions applied to the columns. + */ + template + friend const Product operator*(const MatrixBase& matrix, + const Transpose& trt) { + return Product(matrix.derived(), trt); + } + + /** \returns the \a matrix with the inverse transpositions applied to the rows. + */ + template + const Product operator*(const MatrixBase& matrix) const { + return Product(*this, matrix.derived()); + } + + EIGEN_DEVICE_FUNC const TranspositionType& nestedExpression() const { return m_transpositions; } + + protected: + const TranspositionType& m_transpositions; +}; + +} // end namespace Eigen + +#endif // EIGEN_TRANSPOSITIONS_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/TriangularMatrix.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/TriangularMatrix.h new file mode 100644 index 0000000..e219e51 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/TriangularMatrix.h @@ -0,0 +1,928 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Benoit Jacob +// Copyright (C) 2008-2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_TRIANGULARMATRIX_H +#define EIGEN_TRIANGULARMATRIX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { + +template +struct triangular_solve_retval; + +} + +/** \class TriangularBase + * \ingroup Core_Module + * + * \brief Base class for triangular part in a matrix + */ +template +class TriangularBase : public EigenBase { + public: + enum { + Mode = internal::traits::Mode, + RowsAtCompileTime = internal::traits::RowsAtCompileTime, + ColsAtCompileTime = internal::traits::ColsAtCompileTime, + MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = internal::traits::MaxColsAtCompileTime, + + SizeAtCompileTime = (internal::size_of_xpr_at_compile_time::ret), + /**< This is equal to the number of coefficients, i.e. the number of + * rows times the number of columns, or to \a Dynamic if this is not + * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */ + + MaxSizeAtCompileTime = internal::size_at_compile_time(internal::traits::MaxRowsAtCompileTime, + internal::traits::MaxColsAtCompileTime) + + }; + typedef typename internal::traits::Scalar Scalar; + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::StorageIndex StorageIndex; + typedef typename internal::traits::FullMatrixType DenseMatrixType; + typedef DenseMatrixType DenseType; + typedef Derived const& Nested; + + EIGEN_DEVICE_FUNC inline TriangularBase() { + eigen_assert(!((int(Mode) & int(UnitDiag)) && (int(Mode) & int(ZeroDiag)))); + } + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return derived().rows(); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return derived().cols(); } + EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return derived().outerStride(); } + EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return derived().innerStride(); } + + // dummy resize function + EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) { + EIGEN_UNUSED_VARIABLE(rows); + EIGEN_UNUSED_VARIABLE(cols); + eigen_assert(rows == this->rows() && cols == this->cols()); + } + + EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const { return derived().coeff(row, col); } + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row, col); } + + /** \see MatrixBase::copyCoeff(row,col) + */ + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other) { + derived().coeffRef(row, col) = other.coeff(row, col); + } + + EIGEN_DEVICE_FUNC inline Scalar operator()(Index row, Index col) const { + check_coordinates(row, col); + return coeff(row, col); + } + EIGEN_DEVICE_FUNC inline Scalar& operator()(Index row, Index col) { + check_coordinates(row, col); + return coeffRef(row, col); + } + +#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT + EIGEN_DEVICE_FUNC inline Scalar operator[](Index row, Index col) const { return operator()(row, col); } + EIGEN_DEVICE_FUNC inline Scalar& operator[](Index row, Index col) { return operator()(row, col); } +#endif + +#ifndef EIGEN_PARSED_BY_DOXYGEN + EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast(this); } + EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast(this); } +#endif // not EIGEN_PARSED_BY_DOXYGEN + + template + EIGEN_DEVICE_FUNC void evalTo(MatrixBase& other) const; + template + EIGEN_DEVICE_FUNC void evalToLazy(MatrixBase& other) const; + + EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { + DenseMatrixType res(rows(), cols()); + evalToLazy(res); + return res; + } + + protected: + void check_coordinates(Index row, Index col) const { + EIGEN_ONLY_USED_FOR_DEBUG(row); + EIGEN_ONLY_USED_FOR_DEBUG(col); + eigen_assert(col >= 0 && col < cols() && row >= 0 && row < rows()); + const int mode = int(Mode) & ~SelfAdjoint; + EIGEN_ONLY_USED_FOR_DEBUG(mode); + eigen_assert((mode == Upper && col >= row) || (mode == Lower && col <= row) || + ((mode == StrictlyUpper || mode == UnitUpper) && col > row) || + ((mode == StrictlyLower || mode == UnitLower) && col < row)); + } + +#ifdef EIGEN_INTERNAL_DEBUGGING + void check_coordinates_internal(Index row, Index col) const { check_coordinates(row, col); } +#else + void check_coordinates_internal(Index, Index) const {} +#endif +}; + +/** \class TriangularView + * \ingroup Core_Module + * + * \brief Expression of a triangular part in a matrix + * + * \tparam MatrixType the type of the object in which we are taking the triangular part + * \tparam Mode the kind of triangular matrix expression to construct. Can be #Upper, + * #Lower, #UnitUpper, #UnitLower, #StrictlyUpper, or #StrictlyLower. + * This is in fact a bit field; it must have either #Upper or #Lower, + * and additionally it may have #UnitDiag or #ZeroDiag or neither. + * + * This class represents a triangular part of a matrix, not necessarily square. Strictly speaking, for rectangular + * matrices one should speak of "trapezoid" parts. This class is the return type + * of MatrixBase::triangularView() and SparseMatrixBase::triangularView(), and most of the time this is the only way it + * is used. + * + * \sa MatrixBase::triangularView() + */ +namespace internal { +template +struct traits> : traits { + typedef typename ref_selector::non_const_type MatrixTypeNested; + typedef std::remove_reference_t MatrixTypeNestedNonRef; + typedef remove_all_t MatrixTypeNestedCleaned; + typedef typename MatrixType::PlainObject FullMatrixType; + typedef MatrixType ExpressionType; + enum { + Mode = Mode_, + FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, + Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | FlagsLvalueBit) & + (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) + }; +}; +} // namespace internal + +template +class TriangularViewImpl; + +template +class TriangularView + : public TriangularViewImpl::StorageKind> { + public: + typedef TriangularViewImpl::StorageKind> Base; + typedef typename internal::traits::Scalar Scalar; + typedef MatrixType_ MatrixType; + + protected: + typedef typename internal::traits::MatrixTypeNested MatrixTypeNested; + typedef typename internal::traits::MatrixTypeNestedNonRef MatrixTypeNestedNonRef; + + typedef internal::remove_all_t MatrixConjugateReturnType; + typedef TriangularView, Mode_> ConstTriangularView; + + public: + typedef typename internal::traits::StorageKind StorageKind; + typedef typename internal::traits::MatrixTypeNestedCleaned NestedExpression; + + enum { + Mode = Mode_, + Flags = internal::traits::Flags, + TransposeMode = (int(Mode) & int(Upper) ? Lower : 0) | (int(Mode) & int(Lower) ? Upper : 0) | + (int(Mode) & int(UnitDiag)) | (int(Mode) & int(ZeroDiag)), + IsVectorAtCompileTime = false + }; + + EIGEN_DEVICE_FUNC explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {} + + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView) + + /** \copydoc EigenBase::rows() */ + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_matrix.rows(); } + /** \copydoc EigenBase::cols() */ + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_matrix.cols(); } + + /** \returns a const reference to the nested expression */ + EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; } + + /** \returns a reference to the nested expression */ + EIGEN_DEVICE_FUNC NestedExpression& nestedExpression() { return m_matrix; } + + typedef TriangularView ConjugateReturnType; + /** \sa MatrixBase::conjugate() const */ + EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const { + return ConjugateReturnType(m_matrix.conjugate()); + } + + /** \returns an expression of the complex conjugate of \c *this if Cond==true, + * returns \c *this otherwise. + */ + template + EIGEN_DEVICE_FUNC inline std::conditional_t conjugateIf() const { + typedef std::conditional_t ReturnType; + return ReturnType(m_matrix.template conjugateIf()); + } + + typedef TriangularView AdjointReturnType; + /** \sa MatrixBase::adjoint() const */ + EIGEN_DEVICE_FUNC inline const AdjointReturnType adjoint() const { return AdjointReturnType(m_matrix.adjoint()); } + + typedef TriangularView TransposeReturnType; + /** \sa MatrixBase::transpose() */ + template + EIGEN_DEVICE_FUNC inline TransposeReturnType transpose( + std::enable_if_t::value, Dummy*> = nullptr) { + typename MatrixType::TransposeReturnType tmp(m_matrix); + return TransposeReturnType(tmp); + } + + typedef TriangularView ConstTransposeReturnType; + /** \sa MatrixBase::transpose() const */ + EIGEN_DEVICE_FUNC inline const ConstTransposeReturnType transpose() const { + return ConstTransposeReturnType(m_matrix.transpose()); + } + + template + EIGEN_DEVICE_FUNC inline Solve solve(const MatrixBase& other) const { + return Solve(*this, other.derived()); + } + +// workaround MSVC ICE +#if EIGEN_COMP_MSVC + template + EIGEN_DEVICE_FUNC inline const internal::triangular_solve_retval solve( + const MatrixBase& other) const { + return Base::template solve(other); + } +#else + using Base::solve; +#endif + + /** \returns a selfadjoint view of the referenced triangular part which must be either \c #Upper or \c #Lower. + * + * This is a shortcut for \code this->nestedExpression().selfadjointView<(*this)::Mode>() \endcode + * \sa MatrixBase::selfadjointView() */ + EIGEN_DEVICE_FUNC SelfAdjointView selfadjointView() { + EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR); + return SelfAdjointView(m_matrix); + } + + /** This is the const version of selfadjointView() */ + EIGEN_DEVICE_FUNC const SelfAdjointView selfadjointView() const { + EIGEN_STATIC_ASSERT((Mode & (UnitDiag | ZeroDiag)) == 0, PROGRAMMING_ERROR); + return SelfAdjointView(m_matrix); + } + + /** \returns the determinant of the triangular matrix + * \sa MatrixBase::determinant() */ + EIGEN_DEVICE_FUNC Scalar determinant() const { + if (Mode & UnitDiag) + return 1; + else if (Mode & ZeroDiag) + return 0; + else + return m_matrix.diagonal().prod(); + } + + protected: + MatrixTypeNested m_matrix; +}; + +/** \ingroup Core_Module + * + * \brief Base class for a triangular part in a \b dense matrix + * + * This class is an abstract base class of class TriangularView, and objects of type TriangularViewImpl cannot be + * instantiated. It extends class TriangularView with additional methods which available for dense expressions only. + * + * \sa class TriangularView, MatrixBase::triangularView() + */ +template +class TriangularViewImpl : public TriangularBase> { + public: + typedef TriangularView TriangularViewType; + + typedef TriangularBase Base; + typedef typename internal::traits::Scalar Scalar; + + typedef MatrixType_ MatrixType; + typedef typename MatrixType::PlainObject DenseMatrixType; + typedef DenseMatrixType PlainObject; + + public: + using Base::derived; + using Base::evalToLazy; + + typedef typename internal::traits::StorageKind StorageKind; + + enum { Mode = Mode_, Flags = internal::traits::Flags }; + + /** \returns the outer-stride of the underlying dense matrix + * \sa DenseCoeffsBase::outerStride() */ + EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); } + /** \returns the inner-stride of the underlying dense matrix + * \sa DenseCoeffsBase::innerStride() */ + EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); } + + /** \sa MatrixBase::operator+=() */ + template + EIGEN_DEVICE_FUNC TriangularViewType& operator+=(const DenseBase& other) { + internal::call_assignment_no_alias(derived(), other.derived(), + internal::add_assign_op()); + return derived(); + } + /** \sa MatrixBase::operator-=() */ + template + EIGEN_DEVICE_FUNC TriangularViewType& operator-=(const DenseBase& other) { + internal::call_assignment_no_alias(derived(), other.derived(), + internal::sub_assign_op()); + return derived(); + } + + /** \sa MatrixBase::operator*=() */ + EIGEN_DEVICE_FUNC TriangularViewType& operator*=(const typename internal::traits::Scalar& other) { + return *this = derived().nestedExpression() * other; + } + /** \sa DenseBase::operator/=() */ + EIGEN_DEVICE_FUNC TriangularViewType& operator/=(const typename internal::traits::Scalar& other) { + return *this = derived().nestedExpression() / other; + } + + /** \sa MatrixBase::fill() */ + EIGEN_DEVICE_FUNC void fill(const Scalar& value) { setConstant(value); } + /** \sa MatrixBase::setConstant() */ + EIGEN_DEVICE_FUNC TriangularViewType& setConstant(const Scalar& value) { + return *this = MatrixType::Constant(derived().rows(), derived().cols(), value); + } + /** \sa MatrixBase::setZero() */ + EIGEN_DEVICE_FUNC TriangularViewType& setZero() { return setConstant(Scalar(0)); } + /** \sa MatrixBase::setOnes() */ + EIGEN_DEVICE_FUNC TriangularViewType& setOnes() { return setConstant(Scalar(1)); } + + /** \sa MatrixBase::coeff() + * \warning the coordinates must fit into the referenced triangular part + */ + EIGEN_DEVICE_FUNC inline Scalar coeff(Index row, Index col) const { + Base::check_coordinates_internal(row, col); + return derived().nestedExpression().coeff(row, col); + } + + /** \sa MatrixBase::coeffRef() + * \warning the coordinates must fit into the referenced triangular part + */ + EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) { + EIGEN_STATIC_ASSERT_LVALUE(TriangularViewType); + Base::check_coordinates_internal(row, col); + return derived().nestedExpression().coeffRef(row, col); + } + + /** Assigns a triangular matrix to a triangular part of a dense matrix */ + template + EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularBase& other); + + /** Shortcut for\code *this = other.other.triangularView<(*this)::Mode>() \endcode */ + template + EIGEN_DEVICE_FUNC TriangularViewType& operator=(const MatrixBase& other); + +#ifndef EIGEN_PARSED_BY_DOXYGEN + EIGEN_DEVICE_FUNC TriangularViewType& operator=(const TriangularViewImpl& other) { + return *this = other.derived().nestedExpression(); + } + + template + /** \deprecated */ + EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const TriangularBase& other); + + template + /** \deprecated */ + EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void lazyAssign(const MatrixBase& other); +#endif + + /** Efficient triangular matrix times vector/matrix product */ + template + EIGEN_DEVICE_FUNC const Product operator*( + const MatrixBase& rhs) const { + return Product(derived(), rhs.derived()); + } + + /** Efficient vector/matrix times triangular matrix product */ + template + friend EIGEN_DEVICE_FUNC const Product operator*( + const MatrixBase& lhs, const TriangularViewImpl& rhs) { + return Product(lhs.derived(), rhs.derived()); + } + + /** \returns the product of the inverse of \c *this with \a other, \a *this being triangular. + * + * This function computes the inverse-matrix matrix product inverse(\c *this) * \a other if + * \a Side==OnTheLeft (the default), or the right-inverse-multiply \a other * inverse(\c *this) if + * \a Side==OnTheRight. + * + * Note that the template parameter \c Side can be omitted, in which case \c Side==OnTheLeft + * + * The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the + * diagonal must be non zero). It works as a forward (resp. backward) substitution if \c *this + * is an upper (resp. lower) triangular matrix. + * + * Example: \include Triangular_solve.cpp + * Output: \verbinclude Triangular_solve.out + * + * This function returns an expression of the inverse-multiply and can works in-place if it is assigned + * to the same matrix or vector \a other. + * + * For users coming from BLAS, this function (and more specifically solveInPlace()) offer + * all the operations supported by the \c *TRSV and \c *TRSM BLAS routines. + * + * \sa TriangularView::solveInPlace() + */ + template + inline const internal::triangular_solve_retval solve( + const MatrixBase& other) const; + + /** "in-place" version of TriangularView::solve() where the result is written in \a other + * + * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. + * This function will const_cast it, so constness isn't honored here. + * + * Note that the template parameter \c Side can be omitted, in which case \c Side==OnTheLeft + * + * See TriangularView:solve() for the details. + */ + template + EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase& other) const; + + template + EIGEN_DEVICE_FUNC void solveInPlace(const MatrixBase& other) const { + return solveInPlace(other); + } + + /** Swaps the coefficients of the common triangular parts of two matrices */ + template + EIGEN_DEVICE_FUNC +#ifdef EIGEN_PARSED_BY_DOXYGEN + void + swap(TriangularBase& other) +#else + void + swap(TriangularBase const& other) +#endif + { + EIGEN_STATIC_ASSERT_LVALUE(OtherDerived); + call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op()); + } + + /** Shortcut for \code (*this).swap(other.triangularView<(*this)::Mode>()) \endcode */ + template + /** \deprecated */ + EIGEN_DEPRECATED EIGEN_DEVICE_FUNC void swap(MatrixBase const& other) { + EIGEN_STATIC_ASSERT_LVALUE(OtherDerived); + call_assignment(derived(), other.const_cast_derived(), internal::swap_assign_op()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _solve_impl(const RhsType& rhs, DstType& dst) const { + if (!internal::is_same_dense(dst, rhs)) dst = rhs; + this->solveInPlace(dst); + } + + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha, + bool beta); + + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl) +}; + +/*************************************************************************** + * Implementation of triangular evaluation/assignment + ***************************************************************************/ + +#ifndef EIGEN_PARSED_BY_DOXYGEN +// FIXME should we keep that possibility +template +template +EIGEN_DEVICE_FUNC inline TriangularView& TriangularViewImpl::operator=( + const MatrixBase& other) { + internal::call_assignment_no_alias(derived(), other.derived(), + internal::assign_op()); + return derived(); +} + +// FIXME should we keep that possibility +template +template +EIGEN_DEVICE_FUNC void TriangularViewImpl::lazyAssign(const MatrixBase& other) { + internal::call_assignment_no_alias(derived(), other.template triangularView()); +} + +template +template +EIGEN_DEVICE_FUNC inline TriangularView& TriangularViewImpl::operator=( + const TriangularBase& other) { + eigen_assert(Mode == int(OtherDerived::Mode)); + internal::call_assignment(derived(), other.derived()); + return derived(); +} + +template +template +EIGEN_DEVICE_FUNC void TriangularViewImpl::lazyAssign( + const TriangularBase& other) { + eigen_assert(Mode == int(OtherDerived::Mode)); + internal::call_assignment_no_alias(derived(), other.derived()); +} +#endif + +/*************************************************************************** + * Implementation of TriangularBase methods + ***************************************************************************/ + +/** Assigns a triangular or selfadjoint matrix to a dense matrix. + * If the matrix is triangular, the opposite part is set to zero. */ +template +template +EIGEN_DEVICE_FUNC void TriangularBase::evalTo(MatrixBase& other) const { + evalToLazy(other.derived()); +} + +/*************************************************************************** + * Implementation of TriangularView methods + ***************************************************************************/ + +/*************************************************************************** + * Implementation of MatrixBase methods + ***************************************************************************/ + +/** + * \returns an expression of a triangular view extracted from the current matrix + * + * The parameter \a Mode can have the following values: \c #Upper, \c #StrictlyUpper, \c #UnitUpper, + * \c #Lower, \c #StrictlyLower, \c #UnitLower. + * + * Example: \include MatrixBase_triangularView.cpp + * Output: \verbinclude MatrixBase_triangularView.out + * + * \sa class TriangularView + */ +template +template +EIGEN_DEVICE_FUNC constexpr typename MatrixBase::template TriangularViewReturnType::Type +MatrixBase::triangularView() { + return typename TriangularViewReturnType::Type(derived()); +} + +/** This is the const version of MatrixBase::triangularView() */ +template +template +EIGEN_DEVICE_FUNC constexpr typename MatrixBase::template ConstTriangularViewReturnType::Type +MatrixBase::triangularView() const { + return typename ConstTriangularViewReturnType::Type(derived()); +} + +/** \returns true if *this is approximately equal to an upper triangular matrix, + * within the precision given by \a prec. + * + * \sa isLowerTriangular() + */ +template +bool MatrixBase::isUpperTriangular(const RealScalar& prec) const { + RealScalar maxAbsOnUpperPart = static_cast(-1); + for (Index j = 0; j < cols(); ++j) { + Index maxi = numext::mini(j, rows() - 1); + for (Index i = 0; i <= maxi; ++i) { + RealScalar absValue = numext::abs(coeff(i, j)); + if (absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue; + } + } + RealScalar threshold = maxAbsOnUpperPart * prec; + for (Index j = 0; j < cols(); ++j) + for (Index i = j + 1; i < rows(); ++i) + if (numext::abs(coeff(i, j)) > threshold) return false; + return true; +} + +/** \returns true if *this is approximately equal to a lower triangular matrix, + * within the precision given by \a prec. + * + * \sa isUpperTriangular() + */ +template +bool MatrixBase::isLowerTriangular(const RealScalar& prec) const { + RealScalar maxAbsOnLowerPart = static_cast(-1); + for (Index j = 0; j < cols(); ++j) + for (Index i = j; i < rows(); ++i) { + RealScalar absValue = numext::abs(coeff(i, j)); + if (absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue; + } + RealScalar threshold = maxAbsOnLowerPart * prec; + for (Index j = 1; j < cols(); ++j) { + Index maxi = numext::mini(j, rows() - 1); + for (Index i = 0; i < maxi; ++i) + if (numext::abs(coeff(i, j)) > threshold) return false; + } + return true; +} + +/*************************************************************************** +**************************************************************************** +* Evaluators and Assignment of triangular expressions +*************************************************************************** +***************************************************************************/ + +namespace internal { + +// TODO: currently a triangular expression has the form TriangularView<.,.> +// in the future triangular-ness should be defined by the expression traits +// such that Transpose > is valid. (currently TriangularBase::transpose() is overloaded to make +// it work) +template +struct evaluator_traits> { + typedef typename storage_kind_to_evaluator_kind::Kind Kind; + typedef typename glue_shapes::Shape, TriangularShape>::type Shape; +}; + +template +struct unary_evaluator, IndexBased> : evaluator> { + typedef TriangularView XprType; + typedef evaluator> Base; + EIGEN_DEVICE_FUNC unary_evaluator(const XprType& xpr) : Base(xpr.nestedExpression()) {} +}; + +// Additional assignment kinds: +struct Triangular2Triangular {}; +struct Triangular2Dense {}; +struct Dense2Triangular {}; + +template +struct triangular_assignment_loop; + +/** \internal Specialization of the dense assignment kernel for triangular matrices. + * The main difference is that the triangular, diagonal, and opposite parts are processed through three different + * functions. \tparam UpLo must be either Lower or Upper \tparam Mode must be either 0, UnitDiag, ZeroDiag, or + * SelfAdjoint + */ +template +class triangular_dense_assignment_kernel + : public generic_dense_assignment_kernel { + protected: + typedef generic_dense_assignment_kernel Base; + typedef typename Base::DstXprType DstXprType; + typedef typename Base::SrcXprType SrcXprType; + using Base::m_dst; + using Base::m_functor; + using Base::m_src; + + public: + typedef typename Base::DstEvaluatorType DstEvaluatorType; + typedef typename Base::SrcEvaluatorType SrcEvaluatorType; + typedef typename Base::Scalar Scalar; + typedef typename Base::AssignmentTraits AssignmentTraits; + + EIGEN_DEVICE_FUNC triangular_dense_assignment_kernel(DstEvaluatorType& dst, const SrcEvaluatorType& src, + const Functor& func, DstXprType& dstExpr) + : Base(dst, src, func, dstExpr) {} + +#ifdef EIGEN_INTERNAL_DEBUGGING + EIGEN_DEVICE_FUNC void assignCoeff(Index row, Index col) { + eigen_internal_assert(row != col); + Base::assignCoeff(row, col); + } +#else + using Base::assignCoeff; +#endif + + EIGEN_DEVICE_FUNC void assignDiagonalCoeff(Index id) { + if (Mode == UnitDiag && SetOpposite) + m_functor.assignCoeff(m_dst.coeffRef(id, id), Scalar(1)); + else if (Mode == ZeroDiag && SetOpposite) + m_functor.assignCoeff(m_dst.coeffRef(id, id), Scalar(0)); + else if (Mode == 0) + Base::assignCoeff(id, id); + } + + EIGEN_DEVICE_FUNC void assignOppositeCoeff(Index row, Index col) { + eigen_internal_assert(row != col); + if (SetOpposite) m_functor.assignCoeff(m_dst.coeffRef(row, col), Scalar(0)); + } +}; + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src, + const Functor& func) { + typedef evaluator DstEvaluatorType; + typedef evaluator SrcEvaluatorType; + + SrcEvaluatorType srcEvaluator(src); + + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + DstEvaluatorType dstEvaluator(dst); + + typedef triangular_dense_assignment_kernel + Kernel; + Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived()); + + enum { + unroll = DstXprType::SizeAtCompileTime != Dynamic && SrcEvaluatorType::CoeffReadCost < HugeCost && + DstXprType::SizeAtCompileTime * + (int(DstEvaluatorType::CoeffReadCost) + int(SrcEvaluatorType::CoeffReadCost)) / 2 <= + EIGEN_UNROLLING_LIMIT + }; + + triangular_assignment_loop::run( + kernel); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_triangular_assignment_loop(DstXprType& dst, const SrcXprType& src) { + call_triangular_assignment_loop( + dst, src, internal::assign_op()); +} + +template <> +struct AssignmentKind { + typedef Triangular2Triangular Kind; +}; +template <> +struct AssignmentKind { + typedef Triangular2Dense Kind; +}; +template <> +struct AssignmentKind { + typedef Dense2Triangular Kind; +}; + +template +struct Assignment { + EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) { + eigen_assert(int(DstXprType::Mode) == int(SrcXprType::Mode)); + + call_triangular_assignment_loop(dst, src, func); + } +}; + +template +struct Assignment { + EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) { + call_triangular_assignment_loop(dst, src, func); + } +}; + +template +struct Assignment { + EIGEN_DEVICE_FUNC static void run(DstXprType& dst, const SrcXprType& src, const Functor& func) { + call_triangular_assignment_loop(dst, src, func); + } +}; + +template +struct triangular_assignment_loop { + // FIXME: this is not very clean, perhaps this information should be provided by the kernel? + typedef typename Kernel::DstEvaluatorType DstEvaluatorType; + typedef typename DstEvaluatorType::XprType DstXprType; + + enum { + col = (UnrollCount - 1) / DstXprType::RowsAtCompileTime, + row = (UnrollCount - 1) % DstXprType::RowsAtCompileTime + }; + + typedef typename Kernel::Scalar Scalar; + + EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) { + triangular_assignment_loop::run(kernel); + + if (row == col) + kernel.assignDiagonalCoeff(row); + else if (((Mode & Lower) && row > col) || ((Mode & Upper) && row < col)) + kernel.assignCoeff(row, col); + else if (SetOpposite) + kernel.assignOppositeCoeff(row, col); + } +}; + +// prevent buggy user code from causing an infinite recursion +template +struct triangular_assignment_loop { + EIGEN_DEVICE_FUNC static inline void run(Kernel&) {} +}; + +// TODO: experiment with a recursive assignment procedure splitting the current +// triangular part into one rectangular and two triangular parts. + +template +struct triangular_assignment_loop { + typedef typename Kernel::Scalar Scalar; + typedef typename Kernel::DstEvaluatorType DstEvaluatorType; + typedef typename Kernel::AssignmentTraits AssignmentTraits; + + enum { + IsRowMajor = (int(DstEvaluatorType::Flags) & RowMajorBit) != 0, + // In col-major: inner=row, outer=col. Upper means row active before diagonal. + // In row-major: inner=col, outer=row. Upper means rowouter -> active after diagonal. + // So ActiveBeforeDiag = (Upper XOR IsRowMajor). + ActiveBeforeDiag = (bool(Mode & Upper) != bool(IsRowMajor)) + }; + + // Compile-time outer/inner to row/col mapping. These constant-fold away entirely: + // ColMajor: row(outer,i) -> i, col(outer,i) -> outer + // RowMajor: row(outer,i) -> outer, col(outer,i) -> i + static constexpr Index row(Index outer, Index inner) { return IsRowMajor ? outer : inner; } + static constexpr Index col(Index outer, Index inner) { return IsRowMajor ? inner : outer; } + + // Iterates in outer/inner order matching the storage layout for cache friendliness. + // Unlike the old code (which always iterated outer=col, inner=row), this gives + // contiguous memory access for both ColMajor and RowMajor storage. + // Simple scalar loops allow GCC to recognize memcpy/memset idioms and Clang to auto-vectorize. + // Uses a single running index 'i' per column (not separate loop variables) so the compiler + // can track the continuous progression and optimize register allocation. + EIGEN_DEVICE_FUNC static inline void run(Kernel& kernel) { + const Index outerSize = IsRowMajor ? kernel.rows() : kernel.cols(); + const Index innerSize = IsRowMajor ? kernel.cols() : kernel.rows(); + + for (Index outer = 0; outer < outerSize; ++outer) { + const Index maxi = numext::mini(outer, innerSize); + Index i = 0; + + if (ActiveBeforeDiag) { + for (; i < maxi; ++i) kernel.assignCoeff(row(outer, i), col(outer, i)); + } else if (SetOpposite) { + for (; i < maxi; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i)); + } else { + i = maxi; + } + + if (i < innerSize) kernel.assignDiagonalCoeff(i++); + + if (!ActiveBeforeDiag) { + for (; i < innerSize; ++i) kernel.assignCoeff(row(outer, i), col(outer, i)); + } else if (SetOpposite) { + for (; i < innerSize; ++i) kernel.assignOppositeCoeff(row(outer, i), col(outer, i)); + } + } + } +}; + +} // end namespace internal + +/** Assigns a triangular or selfadjoint matrix to a dense matrix. + * If the matrix is triangular, the opposite part is set to zero. */ +template +template +EIGEN_DEVICE_FUNC void TriangularBase::evalToLazy(MatrixBase& other) const { + other.derived().resize(this->rows(), this->cols()); + internal::call_triangular_assignment_loop( + other.derived(), derived().nestedExpression()); +} + +namespace internal { + +// Triangular = Product +template +struct Assignment, + internal::assign_op::Scalar>, Dense2Triangular> { + typedef Product SrcXprType; + static void run(DstXprType& dst, const SrcXprType& src, + const internal::assign_op&) { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols); + + dst._assignProduct(src, Scalar(1), false); + } +}; + +// Triangular += Product +template +struct Assignment, + internal::add_assign_op::Scalar>, + Dense2Triangular> { + typedef Product SrcXprType; + static void run(DstXprType& dst, const SrcXprType& src, + const internal::add_assign_op&) { + dst._assignProduct(src, Scalar(1), true); + } +}; + +// Triangular -= Product +template +struct Assignment, + internal::sub_assign_op::Scalar>, + Dense2Triangular> { + typedef Product SrcXprType; + static void run(DstXprType& dst, const SrcXprType& src, + const internal::sub_assign_op&) { + dst._assignProduct(src, Scalar(-1), true); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_TRIANGULARMATRIX_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorBlock.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorBlock.h new file mode 100644 index 0000000..1277e26 --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorBlock.h @@ -0,0 +1,83 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_VECTORBLOCK_H +#define EIGEN_VECTORBLOCK_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +namespace internal { +template +struct traits > + : public traits::Flags & RowMajorBit ? 1 : Size, + traits::Flags & RowMajorBit ? Size : 1> > {}; +} // namespace internal + +/** \class VectorBlock + * \ingroup Core_Module + * + * \brief Expression of a fixed-size or dynamic-size sub-vector + * + * \tparam VectorType the type of the object in which we are taking a sub-vector + * \tparam Size size of the sub-vector we are taking at compile time (optional) + * + * This class represents an expression of either a fixed-size or dynamic-size sub-vector. + * It is the return type of DenseBase::segment(Index,Index) and DenseBase::segment(Index) and + * most of the time this is the only way it is used. + * + * However, if you want to directly manipulate sub-vector expressions, + * for instance if you want to write a function returning such an expression, you + * will need to use this class. + * + * Here is an example illustrating the dynamic case: + * \include class_VectorBlock.cpp + * Output: \verbinclude class_VectorBlock.out + * + * \note Even though this expression has dynamic size, in the case where \a VectorType + * has fixed size, this expression inherits a fixed maximal size which means that evaluating + * it does not cause a dynamic memory allocation. + * + * Here is an example illustrating the fixed-size case: + * \include class_FixedVectorBlock.cpp + * Output: \verbinclude class_FixedVectorBlock.out + * + * \sa class Block, DenseBase::segment(Index,Index,Index,Index), DenseBase::segment(Index,Index) + */ +template +class VectorBlock : public Block::Flags & RowMajorBit ? 1 : Size, + internal::traits::Flags & RowMajorBit ? Size : 1> { + typedef Block::Flags & RowMajorBit ? 1 : Size, + internal::traits::Flags & RowMajorBit ? Size : 1> + Base; + enum { IsColVector = !(internal::traits::Flags & RowMajorBit) }; + + public: + EIGEN_DENSE_PUBLIC_INTERFACE(VectorBlock) + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock) + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(VectorBlock) + + /** Dynamic-size constructor + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE VectorBlock(VectorType& vector, Index start, Index size) + : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start, IsColVector ? size : 1, IsColVector ? 1 : size) { + } + + /** Fixed-size constructor + */ + EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE VectorBlock(VectorType& vector, Index start) + : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start) {} +}; + +} // end namespace Eigen + +#endif // EIGEN_VECTORBLOCK_H diff --git a/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorwiseOp.h b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorwiseOp.h new file mode 100644 index 0000000..9e34d8c --- /dev/null +++ b/data_acq_and_processing/third_party/eigen/Eigen/src/Core/VectorwiseOp.h @@ -0,0 +1,735 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2019 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PARTIAL_REDUX_H +#define EIGEN_PARTIAL_REDUX_H + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +namespace Eigen { + +/** \class PartialReduxExpr + * \ingroup Core_Module + * + * \brief Generic expression of a partially reduxed matrix + * + * \tparam MatrixType the type of the matrix we are applying the redux operation + * \tparam MemberOp type of the member functor + * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal) + * + * This class represents an expression of a partial redux operator of a matrix. + * It is the return type of some VectorwiseOp functions, + * and most of the time this is the only way it is used. + * + * \sa class VectorwiseOp + */ + +template +class PartialReduxExpr; + +namespace internal { + +template +struct traits > : traits { + typedef typename MemberOp::result_type Scalar; + typedef typename traits::StorageKind StorageKind; + typedef typename traits::XprKind XprKind; + typedef typename MatrixType::Scalar InputScalar; + enum { + RowsAtCompileTime = Direction == Vertical ? 1 : MatrixType::RowsAtCompileTime, + ColsAtCompileTime = Direction == Horizontal ? 1 : MatrixType::ColsAtCompileTime, + MaxRowsAtCompileTime = Direction == Vertical ? 1 : MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = Direction == Horizontal ? 1 : MatrixType::MaxColsAtCompileTime, + Flags = RowsAtCompileTime == 1 ? RowMajorBit : 0, + TraversalSize = Direction == Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime + }; +}; +} // namespace internal + +template +class PartialReduxExpr : public internal::dense_xpr_base >::type, + internal::no_assignment_operator { + public: + typedef typename internal::dense_xpr_base::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(PartialReduxExpr) + + EIGEN_DEVICE_FUNC explicit PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp()) + : m_matrix(mat), m_functor(func) {} + + EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return (Direction == Vertical ? 1 : m_matrix.rows()); } + EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return (Direction == Horizontal ? 1 : m_matrix.cols()); } + + EIGEN_DEVICE_FUNC typename MatrixType::Nested nestedExpression() const { return m_matrix; } + + EIGEN_DEVICE_FUNC const MemberOp& functor() const { return m_functor; } + + protected: + typename MatrixType::Nested m_matrix; + const MemberOp m_functor; +}; + +template +struct partial_redux_dummy_func; + +#define EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(MEMBER, COST, VECTORIZABLE, BINARYOP) \ + template \ + struct member_##MEMBER { \ + typedef ResultType result_type; \ + typedef BINARYOP BinaryOp; \ + template \ + struct Cost { \ + enum { value = COST }; \ + }; \ + enum { Vectorizable = VECTORIZABLE }; \ + template \ + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const { \ + return mat.MEMBER(); \ + } \ + BinaryOp binaryFunc() const { return BinaryOp(); } \ + } + +#define EIGEN_MEMBER_FUNCTOR(MEMBER, COST) EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(MEMBER, COST, 0, partial_redux_dummy_func) + +namespace internal { + +EIGEN_MEMBER_FUNCTOR(norm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); +EIGEN_MEMBER_FUNCTOR(stableNorm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); +EIGEN_MEMBER_FUNCTOR(blueNorm, (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost); +EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size - 1) * functor_traits >::Cost); +EIGEN_MEMBER_FUNCTOR(all, (Size - 1) * NumTraits::AddCost); +EIGEN_MEMBER_FUNCTOR(any, (Size - 1) * NumTraits::AddCost); +EIGEN_MEMBER_FUNCTOR(count, (Size - 1) * NumTraits::AddCost); + +EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(sum, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_sum_op); +EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(minCoeff, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_min_op); +EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(maxCoeff, (Size - 1) * NumTraits::AddCost, 1, internal::scalar_max_op); +EIGEN_MAKE_PARTIAL_REDUX_FUNCTOR(prod, (Size - 1) * NumTraits::MulCost, 1, internal::scalar_product_op); + +template +struct member_lpnorm { + typedef ResultType result_type; + enum { Vectorizable = 0 }; + template + struct Cost { + enum { value = (Size + 5) * NumTraits::MulCost + (Size - 1) * NumTraits::AddCost }; + }; + EIGEN_DEVICE_FUNC member_lpnorm() {} + template + EIGEN_DEVICE_FUNC inline ResultType operator()(const XprType& mat) const { + return mat.template lpNorm

(); + } +}; + +template +struct member_redux { + typedef BinaryOpT BinaryOp; + typedef typename result_of::type result_type; + + enum { Vectorizable = functor_traits::PacketAccess }; + template + struct Cost { + enum { value = (Size - 1) * functor_traits::Cost }; + }; + EIGEN_DEVICE_FUNC explicit member_redux(const BinaryOp func) : m_functor(func) {} + template + EIGEN_DEVICE_FUNC inline result_type operator()(const DenseBase& mat) const { + return mat.redux(m_functor); + } + const BinaryOp& binaryFunc() const { return m_functor; } + const BinaryOp m_functor; +}; + +template +struct scalar_replace_zero_with_one_op { + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& x) const { + return numext::is_exactly_zero(x) ? Scalar(1) : x; + } + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& x) const { + return pselect(pcmp_eq(x, pzero(x)), pset1(Scalar(1)), x); + } +}; +template +struct functor_traits> { + enum { Cost = 1, PacketAccess = packet_traits::HasCmp }; +}; + +} // namespace internal + +/** \class VectorwiseOp + * \ingroup Core_Module + * + * \brief Pseudo expression providing broadcasting and partial reduction operations + * + * \tparam ExpressionType the type of the object on which to do partial reductions + * \tparam Direction indicates whether to operate on columns (#Vertical) or rows (#Horizontal) + * + * This class represents a pseudo expression with broadcasting and partial reduction features. + * It is the return type of DenseBase::colwise() and DenseBase::rowwise() + * and most of the time this is the only way it is explicitly used. + * + * To understand the logic of rowwise/colwise expression, let's consider a generic case `A.colwise().foo()` + * where `foo` is any method of `VectorwiseOp`. This expression is equivalent to applying `foo()` to each + * column of `A` and then re-assemble the outputs in a matrix expression: + * \code [A.col(0).foo(), A.col(1).foo(), ..., A.col(A.cols()-1).foo()] \endcode + * + * Example: \include MatrixBase_colwise.cpp + * Output: \verbinclude MatrixBase_colwise.out + * + * The begin() and end() methods are obviously exceptions to the previous rule as they + * return STL-compatible begin/end iterators to the rows or columns of the nested expression. + * Typical use cases include for-range-loop and calls to STL algorithms: + * + * Example: \include MatrixBase_colwise_iterator_cxx11.cpp + * Output: \verbinclude MatrixBase_colwise_iterator_cxx11.out + * + * For a partial reduction on an empty input, some rules apply. + * For the sake of clarity, let's consider a vertical reduction: + * - If the number of columns is zero, then a 1x0 row-major vector expression is returned. + * - Otherwise, if the number of rows is zero, then + * - a row vector of zeros is returned for sum-like reductions (sum, squaredNorm, norm, etc.) + * - a row vector of ones is returned for a product reduction (e.g., MatrixXd(n,0).colwise().prod()) + * - an assert is triggered for all other reductions (minCoeff,maxCoeff,redux(bin_op)) + * + * \sa DenseBase::colwise(), DenseBase::rowwise(), class PartialReduxExpr + */ +template +class VectorwiseOp { + public: + typedef typename ExpressionType::Scalar Scalar; + typedef typename ExpressionType::RealScalar RealScalar; + typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3 + typedef typename internal::ref_selector::non_const_type ExpressionTypeNested; + typedef internal::remove_all_t ExpressionTypeNestedCleaned; + + template