mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
337 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55bf82c923 | ||
|
|
0b341486db | ||
|
|
9db0038c42 | ||
|
|
89d7ba0be0 | ||
|
|
c3bab0edb7 | ||
|
|
a1a26f45d3 | ||
|
|
f5ae3a4b5a | ||
|
|
8817798273 | ||
|
|
287c7b8818 | ||
|
|
5ec4922349 | ||
|
|
5a18f7545d | ||
|
|
12570d97ce | ||
|
|
3fc53d2564 | ||
|
|
9ff0baa680 | ||
|
|
1c4b4e136b | ||
|
|
57934b9c30 | ||
|
|
52aed8ac58 | ||
|
|
1304e43f15 | ||
|
|
e47593fb28 | ||
|
|
0104c34b7d | ||
|
|
f82d9bdf9a | ||
|
|
c9edcc5acd | ||
|
|
487edbf325 | ||
|
|
a29a390afa | ||
|
|
a16d18a632 | ||
|
|
3c3653b9de | ||
|
|
c15842c374 | ||
|
|
3c90fc2e64 | ||
|
|
d9c9508a12 | ||
|
|
d6bb34fa5a | ||
|
|
e5b5ab53b8 | ||
|
|
f2829c1358 | ||
|
|
d38504a4c8 | ||
|
|
95e4508b04 | ||
|
|
b064b5e68e | ||
|
|
f7df9f92ff | ||
|
|
d2dcca52a3 | ||
|
|
7408e923a7 | ||
|
|
18ca438a62 | ||
|
|
d286300362 | ||
|
|
02ba4e2f54 | ||
|
|
2eef21a8d5 | ||
|
|
bea1737a5a | ||
|
|
4b09865b8f | ||
|
|
f6aa60bcf3 | ||
|
|
8d236e74a1 | ||
|
|
046a84c0ef | ||
|
|
d7f60257dd | ||
|
|
874ff5a0b4 | ||
|
|
062d6bd47a | ||
|
|
b05c5dd1be | ||
|
|
9ea1050281 | ||
|
|
2776a3197b | ||
|
|
670de11dca | ||
|
|
a79deafc6d | ||
|
|
65e4ae4ff4 | ||
|
|
00d7f8e567 | ||
|
|
414ee1db4b | ||
|
|
56c7e164f0 | ||
|
|
81b0ab53cf | ||
|
|
9849931500 | ||
|
|
e7c48fac9b | ||
|
|
899e2ada15 | ||
|
|
6a722602e6 | ||
|
|
d3dcb04f2d | ||
|
|
291ee89684 | ||
|
|
876b1fb842 | ||
|
|
32754d806d | ||
|
|
9e3c73110a | ||
|
|
4225b7bf57 | ||
|
|
7ccea9222c | ||
|
|
52cf07d266 | ||
|
|
25f1658fce | ||
|
|
5f43a42ee7 | ||
|
|
a5fbf27843 | ||
|
|
294682a25a | ||
|
|
f645d1f911 | ||
|
|
8973d12cda | ||
|
|
81cb887baf | ||
|
|
3134d5290b | ||
|
|
3e5b3a33fa | ||
|
|
8690ba923c | ||
|
|
36c478cd6e | ||
|
|
178858f1bd | ||
|
|
385fd3d918 | ||
|
|
dcaa58744e | ||
|
|
9ae03f4589 | ||
|
|
708fa36750 | ||
|
|
d58bb54e7f | ||
|
|
0c7974dd4d | ||
|
|
22792c696f | ||
|
|
61b85b1436 | ||
|
|
cc6c4d807b | ||
|
|
c5020c6e8e | ||
|
|
1eec38dc36 | ||
|
|
e556e647f4 | ||
|
|
86a192681e | ||
|
|
48df9ed715 | ||
|
|
ccdcebcf03 | ||
|
|
9a4b7998cf | ||
|
|
87241089e1 | ||
|
|
96e1e582ff | ||
|
|
4f33fbfc07 | ||
|
|
2d53466fa9 | ||
|
|
f5741d4277 | ||
|
|
0b606dcccd | ||
|
|
c4c70669d1 | ||
|
|
ee87f5ee49 | ||
|
|
a5632fe1db | ||
|
|
e8e1084267 | ||
|
|
ec0b2f900c | ||
|
|
b179f8e1a4 | ||
|
|
62d01d3cf4 | ||
|
|
534dc60672 | ||
|
|
38d916d50f | ||
|
|
24fd14dab6 | ||
|
|
4d44ca226e | ||
|
|
b26e12abcf | ||
|
|
a7554023a4 | ||
|
|
9d97c06d9d | ||
|
|
1fc17c4792 | ||
|
|
6efaece8ce | ||
|
|
294f5f16dd | ||
|
|
f86818b5a6 | ||
|
|
336ad58213 | ||
|
|
af5034b3c0 | ||
|
|
7f881e814f | ||
|
|
a4252584ed | ||
|
|
b365f443a2 | ||
|
|
484ed3bbe2 | ||
|
|
92959aa5f3 | ||
|
|
2db5888253 | ||
|
|
f268e79709 | ||
|
|
9e8f437a6f | ||
|
|
824b75f182 | ||
|
|
a30b498ab4 | ||
|
|
28e15574df | ||
|
|
6c84b03d77 | ||
|
|
4361cb8913 | ||
|
|
50ad8b9010 | ||
|
|
0c1ef2f4c6 | ||
|
|
3efe6e4176 | ||
|
|
335d3bcf05 | ||
|
|
5052d3659b | ||
|
|
5bef59e371 | ||
|
|
265ab86005 | ||
|
|
b3d580dec7 | ||
|
|
fd831d5a12 | ||
|
|
f52a9e5315 | ||
|
|
003d0ce03e | ||
|
|
208b273106 | ||
|
|
b315f4c359 | ||
|
|
51aa62a5d4 | ||
|
|
eb7dcbbfce | ||
|
|
1d52bd4cad | ||
|
|
e2d2a7d222 | ||
|
|
af27fb7590 | ||
|
|
8d3469ca44 | ||
|
|
4432cf8ca3 | ||
|
|
cb71dc4bbf | ||
|
|
709e903335 | ||
|
|
7078cfaeaa | ||
|
|
336f0a8486 | ||
|
|
6b9d647fc2 | ||
|
|
3e90940189 | ||
|
|
8cea5f6b31 | ||
|
|
94efa16187 | ||
|
|
ac9d805c2f | ||
|
|
2db434265b | ||
|
|
8e888a45d0 | ||
|
|
6736e52d25 | ||
|
|
1c29d70312 | ||
|
|
e71de20f16 | ||
|
|
1eec8488a2 | ||
|
|
9dcde48980 | ||
|
|
215ce5bdc1 | ||
|
|
10f9478f35 | ||
|
|
9c8a653c0b | ||
|
|
8551505436 | ||
|
|
1b88042880 | ||
|
|
7db3f2f72a | ||
|
|
dae7f065d4 | ||
|
|
ab660a4d29 | ||
|
|
986f301233 | ||
|
|
d316d4f393 | ||
|
|
e1ee876daa | ||
|
|
3de311f497 | ||
|
|
06fd84cdb1 | ||
|
|
0e5c640563 | ||
|
|
be64619ab6 | ||
|
|
269bf67796 | ||
|
|
15ca6659ac | ||
|
|
d9e5fd393a | ||
|
|
fd7eba3394 | ||
|
|
d671205755 | ||
|
|
3958e7f751 | ||
|
|
164f410bb5 | ||
|
|
a2782964c1 | ||
|
|
ce3984844d | ||
|
|
361225068d | ||
|
|
6f158fb7fc | ||
|
|
789ea9d676 | ||
|
|
4336cf3833 | ||
|
|
f5a05e7ed1 | ||
|
|
9e00d94543 | ||
|
|
21ab65e4b3 | ||
|
|
ebf906a23a | ||
|
|
df4bd5e46f | ||
|
|
a3fad2e3c3 | ||
|
|
5f6fbaa0e7 | ||
|
|
8679d895d3 | ||
|
|
22875683b9 | ||
|
|
e4980616fd | ||
|
|
84bb868f07 | ||
|
|
f34a4fa335 | ||
|
|
8106d35408 | ||
|
|
fabaa6915b | ||
|
|
b27a3644a2 | ||
|
|
93f8d56789 | ||
|
|
15d72d3f9a | ||
|
|
9084e2a216 | ||
|
|
6e138d0069 | ||
|
|
4cb63808d4 | ||
|
|
c98fe0185e | ||
|
|
5f582aa4e8 | ||
|
|
c22d10f94c | ||
|
|
e3a8431a4a | ||
|
|
89f468671d | ||
|
|
2110cca431 | ||
|
|
38b83b4157 | ||
|
|
50105c3ed6 | ||
|
|
0a220721d1 | ||
|
|
1ad751b991 | ||
|
|
55b603e457 | ||
|
|
763f0a2434 | ||
|
|
9b1a3d6e19 | ||
|
|
dd139b92b4 | ||
|
|
11c8a6bf63 | ||
|
|
703951d5cd | ||
|
|
d11c8704e0 | ||
|
|
a164646c77 | ||
|
|
936eaf600a | ||
|
|
ef0cd3a289 | ||
|
|
1ed17b037d | ||
|
|
5015e48361 | ||
|
|
beabf008b0 | ||
|
|
ba9a53f9c6 | ||
|
|
52a30c1d54 | ||
|
|
cb409914e0 | ||
|
|
069ecbb4ab | ||
|
|
09fd69d734 | ||
|
|
6700f07fb0 | ||
|
|
08e6b7ad80 | ||
|
|
7e8ee5b527 | ||
|
|
93c1f62979 | ||
|
|
2b20da624a | ||
|
|
bb33ec4ef3 | ||
|
|
9c0deb55ca | ||
|
|
faf942a947 | ||
|
|
6d1439a52f | ||
|
|
2ff7961c10 | ||
|
|
c1e2156d8a | ||
|
|
84cc69f0f3 | ||
|
|
20c11bc52c | ||
|
|
eb9dadf3b2 | ||
|
|
6b3d0e68e2 | ||
|
|
aba378eb1a | ||
|
|
00f89a8f37 | ||
|
|
582c1f92c8 | ||
|
|
a040b7f15d | ||
|
|
cc6121b98d | ||
|
|
a3b89e0ee6 | ||
|
|
3614321401 | ||
|
|
139529e97b | ||
|
|
86ccd99d8d | ||
|
|
9aba671cfc | ||
|
|
2a4fdf31c8 | ||
|
|
033ac82c9d | ||
|
|
12f84acda6 | ||
|
|
e80099932a | ||
|
|
a0ec0fca5a | ||
|
|
3d90c13970 | ||
|
|
3f580e240e | ||
|
|
ebe14aae7d | ||
|
|
48137e28d8 | ||
|
|
3e502abfda | ||
|
|
b26e04f40b | ||
|
|
9f873a855f | ||
|
|
ca048aaf77 | ||
|
|
94f6f2a7de | ||
|
|
ec0a423862 | ||
|
|
505ce85814 | ||
|
|
e5b8a59cfa | ||
|
|
568a7e8eba | ||
|
|
72f2c7eed5 | ||
|
|
0c5a09d93f | ||
|
|
8ea8b481de | ||
|
|
65abb4c52e | ||
|
|
cf0f82ecbe | ||
|
|
9e02e42ff6 | ||
|
|
3645d6c138 | ||
|
|
96538b976d | ||
|
|
5066fe8bbe | ||
|
|
e1c50a3cb1 | ||
|
|
fa27cd1ed0 | ||
|
|
f44316e5f8 | ||
|
|
3a231c2349 | ||
|
|
64f7fbe3f2 | ||
|
|
76fe2e1b34 | ||
|
|
ecc6c43dba | ||
|
|
6be0131774 | ||
|
|
cfca7f71fe | ||
|
|
727dfa1c43 | ||
|
|
e747b338ee | ||
|
|
28d32f9bd8 | ||
|
|
765219aa51 | ||
|
|
e2bd8623f8 | ||
|
|
537a0e0a52 | ||
|
|
e80d6a95d9 | ||
|
|
8466244faa | ||
|
|
b46c327133 | ||
|
|
4e502dd6b0 | ||
|
|
22507fa645 | ||
|
|
b8fc1edb2c | ||
|
|
3c155ab073 | ||
|
|
b730c6f57d | ||
|
|
a930dfb229 | ||
|
|
98d3c0a413 | ||
|
|
068ff3370d | ||
|
|
1fc503e3ce | ||
|
|
d907cd4410 | ||
|
|
618de17bf7 | ||
|
|
373331e3bf | ||
|
|
42e88b1724 | ||
|
|
fb5b62fbac | ||
|
|
af991a6bdb | ||
|
|
247f2b0ffa |
140
CMakeLists.txt
140
CMakeLists.txt
@@ -1,67 +1,103 @@
|
||||
PROJECT(Eigen)
|
||||
SET(EIGEN_VERSION_NUMBER "2.0-beta1")
|
||||
project(Eigen)
|
||||
set(EIGEN_VERSION_NUMBER "2.0.3")
|
||||
|
||||
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
|
||||
#but won't stop CMake.
|
||||
EXECUTE_PROCESS(COMMAND svnversion -n ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE EIGEN_SVN_REVISION)
|
||||
execute_process(COMMAND svnversion -n ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE EIGEN_SVNVERSION_OUTPUT)
|
||||
|
||||
IF(EIGEN_SVN_REVISION)
|
||||
SET(EIGEN_VERSION "${EIGEN_VERSION_NUMBER} (SVN revision ${EIGEN_SVN_REVISION})")
|
||||
ELSE(EIGEN_SVN_REVISION)
|
||||
SET(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
ENDIF(EIGEN_SVN_REVISION)
|
||||
#we only want EIGEN_SVN_REVISION if it is an actual revision number, not a string like "exported"
|
||||
string(REGEX MATCH "^[0-9]+.*" EIGEN_SVN_REVISION "${EIGEN_SVNVERSION_OUTPUT}")
|
||||
|
||||
SET(EIGEN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
SET(EIGEN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(EIGEN_SVN_REVISION)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER} (SVN revision ${EIGEN_SVN_REVISION})")
|
||||
else(EIGEN_SVN_REVISION)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
endif(EIGEN_SVN_REVISION)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
OPTION(BUILD_TESTS "Build tests" OFF)
|
||||
OPTION(BUILD_DEMOS "Build demos" OFF)
|
||||
OPTION(BUILD_LIB "Build the binary shared library" OFF)
|
||||
OPTION(BUILD_BTL "Build benchmark suite" OFF)
|
||||
option(EIGEN_BUILD_TESTS "Build tests" OFF)
|
||||
option(EIGEN_BUILD_DEMOS "Build demos" OFF)
|
||||
if(NOT WIN32)
|
||||
option(EIGEN_BUILD_LIB "Build the binary shared library" OFF)
|
||||
endif(NOT WIN32)
|
||||
option(EIGEN_BUILD_BTL "Build benchmark suite" OFF)
|
||||
|
||||
IF(BUILD_LIB)
|
||||
OPTION(TEST_LIB "Build the unit tests using the library (disable -pedantic)" OFF)
|
||||
ENDIF(BUILD_LIB)
|
||||
if(EIGEN_BUILD_LIB)
|
||||
option(EIGEN_TEST_LIB "Build the unit tests using the library (disable -pedantic)" OFF)
|
||||
endif(EIGEN_BUILD_LIB)
|
||||
|
||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-exceptions -fno-check-new -fno-common -fstrict-aliasing")
|
||||
IF(NOT TEST_LIB)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
ENDIF(NOT TEST_LIB)
|
||||
IF(TEST_SSE2)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
|
||||
MESSAGE("Enabling SSE2 in tests/examples")
|
||||
ENDIF(TEST_SSE2)
|
||||
IF(TEST_SSE3)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse3")
|
||||
MESSAGE("Enabling SSE3 in tests/examples")
|
||||
ENDIF(TEST_SSE3)
|
||||
IF(TEST_SSSE3)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mssse3")
|
||||
MESSAGE("Enabling SSSE3 in tests/examples")
|
||||
ENDIF(TEST_SSSE3)
|
||||
IF(TEST_ALTIVEC)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maltivec -mabi=altivec")
|
||||
MESSAGE("Enabling AltiVec in tests/examples")
|
||||
ENDIF(TEST_ALTIVEC)
|
||||
ENDIF(CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wextra -fno-exceptions -fno-check-new -fno-common -fstrict-aliasing")
|
||||
if(NOT EIGEN_TEST_LIB)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||
endif(NOT EIGEN_TEST_LIB)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
option(EIGEN_TEST_SSE2 "Enable/Disable SSE2 in tests/examples" OFF)
|
||||
if(EIGEN_TEST_SSE2)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
|
||||
message("Enabling SSE2 in tests/examples")
|
||||
endif(EIGEN_TEST_SSE2)
|
||||
|
||||
ADD_SUBDIRECTORY(Eigen)
|
||||
ADD_SUBDIRECTORY(test)
|
||||
ADD_SUBDIRECTORY(doc)
|
||||
ADD_SUBDIRECTORY(demos)
|
||||
option(EIGEN_TEST_SSE3 "Enable/Disable SSE3 in tests/examples" OFF)
|
||||
if(EIGEN_TEST_SSE3)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse3")
|
||||
message("Enabling SSE3 in tests/examples")
|
||||
endif(EIGEN_TEST_SSE3)
|
||||
|
||||
IF(BUILD_BTL)
|
||||
ADD_SUBDIRECTORY(bench/btl)
|
||||
ENDIF(BUILD_BTL)
|
||||
option(EIGEN_TEST_SSSE3 "Enable/Disable SSSE3 in tests/examples" OFF)
|
||||
if(EIGEN_TEST_SSSE3)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mssse3")
|
||||
message("Enabling SSSE3 in tests/examples")
|
||||
endif(EIGEN_TEST_SSSE3)
|
||||
|
||||
option(EIGEN_TEST_ALTIVEC "Enable/Disable altivec in tests/examples" OFF)
|
||||
if(EIGEN_TEST_ALTIVEC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maltivec -mabi=altivec")
|
||||
message("Enabling AltiVec in tests/examples")
|
||||
endif(EIGEN_TEST_ALTIVEC)
|
||||
|
||||
endif(CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
|
||||
|
||||
option(EIGEN_TEST_SSE2 "Enable/Disable SSE2 in tests/examples" OFF)
|
||||
if(EIGEN_TEST_SSE2)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
|
||||
message("Enabling SSE2 in tests/examples")
|
||||
endif(EIGEN_TEST_SSE2)
|
||||
endif(MSVC)
|
||||
|
||||
option(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION "Disable explicit vectorization in tests/examples" OFF)
|
||||
if(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
|
||||
add_definitions(-DEIGEN_DONT_VECTORIZE=1)
|
||||
message("Disabling vectorization in tests/examples")
|
||||
endif(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_subdirectory(Eigen)
|
||||
add_subdirectory(unsupported)
|
||||
|
||||
if(EIGEN_BUILD_TESTS)
|
||||
include(CTest)
|
||||
add_subdirectory(test)
|
||||
endif(EIGEN_BUILD_TESTS)
|
||||
|
||||
add_subdirectory(doc)
|
||||
|
||||
if(EIGEN_BUILD_DEMOS)
|
||||
add_subdirectory(demos)
|
||||
endif(EIGEN_BUILD_DEMOS)
|
||||
|
||||
if(EIGEN_BUILD_BTL)
|
||||
add_subdirectory(bench/btl)
|
||||
endif(EIGEN_BUILD_BTL)
|
||||
|
||||
13
CTestConfig.cmake
Normal file
13
CTestConfig.cmake
Normal file
@@ -0,0 +1,13 @@
|
||||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
## # The following are required to uses Dart and the Cdash dashboard
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(Dart)
|
||||
set(CTEST_PROJECT_NAME "Eigen")
|
||||
set(CTEST_NIGHTLY_START_TIME "05:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "www.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/CDashPublic/submit.php?project=Eigen")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
2
Doxyfile
2
Doxyfile
@@ -5,7 +5,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = Eigen
|
||||
PROJECT_NUMBER = 2.0-alpha7
|
||||
PROJECT_NUMBER = 2.0
|
||||
OUTPUT_DIRECTORY = ./
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Array Array module
|
||||
/** \defgroup Array_Module Array module
|
||||
* This module provides several handy features to manipulate matrices as simple array of values.
|
||||
* In addition to listed classes, it defines various methods of the Cwise interface
|
||||
* (accessible from MatrixBase::cwise()), including:
|
||||
@@ -24,11 +26,14 @@ namespace Eigen {
|
||||
|
||||
#include "src/Array/CwiseOperators.h"
|
||||
#include "src/Array/Functors.h"
|
||||
#include "src/Array/AllAndAny.h"
|
||||
#include "src/Array/BooleanRedux.h"
|
||||
#include "src/Array/Select.h"
|
||||
#include "src/Array/PartialRedux.h"
|
||||
#include "src/Array/Random.h"
|
||||
#include "src/Array/Norms.h"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_ARRAY_MODULE_H
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
SET(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression)
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD LeastSquares QtAlignedMalloc StdVector)
|
||||
|
||||
IF(BUILD_LIB)
|
||||
SET(Eigen_SRCS
|
||||
if(EIGEN_BUILD_LIB)
|
||||
set(Eigen_SRCS
|
||||
src/Core/CoreInstantiations.cpp
|
||||
src/Cholesky/CholeskyInstantiations.cpp
|
||||
src/QR/QrInstantiations.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(Eigen2 SHARED ${Eigen_SRCS})
|
||||
add_library(Eigen2 SHARED ${Eigen_SRCS})
|
||||
|
||||
INSTALL(TARGETS Eigen2
|
||||
install(TARGETS Eigen2
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
ENDIF(BUILD_LIB)
|
||||
endif(EIGEN_BUILD_LIB)
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g1 -O2")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1 -O2")
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g1 -O2")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1 -O2")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
SET(INCLUDE_INSTALL_DIR
|
||||
set(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
|
||||
CACHE PATH
|
||||
"The directory where we install the header files"
|
||||
FORCE)
|
||||
|
||||
INSTALL(FILES
|
||||
install(FILES
|
||||
${Eigen_HEADERS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY(src)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
|
||||
#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS>=2)
|
||||
#ifndef EIGEN_HIDE_HEAVY_CODE
|
||||
@@ -15,10 +17,13 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Cholesky_Module Cholesky module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
|
||||
* Those decompositions are accessible via the following MatrixBase methods:
|
||||
* - MatrixBase::cholesky(),
|
||||
* - MatrixBase::choleskyNoSqrt()
|
||||
* - MatrixBase::llt(),
|
||||
* - MatrixBase::ldlt()
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/Cholesky>
|
||||
@@ -27,8 +32,8 @@ namespace Eigen {
|
||||
|
||||
#include "src/Array/CwiseOperators.h"
|
||||
#include "src/Array/Functors.h"
|
||||
#include "src/Cholesky/Cholesky.h"
|
||||
#include "src/Cholesky/CholeskyWithoutSquareRoot.h"
|
||||
#include "src/Cholesky/LLT.h"
|
||||
#include "src/Cholesky/LDLT.h"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
@@ -55,4 +60,6 @@ namespace Eigen {
|
||||
} // namespace Eigen
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_CHOLESKY_MODULE_H
|
||||
|
||||
53
Eigen/Core
53
Eigen/Core
@@ -1,18 +1,33 @@
|
||||
#ifndef EIGEN_CORE_H
|
||||
#define EIGEN_CORE_H
|
||||
|
||||
// first thing Eigen does: prevent MSVC from committing suicide
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4181 4244 )
|
||||
#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
|
||||
#if (_MSC_VER >= 1500) // 2008 or later
|
||||
// Remember that usage of defined() in a #define is undefined by the standard.
|
||||
// a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
|
||||
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(_M_X64)
|
||||
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
||||
#else
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
||||
#endif
|
||||
|
||||
// Remember that usage of defined() in a #define is undefined by the standard
|
||||
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
|
||||
#define EIGEN_SSE2_BUT_NOT_OLD_GCC
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
|
||||
#if defined (EIGEN_SSE2_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_SSE
|
||||
#include <emmintrin.h>
|
||||
@@ -23,11 +38,11 @@
|
||||
#ifdef __SSSE3__
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
#elif (defined __ALTIVEC__)
|
||||
#elif defined __ALTIVEC__
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_ALTIVEC
|
||||
#include <altivec.h>
|
||||
// We _need_ to #undef all these ugly tokens defined in <altivec.h>
|
||||
// We need to #undef all these ugly tokens defined in <altivec.h>
|
||||
// => use __vector instead of vector
|
||||
#undef bool
|
||||
#undef vector
|
||||
@@ -43,6 +58,22 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(EIGEN_NO_EXCEPTIONS)
|
||||
#define EIGEN_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
// this needs to be done after all possible windows C header includes and before any Eigen source includes
|
||||
// (system C++ includes are supposed to be able to deal with this already):
|
||||
// windows.h defines min and max macros which would make Eigen fail to compile.
|
||||
#if defined(min) || defined(max)
|
||||
#error The preprocessor symbols 'min' or 'max' are defined. If you are compiling on Windows, do #define NOMINMAX to prevent windows.h from defining these symbols.
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
@@ -69,9 +100,9 @@ namespace Eigen {
|
||||
#include "src/Core/GenericPacketMath.h"
|
||||
|
||||
#if defined EIGEN_VECTORIZE_SSE
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#elif defined EIGEN_VECTORIZE_ALTIVEC
|
||||
#include "src/Core/arch/AltiVec/PacketMath.h"
|
||||
#include "src/Core/arch/AltiVec/PacketMath.h"
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
|
||||
@@ -81,10 +112,12 @@ namespace Eigen {
|
||||
#include "src/Core/Functors.h"
|
||||
#include "src/Core/MatrixBase.h"
|
||||
#include "src/Core/Coeffs.h"
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
|
||||
// at least confirmed with Doxygen 1.5.5 and 1.5.6
|
||||
#include "src/Core/Assign.h"
|
||||
#include "src/Core/Assign.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/MatrixStorage.h"
|
||||
#include "src/Core/NestByValue.h"
|
||||
#include "src/Core/Flagged.h"
|
||||
@@ -116,4 +149,6 @@ namespace Eigen {
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_CORE_H
|
||||
|
||||
8
Eigen/Dense
Normal file
8
Eigen/Dense
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "Core"
|
||||
#include "Array"
|
||||
#include "LU"
|
||||
#include "Cholesky"
|
||||
#include "QR"
|
||||
#include "SVD"
|
||||
#include "Geometry"
|
||||
#include "LeastSquares"
|
||||
2
Eigen/Eigen
Normal file
2
Eigen/Eigen
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "Dense"
|
||||
#include "Sparse"
|
||||
@@ -1,7 +1,12 @@
|
||||
#ifndef EIGEN_GEOMETRY_MODULE_H
|
||||
#define EIGEN_GEOMETRY_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
#include "Array"
|
||||
#include <limits>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
@@ -9,7 +14,10 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup GeometryModule Geometry module
|
||||
/** \defgroup Geometry_Module Geometry module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides support for:
|
||||
* - fixed-size homogeneous transformations
|
||||
* - translation, scaling, 2D and 3D rotations
|
||||
@@ -28,12 +36,16 @@ namespace Eigen {
|
||||
#include "src/Geometry/Rotation2D.h"
|
||||
#include "src/Geometry/Quaternion.h"
|
||||
#include "src/Geometry/AngleAxis.h"
|
||||
#include "src/Geometry/EulerAngles.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"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_GEOMETRY_MODULE_H
|
||||
|
||||
4
Eigen/LU
4
Eigen/LU
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup LU_Module LU module
|
||||
@@ -22,4 +24,6 @@ namespace Eigen {
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_LU_MODULE_H
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
#ifndef EIGEN_REGRESSION_MODULE_H
|
||||
#define EIGEN_REGRESSION_MODULE_H
|
||||
|
||||
#include "LU"
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
#include "QR"
|
||||
#include "Geometry"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Regression_Module Regression module
|
||||
/** \defgroup LeastSquares_Module LeastSquares module
|
||||
* This module provides linear regression and related features.
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/Regression>
|
||||
* #include <Eigen/LeastSquares>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Regression/Regression.h"
|
||||
#include "src/LeastSquares/LeastSquares.h"
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_REGRESSION_MODULE_H
|
||||
8
Eigen/QR
8
Eigen/QR
@@ -2,6 +2,9 @@
|
||||
#define EIGEN_QR_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
#include "Cholesky"
|
||||
|
||||
// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
|
||||
@@ -16,6 +19,9 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup QR_Module QR module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module mainly provides QR decomposition and an eigen value solver.
|
||||
* This module also provides some MatrixBase methods, including:
|
||||
* - MatrixBase::qr(),
|
||||
@@ -62,4 +68,6 @@ namespace Eigen {
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_QR_MODULE_H
|
||||
|
||||
29
Eigen/QtAlignedMalloc
Normal file
29
Eigen/QtAlignedMalloc
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
#ifndef EIGEN_QTMALLOC_MODULE_H
|
||||
#define EIGEN_QTMALLOC_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
|
||||
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
|
||||
|
||||
inline void *qMalloc(size_t size)
|
||||
{
|
||||
return Eigen::ei_aligned_malloc(size);
|
||||
}
|
||||
|
||||
inline void qFree(void *ptr)
|
||||
{
|
||||
Eigen::ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
inline void *qRealloc(void *ptr, size_t size)
|
||||
{
|
||||
void* newPtr = Eigen::ei_aligned_malloc(size);
|
||||
memcpy(newPtr, ptr, size);
|
||||
Eigen::ei_aligned_free(ptr);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_QTMALLOC_MODULE_H
|
||||
@@ -3,9 +3,14 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup SVD_Module SVD module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This module provides SVD decomposition for (currently) real matrices.
|
||||
* This decomposition is accessible via the following MatrixBase method:
|
||||
* - MatrixBase::svd()
|
||||
@@ -19,4 +24,6 @@ namespace Eigen {
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_SVD_MODULE_H
|
||||
|
||||
113
Eigen/Sparse
113
Eigen/Sparse
@@ -2,26 +2,131 @@
|
||||
#define EIGEN_SPARSE_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableMSVCWarnings.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef EIGEN_GOOGLEHASH_SUPPORT
|
||||
#include <google/dense_hash_map>
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_CHOLMOD_SUPPORT
|
||||
extern "C" {
|
||||
#include "cholmod.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_TAUCS_SUPPORT
|
||||
// taucs.h declares a lot of mess
|
||||
#define isnan
|
||||
#define finite
|
||||
#define isinf
|
||||
extern "C" {
|
||||
#include "taucs.h"
|
||||
}
|
||||
#undef isnan
|
||||
#undef finite
|
||||
#undef isinf
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#ifdef complex
|
||||
#undef complex
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_SUPERLU_SUPPORT
|
||||
typedef int int_t;
|
||||
#include "superlu/slu_Cnames.h"
|
||||
#include "superlu/supermatrix.h"
|
||||
#include "superlu/slu_util.h"
|
||||
|
||||
namespace SuperLU_S {
|
||||
#include "superlu/slu_sdefs.h"
|
||||
}
|
||||
namespace SuperLU_D {
|
||||
#include "superlu/slu_ddefs.h"
|
||||
}
|
||||
namespace SuperLU_C {
|
||||
#include "superlu/slu_cdefs.h"
|
||||
}
|
||||
namespace SuperLU_Z {
|
||||
#include "superlu/slu_zdefs.h"
|
||||
}
|
||||
namespace Eigen { struct SluMatrix; }
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_UMFPACK_SUPPORT
|
||||
#include "umfpack.h"
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \defgroup Sparse_Module Sparse module
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* See the \ref TutorialSparse "Sparse tutorial"
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/QR>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Sparse/SparseUtil.h"
|
||||
#include "src/Sparse/SparseMatrixBase.h"
|
||||
#include "src/Sparse/SparseArray.h"
|
||||
#include "src/Sparse/CompressedStorage.h"
|
||||
#include "src/Sparse/AmbiVector.h"
|
||||
#include "src/Sparse/RandomSetter.h"
|
||||
#include "src/Sparse/SparseBlock.h"
|
||||
#include "src/Sparse/SparseMatrix.h"
|
||||
#include "src/Sparse/HashMatrix.h"
|
||||
#include "src/Sparse/LinkedVectorMatrix.h"
|
||||
#include "src/Sparse/DynamicSparseMatrix.h"
|
||||
#include "src/Sparse/MappedSparseMatrix.h"
|
||||
#include "src/Sparse/SparseVector.h"
|
||||
#include "src/Sparse/CoreIterators.h"
|
||||
#include "src/Sparse/SparseSetter.h"
|
||||
#include "src/Sparse/SparseTranspose.h"
|
||||
#include "src/Sparse/SparseCwise.h"
|
||||
#include "src/Sparse/SparseCwiseUnaryOp.h"
|
||||
#include "src/Sparse/SparseCwiseBinaryOp.h"
|
||||
#include "src/Sparse/SparseDot.h"
|
||||
#include "src/Sparse/SparseAssign.h"
|
||||
#include "src/Sparse/SparseRedux.h"
|
||||
#include "src/Sparse/SparseFuzzy.h"
|
||||
#include "src/Sparse/SparseFlagged.h"
|
||||
#include "src/Sparse/SparseProduct.h"
|
||||
#include "src/Sparse/SparseDiagonalProduct.h"
|
||||
#include "src/Sparse/TriangularSolver.h"
|
||||
#include "src/Sparse/SparseLLT.h"
|
||||
#include "src/Sparse/SparseLDLT.h"
|
||||
#include "src/Sparse/SparseLU.h"
|
||||
|
||||
#ifdef EIGEN_CHOLMOD_SUPPORT
|
||||
# include "src/Sparse/CholmodSupport.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_TAUCS_SUPPORT
|
||||
# include "src/Sparse/TaucsSupport.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_SUPERLU_SUPPORT
|
||||
# include "src/Sparse/SuperLUSupport.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_UMFPACK_SUPPORT
|
||||
# include "src/Sparse/UmfPackSupport.h"
|
||||
#endif
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#include "src/Core/util/EnableMSVCWarnings.h"
|
||||
|
||||
#endif // EIGEN_SPARSE_MODULE_H
|
||||
|
||||
133
Eigen/StdVector
Normal file
133
Eigen/StdVector
Normal file
@@ -0,0 +1,133 @@
|
||||
#ifndef EIGEN_STDVECTOR_MODULE_H
|
||||
#define EIGEN_STDVECTOR_MODULE_H
|
||||
|
||||
#if defined(_GLIBCXX_VECTOR) || defined(_VECTOR_)
|
||||
#error you must include Eigen/StdVector before std::vector
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_GNUC_AT_LEAST
|
||||
#ifdef __GNUC__
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
||||
#else
|
||||
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define vector std_vector
|
||||
#include <vector>
|
||||
#undef vector
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T> class aligned_allocator;
|
||||
|
||||
// meta programming to determine if a class has a given member
|
||||
struct ei_does_not_have_aligned_operator_new_marker_sizeof {int a[1];};
|
||||
struct ei_has_aligned_operator_new_marker_sizeof {int a[2];};
|
||||
|
||||
template<typename ClassType>
|
||||
struct ei_has_aligned_operator_new {
|
||||
template<typename T>
|
||||
static ei_has_aligned_operator_new_marker_sizeof
|
||||
test(T const *, typename T::ei_operator_new_marker_type const * = 0);
|
||||
static ei_does_not_have_aligned_operator_new_marker_sizeof
|
||||
test(...);
|
||||
|
||||
// note that the following indirection is needed for gcc-3.3
|
||||
enum {ret = sizeof(test(static_cast<ClassType*>(0)))
|
||||
== sizeof(ei_has_aligned_operator_new_marker_sizeof) };
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// sometimes, MSVC detects, at compile time, that the argument x
|
||||
// in std::vector::resize(size_t s,T x) won't be aligned and generate an error
|
||||
// even if this function is never called. Whence this little wrapper.
|
||||
#define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector<T>
|
||||
template<typename T> struct ei_workaround_msvc_std_vector : public T
|
||||
{
|
||||
inline ei_workaround_msvc_std_vector() : T() {}
|
||||
inline ei_workaround_msvc_std_vector(const T& other) : T(other) {}
|
||||
inline operator T& () { return *static_cast<T*>(this); }
|
||||
inline operator const T& () const { return *static_cast<const T*>(this); }
|
||||
template<typename OtherT>
|
||||
inline T& operator=(const OtherT& other)
|
||||
{ T::operator=(other); return *this; }
|
||||
inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other)
|
||||
{ T::operator=(other); return *this; }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
|
||||
public: \
|
||||
typedef T value_type; \
|
||||
typedef typename vector_base::allocator_type allocator_type; \
|
||||
typedef typename vector_base::size_type size_type; \
|
||||
typedef typename vector_base::iterator iterator; \
|
||||
explicit vector(const allocator_type& __a = allocator_type()) : vector_base(__a) {} \
|
||||
vector(const vector& c) : vector_base(c) {} \
|
||||
vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
|
||||
vector(iterator start, iterator end) : vector_base(start, end) {} \
|
||||
vector& operator=(const vector& __x) { \
|
||||
vector_base::operator=(__x); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename AllocT = std::allocator<T>,
|
||||
bool HasAlignedNew = Eigen::ei_has_aligned_operator_new<T>::ret>
|
||||
class vector : public std::std_vector<T,AllocT>
|
||||
{
|
||||
typedef std_vector<T, AllocT> vector_base;
|
||||
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
|
||||
};
|
||||
|
||||
template<typename T,typename DummyAlloc>
|
||||
class vector<T,DummyAlloc,true>
|
||||
: public std::std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
|
||||
Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
|
||||
{
|
||||
typedef std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
|
||||
Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base;
|
||||
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
|
||||
|
||||
void resize(size_type __new_size)
|
||||
{ resize(__new_size, T()); }
|
||||
|
||||
#if defined(_VECTOR_)
|
||||
// workaround MSVC std::vector implementation
|
||||
void resize(size_type __new_size, const value_type& __x)
|
||||
{
|
||||
if (vector_base::size() < __new_size)
|
||||
vector_base::_Insert_n(vector_base::end(), __new_size - vector_base::size(), __x);
|
||||
else if (__new_size < vector_base::size())
|
||||
vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
|
||||
}
|
||||
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1)
|
||||
// workaround GCC std::vector implementation
|
||||
// Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
|
||||
// no no need to workaround !
|
||||
void resize(size_type __new_size, const value_type& __x)
|
||||
{
|
||||
if (__new_size < vector_base::size())
|
||||
vector_base::_M_erase_at_end(this->_M_impl._M_start + __new_size);
|
||||
else
|
||||
vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
|
||||
}
|
||||
#else
|
||||
using vector_base::resize;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EIGEN_STDVECTOR_MODULE_H
|
||||
@@ -89,7 +89,7 @@ struct ei_any_unroller<Derived, Dynamic>
|
||||
* \sa MatrixBase::any(), Cwise::operator<()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool MatrixBase<Derived>::all(void) const
|
||||
inline bool MatrixBase<Derived>::all() const
|
||||
{
|
||||
const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
|
||||
<= EIGEN_UNROLLING_LIMIT;
|
||||
@@ -99,8 +99,8 @@ inline bool MatrixBase<Derived>::all(void) const
|
||||
>::run(derived());
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i < rows(); i++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i < rows(); ++i)
|
||||
if (!coeff(i, j)) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ inline bool MatrixBase<Derived>::all(void) const
|
||||
* \sa MatrixBase::all()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool MatrixBase<Derived>::any(void) const
|
||||
inline bool MatrixBase<Derived>::any() const
|
||||
{
|
||||
const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
|
||||
<= EIGEN_UNROLLING_LIMIT;
|
||||
@@ -123,11 +123,23 @@ inline bool MatrixBase<Derived>::any(void) const
|
||||
>::run(derived());
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i < rows(); i++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i < rows(); ++i)
|
||||
if (coeff(i, j)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** \array_module
|
||||
*
|
||||
* \returns the number of coefficients which evaluate to true
|
||||
*
|
||||
* \sa MatrixBase::all(), MatrixBase::any()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline int MatrixBase<Derived>::count() const
|
||||
{
|
||||
return this->cast<bool>().cast<int>().sum();
|
||||
}
|
||||
|
||||
#endif // EIGEN_ALLANDANY_H
|
||||
@@ -200,7 +200,6 @@ template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_cube_op<Scalar> >
|
||||
{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
|
||||
|
||||
|
||||
// default ei_functor_traits for STL functors:
|
||||
|
||||
template<typename T>
|
||||
|
||||
80
Eigen/src/Array/Norms.h
Normal file
80
Eigen/src/Array/Norms.h
Normal file
@@ -0,0 +1,80 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_ARRAY_NORMS_H
|
||||
#define EIGEN_ARRAY_NORMS_H
|
||||
|
||||
template<typename Derived, int p>
|
||||
struct ei_lpNorm_selector
|
||||
{
|
||||
typedef typename NumTraits<typename ei_traits<Derived>::Scalar>::Real RealScalar;
|
||||
inline static RealScalar run(const MatrixBase<Derived>& m)
|
||||
{
|
||||
return ei_pow(m.cwise().abs().cwise().pow(p).sum(), RealScalar(1)/p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_lpNorm_selector<Derived, 1>
|
||||
{
|
||||
inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
|
||||
{
|
||||
return m.cwise().abs().sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_lpNorm_selector<Derived, 2>
|
||||
{
|
||||
inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
|
||||
{
|
||||
return m.norm();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct ei_lpNorm_selector<Derived, Infinity>
|
||||
{
|
||||
inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
|
||||
{
|
||||
return m.cwise().abs().maxCoeff();
|
||||
}
|
||||
};
|
||||
|
||||
/** \array_module
|
||||
*
|
||||
* \returns the \f$ \ell^p \f$ norm of *this, that is, returns the p-th root of the sum of the p-th powers of the absolute values
|
||||
* of the coefficients of *this. If \a p is the special value \a Eigen::Infinity, this function returns the \f$ \ell^p\infty \f$
|
||||
* norm, that is the maximum of the absolute values of the coefficients of *this.
|
||||
*
|
||||
* \sa norm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int p>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::lpNorm() const
|
||||
{
|
||||
return ei_lpNorm_selector<Derived, p>::run(*this);
|
||||
}
|
||||
|
||||
#endif // EIGEN_ARRAY_NORMS_H
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -61,7 +61,11 @@ struct ei_traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
|
||||
Flags = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
|
||||
TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
|
||||
};
|
||||
#if EIGEN_GNUC_AT_LEAST(3,4)
|
||||
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
|
||||
#else
|
||||
typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
|
||||
#endif
|
||||
enum {
|
||||
CoeffReadCost = TraversalSize * ei_traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
|
||||
};
|
||||
@@ -104,16 +108,17 @@ class PartialReduxExpr : ei_no_assignment_operator,
|
||||
{ enum { value = COST }; }; \
|
||||
template<typename Derived> \
|
||||
inline ResultType operator()(const MatrixBase<Derived>& mat) const \
|
||||
{ return mat.MEMBER(); } \
|
||||
{ return mat.MEMBER(); } \
|
||||
}
|
||||
|
||||
EIGEN_MEMBER_FUNCTOR(norm2, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost);
|
||||
|
||||
/** \internal */
|
||||
template <typename BinaryOp, typename Scalar>
|
||||
@@ -172,6 +177,8 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
> Type;
|
||||
};
|
||||
|
||||
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
|
||||
|
||||
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
@@ -204,11 +211,11 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
/** \returns a row (or column) vector expression of the squared norm
|
||||
* of each column (or row) of the referenced expression.
|
||||
*
|
||||
* Example: \include PartialRedux_norm2.cpp
|
||||
* Output: \verbinclude PartialRedux_norm2.out
|
||||
* Example: \include PartialRedux_squaredNorm.cpp
|
||||
* Output: \verbinclude PartialRedux_squaredNorm.out
|
||||
*
|
||||
* \sa MatrixBase::norm2() */
|
||||
const typename ReturnType<ei_member_norm2>::Type norm2() const
|
||||
* \sa MatrixBase::squaredNorm() */
|
||||
const typename ReturnType<ei_member_squaredNorm>::Type squaredNorm() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a row (or column) vector expression of the norm
|
||||
@@ -244,6 +251,42 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
* \sa MatrixBase::any() */
|
||||
const typename ReturnType<ei_member_any>::Type any() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a row (or column) vector expression representing
|
||||
* the number of \c true coefficients of each respective column (or row).
|
||||
*
|
||||
* Example: \include PartialRedux_count.cpp
|
||||
* Output: \verbinclude PartialRedux_count.out
|
||||
*
|
||||
* \sa MatrixBase::count() */
|
||||
const PartialReduxExpr<ExpressionType, ei_member_count<int>, Direction> count() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a 3x3 matrix expression of the cross product
|
||||
* of each column or row of the referenced expression with the \a other vector.
|
||||
*
|
||||
* \geometry_module
|
||||
*
|
||||
* \sa MatrixBase::cross() */
|
||||
template<typename OtherDerived>
|
||||
const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(CrossReturnType,3,3)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
if(Direction==Vertical)
|
||||
return (CrossReturnType()
|
||||
<< _expression().col(0).cross(other),
|
||||
_expression().col(1).cross(other),
|
||||
_expression().col(2).cross(other)).finished();
|
||||
else
|
||||
return (CrossReturnType()
|
||||
<< _expression().row(0).cross(other),
|
||||
_expression().row(1).cross(other),
|
||||
_expression().row(2).cross(other)).finished();
|
||||
}
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
|
||||
@@ -110,7 +110,7 @@ MatrixBase<Derived>::Random()
|
||||
* Example: \include MatrixBase_setRandom.cpp
|
||||
* Output: \verbinclude MatrixBase_setRandom.out
|
||||
*
|
||||
* \sa class CwiseNullaryOp, MatrixBase::setRandom(int,int)
|
||||
* \sa class CwiseNullaryOp, setRandom(int), setRandom(int,int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Derived& MatrixBase<Derived>::setRandom()
|
||||
@@ -118,4 +118,39 @@ inline Derived& MatrixBase<Derived>::setRandom()
|
||||
return *this = Random(rows(), cols());
|
||||
}
|
||||
|
||||
/** Resizes to the given \a size, and sets all coefficients in this expression to random values.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* Example: \include Matrix_setRandom_int.cpp
|
||||
* Output: \verbinclude Matrix_setRandom_int.out
|
||||
*
|
||||
* \sa MatrixBase::setRandom(), setRandom(int,int), class CwiseNullaryOp, MatrixBase::Random()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setRandom(int size)
|
||||
{
|
||||
resize(size);
|
||||
return setRandom();
|
||||
}
|
||||
|
||||
/** Resizes to the given size, and sets all coefficients in this expression to random values.
|
||||
*
|
||||
* \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 MatrixBase::setRandom(), setRandom(int), class CwiseNullaryOp, MatrixBase::Random()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setRandom(int rows, int cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
return setRandom();
|
||||
}
|
||||
|
||||
#endif // EIGEN_RANDOM_H
|
||||
|
||||
@@ -45,15 +45,18 @@ template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMat
|
||||
struct ei_traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
|
||||
{
|
||||
typedef typename ei_traits<ThenMatrixType>::Scalar Scalar;
|
||||
typedef typename ConditionMatrixType::Nested ConditionMatrixNested;
|
||||
typedef typename ThenMatrixType::Nested ThenMatrixNested;
|
||||
typedef typename ElseMatrixType::Nested ElseMatrixNested;
|
||||
enum {
|
||||
RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
|
||||
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits,
|
||||
CoeffReadCost = ei_traits<ConditionMatrixType>::CoeffReadCost
|
||||
+ EIGEN_ENUM_MAX(ei_traits<ThenMatrixType>::CoeffReadCost,
|
||||
ei_traits<ElseMatrixType>::CoeffReadCost)
|
||||
CoeffReadCost = ei_traits<typename ei_cleantype<ConditionMatrixNested>::type>::CoeffReadCost
|
||||
+ EIGEN_ENUM_MAX(ei_traits<typename ei_cleantype<ThenMatrixNested>::type>::CoeffReadCost,
|
||||
ei_traits<typename ei_cleantype<ElseMatrixNested>::type>::CoeffReadCost)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -105,6 +108,9 @@ class Select : ei_no_assignment_operator,
|
||||
* \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
|
||||
* if \c *this(i,j), and \a elseMatrix(i,j) otherwise.
|
||||
*
|
||||
* Example: \include MatrixBase_select.cpp
|
||||
* Output: \verbinclude MatrixBase_select.out
|
||||
*
|
||||
* \sa class Select
|
||||
*/
|
||||
template<typename Derived>
|
||||
|
||||
@@ -5,5 +5,5 @@ ADD_SUBDIRECTORY(SVD)
|
||||
ADD_SUBDIRECTORY(Cholesky)
|
||||
ADD_SUBDIRECTORY(Array)
|
||||
ADD_SUBDIRECTORY(Geometry)
|
||||
ADD_SUBDIRECTORY(Regression)
|
||||
ADD_SUBDIRECTORY(LeastSquares)
|
||||
ADD_SUBDIRECTORY(Sparse)
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_CHOLESKY_H
|
||||
#define EIGEN_CHOLESKY_H
|
||||
|
||||
/** \ingroup Cholesky_Module
|
||||
*
|
||||
* \class Cholesky
|
||||
*
|
||||
* \brief Standard Cholesky decomposition of a matrix and associated features
|
||||
*
|
||||
* \param MatrixType the type of the matrix of which we are computing the Cholesky decomposition
|
||||
*
|
||||
* This class performs a standard 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.
|
||||
*
|
||||
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
|
||||
* the strict lower part does not have to store correct values.
|
||||
*
|
||||
* \sa MatrixBase::cholesky(), class CholeskyWithoutSquareRoot
|
||||
*/
|
||||
template<typename MatrixType> class Cholesky
|
||||
{
|
||||
private:
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
enum {
|
||||
PacketSize = ei_packet_traits<Scalar>::size,
|
||||
AlignmentMask = int(PacketSize)-1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Cholesky(const MatrixType& matrix)
|
||||
: m_matrix(matrix.rows(), matrix.cols())
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
inline Part<MatrixType, Lower> matrixL(void) const { return m_matrix; }
|
||||
|
||||
/** \returns true if the matrix is positive definite */
|
||||
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
|
||||
|
||||
template<typename Derived>
|
||||
typename Derived::Eval solve(const MatrixBase<Derived> &b) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store L
|
||||
* The strict upper part is not used and even not initialized.
|
||||
*/
|
||||
MatrixType m_matrix;
|
||||
bool m_isPositiveDefinite;
|
||||
};
|
||||
|
||||
/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
void Cholesky<MatrixType>::compute(const MatrixType& a)
|
||||
{
|
||||
assert(a.rows()==a.cols());
|
||||
const int size = a.rows();
|
||||
m_matrix.resize(size, size);
|
||||
const RealScalar eps = ei_sqrt(precision<Scalar>());
|
||||
|
||||
RealScalar x;
|
||||
x = ei_real(a.coeff(0,0));
|
||||
m_isPositiveDefinite = x > eps && ei_isMuchSmallerThan(ei_imag(a.coeff(0,0)), RealScalar(1));
|
||||
m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
||||
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
||||
for (int j = 1; j < size; ++j)
|
||||
{
|
||||
Scalar tmp = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).norm2();
|
||||
x = ei_real(tmp);
|
||||
if (x < eps || (!ei_isMuchSmallerThan(ei_imag(tmp), RealScalar(1))))
|
||||
{
|
||||
m_isPositiveDefinite = false;
|
||||
return;
|
||||
}
|
||||
m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
|
||||
|
||||
int endSize = size-j-1;
|
||||
if (endSize>0) {
|
||||
// Note that when all matrix columns have good alignment, then the following
|
||||
// product is guaranteed to be optimal with respect to alignment.
|
||||
m_matrix.col(j).end(endSize) =
|
||||
(m_matrix.block(j+1, 0, endSize, j) * m_matrix.row(j).start(j).adjoint()).lazy();
|
||||
|
||||
// FIXME could use a.col instead of a.row
|
||||
m_matrix.col(j).end(endSize) = (a.row(j).end(endSize).adjoint()
|
||||
- m_matrix.col(j).end(endSize) ) / x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns the solution of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* In other words, it returns \f$ A^{-1} b \f$ computing
|
||||
* \f$ {L^{*}}^{-1} L^{-1} b \f$ from right to left.
|
||||
* \param b the column vector \f$ b \f$, which can also be a matrix.
|
||||
*
|
||||
* Example: \include Cholesky_solve.cpp
|
||||
* Output: \verbinclude Cholesky_solve.out
|
||||
*
|
||||
* \sa MatrixBase::cholesky(), CholeskyWithoutSquareRoot::solve()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
typename Derived::Eval Cholesky<MatrixType>::solve(const MatrixBase<Derived> &b) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows());
|
||||
|
||||
return m_matrix.adjoint().template part<Upper>().solveTriangular(matrixL().solveTriangular(b));
|
||||
}
|
||||
|
||||
/** \cholesky_module
|
||||
* \returns the Cholesky decomposition of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Cholesky<typename MatrixBase<Derived>::EvalType>
|
||||
MatrixBase<Derived>::cholesky() const
|
||||
{
|
||||
return Cholesky<typename ei_eval<Derived>::type>(derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_CHOLESKY_H
|
||||
@@ -22,16 +22,16 @@
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
#define EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
#ifndef EIGEN_LDLT_H
|
||||
#define EIGEN_LDLT_H
|
||||
|
||||
/** \ingroup Cholesky_Module
|
||||
/** \ingroup cholesky_Module
|
||||
*
|
||||
* \class CholeskyWithoutSquareRoot
|
||||
* \class LDLT
|
||||
*
|
||||
* \brief Robust Cholesky decomposition of a matrix and associated features
|
||||
*
|
||||
* \param MatrixType the type of the matrix of which we are computing the Cholesky decomposition
|
||||
* \param MatrixType the type of the matrix of which we are computing the LDL^T Cholesky decomposition
|
||||
*
|
||||
* This class performs a Cholesky decomposition without square root of a symmetric, positive definite
|
||||
* matrix A such that A = L D L^* = U^* D U, where L is lower triangular with a unit diagonal
|
||||
@@ -43,9 +43,9 @@
|
||||
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
|
||||
* the strict lower part does not have to store correct values.
|
||||
*
|
||||
* \sa MatrixBase::choleskyNoSqrt(), class Cholesky
|
||||
* \sa MatrixBase::ldlt(), class LLT
|
||||
*/
|
||||
template<typename MatrixType> class CholeskyWithoutSquareRoot
|
||||
template<typename MatrixType> class LDLT
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -53,14 +53,14 @@ template<typename MatrixType> class CholeskyWithoutSquareRoot
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
CholeskyWithoutSquareRoot(const MatrixType& matrix)
|
||||
LDLT(const MatrixType& matrix)
|
||||
: m_matrix(matrix.rows(), matrix.cols())
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
/** \returns the lower triangular matrix L */
|
||||
inline Part<MatrixType, UnitLower> matrixL(void) const { return m_matrix; }
|
||||
inline Part<MatrixType, UnitLowerTriangular> matrixL(void) const { return m_matrix; }
|
||||
|
||||
/** \returns the coefficients of the diagonal matrix D */
|
||||
inline DiagonalCoeffs<MatrixType> vectorD(void) const { return m_matrix.diagonal(); }
|
||||
@@ -68,8 +68,11 @@ template<typename MatrixType> class CholeskyWithoutSquareRoot
|
||||
/** \returns true if the matrix is positive definite */
|
||||
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
|
||||
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
|
||||
|
||||
template<typename Derived>
|
||||
typename Derived::Eval solve(const MatrixBase<Derived> &b) const;
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
@@ -85,10 +88,10 @@ template<typename MatrixType> class CholeskyWithoutSquareRoot
|
||||
bool m_isPositiveDefinite;
|
||||
};
|
||||
|
||||
/** Compute / recompute the Cholesky decomposition A = L D L^* = U^* D U of \a matrix
|
||||
/** Compute / recompute the LLT decomposition A = L D L^* = U^* D U of \a matrix
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
void CholeskyWithoutSquareRoot<MatrixType>::compute(const MatrixType& a)
|
||||
void LDLT<MatrixType>::compute(const MatrixType& a)
|
||||
{
|
||||
assert(a.rows()==a.cols());
|
||||
const int size = a.rows();
|
||||
@@ -101,9 +104,9 @@ void CholeskyWithoutSquareRoot<MatrixType>::compute(const MatrixType& a)
|
||||
m_matrix = a;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Let's preallocate a temporay vector to evaluate the matrix-vector product into it.
|
||||
// Unlike the standard Cholesky decomposition, here we cannot evaluate it to the destination
|
||||
// Unlike the standard LLT decomposition, here we cannot evaluate it to the destination
|
||||
// matrix because it a sub-row which is not compatible suitable for efficient packet evaluation.
|
||||
// (at least if we assume the matrix is col-major)
|
||||
Matrix<Scalar,MatrixType::RowsAtCompileTime,1> _temporary(size);
|
||||
@@ -138,37 +141,58 @@ void CholeskyWithoutSquareRoot<MatrixType>::compute(const MatrixType& a)
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns the solution of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* In other words, it returns \f$ A^{-1} b \f$ computing
|
||||
* \f$ {L^{*}}^{-1} D^{-1} L^{-1} b \f$ from right to left.
|
||||
* \param b the column vector \f$ b \f$, which can also be a matrix.
|
||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* The result is stored in \a result
|
||||
*
|
||||
* See Cholesky::solve() for a example.
|
||||
*
|
||||
* \sa MatrixBase::choleskyNoSqrt()
|
||||
* \returns true in case of success, false otherwise.
|
||||
*
|
||||
* In other words, it computes \f$ b = A^{-1} b \f$ with
|
||||
* \f$ {L^{*}}^{-1} D^{-1} L^{-1} b \f$ from right to left.
|
||||
*
|
||||
* \sa LDLT::solveInPlace(), MatrixBase::ldlt()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool LDLT<MatrixType>
|
||||
::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
*result = b;
|
||||
return solveInPlace(*result);
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*
|
||||
* \sa LDLT::solve(), MatrixBase::ldlt()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
typename Derived::Eval CholeskyWithoutSquareRoot<MatrixType>::solve(const MatrixBase<Derived> &b) const
|
||||
bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||
{
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows());
|
||||
|
||||
return m_matrix.adjoint().template part<UnitUpper>()
|
||||
.solveTriangular(
|
||||
( m_matrix.cwise().inverse().template part<Diagonal>()
|
||||
* matrixL().solveTriangular(b))
|
||||
);
|
||||
ei_assert(size==bAndX.rows());
|
||||
if (!m_isPositiveDefinite)
|
||||
return false;
|
||||
matrixL().solveTriangularInPlace(bAndX);
|
||||
bAndX = (m_matrix.cwise().inverse().template part<Diagonal>() * bAndX).lazy();
|
||||
m_matrix.adjoint().template part<UnitUpperTriangular>().solveTriangularInPlace(bAndX);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \cholesky_module
|
||||
* \returns the Cholesky decomposition without square root of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const CholeskyWithoutSquareRoot<typename MatrixBase<Derived>::EvalType>
|
||||
MatrixBase<Derived>::choleskyNoSqrt() const
|
||||
inline const LDLT<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::ldlt() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
#endif // EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
|
||||
#endif // EIGEN_LDLT_H
|
||||
219
Eigen/src/Cholesky/LLT.h
Normal file
219
Eigen/src/Cholesky/LLT.h
Normal file
@@ -0,0 +1,219 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_LLT_H
|
||||
#define EIGEN_LLT_H
|
||||
|
||||
/** \ingroup cholesky_Module
|
||||
*
|
||||
* \class LLT
|
||||
*
|
||||
* \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features
|
||||
*
|
||||
* \param MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \sa MatrixBase::llt(), class LDLT
|
||||
*/
|
||||
/* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH)
|
||||
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
|
||||
* the strict lower part does not have to store correct values.
|
||||
*/
|
||||
template<typename MatrixType> class LLT
|
||||
{
|
||||
private:
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
enum {
|
||||
PacketSize = ei_packet_traits<Scalar>::size,
|
||||
AlignmentMask = int(PacketSize)-1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \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_isInitialized(false) {}
|
||||
|
||||
LLT(const MatrixType& matrix)
|
||||
: m_matrix(matrix.rows(), matrix.cols()),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
/** \returns the lower triangular matrix L */
|
||||
inline Part<MatrixType, LowerTriangular> matrixL(void) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
inline bool isPositiveDefinite(void) const { return m_isInitialized && m_isPositiveDefinite; }
|
||||
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
/** \internal
|
||||
* Used to compute and store L
|
||||
* The strict upper part is not used and even not initialized.
|
||||
*/
|
||||
MatrixType m_matrix;
|
||||
bool m_isInitialized;
|
||||
bool m_isPositiveDefinite;
|
||||
};
|
||||
|
||||
/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
void LLT<MatrixType>::compute(const MatrixType& a)
|
||||
{
|
||||
assert(a.rows()==a.cols());
|
||||
m_isPositiveDefinite = true;
|
||||
const int size = a.rows();
|
||||
m_matrix.resize(size, size);
|
||||
// The biggest overall is the point of reference to which further diagonals
|
||||
// are compared; if any diagonal is negligible compared
|
||||
// to the largest overall, the algorithm bails. This cutoff is suggested
|
||||
// in "Analysis of the Cholesky Decomposition of a Semi-definite Matrix" by
|
||||
// Nicholas J. Higham. Also see "Accuracy and Stability of Numerical
|
||||
// Algorithms" page 217, also by Higham.
|
||||
const RealScalar cutoff = machine_epsilon<Scalar>() * size * a.diagonal().cwise().abs().maxCoeff();
|
||||
RealScalar x;
|
||||
x = ei_real(a.coeff(0,0));
|
||||
m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
||||
if(size==1)
|
||||
{
|
||||
m_isInitialized = true;
|
||||
return;
|
||||
}
|
||||
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
||||
for (int j = 1; j < size; ++j)
|
||||
{
|
||||
x = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).squaredNorm();
|
||||
if (x < cutoff)
|
||||
{
|
||||
m_isPositiveDefinite = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
|
||||
|
||||
int endSize = size-j-1;
|
||||
if (endSize>0) {
|
||||
// Note that when all matrix columns have good alignment, then the following
|
||||
// product is guaranteed to be optimal with respect to alignment.
|
||||
m_matrix.col(j).end(endSize) =
|
||||
(m_matrix.block(j+1, 0, endSize, j) * m_matrix.row(j).start(j).adjoint()).lazy();
|
||||
|
||||
// FIXME could use a.col instead of a.row
|
||||
m_matrix.col(j).end(endSize) = (a.row(j).end(endSize).adjoint()
|
||||
- m_matrix.col(j).end(endSize) ) / x;
|
||||
}
|
||||
}
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
* The result is stored in \a result
|
||||
*
|
||||
* \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
|
||||
*
|
||||
* In other words, it computes \f$ b = A^{-1} b \f$ with
|
||||
* \f$ {L^{*}}^{-1} L^{-1} b \f$ from right to left.
|
||||
*
|
||||
* Example: \include LLT_solve.cpp
|
||||
* Output: \verbinclude LLT_solve.out
|
||||
*
|
||||
* \sa LLT::solveInPlace(), MatrixBase::llt()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RhsDerived, typename ResultType>
|
||||
bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return solveInPlace((*result) = b);
|
||||
}
|
||||
|
||||
/** 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 LLT::solve(), MatrixBase::llt()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
bool LLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "LLT is not initialized.");
|
||||
const int size = m_matrix.rows();
|
||||
ei_assert(size==bAndX.rows());
|
||||
matrixL().solveTriangularInPlace(bAndX);
|
||||
m_matrix.adjoint().template part<UpperTriangular>().solveTriangularInPlace(bAndX);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \cholesky_module
|
||||
* \returns the LLT decomposition of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LLT<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::llt() const
|
||||
{
|
||||
return LLT<PlainMatrixType>(derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_LLT_H
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2007 Michael Olbrich <michael.olbrich@gmx.net>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -112,7 +112,7 @@ struct ei_assign_novec_CompleteUnrolling
|
||||
: Index / Derived1::RowsAtCompileTime
|
||||
};
|
||||
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
dst.copyCoeff(row, col, src);
|
||||
ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
|
||||
@@ -122,13 +122,13 @@ struct ei_assign_novec_CompleteUnrolling
|
||||
template<typename Derived1, typename Derived2, int Stop>
|
||||
struct ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
|
||||
{
|
||||
inline static void run(Derived1 &, const Derived2 &) {}
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2, int Index, int Stop>
|
||||
struct ei_assign_novec_InnerUnrolling
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
|
||||
{
|
||||
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
|
||||
const int row = rowMajor ? row_or_col : Index;
|
||||
@@ -141,7 +141,7 @@ struct ei_assign_novec_InnerUnrolling
|
||||
template<typename Derived1, typename Derived2, int Stop>
|
||||
struct ei_assign_novec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
||||
{
|
||||
inline static void run(Derived1 &, const Derived2 &, int) {}
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
|
||||
};
|
||||
|
||||
/**************************
|
||||
@@ -161,7 +161,7 @@ struct ei_assign_innervec_CompleteUnrolling
|
||||
SrcAlignment = ei_assign_traits<Derived1,Derived2>::SrcAlignment
|
||||
};
|
||||
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
dst.template copyPacket<Derived2, Aligned, SrcAlignment>(row, col, src);
|
||||
ei_assign_innervec_CompleteUnrolling<Derived1, Derived2,
|
||||
@@ -172,13 +172,13 @@ struct ei_assign_innervec_CompleteUnrolling
|
||||
template<typename Derived1, typename Derived2, int Stop>
|
||||
struct ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
|
||||
{
|
||||
inline static void run(Derived1 &, const Derived2 &) {}
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2, int Index, int Stop>
|
||||
struct ei_assign_innervec_InnerUnrolling
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
|
||||
{
|
||||
const int row = int(Derived1::Flags)&RowMajorBit ? row_or_col : Index;
|
||||
const int col = int(Derived1::Flags)&RowMajorBit ? Index : row_or_col;
|
||||
@@ -191,7 +191,7 @@ struct ei_assign_innervec_InnerUnrolling
|
||||
template<typename Derived1, typename Derived2, int Stop>
|
||||
struct ei_assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
||||
{
|
||||
inline static void run(Derived1 &, const Derived2 &, int) {}
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@@ -210,12 +210,12 @@ struct ei_assign_impl;
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const int innerSize = dst.innerSize();
|
||||
const int outerSize = dst.outerSize();
|
||||
for(int j = 0; j < outerSize; j++)
|
||||
for(int i = 0; i < innerSize; i++)
|
||||
for(int j = 0; j < outerSize; ++j)
|
||||
for(int i = 0; i < innerSize; ++i)
|
||||
{
|
||||
if(int(Derived1::Flags)&RowMajorBit)
|
||||
dst.copyCoeff(j, i, src);
|
||||
@@ -228,7 +228,7 @@ struct ei_assign_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
ei_assign_novec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
|
||||
::run(dst, src);
|
||||
@@ -238,12 +238,12 @@ struct ei_assign_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, NoVectorization, InnerUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
|
||||
const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
|
||||
const int outerSize = dst.outerSize();
|
||||
for(int j = 0; j < outerSize; j++)
|
||||
for(int j = 0; j < outerSize; ++j)
|
||||
ei_assign_novec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
|
||||
::run(dst, src, j);
|
||||
}
|
||||
@@ -256,12 +256,12 @@ struct ei_assign_impl<Derived1, Derived2, NoVectorization, InnerUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, InnerVectorization, NoUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const int innerSize = dst.innerSize();
|
||||
const int outerSize = dst.outerSize();
|
||||
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
|
||||
for(int j = 0; j < outerSize; j++)
|
||||
for(int j = 0; j < outerSize; ++j)
|
||||
for(int i = 0; i < innerSize; i+=packetSize)
|
||||
{
|
||||
if(int(Derived1::Flags)&RowMajorBit)
|
||||
@@ -275,7 +275,7 @@ struct ei_assign_impl<Derived1, Derived2, InnerVectorization, NoUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, InnerVectorization, CompleteUnrolling>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
|
||||
::run(dst, src);
|
||||
@@ -285,12 +285,12 @@ struct ei_assign_impl<Derived1, Derived2, InnerVectorization, CompleteUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, InnerVectorization, InnerUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
|
||||
const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
|
||||
const int outerSize = dst.outerSize();
|
||||
for(int j = 0; j < outerSize; j++)
|
||||
for(int j = 0; j < outerSize; ++j)
|
||||
ei_assign_innervec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
|
||||
::run(dst, src, j);
|
||||
}
|
||||
@@ -303,7 +303,7 @@ struct ei_assign_impl<Derived1, Derived2, InnerVectorization, InnerUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const int size = dst.size();
|
||||
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
|
||||
@@ -311,7 +311,7 @@ struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
: ei_alignmentOffset(&dst.coeffRef(0), size);
|
||||
const int alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
|
||||
|
||||
for(int index = 0; index < alignedStart; index++)
|
||||
for(int index = 0; index < alignedStart; ++index)
|
||||
dst.copyCoeff(index, src);
|
||||
|
||||
for(int index = alignedStart; index < alignedEnd; index += packetSize)
|
||||
@@ -319,7 +319,7 @@ struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
dst.template copyPacket<Derived2, Aligned, ei_assign_traits<Derived1,Derived2>::SrcAlignment>(index, src);
|
||||
}
|
||||
|
||||
for(int index = alignedEnd; index < size; index++)
|
||||
for(int index = alignedEnd; index < size; ++index)
|
||||
dst.copyCoeff(index, src);
|
||||
}
|
||||
};
|
||||
@@ -327,7 +327,7 @@ struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const int size = Derived1::SizeAtCompileTime;
|
||||
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
|
||||
@@ -345,7 +345,7 @@ struct ei_assign_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
|
||||
{
|
||||
static void run(Derived1 &dst, const Derived2 &src)
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
|
||||
const int packetAlignedMask = packetSize - 1;
|
||||
@@ -353,14 +353,14 @@ struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
|
||||
const int outerSize = dst.outerSize();
|
||||
const int alignedStep = (packetSize - dst.stride() % packetSize) & packetAlignedMask;
|
||||
int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
|
||||
: ei_alignmentOffset(&dst.coeffRef(0), innerSize);
|
||||
: ei_alignmentOffset(&dst.coeffRef(0,0), innerSize);
|
||||
|
||||
for(int i = 0; i < outerSize; i++)
|
||||
for(int i = 0; i < outerSize; ++i)
|
||||
{
|
||||
const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
|
||||
|
||||
// do the non-vectorizable part of the assignment
|
||||
for (int index = 0; index<alignedStart ; index++)
|
||||
for (int index = 0; index<alignedStart ; ++index)
|
||||
{
|
||||
if(Derived1::Flags&RowMajorBit)
|
||||
dst.copyCoeff(i, index, src);
|
||||
@@ -378,7 +378,7 @@ struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
|
||||
}
|
||||
|
||||
// do the non-vectorizable part of the assignment
|
||||
for (int index = alignedEnd; index<innerSize ; index++)
|
||||
for (int index = alignedEnd; index<innerSize ; ++index)
|
||||
{
|
||||
if(Derived1::Flags&RowMajorBit)
|
||||
dst.copyCoeff(i, index, src);
|
||||
@@ -397,17 +397,19 @@ struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline Derived& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||
::lazyAssign(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived);
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
ei_assert(rows() == other.rows() && cols() == other.cols());
|
||||
ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename Derived, typename OtherDerived,
|
||||
bool EvalBeforeAssigning = int(OtherDerived::Flags) & EvalBeforeAssigningBit,
|
||||
bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
|
||||
bool NeedToTranspose = Derived::IsVectorAtCompileTime
|
||||
&& OtherDerived::IsVectorAtCompileTime
|
||||
&& int(Derived::RowsAtCompileTime) == int(OtherDerived::ColsAtCompileTime)
|
||||
@@ -417,24 +419,24 @@ struct ei_assign_selector;
|
||||
|
||||
template<typename Derived, typename OtherDerived>
|
||||
struct ei_assign_selector<Derived,OtherDerived,false,false> {
|
||||
static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
|
||||
EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
|
||||
};
|
||||
template<typename Derived, typename OtherDerived>
|
||||
struct ei_assign_selector<Derived,OtherDerived,true,false> {
|
||||
static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
|
||||
EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
|
||||
};
|
||||
template<typename Derived, typename OtherDerived>
|
||||
struct ei_assign_selector<Derived,OtherDerived,false,true> {
|
||||
static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
|
||||
EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
|
||||
};
|
||||
template<typename Derived, typename OtherDerived>
|
||||
struct ei_assign_selector<Derived,OtherDerived,true,true> {
|
||||
static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
|
||||
EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline Derived& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||
::operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -61,27 +61,28 @@
|
||||
*
|
||||
* \sa MatrixBase::block(int,int,int,int), MatrixBase::block(int,int), class VectorBlock
|
||||
*/
|
||||
|
||||
template<typename MatrixType, int BlockRows, int BlockCols, int _PacketAccess, int _DirectAccessStatus>
|
||||
struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectAccessStatus> >
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::Nested MatrixTypeNested;
|
||||
typedef typename ei_traits<MatrixType>::Scalar Scalar;
|
||||
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
|
||||
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
enum{
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime == 1 ? 1 : BlockRows,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime == 1 ? 1 : BlockCols,
|
||||
RowsAtCompileTime = ei_traits<MatrixType>::RowsAtCompileTime == 1 ? 1 : BlockRows,
|
||||
ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime == 1 ? 1 : BlockCols,
|
||||
MaxRowsAtCompileTime = RowsAtCompileTime == 1 ? 1
|
||||
: (BlockRows==Dynamic ? MatrixType::MaxRowsAtCompileTime : BlockRows),
|
||||
: (BlockRows==Dynamic ? int(ei_traits<MatrixType>::MaxRowsAtCompileTime) : BlockRows),
|
||||
MaxColsAtCompileTime = ColsAtCompileTime == 1 ? 1
|
||||
: (BlockCols==Dynamic ? MatrixType::MaxColsAtCompileTime : BlockCols),
|
||||
RowMajor = int(MatrixType::Flags)&RowMajorBit,
|
||||
InnerSize = RowMajor ? ColsAtCompileTime : RowsAtCompileTime,
|
||||
InnerMaxSize = RowMajor ? MaxColsAtCompileTime : MaxRowsAtCompileTime,
|
||||
: (BlockCols==Dynamic ? int(ei_traits<MatrixType>::MaxColsAtCompileTime) : BlockCols),
|
||||
RowMajor = int(ei_traits<MatrixType>::Flags)&RowMajorBit,
|
||||
InnerSize = RowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
||||
InnerMaxSize = RowMajor ? int(MaxColsAtCompileTime) : int(MaxRowsAtCompileTime),
|
||||
MaskPacketAccessBit = (InnerMaxSize == Dynamic || (InnerSize >= ei_packet_traits<Scalar>::size))
|
||||
? PacketAccessBit : 0,
|
||||
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
|
||||
Flags = (MatrixType::Flags & (HereditaryBits | MaskPacketAccessBit | DirectAccessBit)) | FlagsLinearAccessBit,
|
||||
CoeffReadCost = MatrixType::CoeffReadCost,
|
||||
Flags = (ei_traits<MatrixType>::Flags & (HereditaryBits | MaskPacketAccessBit | DirectAccessBit)) | FlagsLinearAccessBit,
|
||||
CoeffReadCost = ei_traits<MatrixType>::CoeffReadCost,
|
||||
PacketAccess = _PacketAccess
|
||||
};
|
||||
typedef typename ei_meta_if<int(PacketAccess)==ForceAligned,
|
||||
@@ -122,7 +123,7 @@ template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, in
|
||||
: m_matrix(matrix), m_startRow(startRow), m_startCol(startCol),
|
||||
m_blockRows(matrix.rows()), m_blockCols(matrix.cols())
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && RowsAtCompileTime!=Dynamic,this_method_is_only_for_fixed_size);
|
||||
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
|
||||
ei_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= matrix.rows()
|
||||
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= matrix.cols());
|
||||
}
|
||||
@@ -146,8 +147,6 @@ template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, in
|
||||
inline int rows() const { return m_blockRows.value(); }
|
||||
inline int cols() const { return m_blockCols.value(); }
|
||||
|
||||
inline int stride(void) const { return m_matrix.stride(); }
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
return m_matrix.const_cast_derived()
|
||||
@@ -223,15 +222,13 @@ class Block<MatrixType,BlockRows,BlockCols,PacketAccess,HasDirectAccess>
|
||||
|
||||
class InnerIterator;
|
||||
typedef typename ei_traits<Block>::AlignedDerivedType AlignedDerivedType;
|
||||
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==AsRequested?ForceAligned:AsRequested,HasDirectAccess>;
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
|
||||
|
||||
AlignedDerivedType forceAligned()
|
||||
AlignedDerivedType _convertToForceAligned()
|
||||
{
|
||||
if (PacketAccess==ForceAligned)
|
||||
return *this;
|
||||
else
|
||||
return Block<MatrixType,BlockRows,BlockCols,ForceAligned,HasDirectAccess>
|
||||
return Block<MatrixType,BlockRows,BlockCols,ForceAligned,HasDirectAccess>
|
||||
(m_matrix, Base::m_data, Base::m_rows.value(), Base::m_cols.value());
|
||||
}
|
||||
|
||||
@@ -318,41 +315,41 @@ inline const typename BlockReturnType<Derived>::Type MatrixBase<Derived>
|
||||
return typename BlockReturnType<Derived>::Type(derived(), startRow, startCol, blockRows, blockCols);
|
||||
}
|
||||
|
||||
/** \returns a dynamic-size expression of a block in *this.
|
||||
/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \addexample BlockIntInt \label How to reference a sub-vector (dynamic size)
|
||||
* \addexample SegmentIntInt \label How to reference a sub-vector (dynamic size)
|
||||
*
|
||||
* \param start the first coefficient in the block
|
||||
* \param size the number of coefficients in the block
|
||||
* \param start the first coefficient in the segment
|
||||
* \param size the number of coefficients in the segment
|
||||
*
|
||||
* Example: \include MatrixBase_block_int_int.cpp
|
||||
* Output: \verbinclude MatrixBase_block_int_int.out
|
||||
* Example: \include MatrixBase_segment_int_int.cpp
|
||||
* Output: \verbinclude MatrixBase_segment_int_int.out
|
||||
*
|
||||
* \note Even though the returned expression has dynamic size, in the case
|
||||
* when it is applied to a fixed-size vector, it inherits a fixed maximal size,
|
||||
* which means that evaluating it does not cause a dynamic memory allocation.
|
||||
*
|
||||
* \sa class Block, block(int)
|
||||
* \sa class Block, segment(int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename BlockReturnType<Derived>::SubVectorType MatrixBase<Derived>
|
||||
::block(int start, int size)
|
||||
::segment(int start, int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return typename BlockReturnType<Derived>::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start,
|
||||
ColsAtCompileTime == 1 ? 0 : start,
|
||||
RowsAtCompileTime == 1 ? 1 : size,
|
||||
ColsAtCompileTime == 1 ? 1 : size);
|
||||
}
|
||||
|
||||
/** This is the const version of block(int,int).*/
|
||||
/** This is the const version of segment(int,int).*/
|
||||
template<typename Derived>
|
||||
inline const typename BlockReturnType<Derived>::SubVectorType
|
||||
MatrixBase<Derived>::block(int start, int size) const
|
||||
MatrixBase<Derived>::segment(int start, int size) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return typename BlockReturnType<Derived>::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start,
|
||||
ColsAtCompileTime == 1 ? 0 : start,
|
||||
RowsAtCompileTime == 1 ? 1 : size,
|
||||
@@ -380,7 +377,7 @@ template<typename Derived>
|
||||
inline typename BlockReturnType<Derived,Dynamic>::SubVectorType
|
||||
MatrixBase<Derived>::start(int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived,
|
||||
RowsAtCompileTime == 1 ? 1 : Dynamic,
|
||||
ColsAtCompileTime == 1 ? 1 : Dynamic>
|
||||
@@ -394,7 +391,7 @@ template<typename Derived>
|
||||
inline const typename BlockReturnType<Derived,Dynamic>::SubVectorType
|
||||
MatrixBase<Derived>::start(int size) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived,
|
||||
RowsAtCompileTime == 1 ? 1 : Dynamic,
|
||||
ColsAtCompileTime == 1 ? 1 : Dynamic>
|
||||
@@ -424,7 +421,7 @@ template<typename Derived>
|
||||
inline typename BlockReturnType<Derived,Dynamic>::SubVectorType
|
||||
MatrixBase<Derived>::end(int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived,
|
||||
RowsAtCompileTime == 1 ? 1 : Dynamic,
|
||||
ColsAtCompileTime == 1 ? 1 : Dynamic>
|
||||
@@ -440,7 +437,7 @@ template<typename Derived>
|
||||
inline const typename BlockReturnType<Derived,Dynamic>::SubVectorType
|
||||
MatrixBase<Derived>::end(int size) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived,
|
||||
RowsAtCompileTime == 1 ? 1 : Dynamic,
|
||||
ColsAtCompileTime == 1 ? 1 : Dynamic>
|
||||
@@ -451,38 +448,38 @@ MatrixBase<Derived>::end(int size) const
|
||||
ColsAtCompileTime == 1 ? 1 : size);
|
||||
}
|
||||
|
||||
/** \returns a fixed-size expression of a sub-vector of \c *this
|
||||
/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* The template parameter \a Size is the number of coefficients in the block
|
||||
*
|
||||
*
|
||||
* \param start the index of the first element of the sub-vector
|
||||
*
|
||||
* Example: \include MatrixBase_template_int.cpp
|
||||
* Output: \verbinclude MatrixBase_template_int.out
|
||||
* Example: \include MatrixBase_template_int_segment.cpp
|
||||
* Output: \verbinclude MatrixBase_template_int_segment.out
|
||||
*
|
||||
* \sa class Block
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::block(int start)
|
||||
MatrixBase<Derived>::segment(int start)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
|
||||
(ColsAtCompileTime == 1 ? 1 : Size)>
|
||||
(derived(), RowsAtCompileTime == 1 ? 0 : start,
|
||||
ColsAtCompileTime == 1 ? 0 : start);
|
||||
}
|
||||
|
||||
/** This is the const version of block<int>(int).*/
|
||||
/** This is the const version of segment<int>(int).*/
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline const typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::block(int start) const
|
||||
MatrixBase<Derived>::segment(int start) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
|
||||
(ColsAtCompileTime == 1 ? 1 : Size)>
|
||||
(derived(), RowsAtCompileTime == 1 ? 0 : start,
|
||||
@@ -507,7 +504,7 @@ template<int Size>
|
||||
inline typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::start()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
|
||||
(ColsAtCompileTime == 1 ? 1 : Size)>(derived(), 0, 0);
|
||||
}
|
||||
@@ -518,7 +515,7 @@ template<int Size>
|
||||
inline const typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::start() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
|
||||
(ColsAtCompileTime == 1 ? 1 : Size)>(derived(), 0, 0);
|
||||
}
|
||||
@@ -539,7 +536,7 @@ template<int Size>
|
||||
inline typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::end()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, RowsAtCompileTime == 1 ? 1 : Size,
|
||||
ColsAtCompileTime == 1 ? 1 : Size>
|
||||
(derived(),
|
||||
@@ -553,7 +550,7 @@ template<int Size>
|
||||
inline const typename BlockReturnType<Derived,Size>::SubVectorType
|
||||
MatrixBase<Derived>::end() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return Block<Derived, RowsAtCompileTime == 1 ? 1 : Size,
|
||||
ColsAtCompileTime == 1 ? 1 : Size>
|
||||
(derived(),
|
||||
|
||||
@@ -81,7 +81,7 @@ static void ei_cache_friendly_product(
|
||||
MaxBlockRows_ClampingMask = 0xFFFFF8,
|
||||
#endif
|
||||
// maximal size of the blocks fitted in L2 cache
|
||||
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_L2_CACHE_SIZE,Scalar>::width
|
||||
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_CPU_CACHE_SIZE,Scalar>::width
|
||||
};
|
||||
|
||||
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));
|
||||
@@ -95,9 +95,9 @@ static void ei_cache_friendly_product(
|
||||
const bool needRhsCopy = (PacketSize>1) && ((rhsStride%PacketSize!=0) || (size_t(rhs)%16!=0));
|
||||
Scalar* EIGEN_RESTRICT block = 0;
|
||||
const int allocBlockSize = l2BlockRows*size;
|
||||
block = ei_alloc_stack(Scalar, allocBlockSize);
|
||||
block = ei_aligned_stack_new(Scalar, allocBlockSize);
|
||||
Scalar* EIGEN_RESTRICT rhsCopy
|
||||
= ei_alloc_stack(Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
|
||||
= ei_aligned_stack_new(Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
|
||||
|
||||
// loops on each L2 cache friendly blocks of the result
|
||||
for(int l2i=0; l2i<rows; l2i+=l2BlockRows)
|
||||
@@ -338,8 +338,8 @@ static void ei_cache_friendly_product(
|
||||
}
|
||||
}
|
||||
|
||||
ei_free_stack(block, Scalar, allocBlockSize);
|
||||
ei_free_stack(rhsCopy, Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
|
||||
ei_aligned_stack_delete(Scalar, block, allocBlockSize);
|
||||
ei_aligned_stack_delete(Scalar, rhsCopy, l2BlockSizeAligned*l2BlockSizeAligned);
|
||||
}
|
||||
|
||||
#endif // EIGEN_EXTERN_INSTANTIATIONS
|
||||
@@ -361,13 +361,14 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
#ifdef _EIGEN_ACCUMULATE_PACKETS
|
||||
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
||||
#endif
|
||||
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2,OFFSET) \
|
||||
ei_pstore(&res[j OFFSET], \
|
||||
ei_padd(ei_pload(&res[j OFFSET]), \
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) \
|
||||
ei_pstore(&res[j], \
|
||||
ei_padd(ei_pload(&res[j]), \
|
||||
ei_padd( \
|
||||
ei_padd(ei_pmul(ptmp0,ei_pload ## A0(&lhs0[j OFFSET])),ei_pmul(ptmp1,ei_pload ## A13(&lhs1[j OFFSET]))), \
|
||||
ei_padd(ei_pmul(ptmp2,ei_pload ## A2(&lhs2[j OFFSET])),ei_pmul(ptmp3,ei_pload ## A13(&lhs3[j OFFSET]))) )))
|
||||
ei_padd(ei_pmul(ptmp0,EIGEN_CAT(ei_ploa , A0)(&lhs0[j])), \
|
||||
ei_pmul(ptmp1,EIGEN_CAT(ei_ploa , A13)(&lhs1[j]))), \
|
||||
ei_padd(ei_pmul(ptmp2,EIGEN_CAT(ei_ploa , A2)(&lhs2[j])), \
|
||||
ei_pmul(ptmp3,EIGEN_CAT(ei_ploa , A13)(&lhs3[j]))) )))
|
||||
|
||||
typedef typename ei_packet_traits<Scalar>::type Packet;
|
||||
const int PacketSize = sizeof(Packet)/sizeof(Scalar);
|
||||
@@ -397,7 +398,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
if (PacketSize>1)
|
||||
{
|
||||
ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
|
||||
|
||||
|
||||
while (skipColumns<PacketSize &&
|
||||
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%PacketSize))
|
||||
++skipColumns;
|
||||
@@ -418,7 +419,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
|
||||
int offset1 = (FirstAligned && alignmentStep==1?3:1);
|
||||
int offset3 = (FirstAligned && alignmentStep==1?1:3);
|
||||
|
||||
|
||||
int columnBound = ((rhs.size()-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
|
||||
for (int i=skipColumns; i<columnBound; i+=columnsAtOnce)
|
||||
{
|
||||
@@ -433,7 +434,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
{
|
||||
/* explicit vectorization */
|
||||
// process initial unaligned coeffs
|
||||
for (int j=0; j<alignedStart; j++)
|
||||
for (int j=0; j<alignedStart; ++j)
|
||||
res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
@@ -442,11 +443,11 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
{
|
||||
case AllAligned:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,,,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,d,d);
|
||||
break;
|
||||
case EvenAligned:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,u,,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,du,d);
|
||||
break;
|
||||
case FirstAligned:
|
||||
if(peels>1)
|
||||
@@ -482,18 +483,18 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
}
|
||||
}
|
||||
for (int j = peeledSize; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,u,u,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,du,du);
|
||||
break;
|
||||
default:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(u,u,u,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(du,du,du);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end explicit vectorization
|
||||
|
||||
/* process remaining coeffs (or all if there is no explicit vectorization) */
|
||||
for (int j=alignedSize; j<size; j++)
|
||||
for (int j=alignedSize; j<size; ++j)
|
||||
res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
|
||||
}
|
||||
|
||||
@@ -502,7 +503,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
int start = columnBound;
|
||||
do
|
||||
{
|
||||
for (int i=start; i<end; i++)
|
||||
for (int i=start; i<end; ++i)
|
||||
{
|
||||
Packet ptmp0 = ei_pset1(rhs[i]);
|
||||
const Scalar* lhs0 = lhs + i*lhsStride;
|
||||
@@ -511,7 +512,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
{
|
||||
/* explicit vectorization */
|
||||
// process first unaligned result's coeffs
|
||||
for (int j=0; j<alignedStart; j++)
|
||||
for (int j=0; j<alignedStart; ++j)
|
||||
res[j] += ei_pfirst(ptmp0) * lhs0[j];
|
||||
|
||||
// process aligned result's coeffs
|
||||
@@ -524,7 +525,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
|
||||
}
|
||||
|
||||
// process remaining scalars (or all if no explicit vectorization)
|
||||
for (int j=alignedSize; j<size; j++)
|
||||
for (int j=alignedSize; j<size; ++j)
|
||||
res[j] += ei_pfirst(ptmp0) * lhs0[j];
|
||||
}
|
||||
if (skipColumns)
|
||||
@@ -550,12 +551,12 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
||||
#endif
|
||||
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2,OFFSET) {\
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) {\
|
||||
Packet b = ei_pload(&rhs[j]); \
|
||||
ptmp0 = ei_pmadd(b, ei_pload##A0 (&lhs0[j]), ptmp0); \
|
||||
ptmp1 = ei_pmadd(b, ei_pload##A13(&lhs1[j]), ptmp1); \
|
||||
ptmp2 = ei_pmadd(b, ei_pload##A2 (&lhs2[j]), ptmp2); \
|
||||
ptmp3 = ei_pmadd(b, ei_pload##A13(&lhs3[j]), ptmp3); }
|
||||
ptmp0 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A0) (&lhs0[j]), ptmp0); \
|
||||
ptmp1 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs1[j]), ptmp1); \
|
||||
ptmp2 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A2) (&lhs2[j]), ptmp2); \
|
||||
ptmp3 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs3[j]), ptmp3); }
|
||||
|
||||
typedef typename ei_packet_traits<Scalar>::type Packet;
|
||||
const int PacketSize = sizeof(Packet)/sizeof(Scalar);
|
||||
@@ -580,13 +581,13 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
|
||||
// we cannot assume the first element is aligned because of sub-matrices
|
||||
const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
|
||||
|
||||
|
||||
// find how many rows do we have to skip to be aligned with rhs (if possible)
|
||||
int skipRows = 0;
|
||||
if (PacketSize>1)
|
||||
{
|
||||
ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
|
||||
|
||||
|
||||
while (skipRows<PacketSize &&
|
||||
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%PacketSize))
|
||||
++skipRows;
|
||||
@@ -607,7 +608,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
|
||||
int offset1 = (FirstAligned && alignmentStep==1?3:1);
|
||||
int offset3 = (FirstAligned && alignmentStep==1?1:3);
|
||||
|
||||
|
||||
int rowBound = ((res.size()-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
|
||||
for (int i=skipRows; i<rowBound; i+=rowsAtOnce)
|
||||
{
|
||||
@@ -621,10 +622,10 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
{
|
||||
/* explicit vectorization */
|
||||
Packet ptmp0 = ei_pset1(Scalar(0)), ptmp1 = ei_pset1(Scalar(0)), ptmp2 = ei_pset1(Scalar(0)), ptmp3 = ei_pset1(Scalar(0));
|
||||
|
||||
|
||||
// process initial unaligned coeffs
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (int j=0; j<alignedStart; j++)
|
||||
for (int j=0; j<alignedStart; ++j)
|
||||
{
|
||||
Scalar b = rhs[j];
|
||||
tmp0 += b*lhs0[j]; tmp1 += b*lhs1[j]; tmp2 += b*lhs2[j]; tmp3 += b*lhs3[j];
|
||||
@@ -636,11 +637,11 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
{
|
||||
case AllAligned:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,,,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,d,d);
|
||||
break;
|
||||
case EvenAligned:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,u,,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,du,d);
|
||||
break;
|
||||
case FirstAligned:
|
||||
if (peels>1)
|
||||
@@ -679,11 +680,11 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
}
|
||||
}
|
||||
for (int j = peeledSize; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(,u,u,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(d,du,du);
|
||||
break;
|
||||
default:
|
||||
for (int j = alignedStart; j<alignedSize; j+=PacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(u,u,u,);
|
||||
_EIGEN_ACCUMULATE_PACKETS(du,du,du);
|
||||
break;
|
||||
}
|
||||
tmp0 += ei_predux(ptmp0);
|
||||
@@ -695,7 +696,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
|
||||
// process remaining coeffs (or all if no explicit vectorization)
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (int j=alignedSize; j<size; j++)
|
||||
for (int j=alignedSize; j<size; ++j)
|
||||
{
|
||||
Scalar b = rhs[j];
|
||||
tmp0 += b*lhs0[j]; tmp1 += b*lhs1[j]; tmp2 += b*lhs2[j]; tmp3 += b*lhs3[j];
|
||||
@@ -708,14 +709,14 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
int start = rowBound;
|
||||
do
|
||||
{
|
||||
for (int i=start; i<end; i++)
|
||||
for (int i=start; i<end; ++i)
|
||||
{
|
||||
Scalar tmp0 = Scalar(0);
|
||||
Packet ptmp0 = ei_pset1(tmp0);
|
||||
const Scalar* lhs0 = lhs + i*lhsStride;
|
||||
// process first unaligned result's coeffs
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (int j=0; j<alignedStart; j++)
|
||||
for (int j=0; j<alignedStart; ++j)
|
||||
tmp0 += rhs[j] * lhs0[j];
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
@@ -732,7 +733,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
|
||||
|
||||
// process remaining scalars
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (int j=alignedSize; j<size; j++)
|
||||
for (int j=alignedSize; j<size; ++j)
|
||||
tmp0 += rhs[j] * lhs0[j];
|
||||
res[i] += tmp0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -40,7 +40,7 @@
|
||||
* \sa operator()(int,int) const, coeffRef(int,int), coeff(int) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::coeff(int row, int col) const
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
@@ -53,7 +53,7 @@ inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
* \sa operator()(int,int), operator[](int) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::operator()(int row, int col) const
|
||||
{
|
||||
ei_assert(row >= 0 && row < rows()
|
||||
@@ -76,7 +76,7 @@ inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
* \sa operator()(int,int), coeff(int, int) const, coeffRef(int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::coeffRef(int row, int col)
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
@@ -89,7 +89,7 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
* \sa operator()(int,int) const, operator[](int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::operator()(int row, int col)
|
||||
{
|
||||
ei_assert(row >= 0 && row < rows()
|
||||
@@ -112,7 +112,7 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
* \sa operator[](int) const, coeffRef(int), coeff(int,int) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::coeff(int index) const
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
@@ -127,7 +127,7 @@ inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
* z() const, w() const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::operator[](int index) const
|
||||
{
|
||||
ei_assert(index >= 0 && index < size());
|
||||
@@ -144,7 +144,7 @@ inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
* z() const, w() const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::operator()(int index) const
|
||||
{
|
||||
ei_assert(index >= 0 && index < size());
|
||||
@@ -166,7 +166,7 @@ inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
* \sa operator[](int), coeff(int) const, coeffRef(int,int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::coeffRef(int index)
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
@@ -180,7 +180,7 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
* \sa operator[](int) const, operator()(int,int), x(), y(), z(), w()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::operator[](int index)
|
||||
{
|
||||
ei_assert(index >= 0 && index < size());
|
||||
@@ -196,7 +196,7 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
* \sa operator[](int) const, operator()(int,int), x(), y(), z(), w()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::operator()(int index)
|
||||
{
|
||||
ei_assert(index >= 0 && index < size());
|
||||
@@ -205,42 +205,42 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
|
||||
/** equivalent to operator[](0). */
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::x() const { return (*this)[0]; }
|
||||
|
||||
/** equivalent to operator[](1). */
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::y() const { return (*this)[1]; }
|
||||
|
||||
/** equivalent to operator[](2). */
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::z() const { return (*this)[2]; }
|
||||
|
||||
/** equivalent to operator[](3). */
|
||||
template<typename Derived>
|
||||
inline const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
|
||||
::w() const { return (*this)[3]; }
|
||||
|
||||
/** equivalent to operator[](0). */
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::x() { return (*this)[0]; }
|
||||
|
||||
/** equivalent to operator[](1). */
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::y() { return (*this)[1]; }
|
||||
|
||||
/** equivalent to operator[](2). */
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::z() { return (*this)[2]; }
|
||||
|
||||
/** equivalent to operator[](3). */
|
||||
template<typename Derived>
|
||||
inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
::w() { return (*this)[3]; }
|
||||
|
||||
/** \returns the packet of coefficients starting at the given row and column. It is your responsibility
|
||||
@@ -253,7 +253,7 @@ inline typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int LoadMode>
|
||||
inline typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
|
||||
EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
|
||||
MatrixBase<Derived>::packet(int row, int col) const
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
@@ -271,7 +271,7 @@ MatrixBase<Derived>::packet(int row, int col) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int StoreMode>
|
||||
inline void MatrixBase<Derived>::writePacket
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
|
||||
(int row, int col, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x)
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
@@ -289,7 +289,7 @@ inline void MatrixBase<Derived>::writePacket
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int LoadMode>
|
||||
inline typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
|
||||
EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
|
||||
MatrixBase<Derived>::packet(int index) const
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
@@ -306,33 +306,56 @@ MatrixBase<Derived>::packet(int index) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int StoreMode>
|
||||
inline void MatrixBase<Derived>::writePacket
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
|
||||
(int index, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x)
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
derived().template writePacket<StoreMode>(index,x);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** \internal Copies the coefficient at position (row,col) of other into *this.
|
||||
*
|
||||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
|
||||
* with usual assignments.
|
||||
*
|
||||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline void MatrixBase<Derived>::copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
&& col >= 0 && col < cols());
|
||||
derived().coeffRef(row, col) = other.derived().coeff(row, col);
|
||||
}
|
||||
|
||||
/** \internal Copies the coefficient at the given index of other into *this.
|
||||
*
|
||||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
|
||||
* with usual assignments.
|
||||
*
|
||||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline void MatrixBase<Derived>::copyCoeff(int index, const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyCoeff(int index, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
derived().coeffRef(index) = other.derived().coeff(index);
|
||||
}
|
||||
|
||||
/** \internal Copies the packet at position (row,col) of other into *this.
|
||||
*
|
||||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
|
||||
* with usual assignments.
|
||||
*
|
||||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived, int StoreMode, int LoadMode>
|
||||
inline void MatrixBase<Derived>::copyPacket(int row, int col, const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int row, int col, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_internal_assert(row >= 0 && row < rows()
|
||||
&& col >= 0 && col < cols());
|
||||
@@ -340,13 +363,22 @@ inline void MatrixBase<Derived>::copyPacket(int row, int col, const MatrixBase<O
|
||||
other.derived().template packet<LoadMode>(row, col));
|
||||
}
|
||||
|
||||
/** \internal Copies the packet at the given index of other into *this.
|
||||
*
|
||||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
|
||||
* with usual assignments.
|
||||
*
|
||||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived, int StoreMode, int LoadMode>
|
||||
inline void MatrixBase<Derived>::copyPacket(int index, const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int index, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
ei_internal_assert(index >= 0 && index < size());
|
||||
derived().template writePacket<StoreMode>(index,
|
||||
other.derived().template packet<LoadMode>(index));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_COEFFS_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -27,13 +27,13 @@
|
||||
#define EIGEN_COMMAINITIALIZER_H
|
||||
|
||||
/** \class CommaInitializer
|
||||
*
|
||||
*
|
||||
* \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 \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
@@ -128,7 +128,7 @@ struct CommaInitializer
|
||||
*
|
||||
* Example: \include MatrixBase_set.cpp
|
||||
* Output: \verbinclude MatrixBase_set.out
|
||||
*
|
||||
*
|
||||
* \sa CommaInitializer::finished(), class CommaInitializer
|
||||
*/
|
||||
template<typename Derived>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -31,6 +31,18 @@
|
||||
#define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
|
||||
|
||||
#define EIGEN_CWISE_PRODUCT_RETURN_TYPE \
|
||||
CwiseBinaryOp< \
|
||||
ei_scalar_product_op< \
|
||||
typename ei_scalar_product_traits< \
|
||||
typename ei_traits<ExpressionType>::Scalar, \
|
||||
typename ei_traits<OtherDerived>::Scalar \
|
||||
>::ReturnType \
|
||||
>, \
|
||||
ExpressionType, \
|
||||
OtherDerived \
|
||||
>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise unary operation */
|
||||
#define EIGEN_CWISE_UNOP_RETURN_TYPE(OP) \
|
||||
@@ -74,7 +86,7 @@ template<typename ExpressionType> class Cwise
|
||||
inline const ExpressionType& _expression() const { return m_matrix; }
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op)
|
||||
const EIGEN_CWISE_PRODUCT_RETURN_TYPE
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
@@ -116,6 +128,12 @@ template<typename ExpressionType> class Cwise
|
||||
|
||||
ExpressionType& operator-=(const Scalar& scalar);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator*=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator/=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
operator<(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
@@ -153,6 +171,11 @@ template<typename ExpressionType> class Cwise
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(Scalar s) const;
|
||||
|
||||
// allow to extend Cwise outside Eigen
|
||||
#ifdef EIGEN_CWISE_PLUGIN
|
||||
#include EIGEN_CWISE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -46,6 +46,8 @@
|
||||
template<typename BinaryOp, typename Lhs, typename Rhs>
|
||||
struct ei_traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
||||
{
|
||||
// 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 ei_result_of<
|
||||
BinaryOp(
|
||||
typename Lhs::Scalar,
|
||||
@@ -84,35 +86,46 @@ class CwiseBinaryOp : ei_no_assignment_operator,
|
||||
typedef typename ei_traits<CwiseBinaryOp>::LhsNested LhsNested;
|
||||
typedef typename ei_traits<CwiseBinaryOp>::RhsNested RhsNested;
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
|
||||
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
|
||||
: m_lhs(lhs), m_rhs(rhs), m_functor(func)
|
||||
{
|
||||
// we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
|
||||
// that would take two operands of different types. If there were such an example, then this check should be
|
||||
// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
|
||||
// currently they take only one typename Scalar template parameter.
|
||||
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
|
||||
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
|
||||
// add together a float matrix and a double matrix.
|
||||
EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret
|
||||
? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret)
|
||||
: int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
// require the sizes to match
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
|
||||
ei_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
|
||||
}
|
||||
|
||||
inline int rows() const { return m_lhs.rows(); }
|
||||
inline int cols() const { return m_lhs.cols(); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
|
||||
|
||||
inline const Scalar coeff(int row, int col) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
|
||||
{
|
||||
return m_functor(m_lhs.coeff(row, col), m_rhs.coeff(row, col));
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int row, int col) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
|
||||
{
|
||||
return m_functor.packetOp(m_lhs.template packet<LoadMode>(row, col), m_rhs.template packet<LoadMode>(row, col));
|
||||
}
|
||||
|
||||
inline const Scalar coeff(int index) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int index) const
|
||||
{
|
||||
return m_functor(m_lhs.coeff(index), m_rhs.coeff(index));
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int index) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int index) const
|
||||
{
|
||||
return m_functor.packetOp(m_lhs.template packet<LoadMode>(index), m_rhs.template packet<LoadMode>(index));
|
||||
}
|
||||
@@ -131,7 +144,7 @@ class CwiseBinaryOp : ei_no_assignment_operator,
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline const CwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
|
||||
EIGEN_STRONG_INLINE const CwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
|
||||
Derived, OtherDerived>
|
||||
MatrixBase<Derived>::operator-(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
@@ -145,7 +158,7 @@ MatrixBase<Derived>::operator-(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline Derived &
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return *this = *this - other;
|
||||
@@ -161,7 +174,7 @@ MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline const CwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
|
||||
EIGEN_STRONG_INLINE const CwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
|
||||
MatrixBase<Derived>::operator+(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return CwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
|
||||
@@ -173,7 +186,7 @@ MatrixBase<Derived>::operator+(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline Derived &
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return *this = *this + other;
|
||||
@@ -188,10 +201,10 @@ MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE
|
||||
Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op)(_expression(), other.derived());
|
||||
return EIGEN_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \returns an expression of the coefficient-wise quotient of *this and \a other
|
||||
@@ -203,12 +216,40 @@ Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
|
||||
Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** Replaces this expression by its coefficient-wise product with \a other.
|
||||
*
|
||||
* Example: \include Cwise_times_equal.cpp
|
||||
* Output: \verbinclude Cwise_times_equal.out
|
||||
*
|
||||
* \sa operator*(), operator/=()
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this * other;
|
||||
}
|
||||
|
||||
/** Replaces this expression by its coefficient-wise quotient by \a other.
|
||||
*
|
||||
* Example: \include Cwise_slash_equal.cpp
|
||||
* Output: \verbinclude Cwise_slash_equal.out
|
||||
*
|
||||
* \sa operator/(), operator*=()
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this / other;
|
||||
}
|
||||
|
||||
/** \returns an expression of the coefficient-wise min of *this and \a other
|
||||
*
|
||||
* Example: \include Cwise_min.cpp
|
||||
@@ -218,7 +259,7 @@ Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
|
||||
Cwise<ExpressionType>::min(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
|
||||
@@ -233,7 +274,7 @@ Cwise<ExpressionType>::min(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
|
||||
Cwise<ExpressionType>::max(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
|
||||
@@ -254,7 +295,7 @@ Cwise<ExpressionType>::max(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomBinaryOp, typename OtherDerived>
|
||||
inline const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
|
||||
EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
|
||||
MatrixBase<Derived>::binaryExpr(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func) const
|
||||
{
|
||||
return CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>(derived(), other.derived(), func);
|
||||
|
||||
@@ -41,14 +41,9 @@
|
||||
* \sa class CwiseUnaryOp, class CwiseBinaryOp, MatrixBase::NullaryExpr()
|
||||
*/
|
||||
template<typename NullaryOp, typename MatrixType>
|
||||
struct ei_traits<CwiseNullaryOp<NullaryOp, MatrixType> >
|
||||
struct ei_traits<CwiseNullaryOp<NullaryOp, MatrixType> > : ei_traits<MatrixType>
|
||||
{
|
||||
typedef typename ei_traits<MatrixType>::Scalar Scalar;
|
||||
enum {
|
||||
RowsAtCompileTime = ei_traits<MatrixType>::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ei_traits<MatrixType>::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ei_traits<MatrixType>::MaxColsAtCompileTime,
|
||||
Flags = (ei_traits<MatrixType>::Flags
|
||||
& ( HereditaryBits
|
||||
| (ei_functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
|
||||
@@ -75,21 +70,21 @@ class CwiseNullaryOp : ei_no_assignment_operator,
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
}
|
||||
|
||||
int rows() const { return m_rows.value(); }
|
||||
int cols() const { return m_cols.value(); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_rows.value(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_cols.value(); }
|
||||
|
||||
const Scalar coeff(int rows, int cols) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int rows, int cols) const
|
||||
{
|
||||
return m_functor(rows, cols);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
PacketScalar packet(int, int) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int, int) const
|
||||
{
|
||||
return m_functor.packetOp();
|
||||
}
|
||||
|
||||
const Scalar coeff(int index) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int index) const
|
||||
{
|
||||
if(RowsAtCompileTime == 1)
|
||||
return m_functor(0, index);
|
||||
@@ -98,7 +93,7 @@ class CwiseNullaryOp : ei_no_assignment_operator,
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
PacketScalar packet(int) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int) const
|
||||
{
|
||||
return m_functor.packetOp();
|
||||
}
|
||||
@@ -125,7 +120,7 @@ class CwiseNullaryOp : ei_no_assignment_operator,
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
MatrixBase<Derived>::NullaryExpr(int rows, int cols, const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, Derived>(rows, cols, func);
|
||||
@@ -148,9 +143,10 @@ MatrixBase<Derived>::NullaryExpr(int rows, int cols, const CustomNullaryOp& func
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
MatrixBase<Derived>::NullaryExpr(int size, const CustomNullaryOp& func)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
ei_assert(IsVectorAtCompileTime);
|
||||
if(RowsAtCompileTime == 1) return CwiseNullaryOp<CustomNullaryOp, Derived>(1, size, func);
|
||||
else return CwiseNullaryOp<CustomNullaryOp, Derived>(size, 1, func);
|
||||
@@ -167,7 +163,7 @@ MatrixBase<Derived>::NullaryExpr(int size, const CustomNullaryOp& func)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
|
||||
MatrixBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, Derived>(RowsAtCompileTime, ColsAtCompileTime, func);
|
||||
@@ -187,7 +183,7 @@ MatrixBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
|
||||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Constant(int rows, int cols, const Scalar& value)
|
||||
{
|
||||
return NullaryExpr(rows, cols, ei_scalar_constant_op<Scalar>(value));
|
||||
@@ -209,7 +205,7 @@ MatrixBase<Derived>::Constant(int rows, int cols, const Scalar& value)
|
||||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Constant(int size, const Scalar& value)
|
||||
{
|
||||
return NullaryExpr(size, ei_scalar_constant_op<Scalar>(value));
|
||||
@@ -225,34 +221,91 @@ MatrixBase<Derived>::Constant(int size, const Scalar& value)
|
||||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Constant(const Scalar& value)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, ei_scalar_constant_op<Scalar>(value));
|
||||
}
|
||||
|
||||
/** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isApproxToConstant
|
||||
(const Scalar& value, RealScalar prec) const
|
||||
{
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i < rows(); i++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i < rows(); ++i)
|
||||
if(!ei_isApprox(coeff(i, j), value, prec))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Sets all coefficients in this expression to \a value.
|
||||
/** This is just an alias for isApproxToConstant().
|
||||
*
|
||||
* \sa class CwiseNullaryOp, Zero(), Ones()
|
||||
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isConstant
|
||||
(const Scalar& value, RealScalar prec) const
|
||||
{
|
||||
return isApproxToConstant(value, prec);
|
||||
}
|
||||
|
||||
/** Alias for setConstant(): sets all coefficients in this expression to \a value.
|
||||
*
|
||||
* \sa setConstant(), Constant(), class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
Derived& MatrixBase<Derived>::setConstant(const Scalar& value)
|
||||
EIGEN_STRONG_INLINE void MatrixBase<Derived>::fill(const Scalar& value)
|
||||
{
|
||||
setConstant(value);
|
||||
}
|
||||
|
||||
/** Sets all coefficients in this expression to \a value.
|
||||
*
|
||||
* \sa fill(), setConstant(int,const Scalar&), setConstant(int,int,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setConstant(const Scalar& value)
|
||||
{
|
||||
return derived() = Constant(rows(), cols(), value);
|
||||
}
|
||||
|
||||
/** Resizes to the given \a size, and sets all coefficients in this expression to the given \a value.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* Example: \include Matrix_set_int.cpp
|
||||
* Output: \verbinclude Matrix_setConstant_int.out
|
||||
*
|
||||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(int,int,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setConstant(int size, const Scalar& value)
|
||||
{
|
||||
resize(size);
|
||||
return setConstant(value);
|
||||
}
|
||||
|
||||
/** Resizes to the given size, and sets all coefficients in this expression to the given \a value.
|
||||
*
|
||||
* \param rows the new number of rows
|
||||
* \param cols the new number of columns
|
||||
*
|
||||
* Example: \include Matrix_setConstant_int_int.cpp
|
||||
* Output: \verbinclude Matrix_setConstant_int_int.out
|
||||
*
|
||||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(int,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setConstant(int rows, int cols, const Scalar& value)
|
||||
{
|
||||
resize(rows, cols);
|
||||
return setConstant(value);
|
||||
}
|
||||
|
||||
|
||||
// zero:
|
||||
|
||||
/** \returns an expression of a zero matrix.
|
||||
@@ -272,7 +325,7 @@ Derived& MatrixBase<Derived>::setConstant(const Scalar& value)
|
||||
* \sa Zero(), Zero(int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Zero(int rows, int cols)
|
||||
{
|
||||
return Constant(rows, cols, Scalar(0));
|
||||
@@ -295,7 +348,7 @@ MatrixBase<Derived>::Zero(int rows, int cols)
|
||||
* \sa Zero(), Zero(int,int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Zero(int size)
|
||||
{
|
||||
return Constant(size, Scalar(0));
|
||||
@@ -312,7 +365,7 @@ MatrixBase<Derived>::Zero(int size)
|
||||
* \sa Zero(int), Zero(int,int)
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Zero()
|
||||
{
|
||||
return Constant(Scalar(0));
|
||||
@@ -327,11 +380,10 @@ MatrixBase<Derived>::Zero()
|
||||
* \sa class CwiseNullaryOp, Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isZero
|
||||
(RealScalar prec) const
|
||||
bool MatrixBase<Derived>::isZero(RealScalar prec) const
|
||||
{
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i < rows(); i++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i < rows(); ++i)
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), static_cast<Scalar>(1), prec))
|
||||
return false;
|
||||
return true;
|
||||
@@ -345,11 +397,46 @@ bool MatrixBase<Derived>::isZero
|
||||
* \sa class CwiseNullaryOp, Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
Derived& MatrixBase<Derived>::setZero()
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setZero()
|
||||
{
|
||||
return setConstant(Scalar(0));
|
||||
}
|
||||
|
||||
/** 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 MatrixBase::setZero(), setZero(int,int), class CwiseNullaryOp, MatrixBase::Zero()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setZero(int size)
|
||||
{
|
||||
resize(size);
|
||||
return setConstant(Scalar(0));
|
||||
}
|
||||
|
||||
/** 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 MatrixBase::setZero(), setZero(int), class CwiseNullaryOp, MatrixBase::Zero()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setZero(int rows, int cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
return setConstant(Scalar(0));
|
||||
}
|
||||
|
||||
// ones:
|
||||
|
||||
/** \returns an expression of a matrix where all coefficients equal one.
|
||||
@@ -369,7 +456,7 @@ Derived& MatrixBase<Derived>::setZero()
|
||||
* \sa Ones(), Ones(int), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Ones(int rows, int cols)
|
||||
{
|
||||
return Constant(rows, cols, Scalar(1));
|
||||
@@ -392,7 +479,7 @@ MatrixBase<Derived>::Ones(int rows, int cols)
|
||||
* \sa Ones(), Ones(int,int), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Ones(int size)
|
||||
{
|
||||
return Constant(size, Scalar(1));
|
||||
@@ -409,7 +496,7 @@ MatrixBase<Derived>::Ones(int size)
|
||||
* \sa Ones(int), Ones(int,int), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::ConstantReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
|
||||
MatrixBase<Derived>::Ones()
|
||||
{
|
||||
return Constant(Scalar(1));
|
||||
@@ -438,11 +525,46 @@ bool MatrixBase<Derived>::isOnes
|
||||
* \sa class CwiseNullaryOp, Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
Derived& MatrixBase<Derived>::setOnes()
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setOnes()
|
||||
{
|
||||
return setConstant(Scalar(1));
|
||||
}
|
||||
|
||||
/** Resizes to the given \a size, 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(int,int), class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setOnes(int size)
|
||||
{
|
||||
resize(size);
|
||||
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(int), class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setOnes(int rows, int cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
return setConstant(Scalar(1));
|
||||
}
|
||||
|
||||
// Identity:
|
||||
|
||||
/** \returns an expression of the identity matrix (not necessarily square).
|
||||
@@ -462,7 +584,7 @@ Derived& MatrixBase<Derived>::setOnes()
|
||||
* \sa Identity(), setIdentity(), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::IdentityReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
|
||||
MatrixBase<Derived>::Identity(int rows, int cols)
|
||||
{
|
||||
return NullaryExpr(rows, cols, ei_scalar_identity_op<Scalar>());
|
||||
@@ -479,7 +601,7 @@ MatrixBase<Derived>::Identity(int rows, int cols)
|
||||
* \sa Identity(int,int), setIdentity(), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::IdentityReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
|
||||
MatrixBase<Derived>::Identity()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
@@ -499,9 +621,9 @@ template<typename Derived>
|
||||
bool MatrixBase<Derived>::isIdentity
|
||||
(RealScalar prec) const
|
||||
{
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
{
|
||||
for(int i = 0; i < rows(); i++)
|
||||
for(int i = 0; i < rows(); ++i)
|
||||
{
|
||||
if(i == j)
|
||||
{
|
||||
@@ -521,7 +643,7 @@ bool MatrixBase<Derived>::isIdentity
|
||||
template<typename Derived, bool Big = (Derived::SizeAtCompileTime>=16)>
|
||||
struct ei_setIdentity_impl
|
||||
{
|
||||
static inline Derived& run(Derived& m)
|
||||
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
||||
{
|
||||
return m = Derived::Identity(m.rows(), m.cols());
|
||||
}
|
||||
@@ -530,11 +652,11 @@ struct ei_setIdentity_impl
|
||||
template<typename Derived>
|
||||
struct ei_setIdentity_impl<Derived, true>
|
||||
{
|
||||
static inline Derived& run(Derived& m)
|
||||
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
|
||||
{
|
||||
m.setZero();
|
||||
const int size = std::min(m.rows(), m.cols());
|
||||
for(int i = 0; i < size; i++) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
||||
for(int i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
|
||||
return m;
|
||||
}
|
||||
};
|
||||
@@ -547,11 +669,29 @@ struct ei_setIdentity_impl<Derived, true>
|
||||
* \sa class CwiseNullaryOp, Identity(), Identity(int,int), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Derived& MatrixBase<Derived>::setIdentity()
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
|
||||
{
|
||||
return ei_setIdentity_impl<Derived>::run(derived());
|
||||
}
|
||||
|
||||
/** 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<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setIdentity(int rows, int cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
return setIdentity();
|
||||
}
|
||||
|
||||
/** \returns an expression of the i-th unit (basis) vector.
|
||||
*
|
||||
* \only_for_vectors
|
||||
@@ -559,9 +699,9 @@ inline Derived& MatrixBase<Derived>::setIdentity()
|
||||
* \sa MatrixBase::Unit(int), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int size, int i)
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int size, int i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return BasisReturnType(SquareMatrixType::Identity(size,size), i);
|
||||
}
|
||||
|
||||
@@ -574,9 +714,9 @@ const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(in
|
||||
* \sa MatrixBase::Unit(int,int), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int i)
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return BasisReturnType(SquareMatrixType::Identity(),i);
|
||||
}
|
||||
|
||||
@@ -587,7 +727,7 @@ const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(in
|
||||
* \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitX()
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitX()
|
||||
{ return Derived::Unit(0); }
|
||||
|
||||
/** \returns an expression of the Y axis unit vector (0,1{,0}^*)
|
||||
@@ -597,7 +737,7 @@ const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitX()
|
||||
* \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitY()
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitY()
|
||||
{ return Derived::Unit(1); }
|
||||
|
||||
/** \returns an expression of the Z axis unit vector (0,0,1{,0}^*)
|
||||
@@ -607,7 +747,7 @@ const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitY()
|
||||
* \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitZ()
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitZ()
|
||||
{ return Derived::Unit(2); }
|
||||
|
||||
/** \returns an expression of the W axis unit vector (0,0,0,1)
|
||||
@@ -617,7 +757,7 @@ const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitZ()
|
||||
* \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
|
||||
*/
|
||||
template<typename Derived>
|
||||
const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW()
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW()
|
||||
{ return Derived::Unit(3); }
|
||||
|
||||
#endif // EIGEN_CWISE_NULLARY_OP_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -41,6 +41,7 @@
|
||||
*/
|
||||
template<typename UnaryOp, typename MatrixType>
|
||||
struct ei_traits<CwiseUnaryOp<UnaryOp, MatrixType> >
|
||||
: ei_traits<MatrixType>
|
||||
{
|
||||
typedef typename ei_result_of<
|
||||
UnaryOp(typename MatrixType::Scalar)
|
||||
@@ -48,16 +49,10 @@ struct ei_traits<CwiseUnaryOp<UnaryOp, MatrixType> >
|
||||
typedef typename MatrixType::Nested MatrixTypeNested;
|
||||
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
enum {
|
||||
MatrixTypeCoeffReadCost = _MatrixTypeNested::CoeffReadCost,
|
||||
MatrixTypeFlags = _MatrixTypeNested::Flags,
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||
Flags = (MatrixTypeFlags & (
|
||||
Flags = (_MatrixTypeNested::Flags & (
|
||||
HereditaryBits | LinearAccessBit | AlignedBit
|
||||
| (ei_functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0))),
|
||||
CoeffReadCost = MatrixTypeCoeffReadCost + ei_functor_traits<UnaryOp>::Cost
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
|
||||
};
|
||||
};
|
||||
|
||||
@@ -69,32 +64,30 @@ class CwiseUnaryOp : ei_no_assignment_operator,
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline CwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
|
||||
: m_matrix(mat), m_functor(func) {}
|
||||
|
||||
inline int rows() const { return m_matrix.rows(); }
|
||||
inline int cols() const { return m_matrix.cols(); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_matrix.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_matrix.cols(); }
|
||||
|
||||
inline const Scalar coeff(int row, int col) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
|
||||
{
|
||||
return m_functor(m_matrix.coeff(row, col));
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int row, int col) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
|
||||
{
|
||||
return m_functor.packetOp(m_matrix.template packet<LoadMode>(row, col));
|
||||
}
|
||||
|
||||
inline const Scalar coeff(int index) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int index) const
|
||||
{
|
||||
return m_functor(m_matrix.coeff(index));
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int index) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int index) const
|
||||
{
|
||||
return m_functor.packetOp(m_matrix.template packet<LoadMode>(index));
|
||||
}
|
||||
@@ -119,7 +112,7 @@ class CwiseUnaryOp : ei_no_assignment_operator,
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomUnaryOp>
|
||||
inline const CwiseUnaryOp<CustomUnaryOp, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseUnaryOp<CustomUnaryOp, Derived>
|
||||
MatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
|
||||
{
|
||||
return CwiseUnaryOp<CustomUnaryOp, Derived>(derived(), func);
|
||||
@@ -128,7 +121,7 @@ MatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
|
||||
/** \returns an expression of the opposite of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const CwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
|
||||
MatrixBase<Derived>::operator-() const
|
||||
{
|
||||
return derived();
|
||||
@@ -142,7 +135,7 @@ MatrixBase<Derived>::operator-() const
|
||||
* \sa abs2()
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
|
||||
Cwise<ExpressionType>::abs() const
|
||||
{
|
||||
return _expression();
|
||||
@@ -156,7 +149,7 @@ Cwise<ExpressionType>::abs() const
|
||||
* \sa abs(), square()
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
|
||||
Cwise<ExpressionType>::abs2() const
|
||||
{
|
||||
return _expression();
|
||||
@@ -166,7 +159,7 @@ Cwise<ExpressionType>::abs2() const
|
||||
*
|
||||
* \sa adjoint() */
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::ConjugateReturnType
|
||||
EIGEN_STRONG_INLINE typename MatrixBase<Derived>::ConjugateReturnType
|
||||
MatrixBase<Derived>::conjugate() const
|
||||
{
|
||||
return ConjugateReturnType(derived());
|
||||
@@ -174,13 +167,17 @@ MatrixBase<Derived>::conjugate() const
|
||||
|
||||
/** \returns an expression of the real part of \c *this.
|
||||
*
|
||||
* \sa adjoint() */
|
||||
* \sa imag() */
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::RealReturnType
|
||||
MatrixBase<Derived>::real() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::RealReturnType
|
||||
MatrixBase<Derived>::real() const { return derived(); }
|
||||
|
||||
/** \returns an expression of the imaginary part of \c *this.
|
||||
*
|
||||
* \sa real() */
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ImagReturnType
|
||||
MatrixBase<Derived>::imag() const { return derived(); }
|
||||
|
||||
/** \returns an expression of *this with the \a Scalar type casted to
|
||||
* \a NewScalar.
|
||||
@@ -191,7 +188,7 @@ MatrixBase<Derived>::real() const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename NewType>
|
||||
inline const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
|
||||
MatrixBase<Derived>::cast() const
|
||||
{
|
||||
return derived();
|
||||
@@ -199,7 +196,7 @@ MatrixBase<Derived>::cast() const
|
||||
|
||||
/** \relates MatrixBase */
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::ScalarMultipleReturnType
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ScalarMultipleReturnType
|
||||
MatrixBase<Derived>::operator*(const Scalar& scalar) const
|
||||
{
|
||||
return CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived>
|
||||
@@ -208,7 +205,7 @@ MatrixBase<Derived>::operator*(const Scalar& scalar) const
|
||||
|
||||
/** \relates MatrixBase */
|
||||
template<typename Derived>
|
||||
inline const CwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
|
||||
MatrixBase<Derived>::operator/(const Scalar& scalar) const
|
||||
{
|
||||
return CwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived>
|
||||
@@ -216,14 +213,14 @@ MatrixBase<Derived>::operator/(const Scalar& scalar) const
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline Derived&
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
MatrixBase<Derived>::operator*=(const Scalar& other)
|
||||
{
|
||||
return *this = *this * other;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline Derived&
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
MatrixBase<Derived>::operator/=(const Scalar& other)
|
||||
{
|
||||
return *this = *this / other;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_DIAGONALMATRIX_H
|
||||
|
||||
/** \class DiagonalMatrix
|
||||
* \nonstableyet
|
||||
*
|
||||
* \brief Expression of a diagonal matrix
|
||||
*
|
||||
@@ -61,11 +62,21 @@ class DiagonalMatrix : ei_no_assignment_operator,
|
||||
public:
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix)
|
||||
typedef CoeffsVectorType _CoeffsVectorType;
|
||||
|
||||
// needed to evaluate a DiagonalMatrix<Xpr> to a DiagonalMatrix<NestByValue<Vector> >
|
||||
template<typename OtherCoeffsVectorType>
|
||||
inline DiagonalMatrix(const DiagonalMatrix<OtherCoeffsVectorType>& other) : m_coeffs(other.diagonal())
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherCoeffsVectorType);
|
||||
ei_assert(m_coeffs.size() > 0);
|
||||
}
|
||||
|
||||
inline DiagonalMatrix(const CoeffsVectorType& coeffs) : m_coeffs(coeffs)
|
||||
{
|
||||
ei_assert(CoeffsVectorType::IsVectorAtCompileTime
|
||||
&& coeffs.size() > 0);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
|
||||
ei_assert(coeffs.size() > 0);
|
||||
}
|
||||
|
||||
inline int rows() const { return m_coeffs.size(); }
|
||||
@@ -76,11 +87,14 @@ class DiagonalMatrix : ei_no_assignment_operator,
|
||||
return row == col ? m_coeffs.coeff(row) : static_cast<Scalar>(0);
|
||||
}
|
||||
|
||||
inline const CoeffsVectorType& diagonal() const { return m_coeffs; }
|
||||
|
||||
protected:
|
||||
const typename CoeffsVectorType::Nested m_coeffs;
|
||||
};
|
||||
|
||||
/** \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
|
||||
/** \nonstableyet
|
||||
* \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
@@ -98,7 +112,8 @@ MatrixBase<Derived>::asDiagonal() const
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \returns true if *this is approximately equal to a diagonal matrix,
|
||||
/** \nonstableyet
|
||||
* \returns true if *this is approximately equal to a diagonal matrix,
|
||||
* within the precision given by \a prec.
|
||||
*
|
||||
* Example: \include MatrixBase_isDiagonal.cpp
|
||||
@@ -112,13 +127,13 @@ bool MatrixBase<Derived>::isDiagonal
|
||||
{
|
||||
if(cols() != rows()) return false;
|
||||
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
{
|
||||
RealScalar absOnDiagonal = ei_abs(coeff(j,j));
|
||||
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
|
||||
}
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i < j; i++)
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i < j; ++i)
|
||||
{
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
|
||||
if(!ei_isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,12 +26,31 @@
|
||||
#ifndef EIGEN_DIAGONALPRODUCT_H
|
||||
#define EIGEN_DIAGONALPRODUCT_H
|
||||
|
||||
/** \internal Specialization of ei_nested for DiagonalMatrix.
|
||||
* Unlike ei_nested, if the argument is a DiagonalMatrix and if it must be evaluated,
|
||||
* then it evaluated to a DiagonalMatrix having its own argument evaluated.
|
||||
*/
|
||||
template<typename T, int N> struct ei_nested_diagonal : ei_nested<T,N> {};
|
||||
template<typename T, int N> struct ei_nested_diagonal<DiagonalMatrix<T>,N >
|
||||
: ei_nested<DiagonalMatrix<T>, N, DiagonalMatrix<NestByValue<typename ei_plain_matrix_type<T>::type> > >
|
||||
{};
|
||||
|
||||
// specialization of ProductReturnType
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ProductReturnType<Lhs,Rhs,DiagonalProduct>
|
||||
{
|
||||
typedef typename ei_nested_diagonal<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
|
||||
typedef typename ei_nested_diagonal<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
|
||||
|
||||
typedef Product<LhsNested, RhsNested, DiagonalProduct> Type;
|
||||
};
|
||||
|
||||
template<typename LhsNested, typename RhsNested>
|
||||
struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
|
||||
{
|
||||
// clean the nested types:
|
||||
typedef typename ei_unconst<typename ei_unref<LhsNested>::type>::type _LhsNested;
|
||||
typedef typename ei_unconst<typename ei_unref<RhsNested>::type>::type _RhsNested;
|
||||
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
|
||||
typedef typename ei_cleantype<RhsNested>::type _RhsNested;
|
||||
typedef typename _LhsNested::Scalar Scalar;
|
||||
|
||||
enum {
|
||||
@@ -54,7 +73,7 @@ struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
|
||||
RemovedBits = ~((RhsFlags & RowMajorBit) && (!CanVectorizeLhs) ? 0 : RowMajorBit),
|
||||
|
||||
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
|
||||
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0),
|
||||
| (((CanVectorizeLhs&&RhsIsDiagonal) || (CanVectorizeRhs&&LhsIsDiagonal)) ? PacketAccessBit : 0),
|
||||
|
||||
CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost
|
||||
};
|
||||
@@ -95,12 +114,10 @@ template<typename LhsNested, typename RhsNested> class Product<LhsNested, RhsNes
|
||||
{
|
||||
if (RhsIsDiagonal)
|
||||
{
|
||||
ei_assert((_LhsNested::Flags&RowMajorBit)==0);
|
||||
return ei_pmul(m_lhs.template packet<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert(_RhsNested::Flags&RowMajorBit);
|
||||
return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packet<LoadMode>(row, col));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -153,9 +153,10 @@ struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
static Scalar run(const Derived1& v1, const Derived2& v2)
|
||||
{
|
||||
ei_assert(v1.size()>0 && "you are using a non initialized vector");
|
||||
Scalar res;
|
||||
res = v1.coeff(0) * ei_conj(v2.coeff(0));
|
||||
for(int i = 1; i < v1.size(); i++)
|
||||
for(int i = 1; i < v1.size(); ++i)
|
||||
res += v1.coeff(i) * ei_conj(v2.coeff(i));
|
||||
return res;
|
||||
}
|
||||
@@ -210,7 +211,7 @@ struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
|
||||
}
|
||||
|
||||
// do the remainder of the vector
|
||||
for(int index = alignedSize; index < size; index++)
|
||||
for(int index = alignedSize; index < size; ++index)
|
||||
{
|
||||
res += v1.coeff(index) * v2.coeff(index);
|
||||
}
|
||||
@@ -247,51 +248,45 @@ struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \note If the scalar type is complex numbers, then this function returns the hermitian
|
||||
* (sesquilinear) dot product, linear in the first variable and anti-linear in the
|
||||
* (sesquilinear) dot product, linear in the first variable and conjugate-linear in the
|
||||
* second variable.
|
||||
*
|
||||
* \sa norm2(), norm()
|
||||
* \sa squaredNorm(), norm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename ei_traits<Derived>::Scalar
|
||||
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
typedef typename Derived::Nested Nested;
|
||||
typedef typename OtherDerived::Nested OtherNested;
|
||||
typedef typename ei_unref<Nested>::type _Nested;
|
||||
typedef typename ei_unref<OtherNested>::type _OtherNested;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_Nested);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_OtherNested);
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(_Nested,_OtherNested);
|
||||
ei_assert(size() == other.size());
|
||||
|
||||
return ei_dot_impl<_Nested, _OtherNested>::run(derived(), other.derived());
|
||||
return ei_dot_impl<Derived, OtherDerived>::run(derived(), other.derived());
|
||||
}
|
||||
|
||||
/** \returns the squared norm of *this, i.e. the dot product of *this with itself.
|
||||
*
|
||||
* \only_for_vectors
|
||||
/** \returns the squared \em l2 norm of *this, i.e., for vectors, the dot product of *this with itself.
|
||||
*
|
||||
* \sa dot(), norm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm2() const
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
|
||||
{
|
||||
return ei_real(dot(*this));
|
||||
return ei_real((*this).cwise().abs2().sum());
|
||||
}
|
||||
|
||||
/** \returns the norm of *this, i.e. the square root of the dot product of *this with itself.
|
||||
/** \returns the \em l2 norm of *this, i.e., for vectors, the square root of the dot product of *this with itself.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa dot(), norm2()
|
||||
* \sa dot(), squaredNorm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
|
||||
{
|
||||
return ei_sqrt(norm2());
|
||||
return ei_sqrt(squaredNorm());
|
||||
}
|
||||
|
||||
/** \returns an expression of the quotient of *this by its own norm.
|
||||
@@ -301,7 +296,7 @@ inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<
|
||||
* \sa norm(), normalize()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::EvalType
|
||||
inline const typename MatrixBase<Derived>::PlainMatrixType
|
||||
MatrixBase<Derived>::normalized() const
|
||||
{
|
||||
typedef typename ei_nested<Derived>::type Nested;
|
||||
@@ -335,7 +330,7 @@ bool MatrixBase<Derived>::isOrthogonal
|
||||
{
|
||||
typename ei_nested<Derived,2>::type nested(derived());
|
||||
typename ei_nested<OtherDerived,2>::type otherNested(other.derived());
|
||||
return ei_abs2(nested.dot(otherNested)) <= prec * prec * nested.norm2() * otherNested.norm2();
|
||||
return ei_abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
|
||||
}
|
||||
|
||||
/** \returns true if *this is approximately an unitary matrix,
|
||||
@@ -353,11 +348,11 @@ template<typename Derived>
|
||||
bool MatrixBase<Derived>::isUnitary(RealScalar prec) const
|
||||
{
|
||||
typename Derived::Nested nested(derived());
|
||||
for(int i = 0; i < cols(); i++)
|
||||
for(int i = 0; i < cols(); ++i)
|
||||
{
|
||||
if(!ei_isApprox(nested.col(i).norm2(), static_cast<Scalar>(1), prec))
|
||||
if(!ei_isApprox(nested.col(i).squaredNorm(), static_cast<Scalar>(1), prec))
|
||||
return false;
|
||||
for(int j = 0; j < i; j++)
|
||||
for(int j = 0; j < i; ++j)
|
||||
if(!ei_isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast<Scalar>(1), prec))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -40,18 +40,9 @@
|
||||
* \sa MatrixBase::flagged()
|
||||
*/
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
struct ei_traits<Flagged<ExpressionType, Added, Removed> >
|
||||
struct ei_traits<Flagged<ExpressionType, Added, Removed> > : ei_traits<ExpressionType>
|
||||
{
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = ExpressionType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
|
||||
Flags = (ExpressionType::Flags | Added) & ~Removed,
|
||||
CoeffReadCost = ExpressionType::CoeffReadCost
|
||||
};
|
||||
enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
|
||||
};
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
* \sa class CwiseBinaryOp, MatrixBase::operator+, class PartialRedux, MatrixBase::sum()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_sum_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_padd(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -52,9 +52,9 @@ struct ei_functor_traits<ei_scalar_sum_op<Scalar> > {
|
||||
* \sa class CwiseBinaryOp, Cwise::operator*(), class PartialRedux, MatrixBase::redux()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_product_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return a * b; }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a * b; }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_pmul(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -71,9 +71,9 @@ struct ei_functor_traits<ei_scalar_product_op<Scalar> > {
|
||||
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class PartialRedux, MatrixBase::minCoeff()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_min_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::min(a, b); }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::min(a, b); }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_pmin(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -90,9 +90,9 @@ struct ei_functor_traits<ei_scalar_min_op<Scalar> > {
|
||||
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class PartialRedux, MatrixBase::maxCoeff()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_max_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::max(a, b); }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::max(a, b); }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_pmax(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -112,9 +112,9 @@ struct ei_functor_traits<ei_scalar_max_op<Scalar> > {
|
||||
* \sa class CwiseBinaryOp, MatrixBase::operator-
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_difference_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_psub(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -131,9 +131,9 @@ struct ei_functor_traits<ei_scalar_difference_op<Scalar> > {
|
||||
* \sa class CwiseBinaryOp, Cwise::operator/()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_quotient_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
|
||||
{ return ei_pdiv(a,b); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -155,7 +155,7 @@ struct ei_functor_traits<ei_scalar_quotient_op<Scalar> > {
|
||||
* \sa class CwiseUnaryOp, MatrixBase::operator-
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_opposite_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a) const { return -a; }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_opposite_op<Scalar> >
|
||||
@@ -168,7 +168,7 @@ struct ei_functor_traits<ei_scalar_opposite_op<Scalar> >
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_abs_op EIGEN_EMPTY_STRUCT {
|
||||
typedef typename NumTraits<Scalar>::Real result_type;
|
||||
inline const result_type operator() (const Scalar& a) const { return ei_abs(a); }
|
||||
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return ei_abs(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_abs_op<Scalar> >
|
||||
@@ -186,9 +186,9 @@ struct ei_functor_traits<ei_scalar_abs_op<Scalar> >
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_abs2_op EIGEN_EMPTY_STRUCT {
|
||||
typedef typename NumTraits<Scalar>::Real result_type;
|
||||
inline const result_type operator() (const Scalar& a) const { return ei_abs2(a); }
|
||||
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return ei_abs2(a); }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_pmul(a,a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -201,9 +201,9 @@ struct ei_functor_traits<ei_scalar_abs2_op<Scalar> >
|
||||
* \sa class CwiseUnaryOp, MatrixBase::conjugate()
|
||||
*/
|
||||
template<typename Scalar> struct ei_scalar_conjugate_op EIGEN_EMPTY_STRUCT {
|
||||
inline const Scalar operator() (const Scalar& a) const { return ei_conj(a); }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return ei_conj(a); }
|
||||
template<typename PacketScalar>
|
||||
inline const PacketScalar packetOp(const PacketScalar& a) const { return a; }
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const { return a; }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_conjugate_op<Scalar> >
|
||||
@@ -222,7 +222,7 @@ struct ei_functor_traits<ei_scalar_conjugate_op<Scalar> >
|
||||
template<typename Scalar, typename NewType>
|
||||
struct ei_scalar_cast_op EIGEN_EMPTY_STRUCT {
|
||||
typedef NewType result_type;
|
||||
inline const NewType operator() (const Scalar& a) const { return static_cast<NewType>(a); }
|
||||
EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return static_cast<NewType>(a); }
|
||||
};
|
||||
template<typename Scalar, typename NewType>
|
||||
struct ei_functor_traits<ei_scalar_cast_op<Scalar,NewType> >
|
||||
@@ -236,11 +236,25 @@ struct ei_functor_traits<ei_scalar_cast_op<Scalar,NewType> >
|
||||
template<typename Scalar>
|
||||
struct ei_scalar_real_op EIGEN_EMPTY_STRUCT {
|
||||
typedef typename NumTraits<Scalar>::Real result_type;
|
||||
inline result_type operator() (const Scalar& a) const { return ei_real(a); }
|
||||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return ei_real(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_real_op<Scalar> >
|
||||
{ enum { Cost = 0, PacketAccess = false }; };
|
||||
{ enum { Cost = 0, PacketAccess = false }; };
|
||||
|
||||
/** \internal
|
||||
* \brief Template functor to extract the imaginary part of a complex
|
||||
*
|
||||
* \sa class CwiseUnaryOp, MatrixBase::imag()
|
||||
*/
|
||||
template<typename Scalar>
|
||||
struct ei_scalar_imag_op EIGEN_EMPTY_STRUCT {
|
||||
typedef typename NumTraits<Scalar>::Real result_type;
|
||||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return ei_imag(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_imag_op<Scalar> >
|
||||
{ enum { Cost = 0, PacketAccess = false }; };
|
||||
|
||||
/** \internal
|
||||
* \brief Template functor to multiply a scalar by a fixed other one
|
||||
@@ -259,10 +273,10 @@ template<typename Scalar>
|
||||
struct ei_scalar_multiple_op {
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
// FIXME default copy constructors seems bugged with std::complex<>
|
||||
inline ei_scalar_multiple_op(const ei_scalar_multiple_op& other) : m_other(other.m_other) { }
|
||||
inline ei_scalar_multiple_op(const Scalar& other) : m_other(other) { }
|
||||
inline Scalar operator() (const Scalar& a) const { return a * m_other; }
|
||||
inline const PacketScalar packetOp(const PacketScalar& a) const
|
||||
EIGEN_STRONG_INLINE ei_scalar_multiple_op(const ei_scalar_multiple_op& other) : m_other(other.m_other) { }
|
||||
EIGEN_STRONG_INLINE ei_scalar_multiple_op(const Scalar& other) : m_other(other) { }
|
||||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_pmul(a, ei_pset1(m_other)); }
|
||||
const Scalar m_other;
|
||||
};
|
||||
@@ -274,10 +288,10 @@ template<typename Scalar, bool HasFloatingPoint>
|
||||
struct ei_scalar_quotient1_impl {
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
// FIXME default copy constructors seems bugged with std::complex<>
|
||||
inline ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
|
||||
inline ei_scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
|
||||
inline Scalar operator() (const Scalar& a) const { return a * m_other; }
|
||||
inline const PacketScalar packetOp(const PacketScalar& a) const
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
|
||||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
|
||||
{ return ei_pmul(a, ei_pset1(m_other)); }
|
||||
const Scalar m_other;
|
||||
};
|
||||
@@ -288,9 +302,9 @@ struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,true> >
|
||||
template<typename Scalar>
|
||||
struct ei_scalar_quotient1_impl<Scalar,false> {
|
||||
// FIXME default copy constructors seems bugged with std::complex<>
|
||||
inline ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
|
||||
inline ei_scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
|
||||
inline Scalar operator() (const Scalar& a) const { return a / m_other; }
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
|
||||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
|
||||
const Scalar m_other;
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -307,7 +321,7 @@ struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,false> >
|
||||
*/
|
||||
template<typename Scalar>
|
||||
struct ei_scalar_quotient1_op : ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint > {
|
||||
inline ei_scalar_quotient1_op(const Scalar& other)
|
||||
EIGEN_STRONG_INLINE ei_scalar_quotient1_op(const Scalar& other)
|
||||
: ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint >(other) {}
|
||||
};
|
||||
|
||||
@@ -316,10 +330,10 @@ struct ei_scalar_quotient1_op : ei_scalar_quotient1_impl<Scalar, NumTraits<Scala
|
||||
template<typename Scalar>
|
||||
struct ei_scalar_constant_op {
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
inline ei_scalar_constant_op(const ei_scalar_constant_op& other) : m_other(other.m_other) { }
|
||||
inline ei_scalar_constant_op(const Scalar& other) : m_other(other) { }
|
||||
inline const Scalar operator() (int, int = 0) const { return m_other; }
|
||||
inline const PacketScalar packetOp() const { return ei_pset1(m_other); }
|
||||
EIGEN_STRONG_INLINE ei_scalar_constant_op(const ei_scalar_constant_op& other) : m_other(other.m_other) { }
|
||||
EIGEN_STRONG_INLINE ei_scalar_constant_op(const Scalar& other) : m_other(other) { }
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (int, int = 0) const { return m_other; }
|
||||
EIGEN_STRONG_INLINE const PacketScalar packetOp() const { return ei_pset1(m_other); }
|
||||
const Scalar m_other;
|
||||
};
|
||||
template<typename Scalar>
|
||||
@@ -327,18 +341,28 @@ struct ei_functor_traits<ei_scalar_constant_op<Scalar> >
|
||||
{ enum { Cost = 1, PacketAccess = ei_packet_traits<Scalar>::size>1, IsRepeatable = true }; };
|
||||
|
||||
template<typename Scalar> struct ei_scalar_identity_op EIGEN_EMPTY_STRUCT {
|
||||
inline ei_scalar_identity_op(void) {}
|
||||
inline const Scalar operator() (int row, int col) const { return row==col ? Scalar(1) : Scalar(0); }
|
||||
EIGEN_STRONG_INLINE ei_scalar_identity_op(void) {}
|
||||
EIGEN_STRONG_INLINE const Scalar operator() (int row, int col) const { return row==col ? Scalar(1) : Scalar(0); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct ei_functor_traits<ei_scalar_identity_op<Scalar> >
|
||||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
|
||||
|
||||
// NOTE quick hack:
|
||||
// allow to add new functors and specializations of ei_functor_traits from outside Eigen.
|
||||
// this macro is really needed because ei_functor_traits must be specialized after it is declared but before it is used...
|
||||
#ifdef EIGEN_FUNCTORS_PLUGIN
|
||||
#include EIGEN_FUNCTORS_PLUGIN
|
||||
#endif
|
||||
|
||||
// all functors allow linear access, except ei_scalar_identity_op. So we fix here a quick meta
|
||||
// to indicate whether a functor allows linear access, just always answering 'yes' except for
|
||||
// ei_scalar_identity_op.
|
||||
template<typename Functor> struct ei_functor_has_linear_access { enum { ret = 1 }; };
|
||||
template<typename Scalar> struct ei_functor_has_linear_access<ei_scalar_identity_op<Scalar> > { enum { ret = 0 }; };
|
||||
|
||||
// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
|
||||
// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
|
||||
template<typename Functor> struct ei_functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
|
||||
template<typename Scalar> struct ei_functor_allows_mixing_real_and_complex<ei_scalar_product_op<Scalar> > { enum { ret = 1 }; };
|
||||
|
||||
#endif // EIGEN_FUNCTORS_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -176,19 +176,19 @@ struct ei_fuzzy_selector<Derived,OtherDerived,true>
|
||||
typedef typename Derived::RealScalar RealScalar;
|
||||
static bool isApprox(const Derived& self, const OtherDerived& other, RealScalar prec)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived);
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
ei_assert(self.size() == other.size());
|
||||
return((self - other).norm2() <= std::min(self.norm2(), other.norm2()) * prec * prec);
|
||||
return((self - other).squaredNorm() <= std::min(self.squaredNorm(), other.squaredNorm()) * prec * prec);
|
||||
}
|
||||
static bool isMuchSmallerThan(const Derived& self, const RealScalar& other, RealScalar prec)
|
||||
{
|
||||
return(self.norm2() <= ei_abs2(other * prec));
|
||||
return(self.squaredNorm() <= ei_abs2(other * prec));
|
||||
}
|
||||
static bool isMuchSmallerThan(const Derived& self, const OtherDerived& other, RealScalar prec)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived);
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
ei_assert(self.size() == other.size());
|
||||
return(self.norm2() <= other.norm2() * prec * prec);
|
||||
return(self.squaredNorm() <= other.squaredNorm() * prec * prec);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -198,32 +198,32 @@ struct ei_fuzzy_selector<Derived,OtherDerived,false>
|
||||
typedef typename Derived::RealScalar RealScalar;
|
||||
static bool isApprox(const Derived& self, const OtherDerived& other, RealScalar prec)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived);
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
|
||||
ei_assert(self.rows() == other.rows() && self.cols() == other.cols());
|
||||
typename Derived::Nested nested(self);
|
||||
typename OtherDerived::Nested otherNested(other);
|
||||
for(int i = 0; i < self.cols(); i++)
|
||||
if((nested.col(i) - otherNested.col(i)).norm2()
|
||||
> std::min(nested.col(i).norm2(), otherNested.col(i).norm2()) * prec * prec)
|
||||
for(int i = 0; i < self.cols(); ++i)
|
||||
if((nested.col(i) - otherNested.col(i)).squaredNorm()
|
||||
> std::min(nested.col(i).squaredNorm(), otherNested.col(i).squaredNorm()) * prec * prec)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
static bool isMuchSmallerThan(const Derived& self, const RealScalar& other, RealScalar prec)
|
||||
{
|
||||
typename Derived::Nested nested(self);
|
||||
for(int i = 0; i < self.cols(); i++)
|
||||
if(nested.col(i).norm2() > ei_abs2(other * prec))
|
||||
for(int i = 0; i < self.cols(); ++i)
|
||||
if(nested.col(i).squaredNorm() > ei_abs2(other * prec))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
static bool isMuchSmallerThan(const Derived& self, const OtherDerived& other, RealScalar prec)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived);
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
|
||||
ei_assert(self.rows() == other.rows() && self.cols() == other.cols());
|
||||
typename Derived::Nested nested(self);
|
||||
typename OtherDerived::Nested otherNested(other);
|
||||
for(int i = 0; i < self.cols(); i++)
|
||||
if(nested.col(i).norm2() > otherNested.col(i).norm2() * prec * prec)
|
||||
for(int i = 0; i < self.cols(); ++i)
|
||||
if(nested.col(i).squaredNorm() > otherNested.col(i).squaredNorm() * prec * prec)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
@@ -18,7 +19,7 @@
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
@@ -57,7 +58,7 @@ struct IOFormat
|
||||
coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
|
||||
{
|
||||
rowSpacer = "";
|
||||
int i=matSuffix.length()-1;
|
||||
int i = int(matSuffix.length())-1;
|
||||
while (i>=0 && matSuffix[i]!='\n')
|
||||
{
|
||||
rowSpacer += ' ';
|
||||
@@ -80,7 +81,7 @@ struct IOFormat
|
||||
* This class represents an expression with stream operators controlled by a given IOFormat.
|
||||
* It is the return type of MatrixBase::format()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
*
|
||||
* See class IOFormat for some examples.
|
||||
*
|
||||
* \sa MatrixBase::format(), class IOFormat
|
||||
@@ -121,33 +122,33 @@ MatrixBase<Derived>::format(const IOFormat& fmt) const
|
||||
/** \internal
|
||||
* print the matrix \a _m to the output stream \a s using the output format \a fmt */
|
||||
template<typename Derived>
|
||||
std::ostream & ei_print_matrix(std::ostream & s, const MatrixBase<Derived> & _m,
|
||||
const IOFormat& fmt = IOFormat())
|
||||
std::ostream & ei_print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
|
||||
{
|
||||
const typename Derived::Nested m = _m;
|
||||
|
||||
int width = 0;
|
||||
if (fmt.flags & AlignCols)
|
||||
{
|
||||
// compute the largest width
|
||||
for(int j = 1; j < m.cols(); j++)
|
||||
for(int i = 0; i < m.rows(); i++)
|
||||
for(int j = 1; j < m.cols(); ++j)
|
||||
for(int i = 0; i < m.rows(); ++i)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr.precision(fmt.precision);
|
||||
sstr << m.coeff(i,j);
|
||||
width = std::max<int>(width, sstr.str().length());
|
||||
width = std::max<int>(width, int(sstr.str().length()));
|
||||
}
|
||||
}
|
||||
s.precision(fmt.precision);
|
||||
s << fmt.matPrefix;
|
||||
for(int i = 0; i < m.rows(); i++)
|
||||
for(int i = 0; i < m.rows(); ++i)
|
||||
{
|
||||
if (i)
|
||||
s << fmt.rowSpacer;
|
||||
s << fmt.rowPrefix;
|
||||
if(width) s.width(width);
|
||||
s << m.coeff(i, 0);
|
||||
for(int j = 1; j < m.cols(); j++)
|
||||
for(int j = 1; j < m.cols(); ++j)
|
||||
{
|
||||
s << fmt.coeffSeparator;
|
||||
if (width) s.width(width);
|
||||
@@ -163,8 +164,12 @@ std::ostream & ei_print_matrix(std::ostream & s, const MatrixBase<Derived> & _m,
|
||||
|
||||
/** \relates MatrixBase
|
||||
*
|
||||
* Outputs the matrix, laid out as an array as usual, to the given stream.
|
||||
* You can control the way the matrix is printed using MatrixBase::format().
|
||||
* Outputs the matrix, to the given stream.
|
||||
*
|
||||
* If you wish to print the matrix with a format different than the default, use MatrixBase::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 MatrixBase::format()
|
||||
*/
|
||||
@@ -173,7 +178,7 @@ std::ostream & operator <<
|
||||
(std::ostream & s,
|
||||
const MatrixBase<Derived> & m)
|
||||
{
|
||||
return ei_print_matrix(s, m.eval());
|
||||
return ei_print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT);
|
||||
}
|
||||
|
||||
#endif // EIGEN_IO_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -40,9 +40,9 @@
|
||||
* 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.
|
||||
*
|
||||
* This class is the return type of Matrix::map() but can also be used directly.
|
||||
* This class is the return type of Matrix::Map() but can also be used directly.
|
||||
*
|
||||
* \sa Matrix::map()
|
||||
* \sa Matrix::Map()
|
||||
*/
|
||||
template<typename MatrixType, int _PacketAccess>
|
||||
struct ei_traits<Map<MatrixType, _PacketAccess> > : public ei_traits<MatrixType>
|
||||
@@ -66,12 +66,9 @@ template<typename MatrixType, int PacketAccess> class Map
|
||||
|
||||
inline int stride() const { return this->innerSize(); }
|
||||
|
||||
AlignedDerivedType forceAligned()
|
||||
AlignedDerivedType _convertToForceAligned()
|
||||
{
|
||||
if (PacketAccess==ForceAligned)
|
||||
return *this;
|
||||
else
|
||||
return Map<MatrixType,ForceAligned>(Base::m_data, Base::m_rows.value(), Base::m_cols.value());
|
||||
return Map<MatrixType,ForceAligned>(Base::m_data, Base::m_rows.value(), Base::m_cols.value());
|
||||
}
|
||||
|
||||
inline Map(const Scalar* data) : Base(data) {}
|
||||
@@ -85,12 +82,12 @@ template<typename MatrixType, int PacketAccess> class Map
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(rows);
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(cols);
|
||||
ei_assert(rows == this->rows());
|
||||
ei_assert(rows == this->cols());
|
||||
ei_assert(cols == this->cols());
|
||||
}
|
||||
|
||||
inline void resize(int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(MatrixType);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(MatrixType)
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(size);
|
||||
ei_assert(size == this->size());
|
||||
}
|
||||
@@ -102,17 +99,13 @@ template<typename MatrixType, int PacketAccess> class Map
|
||||
* Only for fixed-size matrices and vectors.
|
||||
* \param data The array of data to copy
|
||||
*
|
||||
* For dynamic-size matrices and vectors, see the variants taking additional int parameters
|
||||
* for the dimensions.
|
||||
*
|
||||
* \sa Matrix(const Scalar *, int), Matrix(const Scalar *, int, int),
|
||||
* Matrix::map(const Scalar *)
|
||||
* \sa Matrix::Map(const Scalar *)
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
inline Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
|
||||
::Matrix(const Scalar *data)
|
||||
{
|
||||
*this = Map<Matrix>(data);
|
||||
_set_noalias(Eigen::Map<Matrix>(data));
|
||||
}
|
||||
|
||||
#endif // EIGEN_MAP_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -53,7 +53,7 @@ template<typename Derived> class MapBase
|
||||
ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
|
||||
SizeAtCompileTime = Base::SizeAtCompileTime
|
||||
};
|
||||
|
||||
|
||||
typedef typename ei_traits<Derived>::AlignedDerivedType AlignedDerivedType;
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
typedef typename Base::PacketScalar PacketScalar;
|
||||
@@ -63,10 +63,22 @@ template<typename Derived> class MapBase
|
||||
inline int cols() const { return m_cols.value(); }
|
||||
|
||||
inline int stride() const { return derived().stride(); }
|
||||
inline const Scalar* data() const { return m_data; }
|
||||
|
||||
template<bool IsForceAligned,typename Dummy> struct force_aligned_impl {
|
||||
AlignedDerivedType static run(MapBase& a) { return a.derived(); }
|
||||
};
|
||||
|
||||
template<typename Dummy> struct force_aligned_impl<false,Dummy> {
|
||||
AlignedDerivedType static run(MapBase& a) { return a.derived()._convertToForceAligned(); }
|
||||
};
|
||||
|
||||
/** \returns an expression equivalent to \c *this but having the \c PacketAccess constant
|
||||
* set to \c ForceAligned. Must be reimplemented by the derived class. */
|
||||
AlignedDerivedType forceAligned() { return derived().forceAligned(); }
|
||||
AlignedDerivedType forceAligned()
|
||||
{
|
||||
return force_aligned_impl<int(PacketAccess)==int(ForceAligned),Derived>::run(*this);
|
||||
}
|
||||
|
||||
inline const Scalar& coeff(int row, int col) const
|
||||
{
|
||||
@@ -83,7 +95,7 @@ template<typename Derived> class MapBase
|
||||
else // column-major
|
||||
return const_cast<Scalar*>(m_data)[row + col * stride()];
|
||||
}
|
||||
|
||||
|
||||
inline const Scalar coeff(int index) const
|
||||
{
|
||||
ei_assert(Derived::IsVectorAtCompileTime || (ei_traits<Derived>::Flags & LinearAccessBit));
|
||||
@@ -95,7 +107,11 @@ template<typename Derived> class MapBase
|
||||
|
||||
inline Scalar& coeffRef(int index)
|
||||
{
|
||||
return *const_cast<Scalar*>(m_data + index);
|
||||
ei_assert(Derived::IsVectorAtCompileTime || (ei_traits<Derived>::Flags & LinearAccessBit));
|
||||
if ( ((RowsAtCompileTime == 1) == IsRowMajor) )
|
||||
return const_cast<Scalar*>(m_data)[index];
|
||||
else
|
||||
return const_cast<Scalar*>(m_data)[index*stride()];
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
@@ -138,28 +154,42 @@ template<typename Derived> class MapBase
|
||||
m_cols(ColsAtCompileTime == Dynamic ? size : ColsAtCompileTime)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
ei_assert(size > 0);
|
||||
ei_assert(size > 0 || data == 0);
|
||||
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
|
||||
}
|
||||
|
||||
inline MapBase(const Scalar* data, int rows, int cols)
|
||||
: m_data(data), m_rows(rows), m_cols(cols)
|
||||
{
|
||||
ei_assert(rows > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
ei_assert( (data == 0)
|
||||
|| ( rows > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
|
||||
}
|
||||
|
||||
Derived& operator=(const MapBase& other)
|
||||
{
|
||||
return Base::operator=(other);
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return Base::operator=(other);
|
||||
}
|
||||
|
||||
using Base::operator*=;
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator+=(const MatrixBase<OtherDerived>& other)
|
||||
{ return derived() = forceAligned() + other; }
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& operator-=(const MatrixBase<OtherDerived>& other)
|
||||
{ return derived() = forceAligned() - other; }
|
||||
|
||||
Derived& operator*=(const Scalar& other)
|
||||
{ return derived() = forceAligned() * other; }
|
||||
|
||||
|
||||
Derived& operator/=(const Scalar& other)
|
||||
{ return derived() = forceAligned() / other; }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_MATHFUNCTIONS_H
|
||||
|
||||
template<typename T> inline typename NumTraits<T>::Real precision();
|
||||
template<typename T> inline typename NumTraits<T>::Real machine_epsilon();
|
||||
template<typename T> inline T ei_random(T a, T b);
|
||||
template<typename T> inline T ei_random();
|
||||
template<typename T> inline T ei_random_amplitude()
|
||||
@@ -34,11 +35,22 @@ template<typename T> inline T ei_random_amplitude()
|
||||
else return static_cast<T>(10);
|
||||
}
|
||||
|
||||
template<typename T> inline T ei_hypot(T x, T y)
|
||||
{
|
||||
T _x = ei_abs(x);
|
||||
T _y = ei_abs(y);
|
||||
T p = std::max(_x, _y);
|
||||
T q = std::min(_x, _y);
|
||||
T qp = q/p;
|
||||
return p * ei_sqrt(T(1) + qp*qp);
|
||||
}
|
||||
|
||||
/**************
|
||||
*** int ***
|
||||
**************/
|
||||
|
||||
template<> inline int precision<int>() { return 0; }
|
||||
template<> inline int machine_epsilon<int>() { return 0; }
|
||||
inline int ei_real(int x) { return x; }
|
||||
inline int ei_imag(int) { return 0; }
|
||||
inline int ei_conj(int x) { return x; }
|
||||
@@ -51,7 +63,7 @@ inline int ei_sin(int) { ei_assert(false); return 0; }
|
||||
inline int ei_cos(int) { ei_assert(false); return 0; }
|
||||
|
||||
#if EIGEN_GNUC_AT_LEAST(4,3)
|
||||
inline int ei_pow(int x, int y) { return std::pow(x, y); }
|
||||
inline int ei_pow(int x, int y) { return int(std::pow(x, y)); }
|
||||
#else
|
||||
inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
|
||||
#endif
|
||||
@@ -83,6 +95,7 @@ inline bool ei_isApproxOrLessThan(int a, int b, int = precision<int>())
|
||||
**************/
|
||||
|
||||
template<> inline float precision<float>() { return 1e-5f; }
|
||||
template<> inline float machine_epsilon<float>() { return 1.192e-07f; }
|
||||
inline float ei_real(float x) { return x; }
|
||||
inline float ei_imag(float) { return 0.f; }
|
||||
inline float ei_conj(float x) { return x; }
|
||||
@@ -101,9 +114,9 @@ template<> inline float ei_random(float a, float b)
|
||||
int i;
|
||||
do { i = ei_random<int>(256*int(a),256*int(b));
|
||||
} while(i==0);
|
||||
return i/256.f;
|
||||
return float(i)/256.f;
|
||||
#else
|
||||
return a + (b-a) * std::rand() / RAND_MAX;
|
||||
return a + (b-a) * float(std::rand()) / float(RAND_MAX);
|
||||
#endif
|
||||
}
|
||||
template<> inline float ei_random()
|
||||
@@ -128,6 +141,8 @@ inline bool ei_isApproxOrLessThan(float a, float b, float prec = precision<float
|
||||
**************/
|
||||
|
||||
template<> inline double precision<double>() { return 1e-11; }
|
||||
template<> inline double machine_epsilon<double>() { return 2.220e-16; }
|
||||
|
||||
inline double ei_real(double x) { return x; }
|
||||
inline double ei_imag(double) { return 0.; }
|
||||
inline double ei_conj(double x) { return x; }
|
||||
@@ -138,7 +153,7 @@ inline double ei_exp(double x) { return std::exp(x); }
|
||||
inline double ei_log(double x) { return std::log(x); }
|
||||
inline double ei_sin(double x) { return std::sin(x); }
|
||||
inline double ei_cos(double x) { return std::cos(x); }
|
||||
inline double ei_pow(double x, double y) { return std::pow(x, y); }
|
||||
inline double ei_pow(double x, double y) { return std::pow(x, y); }
|
||||
|
||||
template<> inline double ei_random(double a, double b)
|
||||
{
|
||||
@@ -173,6 +188,7 @@ inline bool ei_isApproxOrLessThan(double a, double b, double prec = precision<do
|
||||
*********************/
|
||||
|
||||
template<> inline float precision<std::complex<float> >() { return precision<float>(); }
|
||||
template<> inline float machine_epsilon<std::complex<float> >() { return machine_epsilon<float>(); }
|
||||
inline float ei_real(const std::complex<float>& x) { return std::real(x); }
|
||||
inline float ei_imag(const std::complex<float>& x) { return std::imag(x); }
|
||||
inline std::complex<float> ei_conj(const std::complex<float>& x) { return std::conj(x); }
|
||||
@@ -206,6 +222,7 @@ inline bool ei_isApprox(const std::complex<float>& a, const std::complex<float>&
|
||||
**********************/
|
||||
|
||||
template<> inline double precision<std::complex<double> >() { return precision<double>(); }
|
||||
template<> inline double machine_epsilon<std::complex<double> >() { return machine_epsilon<double>(); }
|
||||
inline double ei_real(const std::complex<double>& x) { return std::real(x); }
|
||||
inline double ei_imag(const std::complex<double>& x) { return std::imag(x); }
|
||||
inline std::complex<double> ei_conj(const std::complex<double>& x) { return std::conj(x); }
|
||||
@@ -240,6 +257,7 @@ inline bool ei_isApprox(const std::complex<double>& a, const std::complex<double
|
||||
******************/
|
||||
|
||||
template<> inline long double precision<long double>() { return precision<double>(); }
|
||||
template<> inline long double machine_epsilon<long double>() { return 1.084e-19l; }
|
||||
inline long double ei_real(long double x) { return x; }
|
||||
inline long double ei_imag(long double) { return 0.; }
|
||||
inline long double ei_conj(long double x) { return x; }
|
||||
@@ -254,7 +272,7 @@ inline long double ei_pow(long double x, long double y) { return std::pow(x, y)
|
||||
|
||||
template<> inline long double ei_random(long double a, long double b)
|
||||
{
|
||||
return ei_random<double>(a,b);
|
||||
return ei_random<double>(static_cast<double>(a),static_cast<double>(b));
|
||||
}
|
||||
template<> inline long double ei_random()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -30,58 +30,82 @@
|
||||
*
|
||||
* \brief The matrix class, also used for vectors and row-vectors
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e. the type of the coefficients
|
||||
* \param _Rows the number of rows at compile-time. Use the special value \a Dynamic to
|
||||
* specify that the number of rows is dynamic, i.e. is not fixed at compile-time.
|
||||
* \param _Cols the number of columns at compile-time. Use the special value \a Dynamic to
|
||||
* specify that the number of columns is dynamic, i.e. is not fixed at compile-time.
|
||||
* \param _StorageOrder can be either RowMajor or ColMajor. The default is ColMajor.
|
||||
* \param _MaxRows the maximum number of rows at compile-time. By default this is equal to \a _Rows.
|
||||
* The most common exception is when you don't know the exact number of rows, but know that
|
||||
* it is smaller than some given value. Then you can set \a _MaxRows to that value, and set
|
||||
* _Rows to \a Dynamic.
|
||||
* \param _MaxCols the maximum number of cols at compile-time. By default this is equal to \a _Cols.
|
||||
* The most common exception is when you don't know the exact number of cols, but know that
|
||||
* it is smaller than some given value. Then you can set \a _MaxCols to that value, and set
|
||||
* _Cols to \a Dynamic.
|
||||
* 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.
|
||||
*
|
||||
* This single class template covers all kinds of matrix and vectors that Eigen can handle.
|
||||
* All matrix and vector types are just typedefs to specializations of this class template.
|
||||
* The %Matrix class encompasses \em both fixed-size and dynamic-size objects (\ref fixedsize "note").
|
||||
*
|
||||
* These typedefs are as follows:
|
||||
* \li \c %Matrix\#\#Size\#\#Type for square matrices
|
||||
* \li \c Vector\#\#Size\#\#Type for vectors (matrices with one column)
|
||||
* \li \c RowVector\#\#Size\#\#Type for row-vectors (matrices with one row)
|
||||
* The first three template parameters are required:
|
||||
* \param _Scalar Numeric type, i.e. float, double, int
|
||||
* \param _Rows Number of rows, or \b Dynamic
|
||||
* \param _Cols Number of columns, or \b Dynamic
|
||||
*
|
||||
* where \c Size can be
|
||||
* \li \c 2 for fixed size 2
|
||||
* \li \c 3 for fixed size 3
|
||||
* \li \c 4 for fixed size 4
|
||||
* \li \c X for dynamic size
|
||||
* The remaining template parameters are optional -- in most cases you don't have to worry about them.
|
||||
* \param _Options A combination of either \b RowMajor or \b ColMajor, and of either
|
||||
* \b AutoAlign or \b DontAlign.
|
||||
* The former controls 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.
|
||||
* \param _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
|
||||
* \param _MaxCols Maximum number of columns. Defaults to \a _Cols (\ref maxrows "note").
|
||||
*
|
||||
* and \c Type can be
|
||||
* \li \c i for type \c int
|
||||
* \li \c f for type \c float
|
||||
* \li \c d for type \c double
|
||||
* \li \c cf for type \c std::complex<float>
|
||||
* \li \c cd for type \c std::complex<double>
|
||||
* Eigen provides a number of typedefs covering the usual cases. Here are some examples:
|
||||
*
|
||||
* Examples:
|
||||
* \li \c Matrix2d is a typedef for \c Matrix<double,2,2>
|
||||
* \li \c VectorXf is a typedef for \c Matrix<float,Dynamic,1>
|
||||
* \li \c RowVector3i is a typedef for \c Matrix<int,1,3>
|
||||
* \li \c Matrix2d is a 2x2 square matrix of doubles (\c Matrix<double, 2, 2>)
|
||||
* \li \c Vector4f is a vector of 4 floats (\c Matrix<float, 4, 1>)
|
||||
* \li \c RowVector3i is a row-vector of 3 ints (\c Matrix<int, 1, 3>)
|
||||
*
|
||||
* See \ref matrixtypedefs for an explicit list of all matrix typedefs.
|
||||
* \li \c MatrixXf is a dynamic-size matrix of floats (\c Matrix<float, Dynamic, Dynamic>)
|
||||
* \li \c VectorXf is a dynamic-size vector of floats (\c Matrix<float, Dynamic, 1>)
|
||||
*
|
||||
* Of course these typedefs do not exhaust all the possibilities offered by the Matrix class
|
||||
* template, they only address some of the most common cases. For instance, if you want a
|
||||
* fixed-size matrix with 3 rows and 5 columns, there is no typedef for that, so you should use
|
||||
* \c Matrix<double,3,5>.
|
||||
* See \link matrixtypedefs this page \endlink for a complete list of predefined \em %Matrix and \em Vector typedefs.
|
||||
*
|
||||
* Note that most of the API is in the base class MatrixBase.
|
||||
* 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
|
||||
*
|
||||
* <i><b>Some notes:</b></i>
|
||||
*
|
||||
* <dl>
|
||||
* <dt><b>\anchor dense Dense versus sparse:</b></dt>
|
||||
* <dd>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.</dd>
|
||||
*
|
||||
* <dt><b>\anchor fixedsize Fixed-size versus dynamic-size:</b></dt>
|
||||
* <dd>Fixed-size means that the numbers of rows and columns are known are 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, <em>do not</em> expand dynamically in the sense of a std::map.
|
||||
* If you want this behavior, see the Sparse module.</dd>
|
||||
*
|
||||
* <dt><b>\anchor maxrows _MaxRows and _MaxCols:</b></dt>
|
||||
* <dd>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 are 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.</dd>
|
||||
* </dl>
|
||||
*
|
||||
* \see MatrixBase for the majority of the API methods for matrices
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols> >
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
enum {
|
||||
@@ -89,33 +113,35 @@ struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols
|
||||
ColsAtCompileTime = _Cols,
|
||||
MaxRowsAtCompileTime = _MaxRows,
|
||||
MaxColsAtCompileTime = _MaxCols,
|
||||
Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>::ret,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = RandomAccessPattern
|
||||
Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost
|
||||
};
|
||||
};
|
||||
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
class Matrix
|
||||
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols> >
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
, public ei_with_aligned_operator_new<_Scalar,ei_size_at_compile_time<_Rows,_Cols>::ret>
|
||||
#endif
|
||||
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
{
|
||||
public:
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix)
|
||||
enum { Options = _Options };
|
||||
friend class Eigen::Map<Matrix, Unaligned>;
|
||||
typedef class Eigen::Map<Matrix, Unaligned> UnalignedMapType;
|
||||
friend class Eigen::Map<Matrix, Aligned>;
|
||||
typedef class Eigen::Map<Matrix, Aligned> AlignedMapType;
|
||||
|
||||
protected:
|
||||
ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime> m_storage;
|
||||
ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime, Options> m_storage;
|
||||
|
||||
public:
|
||||
enum { NeedsToAlign = (Options&AutoAlign) == AutoAlign
|
||||
&& SizeAtCompileTime!=Dynamic && ((sizeof(Scalar)*SizeAtCompileTime)%16)==0 };
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
|
||||
|
||||
inline int rows() const { return m_storage.rows(); }
|
||||
inline int cols() const { return m_storage.cols(); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_storage.cols(); }
|
||||
|
||||
inline int stride(void) const
|
||||
EIGEN_STRONG_INLINE int stride(void) const
|
||||
{
|
||||
if(Flags & RowMajorBit)
|
||||
return m_storage.cols();
|
||||
@@ -123,7 +149,7 @@ class Matrix
|
||||
return m_storage.rows();
|
||||
}
|
||||
|
||||
inline const Scalar& coeff(int row, int col) const
|
||||
EIGEN_STRONG_INLINE const Scalar& coeff(int row, int col) const
|
||||
{
|
||||
if(Flags & RowMajorBit)
|
||||
return m_storage.data()[col + row * m_storage.cols()];
|
||||
@@ -131,12 +157,12 @@ class Matrix
|
||||
return m_storage.data()[row + col * m_storage.rows()];
|
||||
}
|
||||
|
||||
inline const Scalar& coeff(int index) const
|
||||
EIGEN_STRONG_INLINE const Scalar& coeff(int index) const
|
||||
{
|
||||
return m_storage.data()[index];
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
EIGEN_STRONG_INLINE Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
if(Flags & RowMajorBit)
|
||||
return m_storage.data()[col + row * m_storage.cols()];
|
||||
@@ -144,13 +170,13 @@ class Matrix
|
||||
return m_storage.data()[row + col * m_storage.rows()];
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(int index)
|
||||
EIGEN_STRONG_INLINE Scalar& coeffRef(int index)
|
||||
{
|
||||
return m_storage.data()[index];
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int row, int col) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
|
||||
{
|
||||
return ei_ploadt<Scalar, LoadMode>
|
||||
(m_storage.data() + (Flags & RowMajorBit
|
||||
@@ -159,13 +185,13 @@ class Matrix
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(int index) const
|
||||
EIGEN_STRONG_INLINE PacketScalar packet(int index) const
|
||||
{
|
||||
return ei_ploadt<Scalar, LoadMode>(m_storage.data() + index);
|
||||
}
|
||||
|
||||
template<int StoreMode>
|
||||
inline void writePacket(int row, int col, const PacketScalar& x)
|
||||
EIGEN_STRONG_INLINE void writePacket(int row, int col, const PacketScalar& x)
|
||||
{
|
||||
ei_pstoret<Scalar, PacketScalar, StoreMode>
|
||||
(m_storage.data() + (Flags & RowMajorBit
|
||||
@@ -174,30 +200,43 @@ class Matrix
|
||||
}
|
||||
|
||||
template<int StoreMode>
|
||||
inline void writePacket(int index, const PacketScalar& x)
|
||||
EIGEN_STRONG_INLINE void writePacket(int index, const PacketScalar& x)
|
||||
{
|
||||
ei_pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
|
||||
}
|
||||
|
||||
/** \returns a const pointer to the data array of this matrix */
|
||||
inline const Scalar *data() const
|
||||
EIGEN_STRONG_INLINE const Scalar *data() const
|
||||
{ return m_storage.data(); }
|
||||
|
||||
/** \returns a pointer to the data array of this matrix */
|
||||
inline Scalar *data()
|
||||
EIGEN_STRONG_INLINE Scalar *data()
|
||||
{ return m_storage.data(); }
|
||||
|
||||
/** Resizes \c *this to a \a rows x \a cols matrix.
|
||||
*
|
||||
* Makes sense for dynamic-size matrices only.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \sa resize(int) for vectors.
|
||||
*/
|
||||
inline void resize(int rows, int cols)
|
||||
{
|
||||
ei_assert(rows > 0
|
||||
&& (MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
|
||||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& cols > 0
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
|
||||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
m_storage.resize(rows * cols, rows, cols);
|
||||
}
|
||||
|
||||
/** Resizes \c *this to a vector of length \a size
|
||||
*
|
||||
* \sa resize(int,int) for the details.
|
||||
*/
|
||||
inline void resize(int size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
|
||||
@@ -207,37 +246,27 @@ class Matrix
|
||||
m_storage.resize(size, size, 1);
|
||||
}
|
||||
|
||||
/** Copies the value of the expression \a other into *this.
|
||||
/** Copies the value of the expression \a other into \c *this with automatic resizing.
|
||||
*
|
||||
* *this is resized (if possible) to match the dimensions of \a other.
|
||||
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
|
||||
* it will be initialized.
|
||||
*
|
||||
* As a special exception, 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.
|
||||
* 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<typename OtherDerived>
|
||||
inline Matrix& operator=(const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
if(RowsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(1, other.size());
|
||||
}
|
||||
else if(ColsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(other.size(), 1);
|
||||
}
|
||||
else resize(other.rows(), other.cols());
|
||||
return Base::operator=(other.derived());
|
||||
return _set(other);
|
||||
}
|
||||
|
||||
/** This is a special case of the templated operator=. Its purpose is to
|
||||
* prevent a default operator= from hiding the templated operator=.
|
||||
*/
|
||||
inline Matrix& operator=(const Matrix& other)
|
||||
EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
|
||||
{
|
||||
return operator=<Matrix>(other);
|
||||
return _set(other);
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, +=)
|
||||
@@ -249,23 +278,34 @@ class Matrix
|
||||
*
|
||||
* For fixed-size matrices, does nothing.
|
||||
*
|
||||
* For dynamic-size matrices, initializes with initial size 1x1, which is inefficient, hence
|
||||
* when performance matters one should avoid using this constructor on dynamic-size matrices.
|
||||
* 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(int,int)
|
||||
*/
|
||||
inline explicit Matrix() : m_storage(1, 1, 1)
|
||||
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
|
||||
{
|
||||
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
|
||||
_check_template_params();
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal */
|
||||
Matrix(ei_constructor_without_unaligned_array_assert)
|
||||
: m_storage(ei_constructor_without_unaligned_array_assert())
|
||||
{}
|
||||
#endif
|
||||
|
||||
/** 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 Matrix() instead.
|
||||
*/
|
||||
inline explicit Matrix(int dim)
|
||||
EIGEN_STRONG_INLINE explicit Matrix(int dim)
|
||||
: m_storage(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
|
||||
ei_assert(dim > 0);
|
||||
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
|
||||
@@ -281,8 +321,9 @@ class Matrix
|
||||
* it is redundant to pass these parameters, so one should use the default constructor
|
||||
* Matrix() instead.
|
||||
*/
|
||||
inline Matrix(int x, int y) : m_storage(x*y, x, y)
|
||||
EIGEN_STRONG_INLINE Matrix(int x, int y) : m_storage(x*y, x, y)
|
||||
{
|
||||
_check_template_params();
|
||||
if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|
||||
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
|
||||
{
|
||||
@@ -296,31 +337,35 @@ class Matrix
|
||||
}
|
||||
}
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
inline Matrix(const float& x, const float& y)
|
||||
EIGEN_STRONG_INLINE Matrix(const float& x, const float& y)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2);
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
}
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
inline Matrix(const double& x, const double& y)
|
||||
EIGEN_STRONG_INLINE Matrix(const double& x, const double& y)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2);
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
}
|
||||
/** constructs an initialized 3D vector with given coefficients */
|
||||
inline Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3);
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
}
|
||||
/** constructs an initialized 4D vector with given coefficients */
|
||||
inline Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4);
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
@@ -331,33 +376,26 @@ class Matrix
|
||||
|
||||
/** Constructor copying the value of the expression \a other */
|
||||
template<typename OtherDerived>
|
||||
inline Matrix(const MatrixBase<OtherDerived>& other)
|
||||
EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
|
||||
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
|
||||
//Base::operator=(other.derived());
|
||||
_check_template_params();
|
||||
_set_noalias(other);
|
||||
}
|
||||
/** Copy constructor */
|
||||
inline Matrix(const Matrix& other)
|
||||
EIGEN_STRONG_INLINE Matrix(const Matrix& other)
|
||||
: Base(), m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
Base::lazyAssign(other);
|
||||
_check_template_params();
|
||||
_set_noalias(other);
|
||||
}
|
||||
/** Destructor */
|
||||
inline ~Matrix() {}
|
||||
|
||||
/** Override MatrixBase::eval() since matrices don't need to be evaluated, it is enough to just read them.
|
||||
* This prevents a useless copy when doing e.g. "m1 = m2.eval()"
|
||||
*/
|
||||
const Matrix& eval() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Override MatrixBase::swap() since for dynamic-sized matrices of same type it is enough to swap the
|
||||
* data pointers.
|
||||
*/
|
||||
void swap(Matrix& other)
|
||||
inline void swap(Matrix& other)
|
||||
{
|
||||
if (Base::SizeAtCompileTime==Dynamic)
|
||||
m_storage.swap(other.m_storage);
|
||||
@@ -365,12 +403,137 @@ class Matrix
|
||||
this->Base::swap(other);
|
||||
}
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see class Map
|
||||
*/
|
||||
//@{
|
||||
inline static const UnalignedMapType Map(const Scalar* data)
|
||||
{ return UnalignedMapType(data); }
|
||||
inline static UnalignedMapType Map(Scalar* data)
|
||||
{ return UnalignedMapType(data); }
|
||||
inline static const UnalignedMapType Map(const Scalar* data, int size)
|
||||
{ return UnalignedMapType(data, size); }
|
||||
inline static UnalignedMapType Map(Scalar* data, int size)
|
||||
{ return UnalignedMapType(data, size); }
|
||||
inline static const UnalignedMapType Map(const Scalar* data, int rows, int cols)
|
||||
{ return UnalignedMapType(data, rows, cols); }
|
||||
inline static UnalignedMapType Map(Scalar* data, int rows, int cols)
|
||||
{ return UnalignedMapType(data, rows, cols); }
|
||||
|
||||
inline static const AlignedMapType MapAligned(const Scalar* data)
|
||||
{ return AlignedMapType(data); }
|
||||
inline static AlignedMapType MapAligned(Scalar* data)
|
||||
{ return AlignedMapType(data); }
|
||||
inline static const AlignedMapType MapAligned(const Scalar* data, int size)
|
||||
{ return AlignedMapType(data, size); }
|
||||
inline static AlignedMapType MapAligned(Scalar* data, int size)
|
||||
{ return AlignedMapType(data, size); }
|
||||
inline static const AlignedMapType MapAligned(const Scalar* data, int rows, int cols)
|
||||
{ return AlignedMapType(data, rows, cols); }
|
||||
inline static AlignedMapType MapAligned(Scalar* data, int rows, int cols)
|
||||
{ return AlignedMapType(data, rows, cols); }
|
||||
//@}
|
||||
|
||||
using Base::setConstant;
|
||||
Matrix& setConstant(int size, const Scalar& value);
|
||||
Matrix& setConstant(int rows, int cols, const Scalar& value);
|
||||
|
||||
using Base::setZero;
|
||||
Matrix& setZero(int size);
|
||||
Matrix& setZero(int rows, int cols);
|
||||
|
||||
using Base::setOnes;
|
||||
Matrix& setOnes(int size);
|
||||
Matrix& setOnes(int rows, int cols);
|
||||
|
||||
using Base::setRandom;
|
||||
Matrix& setRandom(int size);
|
||||
Matrix& setRandom(int rows, int cols);
|
||||
|
||||
using Base::setIdentity;
|
||||
Matrix& setIdentity(int rows, int cols);
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
template<typename OtherDerived>
|
||||
explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
|
||||
template<typename OtherDerived>
|
||||
Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
|
||||
|
||||
// allow to extend Matrix outside Eigen
|
||||
#ifdef EIGEN_MATRIX_PLUGIN
|
||||
#include EIGEN_MATRIX_PLUGIN
|
||||
#endif
|
||||
|
||||
private:
|
||||
/** \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<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE void _resize_to_match(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
if(RowsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(1, other.size());
|
||||
}
|
||||
else if(ColsAtCompileTime == 1)
|
||||
{
|
||||
ei_assert(other.isVector());
|
||||
resize(other.size(), 1);
|
||||
}
|
||||
else resize(other.rows(), other.cols());
|
||||
}
|
||||
|
||||
/** \internal 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<OtherDerived>&), _set_noalias()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_resize_to_match(other);
|
||||
return Base::operator=(other);
|
||||
}
|
||||
|
||||
/** \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<OtherDerived>&), _set()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set_noalias(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_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.
|
||||
return ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
|
||||
}
|
||||
|
||||
static EIGEN_STRONG_INLINE void _check_template_params()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((_Rows > 0
|
||||
&& _Cols > 0
|
||||
&& _MaxRows <= _Rows
|
||||
&& _MaxCols <= _Cols
|
||||
&& (_Options & (AutoAlign|RowMajor)) == _Options),
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS)
|
||||
}
|
||||
};
|
||||
|
||||
/** \defgroup matrixtypedefs Global matrix typedefs
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -55,10 +56,12 @@ template<typename Derived> class MatrixBase
|
||||
{
|
||||
public:
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
class InnerIterator;
|
||||
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
enum {
|
||||
|
||||
@@ -139,6 +142,7 @@ template<typename Derived> class MatrixBase
|
||||
ei_assert(ei_are_flags_consistent<Flags>::ret);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This is the "real scalar" type; if the \a Scalar type is already real numbers
|
||||
* (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
|
||||
* \a Scalar is \a std::complex<T> then RealScalar is \a T.
|
||||
@@ -150,6 +154,7 @@ template<typename Derived> class MatrixBase
|
||||
/** type of the equivalent square matrix */
|
||||
typedef Matrix<Scalar,EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime),
|
||||
EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */
|
||||
inline int rows() const { return derived().rows(); }
|
||||
@@ -173,9 +178,21 @@ template<typename Derived> class MatrixBase
|
||||
* i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
|
||||
int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
|
||||
|
||||
/** \internal the type to which the expression gets evaluated (needed by MSVC) */
|
||||
typedef typename ei_eval<Derived>::type EvalType;
|
||||
/** \internal Represents a constant matrix */
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal the plain matrix type corresponding to this expression. Note that 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 guaranteed however, that the return type of eval() is either
|
||||
* PlainMatrixType or const PlainMatrixType&.
|
||||
*/
|
||||
typedef typename ei_plain_matrix_type<Derived>::type PlainMatrixType;
|
||||
/** \internal the column-major plain matrix type corresponding to this expression. Note that 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!
|
||||
* The only difference from PlainMatrixType is that PlainMatrixType_ColMajor is guaranteed to be column-major.
|
||||
*/
|
||||
typedef typename ei_plain_matrix_type<Derived>::type PlainMatrixType_ColMajor;
|
||||
|
||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||
typedef CwiseNullaryOp<ei_scalar_constant_op<Scalar>,Derived> ConstantReturnType;
|
||||
/** \internal Represents a scalar multiple of a matrix */
|
||||
typedef CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived> ScalarMultipleReturnType;
|
||||
@@ -188,8 +205,10 @@ template<typename Derived> class MatrixBase
|
||||
>::ret ConjugateReturnType;
|
||||
/** \internal the return type of MatrixBase::real() */
|
||||
typedef CwiseUnaryOp<ei_scalar_real_op<Scalar>, Derived> RealReturnType;
|
||||
/** \internal the return type of MatrixBase::imag() */
|
||||
typedef CwiseUnaryOp<ei_scalar_imag_op<Scalar>, Derived> ImagReturnType;
|
||||
/** \internal the return type of MatrixBase::adjoint() */
|
||||
typedef Transpose<NestByValue<typename ei_cleantype<ConjugateReturnType>::type> >
|
||||
typedef Eigen::Transpose<NestByValue<typename ei_cleantype<ConjugateReturnType>::type> >
|
||||
AdjointReturnType;
|
||||
/** \internal the return type of MatrixBase::eigenvalues() */
|
||||
typedef Matrix<typename NumTraits<typename ei_traits<Derived>::Scalar>::Real, ei_traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
|
||||
@@ -203,16 +222,13 @@ template<typename Derived> class MatrixBase
|
||||
typedef Block<CwiseNullaryOp<ei_scalar_identity_op<Scalar>, SquareMatrixType>,
|
||||
ei_traits<Derived>::RowsAtCompileTime,
|
||||
ei_traits<Derived>::ColsAtCompileTime> BasisReturnType;
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
|
||||
/** Copies \a other into *this. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
Derived& operator=(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Special case of the template operator=, in order to prevent the compiler
|
||||
* from generating a default operator= (issue hit with g++ 4.1)
|
||||
*/
|
||||
@@ -221,6 +237,11 @@ template<typename Derived> class MatrixBase
|
||||
return this->operator=<Derived>(other);
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
/** Overloaded for cache friendly product evaluation */
|
||||
template<typename Lhs, typename Rhs>
|
||||
Derived& lazyAssign(const Product<Lhs,Rhs,CacheFriendlyProduct>& product);
|
||||
@@ -229,10 +250,7 @@ template<typename Derived> class MatrixBase
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
|
||||
{ return lazyAssign(other._expression()); }
|
||||
|
||||
/** Overloaded for sparse product evaluation */
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const Product<Derived1,Derived2,SparseProduct>& product);
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
CommaInitializer<Derived> operator<< (const Scalar& s);
|
||||
|
||||
@@ -253,6 +271,7 @@ template<typename Derived> class MatrixBase
|
||||
Scalar& operator[](int index);
|
||||
Scalar& operator()(int index);
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename OtherDerived>
|
||||
void copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other);
|
||||
template<typename OtherDerived>
|
||||
@@ -261,6 +280,7 @@ template<typename Derived> class MatrixBase
|
||||
void copyPacket(int row, int col, const MatrixBase<OtherDerived>& other);
|
||||
template<typename OtherDerived, int StoreMode, int LoadMode>
|
||||
void copyPacket(int index, const MatrixBase<OtherDerived>& other);
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
template<int LoadMode>
|
||||
PacketScalar packet(int row, int col) const;
|
||||
@@ -320,21 +340,23 @@ template<typename Derived> class MatrixBase
|
||||
Derived& operator*=(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
typename OtherDerived::Eval solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
||||
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
void solveTriangularInPlace(MatrixBase<OtherDerived>& other) const;
|
||||
void solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
|
||||
template<typename OtherDerived>
|
||||
Scalar dot(const MatrixBase<OtherDerived>& other) const;
|
||||
RealScalar norm2() const;
|
||||
RealScalar squaredNorm() const;
|
||||
RealScalar norm() const;
|
||||
const EvalType normalized() const;
|
||||
const PlainMatrixType normalized() const;
|
||||
void normalize();
|
||||
|
||||
Transpose<Derived> transpose();
|
||||
const Transpose<Derived> transpose() const;
|
||||
Eigen::Transpose<Derived> transpose();
|
||||
const Eigen::Transpose<Derived> transpose() const;
|
||||
void transposeInPlace();
|
||||
const AdjointReturnType adjoint() const;
|
||||
|
||||
|
||||
@@ -351,8 +373,8 @@ template<typename Derived> class MatrixBase
|
||||
const typename BlockReturnType<Derived>::Type
|
||||
block(int startRow, int startCol, int blockRows, int blockCols) const;
|
||||
|
||||
typename BlockReturnType<Derived>::SubVectorType block(int start, int size);
|
||||
const typename BlockReturnType<Derived>::SubVectorType block(int start, int size) const;
|
||||
typename BlockReturnType<Derived>::SubVectorType segment(int start, int size);
|
||||
const typename BlockReturnType<Derived>::SubVectorType segment(int start, int size) const;
|
||||
|
||||
typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size);
|
||||
const typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size) const;
|
||||
@@ -379,8 +401,8 @@ template<typename Derived> class MatrixBase
|
||||
template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType end();
|
||||
template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType end() const;
|
||||
|
||||
template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType block(int start);
|
||||
template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType block(int start) const;
|
||||
template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType segment(int start);
|
||||
template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType segment(int start) const;
|
||||
|
||||
DiagonalCoeffs<Derived> diagonal();
|
||||
const DiagonalCoeffs<Derived> diagonal() const;
|
||||
@@ -423,6 +445,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
const DiagonalMatrix<Derived> asDiagonal() const;
|
||||
|
||||
void fill(const Scalar& value);
|
||||
Derived& setConstant(const Scalar& value);
|
||||
Derived& setZero();
|
||||
Derived& setOnes();
|
||||
@@ -440,13 +463,14 @@ template<typename Derived> class MatrixBase
|
||||
RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
bool isApproxToConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
|
||||
bool isConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
|
||||
bool isZero(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isOnes(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isIdentity(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isDiagonal(RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
bool isUpper(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isLower(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isUpperTriangular(RealScalar prec = precision<Scalar>()) const;
|
||||
bool isLowerTriangular(RealScalar prec = precision<Scalar>()) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
bool isOrthogonal(const MatrixBase<OtherDerived>& other,
|
||||
@@ -467,11 +491,11 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
EIGEN_ALWAYS_INLINE const typename ei_eval<Derived>::type eval() const
|
||||
{
|
||||
return typename ei_eval<Derived>::type(derived());
|
||||
}
|
||||
EIGEN_STRONG_INLINE const typename ei_eval<Derived>::type eval() const
|
||||
{ return typename ei_eval<Derived>::type(derived()); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
void swap(const MatrixBase<OtherDerived>& other);
|
||||
@@ -492,6 +516,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
ConjugateReturnType conjugate() const;
|
||||
const RealReturnType real() const;
|
||||
const ImagReturnType imag() const;
|
||||
|
||||
template<typename CustomUnaryOp>
|
||||
const CwiseUnaryOp<CustomUnaryOp, Derived> unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const;
|
||||
@@ -517,11 +542,12 @@ template<typename Derived> class MatrixBase
|
||||
template<typename Visitor>
|
||||
void visit(Visitor& func) const;
|
||||
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
inline Derived& const_cast_derived() const
|
||||
{ return *static_cast<Derived*>(const_cast<MatrixBase*>(this)); }
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
const Cwise<Derived> cwise() const;
|
||||
Cwise<Derived> cwise();
|
||||
@@ -532,6 +558,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
bool all(void) const;
|
||||
bool any(void) const;
|
||||
int count() const;
|
||||
|
||||
const PartialRedux<Derived,Horizontal> rowwise() const;
|
||||
const PartialRedux<Derived,Vertical> colwise() const;
|
||||
@@ -544,44 +571,56 @@ template<typename Derived> class MatrixBase
|
||||
const Select<Derived,ThenDerived,ElseDerived>
|
||||
select(const MatrixBase<ThenDerived>& thenMatrix,
|
||||
const MatrixBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
|
||||
template<typename ThenDerived>
|
||||
inline const Select<Derived,ThenDerived, NestByValue<typename ThenDerived::ConstantReturnType> >
|
||||
select(const MatrixBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
|
||||
|
||||
|
||||
template<typename ElseDerived>
|
||||
inline const Select<Derived, NestByValue<typename ElseDerived::ConstantReturnType>, ElseDerived >
|
||||
select(typename ElseDerived::Scalar thenScalar, const MatrixBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
template<int p> RealScalar lpNorm() const;
|
||||
|
||||
/////////// LU module ///////////
|
||||
|
||||
const LU<EvalType> lu() const;
|
||||
const EvalType inverse() const;
|
||||
void computeInverse(EvalType *result) const;
|
||||
const LU<PlainMatrixType> lu() const;
|
||||
const PlainMatrixType inverse() const;
|
||||
void computeInverse(PlainMatrixType *result) const;
|
||||
Scalar determinant() const;
|
||||
|
||||
/////////// Cholesky module ///////////
|
||||
|
||||
const Cholesky<EvalType> cholesky() const;
|
||||
const CholeskyWithoutSquareRoot<EvalType> choleskyNoSqrt() const;
|
||||
const LLT<PlainMatrixType> llt() const;
|
||||
const LDLT<PlainMatrixType> ldlt() const;
|
||||
|
||||
/////////// QR module ///////////
|
||||
|
||||
const QR<EvalType> qr() const;
|
||||
const QR<PlainMatrixType> qr() const;
|
||||
|
||||
EigenvaluesReturnType eigenvalues() const;
|
||||
RealScalar operatorNorm() const;
|
||||
|
||||
/////////// SVD module ///////////
|
||||
|
||||
SVD<EvalType> svd() const;
|
||||
SVD<PlainMatrixType> svd() const;
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
template<typename OtherDerived>
|
||||
EvalType cross(const MatrixBase<OtherDerived>& other) const;
|
||||
EvalType unitOrthogonal(void) const;
|
||||
|
||||
PlainMatrixType cross(const MatrixBase<OtherDerived>& other) const;
|
||||
PlainMatrixType unitOrthogonal(void) const;
|
||||
Matrix<Scalar,3,1> eulerAngles(int a0, int a1, int a2) const;
|
||||
|
||||
/////////// Sparse module ///////////
|
||||
|
||||
// dense = spasre * dense
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,SparseTimeDenseProduct>& product);
|
||||
// dense = dense * spasre
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
|
||||
|
||||
#ifdef EIGEN_MATRIXBASE_PLUGIN
|
||||
#include EIGEN_MATRIXBASE_PLUGIN
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,6 +26,35 @@
|
||||
#ifndef EIGEN_MATRIXSTORAGE_H
|
||||
#define EIGEN_MATRIXSTORAGE_H
|
||||
|
||||
struct ei_constructor_without_unaligned_array_assert {};
|
||||
|
||||
/** \internal
|
||||
* Static array automatically aligned if the total byte size is a multiple of 16 and the matrix options require auto alignment
|
||||
*/
|
||||
template <typename T, int Size, int MatrixOptions,
|
||||
bool Align = (MatrixOptions&AutoAlign) && (((Size*sizeof(T))&0xf)==0)
|
||||
> struct ei_matrix_array
|
||||
{
|
||||
EIGEN_ALIGN_128 T array[Size];
|
||||
|
||||
ei_matrix_array()
|
||||
{
|
||||
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
ei_assert((reinterpret_cast<size_t>(array) & 0xf) == 0
|
||||
&& "this assertion is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
|
||||
#endif
|
||||
}
|
||||
|
||||
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
|
||||
};
|
||||
|
||||
template <typename T, int Size, int MatrixOptions> struct ei_matrix_array<T,Size,MatrixOptions,false>
|
||||
{
|
||||
T array[Size];
|
||||
ei_matrix_array() {}
|
||||
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
|
||||
};
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* \class ei_matrix_storage
|
||||
@@ -37,14 +66,16 @@
|
||||
*
|
||||
* \sa Matrix
|
||||
*/
|
||||
template<typename T, int Size, int _Rows, int _Cols> class ei_matrix_storage;
|
||||
template<typename T, int Size, int _Rows, int _Cols, int _Options> class ei_matrix_storage;
|
||||
|
||||
// purely fixed-size matrix
|
||||
template<typename T, int Size, int _Rows, int _Cols> class ei_matrix_storage
|
||||
template<typename T, int Size, int _Rows, int _Cols, int _Options> class ei_matrix_storage
|
||||
{
|
||||
ei_aligned_array<T,Size,((Size*sizeof(T))%16)==0> m_data;
|
||||
ei_matrix_array<T,Size,_Options> m_data;
|
||||
public:
|
||||
inline ei_matrix_storage() {}
|
||||
inline explicit ei_matrix_storage() {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
|
||||
: m_data(ei_constructor_without_unaligned_array_assert()) {}
|
||||
inline ei_matrix_storage(int,int,int) {}
|
||||
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); }
|
||||
inline static int rows(void) {return _Rows;}
|
||||
@@ -55,12 +86,15 @@ template<typename T, int Size, int _Rows, int _Cols> class ei_matrix_storage
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage
|
||||
template<typename T, int Size> class ei_matrix_storage<T, Size, Dynamic, Dynamic>
|
||||
template<typename T, int Size, int _Options> class ei_matrix_storage<T, Size, Dynamic, Dynamic, _Options>
|
||||
{
|
||||
ei_aligned_array<T,Size,((Size*sizeof(T))%16)==0> m_data;
|
||||
ei_matrix_array<T,Size,_Options> m_data;
|
||||
int m_rows;
|
||||
int m_cols;
|
||||
public:
|
||||
inline explicit ei_matrix_storage() : m_rows(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
|
||||
: m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(int, int rows, int cols) : m_rows(rows), m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() {}
|
||||
inline void swap(ei_matrix_storage& other)
|
||||
@@ -77,11 +111,14 @@ template<typename T, int Size> class ei_matrix_storage<T, Size, Dynamic, Dynamic
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage and fixed width
|
||||
template<typename T, int Size, int _Cols> class ei_matrix_storage<T, Size, Dynamic, _Cols>
|
||||
template<typename T, int Size, int _Cols, int _Options> class ei_matrix_storage<T, Size, Dynamic, _Cols, _Options>
|
||||
{
|
||||
ei_aligned_array<T,Size,((Size*sizeof(T))%16)==0> m_data;
|
||||
ei_matrix_array<T,Size,_Options> m_data;
|
||||
int m_rows;
|
||||
public:
|
||||
inline explicit ei_matrix_storage() : m_rows(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
|
||||
: m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0) {}
|
||||
inline ei_matrix_storage(int, int rows, int) : m_rows(rows) {}
|
||||
inline ~ei_matrix_storage() {}
|
||||
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||
@@ -96,17 +133,20 @@ template<typename T, int Size, int _Cols> class ei_matrix_storage<T, Size, Dynam
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage and fixed height
|
||||
template<typename T, int Size, int _Rows> class ei_matrix_storage<T, Size, _Rows, Dynamic>
|
||||
template<typename T, int Size, int _Rows, int _Options> class ei_matrix_storage<T, Size, _Rows, Dynamic, _Options>
|
||||
{
|
||||
ei_aligned_array<T,Size,((Size*sizeof(T))%16)==0> m_data;
|
||||
ei_matrix_array<T,Size,_Options> m_data;
|
||||
int m_cols;
|
||||
public:
|
||||
inline explicit ei_matrix_storage() : m_cols(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
|
||||
: m_data(ei_constructor_without_unaligned_array_assert()), m_cols(0) {}
|
||||
inline ei_matrix_storage(int, int, int cols) : m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() {}
|
||||
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||
inline int rows(void) const {return _Rows;}
|
||||
inline int cols(void) const {return m_cols;}
|
||||
inline void resize(int size, int, int cols)
|
||||
inline void resize(int, int, int cols)
|
||||
{
|
||||
m_cols = cols;
|
||||
}
|
||||
@@ -115,15 +155,18 @@ template<typename T, int Size, int _Rows> class ei_matrix_storage<T, Size, _Rows
|
||||
};
|
||||
|
||||
// purely dynamic matrix.
|
||||
template<typename T> class ei_matrix_storage<T, Dynamic, Dynamic, Dynamic>
|
||||
template<typename T, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic, Dynamic, _Options>
|
||||
{
|
||||
T *m_data;
|
||||
int m_rows;
|
||||
int m_cols;
|
||||
public:
|
||||
inline explicit ei_matrix_storage() : m_data(0), m_rows(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
|
||||
: m_data(0), m_rows(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(int size, int rows, int cols)
|
||||
: m_data(ei_aligned_malloc<T>(size)), m_rows(rows), m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_free(m_data); }
|
||||
: m_data(ei_aligned_new<T>(size)), m_rows(rows), m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, m_rows*m_cols); }
|
||||
inline void swap(ei_matrix_storage& other)
|
||||
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
|
||||
inline int rows(void) const {return m_rows;}
|
||||
@@ -132,8 +175,11 @@ template<typename T> class ei_matrix_storage<T, Dynamic, Dynamic, Dynamic>
|
||||
{
|
||||
if(size != m_rows*m_cols)
|
||||
{
|
||||
ei_aligned_free(m_data);
|
||||
m_data = ei_aligned_malloc<T>(size);
|
||||
ei_aligned_delete(m_data, m_rows*m_cols);
|
||||
if (size)
|
||||
m_data = ei_aligned_new<T>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
}
|
||||
m_rows = rows;
|
||||
m_cols = cols;
|
||||
@@ -143,13 +189,15 @@ template<typename T> class ei_matrix_storage<T, Dynamic, Dynamic, Dynamic>
|
||||
};
|
||||
|
||||
// matrix with dynamic width and fixed height (so that matrix has dynamic size).
|
||||
template<typename T, int _Rows> class ei_matrix_storage<T, Dynamic, _Rows, Dynamic>
|
||||
template<typename T, int _Rows, int _Options> class ei_matrix_storage<T, Dynamic, _Rows, Dynamic, _Options>
|
||||
{
|
||||
T *m_data;
|
||||
int m_cols;
|
||||
public:
|
||||
inline ei_matrix_storage(int size, int, int cols) : m_data(ei_aligned_malloc<T>(size)), m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_free(m_data); }
|
||||
inline explicit ei_matrix_storage() : m_data(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
|
||||
inline ei_matrix_storage(int size, int, int cols) : m_data(ei_aligned_new<T>(size)), m_cols(cols) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Rows*m_cols); }
|
||||
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||
inline static int rows(void) {return _Rows;}
|
||||
inline int cols(void) const {return m_cols;}
|
||||
@@ -157,8 +205,11 @@ template<typename T, int _Rows> class ei_matrix_storage<T, Dynamic, _Rows, Dynam
|
||||
{
|
||||
if(size != _Rows*m_cols)
|
||||
{
|
||||
ei_aligned_free(m_data);
|
||||
m_data = ei_aligned_malloc<T>(size);
|
||||
ei_aligned_delete(m_data, _Rows*m_cols);
|
||||
if (size)
|
||||
m_data = ei_aligned_new<T>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
}
|
||||
m_cols = cols;
|
||||
}
|
||||
@@ -167,13 +218,15 @@ template<typename T, int _Rows> class ei_matrix_storage<T, Dynamic, _Rows, Dynam
|
||||
};
|
||||
|
||||
// matrix with dynamic height and fixed width (so that matrix has dynamic size).
|
||||
template<typename T, int _Cols> class ei_matrix_storage<T, Dynamic, Dynamic, _Cols>
|
||||
template<typename T, int _Cols, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic, _Cols, _Options>
|
||||
{
|
||||
T *m_data;
|
||||
int m_rows;
|
||||
public:
|
||||
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_malloc<T>(size)), m_rows(rows) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_free(m_data); }
|
||||
inline explicit ei_matrix_storage() : m_data(0), m_rows(0) {}
|
||||
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
|
||||
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_new<T>(size)), m_rows(rows) {}
|
||||
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Cols*m_rows); }
|
||||
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||
inline int rows(void) const {return m_rows;}
|
||||
inline static int cols(void) {return _Cols;}
|
||||
@@ -181,8 +234,11 @@ template<typename T, int _Cols> class ei_matrix_storage<T, Dynamic, Dynamic, _Co
|
||||
{
|
||||
if(size != m_rows*_Cols)
|
||||
{
|
||||
ei_aligned_free(m_data);
|
||||
m_data = ei_aligned_malloc<T>(size);
|
||||
ei_aligned_delete(m_data, _Cols*m_rows);
|
||||
if (size)
|
||||
m_data = ei_aligned_new<T>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
}
|
||||
m_rows = rows;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -25,7 +25,8 @@
|
||||
#ifndef EIGEN_MINOR_H
|
||||
#define EIGEN_MINOR_H
|
||||
|
||||
/** \class Minor
|
||||
/** \nonstableyet
|
||||
* \class Minor
|
||||
*
|
||||
* \brief Expression of a minor
|
||||
*
|
||||
@@ -92,7 +93,8 @@ template<typename MatrixType> class Minor
|
||||
const int m_row, m_col;
|
||||
};
|
||||
|
||||
/** \return an expression of the (\a row, \a col)-minor of *this,
|
||||
/** \nonstableyet
|
||||
* \return an expression of the (\a row, \a col)-minor of *this,
|
||||
* i.e. an expression constructed from *this by removing the specified
|
||||
* row and column.
|
||||
*
|
||||
@@ -108,7 +110,8 @@ MatrixBase<Derived>::minor(int row, int col)
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
/** This is the const version of minor(). */
|
||||
/** \nonstableyet
|
||||
* This is the const version of minor(). */
|
||||
template<typename Derived>
|
||||
inline const Minor<Derived>
|
||||
MatrixBase<Derived>::minor(int row, int col) const
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -38,18 +38,8 @@
|
||||
* \sa MatrixBase::nestByValue()
|
||||
*/
|
||||
template<typename ExpressionType>
|
||||
struct ei_traits<NestByValue<ExpressionType> >
|
||||
{
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
enum {
|
||||
RowsAtCompileTime = ExpressionType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
|
||||
Flags = ExpressionType::Flags,
|
||||
CoeffReadCost = ExpressionType::CoeffReadCost
|
||||
};
|
||||
};
|
||||
struct ei_traits<NestByValue<ExpressionType> > : public ei_traits<ExpressionType>
|
||||
{};
|
||||
|
||||
template<typename ExpressionType> class NestByValue
|
||||
: public MatrixBase<NestByValue<ExpressionType> >
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -26,13 +26,14 @@
|
||||
#ifndef EIGEN_PART_H
|
||||
#define EIGEN_PART_H
|
||||
|
||||
/** \class Part
|
||||
/** \nonstableyet
|
||||
* \class Part
|
||||
*
|
||||
* \brief Expression of a triangular matrix extracted from a given matrix
|
||||
*
|
||||
* \param MatrixType the type of the object in which we are taking the triangular part
|
||||
* \param Mode the kind of triangular matrix expression to construct. Can be Upper, StrictlyUpper,
|
||||
* UnitUpper, Lower, StrictlyLower, UnitLower. This is in fact a bit field; it must have either
|
||||
* \param Mode the kind of triangular matrix expression to construct. Can be UpperTriangular, StrictlyUpperTriangular,
|
||||
* UnitUpperTriangular, LowerTriangular, StrictlyLowerTriangular, UnitLowerTriangular. This is in fact a bit field; it must have either
|
||||
* UpperTriangularBit or LowerTriangularBit, and additionnaly it may have either ZeroDiagBit or
|
||||
* UnitDiagBit.
|
||||
*
|
||||
@@ -43,16 +44,11 @@
|
||||
* \sa MatrixBase::part()
|
||||
*/
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
struct ei_traits<Part<MatrixType, Mode> >
|
||||
struct ei_traits<Part<MatrixType, Mode> > : ei_traits<MatrixType>
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
|
||||
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||
Flags = (_MatrixTypeNested::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
|
||||
};
|
||||
@@ -88,8 +84,10 @@ template<typename MatrixType, unsigned int Mode> class Part
|
||||
|
||||
inline Scalar coeff(int row, int col) const
|
||||
{
|
||||
// SelfAdjointBit doesn't play any role here: just because a matrix is selfadjoint doesn't say anything about
|
||||
// each individual coefficient, except for the not-very-useful-here fact that diagonal coefficients are real.
|
||||
if( ((Flags & LowerTriangularBit) && (col>row)) || ((Flags & UpperTriangularBit) && (row>col)) )
|
||||
return (Flags & SelfAdjointBit) ? ei_conj(m_matrix.coeff(col, row)) : (Scalar)0;
|
||||
return (Scalar)0;
|
||||
if(Flags & UnitDiagBit)
|
||||
return col==row ? (Scalar)1 : m_matrix.coeff(row, col);
|
||||
else if(Flags & ZeroDiagBit)
|
||||
@@ -100,12 +98,12 @@ template<typename MatrixType, unsigned int Mode> class Part
|
||||
|
||||
inline Scalar& coeffRef(int row, int col)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(!(Flags & UnitDiagBit), writting_to_triangular_part_with_unit_diag_is_not_supported);
|
||||
EIGEN_STATIC_ASSERT(!(Flags & SelfAdjointBit), default_writting_to_selfadjoint_not_supported);
|
||||
ei_assert( (Mode==Upper && col>=row)
|
||||
|| (Mode==Lower && col<=row)
|
||||
|| (Mode==StrictlyUpper && col>row)
|
||||
|| (Mode==StrictlyLower && col<row));
|
||||
EIGEN_STATIC_ASSERT(!(Flags & UnitDiagBit), WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED)
|
||||
EIGEN_STATIC_ASSERT(!(Flags & SelfAdjointBit), COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED)
|
||||
ei_assert( (Mode==UpperTriangular && col>=row)
|
||||
|| (Mode==LowerTriangular && col<=row)
|
||||
|| (Mode==StrictlyUpperTriangular && col>row)
|
||||
|| (Mode==StrictlyLowerTriangular && col<row));
|
||||
return m_matrix.const_cast_derived().coeffRef(row, col);
|
||||
}
|
||||
|
||||
@@ -119,15 +117,22 @@ template<typename MatrixType, unsigned int Mode> class Part
|
||||
const Block<Part, RowsAtCompileTime, 1> col(int i) { return Base::col(i); }
|
||||
const Block<Part, RowsAtCompileTime, 1> col(int i) const { return Base::col(i); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
void swap(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
Part<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
};
|
||||
|
||||
/** \returns an expression of a triangular matrix extracted from the current matrix
|
||||
/** \nonstableyet
|
||||
* \returns an expression of a triangular matrix 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.
|
||||
* The parameter \a Mode can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c UnitUpperTriangular,
|
||||
* \c LowerTriangular, \c StrictlyLowerTriangular, \c UnitLowerTriangular.
|
||||
*
|
||||
* \addexample PartExample \label How to extract a triangular part of an arbitrary matrix
|
||||
*
|
||||
@@ -149,7 +154,7 @@ inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator=(const Other& ot
|
||||
{
|
||||
if(Other::Flags & EvalBeforeAssigningBit)
|
||||
{
|
||||
typename ei_eval<Other>::type other_evaluated(other.rows(), other.cols());
|
||||
typename MatrixBase<Other>::PlainMatrixType other_evaluated(other.rows(), other.cols());
|
||||
other_evaluated.template part<Mode>().lazyAssign(other);
|
||||
lazyAssign(other_evaluated);
|
||||
}
|
||||
@@ -179,12 +184,12 @@ struct ei_part_assignment_impl
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert(Mode == Upper || Mode == Lower || Mode == StrictlyUpper || Mode == StrictlyLower);
|
||||
if((Mode == Upper && row <= col)
|
||||
|| (Mode == Lower && row >= col)
|
||||
|| (Mode == StrictlyUpper && row < col)
|
||||
|| (Mode == StrictlyLower && row > col))
|
||||
dst.coeffRef(row, col) = src.coeff(row, col);
|
||||
ei_assert(Mode == UpperTriangular || Mode == LowerTriangular || Mode == StrictlyUpperTriangular || Mode == StrictlyLowerTriangular);
|
||||
if((Mode == UpperTriangular && row <= col)
|
||||
|| (Mode == LowerTriangular && row >= col)
|
||||
|| (Mode == StrictlyUpperTriangular && row < col)
|
||||
|| (Mode == StrictlyLowerTriangular && row > col))
|
||||
dst.copyCoeff(row, col, src);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -195,7 +200,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, Mode, 1>
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
if(!(Mode & ZeroDiagBit))
|
||||
dst.coeffRef(0, 0) = src.coeff(0, 0);
|
||||
dst.copyCoeff(0, 0, src);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -207,45 +212,45 @@ struct ei_part_assignment_impl<Derived1, Derived2, Mode, 0>
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, Upper, Dynamic>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, UpperTriangular, Dynamic>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
for(int j = 0; j < dst.cols(); j++)
|
||||
for(int i = 0; i <= j; i++)
|
||||
dst.coeffRef(i, j) = src.coeff(i, j);
|
||||
for(int j = 0; j < dst.cols(); ++j)
|
||||
for(int i = 0; i <= j; ++i)
|
||||
dst.copyCoeff(i, j, src);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, Lower, Dynamic>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, LowerTriangular, Dynamic>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
for(int j = 0; j < dst.cols(); j++)
|
||||
for(int i = j; i < dst.rows(); i++)
|
||||
dst.coeffRef(i, j) = src.coeff(i, j);
|
||||
for(int j = 0; j < dst.cols(); ++j)
|
||||
for(int i = j; i < dst.rows(); ++i)
|
||||
dst.copyCoeff(i, j, src);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyUpper, Dynamic>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyUpperTriangular, Dynamic>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
for(int j = 0; j < dst.cols(); j++)
|
||||
for(int i = 0; i < j; i++)
|
||||
dst.coeffRef(i, j) = src.coeff(i, j);
|
||||
for(int j = 0; j < dst.cols(); ++j)
|
||||
for(int i = 0; i < j; ++i)
|
||||
dst.copyCoeff(i, j, src);
|
||||
}
|
||||
};
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyLower, Dynamic>
|
||||
struct ei_part_assignment_impl<Derived1, Derived2, StrictlyLowerTriangular, Dynamic>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
for(int j = 0; j < dst.cols(); j++)
|
||||
for(int i = j+1; i < dst.rows(); i++)
|
||||
dst.coeffRef(i, j) = src.coeff(i, j);
|
||||
for(int j = 0; j < dst.cols(); ++j)
|
||||
for(int i = j+1; i < dst.rows(); ++i)
|
||||
dst.copyCoeff(i, j, src);
|
||||
}
|
||||
};
|
||||
template<typename Derived1, typename Derived2>
|
||||
@@ -253,9 +258,9 @@ struct ei_part_assignment_impl<Derived1, Derived2, SelfAdjoint, Dynamic>
|
||||
{
|
||||
inline static void run(Derived1 &dst, const Derived2 &src)
|
||||
{
|
||||
for(int j = 0; j < dst.cols(); j++)
|
||||
for(int j = 0; j < dst.cols(); ++j)
|
||||
{
|
||||
for(int i = 0; i < j; i++)
|
||||
for(int i = 0; i < j; ++i)
|
||||
dst.coeffRef(j, i) = ei_conj(dst.coeffRef(i, j) = src.coeff(i, j));
|
||||
dst.coeffRef(j, j) = ei_real(src.coeff(j, j));
|
||||
}
|
||||
@@ -275,10 +280,11 @@ void Part<MatrixType, Mode>::lazyAssign(const Other& other)
|
||||
>::run(m_matrix.const_cast_derived(), other.derived());
|
||||
}
|
||||
|
||||
/** \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
|
||||
/** \nonstableyet
|
||||
* \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
|
||||
*
|
||||
* The \a Mode parameter can have the following values: \c Upper, \c StrictlyUpper, \c Lower,
|
||||
* \c StrictlyLower, \c SelfAdjoint.
|
||||
* The \a Mode parameter can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c LowerTriangular,
|
||||
* \c StrictlyLowerTriangular, \c SelfAdjoint.
|
||||
*
|
||||
* \addexample PartExample \label How to write to a triangular part of a matrix
|
||||
*
|
||||
@@ -297,44 +303,44 @@ inline Part<Derived, Mode> MatrixBase<Derived>::part()
|
||||
/** \returns true if *this is approximately equal to an upper triangular matrix,
|
||||
* within the precision given by \a prec.
|
||||
*
|
||||
* \sa isLower(), extract(), part(), marked()
|
||||
* \sa isLowerTriangular(), extract(), part(), marked()
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isUpper(RealScalar prec) const
|
||||
bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
|
||||
{
|
||||
if(cols() != rows()) return false;
|
||||
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = 0; i <= j; i++)
|
||||
RealScalar maxAbsOnUpperTriangularPart = static_cast<RealScalar>(-1);
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = 0; i <= j; ++i)
|
||||
{
|
||||
RealScalar absValue = ei_abs(coeff(i,j));
|
||||
if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
|
||||
if(absValue > maxAbsOnUpperTriangularPart) maxAbsOnUpperTriangularPart = absValue;
|
||||
}
|
||||
for(int j = 0; j < cols()-1; j++)
|
||||
for(int i = j+1; i < rows(); i++)
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnUpperPart, prec)) return false;
|
||||
for(int j = 0; j < cols()-1; ++j)
|
||||
for(int i = j+1; i < rows(); ++i)
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnUpperTriangularPart, prec)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \returns true if *this is approximately equal to a lower triangular matrix,
|
||||
* within the precision given by \a prec.
|
||||
*
|
||||
* \sa isUpper(), extract(), part(), marked()
|
||||
* \sa isUpperTriangular(), extract(), part(), marked()
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool MatrixBase<Derived>::isLower(RealScalar prec) const
|
||||
bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
|
||||
{
|
||||
if(cols() != rows()) return false;
|
||||
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
|
||||
for(int j = 0; j < cols(); j++)
|
||||
for(int i = j; i < rows(); i++)
|
||||
RealScalar maxAbsOnLowerTriangularPart = static_cast<RealScalar>(-1);
|
||||
for(int j = 0; j < cols(); ++j)
|
||||
for(int i = j; i < rows(); ++i)
|
||||
{
|
||||
RealScalar absValue = ei_abs(coeff(i,j));
|
||||
if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
|
||||
if(absValue > maxAbsOnLowerTriangularPart) maxAbsOnLowerTriangularPart = absValue;
|
||||
}
|
||||
for(int j = 1; j < cols(); j++)
|
||||
for(int i = 0; i < j; i++)
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnLowerPart, prec)) return false;
|
||||
for(int j = 1; j < cols(); ++j)
|
||||
for(int i = 0; i < j; ++i)
|
||||
if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnLowerTriangularPart, prec)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
@@ -30,14 +30,12 @@
|
||||
*** Forward declarations ***
|
||||
***************************/
|
||||
|
||||
template<int VectorizationMode, int Index, typename Lhs, typename Rhs>
|
||||
template<int VectorizationMode, int Index, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl;
|
||||
|
||||
template<int StorageOrder, int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl;
|
||||
|
||||
template<typename T> struct ei_product_eval_to_column_major;
|
||||
|
||||
/** \class ProductReturnType
|
||||
*
|
||||
* \brief Helper class to get the correct and optimized returned type of operator*
|
||||
@@ -64,13 +62,14 @@ struct ProductReturnType
|
||||
};
|
||||
|
||||
// cache friendly specialization
|
||||
// note that there is a DiagonalProduct specialization in DiagonalProduct.h
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ProductReturnType<Lhs,Rhs,CacheFriendlyProduct>
|
||||
{
|
||||
typedef typename ei_nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
|
||||
|
||||
typedef typename ei_nested<Rhs,Lhs::RowsAtCompileTime,
|
||||
typename ei_product_eval_to_column_major<Rhs>::type
|
||||
typename ei_plain_matrix_type_column_major<Rhs>::type
|
||||
>::type RhsNested;
|
||||
|
||||
typedef Product<LhsNested, RhsNested, CacheFriendlyProduct> Type;
|
||||
@@ -79,7 +78,7 @@ struct ProductReturnType<Lhs,Rhs,CacheFriendlyProduct>
|
||||
/* Helper class to determine the type of the product, can be either:
|
||||
* - NormalProduct
|
||||
* - CacheFriendlyProduct
|
||||
* - NormalProduct
|
||||
* - DiagonalProduct
|
||||
*/
|
||||
template<typename Lhs, typename Rhs> struct ei_product_mode
|
||||
{
|
||||
@@ -87,13 +86,12 @@ template<typename Lhs, typename Rhs> struct ei_product_mode
|
||||
|
||||
value = ((Rhs::Flags&Diagonal)==Diagonal) || ((Lhs::Flags&Diagonal)==Diagonal)
|
||||
? DiagonalProduct
|
||||
: (Rhs::Flags & Lhs::Flags & SparseBit)
|
||||
? SparseProduct
|
||||
: Lhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
|
||||
&& ( Lhs::MaxRowsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
|
||||
|| Rhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD )
|
||||
: Lhs::MaxColsAtCompileTime == Dynamic
|
||||
&& ( Lhs::MaxRowsAtCompileTime == Dynamic
|
||||
|| Rhs::MaxColsAtCompileTime == Dynamic )
|
||||
&& (!(Rhs::IsVectorAtCompileTime && (Lhs::Flags&RowMajorBit) && (!(Lhs::Flags&DirectAccessBit))))
|
||||
&& (!(Lhs::IsVectorAtCompileTime && (!(Rhs::Flags&RowMajorBit)) && (!(Rhs::Flags&DirectAccessBit))))
|
||||
&& (ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)
|
||||
? CacheFriendlyProduct
|
||||
: NormalProduct };
|
||||
};
|
||||
@@ -118,9 +116,9 @@ template<typename LhsNested, typename RhsNested, int ProductMode>
|
||||
struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
|
||||
{
|
||||
// clean the nested types:
|
||||
typedef typename ei_unconst<typename ei_unref<LhsNested>::type>::type _LhsNested;
|
||||
typedef typename ei_unconst<typename ei_unref<RhsNested>::type>::type _RhsNested;
|
||||
typedef typename _LhsNested::Scalar Scalar;
|
||||
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
|
||||
typedef typename ei_cleantype<RhsNested>::type _RhsNested;
|
||||
typedef typename ei_scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
|
||||
|
||||
enum {
|
||||
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
||||
@@ -151,7 +149,8 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
|
||||
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
|
||||
| EvalBeforeAssigningBit
|
||||
| EvalBeforeNestingBit
|
||||
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0),
|
||||
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0)
|
||||
| (LhsFlags & RhsFlags & AlignedBit),
|
||||
|
||||
CoeffReadCost = InnerSize == Dynamic ? Dynamic
|
||||
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
||||
@@ -188,7 +187,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
|
||||
typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorization : NoVectorization,
|
||||
Unroll ? InnerSize-1 : Dynamic,
|
||||
_LhsNested, _RhsNested> ScalarCoeffImpl;
|
||||
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||
|
||||
public:
|
||||
|
||||
@@ -196,7 +195,13 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
inline Product(const Lhs& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
{
|
||||
ei_assert(lhs.cols() == rhs.rows());
|
||||
// we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
|
||||
// We still allow to mix T and complex<T>.
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
ei_assert(lhs.cols() == rhs.rows()
|
||||
&& "invalid matrix product"
|
||||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions");
|
||||
}
|
||||
|
||||
/** \internal
|
||||
@@ -208,17 +213,17 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
/** \internal
|
||||
* \returns whether it is worth it to use the cache friendly product.
|
||||
*/
|
||||
inline bool _useCacheFriendlyProduct() const
|
||||
EIGEN_STRONG_INLINE bool _useCacheFriendlyProduct() const
|
||||
{
|
||||
return m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
|
||||
&& ( rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
|
||||
|| cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD);
|
||||
}
|
||||
|
||||
inline int rows() const { return m_lhs.rows(); }
|
||||
inline int cols() const { return m_rhs.cols(); }
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
|
||||
EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
|
||||
|
||||
const Scalar coeff(int row, int col) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
|
||||
{
|
||||
Scalar res;
|
||||
ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
|
||||
@@ -228,7 +233,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
/* 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.
|
||||
*/
|
||||
const Scalar coeff(int index) const
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(int index) const
|
||||
{
|
||||
Scalar res;
|
||||
const int row = RowsAtCompileTime == 1 ? 0 : index;
|
||||
@@ -238,7 +243,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
const PacketScalar packet(int row, int col) const
|
||||
EIGEN_STRONG_INLINE const PacketScalar packet(int row, int col) const
|
||||
{
|
||||
PacketScalar res;
|
||||
ei_product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
|
||||
@@ -248,8 +253,8 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
||||
return res;
|
||||
}
|
||||
|
||||
inline const _LhsNested& lhs() const { return m_lhs; }
|
||||
inline const _RhsNested& rhs() const { return m_rhs; }
|
||||
EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
|
||||
EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
|
||||
|
||||
protected:
|
||||
const LhsNested m_lhs;
|
||||
@@ -267,6 +272,21 @@ template<typename OtherDerived>
|
||||
inline const typename ProductReturnType<Derived,OtherDerived>::Type
|
||||
MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &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.cwise()*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 typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
|
||||
}
|
||||
|
||||
@@ -290,41 +310,42 @@ MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
|
||||
*** Scalar path - no vectorization ***
|
||||
**************************************/
|
||||
|
||||
template<int Index, typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs>
|
||||
template<int Index, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
ei_product_coeff_impl<NoVectorization, Index-1, Lhs, Rhs>::run(row, col, lhs, rhs, res);
|
||||
ei_product_coeff_impl<NoVectorization, Index-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
|
||||
res += lhs.coeff(row, Index) * rhs.coeff(Index, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs>
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs>
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar& res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar& res)
|
||||
{
|
||||
ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
||||
for(int i = 1; i < lhs.cols(); i++)
|
||||
for(int i = 1; i < lhs.cols(); ++i)
|
||||
res += lhs.coeff(row, i) * rhs.coeff(i, col);
|
||||
}
|
||||
};
|
||||
|
||||
// prevent buggy user code from causing an infinite recursion
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs>
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
inline static void run(int, int, const Lhs&, const Rhs&, typename Lhs::Scalar&) {}
|
||||
EIGEN_STRONG_INLINE static void run(int, int, const Lhs&, const Rhs&, RetScalar&) {}
|
||||
};
|
||||
|
||||
/*******************************************
|
||||
@@ -335,7 +356,7 @@ template<int Index, typename Lhs, typename Rhs, typename PacketScalar>
|
||||
struct ei_product_coeff_vectorized_unroller
|
||||
{
|
||||
enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
{
|
||||
ei_product_coeff_vectorized_unroller<Index-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, pres);
|
||||
pres = ei_padd(pres, ei_pmul( lhs.template packet<Aligned>(row, Index) , rhs.template packet<Aligned>(Index, col) ));
|
||||
@@ -345,22 +366,22 @@ struct ei_product_coeff_vectorized_unroller
|
||||
template<typename Lhs, typename Rhs, typename PacketScalar>
|
||||
struct ei_product_coeff_vectorized_unroller<0, Lhs, Rhs, PacketScalar>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
{
|
||||
pres = ei_pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col));
|
||||
}
|
||||
};
|
||||
|
||||
template<int Index, typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs>
|
||||
template<int Index, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::PacketScalar PacketScalar;
|
||||
enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
PacketScalar pres;
|
||||
ei_product_coeff_vectorized_unroller<Index+1-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, pres);
|
||||
ei_product_coeff_impl<NoVectorization,Index,Lhs,Rhs>::run(row, col, lhs, rhs, res);
|
||||
ei_product_coeff_impl<NoVectorization,Index,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, res);
|
||||
res = ei_predux(pres);
|
||||
}
|
||||
};
|
||||
@@ -368,7 +389,7 @@ struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs>
|
||||
template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime>
|
||||
struct ei_product_coeff_vectorized_dyn_selector
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = ei_dot_impl<
|
||||
Block<Lhs, 1, ei_traits<Lhs>::ColsAtCompileTime>,
|
||||
@@ -382,7 +403,7 @@ struct ei_product_coeff_vectorized_dyn_selector
|
||||
template<typename Lhs, typename Rhs, int RhsCols>
|
||||
struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
|
||||
{
|
||||
inline static void run(int /*row*/, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int /*row*/, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = ei_dot_impl<
|
||||
Lhs,
|
||||
@@ -394,7 +415,7 @@ struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
|
||||
template<typename Lhs, typename Rhs, int LhsRows>
|
||||
struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
|
||||
{
|
||||
inline static void run(int row, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = ei_dot_impl<
|
||||
Block<Lhs, 1, ei_traits<Lhs>::ColsAtCompileTime>,
|
||||
@@ -406,7 +427,7 @@ struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
|
||||
{
|
||||
inline static void run(int /*row*/, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int /*row*/, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = ei_dot_impl<
|
||||
Lhs,
|
||||
@@ -415,10 +436,10 @@ struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs>
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, res);
|
||||
}
|
||||
@@ -431,7 +452,7 @@ struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs>
|
||||
template<int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<RowMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
{
|
||||
ei_product_packet_impl<RowMajor, Index-1, Lhs, Rhs, PacketScalar, LoadMode>::run(row, col, lhs, rhs, res);
|
||||
res = ei_pmadd(ei_pset1(lhs.coeff(row, Index)), rhs.template packet<LoadMode>(Index, col), res);
|
||||
@@ -441,7 +462,7 @@ struct ei_product_packet_impl<RowMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
template<int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<ColMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
{
|
||||
ei_product_packet_impl<ColMajor, Index-1, Lhs, Rhs, PacketScalar, LoadMode>::run(row, col, lhs, rhs, res);
|
||||
res = ei_pmadd(lhs.template packet<LoadMode>(row, Index), ei_pset1(rhs.coeff(Index, col)), res);
|
||||
@@ -451,7 +472,7 @@ struct ei_product_packet_impl<ColMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<RowMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
{
|
||||
res = ei_pmul(ei_pset1(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
||||
}
|
||||
@@ -460,7 +481,7 @@ struct ei_product_packet_impl<RowMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<ColMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
|
||||
{
|
||||
res = ei_pmul(lhs.template packet<LoadMode>(row, 0), ei_pset1(rhs.coeff(0, col)));
|
||||
}
|
||||
@@ -469,10 +490,11 @@ struct ei_product_packet_impl<ColMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
|
||||
{
|
||||
ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
||||
res = ei_pmul(ei_pset1(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
||||
for(int i = 1; i < lhs.cols(); i++)
|
||||
for(int i = 1; i < lhs.cols(); ++i)
|
||||
res = ei_pmadd(ei_pset1(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
|
||||
}
|
||||
};
|
||||
@@ -480,10 +502,11 @@ struct ei_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMod
|
||||
template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
||||
struct ei_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMode>
|
||||
{
|
||||
inline static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
|
||||
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
|
||||
{
|
||||
ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
||||
res = ei_pmul(lhs.template packet<LoadMode>(row, 0), ei_pset1(rhs.coeff(0, col)));
|
||||
for(int i = 1; i < lhs.cols(); i++)
|
||||
for(int i = 1; i < lhs.cols(); ++i)
|
||||
res = ei_pmadd(lhs.template packet<LoadMode>(row, i), ei_pset1(rhs.coeff(i, col)), res);
|
||||
}
|
||||
};
|
||||
@@ -547,7 +570,7 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
|
||||
_res = &res.coeffRef(0);
|
||||
else
|
||||
{
|
||||
_res = ei_alloc_stack(Scalar,res.size());
|
||||
_res = ei_aligned_stack_new(Scalar,res.size());
|
||||
Map<Matrix<Scalar,DestDerived::RowsAtCompileTime,1> >(_res, res.size()) = res;
|
||||
}
|
||||
ei_cache_friendly_product_colmajor_times_vector(res.size(),
|
||||
@@ -557,7 +580,7 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
|
||||
if (!EvalToRes)
|
||||
{
|
||||
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
|
||||
ei_free_stack(_res, Scalar, res.size());
|
||||
ei_aligned_stack_delete(Scalar, _res, res.size());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -593,7 +616,7 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
|
||||
_res = &res.coeffRef(0);
|
||||
else
|
||||
{
|
||||
_res = ei_alloc_stack(Scalar, res.size());
|
||||
_res = ei_aligned_stack_new(Scalar, res.size());
|
||||
Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size()) = res;
|
||||
}
|
||||
ei_cache_friendly_product_colmajor_times_vector(res.size(),
|
||||
@@ -603,7 +626,7 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
|
||||
if (!EvalToRes)
|
||||
{
|
||||
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
|
||||
ei_free_stack(_res, Scalar, res.size());
|
||||
ei_aligned_stack_delete(Scalar, _res, res.size());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -626,13 +649,13 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,RowMajor,HasDirect
|
||||
_rhs = &product.rhs().const_cast_derived().coeffRef(0);
|
||||
else
|
||||
{
|
||||
_rhs = ei_alloc_stack(Scalar, product.rhs().size());
|
||||
_rhs = ei_aligned_stack_new(Scalar, product.rhs().size());
|
||||
Map<Matrix<Scalar,Rhs::SizeAtCompileTime,1> >(_rhs, product.rhs().size()) = product.rhs();
|
||||
}
|
||||
ei_cache_friendly_product_rowmajor_times_vector(&product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
|
||||
_rhs, product.rhs().size(), res);
|
||||
|
||||
if (!UseRhsDirectly) ei_free_stack(_rhs, Scalar, product.rhs().size());
|
||||
if (!UseRhsDirectly) ei_aligned_stack_delete(Scalar, _rhs, product.rhs().size());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -654,13 +677,13 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
|
||||
_lhs = &product.lhs().const_cast_derived().coeffRef(0);
|
||||
else
|
||||
{
|
||||
_lhs = ei_alloc_stack(Scalar, product.lhs().size());
|
||||
_lhs = ei_aligned_stack_new(Scalar, product.lhs().size());
|
||||
Map<Matrix<Scalar,Lhs::SizeAtCompileTime,1> >(_lhs, product.lhs().size()) = product.lhs();
|
||||
}
|
||||
ei_cache_friendly_product_rowmajor_times_vector(&product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
|
||||
_lhs, product.lhs().size(), res);
|
||||
|
||||
if(!UseLhsDirectly) ei_free_stack(_lhs, Scalar, product.lhs().size());
|
||||
if(!UseLhsDirectly) ei_aligned_stack_delete(Scalar, _lhs, product.lhs().size());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -706,23 +729,12 @@ inline Derived& MatrixBase<Derived>::lazyAssign(const Product<Lhs,Rhs,CacheFrien
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<typename T> struct ei_product_eval_to_column_major
|
||||
{
|
||||
typedef Matrix<typename ei_traits<T>::Scalar,
|
||||
ei_traits<T>::RowsAtCompileTime,
|
||||
ei_traits<T>::ColsAtCompileTime,
|
||||
ColMajor,
|
||||
ei_traits<T>::MaxRowsAtCompileTime,
|
||||
ei_traits<T>::MaxColsAtCompileTime
|
||||
> type;
|
||||
};
|
||||
|
||||
template<typename T> struct ei_product_copy_rhs
|
||||
{
|
||||
typedef typename ei_meta_if<
|
||||
(ei_traits<T>::Flags & RowMajorBit)
|
||||
|| (!(ei_traits<T>::Flags & DirectAccessBit)),
|
||||
typename ei_product_eval_to_column_major<T>::type,
|
||||
typename ei_plain_matrix_type_column_major<T>::type,
|
||||
const T&
|
||||
>::ret type;
|
||||
};
|
||||
@@ -731,7 +743,7 @@ template<typename T> struct ei_product_copy_lhs
|
||||
{
|
||||
typedef typename ei_meta_if<
|
||||
(!(int(ei_traits<T>::Flags) & DirectAccessBit)),
|
||||
typename ei_eval<T>::type,
|
||||
typename ei_plain_matrix_type<T>::type,
|
||||
const T&
|
||||
>::ret type;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -65,12 +65,13 @@ struct ei_redux_impl<BinaryOp, Derived, Start, Dynamic>
|
||||
typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
|
||||
static Scalar run(const Derived& mat, const BinaryOp& func)
|
||||
{
|
||||
ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
|
||||
Scalar res;
|
||||
res = mat.coeff(0,0);
|
||||
for(int i = 1; i < mat.rows(); i++)
|
||||
for(int i = 1; i < mat.rows(); ++i)
|
||||
res = func(res, mat.coeff(i, 0));
|
||||
for(int j = 1; j < mat.cols(); j++)
|
||||
for(int i = 0; i < mat.rows(); i++)
|
||||
for(int j = 1; j < mat.cols(); ++j)
|
||||
for(int i = 0; i < mat.rows(); ++i)
|
||||
res = func(res, mat.coeff(i, j));
|
||||
return res;
|
||||
}
|
||||
|
||||
120
Eigen/src/Core/SolveTriangular.h
Executable file → Normal file
120
Eigen/src/Core/SolveTriangular.h
Executable file → Normal file
@@ -30,9 +30,9 @@ template<typename XprType, unsigned int Mode> struct ei_is_part<Part<XprType,Mod
|
||||
|
||||
template<typename Lhs, typename Rhs,
|
||||
int TriangularPart = (int(Lhs::Flags) & LowerTriangularBit)
|
||||
? Lower
|
||||
? LowerTriangular
|
||||
: (int(Lhs::Flags) & UpperTriangularBit)
|
||||
? Upper
|
||||
? UpperTriangular
|
||||
: -1,
|
||||
int StorageOrder = ei_is_part<Lhs>::value ? -1 // this is to solve ambiguous specializations
|
||||
: int(Lhs::Flags) & (RowMajorBit|SparseBit)
|
||||
@@ -56,14 +56,14 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
|
||||
typedef typename Rhs::Scalar Scalar;
|
||||
static void run(const Lhs& lhs, Rhs& other)
|
||||
{
|
||||
const bool IsLower = (UpLo==Lower);
|
||||
const bool IsLowerTriangular = (UpLo==LowerTriangular);
|
||||
const int size = lhs.cols();
|
||||
/* We perform the inverse product per block of 4 rows such that we perfectly match
|
||||
* our optimized matrix * vector product. blockyStart represents the number of rows
|
||||
* we have process first using the non-block version.
|
||||
*/
|
||||
int blockyStart = (std::max(size-5,0)/4)*4;
|
||||
if (IsLower)
|
||||
if (IsLowerTriangular)
|
||||
blockyStart = size - blockyStart;
|
||||
else
|
||||
blockyStart -= 1;
|
||||
@@ -72,15 +72,15 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
|
||||
// process first rows using the non block version
|
||||
if(!(Lhs::Flags & UnitDiagBit))
|
||||
{
|
||||
if (IsLower)
|
||||
if (IsLowerTriangular)
|
||||
other.coeffRef(0,c) = other.coeff(0,c)/lhs.coeff(0, 0);
|
||||
else
|
||||
other.coeffRef(size-1,c) = other.coeff(size-1, c)/lhs.coeff(size-1, size-1);
|
||||
}
|
||||
for(int i=(IsLower ? 1 : size-2); IsLower ? i<blockyStart : i>blockyStart; i += (IsLower ? 1 : -1) )
|
||||
for(int i=(IsLowerTriangular ? 1 : size-2); IsLowerTriangular ? i<blockyStart : i>blockyStart; i += (IsLowerTriangular ? 1 : -1) )
|
||||
{
|
||||
Scalar tmp = other.coeff(i,c)
|
||||
- (IsLower ? ((lhs.row(i).start(i)) * other.col(c).start(i)).coeff(0,0)
|
||||
- (IsLowerTriangular ? ((lhs.row(i).start(i)) * other.col(c).start(i)).coeff(0,0)
|
||||
: ((lhs.row(i).end(size-i-1)) * other.col(c).end(size-i-1)).coeff(0,0));
|
||||
if (Lhs::Flags & UnitDiagBit)
|
||||
other.coeffRef(i,c) = tmp;
|
||||
@@ -88,39 +88,39 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
|
||||
other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
|
||||
}
|
||||
|
||||
// now let process the remaining rows 4 at once
|
||||
for(int i=blockyStart; IsLower ? i<size : i>0; )
|
||||
// now let's process the remaining rows 4 at once
|
||||
for(int i=blockyStart; IsLowerTriangular ? i<size : i>0; )
|
||||
{
|
||||
int startBlock = i;
|
||||
int endBlock = startBlock + (IsLower ? 4 : -4);
|
||||
|
||||
int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
|
||||
|
||||
/* Process the i cols times 4 rows block, and keep the result in a temporary vector */
|
||||
// FIXME use fixed size block but take care to small fixed size matrices...
|
||||
Matrix<Scalar,Dynamic,1> btmp(4);
|
||||
if (IsLower)
|
||||
if (IsLowerTriangular)
|
||||
btmp = lhs.block(startBlock,0,4,i) * other.col(c).start(i);
|
||||
else
|
||||
btmp = lhs.block(i-3,i+1,4,size-1-i) * other.col(c).end(size-1-i);
|
||||
|
||||
|
||||
/* Let's process the 4x4 sub-matrix as usual.
|
||||
* btmp stores the diagonal coefficients used to update the remaining part of the result.
|
||||
*/
|
||||
{
|
||||
Scalar tmp = other.coeff(startBlock,c)-btmp.coeff(IsLower?0:3);
|
||||
Scalar tmp = other.coeff(startBlock,c)-btmp.coeff(IsLowerTriangular?0:3);
|
||||
if (Lhs::Flags & UnitDiagBit)
|
||||
other.coeffRef(i,c) = tmp;
|
||||
else
|
||||
other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
|
||||
}
|
||||
|
||||
i += IsLower ? 1 : -1;
|
||||
for (;IsLower ? i<endBlock : i>endBlock; i += IsLower ? 1 : -1)
|
||||
i += IsLowerTriangular ? 1 : -1;
|
||||
for (;IsLowerTriangular ? i<endBlock : i>endBlock; i += IsLowerTriangular ? 1 : -1)
|
||||
{
|
||||
int remainingSize = IsLower ? i-startBlock : startBlock-i;
|
||||
int remainingSize = IsLowerTriangular ? i-startBlock : startBlock-i;
|
||||
Scalar tmp = other.coeff(i,c)
|
||||
- btmp.coeff(IsLower ? remainingSize : 3-remainingSize)
|
||||
- ( lhs.row(i).block(IsLower ? startBlock : i+1, remainingSize)
|
||||
* other.col(c).block(IsLower ? startBlock : i+1, remainingSize)).coeff(0,0);
|
||||
- btmp.coeff(IsLowerTriangular ? remainingSize : 3-remainingSize)
|
||||
- ( lhs.row(i).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)
|
||||
* other.col(c).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)).coeff(0,0);
|
||||
|
||||
if (Lhs::Flags & UnitDiagBit)
|
||||
other.coeffRef(i,c) = tmp;
|
||||
@@ -133,10 +133,10 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
|
||||
};
|
||||
|
||||
// Implements the following configurations:
|
||||
// - inv(Lower, ColMajor) * Column vector
|
||||
// - inv(Lower,UnitDiag,ColMajor) * Column vector
|
||||
// - inv(Upper, ColMajor) * Column vector
|
||||
// - inv(Upper,UnitDiag,ColMajor) * Column vector
|
||||
// - inv(LowerTriangular, ColMajor) * Column vector
|
||||
// - inv(LowerTriangular,UnitDiag,ColMajor) * Column vector
|
||||
// - inv(UpperTriangular, ColMajor) * Column vector
|
||||
// - inv(UpperTriangular,UnitDiag,ColMajor) * Column vector
|
||||
template<typename Lhs, typename Rhs, int UpLo>
|
||||
struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
{
|
||||
@@ -146,7 +146,7 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
|
||||
static void run(const Lhs& lhs, Rhs& other)
|
||||
{
|
||||
static const bool IsLower = (UpLo==Lower);
|
||||
static const bool IsLowerTriangular = (UpLo==LowerTriangular);
|
||||
const int size = lhs.cols();
|
||||
for(int c=0 ; c<other.cols() ; ++c)
|
||||
{
|
||||
@@ -155,27 +155,27 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
* we can process using the block version.
|
||||
*/
|
||||
int blockyEnd = (std::max(size-5,0)/4)*4;
|
||||
if (!IsLower)
|
||||
if (!IsLowerTriangular)
|
||||
blockyEnd = size-1 - blockyEnd;
|
||||
for(int i=IsLower ? 0 : size-1; IsLower ? i<blockyEnd : i>blockyEnd;)
|
||||
for(int i=IsLowerTriangular ? 0 : size-1; IsLowerTriangular ? i<blockyEnd : i>blockyEnd;)
|
||||
{
|
||||
/* Let's process the 4x4 sub-matrix as usual.
|
||||
* btmp stores the diagonal coefficients used to update the remaining part of the result.
|
||||
*/
|
||||
int startBlock = i;
|
||||
int endBlock = startBlock + (IsLower ? 4 : -4);
|
||||
int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
|
||||
Matrix<Scalar,4,1> btmp;
|
||||
for (;IsLower ? i<endBlock : i>endBlock;
|
||||
i += IsLower ? 1 : -1)
|
||||
for (;IsLowerTriangular ? i<endBlock : i>endBlock;
|
||||
i += IsLowerTriangular ? 1 : -1)
|
||||
{
|
||||
if(!(Lhs::Flags & UnitDiagBit))
|
||||
other.coeffRef(i,c) /= lhs.coeff(i,i);
|
||||
int remainingSize = IsLower ? endBlock-i-1 : i-endBlock-1;
|
||||
int remainingSize = IsLowerTriangular ? endBlock-i-1 : i-endBlock-1;
|
||||
if (remainingSize>0)
|
||||
other.col(c).block((IsLower ? i : endBlock) + 1, remainingSize) -=
|
||||
other.col(c).segment((IsLowerTriangular ? i : endBlock) + 1, remainingSize) -=
|
||||
other.coeffRef(i,c)
|
||||
* Block<Lhs,Dynamic,1>(lhs, (IsLower ? i : endBlock) + 1, i, remainingSize, 1);
|
||||
btmp.coeffRef(IsLower ? i-startBlock : remainingSize) = -other.coeffRef(i,c);
|
||||
* Block<Lhs,Dynamic,1>(lhs, (IsLowerTriangular ? i : endBlock) + 1, i, remainingSize, 1);
|
||||
btmp.coeffRef(IsLowerTriangular ? i-startBlock : remainingSize) = -other.coeffRef(i,c);
|
||||
}
|
||||
|
||||
/* Now we can efficiently update the remaining part of the result as a matrix * vector product.
|
||||
@@ -187,15 +187,21 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
// FIXME this is cool but what about conjugate/adjoint expressions ? do we want to evaluate them ?
|
||||
// this is a more general problem though.
|
||||
ei_cache_friendly_product_colmajor_times_vector(
|
||||
IsLower ? size-endBlock : endBlock+1,
|
||||
&(lhs.const_cast_derived().coeffRef(IsLower ? endBlock : 0, IsLower ? startBlock : endBlock+1)),
|
||||
IsLowerTriangular ? size-endBlock : endBlock+1,
|
||||
&(lhs.const_cast_derived().coeffRef(IsLowerTriangular ? endBlock : 0, IsLowerTriangular ? startBlock : endBlock+1)),
|
||||
lhs.stride(),
|
||||
btmp, &(other.coeffRef(IsLower ? endBlock : 0, c)));
|
||||
btmp, &(other.coeffRef(IsLowerTriangular ? endBlock : 0, c)));
|
||||
// if (IsLowerTriangular)
|
||||
// other.col(c).end(size-endBlock) += (lhs.block(endBlock, startBlock, size-endBlock, endBlock-startBlock)
|
||||
// * other.col(c).block(startBlock,endBlock-startBlock)).lazy();
|
||||
// else
|
||||
// other.col(c).end(size-endBlock) += (lhs.block(endBlock, startBlock, size-endBlock, endBlock-startBlock)
|
||||
// * other.col(c).block(startBlock,endBlock-startBlock)).lazy();
|
||||
}
|
||||
|
||||
/* Now we have to process the remaining part as usual */
|
||||
int i;
|
||||
for(i=blockyEnd; IsLower ? i<size-1 : i>0; i += (IsLower ? 1 : -1) )
|
||||
for(i=blockyEnd; IsLowerTriangular ? i<size-1 : i>0; i += (IsLowerTriangular ? 1 : -1) )
|
||||
{
|
||||
if(!(Lhs::Flags & UnitDiagBit))
|
||||
other.coeffRef(i,c) /= lhs.coeff(i,i);
|
||||
@@ -203,7 +209,7 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
/* NOTE we cannot use lhs.col(i).end(size-i-1) because Part::coeffRef gets called by .col() to
|
||||
* get the address of the start of the row
|
||||
*/
|
||||
if(IsLower)
|
||||
if(IsLowerTriangular)
|
||||
other.col(c).end(size-i-1) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, i+1,i, size-i-1,1);
|
||||
else
|
||||
other.col(c).start(i) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, 0,i, i, 1);
|
||||
@@ -215,22 +221,39 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
|
||||
};
|
||||
|
||||
/** "in-place" version of MatrixBase::solveTriangular() where the result is written in \a other
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* See MatrixBase:solveTriangular() for the details.
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
|
||||
void MatrixBase<Derived>::solveTriangularInPlace(const MatrixBase<OtherDerived>& _other) const
|
||||
{
|
||||
MatrixBase<OtherDerived>& other = _other.const_cast_derived();
|
||||
ei_assert(derived().cols() == derived().rows());
|
||||
ei_assert(derived().cols() == other.rows());
|
||||
ei_assert(!(Flags & ZeroDiagBit));
|
||||
ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
|
||||
|
||||
ei_solve_triangular_selector<Derived, OtherDerived>::run(derived(), other.derived());
|
||||
enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
|
||||
|
||||
typedef typename ei_meta_if<copy,
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
|
||||
OtherCopy otherCopy(other.derived());
|
||||
|
||||
ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
|
||||
|
||||
if (copy)
|
||||
other = otherCopy;
|
||||
}
|
||||
|
||||
/** \returns the product of the inverse of \c *this with \a other, \a *this being triangular.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* This function computes the inverse-matrix matrix product inverse(\c *this) * \a other.
|
||||
* The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the
|
||||
@@ -240,17 +263,17 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
|
||||
* It is required that \c *this be marked as either an upper or a lower triangular matrix, which
|
||||
* can be done by marked(), and that is automatically the case with expressions such as those returned
|
||||
* by extract().
|
||||
*
|
||||
*
|
||||
* \addexample SolveTriangular \label How to solve a triangular system (aka. how to multiply the inverse of a triangular matrix by another one)
|
||||
*
|
||||
*
|
||||
* Example: \include MatrixBase_marked.cpp
|
||||
* Output: \verbinclude MatrixBase_marked.out
|
||||
*
|
||||
*
|
||||
* This function is essentially a wrapper to the faster solveTriangularInPlace() function creating
|
||||
* a temporary copy of \a other, calling solveTriangularInPlace() on the copy and returning it.
|
||||
* Therefore, if \a other is not needed anymore, it is quite faster to call solveTriangularInPlace()
|
||||
* instead of solveTriangular().
|
||||
*
|
||||
*
|
||||
* For users coming from BLAS, this function (and more specifically solveTriangularInPlace()) offer
|
||||
* all the operations supported by the \c *TRSV and \c *TRSM BLAS routines.
|
||||
*
|
||||
@@ -258,14 +281,15 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
|
||||
* \code
|
||||
* M * T^1 <=> T.transpose().solveTriangularInPlace(M.transpose());
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
* \sa solveTriangularInPlace(), marked(), extract()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename OtherDerived::Eval MatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
||||
MatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
typename OtherDerived::Eval res(other);
|
||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
|
||||
solveTriangularInPlace(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,7 +42,6 @@ public:
|
||||
enum {
|
||||
Vectorization = (int(Derived::Flags)&ActualPacketAccessBit)
|
||||
&& (int(Derived::Flags)&LinearAccessBit)
|
||||
&& (int(Derived::SizeAtCompileTime)>2*PacketSize)
|
||||
? LinearVectorization
|
||||
: NoVectorization
|
||||
};
|
||||
@@ -101,18 +100,13 @@ struct ei_sum_novec_unroller<Derived, Start, 1>
|
||||
};
|
||||
|
||||
/*** vectorization ***/
|
||||
|
||||
template<typename Derived, int Index, int Stop,
|
||||
bool LastPacket = (Stop-Index == ei_packet_traits<typename Derived::Scalar>::size)>
|
||||
|
||||
template<typename Derived, int Start, int Length>
|
||||
struct ei_sum_vec_unroller
|
||||
{
|
||||
enum {
|
||||
row = int(Derived::Flags)&RowMajorBit
|
||||
? Index / int(Derived::ColsAtCompileTime)
|
||||
: Index % Derived::RowsAtCompileTime,
|
||||
col = int(Derived::Flags)&RowMajorBit
|
||||
? Index % int(Derived::ColsAtCompileTime)
|
||||
: Index / Derived::RowsAtCompileTime
|
||||
PacketSize = ei_packet_traits<typename Derived::Scalar>::size,
|
||||
HalfLength = Length/2
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
@@ -121,22 +115,22 @@ struct ei_sum_vec_unroller
|
||||
inline static PacketScalar run(const Derived &mat)
|
||||
{
|
||||
return ei_padd(
|
||||
mat.template packet<Aligned>(row, col),
|
||||
ei_sum_vec_unroller<Derived, Index+ei_packet_traits<typename Derived::Scalar>::size, Stop>::run(mat)
|
||||
);
|
||||
ei_sum_vec_unroller<Derived, Start, HalfLength>::run(mat),
|
||||
ei_sum_vec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Index, int Stop>
|
||||
struct ei_sum_vec_unroller<Derived, Index, Stop, true>
|
||||
template<typename Derived, int Start>
|
||||
struct ei_sum_vec_unroller<Derived, Start, 1>
|
||||
{
|
||||
enum {
|
||||
index = Start * ei_packet_traits<typename Derived::Scalar>::size,
|
||||
row = int(Derived::Flags)&RowMajorBit
|
||||
? Index / int(Derived::ColsAtCompileTime)
|
||||
: Index % Derived::RowsAtCompileTime,
|
||||
? index / int(Derived::ColsAtCompileTime)
|
||||
: index % Derived::RowsAtCompileTime,
|
||||
col = int(Derived::Flags)&RowMajorBit
|
||||
? Index % int(Derived::ColsAtCompileTime)
|
||||
: Index / Derived::RowsAtCompileTime,
|
||||
? index % int(Derived::ColsAtCompileTime)
|
||||
: index / Derived::RowsAtCompileTime,
|
||||
alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned
|
||||
};
|
||||
|
||||
@@ -165,12 +159,13 @@ struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
static Scalar run(const Derived& mat)
|
||||
{
|
||||
ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
|
||||
Scalar res;
|
||||
res = mat.coeff(0, 0);
|
||||
for(int i = 1; i < mat.rows(); i++)
|
||||
for(int i = 1; i < mat.rows(); ++i)
|
||||
res += mat.coeff(i, 0);
|
||||
for(int j = 1; j < mat.cols(); j++)
|
||||
for(int i = 0; i < mat.rows(); i++)
|
||||
for(int j = 1; j < mat.cols(); ++j)
|
||||
for(int i = 0; i < mat.rows(); ++i)
|
||||
res += mat.coeff(i, j);
|
||||
return res;
|
||||
}
|
||||
@@ -216,10 +211,10 @@ struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
|
||||
res = Scalar(0);
|
||||
}
|
||||
|
||||
for(int index = 0; index < alignedStart; index++)
|
||||
for(int index = 0; index < alignedStart; ++index)
|
||||
res += mat.coeff(index);
|
||||
|
||||
for(int index = alignedEnd; index < size; index++)
|
||||
for(int index = alignedEnd; index < size; ++index)
|
||||
res += mat.coeff(index);
|
||||
|
||||
return res;
|
||||
@@ -230,11 +225,18 @@ template<typename Derived>
|
||||
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
|
||||
enum {
|
||||
PacketSize = ei_packet_traits<Scalar>::size,
|
||||
Size = Derived::SizeAtCompileTime,
|
||||
VectorizationSize = (Size / PacketSize) * PacketSize
|
||||
};
|
||||
static Scalar run(const Derived& mat)
|
||||
{
|
||||
return ei_predux(
|
||||
ei_sum_vec_unroller<Derived, 0, Derived::SizeAtCompileTime>::run(mat)
|
||||
);
|
||||
Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, Size / PacketSize>::run(mat));
|
||||
if (VectorizationSize != Size)
|
||||
res += ei_sum_novec_unroller<Derived, VectorizationSize, Size-VectorizationSize>::run(mat);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -63,8 +63,6 @@ template<typename MatrixType> class Transpose
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
inline Transpose(const MatrixType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
|
||||
@@ -127,7 +125,20 @@ template<typename MatrixType> class Transpose
|
||||
* Example: \include MatrixBase_transpose.cpp
|
||||
* Output: \verbinclude MatrixBase_transpose.out
|
||||
*
|
||||
* \sa adjoint(), class DiagonalCoeffs */
|
||||
* \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<typename Derived>
|
||||
inline Transpose<Derived>
|
||||
MatrixBase<Derived>::transpose()
|
||||
@@ -135,7 +146,11 @@ MatrixBase<Derived>::transpose()
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** This is the const version of transpose(). \sa adjoint() */
|
||||
/** This is the const version of transpose().
|
||||
*
|
||||
* Make sure you read the warning for transpose() !
|
||||
*
|
||||
* \sa transposeInPlace(), adjoint() */
|
||||
template<typename Derived>
|
||||
inline const Transpose<Derived>
|
||||
MatrixBase<Derived>::transpose() const
|
||||
@@ -148,6 +163,15 @@ MatrixBase<Derived>::transpose() const
|
||||
* 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, do:
|
||||
* \code
|
||||
* m = m.adjoint().eval();
|
||||
* \endcode
|
||||
*
|
||||
* \sa transpose(), conjugate(), class Transpose, class ei_scalar_conjugate_op */
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::AdjointReturnType
|
||||
@@ -156,4 +180,49 @@ MatrixBase<Derived>::adjoint() const
|
||||
return conjugate().nestByValue();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* "in place" transpose implementation
|
||||
***************************************************************************/
|
||||
|
||||
template<typename MatrixType,
|
||||
bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
|
||||
struct ei_inplace_transpose_selector;
|
||||
|
||||
template<typename MatrixType>
|
||||
struct ei_inplace_transpose_selector<MatrixType,true> { // square matrix
|
||||
static void run(MatrixType& m) {
|
||||
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
|
||||
static void run(MatrixType& m) {
|
||||
if (m.rows()==m.cols())
|
||||
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
|
||||
else
|
||||
m = m.transpose().eval();
|
||||
}
|
||||
};
|
||||
|
||||
/** This is the "in place" version of transpose: it transposes \c *this.
|
||||
*
|
||||
* In most cases it is probably better to simply use the transposed expression
|
||||
* of a matrix. However, when transposing the matrix data itself is really needed,
|
||||
* then this "in-place" version is probably the right choice because it provides
|
||||
* the following additional features:
|
||||
* - less error prone: doing the same operation with .transpose() requires special care:
|
||||
* \code m = m.transpose().eval(); \endcode
|
||||
* - no temporary object is created (currently only for squared matrices)
|
||||
* - it allows future optimizations (cache friendliness, etc.)
|
||||
*
|
||||
* \note if the matrix is not square, then \c *this must be a resizable matrix.
|
||||
*
|
||||
* \sa transpose(), adjoint() */
|
||||
template<typename Derived>
|
||||
inline void MatrixBase<Derived>::transposeInPlace()
|
||||
{
|
||||
ei_inplace_transpose_selector<Derived>::run(derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_TRANSPOSE_H
|
||||
|
||||
@@ -55,10 +55,10 @@ struct ei_visitor_impl<Visitor, Derived, Dynamic>
|
||||
inline static void run(const Derived& mat, Visitor& visitor)
|
||||
{
|
||||
visitor.init(mat.coeff(0,0), 0, 0);
|
||||
for(int i = 1; i < mat.rows(); i++)
|
||||
for(int i = 1; i < mat.rows(); ++i)
|
||||
visitor(mat.coeff(i, 0), i, 0);
|
||||
for(int j = 1; j < mat.cols(); j++)
|
||||
for(int i = 0; i < mat.rows(); i++)
|
||||
for(int j = 1; j < mat.cols(); ++j)
|
||||
for(int i = 0; i < mat.rows(); ++i)
|
||||
visitor(mat.coeff(i, j), i, j);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,17 +37,21 @@ template<> struct ei_unpacket_traits<__m128> { typedef float type; enum {size=
|
||||
template<> struct ei_unpacket_traits<__m128d> { typedef double type; enum {size=2}; };
|
||||
template<> struct ei_unpacket_traits<__m128i> { typedef int type; enum {size=4}; };
|
||||
|
||||
template<> inline __m128 ei_padd(const __m128& a, const __m128& b) { return _mm_add_ps(a,b); }
|
||||
template<> inline __m128d ei_padd(const __m128d& a, const __m128d& b) { return _mm_add_pd(a,b); }
|
||||
template<> inline __m128i ei_padd(const __m128i& a, const __m128i& b) { return _mm_add_epi32(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pset1<float>(const float& from) { return _mm_set1_ps(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pset1<double>(const double& from) { return _mm_set1_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pset1<int>(const int& from) { return _mm_set1_epi32(from); }
|
||||
|
||||
template<> inline __m128 ei_psub(const __m128& a, const __m128& b) { return _mm_sub_ps(a,b); }
|
||||
template<> inline __m128d ei_psub(const __m128d& a, const __m128d& b) { return _mm_sub_pd(a,b); }
|
||||
template<> inline __m128i ei_psub(const __m128i& a, const __m128i& b) { return _mm_sub_epi32(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_padd<__m128>(const __m128& a, const __m128& b) { return _mm_add_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_padd<__m128d>(const __m128d& a, const __m128d& b) { return _mm_add_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_padd<__m128i>(const __m128i& a, const __m128i& b) { return _mm_add_epi32(a,b); }
|
||||
|
||||
template<> inline __m128 ei_pmul(const __m128& a, const __m128& b) { return _mm_mul_ps(a,b); }
|
||||
template<> inline __m128d ei_pmul(const __m128d& a, const __m128d& b) { return _mm_mul_pd(a,b); }
|
||||
template<> inline __m128i ei_pmul(const __m128i& a, const __m128i& b)
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_psub<__m128>(const __m128& a, const __m128& b) { return _mm_sub_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_psub<__m128d>(const __m128d& a, const __m128d& b) { return _mm_sub_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_psub<__m128i>(const __m128i& a, const __m128i& b) { return _mm_sub_epi32(a,b); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pmul<__m128>(const __m128& a, const __m128& b) { return _mm_mul_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pmul<__m128d>(const __m128d& a, const __m128d& b) { return _mm_mul_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pmul<__m128i>(const __m128i& a, const __m128i& b)
|
||||
{
|
||||
return _mm_or_si128(
|
||||
_mm_and_si128(
|
||||
@@ -59,108 +63,111 @@ template<> inline __m128i ei_pmul(const __m128i& a, const __m128i& b)
|
||||
_mm_setr_epi32(0xffffffff,0,0xffffffff,0)), 4));
|
||||
}
|
||||
|
||||
template<> inline __m128 ei_pdiv(const __m128& a, const __m128& b) { return _mm_div_ps(a,b); }
|
||||
template<> inline __m128d ei_pdiv(const __m128d& a, const __m128d& b) { return _mm_div_pd(a,b); }
|
||||
template<> inline __m128i ei_pdiv(const __m128i& /*a*/, const __m128i& /*b*/)
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pdiv<__m128>(const __m128& a, const __m128& b) { return _mm_div_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pdiv<__m128d>(const __m128d& a, const __m128d& b) { return _mm_div_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pdiv<__m128i>(const __m128i& /*a*/, const __m128i& /*b*/)
|
||||
{ ei_assert(false && "packet integer division are not supported by SSE");
|
||||
__m128i dummy;
|
||||
__m128i dummy = ei_pset1<int>(0);
|
||||
return dummy;
|
||||
}
|
||||
|
||||
// for some weird raisons, it has to be overloaded for packet integer
|
||||
template<> inline __m128i ei_pmadd(const __m128i& a, const __m128i& b, const __m128i& c) { return ei_padd(ei_pmul(a,b), c); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pmadd(const __m128i& a, const __m128i& b, const __m128i& c) { return ei_padd(ei_pmul(a,b), c); }
|
||||
|
||||
template<> inline __m128 ei_pmin(const __m128& a, const __m128& b) { return _mm_min_ps(a,b); }
|
||||
template<> inline __m128d ei_pmin(const __m128d& a, const __m128d& b) { return _mm_min_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pmin<__m128>(const __m128& a, const __m128& b) { return _mm_min_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pmin<__m128d>(const __m128d& a, const __m128d& b) { return _mm_min_pd(a,b); }
|
||||
// FIXME this vectorized min operator is likely to be slower than the standard one
|
||||
template<> inline __m128i ei_pmin(const __m128i& a, const __m128i& b)
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pmin<__m128i>(const __m128i& a, const __m128i& b)
|
||||
{
|
||||
__m128i mask = _mm_cmplt_epi32(a,b);
|
||||
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
||||
}
|
||||
|
||||
template<> inline __m128 ei_pmax(const __m128& a, const __m128& b) { return _mm_max_ps(a,b); }
|
||||
template<> inline __m128d ei_pmax(const __m128d& a, const __m128d& b) { return _mm_max_pd(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pmax<__m128>(const __m128& a, const __m128& b) { return _mm_max_ps(a,b); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pmax<__m128d>(const __m128d& a, const __m128d& b) { return _mm_max_pd(a,b); }
|
||||
// FIXME this vectorized max operator is likely to be slower than the standard one
|
||||
template<> inline __m128i ei_pmax(const __m128i& a, const __m128i& b)
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pmax<__m128i>(const __m128i& a, const __m128i& b)
|
||||
{
|
||||
__m128i mask = _mm_cmpgt_epi32(a,b);
|
||||
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
||||
}
|
||||
|
||||
template<> inline __m128 ei_pload(const float* from) { return _mm_load_ps(from); }
|
||||
template<> inline __m128d ei_pload(const double* from) { return _mm_load_pd(from); }
|
||||
template<> inline __m128i ei_pload(const int* from) { return _mm_load_si128(reinterpret_cast<const __m128i*>(from)); }
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_pload<float>(const float* from) { return _mm_load_ps(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_pload<double>(const double* from) { return _mm_load_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_pload<int>(const int* from) { return _mm_load_si128(reinterpret_cast<const __m128i*>(from)); }
|
||||
|
||||
template<> inline __m128 ei_ploadu(const float* from) { return _mm_loadu_ps(from); }
|
||||
// template<> inline __m128 ei_ploadu(const float* from) {
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_ploadu<float>(const float* from) { return _mm_loadu_ps(from); }
|
||||
// template<> EIGEN_STRONG_INLINE __m128 ei_ploadu(const float* from) {
|
||||
// if (size_t(from)&0xF)
|
||||
// return _mm_loadu_ps(from);
|
||||
// else
|
||||
// return _mm_loadu_ps(from);
|
||||
// }
|
||||
template<> inline __m128d ei_ploadu(const double* from) { return _mm_loadu_pd(from); }
|
||||
template<> inline __m128i ei_ploadu(const int* from) { return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); }
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_ploadu<double>(const double* from) { return _mm_loadu_pd(from); }
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_ploadu<int>(const int* from) { return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); }
|
||||
|
||||
template<> inline __m128 ei_pset1(const float& from) { return _mm_set1_ps(from); }
|
||||
template<> inline __m128d ei_pset1(const double& from) { return _mm_set1_pd(from); }
|
||||
template<> inline __m128i ei_pset1(const int& from) { return _mm_set1_epi32(from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<float>(float* to, const __m128& from) { _mm_store_ps(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<double>(double* to, const __m128d& from) { _mm_store_pd(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstore<int>(int* to, const __m128i& from) { _mm_store_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
|
||||
template<> inline void ei_pstore(float* to, const __m128& from) { _mm_store_ps(to, from); }
|
||||
template<> inline void ei_pstore(double* to, const __m128d& from) { _mm_store_pd(to, from); }
|
||||
template<> inline void ei_pstore(int* to, const __m128i& from) { _mm_store_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstoreu<float>(float* to, const __m128& from) { _mm_storeu_ps(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstoreu<double>(double* to, const __m128d& from) { _mm_storeu_pd(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void ei_pstoreu<int>(int* to, const __m128i& from) { _mm_storeu_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
|
||||
template<> inline void ei_pstoreu(float* to, const __m128& from) { _mm_storeu_ps(to, from); }
|
||||
template<> inline void ei_pstoreu(double* to, const __m128d& from) { _mm_storeu_pd(to, from); }
|
||||
template<> inline void ei_pstoreu(int* to, const __m128i& from) { _mm_storeu_si128(reinterpret_cast<__m128i*>(to), from); }
|
||||
|
||||
template<> inline float ei_pfirst(const __m128& a) { return _mm_cvtss_f32(a); }
|
||||
template<> inline double ei_pfirst(const __m128d& a) { return _mm_cvtsd_f64(a); }
|
||||
template<> inline int ei_pfirst(const __m128i& a) { return _mm_cvtsi128_si32(a); }
|
||||
#ifdef _MSC_VER
|
||||
// this fix internal compilation error
|
||||
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
|
||||
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { double x = _mm_cvtsd_f64(a); return x; }
|
||||
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
|
||||
#else
|
||||
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return _mm_cvtss_f32(a); }
|
||||
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return _mm_cvtsd_f64(a); }
|
||||
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { return _mm_cvtsi128_si32(a); }
|
||||
#endif
|
||||
|
||||
#ifdef __SSE3__
|
||||
// TODO implement SSE2 versions as well as integer versions
|
||||
inline __m128 ei_preduxp(const __m128* vecs)
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_preduxp<__m128>(const __m128* vecs)
|
||||
{
|
||||
return _mm_hadd_ps(_mm_hadd_ps(vecs[0], vecs[1]),_mm_hadd_ps(vecs[2], vecs[3]));
|
||||
}
|
||||
inline __m128d ei_preduxp(const __m128d* vecs)
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_preduxp<__m128d>(const __m128d* vecs)
|
||||
{
|
||||
return _mm_hadd_pd(vecs[0], vecs[1]);
|
||||
}
|
||||
// SSSE3 version:
|
||||
// inline __m128i ei_preduxp(const __m128i* vecs)
|
||||
// EIGEN_STRONG_INLINE __m128i ei_preduxp(const __m128i* vecs)
|
||||
// {
|
||||
// return _mm_hadd_epi32(_mm_hadd_epi32(vecs[0], vecs[1]),_mm_hadd_epi32(vecs[2], vecs[3]));
|
||||
// }
|
||||
|
||||
inline float ei_predux(const __m128& a)
|
||||
template<> EIGEN_STRONG_INLINE float ei_predux<__m128>(const __m128& a)
|
||||
{
|
||||
__m128 tmp0 = _mm_hadd_ps(a,a);
|
||||
return ei_pfirst(_mm_hadd_ps(tmp0, tmp0));
|
||||
}
|
||||
|
||||
inline double ei_predux(const __m128d& a) { return ei_pfirst(_mm_hadd_pd(a, a)); }
|
||||
template<> EIGEN_STRONG_INLINE double ei_predux<__m128d>(const __m128d& a) { return ei_pfirst(_mm_hadd_pd(a, a)); }
|
||||
|
||||
// SSSE3 version:
|
||||
// inline float ei_predux(const __m128i& a)
|
||||
// EIGEN_STRONG_INLINE float ei_predux(const __m128i& a)
|
||||
// {
|
||||
// __m128i tmp0 = _mm_hadd_epi32(a,a);
|
||||
// return ei_pfirst(_mm_hadd_epi32(tmp0, tmp0));
|
||||
// }
|
||||
#else
|
||||
// SSE2 versions
|
||||
inline float ei_predux(const __m128& a)
|
||||
template<> EIGEN_STRONG_INLINE float ei_predux<__m128>(const __m128& a)
|
||||
{
|
||||
__m128 tmp = _mm_add_ps(a, _mm_movehl_ps(a,a));
|
||||
return ei_pfirst(_mm_add_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
|
||||
}
|
||||
inline double ei_predux(const __m128d& a)
|
||||
template<> EIGEN_STRONG_INLINE double ei_predux<__m128d>(const __m128d& a)
|
||||
{
|
||||
return ei_pfirst(_mm_add_sd(a, _mm_unpackhi_pd(a,a)));
|
||||
}
|
||||
|
||||
inline __m128 ei_preduxp(const __m128* vecs)
|
||||
template<> EIGEN_STRONG_INLINE __m128 ei_preduxp<__m128>(const __m128* vecs)
|
||||
{
|
||||
__m128 tmp0, tmp1, tmp2;
|
||||
tmp0 = _mm_unpacklo_ps(vecs[0], vecs[1]);
|
||||
@@ -174,19 +181,19 @@ inline __m128 ei_preduxp(const __m128* vecs)
|
||||
return _mm_add_ps(tmp0, tmp2);
|
||||
}
|
||||
|
||||
inline __m128d ei_preduxp(const __m128d* vecs)
|
||||
template<> EIGEN_STRONG_INLINE __m128d ei_preduxp<__m128d>(const __m128d* vecs)
|
||||
{
|
||||
return _mm_add_pd(_mm_unpacklo_pd(vecs[0], vecs[1]), _mm_unpackhi_pd(vecs[0], vecs[1]));
|
||||
}
|
||||
#endif // SSE3
|
||||
|
||||
inline int ei_predux(const __m128i& a)
|
||||
template<> EIGEN_STRONG_INLINE int ei_predux<__m128i>(const __m128i& a)
|
||||
{
|
||||
__m128i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a));
|
||||
return ei_pfirst(tmp) + ei_pfirst(_mm_shuffle_epi32(tmp, 1));
|
||||
}
|
||||
|
||||
inline __m128i ei_preduxp(const __m128i* vecs)
|
||||
template<> EIGEN_STRONG_INLINE __m128i ei_preduxp<__m128i>(const __m128i* vecs)
|
||||
{
|
||||
__m128i tmp0, tmp1, tmp2;
|
||||
tmp0 = _mm_unpacklo_epi32(vecs[0], vecs[1]);
|
||||
@@ -201,13 +208,13 @@ inline __m128i ei_preduxp(const __m128i* vecs)
|
||||
}
|
||||
|
||||
#if (defined __GNUC__)
|
||||
// template <> inline __m128 ei_pmadd(const __m128& a, const __m128& b, const __m128& c)
|
||||
// template <> EIGEN_STRONG_INLINE __m128 ei_pmadd(const __m128& a, const __m128& b, const __m128& c)
|
||||
// {
|
||||
// __m128 res = b;
|
||||
// asm("mulps %[a], %[b] \n\taddps %[c], %[b]" : [b] "+x" (res) : [a] "x" (a), [c] "x" (c));
|
||||
// return res;
|
||||
// }
|
||||
// inline __m128i _mm_alignr_epi8(const __m128i& a, const __m128i& b, const int i)
|
||||
// EIGEN_STRONG_INLINE __m128i _mm_alignr_epi8(const __m128i& a, const __m128i& b, const int i)
|
||||
// {
|
||||
// __m128i res = a;
|
||||
// asm("palignr %[i], %[a], %[b] " : [b] "+x" (res) : [a] "x" (a), [i] "i" (i));
|
||||
@@ -220,7 +227,7 @@ inline __m128i ei_preduxp(const __m128i* vecs)
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128>
|
||||
{
|
||||
inline static void run(__m128& first, const __m128& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128& first, const __m128& second)
|
||||
{
|
||||
if (Offset!=0)
|
||||
first = _mm_castsi128_ps(_mm_alignr_epi8(_mm_castps_si128(second), _mm_castps_si128(first), Offset*4));
|
||||
@@ -230,7 +237,7 @@ struct ei_palign_impl<Offset,__m128>
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128i>
|
||||
{
|
||||
inline static void run(__m128i& first, const __m128i& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128i& first, const __m128i& second)
|
||||
{
|
||||
if (Offset!=0)
|
||||
first = _mm_alignr_epi8(second,first, Offset*4);
|
||||
@@ -240,7 +247,7 @@ struct ei_palign_impl<Offset,__m128i>
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128d>
|
||||
{
|
||||
inline static void run(__m128d& first, const __m128d& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128d& first, const __m128d& second)
|
||||
{
|
||||
if (Offset==1)
|
||||
first = _mm_castsi128_pd(_mm_alignr_epi8(_mm_castpd_si128(second), _mm_castpd_si128(first), 8));
|
||||
@@ -251,7 +258,7 @@ struct ei_palign_impl<Offset,__m128d>
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128>
|
||||
{
|
||||
inline static void run(__m128& first, const __m128& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128& first, const __m128& second)
|
||||
{
|
||||
if (Offset==1)
|
||||
{
|
||||
@@ -274,7 +281,7 @@ struct ei_palign_impl<Offset,__m128>
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128i>
|
||||
{
|
||||
inline static void run(__m128i& first, const __m128i& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128i& first, const __m128i& second)
|
||||
{
|
||||
if (Offset==1)
|
||||
{
|
||||
@@ -297,7 +304,7 @@ struct ei_palign_impl<Offset,__m128i>
|
||||
template<int Offset>
|
||||
struct ei_palign_impl<Offset,__m128d>
|
||||
{
|
||||
inline static void run(__m128d& first, const __m128d& second)
|
||||
EIGEN_STRONG_INLINE static void run(__m128d& first, const __m128d& second)
|
||||
{
|
||||
if (Offset==1)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,14 +26,37 @@
|
||||
#ifndef EIGEN_CONSTANTS_H
|
||||
#define EIGEN_CONSTANTS_H
|
||||
|
||||
/** This value means that a quantity is not known at compile-time, and that instead the value is
|
||||
* stored in some runtime variable.
|
||||
*
|
||||
* Explanation for the choice of this value:
|
||||
* - It should be positive and larger than any reasonable compile-time-fixed number of rows or columns.
|
||||
* This allows to simplify many compile-time conditions throughout Eigen.
|
||||
* - It should be smaller than the sqrt of INT_MAX. Indeed, we often multiply a number of rows with a number
|
||||
* of columns in order to compute a number of coefficients. Even if we guard that with an "if" checking whether
|
||||
* the values are Dynamic, we still get a compiler warning "integer overflow". So the only way to get around
|
||||
* it would be a meta-selector. Doing this everywhere would reduce code readability and lenghten compilation times.
|
||||
* Also, disabling compiler warnings for integer overflow, sounds like a bad idea.
|
||||
*
|
||||
* If you wish to port Eigen to a platform where sizeof(int)==2, it is perfectly possible to set Dynamic to, say, 100.
|
||||
*/
|
||||
const int Dynamic = 10000;
|
||||
|
||||
/** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm<int>().
|
||||
* The value Infinity there means the L-infinity norm.
|
||||
*/
|
||||
const int Infinity = -1;
|
||||
|
||||
/** \defgroup flags flags
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* These are the possible bits which can be OR'ed to constitute the flags of a matrix or
|
||||
* expression.
|
||||
*
|
||||
* It is important to note that these flags are a purely compile-time notion. They are a compile-time property of
|
||||
* an expression type, implemented as enum's. They are not stored in memory at runtime, and they do not incur any
|
||||
* runtime overhead.
|
||||
*
|
||||
* \sa MatrixBase::Flags
|
||||
*/
|
||||
|
||||
@@ -162,23 +185,23 @@ const unsigned int HereditaryBits = RowMajorBit
|
||||
| SparseBit;
|
||||
|
||||
// Possible values for the Mode parameter of part() and of extract()
|
||||
const unsigned int Upper = UpperTriangularBit;
|
||||
const unsigned int StrictlyUpper = UpperTriangularBit | ZeroDiagBit;
|
||||
const unsigned int Lower = LowerTriangularBit;
|
||||
const unsigned int StrictlyLower = LowerTriangularBit | ZeroDiagBit;
|
||||
const unsigned int UpperTriangular = UpperTriangularBit;
|
||||
const unsigned int StrictlyUpperTriangular = UpperTriangularBit | ZeroDiagBit;
|
||||
const unsigned int LowerTriangular = LowerTriangularBit;
|
||||
const unsigned int StrictlyLowerTriangular = LowerTriangularBit | ZeroDiagBit;
|
||||
const unsigned int SelfAdjoint = SelfAdjointBit;
|
||||
|
||||
// additional possible values for the Mode parameter of extract()
|
||||
const unsigned int UnitUpper = UpperTriangularBit | UnitDiagBit;
|
||||
const unsigned int UnitLower = LowerTriangularBit | UnitDiagBit;
|
||||
const unsigned int Diagonal = Upper | Lower;
|
||||
const unsigned int UnitUpperTriangular = UpperTriangularBit | UnitDiagBit;
|
||||
const unsigned int UnitLowerTriangular = LowerTriangularBit | UnitDiagBit;
|
||||
const unsigned int Diagonal = UpperTriangular | LowerTriangular;
|
||||
|
||||
enum { Aligned, Unaligned };
|
||||
enum { ForceAligned, AsRequested };
|
||||
enum { ConditionalJumpCost = 5 };
|
||||
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||
enum DirectionType { Vertical, Horizontal };
|
||||
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseProduct };
|
||||
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseTimeSparseProduct, SparseTimeDenseProduct, DenseTimeSparseProduct };
|
||||
|
||||
enum {
|
||||
/** \internal Equivalent to a slice vectorization for fixed-size matrices having good alignment
|
||||
@@ -194,26 +217,26 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
CompleteUnrolling,
|
||||
NoUnrolling,
|
||||
InnerUnrolling,
|
||||
NoUnrolling
|
||||
CompleteUnrolling
|
||||
};
|
||||
|
||||
enum {
|
||||
ColMajor = 0,
|
||||
RowMajor = RowMajorBit
|
||||
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
|
||||
/** \internal Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be
|
||||
requested to be aligned) */
|
||||
DontAlign = 0,
|
||||
/** \internal Align the matrix itself if it is vectorizable fixed-size */
|
||||
AutoAlign = 0x2
|
||||
};
|
||||
|
||||
enum {
|
||||
IsDense = 0,
|
||||
IsSparse = SparseBit,
|
||||
NoDirectAccess = 0,
|
||||
HasDirectAccess = DirectAccessBit,
|
||||
IsSparse = SparseBit
|
||||
HasDirectAccess = DirectAccessBit
|
||||
};
|
||||
|
||||
const int FullyCoherentAccessPattern = 0x1;
|
||||
const int InnerCoherentAccessPattern = 0x2 | FullyCoherentAccessPattern;
|
||||
const int OuterCoherentAccessPattern = 0x4 | InnerCoherentAccessPattern;
|
||||
const int RandomAccessPattern = 0x8 | OuterCoherentAccessPattern;
|
||||
|
||||
#endif // EIGEN_CONSTANTS_H
|
||||
|
||||
5
Eigen/src/Core/util/DisableMSVCWarnings.h
Normal file
5
Eigen/src/Core/util/DisableMSVCWarnings.h
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4181 4244 4127 4211 4717 )
|
||||
#endif
|
||||
4
Eigen/src/Core/util/EnableMSVCWarnings.h
Normal file
4
Eigen/src/Core/util/EnableMSVCWarnings.h
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -28,7 +28,8 @@
|
||||
template<typename T> struct ei_traits;
|
||||
template<typename T> struct NumTraits;
|
||||
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder = ColMajor,
|
||||
template<typename _Scalar, int _Rows, int _Cols,
|
||||
int _Options = EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION | AutoAlign,
|
||||
int _MaxRows = _Rows, int _MaxCols = _Cols> class Matrix;
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged;
|
||||
@@ -64,6 +65,7 @@ template<typename Scalar> struct ei_scalar_quotient_op;
|
||||
template<typename Scalar> struct ei_scalar_opposite_op;
|
||||
template<typename Scalar> struct ei_scalar_conjugate_op;
|
||||
template<typename Scalar> struct ei_scalar_real_op;
|
||||
template<typename Scalar> struct ei_scalar_imag_op;
|
||||
template<typename Scalar> struct ei_scalar_abs_op;
|
||||
template<typename Scalar> struct ei_scalar_abs2_op;
|
||||
template<typename Scalar> struct ei_scalar_sqrt_op;
|
||||
@@ -102,8 +104,8 @@ template<typename ExpressionType, int Direction> class PartialRedux;
|
||||
template<typename MatrixType> class LU;
|
||||
template<typename MatrixType> class QR;
|
||||
template<typename MatrixType> class SVD;
|
||||
template<typename MatrixType> class Cholesky;
|
||||
template<typename MatrixType> class CholeskyWithoutSquareRoot;
|
||||
template<typename MatrixType> class LLT;
|
||||
template<typename MatrixType> class LDLT;
|
||||
|
||||
// Geometry module:
|
||||
template<typename Derived, int _Dim> class RotationBase;
|
||||
@@ -117,4 +119,7 @@ template <typename _Scalar, int _AmbientDim> class Hyperplane;
|
||||
template<typename Scalar,int Dim> class Translation;
|
||||
template<typename Scalar,int Dim> class Scaling;
|
||||
|
||||
// Sparse module:
|
||||
template<typename Lhs, typename Rhs, int ProductMode> class SparseProduct;
|
||||
|
||||
#endif // EIGEN_FORWARDDECLARATIONS_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -28,15 +28,58 @@
|
||||
|
||||
#undef minor
|
||||
|
||||
/** \internal Defines the maximal loop size to enable meta unrolling of loops */
|
||||
#define EIGEN_WORLD_VERSION 2
|
||||
#define EIGEN_MAJOR_VERSION 0
|
||||
#define EIGEN_MINOR_VERSION 3
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
EIGEN_MINOR_VERSION>=z))))
|
||||
|
||||
// if the compiler is GNUC, disable 16 byte alignment on exotic archs that probably don't need it, and on which
|
||||
// it may be extra trouble to get aligned memory allocation to work (example: on ARM, overloading new[] is a PITA
|
||||
// because extra memory must be allocated for bookkeeping).
|
||||
// if the compiler is not GNUC, just cross fingers that the architecture isn't too exotic, because we don't want
|
||||
// to keep track of all the different preprocessor symbols for all compilers.
|
||||
#if !defined(__GNUC__) || defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ia64__)
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT 1
|
||||
#else
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
#error Vectorization enabled, but the architecture is not listed among those for which we require 16 byte alignment. If you added vectorization for another architecture, you also need to edit this list.
|
||||
#endif
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT 0
|
||||
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
|
||||
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor
|
||||
#else
|
||||
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ColMajor
|
||||
#endif
|
||||
|
||||
/** \internal Defines the maximal loop size to enable meta unrolling of loops.
|
||||
* Note that the value here is expressed in Eigen's own notion of "number of FLOPS",
|
||||
* it does not correspond to the number of iterations or the number of instructions
|
||||
*/
|
||||
#ifndef EIGEN_UNROLLING_LIMIT
|
||||
#define EIGEN_UNROLLING_LIMIT 100
|
||||
#endif
|
||||
|
||||
/** \internal Define the maximal size in Bytes of L2 blocks.
|
||||
* The current value is set to generate blocks of 256x256 for float */
|
||||
#ifndef EIGEN_TUNE_FOR_L2_CACHE_SIZE
|
||||
#define EIGEN_TUNE_FOR_L2_CACHE_SIZE (1024*256)
|
||||
/** \internal Define the maximal size in Bytes of blocks fitting in CPU cache.
|
||||
* The current value is set to generate blocks of 256x256 for float
|
||||
*
|
||||
* Typically for a single-threaded application you would set that to 25% of the size of your CPU caches in bytes
|
||||
*/
|
||||
#ifndef EIGEN_TUNE_FOR_CPU_CACHE_SIZE
|
||||
#define EIGEN_TUNE_FOR_CPU_CACHE_SIZE (sizeof(float)*256*256)
|
||||
#endif
|
||||
|
||||
// FIXME this should go away quickly
|
||||
#ifdef EIGEN_TUNE_FOR_L2_CACHE_SIZE
|
||||
#error EIGEN_TUNE_FOR_L2_CACHE_SIZE is now called EIGEN_TUNE_FOR_CPU_CACHE_SIZE.
|
||||
#endif
|
||||
|
||||
#define USING_PART_OF_NAMESPACE_EIGEN \
|
||||
@@ -70,7 +113,7 @@ using Eigen::ei_cos;
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||
#define ei_internal_assert(x) ei_assert(x);
|
||||
#define ei_internal_assert(x) ei_assert(x)
|
||||
#else
|
||||
#define ei_internal_assert(x)
|
||||
#endif
|
||||
@@ -81,46 +124,87 @@ using Eigen::ei_cos;
|
||||
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
|
||||
#endif
|
||||
|
||||
// EIGEN_ALWAYS_INLINE_ATTRIB should be use in the declaration of function
|
||||
// which should be inlined even in debug mode.
|
||||
// FIXME with the always_inline attribute,
|
||||
// gcc 3.4.x reports the following compilation error:
|
||||
// Eval.h:91: sorry, unimplemented: inlining failed in call to 'const Eigen::Eval<Derived> Eigen::MatrixBase<Scalar, Derived>::eval() const'
|
||||
// : function body not available
|
||||
#if EIGEN_GNUC_AT_LEAST(4,0)
|
||||
#define EIGEN_ALWAYS_INLINE __attribute__((always_inline)) inline
|
||||
#define EIGEN_ALWAYS_INLINE_ATTRIB __attribute__((always_inline))
|
||||
#else
|
||||
#define EIGEN_ALWAYS_INLINE inline
|
||||
#define EIGEN_ALWAYS_INLINE_ATTRIB
|
||||
#endif
|
||||
|
||||
// EIGEN_FORCE_INLINE means "inline as much as possible"
|
||||
#if (defined _MSC_VER)
|
||||
#define EIGEN_STRONG_INLINE __forceinline
|
||||
#else
|
||||
#define EIGEN_STRONG_INLINE inline
|
||||
#endif
|
||||
|
||||
#if (defined __GNUC__)
|
||||
#define EIGEN_DONT_INLINE __attribute__((noinline))
|
||||
#elif (defined _MSC_VER)
|
||||
#define EIGEN_DONT_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define EIGEN_DONT_INLINE
|
||||
#endif
|
||||
|
||||
#if (defined __GNUC__)
|
||||
#define EIGEN_ALIGN_128 __attribute__ ((aligned(16)))
|
||||
#define EIGEN_DEPRECATED __attribute__((deprecated))
|
||||
#elif (defined _MSC_VER)
|
||||
#define EIGEN_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#define EIGEN_DEPRECATED
|
||||
#endif
|
||||
|
||||
/* EIGEN_ALIGN_128 forces data to be 16-byte aligned, EVEN if vectorization (EIGEN_VECTORIZE) is disabled,
|
||||
* so that vectorization doesn't affect binary compatibility.
|
||||
*
|
||||
* If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link
|
||||
* vectorized and non-vectorized code.
|
||||
*/
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#define EIGEN_ALIGN_128
|
||||
#elif (defined __GNUC__)
|
||||
#define EIGEN_ALIGN_128 __attribute__((aligned(16)))
|
||||
#elif (defined _MSC_VER)
|
||||
#define EIGEN_ALIGN_128 __declspec(align(16))
|
||||
#else
|
||||
#error Please tell me what is the equivalent of __attribute__((aligned(16))) for your compiler
|
||||
#endif
|
||||
|
||||
#define EIGEN_RESTRICT __restrict
|
||||
|
||||
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 16000000
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_DEFAULT_IO_FORMAT
|
||||
#define EIGEN_DEFAULT_IO_FORMAT Eigen::IOFormat()
|
||||
#endif
|
||||
|
||||
// format used in Eigen's documentation
|
||||
// needed to define it here as escaping characters in CMake add_definition's argument seems very problematic.
|
||||
#define EIGEN_DOCS_IO_FORMAT IOFormat(3, AlignCols, " ", "\n", "", "")
|
||||
|
||||
#define EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
|
||||
template<typename OtherDerived> \
|
||||
Derived& operator Op(const MatrixBase<OtherDerived>& other) \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::MatrixBase<OtherDerived>& other) \
|
||||
{ \
|
||||
return Eigen::MatrixBase<Derived>::operator Op(other.derived()); \
|
||||
return Base::operator Op(other.derived()); \
|
||||
} \
|
||||
Derived& operator Op(const Derived& other) \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \
|
||||
{ \
|
||||
return Eigen::MatrixBase<Derived>::operator Op(other); \
|
||||
return Base::operator Op(other); \
|
||||
}
|
||||
|
||||
#define EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \
|
||||
template<typename Other> \
|
||||
Derived& operator Op(const Other& scalar) \
|
||||
EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \
|
||||
{ \
|
||||
return Eigen::MatrixBase<Derived>::operator Op(scalar); \
|
||||
return Base::operator Op(scalar); \
|
||||
}
|
||||
|
||||
#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
|
||||
@@ -136,7 +220,6 @@ typedef typename Eigen::ei_traits<Derived>::Scalar Scalar; \
|
||||
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \
|
||||
typedef typename Base::PacketScalar PacketScalar; \
|
||||
typedef typename Eigen::ei_nested<Derived>::type Nested; \
|
||||
typedef typename Eigen::ei_eval<Derived>::type Eval; \
|
||||
enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime, \
|
||||
ColsAtCompileTime = Eigen::ei_traits<Derived>::ColsAtCompileTime, \
|
||||
MaxRowsAtCompileTime = Eigen::ei_traits<Derived>::MaxRowsAtCompileTime, \
|
||||
@@ -153,4 +236,15 @@ _EIGEN_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::MatrixBase<Derived>)
|
||||
#define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
|
||||
#define EIGEN_ENUM_MAX(a,b) (((int)a >= (int)b) ? (int)a : (int)b)
|
||||
|
||||
// just an empty macro !
|
||||
#define EIGEN_EMPTY
|
||||
|
||||
// concatenate two tokens
|
||||
#define EIGEN_CAT2(a,b) a ## b
|
||||
#define EIGEN_CAT(a,b) EIGEN_CAT2(a,b)
|
||||
|
||||
// convert a token to a string
|
||||
#define EIGEN_MAKESTRING2(a) #a
|
||||
#define EIGEN_MAKESTRING(a) EIGEN_MAKESTRING2(a)
|
||||
|
||||
#endif // EIGEN_MACROS_H
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,52 +27,174 @@
|
||||
#ifndef EIGEN_MEMORY_H
|
||||
#define EIGEN_MEMORY_H
|
||||
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
// it seems we cannot assume posix_memalign is defined in the stdlib header
|
||||
extern "C" int posix_memalign (void **, size_t, size_t) throw ();
|
||||
#if defined(__APPLE__) || defined(_WIN64)
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
|
||||
#endif
|
||||
|
||||
/** \internal
|
||||
* Static array automatically aligned if the total byte size is a multiple of 16
|
||||
#if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
|
||||
#define EIGEN_HAS_POSIX_MEMALIGN 1
|
||||
#else
|
||||
#define EIGEN_HAS_POSIX_MEMALIGN 0
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_SSE
|
||||
#define EIGEN_HAS_MM_MALLOC 1
|
||||
#else
|
||||
#define EIGEN_HAS_MM_MALLOC 0
|
||||
#endif
|
||||
|
||||
/** \internal like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
|
||||
* Fast, but wastes 16 additional bytes of memory.
|
||||
* Does not throw any exception.
|
||||
*/
|
||||
template <typename T, int Size, bool Align> struct ei_aligned_array
|
||||
inline void* ei_handmade_aligned_malloc(size_t size)
|
||||
{
|
||||
EIGEN_ALIGN_128 T array[Size];
|
||||
};
|
||||
|
||||
template <typename T, int Size> struct ei_aligned_array<T,Size,false>
|
||||
{
|
||||
T array[Size];
|
||||
};
|
||||
|
||||
/** \internal allocates \a size * sizeof(\a T) bytes with a 16 bytes based alignment */
|
||||
template<typename T>
|
||||
inline T* ei_aligned_malloc(size_t size)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
if (ei_packet_traits<T>::size>1)
|
||||
{
|
||||
void* ptr;
|
||||
if (posix_memalign(&ptr, 16, size*sizeof(T))==0)
|
||||
return static_cast<T*>(ptr);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return new T[size];
|
||||
void *original = malloc(size+16);
|
||||
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
|
||||
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_aligned_malloc */
|
||||
template<typename T>
|
||||
inline void ei_aligned_free(T* ptr)
|
||||
/** \internal frees memory allocated with ei_handmade_aligned_malloc */
|
||||
inline void ei_handmade_aligned_free(void *ptr)
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
if (ei_packet_traits<T>::size>1)
|
||||
free(ptr);
|
||||
else
|
||||
if(ptr)
|
||||
free(*(reinterpret_cast<void**>(ptr) - 1));
|
||||
}
|
||||
|
||||
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
inline void* ei_aligned_malloc(size_t size)
|
||||
{
|
||||
#ifdef EIGEN_NO_MALLOC
|
||||
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
|
||||
#endif
|
||||
delete[] ptr;
|
||||
|
||||
void *result;
|
||||
#if EIGEN_HAS_POSIX_MEMALIGN && EIGEN_ARCH_WANTS_ALIGNMENT && !EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
const int failed =
|
||||
#endif
|
||||
posix_memalign(&result, 16, size);
|
||||
#else
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
result = malloc(size);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
result = malloc(size);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
result = _mm_malloc(size, 16);
|
||||
#elif (defined _MSC_VER)
|
||||
result = _aligned_malloc(size, 16);
|
||||
#else
|
||||
result = ei_handmade_aligned_malloc(size);
|
||||
#endif
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
const int failed = (result == 0);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
if(failed)
|
||||
throw std::bad_alloc();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
|
||||
{
|
||||
return ei_aligned_malloc(size);
|
||||
}
|
||||
|
||||
template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
|
||||
{
|
||||
#ifdef EIGEN_NO_MALLOC
|
||||
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
|
||||
#endif
|
||||
|
||||
void *result = malloc(size);
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
if(!result) throw std::bad_alloc();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
* The default constructor of T is called.
|
||||
*/
|
||||
template<typename T> inline T* ei_aligned_new(size_t size)
|
||||
{
|
||||
void *void_result = ei_aligned_malloc(sizeof(T)*size);
|
||||
return ::new(void_result) T[size];
|
||||
}
|
||||
|
||||
template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t size)
|
||||
{
|
||||
void *void_result = ei_conditional_aligned_malloc<Align>(sizeof(T)*size);
|
||||
return ::new(void_result) T[size];
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_aligned_malloc
|
||||
*/
|
||||
inline void ei_aligned_free(void *ptr)
|
||||
{
|
||||
#if !EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
free(ptr);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
free(ptr);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
free(ptr);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
_mm_free(ptr);
|
||||
#elif defined(_MSC_VER)
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
ei_handmade_aligned_free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_conditional_aligned_malloc
|
||||
*/
|
||||
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
|
||||
{
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
template<> inline void ei_conditional_aligned_free<false>(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/** \internal delete the elements of an array.
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_delete_elements_of_array(T *ptr, size_t size)
|
||||
{
|
||||
// always destruct an array starting from the end.
|
||||
while(size) ptr[--size].~T();
|
||||
}
|
||||
|
||||
/** \internal delete objects constructed with ei_aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
ei_delete_elements_of_array<T>(ptr, size);
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
/** \internal delete objects constructed with ei_conditional_aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
ei_delete_elements_of_array<T>(ptr, size);
|
||||
ei_conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
|
||||
/** \internal \returns the number of elements which have to be skipped such that data are 16 bytes aligned */
|
||||
@@ -83,151 +206,147 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
const int PacketAlignedMask = PacketSize-1;
|
||||
const bool Vectorized = PacketSize>1;
|
||||
return Vectorized
|
||||
? std::min<int>( (PacketSize - ((size_t(ptr)/sizeof(Scalar)) & PacketAlignedMask))
|
||||
? std::min<int>( (PacketSize - (int((size_t(ptr)/sizeof(Scalar))) & PacketAlignedMask))
|
||||
& PacketAlignedMask, maxOffset)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* ei_alloc_stack(TYPE,SIZE) allocates sizeof(TYPE)*SIZE bytes on the stack if sizeof(TYPE)*SIZE is
|
||||
* smaller than EIGEN_STACK_ALLOCATION_LIMIT. Otherwise the memory is allocated using the operator new.
|
||||
* Data allocated with ei_alloc_stack \b must be freed calling ei_free_stack(PTR,TYPE,SIZE).
|
||||
* ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
|
||||
* on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
|
||||
* Otherwise the memory is allocated on the heap.
|
||||
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
|
||||
* \code
|
||||
* float * data = ei_alloc_stack(float,array.size());
|
||||
* float * data = ei_aligned_stack_alloc(float,array.size());
|
||||
* // ...
|
||||
* ei_free_stack(data,float,array.size());
|
||||
* ei_aligned_stack_free(data,float,array.size());
|
||||
* \endcode
|
||||
*/
|
||||
#ifdef __linux__
|
||||
# define ei_alloc_stack(TYPE,SIZE) ((sizeof(TYPE)*(SIZE)>16000000) ? new TYPE[SIZE] : (TYPE*)alloca(sizeof(TYPE)*(SIZE)))
|
||||
# define ei_free_stack(PTR,TYPE,SIZE) if (sizeof(TYPE)*SIZE>16000000) delete[] PTR
|
||||
#define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
|
||||
? alloca(SIZE) \
|
||||
: ei_aligned_malloc(SIZE)
|
||||
#define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR)
|
||||
#else
|
||||
# define ei_alloc_stack(TYPE,SIZE) new TYPE[SIZE]
|
||||
# define ei_free_stack(PTR,TYPE,SIZE) delete[] PTR
|
||||
#define ei_aligned_stack_alloc(SIZE) ei_aligned_malloc(SIZE)
|
||||
#define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
|
||||
#endif
|
||||
|
||||
/** \class WithAlignedOperatorNew
|
||||
*
|
||||
* \brief Enforces inherited classes to be 16 bytes aligned when dynamicalled allocated with operator new
|
||||
*
|
||||
* When Eigen's explicit vectorization is enabled, Eigen assumes that some fixed sizes types are aligned
|
||||
* on a 16 bytes boundary. Such types include:
|
||||
* - Vector2d, Vector4f, Vector4i, Vector4d,
|
||||
* - Matrix2d, Matrix4f, Matrix4i, Matrix4d,
|
||||
* - etc.
|
||||
* When objects are statically allocated, the compiler will automatically and always enforces 16 bytes
|
||||
* alignment of the data. However some troubles might appear when data are dynamically allocated.
|
||||
* Let's pick an example:
|
||||
* \code
|
||||
* struct Foo {
|
||||
* char dummy;
|
||||
* Vector4f some_vector;
|
||||
* };
|
||||
* Foo obj1; // static allocation
|
||||
* obj1.some_vector = Vector4f(..); // => OK
|
||||
*
|
||||
* Foo *pObj2 = new Foo; // dynamic allocation
|
||||
* pObj2->some_vector = Vector4f(..); // => !! might segfault !!
|
||||
* \endcode
|
||||
* Here, the problem is that operator new is not aware of the compile time alignment requirement of the
|
||||
* type Vector4f (and hence of the type Foo). Therefore "new Foo" does not necessarily returned a 16 bytes
|
||||
* aligned pointer. The purpose of the class WithAlignedOperatorNew is exactly to overcome this issue, by
|
||||
* overloading the operator new to return aligned data when the vectorization is enabled.
|
||||
* Here is a similar safe example:
|
||||
* \code
|
||||
* struct Foo : WithAlignedOperatorNew {
|
||||
* char dummy;
|
||||
* Vector4f some_vector;
|
||||
* };
|
||||
* Foo obj1; // static allocation
|
||||
* obj1.some_vector = Vector4f(..); // => OK
|
||||
*
|
||||
* Foo *pObj2 = new Foo; // dynamic allocation
|
||||
* pObj2->some_vector = Vector4f(..); // => SAFE !
|
||||
* \endcode
|
||||
*
|
||||
* \sa class ei_new_allocator
|
||||
*/
|
||||
struct WithAlignedOperatorNew
|
||||
#define ei_aligned_stack_new(TYPE,SIZE) ::new(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)) TYPE[SIZE]
|
||||
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_delete_elements_of_array<TYPE>(PTR, SIZE); \
|
||||
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
|
||||
|
||||
|
||||
#if EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
|
||||
void *operator new(size_t size) throw() { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void *operator new[](size_t size) throw() { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void *operator new(size_t, void *ptr) throw() { return ptr; } \
|
||||
typedef void ei_operator_new_marker_type;
|
||||
#else
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
|
||||
#endif
|
||||
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
|
||||
|
||||
|
||||
/** \class aligned_allocator
|
||||
*
|
||||
* \brief stl compatible allocator to use with with 16 byte aligned types
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
* // Matrix4f requires 16 bytes alignment:
|
||||
* std::map< int, Matrix4f, std::less<int>, aligned_allocator<Matrix4f> > my_map_mat4;
|
||||
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
||||
* std::map< int, Vector3f > my_map_vec3;
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
template<class T>
|
||||
class aligned_allocator
|
||||
{
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
|
||||
void *operator new(size_t size) throw()
|
||||
{
|
||||
void* ptr = 0;
|
||||
if (posix_memalign(&ptr, 16, size)==0)
|
||||
return ptr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) throw()
|
||||
{
|
||||
void* ptr = 0;
|
||||
if (posix_memalign(&ptr, 16, size)==0)
|
||||
return ptr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void operator delete(void * ptr) { free(ptr); }
|
||||
void operator delete[](void * ptr) { free(ptr); }
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T, int SizeAtCompileTime,
|
||||
bool NeedsToAlign = (SizeAtCompileTime!=Dynamic) && ((sizeof(T)*SizeAtCompileTime)%16==0)>
|
||||
struct ei_with_aligned_operator_new : WithAlignedOperatorNew {};
|
||||
|
||||
template<typename T, int SizeAtCompileTime>
|
||||
struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {};
|
||||
|
||||
/** \class ei_new_allocator
|
||||
*
|
||||
* \brief stl compatible allocator to use with with fixed-size vector and matrix types
|
||||
*
|
||||
* STL allocator simply wrapping operators new[] and delete[]. Unlike GCC's default new_allocator,
|
||||
* ei_new_allocator call operator new on the type \a T and not the general new operator ignoring
|
||||
* overloaded version of operator new.
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
* // Vector4f requires 16 bytes alignment:
|
||||
* std::vector<Vector4f,ei_new_allocator<Vector4f> > dataVec4;
|
||||
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
||||
* std::vector<Vector3f> dataVec3;
|
||||
*
|
||||
* struct Foo : WithAlignedOperatorNew {
|
||||
* char dummy;
|
||||
* Vector4f some_vector;
|
||||
* };
|
||||
* std::vector<Foo,ei_new_allocator<Foo> > dataFoo;
|
||||
* \endcode
|
||||
*
|
||||
* \sa class WithAlignedOperatorNew
|
||||
*/
|
||||
template<typename T> class ei_new_allocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template<typename OtherType>
|
||||
template<class U>
|
||||
struct rebind
|
||||
{ typedef ei_new_allocator<OtherType> other; };
|
||||
{
|
||||
typedef aligned_allocator<U> other;
|
||||
};
|
||||
|
||||
T* address(T& ref) const { return &ref; }
|
||||
const T* address(const T& ref) const { return &ref; }
|
||||
T* allocate(size_t size, const void* = 0) { return new T[size]; }
|
||||
void deallocate(T* ptr, size_t) { delete[] ptr; }
|
||||
size_t max_size() const { return size_t(-1) / sizeof(T); }
|
||||
// FIXME I'm note sure about this construction...
|
||||
void construct(T* ptr, const T& refObj) { ::new(ptr) T(refObj); }
|
||||
void destroy(T* ptr) { ptr->~T(); }
|
||||
pointer address( reference value ) const
|
||||
{
|
||||
return &value;
|
||||
}
|
||||
|
||||
const_pointer address( const_reference value ) const
|
||||
{
|
||||
return &value;
|
||||
}
|
||||
|
||||
aligned_allocator() throw()
|
||||
{
|
||||
}
|
||||
|
||||
aligned_allocator( const aligned_allocator& ) throw()
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
aligned_allocator( const aligned_allocator<U>& ) throw()
|
||||
{
|
||||
}
|
||||
|
||||
~aligned_allocator() throw()
|
||||
{
|
||||
}
|
||||
|
||||
size_type max_size() const throw()
|
||||
{
|
||||
return std::numeric_limits<size_type>::max();
|
||||
}
|
||||
|
||||
pointer allocate( size_type num, const_pointer* hint = 0 )
|
||||
{
|
||||
static_cast<void>( hint ); // suppress unused variable warning
|
||||
return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
|
||||
}
|
||||
|
||||
void construct( pointer p, const T& value )
|
||||
{
|
||||
::new( p ) T( value );
|
||||
}
|
||||
|
||||
void destroy( pointer p )
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
void deallocate( pointer p, size_type /*num*/ )
|
||||
{
|
||||
ei_aligned_free( p );
|
||||
}
|
||||
|
||||
bool operator!=(const aligned_allocator<T>& other) const
|
||||
{ return false; }
|
||||
|
||||
bool operator==(const aligned_allocator<T>& other) const
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
#endif // EIGEN_MEMORY_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -69,7 +69,7 @@ template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleant
|
||||
*
|
||||
* It supports both the current STL mechanism (using the result_type member) as well as
|
||||
* upcoming next STL generation (using a templated result member).
|
||||
* If none of these members is provided, then the type of the first argument is returned.
|
||||
* If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
|
||||
*/
|
||||
template<typename T> struct ei_result_of {};
|
||||
|
||||
@@ -146,4 +146,38 @@ class ei_meta_sqrt
|
||||
template<int Y, int InfX, int SupX>
|
||||
class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
|
||||
|
||||
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
|
||||
template<typename T, typename U> struct ei_scalar_product_traits
|
||||
{
|
||||
// dummy general case where T and U aren't compatible -- not allowed anyway but we catch it elsewhere
|
||||
//enum { Cost = NumTraits<T>::MulCost };
|
||||
typedef T ReturnType;
|
||||
};
|
||||
|
||||
template<typename T> struct ei_scalar_product_traits<T,T>
|
||||
{
|
||||
//enum { Cost = NumTraits<T>::MulCost };
|
||||
typedef T ReturnType;
|
||||
};
|
||||
|
||||
template<typename T> struct ei_scalar_product_traits<T,std::complex<T> >
|
||||
{
|
||||
//enum { Cost = 2*NumTraits<T>::MulCost };
|
||||
typedef std::complex<T> ReturnType;
|
||||
};
|
||||
|
||||
template<typename T> struct ei_scalar_product_traits<std::complex<T>, T>
|
||||
{
|
||||
//enum { Cost = 2*NumTraits<T>::MulCost };
|
||||
typedef std::complex<T> ReturnType;
|
||||
};
|
||||
|
||||
// FIXME quick workaround around current limitation of ei_result_of
|
||||
template<typename Scalar, typename ArgType0, typename ArgType1>
|
||||
struct ei_result_of<ei_scalar_product_op<Scalar>(ArgType0,ArgType1)> {
|
||||
typedef typename ei_scalar_product_traits<typename ei_cleantype<ArgType0>::type, typename ei_cleantype<ArgType1>::type>::ReturnType type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // EIGEN_META_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -44,7 +44,7 @@
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
||||
// if native static_assert is enabled, let's use it
|
||||
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG)
|
||||
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
||||
|
||||
#else // CXX0X
|
||||
|
||||
@@ -55,29 +55,50 @@
|
||||
struct ei_static_assert<true>
|
||||
{
|
||||
enum {
|
||||
you_tried_calling_a_vector_method_on_a_matrix,
|
||||
you_mixed_vectors_of_different_sizes,
|
||||
you_mixed_matrices_of_different_sizes,
|
||||
this_method_is_only_for_vectors_of_a_specific_size,
|
||||
this_method_is_only_for_matrices_of_a_specific_size,
|
||||
you_did_a_programming_error,
|
||||
you_called_a_fixed_size_method_on_a_dynamic_size_matrix_or_vector,
|
||||
unaligned_load_and_store_operations_unimplemented_on_AltiVec,
|
||||
scalar_type_must_be_floating_point,
|
||||
default_writting_to_selfadjoint_not_supported,
|
||||
writting_to_triangular_part_with_unit_diag_is_not_supported,
|
||||
this_method_is_only_for_fixed_size
|
||||
YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX,
|
||||
YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES,
|
||||
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES,
|
||||
THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE,
|
||||
THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE,
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE,
|
||||
YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR,
|
||||
UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC,
|
||||
NUMERIC_TYPE_MUST_BE_FLOATING_POINT,
|
||||
COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED,
|
||||
WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED,
|
||||
THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE,
|
||||
INVALID_MATRIX_PRODUCT,
|
||||
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS,
|
||||
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION,
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY,
|
||||
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
|
||||
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS,
|
||||
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
|
||||
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
|
||||
};
|
||||
};
|
||||
|
||||
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
|
||||
if (ei_static_assert<CONDITION ? true : false>::MSG) {}
|
||||
// Specialized implementation for MSVC to avoid "conditional
|
||||
// expression is constant" warnings. This implementation doesn't
|
||||
// appear to work under GCC, hence the multiple implementations.
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#endif // CXX0X
|
||||
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
|
||||
{Eigen::ei_static_assert<CONDITION ? true : false>::MSG;}
|
||||
|
||||
#else
|
||||
|
||||
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
|
||||
if (Eigen::ei_static_assert<CONDITION ? true : false>::MSG) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // not CXX0X
|
||||
|
||||
#else // EIGEN_NO_STATIC_ASSERT
|
||||
|
||||
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) ei_assert((CONDITION) && #MSG)
|
||||
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) ei_assert((CONDITION) && #MSG);
|
||||
|
||||
#endif // EIGEN_NO_STATIC_ASSERT
|
||||
|
||||
@@ -85,22 +106,22 @@
|
||||
// static assertion failing if the type \a TYPE is not a vector type
|
||||
#define EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) \
|
||||
EIGEN_STATIC_ASSERT(TYPE::IsVectorAtCompileTime, \
|
||||
you_tried_calling_a_vector_method_on_a_matrix)
|
||||
YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX)
|
||||
|
||||
// static assertion failing if the type \a TYPE is not fixed-size
|
||||
#define EIGEN_STATIC_ASSERT_FIXED_SIZE(TYPE) \
|
||||
EIGEN_STATIC_ASSERT(TYPE::SizeAtCompileTime!=Eigen::Dynamic, \
|
||||
you_called_a_fixed_size_method_on_a_dynamic_size_matrix_or_vector)
|
||||
YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR)
|
||||
|
||||
// static assertion failing if the type \a TYPE is not a vector type of the given size
|
||||
#define EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(TYPE, SIZE) \
|
||||
EIGEN_STATIC_ASSERT(TYPE::IsVectorAtCompileTime && TYPE::SizeAtCompileTime==SIZE, \
|
||||
this_method_is_only_for_vectors_of_a_specific_size)
|
||||
THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE)
|
||||
|
||||
// static assertion failing if the type \a TYPE is not a vector type of the given size
|
||||
#define EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(TYPE, ROWS, COLS) \
|
||||
EIGEN_STATIC_ASSERT(TYPE::RowsAtCompileTime==ROWS && TYPE::ColsAtCompileTime==COLS, \
|
||||
this_method_is_only_for_matrices_of_a_specific_size)
|
||||
THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE)
|
||||
|
||||
// static assertion failing if the two vector expression types are not compatible (same fixed-size or dynamic size)
|
||||
#define EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TYPE0,TYPE1) \
|
||||
@@ -108,17 +129,20 @@
|
||||
(int(TYPE0::SizeAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE1::SizeAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE0::SizeAtCompileTime)==int(TYPE1::SizeAtCompileTime)),\
|
||||
you_mixed_vectors_of_different_sizes)
|
||||
YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES)
|
||||
|
||||
// static assertion failing if the two matrix expression types are not compatible (same fixed-size or dynamic size)
|
||||
#define EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
|
||||
EIGEN_STATIC_ASSERT( \
|
||||
((int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
|
||||
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
|
||||
((int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE1::RowsAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE0::RowsAtCompileTime)==int(TYPE1::RowsAtCompileTime)) \
|
||||
&& (int(TYPE0::ColsAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE1::ColsAtCompileTime)==Eigen::Dynamic \
|
||||
|| int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime))),\
|
||||
you_mixed_matrices_of_different_sizes)
|
||||
|| int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime)))
|
||||
|
||||
// static assertion failing if it is guaranteed at compile-time that the two matrix expression types have different sizes
|
||||
#define EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
|
||||
EIGEN_STATIC_ASSERT( \
|
||||
EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1),\
|
||||
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
|
||||
|
||||
#endif // EIGEN_STATIC_ASSERT_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -41,6 +41,10 @@ class ei_no_assignment_operator
|
||||
ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
|
||||
};
|
||||
|
||||
/** \internal If the template parameter Value is Dynamic, this class is just a wrapper around an int variable that
|
||||
* can be accessed using value() and setValue().
|
||||
* Otherwise, this class is an empty structure and value() just returns the template parameter Value.
|
||||
*/
|
||||
template<int Value> class ei_int_if_dynamic EIGEN_EMPTY_STRUCT
|
||||
{
|
||||
public:
|
||||
@@ -81,22 +85,16 @@ template<typename T> struct ei_unpacket_traits
|
||||
enum {size=1};
|
||||
};
|
||||
|
||||
|
||||
template<typename Scalar, int Rows, int Cols, int StorageOrder, int MaxRows, int MaxCols>
|
||||
template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
|
||||
class ei_compute_matrix_flags
|
||||
{
|
||||
enum {
|
||||
row_major_bit = (Rows != 1 && Cols != 1) // if this is not a vector,
|
||||
// then the storage order really matters,
|
||||
// so let us strictly honor the user's choice.
|
||||
? StorageOrder
|
||||
: Cols > 1 ? RowMajorBit : 0,
|
||||
row_major_bit = Options&RowMajor ? RowMajorBit : 0,
|
||||
inner_max_size = row_major_bit ? MaxCols : MaxRows,
|
||||
is_big = inner_max_size == Dynamic,
|
||||
is_packet_size_multiple = (Cols * Rows)%ei_packet_traits<Scalar>::size==0,
|
||||
packet_access_bit = ei_packet_traits<Scalar>::size > 1
|
||||
&& (is_big || is_packet_size_multiple) ? PacketAccessBit : 0,
|
||||
aligned_bit = packet_access_bit && (is_big || is_packet_size_multiple) ? AlignedBit : 0
|
||||
is_packet_size_multiple = (Cols*Rows) % ei_packet_traits<Scalar>::size == 0,
|
||||
aligned_bit = ((Options&AutoAlign) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
|
||||
packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -108,6 +106,10 @@ template<int _Rows, int _Cols> struct ei_size_at_compile_time
|
||||
enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
|
||||
};
|
||||
|
||||
/* ei_eval : the return type of eval(). For matrices, this is just a const reference
|
||||
* in order to avoid a useless copy
|
||||
*/
|
||||
|
||||
template<typename T, int Sparseness = ei_traits<T>::Flags&SparseBit> class ei_eval;
|
||||
|
||||
template<typename T> struct ei_eval<T,IsDense>
|
||||
@@ -115,7 +117,41 @@ template<typename T> struct ei_eval<T,IsDense>
|
||||
typedef Matrix<typename ei_traits<T>::Scalar,
|
||||
ei_traits<T>::RowsAtCompileTime,
|
||||
ei_traits<T>::ColsAtCompileTime,
|
||||
ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor,
|
||||
AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
|
||||
ei_traits<T>::MaxRowsAtCompileTime,
|
||||
ei_traits<T>::MaxColsAtCompileTime
|
||||
> type;
|
||||
};
|
||||
|
||||
// for matrices, no need to evaluate, just use a const reference to avoid a useless copy
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
struct ei_eval<Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>, IsDense>
|
||||
{
|
||||
typedef const Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>& type;
|
||||
};
|
||||
|
||||
/* ei_plain_matrix_type : the difference from ei_eval is that ei_plain_matrix_type is always a plain matrix type,
|
||||
* whereas ei_eval is a const reference in the case of a matrix
|
||||
*/
|
||||
template<typename T> struct ei_plain_matrix_type
|
||||
{
|
||||
typedef Matrix<typename ei_traits<T>::Scalar,
|
||||
ei_traits<T>::RowsAtCompileTime,
|
||||
ei_traits<T>::ColsAtCompileTime,
|
||||
AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
|
||||
ei_traits<T>::MaxRowsAtCompileTime,
|
||||
ei_traits<T>::MaxColsAtCompileTime
|
||||
> type;
|
||||
};
|
||||
|
||||
/* ei_plain_matrix_type_column_major : same as ei_plain_matrix_type but guaranteed to be column-major
|
||||
*/
|
||||
template<typename T> struct ei_plain_matrix_type_column_major
|
||||
{
|
||||
typedef Matrix<typename ei_traits<T>::Scalar,
|
||||
ei_traits<T>::RowsAtCompileTime,
|
||||
ei_traits<T>::ColsAtCompileTime,
|
||||
AutoAlign | ColMajor,
|
||||
ei_traits<T>::MaxRowsAtCompileTime,
|
||||
ei_traits<T>::MaxColsAtCompileTime
|
||||
> type;
|
||||
@@ -124,7 +160,25 @@ template<typename T> struct ei_eval<T,IsDense>
|
||||
template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
|
||||
template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };
|
||||
|
||||
template<typename T, int n=1, typename EvalType = typename ei_eval<T>::type> struct ei_nested
|
||||
/** \internal Determines how a given expression should be nested into another one.
|
||||
* For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
|
||||
* nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
|
||||
* evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is
|
||||
* a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes
|
||||
* many coefficient accesses in the nested expressions -- as is the case with matrix product for example.
|
||||
*
|
||||
* \param T the type of the expression being nested
|
||||
* \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression.
|
||||
*
|
||||
* Example. Suppose that a, b, and c are of type Matrix3d. The user forms the expression a*(b+c).
|
||||
* b+c is an expression "sum of matrices", which we will denote by S. In order to determine how to nest it,
|
||||
* the Product expression uses: ei_nested<S, 3>::ret, which turns out to be Matrix3d because the internal logic of
|
||||
* ei_nested determined that in this case it was better to evaluate the expression b+c into a temporary. On the other hand,
|
||||
* since a is of type Matrix3d, the Product expression nests it as ei_nested<Matrix3d, 3>::ret, which turns out to be
|
||||
* const Matrix3d&, because the internal logic of ei_nested determined that since a was already a matrix, there was no point
|
||||
* in copying it into another matrix.
|
||||
*/
|
||||
template<typename T, int n=1, typename PlainMatrixType = typename ei_eval<T>::type> struct ei_nested
|
||||
{
|
||||
enum {
|
||||
CostEval = (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost),
|
||||
@@ -136,7 +190,7 @@ template<typename T, int n=1, typename EvalType = typename ei_eval<T>::type> str
|
||||
typename ei_meta_if<
|
||||
(int(ei_traits<T>::Flags) & EvalBeforeNestingBit)
|
||||
|| ( int(CostEval) <= int(CostNoEval) ),
|
||||
EvalType,
|
||||
PlainMatrixType,
|
||||
const T&
|
||||
>::ret
|
||||
>::ret type;
|
||||
@@ -157,4 +211,9 @@ template<typename ExpressionType, int RowsOrSize=Dynamic, int Cols=Dynamic> stru
|
||||
typedef Block<ExpressionType, RowsOrSize, Cols> Type;
|
||||
};
|
||||
|
||||
template<typename CurrentType, typename NewType> struct ei_cast_return_type
|
||||
{
|
||||
typedef typename ei_meta_if<ei_is_same_type<CurrentType,NewType>::ret,const CurrentType&,NewType>::ret type;
|
||||
};
|
||||
|
||||
#endif // EIGEN_XPRHELPER_H
|
||||
|
||||
173
Eigen/src/Geometry/AlignedBox.h
Normal file
173
Eigen/src/Geometry/AlignedBox.h
Normal file
@@ -0,0 +1,173 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_ALIGNEDBOX_H
|
||||
#define EIGEN_ALIGNEDBOX_H
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class AlignedBox
|
||||
*
|
||||
* \brief An axis aligned box
|
||||
*
|
||||
* \param _Scalar the type of the scalar coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*
|
||||
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class AlignedBox
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Default constructor initializing a null box. */
|
||||
inline explicit AlignedBox()
|
||||
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
||||
|
||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||
inline explicit AlignedBox(int _dim) : m_min(_dim), m_max(_dim)
|
||||
{ setNull(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max. */
|
||||
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}
|
||||
|
||||
~AlignedBox() {}
|
||||
|
||||
/** \returns the dimension in which the box holds */
|
||||
inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; }
|
||||
|
||||
/** \returns true if the box is null, i.e, empty. */
|
||||
inline bool isNull() const { return (m_min.cwise() > m_max).any(); }
|
||||
|
||||
/** Makes \c *this a null/empty box. */
|
||||
inline void setNull()
|
||||
{
|
||||
m_min.setConstant( std::numeric_limits<Scalar>::max());
|
||||
m_max.setConstant(-std::numeric_limits<Scalar>::max());
|
||||
}
|
||||
|
||||
/** \returns the minimal corner */
|
||||
inline const VectorType& min() const { return m_min; }
|
||||
/** \returns a non const reference to the minimal corner */
|
||||
inline VectorType& min() { return m_min; }
|
||||
/** \returns the maximal corner */
|
||||
inline const VectorType& max() const { return m_max; }
|
||||
/** \returns a non const reference to the maximal corner */
|
||||
inline VectorType& max() { return m_max; }
|
||||
|
||||
/** \returns true if the point \a p is inside the box \c *this. */
|
||||
inline bool contains(const VectorType& p) const
|
||||
{ return (m_min.cwise()<=p).all() && (p.cwise()<=m_max).all(); }
|
||||
|
||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||
inline bool contains(const AlignedBox& b) const
|
||||
{ return (m_min.cwise()<=b.min()).all() && (b.max().cwise()<=m_max).all(); }
|
||||
|
||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const VectorType& p)
|
||||
{ m_min = m_min.cwise().min(p); m_max = m_max.cwise().max(p); return *this; }
|
||||
|
||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const AlignedBox& b)
|
||||
{ m_min = m_min.cwise().min(b.m_min); m_max = m_max.cwise().max(b.m_max); return *this; }
|
||||
|
||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& clamp(const AlignedBox& b)
|
||||
{ m_min = m_min.cwise().max(b.m_min); m_max = m_max.cwise().min(b.m_max); return *this; }
|
||||
|
||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||
inline AlignedBox& translate(const VectorType& t)
|
||||
{ m_min += t; m_max += t; return *this; }
|
||||
|
||||
/** \returns the squared distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa exteriorDistance()
|
||||
*/
|
||||
inline Scalar squaredExteriorDistance(const VectorType& p) const;
|
||||
|
||||
/** \returns the distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa squaredExteriorDistance()
|
||||
*/
|
||||
inline Scalar exteriorDistance(const VectorType& p) const
|
||||
{ return ei_sqrt(squaredExteriorDistance(p)); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename ei_cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_min = other.min().template cast<Scalar>();
|
||||
m_max = other.max().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AlignedBox& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_min, m_max;
|
||||
};
|
||||
|
||||
template<typename Scalar,int AmbiantDim>
|
||||
inline Scalar AlignedBox<Scalar,AmbiantDim>::squaredExteriorDistance(const VectorType& p) const
|
||||
{
|
||||
Scalar dist2 = 0.;
|
||||
Scalar aux;
|
||||
for (int k=0; k<dim(); ++k)
|
||||
{
|
||||
if ((aux = (p[k]-m_min[k]))<0.)
|
||||
dist2 += aux*aux;
|
||||
else if ( (aux = (m_max[k]-p[k]))<0. )
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
return dist2;
|
||||
}
|
||||
|
||||
#endif // EIGEN_ALIGNEDBOX_H
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_ANGLEAXIS_H
|
||||
#define EIGEN_ANGLEAXIS_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class AngleAxis
|
||||
*
|
||||
@@ -47,7 +47,7 @@
|
||||
* \note This class is not aimed to be used to store a rotation transformation,
|
||||
* but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
|
||||
* and transformation objects.
|
||||
*
|
||||
*
|
||||
* \sa class Quaternion, class Transform, MatrixBase::UnitX()
|
||||
*/
|
||||
|
||||
@@ -64,7 +64,7 @@ class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
|
||||
enum { Dim = 3 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
@@ -132,12 +132,36 @@ public:
|
||||
template<typename Derived>
|
||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
{ return typename ei_cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
{
|
||||
m_axis = other.axis().template cast<Scalar>();
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision angle-axis type */
|
||||
typedef AngleAxis<float> AngleAxisf;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision angle-axis type */
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
@@ -147,7 +171,7 @@ typedef AngleAxis<double> AngleAxisd;
|
||||
template<typename Scalar>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionType& q)
|
||||
{
|
||||
Scalar n2 = q.vec().norm2();
|
||||
Scalar n2 = q.vec().squaredNorm();
|
||||
if (n2 < precision<Scalar>()*precision<Scalar>())
|
||||
{
|
||||
m_angle = 0;
|
||||
|
||||
96
Eigen/src/Geometry/EulerAngles.h
Normal file
96
Eigen/src/Geometry/EulerAngles.h
Normal file
@@ -0,0 +1,96 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_EULERANGLES_H
|
||||
#define EIGEN_EULERANGLES_H
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \returns the Euler-angles of the rotation matrix \c *this using the convention defined by the triplet (\a a0,\a a1,\a a2)
|
||||
*
|
||||
* Each of the three parameters \a a0,\a a1,\a a2 represents the respective rotation axis as an integer in {0,1,2}.
|
||||
* For instance, in:
|
||||
* \code Vector3f ea = mat.eulerAngles(2, 0, 2); \endcode
|
||||
* "2" represents the z axis and "0" the x axis, etc. The returned angles are such that
|
||||
* we have the following equality:
|
||||
* \code
|
||||
* mat == AngleAxisf(ea[0], Vector3f::UnitZ())
|
||||
* * AngleAxisf(ea[1], Vector3f::UnitX())
|
||||
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
|
||||
* This corresponds to the right-multiply conventions (with right hand side frames).
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
||||
MatrixBase<Derived>::eulerAngles(int a0, int a1, int a2) const
|
||||
{
|
||||
/* Implemented from Graphics Gems IV */
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
||||
|
||||
Matrix<Scalar,3,1> res;
|
||||
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
|
||||
const Scalar epsilon = precision<Scalar>();
|
||||
|
||||
const int odd = ((a0+1)%3 == a1) ? 0 : 1;
|
||||
const int i = a0;
|
||||
const int j = (a0 + 1 + odd)%3;
|
||||
const int k = (a0 + 2 - odd)%3;
|
||||
|
||||
if (a0==a2)
|
||||
{
|
||||
Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
|
||||
res[1] = std::atan2(s, coeff(i,i));
|
||||
if (s > epsilon)
|
||||
{
|
||||
res[0] = std::atan2(coeff(j,i), coeff(k,i));
|
||||
res[2] = std::atan2(coeff(i,j),-coeff(i,k));
|
||||
}
|
||||
else
|
||||
{
|
||||
res[0] = Scalar(0);
|
||||
res[2] = (coeff(i,i)>0?1:-1)*std::atan2(-coeff(k,j), coeff(j,j));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar c = Vector2(coeff(i,i) , coeff(i,j)).norm();
|
||||
res[1] = std::atan2(-coeff(i,k), c);
|
||||
if (c > epsilon)
|
||||
{
|
||||
res[0] = std::atan2(coeff(j,k), coeff(k,k));
|
||||
res[2] = std::atan2(coeff(i,j), coeff(i,i));
|
||||
}
|
||||
else
|
||||
{
|
||||
res[0] = Scalar(0);
|
||||
res[2] = (coeff(i,k)>0?1:-1)*std::atan2(-coeff(k,j), coeff(j,j));
|
||||
}
|
||||
}
|
||||
if (!odd)
|
||||
res = -res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endif // EIGEN_EULERANGLES_H
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef EIGEN_HYPERPLANE_H
|
||||
#define EIGEN_HYPERPLANE_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Hyperplane
|
||||
*
|
||||
@@ -45,177 +45,224 @@
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class Hyperplane
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime==Dynamic
|
||||
? Dynamic
|
||||
: AmbientDimAtCompileTime+1,1> Coefficients;
|
||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime==Dynamic
|
||||
? Dynamic
|
||||
: AmbientDimAtCompileTime+1,1> Coefficients;
|
||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||
/** Default constructor without initialization */
|
||||
inline explicit Hyperplane() {}
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline explicit Hyperplane(int _dim = AmbientDimAtCompileTime) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = -e.dot(n);
|
||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit Hyperplane(int _dim) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = -e.dot(n);
|
||||
}
|
||||
|
||||
/** Constructs a plane from its normal \a n and distance to the origin \a d
|
||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, Scalar d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = d;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
result.offset() = -result.normal().dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p2 - p0).cross(p1 - p0).normalized();
|
||||
result.offset() = -result.normal().dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the parametrized line \a parametrized.
|
||||
* If the dimension of the ambient space is greater than 2, then there isn't uniqueness,
|
||||
* so an arbitrary choice is made.
|
||||
*/
|
||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
||||
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -normal().dot(parametrized.origin());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : AmbientDimAtCompileTime; }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
* \sa absDistance()
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return p.dot(normal()) + offset(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
* \sa signedDistance()
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { return ei_abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline const NormalReturnType normal() const { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
* \warning The ambient space must be a plane, i.e. have dimension 2, so that \c *this and \a other are lines.
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(ei_isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(ei_abs(coeffs().coeff(1))>ei_abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
}
|
||||
|
||||
/** Constructs a plane from its normal \a n and distance to the origin \a d.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, Scalar d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = d;
|
||||
else
|
||||
{ // general case
|
||||
Scalar invdet = Scalar(1) / det;
|
||||
return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
|
||||
invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param mat the Dim x Dim transformation matrix
|
||||
* \param traits specifies whether the matrix \a mat represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
*/
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
result.offset() = -result.normal().dot(p0);
|
||||
return result;
|
||||
ei_assert("invalid traits value in Hyperplane::transform()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3);
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p2 - p0).cross(p1 - p0).normalized();
|
||||
result.offset() = -result.normal().dot(p0);
|
||||
return result;
|
||||
}
|
||||
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param t the transformation of dimension Dim
|
||||
* \param traits specifies whether the transformation \a t represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
* Other kind of transformations are not supported.
|
||||
*/
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
offset() -= t.translation().dot(normal());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -normal().dot(parametrized.origin());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename ei_cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : AmbientDimAtCompileTime; }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return p.dot(normal()) + offset(); }
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { return ei_abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline const NormalReturnType normal() const { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
* \warning The ambient space must be a plane, i.e. have dimension 2, so that *this and \a other are lines.
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2);
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(ei_isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(ei_abs(coeffs().coeff(1))>ei_abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
}
|
||||
else
|
||||
{ // general case
|
||||
Scalar invdet = Scalar(1) / det;
|
||||
return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
|
||||
invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Hyperplane::transform()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
offset() -= t.translation().dot(normal());
|
||||
return *this;
|
||||
}
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Hyperplane& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
Coefficients m_coeffs;
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
#endif // EIGEN_HYPERPLANE_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -27,19 +27,23 @@
|
||||
#define EIGEN_ORTHOMETHODS_H
|
||||
|
||||
/** \geometry_module
|
||||
* \returns the cross product of \c *this and \a other */
|
||||
*
|
||||
* \returns the cross product of \c *this and \a other
|
||||
*
|
||||
* Here is a very good explanation of cross-product: http://xkcd.com/199/
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline typename MatrixBase<Derived>::EvalType
|
||||
inline typename MatrixBase<Derived>::PlainMatrixType
|
||||
MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3)
|
||||
|
||||
// Note that there is no need for an expression here since the compiler
|
||||
// optimize such a small temporary very well (even within a complex expression)
|
||||
const typename ei_nested<Derived,2>::type lhs(derived());
|
||||
const typename ei_nested<OtherDerived,2>::type rhs(other.derived());
|
||||
return typename ei_eval<Derived>::type(
|
||||
return typename ei_plain_matrix_type<Derived>::type(
|
||||
lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1),
|
||||
lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2),
|
||||
lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)
|
||||
@@ -49,7 +53,7 @@ MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
|
||||
template<typename Derived, int Size = Derived::SizeAtCompileTime>
|
||||
struct ei_unitOrthogonal_selector
|
||||
{
|
||||
typedef typename ei_eval<Derived>::type VectorType;
|
||||
typedef typename ei_plain_matrix_type<Derived>::type VectorType;
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
inline static VectorType run(const Derived& src)
|
||||
@@ -92,7 +96,7 @@ struct ei_unitOrthogonal_selector
|
||||
template<typename Derived>
|
||||
struct ei_unitOrthogonal_selector<Derived,2>
|
||||
{
|
||||
typedef typename ei_eval<Derived>::type VectorType;
|
||||
typedef typename ei_plain_matrix_type<Derived>::type VectorType;
|
||||
inline static VectorType run(const Derived& src)
|
||||
{ return VectorType(-ei_conj(src.y()), ei_conj(src.x())).normalized(); }
|
||||
};
|
||||
@@ -105,10 +109,10 @@ struct ei_unitOrthogonal_selector<Derived,2>
|
||||
* \sa cross()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename MatrixBase<Derived>::EvalType
|
||||
typename MatrixBase<Derived>::PlainMatrixType
|
||||
MatrixBase<Derived>::unitOrthogonal() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return ei_unitOrthogonal_selector<Derived>::run(derived());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,87 +26,124 @@
|
||||
#ifndef EIGEN_PARAMETRIZEDLINE_H
|
||||
#define EIGEN_PARAMETRIZEDLINE_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class ParametrizedLine
|
||||
*
|
||||
* \brief A parametrized line
|
||||
*
|
||||
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
||||
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
||||
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ l \in \mathbf{R} \f$.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
* Notice that the dimension of the hyperplane is _AmbientDim-1.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class ParametrizedLine
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
/** Default constructor without initialization */
|
||||
inline explicit ParametrizedLine() {}
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline explicit ParametrizedLine(int _dim = AmbientDimAtCompileTime)
|
||||
: m_origin(_dim), m_direction(_dim)
|
||||
{}
|
||||
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit ParametrizedLine(int _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
|
||||
~ParametrizedLine() {}
|
||||
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||
* \warning the vector direction is assumed to be normalized.
|
||||
*/
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline int dim() const { return m_direction.size(); }
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
/** Constructs a parametrized line going from \a p0 to \a p1. */
|
||||
static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
~ParametrizedLine() {}
|
||||
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p-origin();
|
||||
return (diff - diff.dot(direction())* direction()).norm2();
|
||||
}
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { return ei_sqrt(squaredDistance(p)); }
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline int dim() const { return m_direction.size(); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the line \c *this.
|
||||
*/
|
||||
VectorType projection(const VectorType& p) const
|
||||
{ return origin() + (p-origin()).dot(direction()) * direction(); }
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
|
||||
protected:
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p-origin();
|
||||
return (diff - diff.dot(direction())* direction()).squaredNorm();
|
||||
}
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { return ei_sqrt(squaredDistance(p)); }
|
||||
|
||||
VectorType m_origin, m_direction;
|
||||
/** \returns the projection of a point \a p onto the line \c *this. */
|
||||
VectorType projection(const VectorType& p) const
|
||||
{ return origin() + (p-origin()).dot(direction()) * direction(); }
|
||||
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename ei_cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_origin = other.origin().template cast<Scalar>();
|
||||
m_direction = other.direction().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_origin, m_direction;
|
||||
};
|
||||
|
||||
/** Construct a parametrized line from a 2D hyperplane
|
||||
/** Constructs a parametrized line from a 2D hyperplane
|
||||
*
|
||||
* \warning the ambient space must have dimension 2 such that the hyperplane actually describes a line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline ParametrizedLine<_Scalar, _AmbientDim>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2);
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
direction() = hyperplane.normal().unitOrthogonal();
|
||||
origin() = -hyperplane.normal()*hyperplane.offset();
|
||||
}
|
||||
|
||||
/** \returns the parameter value of the intersection between *this and the given hyperplane
|
||||
/** \returns the parameter value of the intersection between \c *this and the given hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim>::intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
|
||||
@@ -30,7 +30,7 @@ template<typename Other,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_quaternion_assign_impl;
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Quaternion
|
||||
*
|
||||
@@ -59,21 +59,19 @@ template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
|
||||
|
||||
template<typename _Scalar>
|
||||
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
, public ei_with_aligned_operator_new<_Scalar,4>
|
||||
#endif
|
||||
{
|
||||
typedef RotationBase<Quaternion<_Scalar>,3> Base;
|
||||
typedef Matrix<_Scalar, 4, 1> Coefficients;
|
||||
Coefficients m_coeffs;
|
||||
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4)
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/** the type of the Coefficients 4-vector */
|
||||
typedef Matrix<Scalar, 4, 1> Coefficients;
|
||||
/** the type of a 3D vector */
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
/** the equivalent rotation matrix type */
|
||||
@@ -111,13 +109,12 @@ public:
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Default constructor and initializing an identity quaternion. */
|
||||
inline Quaternion()
|
||||
{ m_coeffs << 0, 0, 0, 1; }
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
|
||||
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||
* its four coefficients \a w, \a x, \a y and \a z.
|
||||
*
|
||||
*
|
||||
* \warning Note the order of the arguments: the real \a w coefficient first,
|
||||
* while internally the coefficients are stored in the following order:
|
||||
* [\c x, \c y, \c z, \c w]
|
||||
@@ -151,24 +148,24 @@ public:
|
||||
|
||||
/** \sa Quaternion::Identity(), MatrixBase::setIdentity()
|
||||
*/
|
||||
inline Quaternion& setIdentity() { m_coeffs << 1, 0, 0, 0; return *this; }
|
||||
inline Quaternion& setIdentity() { m_coeffs << 0, 0, 0, 1; return *this; }
|
||||
|
||||
/** \returns the squared norm of the quaternion's coefficients
|
||||
* \sa Quaternion::norm(), MatrixBase::norm2()
|
||||
* \sa Quaternion::norm(), MatrixBase::squaredNorm()
|
||||
*/
|
||||
inline Scalar norm2() const { return m_coeffs.norm2(); }
|
||||
inline Scalar squaredNorm() const { return m_coeffs.squaredNorm(); }
|
||||
|
||||
/** \returns the norm of the quaternion's coefficients
|
||||
* \sa Quaternion::norm2(), MatrixBase::norm()
|
||||
* \sa Quaternion::squaredNorm(), MatrixBase::norm()
|
||||
*/
|
||||
inline Scalar norm() const { return m_coeffs.norm(); }
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
* \sa normalized(), MatrixBase::normalize() */
|
||||
inline void normalize() { m_coeffs.normalize(); }
|
||||
inline void normalize() { m_coeffs.normalize(); }
|
||||
/** \returns a normalized version of \c *this
|
||||
* \sa normalize(), MatrixBase::normalized() */
|
||||
inline Quaternion normalized() const { Quaternion(m_coeffs.normalized()); }
|
||||
inline Quaternion normalized() const { return Quaternion(m_coeffs.normalized()); }
|
||||
|
||||
/** \returns the dot product of \c *this and \a other
|
||||
* Geometrically speaking, the dot product of two unit quaternions
|
||||
@@ -195,12 +192,35 @@ public:
|
||||
template<typename Derived>
|
||||
Vector3 operator* (const MatrixBase<Derived>& vec) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const
|
||||
{ return typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Quaternion(const Quaternion<OtherScalarType>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Quaternion& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision quaternion type */
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
@@ -258,7 +278,7 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const Quaternion& other
|
||||
template<typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const AngleAxisType& aa)
|
||||
{
|
||||
Scalar ha = 0.5*aa.angle();
|
||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||
this->w() = ei_cos(ha);
|
||||
this->vec() = ei_sin(ha) * aa.axis();
|
||||
return *this;
|
||||
@@ -288,18 +308,18 @@ Quaternion<Scalar>::toRotationMatrix(void) const
|
||||
// it has to be inlined, and so the return by value is not an issue
|
||||
Matrix3 res;
|
||||
|
||||
Scalar tx = 2*this->x();
|
||||
Scalar ty = 2*this->y();
|
||||
Scalar tz = 2*this->z();
|
||||
Scalar twx = tx*this->w();
|
||||
Scalar twy = ty*this->w();
|
||||
Scalar twz = tz*this->w();
|
||||
Scalar txx = tx*this->x();
|
||||
Scalar txy = ty*this->x();
|
||||
Scalar txz = tz*this->x();
|
||||
Scalar tyy = ty*this->y();
|
||||
Scalar tyz = tz*this->y();
|
||||
Scalar tzz = tz*this->z();
|
||||
const Scalar tx = 2*this->x();
|
||||
const Scalar ty = 2*this->y();
|
||||
const Scalar tz = 2*this->z();
|
||||
const Scalar twx = tx*this->w();
|
||||
const Scalar twy = ty*this->w();
|
||||
const Scalar twz = tz*this->w();
|
||||
const Scalar txx = tx*this->x();
|
||||
const Scalar txy = ty*this->x();
|
||||
const Scalar txz = tz*this->x();
|
||||
const Scalar tyy = ty*this->y();
|
||||
const Scalar tyz = tz*this->y();
|
||||
const Scalar tzz = tz*this->z();
|
||||
|
||||
res.coeffRef(0,0) = 1-(tyy+tzz);
|
||||
res.coeffRef(0,1) = txy-twz;
|
||||
@@ -314,9 +334,11 @@ Quaternion<Scalar>::toRotationMatrix(void) const
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Makes a quaternion representing the rotation between two vectors \a a and \a b.
|
||||
* \returns a reference to the actual quaternion
|
||||
* Note that the two input vectors have \b not to be normalized.
|
||||
/** Sets *this to be a quaternion representing a rotation sending the vector \a a to the vector \a b.
|
||||
*
|
||||
* \returns a reference to *this.
|
||||
*
|
||||
* Note that the two input vectors do \b not have to be normalized.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived1, typename Derived2>
|
||||
@@ -333,10 +355,10 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
|
||||
// set to identity
|
||||
this->w() = 1; this->vec().setZero();
|
||||
}
|
||||
Scalar s = ei_sqrt((1+c)*2);
|
||||
Scalar invs = 1./s;
|
||||
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
|
||||
Scalar invs = Scalar(1)/s;
|
||||
this->vec() = axis * invs;
|
||||
this->w() = s * 0.5;
|
||||
this->w() = s * Scalar(0.5);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -351,7 +373,7 @@ template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::inverse() const
|
||||
{
|
||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||
Scalar n2 = this->norm2();
|
||||
Scalar n2 = this->squaredNorm();
|
||||
if (n2 > 0)
|
||||
return Quaternion(conjugate().coeffs() / n2);
|
||||
else
|
||||
@@ -382,7 +404,7 @@ inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
|
||||
double d = ei_abs(this->dot(other));
|
||||
if (d>=1.0)
|
||||
return 0;
|
||||
return 2.0 * std::acos(d);
|
||||
return Scalar(2) * std::acos(d);
|
||||
}
|
||||
|
||||
/** \returns the spherical linear interpolation between the two quaternions
|
||||
@@ -438,9 +460,9 @@ struct ei_quaternion_assign_impl<Other,3,3>
|
||||
int j = (i+1)%3;
|
||||
int k = (j+1)%3;
|
||||
|
||||
t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + 1.0);
|
||||
q.coeffs().coeffRef(i) = 0.5 * t;
|
||||
t = 0.5/t;
|
||||
t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
|
||||
q.coeffs().coeffRef(i) = Scalar(0.5) * t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
|
||||
q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
|
||||
q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_ROTATION2D_H
|
||||
#define EIGEN_ROTATION2D_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Rotation2D
|
||||
*
|
||||
@@ -100,12 +100,35 @@ public:
|
||||
*/
|
||||
inline Rotation2D slerp(Scalar t, const Rotation2D& other) const
|
||||
{ return m_angle * (1-t) + other.angle() * t; }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
{ return typename ei_cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
{
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Rotation2D& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision 2D rotation type */
|
||||
typedef Rotation2D<float> Rotation2Df;
|
||||
/** \ingroup GeometryModule
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision 2D rotation type */
|
||||
typedef Rotation2D<double> Rotation2Dd;
|
||||
|
||||
@@ -117,7 +140,7 @@ template<typename Scalar>
|
||||
template<typename Derived>
|
||||
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_angle = ei_atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim));
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
*this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim));
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
return *this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
template<typename Scalar, int Dim>
|
||||
inline static Matrix<Scalar,2,2> ei_toRotationMatrix(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2,you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ template<typename Scalar, int Dim, typename OtherDerived>
|
||||
inline static const MatrixBase<OtherDerived>& ei_toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||
you_did_a_programming_error);
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_SCALING_H
|
||||
#define EIGEN_SCALING_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Scaling
|
||||
*
|
||||
@@ -35,17 +35,15 @@
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a scaling transformation,
|
||||
* but rather to make easier the constructions and updates of Transformation object.
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Translation, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Scaling
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
@@ -120,7 +118,7 @@ public:
|
||||
|
||||
/** \returns the inverse scaling */
|
||||
inline Scaling inverse() const
|
||||
{ return Scaling(coeffs.cwise().inverse()); }
|
||||
{ return Scaling(coeffs().cwise().inverse()); }
|
||||
|
||||
inline Scaling& operator=(const Scaling& other)
|
||||
{
|
||||
@@ -128,9 +126,30 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Scaling(const Scaling<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Scaling& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup GeometryModule */
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Scaling<float, 2> Scaling2f;
|
||||
typedef Scaling<double,2> Scaling2d;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -42,7 +43,7 @@ template< typename Other,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_transform_product_impl;
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Transform
|
||||
*
|
||||
@@ -61,12 +62,9 @@ struct ei_transform_product_impl;
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Transform
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
|
||||
enum {
|
||||
Dim = _Dim, ///< space dimension in which the transformation holds
|
||||
HDim = _Dim+1 ///< size of a respective homogeneous vector
|
||||
@@ -98,12 +96,19 @@ public:
|
||||
inline Transform() { }
|
||||
|
||||
inline Transform(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; }
|
||||
{
|
||||
m_matrix = other.m_matrix;
|
||||
}
|
||||
|
||||
inline explicit Transform(const TranslationType& t) { *this = t; }
|
||||
inline explicit Transform(const ScalingType& s) { *this = s; }
|
||||
template<typename Derived>
|
||||
inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
|
||||
|
||||
inline Transform& operator=(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; return *this; }
|
||||
|
||||
template<typename OtherDerived, bool select = OtherDerived::RowsAtCompileTime == Dim>
|
||||
template<typename OtherDerived, bool BigMatrix> // MSVC 2005 will commit suicide if BigMatrix has a default value
|
||||
struct construct_from_matrix
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
@@ -127,7 +132,7 @@ public:
|
||||
template<typename OtherDerived>
|
||||
inline explicit Transform(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
construct_from_matrix<OtherDerived>::run(this, other);
|
||||
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
|
||||
}
|
||||
|
||||
/** Set \c *this from a (Dim+1)^2 matrix. */
|
||||
@@ -179,10 +184,17 @@ public:
|
||||
operator * (const MatrixBase<OtherDerived> &other) const
|
||||
{ return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
|
||||
|
||||
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
||||
* The transformation matrix \a a must have a Dim+1 x Dim+1 sizes. */
|
||||
template<typename OtherDerived>
|
||||
friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
|
||||
operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
|
||||
{ return a.derived() * b.matrix(); }
|
||||
|
||||
/** Contatenates two transformations */
|
||||
inline const typename ProductReturnType<MatrixType,MatrixType>::Type
|
||||
inline const Transform
|
||||
operator * (const Transform& other) const
|
||||
{ return m_matrix * other.matrix(); }
|
||||
{ return Transform(m_matrix * other.matrix()); }
|
||||
|
||||
/** \sa MatrixBase::setIdentity() */
|
||||
void setIdentity() { m_matrix.setIdentity(); }
|
||||
@@ -226,14 +238,18 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
// template<typename Derived>
|
||||
// inline Transform& operator=(const Rotation<Derived,Dim>& t);
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
|
||||
LinearMatrixType extractRotation(TransformTraits traits = Affine) const;
|
||||
LinearMatrixType rotation() const;
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
@@ -241,20 +257,43 @@ public:
|
||||
|
||||
inline const MatrixType inverse(TransformTraits traits = Affine) const;
|
||||
|
||||
/** \returns a const pointer to the column major internal matrix */
|
||||
const Scalar* data() const { return m_matrix.data(); }
|
||||
/** \returns a non-const pointer to the column major internal matrix */
|
||||
Scalar* data() { return m_matrix.data(); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
|
||||
{ m_matrix = other.matrix().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,2> Transform2f;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,3> Transform3f;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,2> Transform2d;
|
||||
/** \ingroup GeometryModule */
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,3> Transform3d;
|
||||
|
||||
/**************************
|
||||
@@ -279,7 +318,7 @@ Transform<Scalar,Dim>::Transform(const QMatrix& other)
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
0, 0, 1;
|
||||
@@ -295,7 +334,7 @@ Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
|
||||
template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QMatrix(other.coeffRef(0,0), other.coeffRef(1,0),
|
||||
other.coeffRef(0,1), other.coeffRef(1,1),
|
||||
other.coeffRef(0,2), other.coeffRef(1,2));
|
||||
@@ -318,7 +357,7 @@ Transform<Scalar,Dim>::Transform(const QTransform& other)
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
other.m13(), other.m23(), other.m33();
|
||||
@@ -332,7 +371,7 @@ Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
|
||||
template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQTransform(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QTransform(other.coeffRef(0,0), other.coeffRef(1,0), other.coeffRef(2,0)
|
||||
other.coeffRef(0,1), other.coeffRef(1,1), other.coeffRef(2,1)
|
||||
other.coeffRef(0,2), other.coeffRef(1,2), other.coeffRef(2,2);
|
||||
@@ -352,7 +391,7 @@ template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim));
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
linear() = (linear() * other.asDiagonal()).lazy();
|
||||
return *this;
|
||||
}
|
||||
@@ -377,7 +416,7 @@ template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim));
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
|
||||
return *this;
|
||||
}
|
||||
@@ -402,7 +441,7 @@ template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim));
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += linear() * other;
|
||||
return *this;
|
||||
}
|
||||
@@ -416,7 +455,7 @@ template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim));
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += other;
|
||||
return *this;
|
||||
}
|
||||
@@ -473,7 +512,7 @@ template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
VectorType tmp = linear().col(0)*sy + linear().col(1);
|
||||
linear() << linear().col(0) + linear().col(1)*sx, tmp;
|
||||
return *this;
|
||||
@@ -488,7 +527,7 @@ template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, you_did_a_programming_error);
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
|
||||
return *this;
|
||||
}
|
||||
@@ -500,8 +539,10 @@ Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
|
||||
{
|
||||
setIdentity();
|
||||
linear().setIdentity();
|
||||
translation() = t.vector();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -518,7 +559,7 @@ inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType
|
||||
{
|
||||
m_matrix.setZero();
|
||||
linear().diagonal() = s.coeffs();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -530,6 +571,17 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType&
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
|
||||
{
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(r);
|
||||
translation().setZero();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
|
||||
@@ -539,47 +591,61 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase
|
||||
return res;
|
||||
}
|
||||
|
||||
/***************************
|
||||
*** Specialial functions ***
|
||||
***************************/
|
||||
/************************
|
||||
*** Special functions ***
|
||||
************************/
|
||||
|
||||
/** \returns the rotation part of the transformation
|
||||
* \nonstableyet
|
||||
*
|
||||
* \param traits allows to optimize the extraction process when the transformion
|
||||
* is known to be not a general aafine transformation. The possible values are:
|
||||
* - Affine which use a QR decomposition (default),
|
||||
* - Isometry which simply returns the linear part !
|
||||
* \svd_module
|
||||
*
|
||||
* \warning this function consider the scaling is positive
|
||||
*
|
||||
* \warning to use this method in the general case (traits==GenericAffine), you need
|
||||
* to include the QR module.
|
||||
*
|
||||
* \sa inverse(), class QR
|
||||
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
typename Transform<Scalar,Dim>::LinearMatrixType
|
||||
Transform<Scalar,Dim>::extractRotation(TransformTraits traits) const
|
||||
Transform<Scalar,Dim>::rotation() const
|
||||
{
|
||||
ei_assert(traits!=Projective && "you cannot extract a rotation from a non affine transformation");
|
||||
if (traits == Affine)
|
||||
{
|
||||
// FIXME maybe QR should be fixed to return a R matrix with a positive diagonal ??
|
||||
QR<LinearMatrixType> qr(linear());
|
||||
LinearMatrixType matQ = qr.matrixQ();
|
||||
LinearMatrixType matR = qr.matrixR();
|
||||
for (int i=0 ; i<Dim; ++i)
|
||||
if (matR(i,i)<0)
|
||||
matQ.col(i) = -matQ.col(i);
|
||||
return matQ;
|
||||
}
|
||||
else if (traits == Isometry) // though that's stupid let's handle it !
|
||||
return linear();
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Transform::extractRotation()");
|
||||
return LinearMatrixType();
|
||||
}
|
||||
LinearMatrixType result;
|
||||
computeRotationScaling(&result, (LinearMatrixType*)0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeScalingRotation(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
{
|
||||
linear().svd().computeRotationScaling(rotation, scaling);
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
{
|
||||
linear().svd().computeScalingRotation(scaling, rotation);
|
||||
}
|
||||
|
||||
/** Convenient method to set \c *this from a position, orientation and scale
|
||||
@@ -594,12 +660,14 @@ Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDer
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
|
||||
linear() *= scale.asDiagonal();
|
||||
translation() = position;
|
||||
m_matrix(Dim,Dim) = 1.;
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the inverse transformation matrix according to some given knowledge
|
||||
/** \nonstableyet
|
||||
*
|
||||
* \returns the inverse transformation matrix according to some given knowledge
|
||||
* on \c *this.
|
||||
*
|
||||
* \param traits allows to optimize the inversion process when the transformion
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef EIGEN_TRANSLATION_H
|
||||
#define EIGEN_TRANSLATION_H
|
||||
|
||||
/** \geometry_module \ingroup GeometryModule
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Translation
|
||||
*
|
||||
@@ -35,17 +35,15 @@
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a translation transformation,
|
||||
* but rather to make easier the constructions and updates of Transformation object.
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Scaling, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Translation
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
@@ -91,7 +89,7 @@ public:
|
||||
/** Concatenates two translation */
|
||||
inline Translation operator* (const Translation& other) const
|
||||
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||
|
||||
|
||||
/** Concatenates a translation and a scaling */
|
||||
inline TransformType operator* (const ScalingType& other) const;
|
||||
|
||||
@@ -131,9 +129,30 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename ei_cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename ei_cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup GeometryModule */
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Translation<float, 2> Translation2f;
|
||||
typedef Translation<double,2> Translation2d;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -92,7 +92,7 @@ bool ei_compute_inverse_in_size4_case_helper(const MatrixType& matrix, MatrixTyp
|
||||
* R' = -S' * (R*P_inverse)
|
||||
*/
|
||||
typedef Block<MatrixType,2,2> XprBlock22;
|
||||
typedef typename XprBlock22::Eval Block22;
|
||||
typedef typename MatrixBase<XprBlock22>::PlainMatrixType Block22;
|
||||
Block22 P_inverse;
|
||||
if(ei_compute_inverse_in_size2_case_with_check(matrix.template block<2,2>(0,0), &P_inverse))
|
||||
{
|
||||
@@ -132,21 +132,31 @@ void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* resu
|
||||
// since this is a rare case, we don't need to optimize it. We just want to handle it with little
|
||||
// additional code.
|
||||
MatrixType m(matrix);
|
||||
m.row(1).swap(m.row(2));
|
||||
m.row(0).swap(m.row(2));
|
||||
m.row(1).swap(m.row(3));
|
||||
if(ei_compute_inverse_in_size4_case_helper(m, result))
|
||||
{
|
||||
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that two
|
||||
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that some
|
||||
// rows were permuted, the actual inverse of matrix is derived from the inverse of m by permuting
|
||||
// the corresponding columns.
|
||||
result->col(1).swap(result->col(2));
|
||||
result->col(0).swap(result->col(2));
|
||||
result->col(1).swap(result->col(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
// last possible case. Since matrix is assumed to be invertible, this last case has to work.
|
||||
m.row(1).swap(m.row(2));
|
||||
// first, undo the swaps previously made
|
||||
m.row(0).swap(m.row(2));
|
||||
m.row(1).swap(m.row(3));
|
||||
// swap row 0 with the the row among 0 and 1 that has the biggest 2 first coeffs
|
||||
int swap0with = ei_abs(m.coeff(0,0))+ei_abs(m.coeff(0,1))>ei_abs(m.coeff(1,0))+ei_abs(m.coeff(1,1)) ? 0 : 1;
|
||||
m.row(0).swap(m.row(swap0with));
|
||||
// swap row 1 with the the row among 2 and 3 that has the biggest 2 first coeffs
|
||||
int swap1with = ei_abs(m.coeff(2,0))+ei_abs(m.coeff(2,1))>ei_abs(m.coeff(3,0))+ei_abs(m.coeff(3,1)) ? 2 : 3;
|
||||
m.row(1).swap(m.row(swap1with));
|
||||
ei_compute_inverse_in_size4_case_helper(m, result);
|
||||
result->col(1).swap(result->col(3));
|
||||
result->col(1).swap(result->col(swap1with));
|
||||
result->col(0).swap(result->col(swap0with));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,12 +226,11 @@ struct ei_compute_inverse<MatrixType, 4>
|
||||
* \sa inverse()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline void MatrixBase<Derived>::computeInverse(EvalType *result) const
|
||||
inline void MatrixBase<Derived>::computeInverse(PlainMatrixType *result) const
|
||||
{
|
||||
typedef typename ei_eval<Derived>::type MatrixType;
|
||||
ei_assert(rows() == cols());
|
||||
EIGEN_STATIC_ASSERT(NumTraits<Scalar>::HasFloatingPoint,scalar_type_must_be_floating_point);
|
||||
ei_compute_inverse<MatrixType>::run(eval(), result);
|
||||
EIGEN_STATIC_ASSERT(NumTraits<Scalar>::HasFloatingPoint,NUMERIC_TYPE_MUST_BE_FLOATING_POINT)
|
||||
ei_compute_inverse<PlainMatrixType>::run(eval(), result);
|
||||
}
|
||||
|
||||
/** \lu_module
|
||||
@@ -239,9 +248,9 @@ inline void MatrixBase<Derived>::computeInverse(EvalType *result) const
|
||||
* \sa computeInverse()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::EvalType MatrixBase<Derived>::inverse() const
|
||||
inline const typename MatrixBase<Derived>::PlainMatrixType MatrixBase<Derived>::inverse() const
|
||||
{
|
||||
EvalType result(rows(), cols());
|
||||
PlainMatrixType result(rows(), cols());
|
||||
computeInverse(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -35,23 +35,25 @@
|
||||
*
|
||||
* This class represents a LU decomposition of any matrix, with complete pivoting: the matrix A
|
||||
* is decomposed as A = PLUQ where L is unit-lower-triangular, U is upper-triangular, and P and Q
|
||||
* are permutation matrices. This is a rank-revealing LU decomposition. The eigenvalues of U are
|
||||
* in non-increasing order.
|
||||
* are permutation matrices. This is a rank-revealing LU decomposition. The eigenvalues (diagonal
|
||||
* coefficients) of U are sorted in such a way that any zeros are at the end, so that the rank
|
||||
* of A is the index of the first zero on the diagonal of U (with indices starting at 0) if any.
|
||||
*
|
||||
* This decomposition provides the generic approach to solving systems of linear equations, computing
|
||||
* the rank, invertibility, inverse, kernel, and determinant.
|
||||
*
|
||||
* This LU decomposition is very stable and well tested with large matrices. Even exact rank computation
|
||||
* works at sizes larger than 1000x1000. However there are use cases where the SVD decomposition is inherently
|
||||
* more stable when dealing with numerically damaged input. For example, computing the kernel is more stable with
|
||||
* SVD because the SVD can determine which singular values are negligible while LU has to work at the level of matrix
|
||||
* coefficients that are less meaningful in this respect.
|
||||
*
|
||||
* The data of the LU decomposition can be directly accessed through the methods matrixLU(),
|
||||
* permutationP(), permutationQ(). Convenience methods matrixL(), matrixU() are also provided.
|
||||
* permutationP(), permutationQ().
|
||||
*
|
||||
* As an exemple, here is how the original matrix can be retrieved, in the square case:
|
||||
* \include class_LU_1.cpp
|
||||
* Output: \verbinclude class_LU_1.out
|
||||
*
|
||||
* When the matrix is not square, matrixL() is no longer very useful: if one needs it, one has
|
||||
* to construct the L matrix by hand, as shown in this example:
|
||||
* \include class_LU_2.cpp
|
||||
* Output: \verbinclude class_LU_2.out
|
||||
* As an exemple, here is how the original matrix can be retrieved:
|
||||
* \include class_LU.cpp
|
||||
* Output: \verbinclude class_LU.out
|
||||
*
|
||||
* \sa MatrixBase::lu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse()
|
||||
*/
|
||||
@@ -71,9 +73,24 @@ template<typename MatrixType> class LU
|
||||
MatrixType::MaxRowsAtCompileTime)
|
||||
};
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, Dynamic,
|
||||
MatrixType::Flags&RowMajorBit,
|
||||
MatrixType::MaxColsAtCompileTime, MaxSmallDimAtCompileTime> KernelResultType;
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix
|
||||
// so that the product "matrix * kernel = zero" makes sense
|
||||
Dynamic, // we don't know at compile-time the dimension of the kernel
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
|
||||
MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number
|
||||
// of columns of the original matrix
|
||||
> KernelResultType;
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number
|
||||
// of rows of the original matrix
|
||||
Dynamic, // we don't know at compile time the dimension of the image (the rank)
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
|
||||
MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
|
||||
> ImageResultType;
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
@@ -92,28 +109,6 @@ template<typename MatrixType> class LU
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns an expression of the unit-lower-triangular part of the LU matrix. In the square case,
|
||||
* this is the L matrix. In the non-square, actually obtaining the L matrix takes some
|
||||
* more care, see the documentation of class LU.
|
||||
*
|
||||
* \sa matrixLU(), matrixU()
|
||||
*/
|
||||
inline const Part<MatrixType, UnitLower> matrixL() const
|
||||
{
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns an expression of the U matrix, i.e. the upper-triangular part of the LU matrix.
|
||||
*
|
||||
* \note The eigenvalues of U are sorted in non-increasing order.
|
||||
*
|
||||
* \sa matrixLU(), matrixL()
|
||||
*/
|
||||
inline const Part<MatrixType, Upper> matrixU() const
|
||||
{
|
||||
return m_lu;
|
||||
}
|
||||
|
||||
/** \returns a vector of integers, whose size is the number of rows of the matrix being decomposed,
|
||||
* representing the P permutation i.e. the permutation of the rows. For its precise meaning,
|
||||
* see the examples given in the documentation of class LU.
|
||||
@@ -136,10 +131,10 @@ template<typename MatrixType> class LU
|
||||
return m_q;
|
||||
}
|
||||
|
||||
/** Computes the kernel of the matrix.
|
||||
/** Computes a basis of the kernel of the matrix, also called the null-space of the matrix.
|
||||
*
|
||||
* \note: this method is only allowed on non-invertible matrices, as determined by
|
||||
* isInvertible(). Calling it on an invertible matrice will make an assertion fail.
|
||||
* \note This method is only allowed on non-invertible matrices, as determined by
|
||||
* isInvertible(). Calling it on an invertible matrix will make an assertion fail.
|
||||
*
|
||||
* \param result a pointer to the matrix in which to store the kernel. The columns of this
|
||||
* matrix will be set to form a basis of the kernel (it will be resized
|
||||
@@ -148,15 +143,32 @@ template<typename MatrixType> class LU
|
||||
* Example: \include LU_computeKernel.cpp
|
||||
* Output: \verbinclude LU_computeKernel.out
|
||||
*
|
||||
* \sa kernel()
|
||||
* \sa kernel(), computeImage(), image()
|
||||
*/
|
||||
void computeKernel(KernelResultType *result) const;
|
||||
template<typename KernelMatrixType>
|
||||
void computeKernel(KernelMatrixType *result) const;
|
||||
|
||||
/** \returns the kernel of the matrix. The columns of the returned matrix
|
||||
/** Computes a basis of the image of the matrix, also called the column-space or range of he matrix.
|
||||
*
|
||||
* \note Calling this method on the zero matrix will make an assertion fail.
|
||||
*
|
||||
* \param result a pointer to the matrix in which to store the image. The columns of this
|
||||
* matrix will be set to form a basis of the image (it will be resized
|
||||
* if necessary).
|
||||
*
|
||||
* Example: \include LU_computeImage.cpp
|
||||
* Output: \verbinclude LU_computeImage.out
|
||||
*
|
||||
* \sa image(), computeKernel(), kernel()
|
||||
*/
|
||||
template<typename ImageMatrixType>
|
||||
void computeImage(ImageMatrixType *result) const;
|
||||
|
||||
/** \returns the kernel of the matrix, also called its null-space. The columns of the returned matrix
|
||||
* will form a basis of the kernel.
|
||||
*
|
||||
* \note: this method is only allowed on non-invertible matrices, as determined by
|
||||
* isInvertible(). Calling it on an invertible matrice will make an assertion fail.
|
||||
* isInvertible(). Calling it on an invertible matrix will make an assertion fail.
|
||||
*
|
||||
* \note: this method returns a matrix by value, which induces some inefficiency.
|
||||
* If you prefer to avoid this overhead, use computeKernel() instead.
|
||||
@@ -164,10 +176,25 @@ template<typename MatrixType> class LU
|
||||
* Example: \include LU_kernel.cpp
|
||||
* Output: \verbinclude LU_kernel.out
|
||||
*
|
||||
* \sa computeKernel()
|
||||
* \sa computeKernel(), image()
|
||||
*/
|
||||
const KernelResultType kernel() const;
|
||||
|
||||
/** \returns the image of the matrix, also called its column-space. The columns of the returned matrix
|
||||
* will form a basis of the kernel.
|
||||
*
|
||||
* \note: Calling this method on the zero matrix will make an assertion fail.
|
||||
*
|
||||
* \note: this method returns a matrix by value, which induces some inefficiency.
|
||||
* If you prefer to avoid this overhead, use computeImage() instead.
|
||||
*
|
||||
* Example: \include LU_image.cpp
|
||||
* Output: \verbinclude LU_image.out
|
||||
*
|
||||
* \sa computeImage(), kernel()
|
||||
*/
|
||||
const ImageResultType image() const;
|
||||
|
||||
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the LU decomposition, if any exists.
|
||||
*
|
||||
@@ -181,7 +208,8 @@ template<typename MatrixType> class LU
|
||||
* \returns true if any solution exists, false if no solution exists.
|
||||
*
|
||||
* \note If there exist more than one solution, this method will arbitrarily choose one.
|
||||
* If you need a complete analysis of the space of solutions, take the one solution obtained * by this method and add to it elements of the kernel, as determined by kernel().
|
||||
* If you need a complete analysis of the space of solutions, take the one solution obtained
|
||||
* by this method and add to it elements of the kernel, as determined by kernel().
|
||||
*
|
||||
* Example: \include LU_solve.cpp
|
||||
* Output: \verbinclude LU_solve.out
|
||||
@@ -189,10 +217,7 @@ template<typename MatrixType> class LU
|
||||
* \sa MatrixBase::solveTriangular(), kernel(), computeKernel(), inverse(), computeInverse()
|
||||
*/
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(
|
||||
const MatrixBase<OtherDerived>& b,
|
||||
ResultType *result
|
||||
) const;
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
|
||||
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the LU decomposition. It has only linear complexity
|
||||
@@ -292,72 +317,86 @@ template<typename MatrixType> class LU
|
||||
}
|
||||
|
||||
protected:
|
||||
const MatrixType& m_originalMatrix;
|
||||
MatrixType m_lu;
|
||||
IntColVectorType m_p;
|
||||
IntRowVectorType m_q;
|
||||
int m_det_pq;
|
||||
int m_rank;
|
||||
RealScalar m_precision;
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
LU<MatrixType>::LU(const MatrixType& matrix)
|
||||
: m_lu(matrix),
|
||||
: m_originalMatrix(matrix),
|
||||
m_lu(matrix),
|
||||
m_p(matrix.rows()),
|
||||
m_q(matrix.cols())
|
||||
{
|
||||
const int size = matrix.diagonal().size();
|
||||
const int rows = matrix.rows();
|
||||
const int cols = matrix.cols();
|
||||
|
||||
// this formula comes from experimenting (see "LU precision tuning" thread on the list)
|
||||
// and turns out to be identical to Higham's formula used already in LDLt.
|
||||
m_precision = machine_epsilon<Scalar>() * size;
|
||||
|
||||
IntColVectorType rows_transpositions(matrix.rows());
|
||||
IntRowVectorType cols_transpositions(matrix.cols());
|
||||
int number_of_transpositions = 0;
|
||||
|
||||
RealScalar biggest = RealScalar(0);
|
||||
for(int k = 0; k < size; k++)
|
||||
m_rank = size;
|
||||
for(int k = 0; k < size; ++k)
|
||||
{
|
||||
int row_of_biggest_in_corner, col_of_biggest_in_corner;
|
||||
RealScalar biggest_in_corner;
|
||||
|
||||
biggest_in_corner = m_lu.corner(Eigen::BottomRight, rows-k, cols-k)
|
||||
.cwise().abs()
|
||||
.maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
|
||||
.cwise().abs()
|
||||
.maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
|
||||
row_of_biggest_in_corner += k;
|
||||
col_of_biggest_in_corner += k;
|
||||
if(k==0) biggest = biggest_in_corner;
|
||||
|
||||
// if the corner is negligible, then we have less than full rank, and we can finish early
|
||||
if(ei_isMuchSmallerThan(biggest_in_corner, biggest, m_precision))
|
||||
{
|
||||
m_rank = k;
|
||||
for(int i = k; i < size; i++)
|
||||
{
|
||||
rows_transpositions.coeffRef(i) = i;
|
||||
cols_transpositions.coeffRef(i) = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
|
||||
cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
|
||||
if(k != row_of_biggest_in_corner) {
|
||||
m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
|
||||
number_of_transpositions++;
|
||||
++number_of_transpositions;
|
||||
}
|
||||
if(k != col_of_biggest_in_corner) {
|
||||
m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
|
||||
number_of_transpositions++;
|
||||
++number_of_transpositions;
|
||||
}
|
||||
|
||||
if(k==0) biggest = biggest_in_corner;
|
||||
const Scalar lu_k_k = m_lu.coeff(k,k);
|
||||
if(ei_isMuchSmallerThan(lu_k_k, biggest)) continue;
|
||||
if(k<rows-1)
|
||||
m_lu.col(k).end(rows-k-1) /= lu_k_k;
|
||||
m_lu.col(k).end(rows-k-1) /= m_lu.coeff(k,k);
|
||||
if(k<size-1)
|
||||
for( int col = k + 1; col < cols; col++ )
|
||||
for(int col = k + 1; col < cols; ++col)
|
||||
m_lu.col(col).end(rows-k-1) -= m_lu.col(k).end(rows-k-1) * m_lu.coeff(k,col);
|
||||
}
|
||||
|
||||
for(int k = 0; k < matrix.rows(); k++) m_p.coeffRef(k) = k;
|
||||
for(int k = size-1; k >= 0; k--)
|
||||
for(int k = 0; k < matrix.rows(); ++k) m_p.coeffRef(k) = k;
|
||||
for(int k = size-1; k >= 0; --k)
|
||||
std::swap(m_p.coeffRef(k), m_p.coeffRef(rows_transpositions.coeff(k)));
|
||||
|
||||
for(int k = 0; k < matrix.cols(); k++) m_q.coeffRef(k) = k;
|
||||
for(int k = 0; k < size; k++)
|
||||
for(int k = 0; k < matrix.cols(); ++k) m_q.coeffRef(k) = k;
|
||||
for(int k = 0; k < size; ++k)
|
||||
std::swap(m_q.coeffRef(k), m_q.coeffRef(cols_transpositions.coeff(k)));
|
||||
|
||||
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
||||
|
||||
for(m_rank = 0; m_rank < size; m_rank++)
|
||||
if(ei_isMuchSmallerThan(m_lu.diagonal().coeff(m_rank), m_lu.diagonal().coeff(0)))
|
||||
break;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
@@ -367,7 +406,8 @@ typename ei_traits<MatrixType>::Scalar LU<MatrixType>::determinant() const
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void LU<MatrixType>::computeKernel(KernelResultType *result) const
|
||||
template<typename KernelMatrixType>
|
||||
void LU<MatrixType>::computeKernel(KernelMatrixType *result) const
|
||||
{
|
||||
ei_assert(!isInvertible());
|
||||
const int dimker = dimensionOfKernel(), cols = m_lu.cols();
|
||||
@@ -376,31 +416,30 @@ void LU<MatrixType>::computeKernel(KernelResultType *result) const
|
||||
/* Let us use the following lemma:
|
||||
*
|
||||
* Lemma: If the matrix A has the LU decomposition PAQ = LU,
|
||||
* then Ker A = Q( Ker U ).
|
||||
* then Ker A = Q(Ker U).
|
||||
*
|
||||
* Proof: trivial: just keep in mind that P, Q, L are invertible.
|
||||
*/
|
||||
|
||||
/* Thus, all we need to do is to compute Ker U, and then apply Q.
|
||||
*
|
||||
* U is upper triangular, with eigenvalues sorted in decreasing order of
|
||||
* absolute value. Thus, the diagonal of U ends with exactly
|
||||
* U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
|
||||
* Thus, the diagonal of U ends with exactly
|
||||
* m_dimKer zero's. Let us use that to construct m_dimKer linearly
|
||||
* independent vectors in Ker U.
|
||||
*/
|
||||
|
||||
Matrix<Scalar, Dynamic, Dynamic, MatrixType::Flags&RowMajorBit,
|
||||
MatrixType::MaxColsAtCompileTime, MaxSmallDimAtCompileTime>
|
||||
Matrix<Scalar, Dynamic, Dynamic, MatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime, MatrixType::MaxColsAtCompileTime>
|
||||
y(-m_lu.corner(TopRight, m_rank, dimker));
|
||||
|
||||
m_lu.corner(TopLeft, m_rank, m_rank)
|
||||
.template marked<Upper>()
|
||||
.template marked<UpperTriangular>()
|
||||
.solveTriangularInPlace(y);
|
||||
|
||||
for(int i = 0; i < m_rank; i++)
|
||||
result->row(m_q.coeff(i)) = y.row(i);
|
||||
for(int i = m_rank; i < cols; i++) result->row(m_q.coeff(i)).setZero();
|
||||
for(int k = 0; k < dimker; k++) result->coeffRef(m_q.coeff(m_rank+k), k) = Scalar(1);
|
||||
for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = y.row(i);
|
||||
for(int i = m_rank; i < cols; ++i) result->row(m_q.coeff(i)).setZero();
|
||||
for(int k = 0; k < dimker; ++k) result->coeffRef(m_q.coeff(m_rank+k), k) = Scalar(1);
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
@@ -412,6 +451,25 @@ LU<MatrixType>::kernel() const
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
template<typename ImageMatrixType>
|
||||
void LU<MatrixType>::computeImage(ImageMatrixType *result) const
|
||||
{
|
||||
ei_assert(m_rank > 0);
|
||||
result->resize(m_originalMatrix.rows(), m_rank);
|
||||
for(int i = 0; i < m_rank; ++i)
|
||||
result->col(i) = m_originalMatrix.col(m_q.coeff(i));
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
const typename LU<MatrixType>::ImageResultType
|
||||
LU<MatrixType>::image() const
|
||||
{
|
||||
ImageResultType result(m_originalMatrix.rows(), m_rank);
|
||||
computeImage(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool LU<MatrixType>::solve(
|
||||
@@ -423,51 +481,47 @@ bool LU<MatrixType>::solve(
|
||||
* So we proceed as follows:
|
||||
* Step 1: compute c = Pb.
|
||||
* Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
|
||||
* Step 3: compute d such that Ud = c. Check if such d really exists.
|
||||
* Step 4: result = Qd;
|
||||
* Step 3: replace c by the solution x to Ux = c. Check if a solution really exists.
|
||||
* Step 4: result = Qc;
|
||||
*/
|
||||
|
||||
const int rows = m_lu.rows();
|
||||
const int rows = m_lu.rows(), cols = m_lu.cols();
|
||||
ei_assert(b.rows() == rows);
|
||||
const int smalldim = std::min(rows, m_lu.cols());
|
||||
const int smalldim = std::min(rows, cols);
|
||||
|
||||
typename OtherDerived::Eval c(b.rows(), b.cols());
|
||||
typename OtherDerived::PlainMatrixType c(b.rows(), b.cols());
|
||||
|
||||
// Step 1
|
||||
for(int i = 0; i < rows; i++) c.row(m_p.coeff(i)) = b.row(i);
|
||||
for(int i = 0; i < rows; ++i) c.row(m_p.coeff(i)) = b.row(i);
|
||||
|
||||
// Step 2
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime,
|
||||
MatrixType::Flags&RowMajorBit,
|
||||
MatrixType::MaxRowsAtCompileTime,
|
||||
MatrixType::MaxRowsAtCompileTime> l(rows, rows);
|
||||
l.setZero();
|
||||
l.corner(Eigen::TopLeft,rows,smalldim)
|
||||
= m_lu.corner(Eigen::TopLeft,rows,smalldim);
|
||||
l.template marked<UnitLower>().solveTriangularInPlace(c);
|
||||
m_lu.corner(Eigen::TopLeft,smalldim,smalldim).template marked<UnitLowerTriangular>()
|
||||
.solveTriangularInPlace(
|
||||
c.corner(Eigen::TopLeft, smalldim, c.cols()));
|
||||
if(rows>cols)
|
||||
{
|
||||
c.corner(Eigen::BottomLeft, rows-cols, c.cols())
|
||||
-= m_lu.corner(Eigen::BottomLeft, rows-cols, cols) * c.corner(Eigen::TopLeft, cols, c.cols());
|
||||
}
|
||||
|
||||
// Step 3
|
||||
if(!isSurjective())
|
||||
{
|
||||
// is c is in the image of U ?
|
||||
RealScalar biggest_in_c = c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff();
|
||||
for(int col = 0; col < c.cols(); col++)
|
||||
for(int row = m_rank; row < c.rows(); row++)
|
||||
if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c))
|
||||
for(int col = 0; col < c.cols(); ++col)
|
||||
for(int row = m_rank; row < c.rows(); ++row)
|
||||
if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c, m_precision))
|
||||
return false;
|
||||
}
|
||||
Matrix<Scalar, Dynamic, OtherDerived::ColsAtCompileTime,
|
||||
MatrixType::Flags&RowMajorBit,
|
||||
MatrixType::MaxRowsAtCompileTime, OtherDerived::MaxColsAtCompileTime>
|
||||
d(c.corner(TopLeft, m_rank, c.cols()));
|
||||
m_lu.corner(TopLeft, m_rank, m_rank)
|
||||
.template marked<Upper>()
|
||||
.solveTriangularInPlace(d);
|
||||
.template marked<UpperTriangular>()
|
||||
.solveTriangularInPlace(c.corner(TopLeft, m_rank, c.cols()));
|
||||
|
||||
// Step 4
|
||||
result->resize(m_lu.cols(), b.cols());
|
||||
for(int i = 0; i < m_rank; i++) result->row(m_q.coeff(i)) = d.row(i);
|
||||
for(int i = m_rank; i < m_lu.cols(); i++) result->row(m_q.coeff(i)).setZero();
|
||||
for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = c.row(i);
|
||||
for(int i = m_rank; i < m_lu.cols(); ++i) result->row(m_q.coeff(i)).setZero();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -478,10 +532,10 @@ bool LU<MatrixType>::solve(
|
||||
* \sa class LU
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LU<typename MatrixBase<Derived>::EvalType>
|
||||
inline const LU<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::lu() const
|
||||
{
|
||||
return eval();
|
||||
return LU<PlainMatrixType>(eval());
|
||||
}
|
||||
|
||||
#endif // EIGEN_LU_H
|
||||
|
||||
6
Eigen/src/LeastSquares/CMakeLists.txt
Normal file
6
Eigen/src/LeastSquares/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB Eigen_LeastSquares_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_LeastSquares_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/LeastSquares
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -22,12 +22,12 @@
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_REGRESSION_H
|
||||
#define EIGEN_REGRESSION_H
|
||||
#ifndef EIGEN_LEASTSQUARES_H
|
||||
#define EIGEN_LEASTSQUARES_H
|
||||
|
||||
/** \ingroup Regression_Module
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \regression_module
|
||||
* \leastsquares_module
|
||||
*
|
||||
* For a set of points, this function tries to express
|
||||
* one of the coords as a linear (affine) function of the other coords.
|
||||
@@ -57,7 +57,7 @@
|
||||
Vector3d coeffs; // will store the coefficients a, b, c
|
||||
linearRegression(
|
||||
5,
|
||||
points,
|
||||
&points,
|
||||
&coeffs,
|
||||
1 // the coord to express as a function of
|
||||
// the other ones. 0 means x, 1 means y, 2 means z.
|
||||
@@ -80,11 +80,11 @@
|
||||
This vector must be of the same type and size as the
|
||||
data points. The meaning of its coords is as follows.
|
||||
For brevity, let \f$n=Size\f$,
|
||||
\f$r_i=retCoefficients[i]\f$,
|
||||
\f$r_i=result[i]\f$,
|
||||
and \f$f=funcOfOthers\f$. Denote by
|
||||
\f$x_0,\ldots,x_{n-1}\f$
|
||||
the n coordinates in the n-dimensional space.
|
||||
Then the result equation is:
|
||||
Then the resulting equation is:
|
||||
\f[ x_f = r_0 x_0 + \cdots + r_{f-1}x_{f-1}
|
||||
+ r_{f+1}x_{f+1} + \cdots + r_{n-1}x_{n-1} + r_n. \f]
|
||||
* @param funcOfOthers Determines which coord to express as a function of the
|
||||
@@ -101,36 +101,20 @@ void linearRegression(int numPoints,
|
||||
int funcOfOthers )
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType)
|
||||
ei_assert(numPoints >= 1);
|
||||
int size = points[0]->size();
|
||||
ei_assert(funcOfOthers >= 0 && funcOfOthers < size);
|
||||
typedef Hyperplane<Scalar, VectorType::SizeAtCompileTime> HyperplaneType;
|
||||
const int size = points[0]->size();
|
||||
result->resize(size);
|
||||
|
||||
Matrix<Scalar, Dynamic, VectorType::SizeAtCompileTime,
|
||||
Dynamic, VectorType::MaxSizeAtCompileTime, RowMajorBit>
|
||||
m(numPoints, size);
|
||||
if(funcOfOthers>0)
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
m.row(i).start(funcOfOthers) = points[i]->start(funcOfOthers);
|
||||
if(funcOfOthers<size-1)
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
m.row(i).block(funcOfOthers, size-funcOfOthers-1)
|
||||
= points[i]->end(size-funcOfOthers-1);
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
m.row(i).coeffRef(size-1) = Scalar(1);
|
||||
|
||||
VectorType v(size);
|
||||
v.setZero();
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
v += m.row(i).adjoint() * points[i]->coeff(funcOfOthers);
|
||||
|
||||
ei_assert((m.adjoint()*m).lu().solve(v, result));
|
||||
HyperplaneType h(size);
|
||||
fitHyperplane(numPoints, points, &h);
|
||||
for(int i = 0; i < funcOfOthers; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i] / h.coeffs()[funcOfOthers];
|
||||
for(int i = funcOfOthers; i < size; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i+1] / h.coeffs()[funcOfOthers];
|
||||
}
|
||||
|
||||
/** \ingroup Regression_Module
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \regression_module
|
||||
* \leastsquares_module
|
||||
*
|
||||
* This function is quite similar to linearRegression(), so we refer to the
|
||||
* documentation of this function and only list here the differences.
|
||||
@@ -170,14 +154,14 @@ void fitHyperplane(int numPoints,
|
||||
|
||||
// compute the mean of the data
|
||||
VectorType mean = VectorType::Zero(size);
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
mean += *(points[i]);
|
||||
mean /= numPoints;
|
||||
|
||||
// compute the covariance matrix
|
||||
CovMatrixType covMat = CovMatrixType::Zero(size, size);
|
||||
VectorType remean = VectorType::Zero(size);
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
{
|
||||
VectorType diff = (*(points[i]) - mean).conjugate();
|
||||
covMat += diff * diff.adjoint();
|
||||
@@ -195,4 +179,4 @@ void fitHyperplane(int numPoints,
|
||||
}
|
||||
|
||||
|
||||
#endif // EIGEN_REGRESSION_H
|
||||
#endif // EIGEN_LEASTSQUARES_H
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_EIGENSOLVER_H
|
||||
|
||||
/** \ingroup QR_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class EigenSolver
|
||||
*
|
||||
@@ -48,19 +49,74 @@ template<typename _MatrixType> class EigenSolver
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef std::complex<RealScalar> Complex;
|
||||
typedef Matrix<Complex, MatrixType::ColsAtCompileTime, 1> EigenvalueType;
|
||||
typedef Matrix<Complex, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> EigenvectorType;
|
||||
typedef Matrix<RealScalar, MatrixType::ColsAtCompileTime, 1> RealVectorType;
|
||||
typedef Matrix<RealScalar, Dynamic, 1> RealVectorTypeX;
|
||||
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via EigenSolver::compute(const MatrixType&).
|
||||
*/
|
||||
EigenSolver() : m_eivec(), m_eivalues(), m_isInitialized(false) {}
|
||||
|
||||
EigenSolver(const MatrixType& matrix)
|
||||
: m_eivec(matrix.rows(), matrix.cols()),
|
||||
m_eivalues(matrix.cols())
|
||||
m_eivalues(matrix.cols()),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
MatrixType eigenvectors(void) const { return m_eivec; }
|
||||
|
||||
EigenvalueType eigenvalues(void) const { return m_eivalues; }
|
||||
EigenvectorType eigenvectors(void) const;
|
||||
|
||||
/** \returns a real matrix V of pseudo eigenvectors.
|
||||
*
|
||||
* Let D be the block diagonal matrix with the real eigenvalues in 1x1 blocks,
|
||||
* and any complex values u+iv in 2x2 blocks [u v ; -v u]. Then, the matrices D
|
||||
* and V satisfy A*V = V*D.
|
||||
*
|
||||
* More precisely, if the diagonal matrix of the eigen values is:\n
|
||||
* \f$
|
||||
* \left[ \begin{array}{cccccc}
|
||||
* u+iv & & & & & \\
|
||||
* & u-iv & & & & \\
|
||||
* & & a+ib & & & \\
|
||||
* & & & a-ib & & \\
|
||||
* & & & & x & \\
|
||||
* & & & & & y \\
|
||||
* \end{array} \right]
|
||||
* \f$ \n
|
||||
* then, we have:\n
|
||||
* \f$
|
||||
* D =\left[ \begin{array}{cccccc}
|
||||
* u & v & & & & \\
|
||||
* -v & u & & & & \\
|
||||
* & & a & b & & \\
|
||||
* & & -b & a & & \\
|
||||
* & & & & x & \\
|
||||
* & & & & & y \\
|
||||
* \end{array} \right]
|
||||
* \f$
|
||||
*
|
||||
* \sa pseudoEigenvalueMatrix()
|
||||
*/
|
||||
const MatrixType& pseudoEigenvectors() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
return m_eivec;
|
||||
}
|
||||
|
||||
MatrixType pseudoEigenvalueMatrix() const;
|
||||
|
||||
/** \returns the eigenvalues as a column vector */
|
||||
EigenvalueType eigenvalues() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
return m_eivalues;
|
||||
}
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
@@ -72,8 +128,66 @@ template<typename _MatrixType> class EigenSolver
|
||||
protected:
|
||||
MatrixType m_eivec;
|
||||
EigenvalueType m_eivalues;
|
||||
bool m_isInitialized;
|
||||
};
|
||||
|
||||
/** \returns the real block diagonal matrix D of the eigenvalues.
|
||||
*
|
||||
* See pseudoEigenvectors() for the details.
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
int n = m_eivec.cols();
|
||||
MatrixType matD = MatrixType::Zero(n,n);
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
if (ei_isMuchSmallerThan(ei_imag(m_eivalues.coeff(i)), ei_real(m_eivalues.coeff(i))))
|
||||
matD.coeffRef(i,i) = ei_real(m_eivalues.coeff(i));
|
||||
else
|
||||
{
|
||||
matD.template block<2,2>(i,i) << ei_real(m_eivalues.coeff(i)), ei_imag(m_eivalues.coeff(i)),
|
||||
-ei_imag(m_eivalues.coeff(i)), ei_real(m_eivalues.coeff(i));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return matD;
|
||||
}
|
||||
|
||||
/** \returns the normalized complex eigenvectors as a matrix of column vectors.
|
||||
*
|
||||
* \sa eigenvalues(), pseudoEigenvectors()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
typename EigenSolver<MatrixType>::EigenvectorType EigenSolver<MatrixType>::eigenvectors(void) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "EigenSolver is not initialized.");
|
||||
int n = m_eivec.cols();
|
||||
EigenvectorType matV(n,n);
|
||||
for (int j=0; j<n; ++j)
|
||||
{
|
||||
if (ei_isMuchSmallerThan(ei_abs(ei_imag(m_eivalues.coeff(j))), ei_abs(ei_real(m_eivalues.coeff(j)))))
|
||||
{
|
||||
// we have a real eigen value
|
||||
matV.col(j) = m_eivec.col(j).template cast<Complex>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a pair of complex eigen values
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
matV.coeffRef(i,j) = Complex(m_eivec.coeff(i,j), m_eivec.coeff(i,j+1));
|
||||
matV.coeffRef(i,j+1) = Complex(m_eivec.coeff(i,j), -m_eivec.coeff(i,j+1));
|
||||
}
|
||||
matV.col(j).normalize();
|
||||
matV.col(j+1).normalize();
|
||||
++j;
|
||||
}
|
||||
}
|
||||
return matV;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void EigenSolver<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
@@ -89,6 +203,8 @@ void EigenSolver<MatrixType>::compute(const MatrixType& matrix)
|
||||
|
||||
// Reduce Hessenberg to real Schur form.
|
||||
hqr2(matH);
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
// Nonsymmetric reduction to Hessenberg form.
|
||||
@@ -104,21 +220,21 @@ void EigenSolver<MatrixType>::orthes(MatrixType& matH, RealVectorType& ort)
|
||||
int low = 0;
|
||||
int high = n-1;
|
||||
|
||||
for (int m = low+1; m <= high-1; m++)
|
||||
for (int m = low+1; m <= high-1; ++m)
|
||||
{
|
||||
// Scale column.
|
||||
Scalar scale = matH.block(m, m-1, high-m+1, 1).cwise().abs().sum();
|
||||
RealScalar scale = matH.block(m, m-1, high-m+1, 1).cwise().abs().sum();
|
||||
if (scale != 0.0)
|
||||
{
|
||||
// Compute Householder transformation.
|
||||
Scalar h = 0.0;
|
||||
RealScalar h = 0.0;
|
||||
// FIXME could be rewritten, but this one looks better wrt cache
|
||||
for (int i = high; i >= m; i--)
|
||||
{
|
||||
ort.coeffRef(i) = matH.coeff(i,m-1)/scale;
|
||||
h += ort.coeff(i) * ort.coeff(i);
|
||||
}
|
||||
Scalar g = ei_sqrt(h);
|
||||
RealScalar g = ei_sqrt(h);
|
||||
if (ort.coeff(m) > 0)
|
||||
g = -g;
|
||||
h = h - ort.coeff(m) * g;
|
||||
@@ -127,11 +243,11 @@ void EigenSolver<MatrixType>::orthes(MatrixType& matH, RealVectorType& ort)
|
||||
// Apply Householder similarity transformation
|
||||
// H = (I-u*u'/h)*H*(I-u*u')/h)
|
||||
int bSize = high-m+1;
|
||||
matH.block(m, m, bSize, n-m) -= ((ort.block(m, bSize)/h)
|
||||
* (ort.block(m, bSize).transpose() * matH.block(m, m, bSize, n-m)).lazy()).lazy();
|
||||
matH.block(m, m, bSize, n-m) -= ((ort.segment(m, bSize)/h)
|
||||
* (ort.segment(m, bSize).transpose() * matH.block(m, m, bSize, n-m)).lazy()).lazy();
|
||||
|
||||
matH.block(0, m, high+1, bSize) -= ((matH.block(0, m, high+1, bSize) * ort.block(m, bSize)).lazy()
|
||||
* (ort.block(m, bSize)/h).transpose()).lazy();
|
||||
matH.block(0, m, high+1, bSize) -= ((matH.block(0, m, high+1, bSize) * ort.segment(m, bSize)).lazy()
|
||||
* (ort.segment(m, bSize)/h).transpose()).lazy();
|
||||
|
||||
ort.coeffRef(m) = scale*ort.coeff(m);
|
||||
matH.coeffRef(m,m-1) = scale*g;
|
||||
@@ -145,16 +261,15 @@ void EigenSolver<MatrixType>::orthes(MatrixType& matH, RealVectorType& ort)
|
||||
{
|
||||
if (matH.coeff(m,m-1) != 0.0)
|
||||
{
|
||||
ort.block(m+1, high-m) = matH.col(m-1).block(m+1, high-m);
|
||||
ort.segment(m+1, high-m) = matH.col(m-1).segment(m+1, high-m);
|
||||
|
||||
int bSize = high-m+1;
|
||||
m_eivec.block(m, m, bSize, bSize) += ( (ort.block(m, bSize) / (matH.coeff(m,m-1) * ort.coeff(m) ) )
|
||||
* (ort.block(m, bSize).transpose() * m_eivec.block(m, m, bSize, bSize)).lazy());
|
||||
m_eivec.block(m, m, bSize, bSize) += ( (ort.segment(m, bSize) / (matH.coeff(m,m-1) * ort.coeff(m) ) )
|
||||
* (ort.segment(m, bSize).transpose() * m_eivec.block(m, m, bSize, bSize)).lazy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Complex scalar division.
|
||||
template<typename Scalar>
|
||||
std::complex<Scalar> cdiv(Scalar xr, Scalar xi, Scalar yr, Scalar yi)
|
||||
@@ -189,7 +304,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
int n = nn-1;
|
||||
int low = 0;
|
||||
int high = nn-1;
|
||||
Scalar eps = pow(2.0,-52.0);
|
||||
Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
|
||||
Scalar exshift = 0.0;
|
||||
Scalar p=0,q=0,r=0,s=0,z=0,t,w,x,y;
|
||||
|
||||
@@ -197,15 +312,14 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
// FIXME to be efficient the following would requires a triangular reduxion code
|
||||
// Scalar norm = matH.upper().cwise().abs().sum() + matH.corner(BottomLeft,n,n).diagonal().cwise().abs().sum();
|
||||
Scalar norm = 0.0;
|
||||
for (int j = 0; j < nn; j++)
|
||||
for (int j = 0; j < nn; ++j)
|
||||
{
|
||||
// FIXME what's the purpose of the following since the condition is always false
|
||||
if ((j < low) || (j > high))
|
||||
{
|
||||
m_eivalues.coeffRef(j).real() = matH.coeff(j,j);
|
||||
m_eivalues.coeffRef(j).imag() = 0.0;
|
||||
m_eivalues.coeffRef(j) = Complex(matH.coeff(j,j), 0.0);
|
||||
}
|
||||
norm += matH.col(j).start(std::min(j+1,nn)).cwise().abs().sum();
|
||||
norm += matH.row(j).segment(std::max(j-1,0), nn-std::max(j-1,0)).cwise().abs().sum();
|
||||
}
|
||||
|
||||
// Outer loop over eigenvalue index
|
||||
@@ -229,15 +343,14 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
if (l == n)
|
||||
{
|
||||
matH.coeffRef(n,n) = matH.coeff(n,n) + exshift;
|
||||
m_eivalues.coeffRef(n).real() = matH.coeff(n,n);
|
||||
m_eivalues.coeffRef(n).imag() = 0.0;
|
||||
m_eivalues.coeffRef(n) = Complex(matH.coeff(n,n), 0.0);
|
||||
n--;
|
||||
iter = 0;
|
||||
}
|
||||
else if (l == n-1) // Two roots found
|
||||
{
|
||||
w = matH.coeff(n,n-1) * matH.coeff(n-1,n);
|
||||
p = (matH.coeff(n-1,n-1) - matH.coeff(n,n)) / 2.0;
|
||||
p = (matH.coeff(n-1,n-1) - matH.coeff(n,n)) * Scalar(0.5);
|
||||
q = p * p + w;
|
||||
z = ei_sqrt(ei_abs(q));
|
||||
matH.coeffRef(n,n) = matH.coeff(n,n) + exshift;
|
||||
@@ -252,13 +365,9 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
else
|
||||
z = p - z;
|
||||
|
||||
m_eivalues.coeffRef(n-1).real() = x + z;
|
||||
m_eivalues.coeffRef(n).real() = m_eivalues.coeff(n-1).real();
|
||||
if (z != 0.0)
|
||||
m_eivalues.coeffRef(n).real() = x - w / z;
|
||||
m_eivalues.coeffRef(n-1) = Complex(x + z, 0.0);
|
||||
m_eivalues.coeffRef(n) = Complex(z!=0.0 ? x - w / z : m_eivalues.coeff(n-1).real(), 0.0);
|
||||
|
||||
m_eivalues.coeffRef(n-1).imag() = 0.0;
|
||||
m_eivalues.coeffRef(n).imag() = 0.0;
|
||||
x = matH.coeff(n,n-1);
|
||||
s = ei_abs(x) + ei_abs(z);
|
||||
p = x / s;
|
||||
@@ -268,7 +377,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
q = q / r;
|
||||
|
||||
// Row modification
|
||||
for (int j = n-1; j < nn; j++)
|
||||
for (int j = n-1; j < nn; ++j)
|
||||
{
|
||||
z = matH.coeff(n-1,j);
|
||||
matH.coeffRef(n-1,j) = q * z + p * matH.coeff(n,j);
|
||||
@@ -276,7 +385,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Column modification
|
||||
for (int i = 0; i <= n; i++)
|
||||
for (int i = 0; i <= n; ++i)
|
||||
{
|
||||
z = matH.coeff(i,n-1);
|
||||
matH.coeffRef(i,n-1) = q * z + p * matH.coeff(i,n);
|
||||
@@ -284,7 +393,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Accumulate transformations
|
||||
for (int i = low; i <= high; i++)
|
||||
for (int i = low; i <= high; ++i)
|
||||
{
|
||||
z = m_eivec.coeff(i,n-1);
|
||||
m_eivec.coeffRef(i,n-1) = q * z + p * m_eivec.coeff(i,n);
|
||||
@@ -293,10 +402,8 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
else // Complex pair
|
||||
{
|
||||
m_eivalues.coeffRef(n-1).real() = x + p;
|
||||
m_eivalues.coeffRef(n).real() = x + p;
|
||||
m_eivalues.coeffRef(n-1).imag() = z;
|
||||
m_eivalues.coeffRef(n).imag() = -z;
|
||||
m_eivalues.coeffRef(n-1) = Complex(x + p, z);
|
||||
m_eivalues.coeffRef(n) = Complex(x + p, -z);
|
||||
}
|
||||
n = n - 2;
|
||||
iter = 0;
|
||||
@@ -317,28 +424,28 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
if (iter == 10)
|
||||
{
|
||||
exshift += x;
|
||||
for (int i = low; i <= n; i++)
|
||||
for (int i = low; i <= n; ++i)
|
||||
matH.coeffRef(i,i) -= x;
|
||||
s = ei_abs(matH.coeff(n,n-1)) + ei_abs(matH.coeff(n-1,n-2));
|
||||
x = y = 0.75 * s;
|
||||
w = -0.4375 * s * s;
|
||||
x = y = Scalar(0.75) * s;
|
||||
w = Scalar(-0.4375) * s * s;
|
||||
}
|
||||
|
||||
// MATLAB's new ad hoc shift
|
||||
if (iter == 30)
|
||||
{
|
||||
s = (y - x) / 2.0;
|
||||
s = Scalar((y - x) / 2.0);
|
||||
s = s * s + w;
|
||||
if (s > 0)
|
||||
{
|
||||
s = ei_sqrt(s);
|
||||
if (y < x)
|
||||
s = -s;
|
||||
s = x - w / ((y - x) / 2.0 + s);
|
||||
for (int i = low; i <= n; i++)
|
||||
s = Scalar(x - w / ((y - x) / 2.0 + s));
|
||||
for (int i = low; i <= n; ++i)
|
||||
matH.coeffRef(i,i) -= s;
|
||||
exshift += s;
|
||||
x = y = w = 0.964;
|
||||
x = y = w = Scalar(0.964);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +477,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
m--;
|
||||
}
|
||||
|
||||
for (int i = m+2; i <= n; i++)
|
||||
for (int i = m+2; i <= n; ++i)
|
||||
{
|
||||
matH.coeffRef(i,i-2) = 0.0;
|
||||
if (i > m+2)
|
||||
@@ -378,13 +485,13 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Double QR step involving rows l:n and columns m:n
|
||||
for (int k = m; k <= n-1; k++)
|
||||
for (int k = m; k <= n-1; ++k)
|
||||
{
|
||||
int notlast = (k != n-1);
|
||||
if (k != m) {
|
||||
p = matH.coeff(k,k-1);
|
||||
q = matH.coeff(k+1,k-1);
|
||||
r = (notlast ? matH.coeff(k+2,k-1) : 0.0);
|
||||
r = notlast ? matH.coeff(k+2,k-1) : Scalar(0);
|
||||
x = ei_abs(p) + ei_abs(q) + ei_abs(r);
|
||||
if (x != 0.0)
|
||||
{
|
||||
@@ -417,7 +524,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
r = r / p;
|
||||
|
||||
// Row modification
|
||||
for (int j = k; j < nn; j++)
|
||||
for (int j = k; j < nn; ++j)
|
||||
{
|
||||
p = matH.coeff(k,j) + q * matH.coeff(k+1,j);
|
||||
if (notlast)
|
||||
@@ -430,7 +537,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Column modification
|
||||
for (int i = 0; i <= std::min(n,k+3); i++)
|
||||
for (int i = 0; i <= std::min(n,k+3); ++i)
|
||||
{
|
||||
p = x * matH.coeff(i,k) + y * matH.coeff(i,k+1);
|
||||
if (notlast)
|
||||
@@ -443,7 +550,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Accumulate transformations
|
||||
for (int i = low; i <= high; i++)
|
||||
for (int i = low; i <= high; ++i)
|
||||
{
|
||||
p = x * m_eivec.coeff(i,k) + y * m_eivec.coeff(i,k+1);
|
||||
if (notlast)
|
||||
@@ -478,7 +585,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
for (int i = n-1; i >= 0; i--)
|
||||
{
|
||||
w = matH.coeff(i,i) - p;
|
||||
r = (matH.row(i).end(nn-l) * matH.col(n).end(nn-l))(0,0);
|
||||
r = (matH.row(i).segment(l,n-l+1) * matH.col(n).segment(l, n-l+1))(0,0);
|
||||
|
||||
if (m_eivalues.coeff(i).imag() < 0.0)
|
||||
{
|
||||
@@ -537,8 +644,8 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
for (int i = n-2; i >= 0; i--)
|
||||
{
|
||||
Scalar ra,sa,vr,vi;
|
||||
ra = (matH.row(i).end(nn-l) * matH.col(n-1).end(nn-l)).lazy()(0,0);
|
||||
sa = (matH.row(i).end(nn-l) * matH.col(n).end(nn-l)).lazy()(0,0);
|
||||
ra = (matH.block(i,l, 1, n-l+1) * matH.block(l,n-1, n-l+1, 1)).lazy()(0,0);
|
||||
sa = (matH.block(i,l, 1, n-l+1) * matH.block(l,n, n-l+1, 1)).lazy()(0,0);
|
||||
w = matH.coeff(i,i) - p;
|
||||
|
||||
if (m_eivalues.coeff(i).imag() < 0.0)
|
||||
@@ -562,7 +669,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
x = matH.coeff(i,i+1);
|
||||
y = matH.coeff(i+1,i);
|
||||
vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
|
||||
vi = (m_eivalues.coeff(i).real() - p) * 2.0 * q;
|
||||
vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
|
||||
if ((vr == 0.0) && (vi == 0.0))
|
||||
vr = eps * norm * (ei_abs(w) + ei_abs(q) + ei_abs(x) + ei_abs(y) + ei_abs(z));
|
||||
|
||||
@@ -593,7 +700,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
}
|
||||
|
||||
// Vectors of isolated roots
|
||||
for (int i = 0; i < nn; i++)
|
||||
for (int i = 0; i < nn; ++i)
|
||||
{
|
||||
// FIXME again what's the purpose of this test ?
|
||||
// in this algo low==0 and high==nn-1 !!
|
||||
@@ -608,7 +715,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
|
||||
for (int j = nn-1; j >= low; j--)
|
||||
{
|
||||
int bSize = std::min(j,high)-low+1;
|
||||
m_eivec.col(j).block(low, bRows) = (m_eivec.block(low, low, bRows, bSize) * matH.col(j).block(low, bSize));
|
||||
m_eivec.col(j).segment(low, bRows) = (m_eivec.block(low, low, bRows, bSize) * matH.col(j).segment(low, bSize));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
5
Eigen/src/QR/HessenbergDecomposition.h
Executable file → Normal file
5
Eigen/src/QR/HessenbergDecomposition.h
Executable file → Normal file
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_HESSENBERGDECOMPOSITION_H
|
||||
|
||||
/** \ingroup QR_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class HessenbergDecomposition
|
||||
*
|
||||
@@ -148,7 +149,7 @@ void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVector
|
||||
|
||||
// start of the householder transformation
|
||||
// squared norm of the vector v skipping the first element
|
||||
RealScalar v1norm2 = matA.col(i).end(n-(i+2)).norm2();
|
||||
RealScalar v1norm2 = matA.col(i).end(n-(i+2)).squaredNorm();
|
||||
|
||||
if (ei_isMuchSmallerThan(v1norm2,static_cast<Scalar>(1)))
|
||||
{
|
||||
@@ -242,7 +243,7 @@ HessenbergDecomposition<MatrixType>::matrixH(void) const
|
||||
int n = m_matrix.rows();
|
||||
MatrixType matH = m_matrix;
|
||||
if (n>2)
|
||||
matH.corner(BottomLeft,n-2, n-2).template part<Lower>().setZero();
|
||||
matH.corner(BottomLeft,n-2, n-2).template part<LowerTriangular>().setZero();
|
||||
return matH;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_QR_H
|
||||
|
||||
/** \ingroup QR_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class QR
|
||||
*
|
||||
@@ -48,45 +49,165 @@ template<typename MatrixType> class QR
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixTypeR;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via QR::compute(const MatrixType&).
|
||||
*/
|
||||
QR() : m_qr(), m_hCoeffs(), m_isInitialized(false) {}
|
||||
|
||||
QR(const MatrixType& matrix)
|
||||
: m_qr(matrix.rows(), matrix.cols()),
|
||||
m_hCoeffs(matrix.cols())
|
||||
m_hCoeffs(matrix.cols()),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
_compute(matrix);
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
/** \deprecated use isInjective()
|
||||
* \returns whether or not the matrix is of full rank
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
EIGEN_DEPRECATED bool isFullRank() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
return rank() == m_qr.cols();
|
||||
}
|
||||
|
||||
/** \returns the rank of the matrix of which *this is the QR decomposition.
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
int rank() const;
|
||||
|
||||
/** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition.
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
inline int dimensionOfKernel() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
return m_qr.cols() - rank();
|
||||
}
|
||||
|
||||
/** \returns true if the matrix of which *this is the QR decomposition represents an injective
|
||||
* linear map, i.e. has trivial kernel; false otherwise.
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
inline bool isInjective() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
return rank() == m_qr.cols();
|
||||
}
|
||||
|
||||
/** \returns true if the matrix of which *this is the QR decomposition represents a surjective
|
||||
* linear map; false otherwise.
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
inline bool isSurjective() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
return rank() == m_qr.rows();
|
||||
}
|
||||
|
||||
/** \returns whether or not the matrix is of full rank */
|
||||
bool isFullRank() const { return ei_isMuchSmallerThan(m_hCoeffs.cwise().abs().minCoeff(), Scalar(1)); }
|
||||
|
||||
/** \returns true if the matrix of which *this is the QR decomposition is invertible.
|
||||
*
|
||||
* \note Since the rank is computed only once, i.e. the first time it is needed, this
|
||||
* method almost does not perform any further computation.
|
||||
*/
|
||||
inline bool isInvertible() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
return isInjective() && isSurjective();
|
||||
}
|
||||
|
||||
/** \returns a read-only expression of the matrix R of the actual the QR decomposition */
|
||||
const Part<NestByValue<MatrixRBlockType>, Upper>
|
||||
const Part<NestByValue<MatrixRBlockType>, UpperTriangular>
|
||||
matrixR(void) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
int cols = m_qr.cols();
|
||||
return MatrixRBlockType(m_qr, 0, 0, cols, cols).nestByValue().template part<Upper>();
|
||||
return MatrixRBlockType(m_qr, 0, 0, cols, cols).nestByValue().template part<UpperTriangular>();
|
||||
}
|
||||
|
||||
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the QR decomposition, if any exists.
|
||||
*
|
||||
* \param b the right-hand-side of the equation to solve.
|
||||
*
|
||||
* \param result a pointer to the vector/matrix in which to store the solution, if any exists.
|
||||
* Resized if necessary, so that result->rows()==A.cols() and result->cols()==b.cols().
|
||||
* If no solution exists, *result is left with undefined coefficients.
|
||||
*
|
||||
* \returns true if any solution exists, false if no solution exists.
|
||||
*
|
||||
* \note If there exist more than one solution, this method will arbitrarily choose one.
|
||||
* If you need a complete analysis of the space of solutions, take the one solution obtained
|
||||
* by this method and add to it elements of the kernel, as determined by kernel().
|
||||
*
|
||||
* \note The case where b is a matrix is not yet implemented. Also, this
|
||||
* code is space inefficient.
|
||||
*
|
||||
* Example: \include QR_solve.cpp
|
||||
* Output: \verbinclude QR_solve.out
|
||||
*
|
||||
* \sa MatrixBase::solveTriangular(), kernel(), computeKernel(), inverse(), computeInverse()
|
||||
*/
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
|
||||
|
||||
MatrixType matrixQ(void) const;
|
||||
|
||||
private:
|
||||
|
||||
void _compute(const MatrixType& matrix);
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
MatrixType m_qr;
|
||||
VectorType m_hCoeffs;
|
||||
mutable int m_rank;
|
||||
mutable bool m_rankIsUptodate;
|
||||
bool m_isInitialized;
|
||||
};
|
||||
|
||||
/** \returns the rank of the matrix of which *this is the QR decomposition. */
|
||||
template<typename MatrixType>
|
||||
int QR<MatrixType>::rank() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
if (!m_rankIsUptodate)
|
||||
{
|
||||
RealScalar maxCoeff = m_qr.diagonal().cwise().abs().maxCoeff();
|
||||
int n = m_qr.cols();
|
||||
m_rank = 0;
|
||||
while(m_rank<n && !ei_isMuchSmallerThan(m_qr.diagonal().coeff(m_rank), maxCoeff))
|
||||
++m_rank;
|
||||
m_rankIsUptodate = true;
|
||||
}
|
||||
return m_rank;
|
||||
}
|
||||
|
||||
#ifndef EIGEN_HIDE_HEAVY_CODE
|
||||
|
||||
template<typename MatrixType>
|
||||
void QR<MatrixType>::_compute(const MatrixType& matrix)
|
||||
{
|
||||
void QR<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
m_rankIsUptodate = false;
|
||||
m_qr = matrix;
|
||||
m_hCoeffs.resize(matrix.cols());
|
||||
|
||||
int rows = matrix.rows();
|
||||
int cols = matrix.cols();
|
||||
RealScalar eps2 = precision<RealScalar>()*precision<RealScalar>();
|
||||
|
||||
for (int k = 0; k < cols; k++)
|
||||
for (int k = 0; k < cols; ++k)
|
||||
{
|
||||
int remainingSize = rows-k;
|
||||
|
||||
@@ -109,7 +230,8 @@ void QR<MatrixType>::_compute(const MatrixType& matrix)
|
||||
m_hCoeffs.coeffRef(k) = 0;
|
||||
}
|
||||
}
|
||||
else if ( (!ei_isMuchSmallerThan(beta=m_qr.col(k).end(remainingSize-1).norm2(),static_cast<Scalar>(1))) || ei_imag(v0)==0 )
|
||||
else if ((beta=m_qr.col(k).end(remainingSize-1).squaredNorm())>eps2)
|
||||
// FIXME what about ei_imag(v0) ??
|
||||
{
|
||||
// form k-th Householder vector
|
||||
beta = ei_sqrt(ei_abs2(v0)+beta);
|
||||
@@ -135,12 +257,46 @@ void QR<MatrixType>::_compute(const MatrixType& matrix)
|
||||
m_hCoeffs.coeffRef(k) = 0;
|
||||
}
|
||||
}
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool QR<MatrixType>::solve(
|
||||
const MatrixBase<OtherDerived>& b,
|
||||
ResultType *result
|
||||
) const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
const int rows = m_qr.rows();
|
||||
ei_assert(b.rows() == rows);
|
||||
result->resize(rows, b.cols());
|
||||
|
||||
// TODO(keir): There is almost certainly a faster way to multiply by
|
||||
// Q^T without explicitly forming matrixQ(). Investigate.
|
||||
*result = matrixQ().transpose()*b;
|
||||
|
||||
if(!isSurjective())
|
||||
{
|
||||
// is result is in the image of R ?
|
||||
RealScalar biggest_in_res = result->corner(TopLeft, m_rank, result->cols()).cwise().abs().maxCoeff();
|
||||
for(int col = 0; col < result->cols(); ++col)
|
||||
for(int row = m_rank; row < result->rows(); ++row)
|
||||
if(!ei_isMuchSmallerThan(result->coeff(row,col), biggest_in_res))
|
||||
return false;
|
||||
}
|
||||
m_qr.corner(TopLeft, m_rank, m_rank)
|
||||
.template marked<UpperTriangular>()
|
||||
.solveTriangularInPlace(result->corner(TopLeft, m_rank, result->cols()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \returns the matrix Q */
|
||||
template<typename MatrixType>
|
||||
MatrixType QR<MatrixType>::matrixQ(void) const
|
||||
MatrixType QR<MatrixType>::matrixQ() const
|
||||
{
|
||||
ei_assert(m_isInitialized && "QR is not initialized.");
|
||||
// compute the product Q_0 Q_1 ... Q_n-1,
|
||||
// where Q_k is the k-th Householder transformation I - h_k v_k v_k'
|
||||
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
|
||||
@@ -168,10 +324,10 @@ MatrixType QR<MatrixType>::matrixQ(void) const
|
||||
* \sa class QR
|
||||
*/
|
||||
template<typename Derived>
|
||||
const QR<typename MatrixBase<Derived>::EvalType>
|
||||
const QR<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::qr() const
|
||||
{
|
||||
return eval();
|
||||
return QR<PlainMatrixType>(eval());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#define EIGEN_EXTERN_INSTANTIATIONS
|
||||
#endif
|
||||
#include "../../Core"
|
||||
// commented because of -pedantic
|
||||
// #include "../../Cholesky"
|
||||
#undef EIGEN_EXTERN_INSTANTIATIONS
|
||||
|
||||
#include "../../QR"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_SELFADJOINTEIGENSOLVER_H
|
||||
|
||||
/** \qr_module \ingroup QR_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class SelfAdjointEigenSolver
|
||||
*
|
||||
@@ -51,8 +52,8 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
typedef Tridiagonalization<MatrixType> TridiagonalizationType;
|
||||
|
||||
SelfAdjointEigenSolver()
|
||||
: m_eivec(Size, Size),
|
||||
m_eivalues(Size)
|
||||
: m_eivec(int(Size), int(Size)),
|
||||
m_eivalues(int(Size))
|
||||
{
|
||||
ei_assert(Size!=Dynamic);
|
||||
}
|
||||
@@ -104,6 +105,25 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
/** \returns the computed eigen values */
|
||||
RealVectorType eigenvalues(void) const { return m_eivalues; }
|
||||
|
||||
/** \returns the positive square root of the matrix
|
||||
*
|
||||
* \note the matrix itself must be positive in order for this to make sense.
|
||||
*/
|
||||
MatrixType operatorSqrt() const
|
||||
{
|
||||
return m_eivec * m_eivalues.cwise().sqrt().asDiagonal() * m_eivec.adjoint();
|
||||
}
|
||||
|
||||
/** \returns the positive inverse square root of the matrix
|
||||
*
|
||||
* \note the matrix itself must be positive definite in order for this to make sense.
|
||||
*/
|
||||
MatrixType operatorInverseSqrt() const
|
||||
{
|
||||
return m_eivec * m_eivalues.cwise().inverse().cwise().sqrt().asDiagonal() * m_eivec.adjoint();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
MatrixType m_eivec;
|
||||
RealVectorType m_eivalues;
|
||||
@@ -169,6 +189,14 @@ void SelfAdjointEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool
|
||||
assert(matrix.cols() == matrix.rows());
|
||||
int n = matrix.cols();
|
||||
m_eivalues.resize(n,1);
|
||||
|
||||
if(n==1)
|
||||
{
|
||||
m_eivalues.coeffRef(0,0) = ei_real(matrix.coeff(0,0));
|
||||
m_eivec.setOnes();
|
||||
return;
|
||||
}
|
||||
|
||||
m_eivec = matrix;
|
||||
|
||||
// FIXME, should tridiag be a local variable of this function or an attribute of SelfAdjointEigenSolver ?
|
||||
@@ -201,10 +229,10 @@ void SelfAdjointEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool
|
||||
// Sort eigenvalues and corresponding vectors.
|
||||
// TODO make the sort optional ?
|
||||
// TODO use a better sort algorithm !!
|
||||
for (int i = 0; i < n-1; i++)
|
||||
for (int i = 0; i < n-1; ++i)
|
||||
{
|
||||
int k;
|
||||
m_eivalues.block(i,n-i).minCoeff(&k);
|
||||
m_eivalues.segment(i,n-i).minCoeff(&k);
|
||||
if (k > 0)
|
||||
{
|
||||
std::swap(m_eivalues[i], m_eivalues[k+i]);
|
||||
@@ -225,31 +253,31 @@ void SelfAdjointEigenSolver<MatrixType>::
|
||||
compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors)
|
||||
{
|
||||
ei_assert(matA.cols()==matA.rows() && matB.rows()==matA.rows() && matB.cols()==matB.rows());
|
||||
|
||||
|
||||
// Compute the cholesky decomposition of matB = L L'
|
||||
Cholesky<MatrixType> cholB(matB);
|
||||
LLT<MatrixType> cholB(matB);
|
||||
|
||||
// compute C = inv(L) A inv(L')
|
||||
MatrixType matC = matA;
|
||||
cholB.matrixL().solveTriangularInPlace(matC);
|
||||
// FIXME since we currently do not support A * inv(L'), let's do (inv(L) A')' :
|
||||
matC = matC.adjoint().eval();
|
||||
cholB.matrixL().template marked<Lower>().solveTriangularInPlace(matC);
|
||||
cholB.matrixL().template marked<LowerTriangular>().solveTriangularInPlace(matC);
|
||||
matC = matC.adjoint().eval();
|
||||
// this version works too:
|
||||
// matC = matC.transpose();
|
||||
// cholB.matrixL().conjugate().template marked<Lower>().solveTriangularInPlace(matC);
|
||||
// cholB.matrixL().conjugate().template marked<LowerTriangular>().solveTriangularInPlace(matC);
|
||||
// matC = matC.transpose();
|
||||
// FIXME: this should work: (currently it only does for small matrices)
|
||||
// Transpose<MatrixType> trMatC(matC);
|
||||
// cholB.matrixL().conjugate().eval().template marked<Lower>().solveTriangularInPlace(trMatC);
|
||||
// cholB.matrixL().conjugate().eval().template marked<LowerTriangular>().solveTriangularInPlace(trMatC);
|
||||
|
||||
compute(matC, computeEigenvectors);
|
||||
|
||||
if (computeEigenvectors)
|
||||
{
|
||||
// transform back the eigen vectors: evecs = inv(U) * evecs
|
||||
cholB.matrixL().adjoint().template marked<Upper>().solveTriangularInPlace(m_eivec);
|
||||
cholB.matrixL().adjoint().template marked<UpperTriangular>().solveTriangularInPlace(m_eivec);
|
||||
for (int i=0; i<m_eivec.cols(); ++i)
|
||||
m_eivec.col(i) = m_eivec.col(i).normalized();
|
||||
}
|
||||
@@ -266,7 +294,7 @@ inline Matrix<typename NumTraits<typename ei_traits<Derived>::Scalar>::Real, ei_
|
||||
MatrixBase<Derived>::eigenvalues() const
|
||||
{
|
||||
ei_assert(Flags&SelfAdjointBit);
|
||||
return SelfAdjointEigenSolver<typename Derived::Eval>(eval(),false).eigenvalues();
|
||||
return SelfAdjointEigenSolver<typename Derived::PlainMatrixType>(eval(),false).eigenvalues();
|
||||
}
|
||||
|
||||
template<typename Derived, bool IsSelfAdjoint>
|
||||
@@ -286,7 +314,7 @@ template<typename Derived> struct ei_operatorNorm_selector<Derived, false>
|
||||
static inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
|
||||
operatorNorm(const MatrixBase<Derived>& m)
|
||||
{
|
||||
typename Derived::Eval m_eval(m);
|
||||
typename Derived::PlainMatrixType m_eval(m);
|
||||
// FIXME if it is really guaranteed that the eigenvalues are already sorted,
|
||||
// then we don't need to compute a maxCoeff() here, comparing the 1st and last ones is enough.
|
||||
return ei_sqrt(
|
||||
@@ -314,7 +342,7 @@ MatrixBase<Derived>::operatorNorm() const
|
||||
template<typename RealScalar, typename Scalar>
|
||||
static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int start, int end, Scalar* matrixQ, int n)
|
||||
{
|
||||
RealScalar td = (diag[end-1] - diag[end])*0.5;
|
||||
RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
|
||||
RealScalar e2 = ei_abs2(subdiag[end-1]);
|
||||
RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * ei_sqrt(td*td + e2));
|
||||
RealScalar x = diag[start] - mu;
|
||||
@@ -337,10 +365,12 @@ static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int st
|
||||
subdiag[k - 1] = c * subdiag[k-1] - s * z;
|
||||
|
||||
x = subdiag[k];
|
||||
z = -s * subdiag[k+1];
|
||||
|
||||
if (k < end - 1)
|
||||
{
|
||||
z = -s * subdiag[k+1];
|
||||
subdiag[k + 1] = c * subdiag[k+1];
|
||||
}
|
||||
|
||||
// apply the givens rotation to the unit matrix Q = Q * G
|
||||
// G only modifies the two columns k and k+1
|
||||
|
||||
31
Eigen/src/QR/Tridiagonalization.h
Executable file → Normal file
31
Eigen/src/QR/Tridiagonalization.h
Executable file → Normal file
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_TRIDIAGONALIZATION_H
|
||||
|
||||
/** \ingroup QR_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class Tridiagonalization
|
||||
*
|
||||
@@ -163,11 +164,11 @@ Tridiagonalization<MatrixType>::matrixT(void) const
|
||||
// and fill it ? (to avoid temporaries)
|
||||
int n = m_matrix.rows();
|
||||
MatrixType matT = m_matrix;
|
||||
matT.corner(TopRight,n-1, n-1).diagonal() = subDiagonal().conjugate();
|
||||
matT.corner(TopRight,n-1, n-1).diagonal() = subDiagonal().template cast<Scalar>().conjugate();
|
||||
if (n>2)
|
||||
{
|
||||
matT.corner(TopRight,n-2, n-2).template part<Upper>().setZero();
|
||||
matT.corner(BottomLeft,n-2, n-2).template part<Lower>().setZero();
|
||||
matT.corner(TopRight,n-2, n-2).template part<UpperTriangular>().setZero();
|
||||
matT.corner(BottomLeft,n-2, n-2).template part<LowerTriangular>().setZero();
|
||||
}
|
||||
return matT;
|
||||
}
|
||||
@@ -198,8 +199,9 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
|
||||
// start of the householder transformation
|
||||
// squared norm of the vector v skipping the first element
|
||||
RealScalar v1norm2 = matA.col(i).end(n-(i+2)).norm2();
|
||||
RealScalar v1norm2 = matA.col(i).end(n-(i+2)).squaredNorm();
|
||||
|
||||
// FIXME comparing against 1
|
||||
if (ei_isMuchSmallerThan(v1norm2,static_cast<Scalar>(1)))
|
||||
{
|
||||
hCoeffs.coeffRef(i) = 0.;
|
||||
@@ -219,20 +221,20 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
// i.e., A = H' A H where H = I - h v v' and v = matA.col(i).end(n-i-1)
|
||||
|
||||
matA.col(i).coeffRef(i+1) = 1;
|
||||
|
||||
|
||||
/* This is the initial algorithm which minimize operation counts and maximize
|
||||
* the use of Eigen's expression. Unfortunately, the first matrix-vector product
|
||||
* using Part<Lower|Selfadjoint> is very very slow */
|
||||
* using Part<LowerTriangular|Selfadjoint> is very very slow */
|
||||
#ifdef EIGEN_NEVER_DEFINED
|
||||
// matrix - vector product
|
||||
hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1).template part<Lower|SelfAdjoint>()
|
||||
hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1).template part<LowerTriangular|SelfAdjoint>()
|
||||
* (h * matA.col(i).end(n-i-1))).lazy();
|
||||
// simple axpy
|
||||
hCoeffs.end(n-i-1) += (h * Scalar(-0.5) * matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))
|
||||
* matA.col(i).end(n-i-1);
|
||||
// rank-2 update
|
||||
//Block<MatrixType,Dynamic,1> B(matA,i+1,i,n-i-1,1);
|
||||
matA.corner(BottomRight,n-i-1,n-i-1).template part<Lower>() -=
|
||||
matA.corner(BottomRight,n-i-1,n-i-1).template part<LowerTriangular>() -=
|
||||
(matA.col(i).end(n-i-1) * hCoeffs.end(n-i-1).adjoint()).lazy()
|
||||
+ (hCoeffs.end(n-i-1) * matA.col(i).end(n-i-1).adjoint()).lazy();
|
||||
#endif
|
||||
@@ -255,7 +257,7 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
Block<MatrixType,Dynamic,4>(matA,b+4,b,n-b-4,4).adjoint() * Block<MatrixType,Dynamic,1>(matA,b+4,i,n-b-4,1);
|
||||
// the 4x4 block diagonal:
|
||||
Block<CoeffVectorType,4,1>(hCoeffs, b, 0, 4,1) +=
|
||||
(Block<MatrixType,4,4>(matA,b,b,4,4).template part<Lower|SelfAdjoint>()
|
||||
(Block<MatrixType,4,4>(matA,b,b,4,4).template part<LowerTriangular|SelfAdjoint>()
|
||||
* (h * Block<MatrixType,4,1>(matA,b,i,4,1))).lazy();
|
||||
}
|
||||
#endif
|
||||
@@ -267,7 +269,7 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
* if we remove the specialization of Block for Matrix then it is even worse, much worse ! */
|
||||
#ifdef EIGEN_NEVER_DEFINED
|
||||
for (int j1=i+1; j1<n; ++j1)
|
||||
for (int i1=j1; i1<n; i1++)
|
||||
for (int i1=j1; i1<n; ++i1)
|
||||
matA.coeffRef(i1,j1) -= matA.coeff(i1,i)*ei_conj(hCoeffs.coeff(j1-1))
|
||||
+ hCoeffs.coeff(i1-1)*ei_conj(matA.coeff(j1,i));
|
||||
#endif
|
||||
@@ -284,7 +286,7 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
|
||||
hCoeffs.end(n-i-1) += (h * Scalar(-0.5) * matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))
|
||||
* matA.col(i).end(n-i-1);
|
||||
|
||||
|
||||
const Scalar* EIGEN_RESTRICT pb = &matA.coeffRef(0,i);
|
||||
const Scalar* EIGEN_RESTRICT pa = (&hCoeffs.coeffRef(0)) - 1;
|
||||
for (int j1=i+1; j1<n; ++j1)
|
||||
@@ -295,11 +297,11 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
{
|
||||
int alignedStart = (starti) + ei_alignmentOffset(&matA.coeffRef(starti,j1), n-starti);
|
||||
alignedEnd = alignedStart + ((n-alignedStart)/PacketSize)*PacketSize;
|
||||
|
||||
|
||||
for (int i1=starti; i1<alignedStart; ++i1)
|
||||
matA.coeffRef(i1,j1) -= matA.coeff(i1,i)*ei_conj(hCoeffs.coeff(j1-1))
|
||||
+ hCoeffs.coeff(i1-1)*ei_conj(matA.coeff(j1,i));
|
||||
|
||||
|
||||
Packet tmp0 = ei_pset1(hCoeffs.coeff(j1-1));
|
||||
Packet tmp1 = ei_pset1(matA.coeff(j1,i));
|
||||
Scalar* pc = &matA.coeffRef(0,j1);
|
||||
@@ -330,7 +332,8 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
|
||||
if (ei_real(v0)>=0.)
|
||||
beta = -beta;
|
||||
matA.col(i).coeffRef(i+1) = beta;
|
||||
hCoeffs.coeffRef(i) = (beta - v0) / beta;
|
||||
if(ei_isMuchSmallerThan(beta, Scalar(1))) hCoeffs.coeffRef(i) = Scalar(0);
|
||||
else hCoeffs.coeffRef(i) = (beta - v0) / beta;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Regression_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Regression_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Regression
|
||||
)
|
||||
@@ -26,6 +26,7 @@
|
||||
#define EIGEN_SVD_H
|
||||
|
||||
/** \ingroup SVD_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class SVD
|
||||
*
|
||||
@@ -50,16 +51,16 @@ template<typename MatrixType> class SVD
|
||||
AlignmentMask = int(PacketSize)-1,
|
||||
MinSize = EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
|
||||
};
|
||||
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVector;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> RowVector;
|
||||
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MinSize> MatrixUType;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixVType;
|
||||
typedef Matrix<Scalar, MinSize, 1> SingularValuesType;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
SVD(const MatrixType& matrix)
|
||||
: m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())),
|
||||
m_matV(matrix.cols(),matrix.cols()),
|
||||
@@ -69,7 +70,7 @@ template<typename MatrixType> class SVD
|
||||
}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
void solve(const MatrixBase<OtherDerived> &b, ResultType* result) const;
|
||||
bool solve(const MatrixBase<OtherDerived> &b, ResultType* result) const;
|
||||
|
||||
const MatrixUType& matrixU() const { return m_matU; }
|
||||
const SingularValuesType& singularValues() const { return m_sigma; }
|
||||
@@ -78,6 +79,15 @@ template<typename MatrixType> class SVD
|
||||
void compute(const MatrixType& matrix);
|
||||
SVD& sort();
|
||||
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void computeUnitaryPositive(UnitaryType *unitary, PositiveType *positive) const;
|
||||
template<typename PositiveType, typename UnitaryType>
|
||||
void computePositiveUnitary(PositiveType *positive, UnitaryType *unitary) const;
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void computeRotationScaling(RotationType *unitary, ScalingType *positive) const;
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void computeScalingRotation(ScalingType *positive, RotationType *unitary) const;
|
||||
|
||||
protected:
|
||||
/** \internal */
|
||||
MatrixUType m_matU;
|
||||
@@ -97,7 +107,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
const int m = matrix.rows();
|
||||
const int n = matrix.cols();
|
||||
const int nu = std::min(m,n);
|
||||
|
||||
|
||||
m_matU.resize(m, nu);
|
||||
m_matU.setZero();
|
||||
m_sigma.resize(std::min(m,n));
|
||||
@@ -114,7 +124,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
// in s and the super-diagonal elements in e.
|
||||
int nct = std::min(m-1,n);
|
||||
int nrt = std::max(0,std::min(n-2,m));
|
||||
for (k = 0; k < std::max(nct,nrt); k++)
|
||||
for (k = 0; k < std::max(nct,nrt); ++k)
|
||||
{
|
||||
if (k < nct)
|
||||
{
|
||||
@@ -130,8 +140,8 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
}
|
||||
m_sigma[k] = -m_sigma[k];
|
||||
}
|
||||
|
||||
for (j = k+1; j < n; j++)
|
||||
|
||||
for (j = k+1; j < n; ++j)
|
||||
{
|
||||
if ((k < nct) && (m_sigma[k] != 0.0))
|
||||
{
|
||||
@@ -167,7 +177,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
// Apply the transformation.
|
||||
work.end(m-k-1) = matA.corner(BottomRight,m-k-1,n-k-1) * e.end(n-k-1);
|
||||
for (j = k+1; j < n; j++)
|
||||
for (j = k+1; j < n; ++j)
|
||||
matA.col(j).end(m-k-1) += (-e[j]/e[k+1]) * work.end(m-k-1);
|
||||
}
|
||||
|
||||
@@ -191,7 +201,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
// If required, generate U.
|
||||
if (wantu)
|
||||
{
|
||||
for (j = nct; j < nu; j++)
|
||||
for (j = nct; j < nu; ++j)
|
||||
{
|
||||
m_matU.col(j).setZero();
|
||||
m_matU(j,j) = 1.0;
|
||||
@@ -200,14 +210,14 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
if (m_sigma[k] != 0.0)
|
||||
{
|
||||
for (j = k+1; j < nu; j++)
|
||||
for (j = k+1; j < nu; ++j)
|
||||
{
|
||||
Scalar t = m_matU.col(k).end(m-k).dot(m_matU.col(j).end(m-k)); // FIXME is it really a dot product we want ?
|
||||
t = -t/m_matU(k,k);
|
||||
m_matU.col(j).end(m-k) += t * m_matU.col(k).end(m-k);
|
||||
}
|
||||
m_matU.col(k).end(m-k) = - m_matU.col(k).end(m-k);
|
||||
m_matU(k,k) = 1.0 + m_matU(k,k);
|
||||
m_matU(k,k) = Scalar(1) + m_matU(k,k);
|
||||
if (k-1>0)
|
||||
m_matU.col(k).start(k-1).setZero();
|
||||
}
|
||||
@@ -226,7 +236,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
if ((k < nrt) & (e[k] != 0.0))
|
||||
{
|
||||
for (j = k+1; j < nu; j++)
|
||||
for (j = k+1; j < nu; ++j)
|
||||
{
|
||||
Scalar t = m_matV.col(k).end(n-k-1).dot(m_matV.col(j).end(n-k-1)); // FIXME is it really a dot product we want ?
|
||||
t = -t/m_matV(k+1,k);
|
||||
@@ -241,7 +251,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
// Main iteration loop for the singular values.
|
||||
int pp = p-1;
|
||||
int iter = 0;
|
||||
Scalar eps(pow(2.0,-52.0));
|
||||
Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
|
||||
while (p > 0)
|
||||
{
|
||||
int k=0;
|
||||
@@ -259,7 +269,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
// s(k), ..., s(p) are not negligible (qr step).
|
||||
// kase = 4 if e(p-1) is negligible (convergence).
|
||||
|
||||
for (k = p-2; k >= -1; k--)
|
||||
for (k = p-2; k >= -1; --k)
|
||||
{
|
||||
if (k == -1)
|
||||
break;
|
||||
@@ -276,11 +286,11 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
else
|
||||
{
|
||||
int ks;
|
||||
for (ks = p-1; ks >= k; ks--)
|
||||
for (ks = p-1; ks >= k; --ks)
|
||||
{
|
||||
if (ks == k)
|
||||
break;
|
||||
Scalar t( (ks != p ? ei_abs(e[ks]) : 0.) + (ks != k+1 ? ei_abs(e[ks-1]) : 0.));
|
||||
Scalar t = (ks != p ? ei_abs(e[ks]) : Scalar(0)) + (ks != k+1 ? ei_abs(e[ks-1]) : Scalar(0));
|
||||
if (ei_abs(m_sigma[ks]) <= eps*t)
|
||||
{
|
||||
m_sigma[ks] = 0.0;
|
||||
@@ -301,7 +311,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
k = ks;
|
||||
}
|
||||
}
|
||||
k++;
|
||||
++k;
|
||||
|
||||
// Perform the task indicated by kase.
|
||||
switch (kase)
|
||||
@@ -312,9 +322,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
Scalar f(e[p-2]);
|
||||
e[p-2] = 0.0;
|
||||
for (j = p-2; j >= k; j--)
|
||||
for (j = p-2; j >= k; --j)
|
||||
{
|
||||
Scalar t(hypot(m_sigma[j],f));
|
||||
Scalar t(ei_hypot(m_sigma[j],f));
|
||||
Scalar cs(m_sigma[j]/t);
|
||||
Scalar sn(f/t);
|
||||
m_sigma[j] = t;
|
||||
@@ -325,7 +335,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
}
|
||||
if (wantv)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
t = cs*m_matV(i,j) + sn*m_matV(i,p-1);
|
||||
m_matV(i,p-1) = -sn*m_matV(i,j) + cs*m_matV(i,p-1);
|
||||
@@ -341,9 +351,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
Scalar f(e[k-1]);
|
||||
e[k-1] = 0.0;
|
||||
for (j = k; j < p; j++)
|
||||
for (j = k; j < p; ++j)
|
||||
{
|
||||
Scalar t(hypot(m_sigma[j],f));
|
||||
Scalar t(ei_hypot(m_sigma[j],f));
|
||||
Scalar cs( m_sigma[j]/t);
|
||||
Scalar sn(f/t);
|
||||
m_sigma[j] = t;
|
||||
@@ -351,7 +361,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
e[j] = cs*e[j];
|
||||
if (wantu)
|
||||
{
|
||||
for (i = 0; i < m; i++)
|
||||
for (i = 0; i < m; ++i)
|
||||
{
|
||||
t = cs*m_matU(i,j) + sn*m_matU(i,k-1);
|
||||
m_matU(i,k-1) = -sn*m_matU(i,j) + cs*m_matU(i,k-1);
|
||||
@@ -374,7 +384,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
Scalar epm1 = e[p-2]/scale;
|
||||
Scalar sk = m_sigma[k]/scale;
|
||||
Scalar ek = e[k]/scale;
|
||||
Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
|
||||
Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/Scalar(2);
|
||||
Scalar c = (sp*epm1)*(sp*epm1);
|
||||
Scalar shift = 0.0;
|
||||
if ((b != 0.0) || (c != 0.0))
|
||||
@@ -389,9 +399,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
|
||||
// Chase zeros.
|
||||
|
||||
for (j = k; j < p-1; j++)
|
||||
for (j = k; j < p-1; ++j)
|
||||
{
|
||||
Scalar t = hypot(f,g);
|
||||
Scalar t = ei_hypot(f,g);
|
||||
Scalar cs = f/t;
|
||||
Scalar sn = g/t;
|
||||
if (j != k)
|
||||
@@ -402,14 +412,14 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
m_sigma[j+1] = cs*m_sigma[j+1];
|
||||
if (wantv)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
t = cs*m_matV(i,j) + sn*m_matV(i,j+1);
|
||||
m_matV(i,j+1) = -sn*m_matV(i,j) + cs*m_matV(i,j+1);
|
||||
m_matV(i,j) = t;
|
||||
}
|
||||
}
|
||||
t = hypot(f,g);
|
||||
t = ei_hypot(f,g);
|
||||
cs = f/t;
|
||||
sn = g/t;
|
||||
m_sigma[j] = t;
|
||||
@@ -419,7 +429,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
e[j+1] = cs*e[j+1];
|
||||
if (wantu && (j < m-1))
|
||||
{
|
||||
for (i = 0; i < m; i++)
|
||||
for (i = 0; i < m; ++i)
|
||||
{
|
||||
t = cs*m_matU(i,j) + sn*m_matU(i,j+1);
|
||||
m_matU(i,j+1) = -sn*m_matU(i,j) + cs*m_matU(i,j+1);
|
||||
@@ -438,7 +448,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
// Make the singular values positive.
|
||||
if (m_sigma[k] <= 0.0)
|
||||
{
|
||||
m_sigma[k] = (m_sigma[k] < 0.0 ? -m_sigma[k] : 0.0);
|
||||
m_sigma[k] = m_sigma[k] < Scalar(0) ? -m_sigma[k] : Scalar(0);
|
||||
if (wantv)
|
||||
m_matV.col(k).start(pp+1) = -m_matV.col(k).start(pp+1);
|
||||
}
|
||||
@@ -455,7 +465,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
m_matV.col(k).swap(m_matV.col(k+1));
|
||||
if (wantu && (k < m-1))
|
||||
m_matU.col(k).swap(m_matU.col(k+1));
|
||||
k++;
|
||||
++k;
|
||||
}
|
||||
iter = 0;
|
||||
p--;
|
||||
@@ -468,18 +478,18 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
template<typename MatrixType>
|
||||
SVD<MatrixType>& SVD<MatrixType>::sort()
|
||||
{
|
||||
int mu = m_matU.rows();
|
||||
int mv = m_matV.rows();
|
||||
int mu = m_matU.rows();
|
||||
int mv = m_matV.rows();
|
||||
int n = m_matU.cols();
|
||||
|
||||
for (int i=0; i<n; i++)
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
int k = i;
|
||||
int k = i;
|
||||
Scalar p = m_sigma.coeff(i);
|
||||
|
||||
for (int j=i+1; j<n; j++)
|
||||
for (int j=i+1; j<n; ++j)
|
||||
{
|
||||
if (m_sigma.coeff(j) > p)
|
||||
if (m_sigma.coeff(j) > p)
|
||||
{
|
||||
k = j;
|
||||
p = m_sigma.coeff(j);
|
||||
@@ -505,11 +515,11 @@ SVD<MatrixType>& SVD<MatrixType>::sort()
|
||||
/** \returns the solution of \f$ A x = b \f$ using the current SVD decomposition of A.
|
||||
* The parts of the solution corresponding to zero singular values are ignored.
|
||||
*
|
||||
* \sa MatrixBase::svd(), LU::solve(), Cholesky::solve()
|
||||
* \sa MatrixBase::svd(), LU::solve(), LLT::solve()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
void SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
|
||||
bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
|
||||
{
|
||||
const int rows = m_matU.rows();
|
||||
ei_assert(b.rows() == rows);
|
||||
@@ -519,7 +529,7 @@ void SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* resul
|
||||
{
|
||||
Matrix<Scalar,MatrixUType::RowsAtCompileTime,1> aux = m_matU.transpose() * b.col(j);
|
||||
|
||||
for (int i = 0; i <m_matU.cols(); i++)
|
||||
for (int i = 0; i <m_matU.cols(); ++i)
|
||||
{
|
||||
Scalar si = m_sigma.coeff(i);
|
||||
if (ei_isMuchSmallerThan(ei_abs(si),maxVal))
|
||||
@@ -530,16 +540,106 @@ void SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* resul
|
||||
|
||||
result->col(j) = m_matV * aux;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product unitary x positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computePositiveUnitary(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computeUnitaryPositive(UnitaryType *unitary,
|
||||
PositiveType *positive) const
|
||||
{
|
||||
ei_assert(m_matU.cols() == m_matV.cols() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matV * m_sigma.asDiagonal() * m_matV.adjoint();
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product positive x unitary.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computeUnitaryPositive(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computePositiveUnitary(UnitaryType *positive,
|
||||
PositiveType *unitary) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matU * m_sigma.asDiagonal() * m_matU.adjoint();
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeScalingRotation(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void SVD<MatrixType>::computeRotationScaling(RotationType *rotation, ScalingType *scaling) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matV * sv.asDiagonal() * m_matV.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product scaling x rotation, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeRotationScaling(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void SVD<MatrixType>::computeScalingRotation(ScalingType *scaling, RotationType *rotation) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matU * sv.asDiagonal() * m_matU.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \svd_module
|
||||
* \returns the SVD decomposition of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline SVD<typename MatrixBase<Derived>::EvalType>
|
||||
inline SVD<typename MatrixBase<Derived>::PlainMatrixType>
|
||||
MatrixBase<Derived>::svd() const
|
||||
{
|
||||
return SVD<typename ei_eval<Derived>::type>(derived());
|
||||
return SVD<PlainMatrixType>(derived());
|
||||
}
|
||||
|
||||
#endif // EIGEN_SVD_H
|
||||
|
||||
371
Eigen/src/Sparse/AmbiVector.h
Normal file
371
Eigen/src/Sparse/AmbiVector.h
Normal file
@@ -0,0 +1,371 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_AMBIVECTOR_H
|
||||
#define EIGEN_AMBIVECTOR_H
|
||||
|
||||
/** \internal
|
||||
* Hybrid sparse/dense vector class designed for intensive read-write operations.
|
||||
*
|
||||
* See BasicSparseLLT and SparseProduct for usage examples.
|
||||
*/
|
||||
template<typename _Scalar> class AmbiVector
|
||||
{
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
AmbiVector(int size)
|
||||
: m_buffer(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
void init(RealScalar estimatedDensity);
|
||||
void init(int mode);
|
||||
|
||||
void nonZeros() const;
|
||||
|
||||
/** Specifies a sub-vector to work on */
|
||||
void setBounds(int start, int end) { m_start = start; m_end = end; }
|
||||
|
||||
void setZero();
|
||||
|
||||
void restart();
|
||||
Scalar& coeffRef(int i);
|
||||
Scalar coeff(int i);
|
||||
|
||||
class Iterator;
|
||||
|
||||
~AmbiVector() { delete[] m_buffer; }
|
||||
|
||||
void resize(int size)
|
||||
{
|
||||
if (m_allocatedSize < size)
|
||||
reallocate(size);
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
int size() const { return m_size; }
|
||||
|
||||
protected:
|
||||
|
||||
void reallocate(int size)
|
||||
{
|
||||
// if the size of the matrix is not too large, let's allocate a bit more than needed such
|
||||
// that we can handle dense vector even in sparse mode.
|
||||
delete[] m_buffer;
|
||||
if (size<1000)
|
||||
{
|
||||
int allocSize = (size * sizeof(ListEl))/sizeof(Scalar);
|
||||
m_allocatedElements = (allocSize*sizeof(Scalar))/sizeof(ListEl);
|
||||
m_buffer = new Scalar[allocSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_allocatedElements = (size*sizeof(Scalar))/sizeof(ListEl);
|
||||
m_buffer = new Scalar[size];
|
||||
}
|
||||
m_size = size;
|
||||
m_start = 0;
|
||||
m_end = m_size;
|
||||
}
|
||||
|
||||
void reallocateSparse()
|
||||
{
|
||||
int copyElements = m_allocatedElements;
|
||||
m_allocatedElements = std::min(int(m_allocatedElements*1.5),m_size);
|
||||
int allocSize = m_allocatedElements * sizeof(ListEl);
|
||||
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
|
||||
Scalar* newBuffer = new Scalar[allocSize];
|
||||
memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
|
||||
}
|
||||
|
||||
protected:
|
||||
// element type of the linked list
|
||||
struct ListEl
|
||||
{
|
||||
int next;
|
||||
int index;
|
||||
Scalar value;
|
||||
};
|
||||
|
||||
// used to store data in both mode
|
||||
Scalar* m_buffer;
|
||||
int m_size;
|
||||
int m_start;
|
||||
int m_end;
|
||||
int m_allocatedSize;
|
||||
int m_allocatedElements;
|
||||
int m_mode;
|
||||
|
||||
// linked list mode
|
||||
int m_llStart;
|
||||
int m_llCurrent;
|
||||
int m_llSize;
|
||||
|
||||
private:
|
||||
AmbiVector(const AmbiVector&);
|
||||
|
||||
};
|
||||
|
||||
/** \returns the number of non zeros in the current sub vector */
|
||||
template<typename Scalar>
|
||||
void AmbiVector<Scalar>::nonZeros() const
|
||||
{
|
||||
if (m_mode==IsSparse)
|
||||
return m_llSize;
|
||||
else
|
||||
return m_end - m_start;
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void AmbiVector<Scalar>::init(RealScalar estimatedDensity)
|
||||
{
|
||||
if (estimatedDensity>0.1)
|
||||
init(IsDense);
|
||||
else
|
||||
init(IsSparse);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void AmbiVector<Scalar>::init(int mode)
|
||||
{
|
||||
m_mode = mode;
|
||||
if (m_mode==IsSparse)
|
||||
{
|
||||
m_llSize = 0;
|
||||
m_llStart = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Must be called whenever we might perform a write access
|
||||
* with an index smaller than the previous one.
|
||||
*
|
||||
* Don't worry, this function is extremely cheap.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
void AmbiVector<Scalar>::restart()
|
||||
{
|
||||
m_llCurrent = m_llStart;
|
||||
}
|
||||
|
||||
/** Set all coefficients of current subvector to zero */
|
||||
template<typename Scalar>
|
||||
void AmbiVector<Scalar>::setZero()
|
||||
{
|
||||
if (m_mode==IsDense)
|
||||
{
|
||||
for (int i=m_start; i<m_end; ++i)
|
||||
m_buffer[i] = Scalar(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert(m_mode==IsSparse);
|
||||
m_llSize = 0;
|
||||
m_llStart = -1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
Scalar& AmbiVector<Scalar>::coeffRef(int i)
|
||||
{
|
||||
if (m_mode==IsDense)
|
||||
return m_buffer[i];
|
||||
else
|
||||
{
|
||||
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
|
||||
// TODO factorize the following code to reduce code generation
|
||||
ei_assert(m_mode==IsSparse);
|
||||
if (m_llSize==0)
|
||||
{
|
||||
// this is the first element
|
||||
m_llStart = 0;
|
||||
m_llCurrent = 0;
|
||||
++m_llSize;
|
||||
llElements[0].value = Scalar(0);
|
||||
llElements[0].index = i;
|
||||
llElements[0].next = -1;
|
||||
return llElements[0].value;
|
||||
}
|
||||
else if (i<llElements[m_llStart].index)
|
||||
{
|
||||
// this is going to be the new first element of the list
|
||||
ListEl& el = llElements[m_llSize];
|
||||
el.value = Scalar(0);
|
||||
el.index = i;
|
||||
el.next = m_llStart;
|
||||
m_llStart = m_llSize;
|
||||
++m_llSize;
|
||||
m_llCurrent = m_llStart;
|
||||
return el.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nextel = llElements[m_llCurrent].next;
|
||||
ei_assert(i>=llElements[m_llCurrent].index && "you must call restart() before inserting an element with lower or equal index");
|
||||
while (nextel >= 0 && llElements[nextel].index<=i)
|
||||
{
|
||||
m_llCurrent = nextel;
|
||||
nextel = llElements[nextel].next;
|
||||
}
|
||||
|
||||
if (llElements[m_llCurrent].index==i)
|
||||
{
|
||||
// the coefficient already exists and we found it !
|
||||
return llElements[m_llCurrent].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_llSize>=m_allocatedElements)
|
||||
reallocateSparse();
|
||||
ei_internal_assert(m_llSize<m_size && "internal error: overflow in sparse mode");
|
||||
// let's insert a new coefficient
|
||||
ListEl& el = llElements[m_llSize];
|
||||
el.value = Scalar(0);
|
||||
el.index = i;
|
||||
el.next = llElements[m_llCurrent].next;
|
||||
llElements[m_llCurrent].next = m_llSize;
|
||||
++m_llSize;
|
||||
return el.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
Scalar AmbiVector<Scalar>::coeff(int i)
|
||||
{
|
||||
if (m_mode==IsDense)
|
||||
return m_buffer[i];
|
||||
else
|
||||
{
|
||||
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
|
||||
ei_assert(m_mode==IsSparse);
|
||||
if ((m_llSize==0) || (i<llElements[m_llStart].index))
|
||||
{
|
||||
return Scalar(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int elid = m_llStart;
|
||||
while (elid >= 0 && llElements[elid].index<i)
|
||||
elid = llElements[elid].next;
|
||||
|
||||
if (llElements[elid].index==i)
|
||||
return llElements[m_llCurrent].value;
|
||||
else
|
||||
return Scalar(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Iterator over the nonzero coefficients */
|
||||
template<typename _Scalar>
|
||||
class AmbiVector<_Scalar>::Iterator
|
||||
{
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
/** Default constructor
|
||||
* \param vec the vector on which we iterate
|
||||
* \param epsilon the minimal value used to prune zero coefficients.
|
||||
* In practice, all coefficients having a magnitude smaller than \a epsilon
|
||||
* are skipped.
|
||||
*/
|
||||
Iterator(const AmbiVector& vec, RealScalar epsilon = RealScalar(0.1)*precision<RealScalar>())
|
||||
: m_vector(vec)
|
||||
{
|
||||
m_epsilon = epsilon;
|
||||
m_isDense = m_vector.m_mode==IsDense;
|
||||
if (m_isDense)
|
||||
{
|
||||
m_cachedIndex = m_vector.m_start-1;
|
||||
++(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
|
||||
m_currentEl = m_vector.m_llStart;
|
||||
while (m_currentEl>=0 && ei_abs(llElements[m_currentEl].value)<m_epsilon)
|
||||
m_currentEl = llElements[m_currentEl].next;
|
||||
if (m_currentEl<0)
|
||||
{
|
||||
m_cachedIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedIndex = llElements[m_currentEl].index;
|
||||
m_cachedValue = llElements[m_currentEl].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int index() const { return m_cachedIndex; }
|
||||
Scalar value() const { return m_cachedValue; }
|
||||
|
||||
operator bool() const { return m_cachedIndex>=0; }
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
if (m_isDense)
|
||||
{
|
||||
do {
|
||||
++m_cachedIndex;
|
||||
} while (m_cachedIndex<m_vector.m_end && ei_abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
|
||||
if (m_cachedIndex<m_vector.m_end)
|
||||
m_cachedValue = m_vector.m_buffer[m_cachedIndex];
|
||||
else
|
||||
m_cachedIndex=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
|
||||
do {
|
||||
m_currentEl = llElements[m_currentEl].next;
|
||||
} while (m_currentEl>=0 && ei_abs(llElements[m_currentEl].value)<m_epsilon);
|
||||
if (m_currentEl<0)
|
||||
{
|
||||
m_cachedIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedIndex = llElements[m_currentEl].index;
|
||||
m_cachedValue = llElements[m_currentEl].value;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
const AmbiVector& m_vector; // the target vector
|
||||
int m_currentEl; // the current element in sparse/linked-list mode
|
||||
RealScalar m_epsilon; // epsilon used to prune zero coefficients
|
||||
int m_cachedIndex; // current coordinate
|
||||
Scalar m_cachedValue; // current value
|
||||
bool m_isDense; // mode of the vector
|
||||
};
|
||||
|
||||
|
||||
#endif // EIGEN_AMBIVECTOR_H
|
||||
@@ -2,5 +2,5 @@ FILE(GLOB Eigen_Sparse_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Sparse_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Sparse
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Sparse COMPONENT Devel
|
||||
)
|
||||
|
||||
236
Eigen/src/Sparse/CholmodSupport.h
Normal file
236
Eigen/src/Sparse/CholmodSupport.h
Normal file
@@ -0,0 +1,236 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_CHOLMODSUPPORT_H
|
||||
#define EIGEN_CHOLMODSUPPORT_H
|
||||
|
||||
template<typename Scalar, typename CholmodType>
|
||||
void ei_cholmod_configure_matrix(CholmodType& mat)
|
||||
{
|
||||
if (ei_is_same_type<Scalar,float>::ret)
|
||||
{
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = 1;
|
||||
}
|
||||
else if (ei_is_same_type<Scalar,double>::ret)
|
||||
{
|
||||
mat.xtype = CHOLMOD_REAL;
|
||||
mat.dtype = 0;
|
||||
}
|
||||
else if (ei_is_same_type<Scalar,std::complex<float> >::ret)
|
||||
{
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = 1;
|
||||
}
|
||||
else if (ei_is_same_type<Scalar,std::complex<double> >::ret)
|
||||
{
|
||||
mat.xtype = CHOLMOD_COMPLEX;
|
||||
mat.dtype = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert(false && "Scalar type not supported by CHOLMOD");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
cholmod_sparse SparseMatrixBase<Derived>::asCholmodMatrix()
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
cholmod_sparse res;
|
||||
res.nzmax = nonZeros();
|
||||
res.nrow = rows();;
|
||||
res.ncol = cols();
|
||||
res.p = derived()._outerIndexPtr();
|
||||
res.i = derived()._innerIndexPtr();
|
||||
res.x = derived()._valuePtr();
|
||||
res.xtype = CHOLMOD_REAL;
|
||||
res.itype = CHOLMOD_INT;
|
||||
res.sorted = 1;
|
||||
res.packed = 1;
|
||||
res.dtype = 0;
|
||||
res.stype = -1;
|
||||
|
||||
ei_cholmod_configure_matrix<Scalar>(res);
|
||||
|
||||
if (Derived::Flags & SelfAdjoint)
|
||||
{
|
||||
if (Derived::Flags & UpperTriangular)
|
||||
res.stype = 1;
|
||||
else if (Derived::Flags & LowerTriangular)
|
||||
res.stype = -1;
|
||||
else
|
||||
res.stype = 0;
|
||||
}
|
||||
else
|
||||
res.stype = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
cholmod_dense ei_cholmod_map_eigen_to_dense(MatrixBase<Derived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((ei_traits<Derived>::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 = mat.derived().stride();
|
||||
res.x = mat.derived().data();
|
||||
res.z = 0;
|
||||
|
||||
ei_cholmod_configure_matrix<Scalar>(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Flags>
|
||||
MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(cholmod_sparse& cm)
|
||||
{
|
||||
m_innerSize = cm.nrow;
|
||||
m_outerSize = cm.ncol;
|
||||
m_outerIndex = reinterpret_cast<int*>(cm.p);
|
||||
m_innerIndices = reinterpret_cast<int*>(cm.i);
|
||||
m_values = reinterpret_cast<Scalar*>(cm.x);
|
||||
m_nnz = m_outerIndex[cm.ncol];
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
class SparseLLT<MatrixType,Cholmod> : public SparseLLT<MatrixType>
|
||||
{
|
||||
protected:
|
||||
typedef SparseLLT<MatrixType> Base;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
typedef typename Base::RealScalar RealScalar;
|
||||
using Base::MatrixLIsDirty;
|
||||
using Base::SupernodalFactorIsDirty;
|
||||
using Base::m_flags;
|
||||
using Base::m_matrix;
|
||||
using Base::m_status;
|
||||
|
||||
public:
|
||||
|
||||
SparseLLT(int flags = 0)
|
||||
: Base(flags), m_cholmodFactor(0)
|
||||
{
|
||||
cholmod_start(&m_cholmod);
|
||||
}
|
||||
|
||||
SparseLLT(const MatrixType& matrix, int flags = 0)
|
||||
: Base(flags), m_cholmodFactor(0)
|
||||
{
|
||||
cholmod_start(&m_cholmod);
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
~SparseLLT()
|
||||
{
|
||||
if (m_cholmodFactor)
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
cholmod_finish(&m_cholmod);
|
||||
}
|
||||
|
||||
inline const typename Base::CholMatrixType& matrixL(void) const;
|
||||
|
||||
template<typename Derived>
|
||||
void solveInPlace(MatrixBase<Derived> &b) const;
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
|
||||
protected:
|
||||
mutable cholmod_common m_cholmod;
|
||||
cholmod_factor* m_cholmodFactor;
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
void SparseLLT<MatrixType,Cholmod>::compute(const MatrixType& a)
|
||||
{
|
||||
if (m_cholmodFactor)
|
||||
{
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
m_cholmodFactor = 0;
|
||||
}
|
||||
|
||||
cholmod_sparse A = const_cast<MatrixType&>(a).asCholmodMatrix();
|
||||
m_cholmod.supernodal = CHOLMOD_AUTO;
|
||||
// TODO
|
||||
if (m_flags&IncompleteFactorization)
|
||||
{
|
||||
m_cholmod.nmethods = 1;
|
||||
m_cholmod.method[0].ordering = CHOLMOD_NATURAL;
|
||||
m_cholmod.postorder = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cholmod.nmethods = 1;
|
||||
m_cholmod.method[0].ordering = CHOLMOD_NATURAL;
|
||||
m_cholmod.postorder = 0;
|
||||
}
|
||||
m_cholmod.final_ll = 1;
|
||||
m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
|
||||
cholmod_factorize(&A, m_cholmodFactor, &m_cholmod);
|
||||
|
||||
m_status = (m_status & ~SupernodalFactorIsDirty) | MatrixLIsDirty;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
inline const typename SparseLLT<MatrixType>::CholMatrixType&
|
||||
SparseLLT<MatrixType,Cholmod>::matrixL() const
|
||||
{
|
||||
if (m_status & MatrixLIsDirty)
|
||||
{
|
||||
ei_assert(!(m_status & SupernodalFactorIsDirty));
|
||||
|
||||
cholmod_sparse* cmRes = cholmod_factor_to_sparse(m_cholmodFactor, &m_cholmod);
|
||||
const_cast<typename Base::CholMatrixType&>(m_matrix) = MappedSparseMatrix<Scalar>(*cmRes);
|
||||
free(cmRes);
|
||||
|
||||
m_status = (m_status & ~MatrixLIsDirty);
|
||||
}
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
template<typename Derived>
|
||||
void SparseLLT<MatrixType,Cholmod>::solveInPlace(MatrixBase<Derived> &b) const
|
||||
{
|
||||
const int size = m_cholmodFactor->n;
|
||||
ei_assert(size==b.rows());
|
||||
|
||||
// this uses Eigen's triangular sparse solver
|
||||
// if (m_status & MatrixLIsDirty)
|
||||
// matrixL();
|
||||
// Base::solveInPlace(b);
|
||||
// as long as our own triangular sparse solver is not fully optimal,
|
||||
// let's use CHOLMOD's one:
|
||||
cholmod_dense cdb = ei_cholmod_map_eigen_to_dense(b);
|
||||
cholmod_dense* x = cholmod_solve(CHOLMOD_LDLt, m_cholmodFactor, &cdb, &m_cholmod);
|
||||
b = Matrix<typename Base::Scalar,Dynamic,1>::Map(reinterpret_cast<typename Base::Scalar*>(x->x),b.rows());
|
||||
cholmod_free_dense(&x, &m_cholmod);
|
||||
}
|
||||
|
||||
#endif // EIGEN_CHOLMODSUPPORT_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user