Compare commits

...

449 Commits

Author SHA1 Message Date
Antonio Sanchez
2bcca69afa Add CI for building docs 2025-10-17 21:58:59 -07:00
Thomas Capricelli
2827b35b29 simplify/uniformize eigen_gen_docs 2013-10-18 12:56:28 +02:00
Thomas Capricelli
3664ba0811 add piwik code to documentation (web stats engine) 2012-08-21 22:38:14 +02:00
Thomas Capricelli
ebef1f829d uniformize eigen_gen_docs between branches / cleaning 2012-04-03 14:23:16 +02:00
Gael Guennebaud
d2deedd5a8 bug #411: fix link to UnalignedArrayAssert.html 2012-01-25 16:33:35 +01:00
Thomas Capricelli
8c78edc04c eigen_gen_docs: dont try to update permissions on server 2011-12-06 15:52:55 +01:00
Benoit Jacob
b029007996 Added tag 2.0.17 for changeset 8ebe822a20 2011-12-06 08:18:58 -05:00
Benoit Jacob
8ebe822a20 bump 2011-12-06 08:18:54 -05:00
Thomas Capricelli
bd7475cc0c fix typo in doc for ParametrizedLine 2011-06-23 00:39:40 +02:00
Gael Guennebaud
e5203d46fe fix aligned_allocator::allocate interface 2011-06-14 08:52:38 +02:00
Gael Guennebaud
7065c3a398 Added tag 2.0.16 for changeset f90db64e6a 2011-05-28 10:16:30 +02:00
Gael Guennebaud
f90db64e6a bump to 2.0.16 2011-05-28 10:16:08 +02:00
Gael Guennebaud
d6293e6385 fix perf regression introduced by changeset 7852a48a2f
(matrix-vector product did not use the nesting rules....)
2011-05-27 22:05:39 +02:00
Gael Guennebaud
aaaa9301a8 fix bug #250 (gcc 4.6 compilation) 2011-04-19 16:35:48 +02:00
Gael Guennebaud
780f312228 fix LS documentation 2011-02-24 19:03:49 +01:00
Piotr Trojanek
ced86f3bfc class/struct mismatch for different template invocations 2011-01-16 00:32:13 +01:00
Benoit Jacob
1869a02f52 add part<SelfAdjoint>... it's never too late and I need this for eigen2support 2011-01-25 19:49:38 -05:00
DJ Marcin
0c8a25ef94 fix operator& precedence bug 2010-08-23 22:32:49 -04:00
Gael Guennebaud
70f355b51a backport fix on 3x3 triadiagonalization, this fix #149 2010-07-22 21:26:09 +02:00
Benoit Jacob
2d0963fb00 Added tag 2.0.15 for changeset 907fba9ea9 2010-07-16 22:25:12 -04:00
Benoit Jacob
907fba9ea9 bump 2010-07-16 22:25:08 -04:00
Gael Guennebaud
7e0b7b1f25 uncomment tests (sorry) 2010-07-16 11:50:40 +02:00
Gael Guennebaud
5ac00624ed adapted pactch from Nick Lewycky fixing a couple of issue with CLang 2010-07-15 22:48:44 +02:00
Gael Guennebaud
c0a0d2d181 add unit tests for 0 matrix 2010-07-15 20:00:50 +02:00
Gael Guennebaud
ec39a39cb6 fix LLT for zero matrix 2010-07-15 20:00:34 +02:00
Gael Guennebaud
ccc6731f86 fix use of rank in QR 2010-07-15 19:59:21 +02:00
Gael Guennebaud
b09bb50aeb fix QR solving with m>n 2010-07-15 19:52:11 +02:00
Gael Guennebaud
c7b8de77c0 fix aligned_delete for null pointers 2010-07-15 09:28:29 +02:00
Gael Guennebaud
c44bbabdcc fix LU and QR solve when rank==0, fix LLT when the matrix is purely 0 2010-07-12 16:42:38 +02:00
Gael Guennebaud
468863f3a0 fix bad Map in row-vector by matrix products 2010-07-09 20:27:05 +02:00
Gael Guennebaud
81f36b0e21 disable MSVC optimization when the underlying compiler is ICC 2010-07-09 19:36:43 +02:00
Benoit Jacob
c196a49f67 Added tag 2.0.14 for changeset e18e51d891 2010-06-22 22:23:39 -04:00
Benoit Jacob
e18e51d891 bump 2010-06-22 22:22:11 -04:00
Stuart Glaser
58fc972ed3 LU on limited-size matrices no longer allocates for temporaries. 2010-06-21 21:29:45 -07:00
Benoit Jacob
e7b6a4bcba fix bug introduced yesterday preventing vectorization of vectors when the storage order is not "the right one".
expand a little the vectorization_logic test and backport EIGEN_DEBUG_ASSIGN.
2010-06-22 09:24:07 -04:00
Benoit Jacob
eaa81c135a fix brain dead computation of the aligned bit.
When using a max-size that is fixed and not a multiple of 16 bit, we're not aligned.
2010-06-21 21:07:53 -04:00
Benoit Jacob
ad8b6c2342 fix #127: remove static keywords that had no effect anyway since the forward-declaration wasn't static,
and that would have been bad if they had taken effect.
2010-06-16 08:28:34 -04:00
Benoit Jacob
37fe67372b Added tag 2.0.13 for changeset ee499a855c 2010-06-10 08:06:38 -04:00
Benoit Jacob
ee499a855c bump version 2010-06-10 08:06:06 -04:00
Benoit Jacob
bc0ce37395 mention that that issue has been solved in GCC 4.5 2010-06-10 08:02:20 -04:00
Benoit Jacob
65c0b2a04d install the Eigen and Dense public headers !!!!! 2010-06-10 08:02:02 -04:00
Benoit Jacob
93d8d0e1b5 add unit test for bug #132 2010-06-09 20:50:18 -04:00
Benoit Jacob
501063d9e9 Fix bug #132
In the matrix-vector products, we were calling coeffRef on the vector xpr without checking it has DirectAccess.

Will add unit test (since it's in 2.0, just import the test case provided in the bug report).

Confirming that this can't happen in the devel branch, and that if we tried to call coeffRef on an xpr
without DirectAccess, that would not compile (since the DenseCoeffsBase class was introduced).
2010-06-09 19:39:05 -04:00
Gael Guennebaud
c76c8d6917 fix issue #125 2010-05-31 22:53:02 +02:00
Thomas Capricelli
0bb8688d70 sync .hgignore with tip 2010-05-26 02:37:52 +02:00
Thomas Capricelli
ea87337647 fix readcost for complex types (backport from tip) 2010-05-26 02:34:55 +02:00
Piotr Trojanek
12557fb2a2 more std:: namespace fixups for 2.0 branch 2010-05-01 09:25:36 +09:00
Benoit Jacob
8a95876825 with QCC, don't try passing --version 2010-04-29 07:58:47 -04:00
Benoit Jacob
82d7c4e1d0 forgot hg add 2010-04-26 07:54:19 -04:00
Benoit Jacob
8d4b0aae04 Fix bug #93: add platform check for how to link to the standard math library.
This allows to support QNX.
2010-04-19 11:30:46 -04:00
Gael Guennebaud
4785e27d6a fix btl compilation 2010-04-01 12:34:55 +02:00
Benoit Jacob
20b544b444 disable all alignment with QCC/QNX in eigen 2.0 2010-03-06 00:31:55 -05:00
Piotr Trojanek
135013c608 EIGEN_ALIGN std:: fixup 2010-03-04 16:38:37 +01:00
Piotr Trojanek
1625a5e3f8 fixups for clean QCC compilation (add std:: in front of size_t, memcpy, etc.) 2010-03-05 11:21:11 +01:00
Piotr Trojanek
47a61bbd80 posix_memalign check for QNX 2010-03-04 17:12:30 +01:00
Benoit Jacob
12bcfae0c5 clarify EIGEN_DONT_ALIGN docs wrt versions 2010-02-28 15:56:50 -05:00
Benoit Jacob
5f42104e0a really fix the LDLt, at the expense of letting isPositiveDefinite() always return true (it was fundamentally broken anyway, especially as in 2.0 we don't even pivot at all).
also, fix compilation
2010-02-23 18:10:31 -05:00
Benoit Jacob
6b3f81b414 precision improvement. Wtf were we using sqrt(precision) for the cutoff? Replaced by precision*biggest. 2010-02-23 16:26:39 -05:00
Gael Guennebaud
1f4b8e6a36 compilation fix in ldlt() for non matrix types
(transplanted from 608959aa6f
)
2010-02-21 10:29:19 +01:00
Benoit Jacob
e1f61b40c8 oops, this had to be done here, not at the end. 2010-02-12 09:02:25 -05:00
Benoit Jacob
f369dc873e Piotr's patch was missing many occurences of size_t. So,
using std::size_t;
This is the only way that we can ensure QCC support in the long term without having to think about it everytime.
2010-02-12 08:57:04 -05:00
Benoit Jacob
c03bca21c4 Added tag 2.0.12 for changeset ed6eb5a625 2010-02-11 21:39:46 -05:00
Benoit Jacob
ed6eb5a625 bump 2010-02-11 21:39:41 -05:00
Benoit Jacob
9488a12125 work around brain dead ICC 2010-02-11 19:32:56 -05:00
Piotr Trojanek
7b44957c4b std:: namespace fixup for more restricive compilers such as QNX's QCC 2010-02-10 22:27:35 +01:00
Hauke Heibel
743ad75595 BenchTimer backport (clock_gettime & QueryPerformanceCounter). 2010-02-03 21:55:01 +01:00
Benoit Jacob
a9eabed421 Patch by 'Wolf' from the issue tracker:
Fix bug #90, missing type cast in LU, allow to use LU with MPFR.
2010-02-02 07:06:15 -05:00
Benoit Jacob
cd34a1d351 backport bug fix by Jitse. 2010-01-28 14:00:09 -05:00
Benoit Jacob
3e963ee69d EIGEN_ENUM_MIN ---> EIGEN_SIZE_MIN 2010-01-26 20:37:57 -05:00
Benoit Jacob
6cc9dc17f2 In LU / Inverse, decouple the output type from the input type.
This has long been done in the default branch
2010-01-26 18:45:23 -05:00
Gael Guennebaud
7852a48a2f fix matrix product with EIGEN_DEFAULT_TO_ROW_MAJOR 2010-01-25 21:56:01 +01:00
Benoit Jacob
d209120180 * Introduce EIGEN_DEFAULT_TO_ROW_MAJOR tests option
---> Now only product_large fails with EIGEN_DEFAULT_TO_ROW_MAJOR.
* Fix EIGEN_NO_ASSERTION_CHECKING tests option
* Fix a crash in Tridiagonalization on row-major matrices + SSE
* Fix inverse test (numeric stability noise)
* Extend map test (see previous fixes in MapBase)
* Fix vectorization_logic test for row-major
* Disable sparse tests with EIGEN_DEFAULT_TO_ROW_MAJOR
2010-01-25 14:00:02 -05:00
Thomas Capricelli
55c0707b1d fix the script again (definitely?) + cleaning 2010-01-22 19:28:33 +01:00
Benoit Jacob
72044ca925 fix a super nasty bug: on row-major expressions that are NOT vectors but that
do have LinearAccess, the MapBase::coeff(int) and MapBase::coeffRef(int)
methods were broken.
2010-01-21 23:33:20 -05:00
Benoit Jacob
c2b8ca7493 if EIGEN_DONT_ALIGN then don't try to vectorize (was giving a #error later on). 2010-01-21 22:32:16 -05:00
Gael Guennebaud
018cb8975a fix plugin doc 2010-01-17 19:55:08 +01:00
Benoit Jacob
3ab280ce4e add missing semicolon in the example 2010-01-17 12:40:19 -05:00
Benoit Jacob
b40030753b Added tag 2.0.11 for changeset 5f73a8df20 2010-01-10 11:30:40 -05:00
Benoit Jacob
5f73a8df20 bump 2010-01-10 11:30:10 -05:00
Thomas Capricelli
8a6d5f10dc backport from tip : actually stop on compile failure 2010-01-06 17:17:40 +01:00
Benoit Jacob
ba6ed5fa5f Fix CoeffReadCost in Part: it must account for the cost of the
conditional jump. This makes Part considered an "expensive" xpr
 that must be evaluated in operations such as Product.
This fixes bug #80.
2010-01-02 13:04:04 -05:00
Benoit Jacob
e4c88c14ec clarify docs as requested on the forum 2010-01-02 12:54:55 -05:00
Benoit Jacob
74207a31fa backport the fix to bug #79, and the unit test 2010-01-02 12:45:49 -05:00
Benoit Jacob
6fd9248c09 add Intel copyright info 2009-12-15 08:43:31 -05:00
Benoit Jacob
4262117f84 backport 4x4 inverse changes:
- use cofactors
 - use Intel's SSE code in the float case
2009-12-15 08:16:48 -05:00
Gael Guennebaud
b581cb870c fix #74: sparse triangular solver for lower/row-major matrices 2009-12-14 10:20:35 +01:00
Gael Guennebaud
72fc81dd9d backport quaternion slerp precision fix 2009-12-05 18:28:17 +01:00
Gael Guennebaud
f36650b00a fix MSVC10 compilation issues 2009-12-02 19:34:37 +01:00
Benoit Jacob
8d31f58ea1 fix bug #70
Was trying to apply stupid invertibility check to top-left 2x2 corner.
2009-11-26 15:33:07 -05:00
Benoit Jacob
a161a70696 Added tag 2.0.10 for changeset 8f1ce52e76 2009-11-25 08:54:17 -05:00
Benoit Jacob
8f1ce52e76 bump 2009-11-25 08:46:42 -05:00
Benoit Jacob
268df314f1 make the inverse_4x4 test pass more consistently 2009-11-25 08:43:20 -05:00
Benoit Jacob
522022ebfc wow, restore Gael's changeset 5455d6fbe8
that I had accidentally undone in my changeset c64ca6870e
.
2009-11-25 08:31:25 -05:00
Thomas Capricelli
d048d7e712 fix bitbucket url after recent change 2009-11-24 23:08:16 +01:00
Benoit Jacob
cd3c8a9404 typo 2009-11-23 11:23:30 -05:00
Benoit Jacob
ec8f37ac75 improve precision test 2009-11-23 11:20:48 -05:00
Benoit Jacob
fc7f39980c backport improvement in 4x4 inverse precisio, and rigorous precision test 2009-11-23 10:27:10 -05:00
Gael Guennebaud
70af59c455 an attempt to fix compilation with recent MSVC 2009-11-23 10:29:40 +01:00
Benoit Jacob
f4dd399499 fix warnings 2009-11-16 14:15:47 -05:00
Benoit Jacob
153557527e backport: init-by-zero option: resize with same size must be a NOP 2009-11-16 13:47:02 -05:00
Benoit Jacob
6aad7f80ff avoid infinite loop, optimization not important, so a plain for loop is the safe way 2009-11-12 14:09:53 -05:00
Benoit Jacob
e3f6c3115a backport the initialize-by-0 option 2009-11-12 12:53:24 -05:00
Benoit Jacob
a2c838ff8f fix PowerPC platform detection 2009-11-11 10:52:00 -05:00
Thomas Capricelli
1e2f56c35a backport of b53c2fcc99
: fix install dir for *.pc

Ingmar Vanhassel <ingmar@exherbo.org>:
Packages that don't install architecture-specific files should install
their pkg-config file to datadir, not libdir.
2009-11-11 15:35:12 +01:00
Hauke Heibel
808c4e9581 Fixed the packport of 62 - Packet4f/d/i does not exist in 2.0. 2009-11-05 10:49:49 +01:00
Hauke Heibel
65331c3884 backporting3979f6d8aad001174160774b49b747430a7686b5
: fixed bug #62
2009-11-04 17:49:34 +01:00
Benoit Jacob
e158cdd61d fix Matrix::Map/MapAligned documentation, and rephrase the tutorial on Map 2009-10-31 14:45:50 -04:00
Benoit Jacob
c64ca6870e this explicit keyword can't hurt 2009-10-31 11:49:20 -04:00
Benoit Jacob
6a90f6c5f0 * default MatrixBase ctor: make it protected, make it a static assert, only do the check when debugging eigen to avoid slowing down compilation for everybody (this check is paranoiac, it's very seldom useful)
* add private MatrixBase ctors to catch cases when the user tries to construct MatrixBase objects directly
2009-10-31 11:48:33 -04:00
Gael Guennebaud
22dd13fdb9 backporting fix of #65 2009-10-29 14:26:38 +01:00
Gael Guennebaud
5455d6fbe8 backporting fix of #65 2009-10-29 14:26:00 +01:00
Benoit Jacob
de693cf34a remove extra ; 2009-10-28 10:04:13 -04:00
Benoit Jacob
21c4e0802d fix potential warning 2009-10-28 09:45:09 -04:00
Benoit Jacob
241b9d34a7 Hey, I was insomniac too ;)
This restores much of the performance benefit of Euler's method, without compromising accuracy (tested on 1e+7 matrices). Namely, my benchmark now runs in 1.5 s instead of 2.2 s. The same in the default branch runs in 1.08 s instead of 1.9 s, so the default branch benefits even more!
2009-10-28 03:50:29 -04:00
Benoit Jacob
9e15a6da2e Fix 4x4 matrix inversion. Applying Euler's trick is more tricky than what "high performance matrix inversion" websites would have you believe. Our 4x4 matrix inversion wasn't numerically stable, because in applying the Euler trick we didn't take the 2x2 block of biggest determinant. As a result, with float, we got relative errors above 1% every 1000 random matrices, and we got completely wrong results every 10000 matrices.
Note that this decreases the performance, but we're still significantly faster than the brutal cofactors approach.
2009-10-27 07:35:25 -04:00
Benoit Jacob
3d365a75cd Added tag 2.0.9 for changeset 38bc82a6f7 2009-10-24 19:38:58 -04:00
Benoit Jacob
38bc82a6f7 bump 2009-10-24 16:35:46 -04:00
Benoit Jacob
6173eb67ff really fix pkgconfig support and make install.
* mistake: was using the install dir instead of binary dir
* was also using INCLUDE_INSTALL_DIR before it was set, so on a first cmake run, the pkgconfig file was bad
2009-10-24 16:16:48 -04:00
Benoit Jacob
9f89431cea install NewStdVector 2009-10-23 19:58:37 -04:00
Benoit Jacob
79e392472a Added tag 2.0.8 for changeset e1c96f3fe0 2009-10-23 18:47:33 -04:00
Benoit Jacob
e1c96f3fe0 bump 2009-10-23 18:37:05 -04:00
Benoit Jacob
46f0fe3b4b SVD:
* implement default ctor, users were relying on the compiler generater one and reported issues on the forum
* turns out that we crash on 1x1 matrices but work on Nx1. No interest in fixing that, so just guard by assert and unit test.
2009-10-23 18:05:55 -04:00
Benoit Jacob
e17e4f3654 just this is enough 2009-10-23 17:51:32 -04:00
Benoit Jacob
2b006ae430 fix "make install"
aaargh
my shiny birthday release, it's broken already!
2009-10-23 17:47:12 -04:00
Benoit Jacob
df6923fd2b Added tag 2.0.7 for changeset 21d081c6da 2009-10-22 16:15:15 -04:00
Benoit Jacob
21d081c6da bump 2009-10-22 16:14:03 -04:00
Benoit Jacob
81fd1e9060 support gcc 3.3 2009-10-22 15:53:23 -04:00
Benoit Jacob
be8ae0d45f * CMakeLists: only pass -Wextra if it's supported (it's not on gcc 3.3)
* MapBase: put static first (fix gcc 3.3 warning)
* StdVector: add missing newline at end
2009-10-22 15:20:02 -04:00
Hauke Heibel
fc8b54c142 Code cleanup. 2009-10-22 20:06:05 +02:00
Hauke Heibel
76d578fb99 This does fix #61. See the comments in #61 for details. 2009-10-22 09:29:59 +02:00
Benoit Jacob
9af431e78e tentative fix for bug #61 2009-10-21 18:55:54 -04:00
Hauke Heibel
a4a3e511d0 Added missing resize case for m_outerSize==0. 2009-10-15 23:30:15 +02:00
Hauke Heibel
ffee27bf72 Fixed uninitialized variables in unit tests.
Fixed /W4 warning C4512 (LU was left out on purpose).
2009-10-14 08:33:36 +02:00
Benoit Jacob
5e24fbbead add assert for M>=N 2009-10-13 14:17:25 -04:00
Benoit Jacob
09364c8d05 fix compilation with gcc 3.3 2009-10-12 12:29:07 -04:00
Gael Guennebaud
3b8938ee1a backport d97d307fcf 2009-10-06 10:36:59 +02:00
Gael Guennebaud
e43d630d80 fix #10: the reallocateSparse function was half coded
(transplanted from 55de162cf6
)
2009-06-08 14:05:23 +02:00
Thomas Capricelli
eb1df142a3 backport changes in tip related to eigen_gen_docs 2009-10-04 03:38:13 +02:00
Thomas Capricelli
746d8b7ce9 update URL for adol-c (backport from tip) 2009-09-27 02:00:45 +02:00
Benoit Jacob
656c8faeb8 merge 2009-09-25 09:09:49 -04:00
Benoit Jacob
8084dbc86a copy the Memory.h file from the devel branch and remove some added trailing spaces.
This is now very harmless to do as the big change (EIGEN_ALIGN preprocessor stuff and the body of ei_aligned_malloc) was already introduced in 2.0.6.

Should address Björn's issue, and also improve FreeBSD platform detection.
2009-09-25 09:09:14 -04:00
Thomas Capricelli
79ebba4f52 clean tags... 2.0.6 was tagged three times, with two different values.
The best way to "push" a tag is to edit the .hgtags instead of using 'hg
tag xx' several times with the same value 'xx'.
2009-09-25 03:19:28 +02:00
Benoit Jacob
b362b45cff update .hgignore to ignore files created by eigen_gen_credits 2009-09-24 07:06:31 -04:00
Rhys Ulerich
c67b8b7ce0 Added pkgconfig support 2009-09-23 22:05:46 -04:00
Benoit Jacob
bcd621fcd5 Added tag 2.0.6 for changeset de88fb67d6 2009-09-23 12:11:26 -04:00
Benoit Jacob
de88fb67d6 bump that too 2009-09-23 12:11:19 -04:00
Benoit Jacob
4936720648 Added tag 2.0.6 for changeset 922e11e184 2009-09-23 12:08:22 -04:00
Benoit Jacob
922e11e184 bump 2009-09-23 12:08:16 -04:00
Benoit Jacob
8c2ace33c9 backport Rohit's vectorized quaternion product 2009-09-22 13:39:30 -04:00
Benoit Jacob
b66516e746 fix bug #42: add missing Transform::Identity() 2009-09-19 20:00:36 -04:00
Benoit Jacob
ecf64d2dc3 Allow to override EIGEN_RESTRICT, to satisfy a smart ass blogger who claims
that eigen2 owes all its performance to nonstandard restrict keyword.
well, this can also improve portability in case some compiler doesn't have __restrict.
2009-09-19 19:46:40 -04:00
Benoit Jacob
6af2c2c67a backported the following to 2.0:
* EIGEN_ALIGN and EIGEN_DONT_ALIGN and the corresponding logic in Macros.h
  (instead of using EIGEN_ARCH_WANTS_ALIGNMENT)
* The body of ei_aligned_malloc and ei_aligned_free

The reason for this backporting is that a user complained that with eigen 2.0 he got a warning at Memory.h:81 that the return value of posix_memalign was not used, and that function was declared with an attribute warn_unused_result.

Looking at this, it seemed that the body of this function was already overly complicated, and fixing this warning made it even worse, while the devel branch had a much simpler body and didn't suffer from that problem.

Then it was necessary to update ei_aligned_free too, and to backport EIGEN_ALIGN.

Inch' Allah....
2009-09-21 05:39:55 -04:00
Benoit Jacob
d0ac4fa479 explain how to get rid of it 2009-09-18 22:02:28 -04:00
Benoit Jacob
09f77b356d hg add the unit test 2009-09-16 14:29:44 -04:00
Benoit Jacob
8097487b9d backport bugfix in visitor (didn't work on rowvectors, fixed by splitting the vector case away from the matrix case) 2009-09-16 14:28:49 -04:00
Benoit Jacob
aaf1826384 backport: the first fix was the good one 2009-09-03 01:28:12 -04:00
Benoit Jacob
3590911de2 backport the fix to bug #50: compilation errors with swap 2009-09-02 17:04:34 -04:00
Benoit Jacob
21e97f07d8 update to reflect NewStdVector 2009-08-29 12:35:44 -04:00
Benoit Jacob
82df5b4a24 backport the new StdVector as NewStdVector
make StdVector be a wrapper around it if EIGEN_USE_NEW_STDVECTOR is defined
otherwise StdVector doesn't change ---> compatibility is preserved
backport unit-test
2009-08-29 12:13:52 -04:00
Benoit Jacob
35e88996c7 add missing parentheses after bug #42 2009-08-24 09:14:32 -04:00
Benoit Jacob
5dfb7204bd Added tag 2.0.5 for changeset e0cbf79e5a 2009-08-22 17:19:13 -04:00
Benoit Jacob
e0cbf79e5a bump to 2.0.5 2009-08-22 17:19:08 -04:00
Benoit Jacob
3af177058e fix nasty bug: when calling the cache friendly product, one used the product xpr flags instead of the destination flags, resulting in a transposed result when the storage orders didn't match. 2009-08-21 16:03:14 -04:00
Marcus D. Hanwell
258ea3ea02 Proper fix for linking to the Qt libraries (and others)
My initial fix was incorrect, the libraries must be quoted when being
passed to the add test macro, but must be unquoted when passed to the
target_link_libraries function.
2009-08-21 14:08:53 -04:00
Benoit Jacob
6580278e2c fix potential compilation issue 2009-08-21 12:08:59 -04:00
Benoit Jacob
dcefb66283 Fix bug #41, our resize() method didn't work with gcc 4.1 2009-08-21 11:53:04 -04:00
Benoit Jacob
9d64571963 disable fortran by default, because of bug http://public.kitware.com/Bug/view.php?id=9220 in cmake. 2009-08-21 11:48:59 -04:00
Benoit Jacob
65724def70 more useful error message about the including order 2009-08-20 12:27:01 -04:00
Benoit Jacob
7a44945a16 fix casting warning with MSVC 2009-08-18 07:41:17 -04:00
Gael Guennebaud
ed33d688e1 forgot to remove the link to the example list page 2009-08-17 18:23:21 +02:00
Gael Guennebaud
d7bf8b8581 remove the broken examplelist 2009-08-17 18:20:53 +02:00
Gael Guennebaud
a9c60954ed add EIGEN_TRANSFORM_PLUGIN 2009-08-17 09:16:04 +02:00
Gael Guennebaud
78ea8b2dbd fix #32 even though I agree this feature should be removed, or put somewhere else... 2009-08-15 22:35:33 +02:00
Benoit Jacob
d4e25e5acf in the 2.0 branch, that stuff isn't wanted anymore 2009-08-14 22:08:14 -04:00
Thomas Capricelli
36b324fe7b backport from main branch : basic .hgignore file 2009-08-15 03:43:40 +02:00
Thomas Capricelli
d37de5db30 todo list for the script eigen_gen_docs 2009-08-15 03:42:04 +02:00
Thomas Capricelli
456b6abed5 backport from the main branch : this script is used to create and upload
the documentation to the website
2009-08-15 03:39:08 +02:00
Gael Guennebaud
4a50ee8c21 fix issue #36 (missing return *this in Rotation2D
(transplanted from a4f6642518
)
2009-08-11 15:11:47 +02:00
Gael Guennebaud
c9f7a19053 make LU::solve() not to crash when rank=0
(transplanted from fe813911f2
)
2009-08-09 00:06:53 +02:00
Gael Guennebaud
47973c4963 set EIGEN_STACK_ALLOCATION_LIMIT as in the devel branch 2009-08-08 10:45:57 +02:00
Marcus D. Hanwell
65487176e3 Improved quoting of tests when added to the build.
This fixes an issue where multiple versions of the Qt libraries are
available, if the Qt library variable is not quoted an error was
generated as only the first part 'optimized' was used by the create test
macro.
2009-08-01 13:43:06 -04:00
Benoit Jacob
d28fae5bdf Added tag 2.0.4 for changeset d4f9515ca0 2009-08-01 00:58:16 +02:00
Benoit Jacob
d4f9515ca0 bump to 2.0.4 2009-08-01 00:58:09 +02:00
Gael Guennebaud
0361e8a7aa no more workaround, the -r option of clone works with branch name too 2009-07-31 17:24:57 +02:00
Gael Guennebaud
b7035b67b7 workaround to make the testsuite ctest script to work with the 2.0 branch, but that's only for unix systems 2009-07-31 17:07:43 +02:00
Gael Guennebaud
a1eae7ad00 update the ctest script for the 2.0 branch 2009-07-31 16:27:31 +02:00
Gael Guennebaud
30b605bef8 update the CTestConfig file to upload 2.0 reports to a different cdash project 2009-07-31 16:15:37 +02:00
Benoit Jacob
990615e884 backport 126284d08b
.
2009-07-31 13:30:12 +02:00
Gael Guennebaud
841ec959e5 s/std::atan2/ei_atan2 2009-07-31 10:08:23 +02:00
Manuel Yguel
2dce3311f7 add missing ei_atan2 without painfull warnings 2009-07-31 09:21:31 +02:00
Anthony Truchet
8eab0bccbf Bugfix in the Qt's QTransform and QMatrix support in Geometry/Transform.h
Function 'Transform<Scalar,Dim>::toQMatrix(void) const' :
  - 'other' was a hasty copy/paste to be replaced my m_matrix
	- 'coeffRef' was incorect for const Transform

Function 'Transform<Scalar,Dim>::toQTransform(void) const' :
	- return type was incorrect 'QMatrix' to be replaced by 'QTransform'
	- same bigfixes as in the previous point
2009-07-30 10:09:41 +02:00
Gael Guennebaud
f5a167b3e7 apply patch from Hauke Heibel cleaning overloaded operator new/detete 2009-05-07 20:33:48 +00:00
Gael Guennebaud
f845d15192 enable our own ctest dashboard 2009-07-20 23:55:43 +02:00
Gael Guennebaud
7ae2bc6109 compilation fix
(transplanted from c10b919edb
)
2009-07-20 10:56:03 +02:00
Gael Guennebaud
654fea39dc bugfix in operator*= (matrix product)
(transplanted from b3ad796d40
)
2009-07-20 10:44:07 +02:00
Gael Guennebaud
fa44566305 bugfix for a = a * b; when a has to be resized
(transplanted from a551107cce
)
2009-07-20 10:35:47 +02:00
Gael Guennebaud
8302ce6cdc remove the special version of ei_pow(int,int) for gcc >= 4.3 that was stupid
because gcc convert it to a pow(double,double)
2009-07-16 09:10:34 +02:00
Gael Guennebaud
c6eb9ef60e backporting bugfix in Quaternion::setFromTwoVectors() 2009-07-06 09:05:48 +02:00
Benoit Jacob
9bff5e4f67 some docs improvements 2009-07-05 01:52:42 +02:00
Gael Guennebaud
5f350c51b3 update the stack alignment doc 2009-06-22 10:46:03 +02:00
Benoit Jacob
df0b107243 Added tag 2.0.3 for changeset 55bf82c923 2009-06-21 17:46:35 +02:00
Benoit Jacob
55bf82c923 backport improvements to transpose documentation 2009-06-21 17:41:55 +02:00
Benoit Jacob
0b341486db document the "wrong stack alignment" issue 2009-06-21 17:34:17 +02:00
Benoit Jacob
9db0038c42 add Eigen/Eigen 2009-06-19 20:49:02 +02:00
Benoit Jacob
89d7ba0be0 add Dense header 2009-06-19 19:11:50 +02:00
Benoit Jacob
c3bab0edb7 fix #12, but the fix is not optimal, householder transformations need to be rethought in the complex case, see:
http://download.tuxfamily.org/eigen/complex-householder.pdf
2009-06-19 18:50:22 +02:00
Benoit Jacob
a1a26f45d3 fix #14: make llt::solve() and also ldlt::solve() work with uninitialized result 2009-06-19 17:01:32 +02:00
Benoit Jacob
f5ae3a4b5a result of our experiments with LU tuning: implement very simple formula, that
turns out to be similar to Higham's formula already in use in LDLt
2009-05-07 20:35:26 +00:00
Gael Guennebaud
8817798273 backporting accuracy fixes in QR module 2009-06-11 16:24:54 +02:00
Gael Guennebaud
287c7b8818 backporting LLT accuracy fixes 2009-06-11 16:18:37 +02:00
Benoit Jacob
5ec4922349 forgot to add the unsupported IterativeSolvers module needed by Step 2009-06-04 18:40:16 +02:00
Benoit Jacob
5a18f7545d this is essentially backporting all the changes made in the Sparse module up to KDE SVN revision r945600, aka changeset:
df9dfa1455


This is what is needed to make Step (in KDE/kdeedu) build.

The rest of Eigen (outside of Sparse) is unaffected except for a few trivial changes that were needed.

calling this 2.0.3, will tag if no problem.
2009-06-04 18:02:20 +02:00
Benoit Jacob
12570d97ce Added tag 2.0.2 for changeset 3fc53d2564 2009-05-22 15:41:27 +02:00
Benoit Jacob
3fc53d2564 bump version number 2009-05-22 15:41:22 +02:00
Benoit Jacob
9ff0baa680 the EIGEN_CAT macro is needed for the latest change in CacheFriendlyProduct 2009-05-22 15:03:40 +02:00
Gael Guennebaud
1c4b4e136b backporting warning fixes in cache friendly product 2009-05-19 02:20:04 +02:00
Thomas Capricelli
57934b9c30 backport ddb6e96d48
: fix warnings with recent gcc(4.3.3)
2009-05-19 00:05:33 +02:00
Thomas Capricelli
52aed8ac58 Remove this old file. It was stalling in history because of a bug in
svn, which did not prevent the commit (svn r722564) to 'svn copy' a
directory called 'Core/' on top of an existing file 'Core'

see http://websvn.kde.org/?view=rev&revision=722564
or
http://www.freehackers.org/thomas/2009/05/18/feedback-about-converting-eigen2-to-mercurial/
2009-05-18 15:20:56 +02:00
Benoit Jacob
1304e43f15 backport 964558: add missing setZero (etc) overloads that were mentioned in the tutorial
this should be safe as it's covered by the updated unit-test
2009-05-06 21:42:31 +00:00
Gael Guennebaud
e47593fb28 backporting 964177 (gcc 3.3 fix) 2009-05-06 09:41:36 +00:00
Gael Guennebaud
0104c34b7d backporting r964165 (gcc 3.3 fixes) 2009-05-06 09:40:41 +00:00
Benoit Jacob
f82d9bdf9a backport r963940, reimplement linearRegression on top of the better fitHyperplane 2009-05-05 17:16:45 +00:00
Benoit Jacob
c9edcc5acd backport 963931: fix linearRegression 2009-05-05 16:52:10 +00:00
Benoit Jacob
487edbf325 backport 963281, fix msvc detection on win64 2009-05-04 12:14:37 +00:00
Benoit Jacob
a29a390afa backport 958657: fix posix_memalign detection (Ross Smith) 2009-04-24 13:28:25 +00:00
Benoit Jacob
a16d18a632 update version number to 2.0.1 2009-04-14 14:32:00 +00:00
Benoit Jacob
3c3653b9de merge 953719: fix 4x4 inverse 2009-04-14 13:43:21 +00:00
Gael Guennebaud
c15842c374 backporting rev 951682 (compilation fix in aligned allocator) 2009-04-09 21:23:25 +00:00
Benoit Jacob
3c90fc2e64 patch by Hauke Heibel: compilation fix with VS 9 2009-04-09 12:05:36 +00:00
Benoit Jacob
d9c9508a12 backport 947492 -- fix static assertion / patch by Markus Moll 2009-03-31 16:08:06 +00:00
Gael Guennebaud
d6bb34fa5a backporting various bug fixes related to MapBase/Map/Block and new
StdVector workaround because the previous was really too limited. I hope
it is not a too big change for a "stable" branch.
2009-03-24 08:20:43 +00:00
Gael Guennebaud
e5b5ab53b8 backporting bugfix in SliceVectorization 2009-03-07 15:12:42 +00:00
Gael Guennebaud
f2829c1358 backporting rev 918446: fix MSVC internal compilation error 2009-03-06 22:18:26 +00:00
Benoit Jacob
d38504a4c8 backport 921254-921261 to the branch: disable alignment altogether on exotic platforms 2009-02-16 16:29:33 +00:00
Gael Guennebaud
95e4508b04 backporting rev925153 (bugfix in MapBase::coeffRef(int) ) 2009-02-12 15:32:32 +00:00
Benoit Jacob
b064b5e68e forgot to update version number 2009-02-02 16:18:42 +00:00
Benoit Jacob
f7df9f92ff backport 919961 and 920175 2009-02-02 14:26:40 +00:00
Benoit Jacob
d2dcca52a3 backport 920106: BSD's don't have aligned malloc 2009-02-02 13:24:17 +00:00
Gael Guennebaud
7408e923a7 backporting commit 918468 (fix MSVC internal error) 2009-01-29 23:14:51 +00:00
Gael Guennebaud
18ca438a62 backport r917694 (Patch from Frank fixing stupid MSVC internal crash) 2009-01-28 15:18:28 +00:00
Benoit Jacob
d286300362 backport unit-tests fixes 2009-01-27 20:56:47 +00:00
Benoit Jacob
02ba4e2f54 backport compilation fix 2009-01-27 17:46:02 +00:00
Benoit Jacob
2eef21a8d5 branch eigen 2.0 2009-01-27 17:26:44 +00:00
Gael Guennebaud
bea1737a5a FindUmfPack: add AMD and COLAMD libraries only if they are found 2009-01-27 16:22:08 +00:00
Gael Guennebaud
4b09865b8f check GSL version in cmake files 2009-01-27 16:04:16 +00:00
Benoit Jacob
f6aa60bcf3 centralize those static asserts more upstream, reduces duplication and ensures they can't be bypassed (e.g.
until now it was possible to bypass the static assert on sizes)
2009-01-27 15:40:05 +00:00
Benoit Jacob
8d236e74a1 add a missing static assertion on the scalar types 2009-01-27 15:29:07 +00:00
Benoit Jacob
046a84c0ef fix doc for norm() and squaredNorm(): these are not only for vectors 2009-01-27 14:05:20 +00:00
Gael Guennebaud
d7f60257dd small fix related to GSL cmake stuff 2009-01-26 20:00:41 +00:00
Benoit Jacob
874ff5a0b4 fix msvc warnings (useful ones again) reported by gael on CDash 2009-01-26 17:56:04 +00:00
Benoit Jacob
062d6bd47a documentation update/improvement 2009-01-26 16:22:40 +00:00
Benoit Jacob
b05c5dd1be compute the rank on the fly rather than at the end, and stop early
in the case of non-full rank (so big optimization in case the rank is low)
2009-01-26 16:14:20 +00:00
Gael Guennebaud
9ea1050281 fix MatrixNase::fillrand bug 2009-01-26 14:01:16 +00:00
Benoit Jacob
2776a3197b make these functions inline, thanks to Mek 2009-01-26 13:59:52 +00:00
Benoit Jacob
670de11dca forgot to backport an update to Mainpage.dox 2009-01-26 13:55:58 +00:00
Benoit Jacob
a79deafc6d * mark Geometry as experimental
* install QtAlignedMalloc
* finish the renaming Regression->LeastSquares
* install LeastSquares directory (!!!)
* misc dox fixes
2009-01-26 13:53:43 +00:00
Gael Guennebaud
65e4ae4ff4 disable unordered_map for ICC 2009-01-26 12:47:58 +00:00
Benoit Jacob
00d7f8e567 * solveTriangularInPlace(): take a const ref and const_cast it, to allow passing temporary xprs.
* improvements, simplifications in LU::solve()
* remove remnant of old norm2()
2009-01-25 23:46:51 +00:00
Benoit Jacob
414ee1db4b Optimization in LU::solve: when rows<=cols, no need to compute the L matrix
Remove matrixL() and matrixU() methods: they were tricky, returning a Part,
and matrixL() was useless for non-square LU. Also they were untested. This is
the occasion to simplify the docs (class_LU.cpp) removing the most confusing part.
I think that it's better to let the user do his own cooking with Part's.
2009-01-25 16:33:06 +00:00
Gael Guennebaud
56c7e164f0 add partial count redux (adapted patch from Ricard Marxer) 2009-01-24 15:22:44 +00:00
Gael Guennebaud
81b0ab53cf add fill() function as an alias for setConstant 2009-01-24 10:52:18 +00:00
Gael Guennebaud
9849931500 eventually it turns out that our current
EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
is the right way to go for allowing placement new on a class having
overloaded operator new. Qt 4.5 won't add the :: prefix. (I still do not
understand how you can distinghish a placement new from an overloaded
operator new taking an allocator as argument...)
2009-01-23 16:31:03 +00:00
Gael Guennebaud
e7c48fac9b sparse module: makes -= and += operator working
Question 1: why are *=scalar and /=scalar working right away ?
Same weirdness in DynamicSparseMatrix where operators += and -= work wihout
  having to redefine them ???
2009-01-23 13:59:32 +00:00
Gael Guennebaud
899e2ada15 very minor update in test/CMakeLists.txt 2009-01-23 13:17:57 +00:00
Gael Guennebaud
6a722602e6 fix a few remaining warnings
and fix commainitializer unit test with MSVC
2009-01-23 12:26:32 +00:00
Gael Guennebaud
d3dcb04f2d * fix compilation with gcc 3.4
* add an option to disable Qt testing
2009-01-23 09:50:16 +00:00
Benoit Jacob
291ee89684 add computeRotationScaling and computeScalingRotation in SVD
add convenience functions in Transform
reimplement Transform::rotation() to use that
add unit-test
2009-01-22 16:39:08 +00:00
Benoit Jacob
876b1fb842 add polar decomposition on both sides, in SVD, with test 2009-01-22 15:00:47 +00:00
Gael Guennebaud
32754d806d I hope this one fix the issue with MSVC and sparse module 2009-01-22 13:59:28 +00:00
Benoit Jacob
9e3c73110a fix a bunch of warnings (actual issues) reported by Frank 2009-01-22 00:09:34 +00:00
Gael Guennebaud
4225b7bf57 perhaps fix a compilation issue in the sparse module with MSVC 2009-01-21 21:02:55 +00:00
Benoit Jacob
7ccea9222c fix warnings 2009-01-21 20:06:16 +00:00
Gael Guennebaud
52cf07d266 sparse module:
* add row(i), col(i) functions
* add prune() function to remove small coefficients
2009-01-21 18:46:04 +00:00
Gael Guennebaud
25f1658fce update sparse matrix tutorial (far to be satisfactory yet) 2009-01-21 17:44:58 +00:00
Benoit Jacob
5f43a42ee7 * remove set(), revert to old behavior where = resizes
* try to be clever in matrix ctors and operator=: be lazy when we can, always allow
  to copy rowvector into columnvector, check the template parameters,
  try to factor the code better
* add missing copy ctor in UnalignedType
* fix bug in the traits of DiagonalProduct
* renaming: EIGEN_TUNE_FOR_CPU_CACHE_SIZE
* update the dox a little
2009-01-21 17:10:23 +00:00
Marijn Kruisselbrink
a5fbf27843 don't claim googlehash is there when only qt4 has been found :) 2009-01-20 22:15:51 +00:00
Benoit Jacob
294682a25a lu test:don't fail 2009-01-20 19:06:39 +00:00
Gael Guennebaud
f645d1f911 * complete the support of QVector via a QtAlignedMalloc header
* add a unit test for QVector which shows the issue with QVector::fill
2009-01-20 16:50:47 +00:00
Gael Guennebaud
8973d12cda * QR: add a rank() method and improve the accuracy of the rank
* computation
* Array: add a count() method and rename AllAndAny.h file to
  BooleanRedux.h
2009-01-20 16:37:52 +00:00
Benoit Jacob
81cb887baf fix bug in the computation of rank
very difficult to catch in unit-tests because this is very noisy
2009-01-20 16:21:56 +00:00
Gael Guennebaud
3134d5290b forgot to include the update of the qr test 2009-01-20 10:38:56 +00:00
Gael Guennebaud
3e5b3a33fa quick bugfix in QR::isFullRank() (not 100% sure about the reference value
for the comparison to 0)
2009-01-20 10:37:39 +00:00
Marijn Kruisselbrink
8690ba923c I assume these files where supposed to be installed 2009-01-19 22:58:15 +00:00
Gael Guennebaud
36c478cd6e optimize A * v product for A sparse and row major 2009-01-19 22:29:28 +00:00
Gael Guennebaud
178858f1bd add a flexible sparse matrix class designed for fast matrix assembly 2009-01-19 15:20:45 +00:00
Benoit Jacob
385fd3d918 * clarify the situation with experimental parts
* remove all what was marked deprecated
2009-01-19 15:02:24 +00:00
Benoit Jacob
dcaa58744e #error if min or max is defined 2009-01-19 13:23:41 +00:00
Gael Guennebaud
9ae03f4589 add a compilation test in FindGoogleHash.cmake to catch configuration
issues when multiple compilers are used on the same system.
2009-01-19 08:51:06 +00:00
Gael Guennebaud
708fa36750 revert bad commit 2009-01-19 08:21:32 +00:00
Gael Guennebaud
d58bb54e7f add a smart realloc algorithm when filling a sparse matrix 2009-01-18 18:00:19 +00:00
Gael Guennebaud
0c7974dd4d bugfix in Map by Keir Mierle 2009-01-18 09:53:06 +00:00
Gael Guennebaud
22792c696f add ublas vector of vector in sparse setter bench 2009-01-17 16:24:49 +00:00
Benoit Jacob
61b85b1436 update documentation (thanks Kenneth) 2009-01-17 14:24:09 +00:00
Gael Guennebaud
cc6c4d807b add a sparse setter bench 2009-01-17 14:05:01 +00:00
Gael Guennebaud
c5020c6e8e patch from Ricard Marxer: add doc example for select() 2009-01-17 09:59:32 +00:00
Gael Guennebaud
1eec38dc36 Rewrite the vectorized meta unroller of sum to reduce instruction
dependency => significant speed up
2009-01-17 09:48:58 +00:00
Benoit Jacob
e556e647f4 typo found by Ben Axelrod
CCMAIL:baxelrod@coroware.com
2009-01-17 00:53:38 +00:00
Gael Guennebaud
86a192681e * Started a tutorial page for sparse matrix.
* Updated Mainpage.dox's directives used by kde's scripts
2009-01-16 17:20:12 +00:00
Gael Guennebaud
48df9ed715 Add a data() function in Map and Block 2009-01-16 10:25:53 +00:00
Gael Guennebaud
ccdcebcf03 Sparse module: add support for sparse selfadjoint * dense 2009-01-15 18:52:14 +00:00
Gael Guennebaud
9a4b7998cf Sparse module: add row/col methods to the iterators 2009-01-15 14:16:41 +00:00
Gael Guennebaud
87241089e1 Sparse module: bugfix in SparseMatrix::resize(), now the indices are
correctly initialized to 0.
2009-01-15 13:30:50 +00:00
Gael Guennebaud
96e1e582ff Sparse module:
* add a MappedSparseMatrix class (like Eigen::Map but for sparse
  matrices)
* rename SparseArray to CompressedStorage
2009-01-15 12:52:59 +00:00
Gael Guennebaud
4f33fbfc07 two compilation fixes 2009-01-15 08:26:40 +00:00
Gael Guennebaud
2d53466fa9 Sparse module:
* improved performance of mat*=scalar
* bug fix in cwise*
2009-01-14 21:27:54 +00:00
Gael Guennebaud
f5741d4277 add a sparse * dense_vector bench 2009-01-14 18:27:17 +00:00
Gael Guennebaud
0b606dcccd Add support for sparse * dense and dense * sparse matrix/vector products 2009-01-14 17:41:55 +00:00
Gael Guennebaud
c4c70669d1 Big rewrite in the Sparse module: SparseMatrixBase no longer inherits MatrixBase.
That means a lot of features which were available for sparse matrices
via the dense (and super slow) implemention are no longer available.
All features which make sense for sparse matrices (aka can be implemented efficiently) will be
implemented soon, but don't expect to see an API as rich as for the dense path.
Other changes:
* no block(), row(), col() anymore.
* instead use .innerVector() to get a col or row vector of a matrix.
* .segment(), start(), end() will be back soon, not sure for block()
* faster cwise product
2009-01-14 14:24:10 +00:00
Gael Guennebaud
ee87f5ee49 s/EIGEN_WORK_DIRECTORY/EIGEN_WORK_DIR in testsuite script 2009-01-14 10:43:36 +00:00
Benoit Jacob
a5632fe1db add EIGEN_FUNCTORS_PLUGIN 2009-01-13 16:27:26 +00:00
Benoit Jacob
e8e1084267 add EIGEN_CWISE_PLUGIN support for extending class Cwise 2009-01-13 15:31:06 +00:00
Gael Guennebaud
ec0b2f900c fix a couple of doxygen issues 2009-01-13 08:30:17 +00:00
Benoit Jacob
b179f8e1a4 add NetBSD to the list of OSes on which malloc is guaranteed to be 16
byte aligned, after discussion with Mark Davies.

CCMAIL: mark@ecs.vuw.ac.nz
2009-01-12 22:39:26 +00:00
Gael Guennebaud
62d01d3cf4 hm it seems cmake does not understand CYGWIN (=> UNIX) 2009-01-12 19:39:50 +00:00
Gael Guennebaud
534dc60672 improved a bit the testsuite script 2009-01-12 18:10:41 +00:00
Benoit Jacob
38d916d50f just a stub for the householder stuff we did with keir yesterday... 2009-01-12 16:56:11 +00:00
Benoit Jacob
24fd14dab6 * minor dox tweaks
* pretext to bump to beta6
2009-01-12 16:14:13 +00:00
Benoit Jacob
4d44ca226e * make std::vector specializations also for Transform and for Quaternion
* update test_stdvector
* Quaternion() does nothing (instead of bug)
* update test_geometry
* some renaming
2009-01-12 16:06:04 +00:00
Gael Guennebaud
b26e12abcf make ei_traist<Select> honors nested types 2009-01-12 15:55:56 +00:00
Gael Guennebaud
a7554023a4 bugfix in ei_unaligned_type copy ctor 2009-01-12 15:51:49 +00:00
Gael Guennebaud
9d97c06d9d fix a warning in test/alignedbox 2009-01-12 15:29:51 +00:00
Gael Guennebaud
1fc17c4792 remove stupid output in test/meta 2009-01-12 15:27:25 +00:00
Gael Guennebaud
6efaece8ce disable/enable msvc headers are allowed to be included multiple times 2009-01-12 14:46:11 +00:00
Benoit Jacob
294f5f16dd muuuch improved documentation for the unaligned array assert.
also split into several pages for better reusability (more generally useful than
just for this assert)
2009-01-12 14:41:12 +00:00
Gael Guennebaud
f86818b5a6 bug fix in ei_stack_free 2009-01-12 14:20:21 +00:00
Benoit Jacob
336ad58213 * move cwise *= and /= to Core (like * and /)
* tidy the StdVector module
* fix warnings (especially a | instead of ||) in stdvector test
2009-01-12 13:41:40 +00:00
Gael Guennebaud
af5034b3c0 add a clean configuration summary for the unit tests (useful to analyze the dashboards) 2009-01-12 13:40:02 +00:00
Gael Guennebaud
7f881e814f another warning fix 2009-01-12 13:01:31 +00:00
Gael Guennebaud
a4252584ed bugfix in ei_handmade_aligned_free for null pointers 2009-01-12 12:54:32 +00:00
Gael Guennebaud
b365f443a2 make the testsuite works on windows with nmake 2009-01-12 12:53:41 +00:00
Gael Guennebaud
484ed3bbe2 fix a warning in test/sparse.h 2009-01-12 12:52:36 +00:00
Gael Guennebaud
92959aa5f3 add the possiblity to disable Fortran (workaround cmake's bug 2009-01-12 12:51:40 +00:00
Gael Guennebaud
2db5888253 update testsuite script 2009-01-12 11:55:52 +00:00
Gael Guennebaud
f268e79709 simplify some ei_traits<> using inheritance
(less loc and slight compilation speed up)
2009-01-11 22:03:40 +00:00
Gael Guennebaud
9e8f437a6f extend stdvector test with more push_back... 2009-01-11 21:59:04 +00:00
Benoit Jacob
824b75f182 forgot to commit updated test 2009-01-11 21:04:23 +00:00
Benoit Jacob
a30b498ab4 add cwise operator *= and /=.
Keir says hi!!
2009-01-11 20:48:56 +00:00
James Richard Tyrer
28e15574df updating FindEigen2.cmake for proper search order 2009-01-11 16:18:59 +00:00
Armin Berres
6c84b03d77 add missing newline at EOF 2009-01-11 13:32:55 +00:00
Benoit Jacob
4361cb8913 EIGEN_NO_MALLOC must also block traditional unaligned malloc 2009-01-10 14:24:55 +00:00
Benoit Jacob
50ad8b9010 fix potential compilation issue on MSVC + no vectorization 2009-01-10 14:10:40 +00:00
Benoit Jacob
0c1ef2f4c6 make the std::vector fix work also with dynamic size Eigen objects, e.g.
std::vector<VectorXd>
update unit test
2009-01-10 13:10:23 +00:00
Benoit Jacob
3efe6e4176 remove ei_new_allocator
remove corresponding part of test_dynalloc
2009-01-10 02:50:09 +00:00
Benoit Jacob
335d3bcf05 Based on code + help from Alex Stapleton:
*Add Eigen/StdVector header.
Including it #includes<vector> and "Core" and generates a partial
specialization of std::vector<T> for T=Eigen::Matrix<...>
that will work even with vectorizable fixed-size Eigen types
(working around a design issue in the c++ STL)
*Add unit-test

CCMAIL: alex.stapleton@gmail.com
2009-01-09 23:26:45 +00:00
Benoit Jacob
5052d3659b oops, fix compilation (sorry for all that noise!) 2009-01-09 21:43:46 +00:00
Benoit Jacob
5bef59e371 (previous commit was bad) 2009-01-09 21:32:44 +00:00
Benoit Jacob
265ab86005 overloaded operator delete should call ei_conditinal_aligned_free, not
ei_aligned_free
2009-01-09 21:28:53 +00:00
Benoit Jacob
b3d580dec7 ei_aligned_delete was running through the various paths in the wrong
order
2009-01-09 20:57:06 +00:00
Benoit Jacob
fd831d5a12 * implement handmade aligned malloc, fast but always wastes 16 bytes of memory.
only used as fallback for now, needs benchmarking.
  also notice that some malloc() impls do waste memory to keep track of alignment
  and other stuff (check msdn's page on malloc).
* expand test_dynalloc to cover low level aligned alloc funcs. Remove the old
  #ifdef EIGEN_VECTORIZE...
* rewrite the logic choosing an aligned alloc, some new stuff:
  * malloc() already aligned on freebsd and windows x64 (plus apple already)
  * _mm_malloc() used only if EIGEN_VECTORIZE
  * posix_memalign: correct detection according to man page (not necessarily
    linux specific), don't attempt to declare it if the platform didn't declare it
    (there had to be a reason why it didn't declare it, right?)
2009-01-09 14:56:44 +00:00
Kenneth Frank Riddile
f52a9e5315 * Added aligned_allocator for using 16-byte aligned types with STL containers. There is still a compile-time problem with STL containers that have a standard-conformant resize() method, but this should resolve the original user issue which was storing aligned objects in a std::map. 2009-01-09 00:55:53 +00:00
Benoit Jacob
003d0ce03e add missing inline keywords (compilation error) spotted by timvdm 2009-01-08 20:20:11 +00:00
Gael Guennebaud
208b273106 change the day switch time to 5:00 UTC 2009-01-08 18:45:26 +00:00
Gael Guennebaud
b315f4c359 add a ctest testsuite.cmake script to simplify the generation of nightly builds 2009-01-08 18:38:58 +00:00
Benoit Jacob
51aa62a5d4 add EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
an ugly hack that allows people to do QVector<Vector4f> with Qt <= 4.4
the Qt bug this is working around is fixed by Gael in Qt 4.5
2009-01-08 16:03:24 +00:00
Benoit Jacob
eb7dcbbfce EIGEN_MAKE_ALIGNED_OPERATOR_NEW didn't actually need to get the class
name as parameter
2009-01-08 15:37:13 +00:00
Benoit Jacob
1d52bd4cad the big memory changes. the most important changes are:
ei_aligned_malloc now really behaves like a malloc
 (untyped, doesn't call ctor)
ei_aligned_new is the typed variant calling ctor
EIGEN_MAKE_ALIGNED_OPERATOR_NEW now takes the class name as parameter
2009-01-08 15:20:21 +00:00
Benoit Jacob
e2d2a7d222 fix a bug -- bad read found by valgrind 2009-01-08 14:23:30 +00:00
Gael Guennebaud
af27fb7590 Add cdash.org support:
* the dashboard is there: http://my.cdash.org/index.php?project=Eigen
* now you can run the tests from the top build dir
  and submit report like that (from the top build dir):
  ctest -D Experimental
* todo:
 - add some nighlty builds (I'll add a few on my computer)
 - add valgrind memory checks, performances tests, compilation time tests, etc.
2009-01-08 11:53:21 +00:00
Gael Guennebaud
8d3469ca44 add BLAS dependency in FindSuperLU.cmake 2009-01-08 11:27:02 +00:00
Gael Guennebaud
4432cf8ca3 bugfix in sum 2009-01-08 10:36:54 +00:00
Gael Guennebaud
cb71dc4bbf Add a vectorization_logic unit test for assign and sum.
Need to add dot and more tests, but it seems I've already
found some room for improvement in sum.
2009-01-07 22:20:03 +00:00
Gael Guennebaud
709e903335 Sparse module:
* extend unit tests
* add support for generic sum reduction and dot product
* optimize the cwise()* : this is a special case of CwiseBinaryOp where
  we only have to process the coeffs which are not null for *both* matrices.
  Perhaps there exist some other binary operations like that ?
2009-01-07 17:01:57 +00:00
Kenneth Frank Riddile
7078cfaeaa * re-enabled deprecation warning on msvc now that eigen isn't using functions microsoft deems deprecated 2009-01-07 16:59:43 +00:00
Gael Guennebaud
336f0a8486 fine tuning in dot() and sum(), and prepare for the sparse versions... 2009-01-07 16:58:17 +00:00
Gael Guennebaud
6b9d647fc2 add custom implementation of hypot 2009-01-07 16:53:09 +00:00
Kenneth Frank Riddile
3e90940189 * disabled deprecation warning under msvc that was being triggered due to microsoft deprecating portable functions in favor of non-portable ones ( ex: hypot() deprecated in favor of _hypot() ) 2009-01-07 16:50:35 +00:00
Gael Guennebaud
8cea5f6b31 remove non standard hypotf function call 2009-01-07 16:24:27 +00:00
Gael Guennebaud
94efa16187 more Scalar conversions fixes 2009-01-07 10:22:46 +00:00
Gael Guennebaud
ac9d805c2f two scalar conversion fixes 2009-01-07 09:47:16 +00:00
Benoit Jacob
2db434265b remove the Matrix_ prefix 2009-01-06 18:07:16 +00:00
Armin Berres
8e888a45d0 call methods from the eigen namespace with prepended Eigen:: in define 2009-01-06 11:20:36 +00:00
Kenneth Frank Riddile
6736e52d25 * suppressed some minor warnings 2009-01-06 04:38:00 +00:00
Benoit Jacob
1c29d70312 * introduce macros to replace inheritance for operator new overloading
(former solution still available and tested)
  This plays much better with classes that already have base classes --
  don't force the user to mess with multiple inheritance, which gave
  much trouble with MSVC.
* Expand the unaligned assert dox page
* Minor fixes in the lazy evaluation dox page
2009-01-06 03:16:50 +00:00
Benoit Jacob
e71de20f16 ...so the placement new is really trivial:) 2009-01-05 20:06:52 +00:00
Benoit Jacob
1eec8488a2 oops, placement new should take a void* 2009-01-05 19:56:32 +00:00
Benoit Jacob
9dcde48980 we also had to overload the placement new... issue uncovered by Tim when
doing QVector<Vector3d>...
2009-01-05 19:49:07 +00:00
Benoit Jacob
215ce5bdc1 forgot to install the LeastSquares header 2009-01-05 19:12:35 +00:00
Benoit Jacob
10f9478f35 release beta5, fix a doc typo 2009-01-05 19:00:10 +00:00
Benoit Jacob
9c8a653c0b gaaaaaaaaaaaaaaaaaah
can't believe that 3 people wasted so much time because of a missing &
!!!!!
and this time MSVC didn't catch it so it was really copying the vector
on the stack at an unaligned location!
2009-01-05 18:33:39 +00:00
Benoit Jacob
8551505436 problem solved, we really want public inheritance and it is only
automatic when the _child_ class is a struct.
2009-01-05 18:21:44 +00:00
Benoit Jacob
1b88042880 the empty base class optimization is not standard. Most compilers implement a basic form of it; however MSVC won't implement it if there is more than one empty base class.
For that reason, we shouldn't give Matrix two empty base classes, since sizeof(Matrix) must be optimal.
So we overload operator new and delete manually rather than inheriting an empty struct for doing that.
2009-01-05 16:46:19 +00:00
Benoit Jacob
7db3f2f72a *fix compilation with MSVC 2005 in the Transform::construct_from_matrix
*fix warnings with MSVC 2005: converting M_PI to float gives loss-of-precision warnings
2009-01-05 14:47:38 +00:00
Armin Berres
dae7f065d4 didn't meant to commit the fortran check. but anyway, unfortunately it doesn't work the way iot should. the test fails and cmake will terminate if it doesn't find a fortran compiler 2009-01-05 14:40:27 +00:00
Armin Berres
ab660a4d29 inherit from ei_with_aligned_operator_new even with disabled vectorization 2009-01-05 14:35:07 +00:00
Benoit Jacob
986f301233 *add PartialRedux::cross() with unit test
*add transform-from-matrices test
*undo an unwanted change in Matrix
2009-01-05 14:26:34 +00:00
Benoit Jacob
d316d4f393 fix compilation on apple: _mm_malloc was undefined. the fix is to just use malloc since on apple it already returns aligned ptrs 2009-01-05 13:15:27 +00:00
Benoit Jacob
e1ee876daa fix segfault due to non-aligned packets 2009-01-04 23:23:32 +00:00
Benoit Jacob
3de311f497 oops forgot important parentheses 2009-01-04 21:23:02 +00:00
Benoit Jacob
06fd84cdb1 Fix bug in Matrix, in determining whether to overload operator new with an aligned one, introduced in r905543 2009-01-04 21:20:42 +00:00
Benoit Jacob
0e5c640563 * fix a unused variable warning
* if svnversion returns prose such as "exported" then discard that
2009-01-04 17:32:20 +00:00
Benoit Jacob
be64619ab6 * require CMake 2.6.2 everywhere, Alexander Neundorf says it'd make it
easier to have a uniform requirement in kdesupport for when he makes
fixes.
* add eigen versioning macros
2009-01-04 16:19:12 +00:00
Benoit Jacob
269bf67796 rename Regression --> LeastSquares 2009-01-04 15:55:54 +00:00
Benoit Jacob
15ca6659ac * the 4th template param of Matrix is now Options. One bit for storage
order, one bit for enabling/disabling auto-alignment. If you want to
disable, do:
Matrix<float,4,1,Matrix_DontAlign>
The Matrix_ prefix is the only way I can see to avoid
ambiguity/pollution. The old RowMajor, ColMajor constants are
deprecated, remain for now.
* this prompted several improvements in matrix_storage. ei_aligned_array
renamed to ei_matrix_array and moved there. The %16==0 tests are now
much more centralized in 1 place there.
* unalignedassert test: updated
* update FindEigen2.cmake from KDElibs
* determinant test: use VERIFY_IS_APPROX to fix false positives; add
testing of 1 big matrix
2009-01-04 15:26:32 +00:00
Benoit Jacob
d9e5fd393a * In LU solvers: no need anymore to use row-major matrices
* Matrix: always inherit WithAlignedOperatorNew, regardless of
vectorization or not
* rename ei_alloc_stack to ei_aligned_stack_alloc
* mixingtypes test: disable vectorization as SSE intrinsics don't allow
mixing types and we just get compile errors there.
2009-01-03 22:33:08 +00:00
Gael Guennebaud
fd7eba3394 Added a SparseVector class (not tested yet) 2009-01-02 08:47:09 +00:00
Benoit Jacob
d671205755 fix the nomalloc test: it didn't catch the ei_stack_alloc in
cachefriendlyproduct, that should be banned as well as depending on the
platform they can give a malloc, and they could happen even with (large
enough) fixed size matrices. Corresponding fix in Product.h:
cachefriendly is now only used for dynamic matrices -- fixedsize, no
matter how large, doesn't use the cachefriendly product. We don't need
to care (in my opinion) about performance for large fixed size, as large
fixed size is a bad idea in the first place and it is more important to
be able to guarantee clearly that fixed size never causes a malloc.
2008-12-31 00:25:31 +00:00
Benoit Jacob
3958e7f751 add unit-test checking the assertion on unaligned arrays -- checking
that it's triggered when and only when it should.
2008-12-31 00:05:22 +00:00
Benoit Jacob
164f410bb5 * make WithAlignedOperatorNew always align even when vectorization is disabled
* make ei_aligned_malloc and ei_aligned_free honor custom operator new and delete
2008-12-30 14:11:35 +00:00
Gael Guennebaud
a2782964c1 Sparse module, add an assertion and make the use of CHOLMOD's solve method the default. 2008-12-27 19:51:54 +00:00
Gael Guennebaud
ce3984844d Sparse module:
* enable complex support for the CHOLMOD LLT backend
   using CHOLMOD's triangular solver
 * quick fix for complex support in SparseLLT::solve
2008-12-27 18:13:29 +00:00
Benoit Jacob
361225068d fix bug discovered by Frank:
ei_alloc_stack must really return aligned pointers
2008-12-24 13:59:24 +00:00
Benoit Jacob
6f158fb7fc one last compilation fix ... 2008-12-22 21:04:13 +00:00
Benoit Jacob
789ea9d676 unless i find more failures in the tests, this will be beta3...
* fixes for mistakes (especially in the cast() methods in Geometry) revealed by the new "mixing types" test
* dox love, including a section on coeff access in core and an overview in geometry
2008-12-22 20:50:47 +00:00
Benoit Jacob
4336cf3833 * add unit-tests to check allowed and forbiddent mixing of different scalar types
* fix issues in Product revealed by this test
* in Dot.h forbid mixing of different types (at least for now, might allow real.dot(complex) in the future).
2008-12-22 19:17:44 +00:00
Benoit Jacob
f5a05e7ed1 unfuck v.cwise()*w where v is real and w is complex 2008-12-21 20:55:46 +00:00
Benoit Jacob
9e00d94543 * the Upper->UpperTriangular change
* finally get ei_add_test right
2008-12-20 13:36:12 +00:00
Benoit Jacob
21ab65e4b3 fix nasty little bug in ei_add_test 2008-12-20 01:13:38 +00:00
Gael Guennebaud
ebf906a23a add matrix * transform product 2008-12-19 16:31:22 +00:00
Benoit Jacob
df4bd5e46f * fix a test giving some false positives
* add coverage for various operator*=
2008-12-19 16:16:39 +00:00
Benoit Jacob
a3fad2e3c3 Transform*Transform should return Transform
unit test compiles again
2008-12-19 15:55:35 +00:00
Gael Guennebaud
5f6fbaa0e7 * fix a vectorization issue in Product
* use _mm_malloc/_mm_free on other platforms than linux of MSVC (eg., cygwin, OSX)
* replace a lot of inline keywords by EIGEN_STRONG_INLINE to compensate for
  poor MSVC inlining
2008-12-19 15:38:39 +00:00
Gael Guennebaud
8679d895d3 various MSVC fixes in BTL 2008-12-19 15:31:47 +00:00
Benoit Jacob
22875683b9 * extractRotation ---> rotation
* expand the geometry/Transform tests, after Mek's reports
* fix my own stupidity in eigensolver test
2008-12-19 14:52:03 +00:00
Benoit Jacob
e4980616fd SelfAdjointEigenSolver: add operatorSqrt() and operatorInverseSqrt() 2008-12-19 14:15:32 +00:00
Benoit Jacob
84bb868f07 * more MSVC warning fixes from Kenneth Riddile
* actually GCC 4.3.0 has a bug, "deprecated" placed at the end
  of a function prototype doesn't have any effect, moving them to
  the start of the function prototype makes it actually work!
* finish porting the cholesky unit-test to the new LLT/LDLT,
  after the above fix revealed a deprecated warning
2008-12-19 02:59:04 +00:00
Benoit Jacob
f34a4fa335 * forgot to svn add 2 files
* idea of Keir Mierle: make the static assert error msgs UPPERCASE
2008-12-18 21:04:06 +00:00
Benoit Jacob
8106d35408 Patch by Kenneth Riddile: disable MSVC warnings, reenable them outside
of Eigen, and add a MSVC-friendly path in StaticAssert.
2008-12-18 20:48:02 +00:00
Benoit Jacob
fabaa6915b * fix in IO.h, a useless copy was made because of assignment from
Derived to MatrixBase.
* the optimization of eval() for Matrix now consists in a partial
  specialization of ei_eval, which returns a reference type for Matrix.
  No overriding of eval() in Matrix anymore. Consequence: careful,
  ei_eval is no longer guaranteed to give a plain matrix type!
  For that, use ei_plain_matrix_type, or the PlainMatrixType typedef.
* so lots of changes to adapt to that everywhere. Hope this doesn't
  break (too much) MSVC compilation.
* add code examples for the new image() stuff.
* lower a bit the precision for floats in the unit tests as
  we were already doing some workarounds in inverse.cpp and we got some
  failed tests.
2008-12-18 20:36:25 +00:00
Benoit Jacob
b27a3644a2 Macros: add MSVC paths, add an important comment on EIGEN_ALIGN_128 2008-12-18 13:36:31 +00:00
Gael Guennebaud
93f8d56789 improved MSVC support in cmake files (SSE) 2008-12-18 09:07:36 +00:00
Benoit Jacob
15d72d3f9a somehow we had forgotten this very important static assertion... 2008-12-18 03:47:49 +00:00
Gael Guennebaud
9084e2a216 oops I commited bad stuff in the previous commit 2008-12-17 18:54:28 +00:00
Gael Guennebaud
6e138d0069 more MSVC cmake fixes 2008-12-17 18:37:04 +00:00
Gael Guennebaud
4cb63808d4 some cmake fixes for windows and GSL 2008-12-17 17:50:43 +00:00
Gael Guennebaud
c98fe0185e fix non standard non-const std::complex::real/imag issue 2008-12-17 17:31:23 +00:00
Benoit Jacob
5f582aa4e8 fix bad typos, thanks to Kenneth Riddile 2008-12-17 17:14:37 +00:00
Benoit Jacob
c22d10f94c LU class:
* add image() and computeImage() methods, with unit test
* fix a mistake in the definition of KernelResultType
* fix and improve comments
2008-12-17 16:47:55 +00:00
Gael Guennebaud
e3a8431a4a found one bug in the previous ++ changes 2008-12-17 16:04:21 +00:00
Benoit Jacob
89f468671d * replace postfix ++ by prefix ++ wherever that makes sense in Eigen/
* fix some "unused variable" warnings in the tests; there remains a libstdc++ "deprecated"
warning which I haven't looked much into
2008-12-17 14:30:01 +00:00
Benoit Jacob
2110cca431 actually honor EIGEN_STACK_ALLOCATION.
Can set it to 0 to disable stack alloc which guarantees that bad alloc throws exceptions if they are enabled.
2008-12-16 15:44:48 +00:00
Benoit Jacob
38b83b4157 * throw bad_alloc if exceptions are enabled, after patch by Kenneth Riddile
* disable vectorization on MSVC 2005, as it doesn't have all the required intrinsics. require 2008.
2008-12-16 15:17:29 +00:00
Benoit Jacob
50105c3ed6 Hopefully fix compilation of SSE Packetmath with MSVC.
The reason why we didn't realize until now that it didn't compile at all
with MSVC is that before today with MSVC the SSE2 detection didn't work.
2008-12-16 03:48:49 +00:00
Benoit Jacob
0a220721d1 Finally work around enough of MSVC preprocessor dumbness so that it actually detects SSE2 2008-12-15 21:20:40 +00:00
Benoit Jacob
1ad751b991 only enable the "unaligned array" assert if vectorization is enabled.
if vectorization is disabled, WithAlignedOperatorNew is empty!
2008-12-15 20:49:03 +00:00
Benoit Jacob
55b603e457 * fix a bug I introduced in WithAlignedOperatorNew
* add an important comment
2008-12-15 20:14:59 +00:00
Benoit Jacob
763f0a2434 use ei_aligned_malloc and ei_aligned_free also in WithAlignedOperatorNew, so this too should now work with MSVC. 2008-12-15 17:55:11 +00:00
Benoit Jacob
9b1a3d6e19 small optimization (for MSVC) and simplification of ei_alligned_malloc 2008-12-15 17:33:19 +00:00
Benoit Jacob
dd139b92b4 work around the braindead msvc preprocessor 2008-12-15 17:16:22 +00:00
Benoit Jacob
11c8a6bf63 Fix detection of SSE2 with MSVC. 2008-12-15 16:14:54 +00:00
Benoit Jacob
703951d5cd Fix memory alignment (hence vectorization) on MSVC thanks to help from Armin Berres. 2008-12-15 15:54:33 +00:00
Gael Guennebaud
d11c8704e0 oops, forget to remove a line 2008-12-15 12:35:46 +00:00
Gael Guennebaud
a164646c77 more warning fixes by Armin Berres 2008-12-15 12:30:04 +00:00
Benoit Jacob
936eaf600a compilation fix thanks to Dennis Schridde 2008-12-13 21:09:19 +00:00
Gael Guennebaud
ef0cd3a289 one more warning fix, thanks to Armin Berres 2008-12-12 13:50:01 +00:00
Gael Guennebaud
1ed17b037d * fix a couple of warnings (patch from Armin Berres)
* allow Map to map null data
2008-12-12 12:54:45 +00:00
Gael Guennebaud
5015e48361 Sparse module: add a more flexible SparseMatrix::fillrand() function
which allows to fill a matrix with random inner coordinates (makes sense
only when a very few coeffs are inserted per col/row)
2008-12-11 18:26:24 +00:00
Gael Guennebaud
beabf008b0 bugfix in DiagonalProduct: a "DiagonalProduct<SomeXpr>" expression
is now evaluated as a "DiagonalProduct<Matrix<SomeXpr::Eval> >".
Note that currently this only happens in DiagonalProduct.
2008-12-10 19:02:13 +00:00
Gael Guennebaud
ba9a53f9c6 fix compilation issue for 64bit systems (pointer <=> size_t) 2008-12-08 15:07:42 +00:00
Gael Guennebaud
52a30c1d54 fix minor mistake in the inside eigen example 2008-12-08 10:07:09 +00:00
248 changed files with 13252 additions and 3460 deletions

41
.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
qrc_*cxx
*.orig
*.pyc
*.diff
diff
*.save
save
*.old
*.gmo
*.qm
core
core.*
*.bak
*~
*.build*
*.moc.*
*.moc
ui_*
CMakeCache.txt
tags
.*.swp
activity.png
*.out
*.php*
*.log
*.orig
*.rej
log
patch
*.patch
a
a.*
lapack/testing
lapack/reference
.*project
.settings
Makefile
!ci/build.gitlab-ci.yml
!scripts/buildtests.in
!Eigen/Core
!Eigen/src/Core

28
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,28 @@
# This file is part of Eigen, a lightweight C++ template library
# for linear algebra.
#
# Copyright (C) 2023, The Eigen Authors
#
# This Source Code Form is subject to the terms of the Mozilla
# Public License v. 2.0. If a copy of the MPL was not distributed
# with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
stages:
- build
- deploy
variables:
# CMake build directory.
EIGEN_CI_BUILDDIR: .build
# Specify the CMake build target.
EIGEN_CI_BUILD_TARGET: ""
# If a test regex is specified, that will be selected.
# Otherwise, we will try a label if specified.
EIGEN_CI_CTEST_REGEX: ""
EIGEN_CI_CTEST_LABEL: ""
EIGEN_CI_CTEST_ARGS: ""
include:
- "/ci/common.gitlab-ci.yml"
- "/ci/build.linux.gitlab-ci.yml"
- "/ci/deploy.gitlab-ci.yml"

25
.hgignore Normal file
View File

@@ -0,0 +1,25 @@
syntax: glob
qrc_*cxx
*.orig
*.pyc
*.diff
diff
*.save
save
*.old
*.gmo
*.qm
core
core.*
*.bak
*~
build*
*.moc.*
*.moc
ui_*
CMakeCache.txt
tags
.*.swp
activity.png
*.out
*.php*

View File

@@ -1,18 +1,14 @@
project(Eigen)
set(EIGEN_VERSION_NUMBER "2.0-beta2")
cmake_minimum_required(VERSION 2.6.2)
#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)
set(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
CACHE PATH
"The directory where we install the header files"
FORCE)
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)
set(EIGEN_VERSION_NUMBER "2.0.17")
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
@@ -22,43 +18,117 @@ 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(NOT WIN32)
option(EIGEN_BUILD_PKGCONFIG "Build pkg-config .pc file for Eigen" ON)
endif(NOT WIN32)
if(EIGEN_BUILD_LIB)
option(EIGEN_TEST_LIB "Build the unit tests using the library (disable -pedantic)" OFF)
endif(EIGEN_BUILD_LIB)
#############################################################################
# find how to link to the standard libraries #
#############################################################################
find_package(StandardMathLibrary)
set(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO "")
if(NOT STANDARD_MATH_LIBRARY_FOUND)
message(FATAL_ERROR
"Can't link to the standard math library. Please report to the Eigen developers, telling them about your platform.")
else()
if(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO)
set(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO "${EIGEN_STANDARD_LIBRARIES_TO_LINK_TO} ${STANDARD_MATH_LIBRARY}")
else()
set(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO "${STANDARD_MATH_LIBRARY}")
endif()
endif()
if(EIGEN_STANDARD_LIBRARIES_TO_LINK_TO)
message(STATUS "Standard libraries to link to explicitly: ${EIGEN_STANDARD_LIBRARIES_TO_LINK_TO}")
else()
message(STATUS "Standard libraries to link to explicitly: none")
endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_SYSTEM_NAME MATCHES Linux)
include(CheckCXXCompilerFlag)
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")
check_cxx_compiler_flag("-Wextra" has_wextra)
if(has_wextra)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
endif()
if(NOT EIGEN_TEST_LIB)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif(NOT EIGEN_TEST_LIB)
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)
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)
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})
if(EIGEN_BUILD_PKGCONFIG)
configure_file(eigen2.pc.in eigen2.pc) # uses INCLUDE_INSTALL_DIR
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen2.pc
DESTINATION share/pkgconfig
)
endif(EIGEN_BUILD_PKGCONFIG)
add_subdirectory(Eigen)
add_subdirectory(unsupported)
if(EIGEN_BUILD_TESTS)
include(CTest)
add_subdirectory(test)
endif(EIGEN_BUILD_TESTS)

13
CTestConfig.cmake Normal file
View 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(CTest)
set(CTEST_PROJECT_NAME "Eigen 2.0")
set(CTEST_NIGHTLY_START_TIME "06:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "eigen.tuxfamily.org")
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen+2.0")
set(CTEST_DROP_SITE_CDASH TRUE)

View File

@@ -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,7 +26,7 @@ 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"
@@ -32,4 +34,6 @@ namespace Eigen {
} // namespace Eigen
#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_ARRAY_MODULE_H

View File

@@ -1,4 +1,7 @@
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 NewStdVector
Eigen Dense)
if(EIGEN_BUILD_LIB)
set(Eigen_SRCS
@@ -20,12 +23,6 @@ if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1 -O2")
endif(CMAKE_COMPILER_IS_GNUCXX)
set(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
CACHE PATH
"The directory where we install the header files"
FORCE)
install(FILES
${Eigen_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen

View File

@@ -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,6 +17,9 @@
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::llt(),
@@ -29,14 +34,12 @@ namespace Eigen {
#include "src/Array/Functors.h"
#include "src/Cholesky/LLT.h"
#include "src/Cholesky/LDLT.h"
#include "src/Cholesky/Cholesky.h"
#include "src/Cholesky/CholeskyWithoutSquareRoot.h"
} // namespace Eigen
#define EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MATRIXTYPE,PREFIX) \
PREFIX template class Cholesky<MATRIXTYPE>; \
PREFIX template class CholeskyWithoutSquareRoot<MATRIXTYPE>
PREFIX template class LLT<MATRIXTYPE>; \
PREFIX template class LDLT<MATRIXTYPE>
#define EIGEN_CHOLESKY_MODULE_INSTANTIATE(PREFIX) \
EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix2f,PREFIX); \
@@ -57,4 +60,6 @@ namespace Eigen {
} // namespace Eigen
#endif
#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_CHOLESKY_MODULE_H

View File

@@ -1,18 +1,35 @@
#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)
// FIXME: this check should not be against __QNXNTO__, which is also defined
// while compiling with GCC for QNX target. Better solution is welcome!
#if defined(__GNUC__) && !defined(__QNXNTO__)
#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
#ifndef EIGEN_DONT_VECTORIZE
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
// 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
#if !defined(EIGEN_DONT_VECTORIZE) && !defined(EIGEN_DONT_ALIGN)
#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 +40,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
@@ -35,6 +52,7 @@
#endif
#endif
#include <cstddef>
#include <cstdlib>
#include <cmath>
#include <complex>
@@ -43,9 +61,29 @@
#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 {
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
// ensure QNX/QCC support
using std::size_t;
/** \defgroup Core_Module Core module
* This is the main module of Eigen providing dense matrix and vector support
* (both fixed and dynamic size) with all the features corresponding to a BLAS library
@@ -69,9 +107,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 +119,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 +156,6 @@ namespace Eigen {
} // namespace Eigen
#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_CORE_H

8
Eigen/Dense Normal file
View 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
View File

@@ -0,0 +1,2 @@
#include "Dense"
#include "Sparse"

View File

@@ -1,6 +1,10 @@
#ifndef EIGEN_GEOMETRY_MODULE_H
#define EIGEN_GEOMETRY_MODULE_H
#include "Core"
#include "src/Core/util/DisableMSVCWarnings.h"
#include "Array"
#include <limits>
@@ -10,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
@@ -39,4 +46,6 @@ namespace Eigen {
} // namespace Eigen
#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_GEOMETRY_MODULE_H

View File

@@ -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

View File

@@ -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

168
Eigen/NewStdVector Normal file
View File

@@ -0,0 +1,168 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.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_STDVECTOR_MODULE_H
#define EIGEN_STDVECTOR_MODULE_H
#include "Core"
#include <vector>
namespace Eigen {
// This one is needed to prevent reimplementing the whole std::vector.
template <class T>
class aligned_allocator_indirection : public aligned_allocator<T>
{
public:
typedef std::size_t size_type;
typedef std::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<class U>
struct rebind
{
typedef aligned_allocator_indirection<U> other;
};
aligned_allocator_indirection() throw() {}
aligned_allocator_indirection(const aligned_allocator_indirection& ) throw() : aligned_allocator<T>() {}
aligned_allocator_indirection(const aligned_allocator<T>& ) throw() {}
template<class U>
aligned_allocator_indirection(const aligned_allocator_indirection<U>& ) throw() {}
template<class U>
aligned_allocator_indirection(const aligned_allocator<U>& ) throw() {}
~aligned_allocator_indirection() throw() {}
};
#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; \
typedef typename vector_base::const_iterator const_iterator; \
explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {} \
template<typename InputIterator> \
vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
: vector_base(first, last, a) {} \
vector(const vector& c) : vector_base(c) {} \
explicit 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>
class vector<T,Eigen::aligned_allocator<T> >
: public vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
{
typedef vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
Eigen::aligned_allocator_indirection<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());
}
void push_back(const value_type& x)
{ vector_base::push_back(x); }
using vector_base::insert;
iterator insert(const_iterator position, const value_type& x)
{ return vector_base::insert(position,x); }
void insert(const_iterator position, size_type new_size, const value_type& x)
{ vector_base::insert(position, new_size, x); }
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
// workaround GCC std::vector implementation
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);
}
#elif defined(_GLIBCXX_VECTOR) && (!EIGEN_GNUC_AT_LEAST(4,1))
// Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
// no no need to workaround !
using vector_base::resize;
#else
// either GCC 4.1 or non-GCC
// default implementation which should always work.
void resize(size_type new_size, const value_type& x)
{
if (new_size < vector_base::size())
vector_base::erase(vector_base::begin() + new_size, vector_base::end());
else if (new_size > vector_base::size())
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
}
#endif
};
}
#endif // EIGEN_STDVECTOR_MODULE_H

View File

@@ -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

49
Eigen/QtAlignedMalloc Normal file
View File

@@ -0,0 +1,49 @@
#ifndef EIGEN_QTMALLOC_MODULE_H
#define EIGEN_QTMALLOC_MODULE_H
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
#ifdef QVECTOR_H
#error You must include <Eigen/QtAlignedMalloc> before <QtCore/QVector>.
#endif
#ifdef Q_DECL_IMPORT
#define Q_DECL_IMPORT_ORIG Q_DECL_IMPORT
#undef Q_DECL_IMPORT
#define Q_DECL_IMPORT
#else
#define Q_DECL_IMPORT
#endif
#include "Core"
#include <QtCore/QVector>
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
#ifdef Q_DECL_IMPORT_ORIG
#define Q_DECL_IMPORT Q_DECL_IMPORT_ORIG
#undef Q_DECL_IMPORT_ORIG
#else
#undef Q_DECL_IMPORT
#endif
#endif // EIGEN_QTMALLOC_MODULE_H

View File

@@ -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

View File

@@ -2,6 +2,9 @@
#define EIGEN_SPARSE_MODULE_H
#include "Core"
#include "src/Core/util/DisableMSVCWarnings.h"
#include <vector>
#include <map>
#include <cstdlib>
@@ -19,7 +22,6 @@
#endif
#ifdef EIGEN_TAUCS_SUPPORT
// taucs.h declares a lot of mess
#define isnan
#define finite
@@ -37,7 +39,9 @@
#ifdef max
#undef max
#endif
#ifdef complex
#undef complex
#endif
#endif
#ifdef EIGEN_SUPERLU_SUPPORT
@@ -67,18 +71,39 @@
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"
@@ -102,4 +127,6 @@ namespace Eigen {
} // namespace Eigen
#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_SPARSE_MODULE_H

147
Eigen/StdVector Normal file
View File

@@ -0,0 +1,147 @@
#ifdef EIGEN_USE_NEW_STDVECTOR
#include "NewStdVector"
#else
#ifndef EIGEN_STDVECTOR_MODULE_H
#define EIGEN_STDVECTOR_MODULE_H
#if defined(_GLIBCXX_VECTOR) || defined(_VECTOR_)
#error you must include <Eigen/StdVector> before <vector>. Also note that <Eigen/Sparse> includes <vector>, so it must be included after <Eigen/StdVector> too.
#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,2)
// workaround GCC std::vector implementation
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);
}
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1)
void resize(size_type __new_size, const value_type& __x)
{
if (__new_size < vector_base::size())
vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
else
vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
}
#else
// Before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
// so no need for a workaround !
using vector_base::resize;
#endif
};
}
#endif // EIGEN_STDVECTOR_MODULE_H
#endif // EIGEN_USE_NEW_STDVECTOR

View File

@@ -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>().template cast<int>().sum();
}
#endif // EIGEN_ALLANDANY_H

View File

@@ -43,6 +43,8 @@ struct ei_scalar_add_op {
inline const PacketScalar packetOp(const PacketScalar& a) const
{ return ei_padd(a, ei_pset1(m_other)); }
const Scalar m_other;
private:
ei_scalar_add_op& operator=(const ei_scalar_add_op&);
};
template<typename Scalar>
struct ei_functor_traits<ei_scalar_add_op<Scalar> >
@@ -138,6 +140,8 @@ struct ei_scalar_pow_op {
inline ei_scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
inline Scalar operator() (const Scalar& a) const { return ei_pow(a, m_exponent); }
const Scalar m_exponent;
private:
ei_scalar_pow_op& operator=(const ei_scalar_pow_op&);
};
template<typename Scalar>
struct ei_functor_traits<ei_scalar_pow_op<Scalar> >
@@ -200,7 +204,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>

View File

@@ -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,7 +108,7 @@ 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(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
@@ -114,6 +118,7 @@ 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>
@@ -128,6 +133,8 @@ struct ei_member_redux {
inline result_type operator()(const MatrixBase<Derived>& mat) const
{ return mat.redux(m_functor); }
const BinaryOp m_functor;
private:
ei_member_redux& operator=(const ei_member_redux&);
};
/** \array_module \ingroup Array
@@ -153,13 +160,15 @@ template<typename ExpressionType, int Direction> class PartialRedux
public:
typedef typename ei_traits<ExpressionType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
template<template<typename _Scalar> class Functor> struct ReturnType
template<template<typename _Scalar> class Functor,
typename Scalar = typename ei_traits<ExpressionType>::Scalar> struct ReturnType
{
typedef PartialReduxExpr<ExpressionType,
Functor<typename ei_traits<ExpressionType>::Scalar>,
Functor<Scalar>,
Direction
> Type;
};
@@ -172,6 +181,8 @@ template<typename ExpressionType, int Direction> class PartialRedux
> Type;
};
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */
@@ -208,7 +219,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
* Output: \verbinclude PartialRedux_squaredNorm.out
*
* \sa MatrixBase::squaredNorm() */
const typename ReturnType<ei_member_squaredNorm>::Type squaredNorm() const
const typename ReturnType<ei_member_squaredNorm,RealScalar>::Type squaredNorm() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the norm
@@ -218,7 +229,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
* Output: \verbinclude PartialRedux_norm.out
*
* \sa MatrixBase::norm() */
const typename ReturnType<ei_member_norm>::Type norm() const
const typename ReturnType<ei_member_norm,RealScalar>::Type norm() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the sum
@@ -244,9 +255,48 @@ 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;
private:
PartialRedux& operator=(const PartialRedux&);
};
/** \array_module

View File

@@ -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

View File

@@ -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>

View File

@@ -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)

View File

@@ -1,165 +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
*
* \deprecated this class has been renamed LLT
*/
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);
}
/** \deprecated */
inline Part<MatrixType, Lower> matrixL(void) const { return m_matrix; }
/** \deprecated */
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
template<typename Derived>
typename Derived::Eval solve(const MatrixBase<Derived> &b) const EIGEN_DEPRECATED;
template<typename RhsDerived, typename ResDerived>
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *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_isPositiveDefinite;
};
/** \deprecated */
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).squaredNorm();
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;
}
}
}
/** \deprecated */
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());
typename ei_eval_to_column_major<Derived>::type x(b);
solveInPlace(x);
return x;
}
/** \deprecated */
template<typename MatrixType>
template<typename RhsDerived, typename ResDerived>
bool Cholesky<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
{
const int size = m_matrix.rows();
ei_assert(size==b.rows() && "Cholesky::solve(): invalid number of rows of the right hand side matrix b");
return solveInPlace((*result) = b);
}
/** \deprecated */
template<typename MatrixType>
template<typename Derived>
bool Cholesky<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
{
const int size = m_matrix.rows();
ei_assert(size==bAndX.rows());
if (!m_isPositiveDefinite)
return false;
matrixL().solveTriangularInPlace(bAndX);
m_matrix.adjoint().template part<Upper>().solveTriangularInPlace(bAndX);
return true;
}
/** \cholesky_module
* \deprecated has been renamed llt()
*/
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

View File

@@ -1,184 +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_WITHOUT_SQUARE_ROOT_H
#define EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H
/** \deprecated \ingroup Cholesky_Module
*
* \class CholeskyWithoutSquareRoot
*
* \deprecated this class has been renamed LDLT
*/
template<typename MatrixType> class CholeskyWithoutSquareRoot
{
public:
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
CholeskyWithoutSquareRoot(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; }
/** \returns the coefficients of the diagonal matrix D */
inline DiagonalCoeffs<MatrixType> vectorD(void) const { return m_matrix.diagonal(); }
/** \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 EIGEN_DEPRECATED;
template<typename RhsDerived, typename ResDerived>
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
template<typename Derived>
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
void compute(const MatrixType& matrix);
protected:
/** \internal
* Used to compute and store the cholesky decomposition A = L D L^* = U^* D U.
* The strict upper part is used during the decomposition, the strict lower
* part correspond to the coefficients of L (its diagonal is equal to 1 and
* is not stored), and the diagonal entries correspond to D.
*/
MatrixType m_matrix;
bool m_isPositiveDefinite;
};
/** \deprecated */
template<typename MatrixType>
void CholeskyWithoutSquareRoot<MatrixType>::compute(const MatrixType& a)
{
assert(a.rows()==a.cols());
const int size = a.rows();
m_matrix.resize(size, size);
m_isPositiveDefinite = true;
const RealScalar eps = ei_sqrt(precision<Scalar>());
if (size<=1)
{
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
// 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);
// Note that, in this algorithm the rows of the strict upper part of m_matrix is used to store
// column vector, thus the strange .conjugate() and .transpose()...
m_matrix.row(0) = a.row(0).conjugate();
m_matrix.col(0).end(size-1) = m_matrix.row(0).end(size-1) / m_matrix.coeff(0,0);
for (int j = 1; j < size; ++j)
{
RealScalar tmp = ei_real(a.coeff(j,j) - (m_matrix.row(j).start(j) * m_matrix.col(j).start(j).conjugate()).coeff(0,0));
m_matrix.coeffRef(j,j) = tmp;
if (tmp < eps)
{
m_isPositiveDefinite = false;
return;
}
int endSize = size-j-1;
if (endSize>0)
{
_temporary.end(endSize) = ( m_matrix.block(j+1,0, endSize, j)
* m_matrix.col(j).start(j).conjugate() ).lazy();
m_matrix.row(j).end(endSize) = a.row(j).end(endSize).conjugate()
- _temporary.end(endSize).transpose();
m_matrix.col(j).end(endSize) = m_matrix.row(j).end(endSize) / tmp;
}
}
}
/** \deprecated */
template<typename MatrixType>
template<typename Derived>
typename Derived::Eval CholeskyWithoutSquareRoot<MatrixType>::solve(const MatrixBase<Derived> &b) 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))
);
}
/** \deprecated */
template<typename MatrixType>
template<typename RhsDerived, typename ResDerived>
bool CholeskyWithoutSquareRoot<MatrixType>
::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
{
const int size = m_matrix.rows();
ei_assert(size==b.rows() && "Cholesky::solve(): invalid number of rows of the right hand side matrix b");
*result = b;
return solveInPlace(*result);
}
/** \deprecated */
template<typename MatrixType>
template<typename Derived>
bool CholeskyWithoutSquareRoot<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
{
const int size = m_matrix.rows();
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<UnitUpper>().solveTriangularInPlace(bAndX);
return true;
}
/** \cholesky_module
* \deprecated has been renamed ldlt()
*/
template<typename Derived>
inline const CholeskyWithoutSquareRoot<typename MatrixBase<Derived>::EvalType>
MatrixBase<Derived>::choleskyNoSqrt() const
{
return derived();
}
#endif // EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H

View File

@@ -60,7 +60,7 @@ template<typename MatrixType> class LDLT
}
/** \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,8 @@ template<typename MatrixType> class LDLT
/** \returns true if the matrix is positive definite */
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
template<typename RhsDerived, typename ResDerived>
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
template<typename RhsDerived, typename ResultType>
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
template<typename Derived>
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
@@ -96,8 +96,7 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
assert(a.rows()==a.cols());
const int size = a.rows();
m_matrix.resize(size, size);
m_isPositiveDefinite = true;
const RealScalar eps = ei_sqrt(precision<Scalar>());
m_isPositiveDefinite = true; // always true. This decomposition is not rank-revealing anyway.
if (size<=1)
{
@@ -121,12 +120,6 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
RealScalar tmp = ei_real(a.coeff(j,j) - (m_matrix.row(j).start(j) * m_matrix.col(j).start(j).conjugate()).coeff(0,0));
m_matrix.coeffRef(j,j) = tmp;
if (tmp < eps)
{
m_isPositiveDefinite = false;
return;
}
int endSize = size-j-1;
if (endSize>0)
{
@@ -136,7 +129,8 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
m_matrix.row(j).end(endSize) = a.row(j).end(endSize).conjugate()
- _temporary.end(endSize).transpose();
m_matrix.col(j).end(endSize) = m_matrix.row(j).end(endSize) / tmp;
if(tmp != RealScalar(0))
m_matrix.col(j).end(endSize) = m_matrix.row(j).end(endSize) / tmp;
}
}
}
@@ -152,9 +146,9 @@ void LDLT<MatrixType>::compute(const MatrixType& a)
* \sa LDLT::solveInPlace(), MatrixBase::ldlt()
*/
template<typename MatrixType>
template<typename RhsDerived, typename ResDerived>
template<typename RhsDerived, typename ResultType>
bool LDLT<MatrixType>
::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
::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");
@@ -181,7 +175,7 @@ bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
return false;
matrixL().solveTriangularInPlace(bAndX);
bAndX = (m_matrix.cwise().inverse().template part<Diagonal>() * bAndX).lazy();
m_matrix.adjoint().template part<UnitUpper>().solveTriangularInPlace(bAndX);
m_matrix.adjoint().template part<UnitUpperTriangular>().solveTriangularInPlace(bAndX);
return true;
}
@@ -189,10 +183,10 @@ bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
* \returns the Cholesky decomposition without square root of \c *this
*/
template<typename Derived>
inline const LDLT<typename MatrixBase<Derived>::EvalType>
inline const LDLT<typename MatrixBase<Derived>::PlainMatrixType>
MatrixBase<Derived>::ldlt() const
{
return derived();
return LDLT<PlainMatrixType>(derived());
}
#endif // EIGEN_LDLT_H

View File

@@ -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>
//
@@ -41,11 +41,16 @@
* 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.
* 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:
@@ -60,20 +65,33 @@ template<typename MatrixType> class LLT
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_matrix(matrix.rows(), matrix.cols()),
m_isInitialized(false)
{
compute(matrix);
}
/** \returns the lower triangular matrix L */
inline Part<MatrixType, Lower> matrixL(void) const { return m_matrix; }
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; }
/** \returns true if the matrix is positive definite */
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
template<typename RhsDerived, typename ResDerived>
bool solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const;
template<typename RhsDerived, typename ResultType>
bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
template<typename Derived>
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
@@ -86,6 +104,7 @@ template<typename MatrixType> class LLT
* The strict upper part is not used and even not initialized.
*/
MatrixType m_matrix;
bool m_isInitialized;
bool m_isPositiveDefinite;
};
@@ -95,24 +114,35 @@ 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);
const RealScalar eps = ei_sqrt(precision<Scalar>());
// 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_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));
if(size==1)
{
m_isInitialized = true;
return;
}
if(ei_real(m_matrix.coeff(0,0))>0)
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).squaredNorm();
x = ei_real(tmp);
if (x < eps || (!ei_isMuchSmallerThan(ei_imag(tmp), RealScalar(1))))
x = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).squaredNorm();
if (x <= cutoff)
{
m_isPositiveDefinite = false;
return;
continue;
}
m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
int endSize = size-j-1;
@@ -127,12 +157,14 @@ void LLT<MatrixType>::compute(const MatrixType& a)
- 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 in case of success, false otherwise.
* \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.
@@ -143,9 +175,10 @@ void LLT<MatrixType>::compute(const MatrixType& a)
* \sa LLT::solveInPlace(), MatrixBase::llt()
*/
template<typename MatrixType>
template<typename RhsDerived, typename ResDerived>
bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDerived> *result) const
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);
@@ -155,6 +188,8 @@ bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, MatrixBase<ResDeriv
*
* \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.
*
@@ -164,12 +199,11 @@ 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());
if (!m_isPositiveDefinite)
return false;
matrixL().solveTriangularInPlace(bAndX);
m_matrix.adjoint().template part<Upper>().solveTriangularInPlace(bAndX);
m_matrix.adjoint().template part<UpperTriangular>().solveTriangularInPlace(bAndX);
return true;
}
@@ -177,10 +211,10 @@ bool LLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
* \returns the LLT decomposition of \c *this
*/
template<typename Derived>
inline const LLT<typename MatrixBase<Derived>::EvalType>
inline const LLT<typename MatrixBase<Derived>::PlainMatrixType>
MatrixBase<Derived>::llt() const
{
return LLT<typename ei_eval<Derived>::type>(derived());
return LLT<PlainMatrixType>(derived());
}
#endif // EIGEN_LLT_H

View File

@@ -90,6 +90,28 @@ public:
? ( int(MayUnrollCompletely) && int(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) )
: int(NoUnrolling)
};
#ifdef EIGEN_DEBUG_ASSIGN
#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
static void debug()
{
EIGEN_DEBUG_VAR(DstIsAligned)
EIGEN_DEBUG_VAR(SrcIsAligned)
EIGEN_DEBUG_VAR(SrcAlignment)
EIGEN_DEBUG_VAR(InnerSize)
EIGEN_DEBUG_VAR(InnerMaxSize)
EIGEN_DEBUG_VAR(PacketSize)
EIGEN_DEBUG_VAR(MightVectorize)
EIGEN_DEBUG_VAR(MayInnerVectorize)
EIGEN_DEBUG_VAR(MayLinearVectorize)
EIGEN_DEBUG_VAR(MaySliceVectorize)
EIGEN_DEBUG_VAR(Vectorization)
EIGEN_DEBUG_VAR(UnrollingLimit)
EIGEN_DEBUG_VAR(MayUnrollCompletely)
EIGEN_DEBUG_VAR(MayUnrollInner)
EIGEN_DEBUG_VAR(Unrolling)
}
#endif
};
/***************************************************************************
@@ -112,7 +134,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 +144,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 +163,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 +183,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 +194,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 +213,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 +232,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 +250,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 +260,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 +278,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 +297,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 +307,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 +325,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 +333,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 +341,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 +349,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 +367,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 +375,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 +400,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 +419,22 @@ 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)
{
#ifdef EIGEN_DEBUG_ASSIGN
ei_assign_traits<Derived, OtherDerived>::debug();
#endif
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 +444,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());

View File

@@ -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==int(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());
}
@@ -456,7 +453,7 @@ MatrixBase<Derived>::end(int size) const
* \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_segment.cpp

View File

@@ -33,7 +33,7 @@ struct ei_L2_block_traits {
#ifndef EIGEN_EXTERN_INSTANTIATIONS
template<typename Scalar>
static void ei_cache_friendly_product(
void ei_cache_friendly_product(
int _rows, int _cols, int depth,
bool _lhsRowMajor, const Scalar* _lhs, int _lhsStride,
bool _rhsRowMajor, const Scalar* _rhs, int _rhsStride,
@@ -81,10 +81,10 @@ 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));
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (std::size_t(res)%16==0));
const int remainingSize = depth % PacketSize;
const int size = depth - remainingSize; // third dimension of the product clamped to packet boundaries
@@ -92,12 +92,12 @@ static void ei_cache_friendly_product(
const int l2BlockCols = MaxL2BlockSize > cols ? cols : MaxL2BlockSize;
const int l2BlockSize = MaxL2BlockSize > size ? size : MaxL2BlockSize;
const int l2BlockSizeAligned = (1 + std::max(l2BlockSize,l2BlockCols)/PacketSize)*PacketSize;
const bool needRhsCopy = (PacketSize>1) && ((rhsStride%PacketSize!=0) || (size_t(rhs)%16!=0));
const bool needRhsCopy = (PacketSize>1) && ((rhsStride%PacketSize!=0) || (std::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)
@@ -172,7 +172,7 @@ static void ei_cache_friendly_product(
for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
{
ei_internal_assert(l2BlockSizeAligned*(l1j-l2j)+(l2blockSizeEnd-l2k) < l2BlockSizeAligned*l2BlockSizeAligned);
memcpy(rhsCopy+l2BlockSizeAligned*(l1j-l2j),&(rhs[l1j*rhsStride+l2k]),(l2blockSizeEnd-l2k)*sizeof(Scalar));
std::memcpy(rhsCopy+l2BlockSizeAligned*(l1j-l2j),&(rhs[l1j*rhsStride+l2k]),(l2blockSizeEnd-l2k)*sizeof(Scalar));
}
// for each bw x 1 result's block
@@ -180,7 +180,7 @@ static void ei_cache_friendly_product(
{
int offsetblock = l2k * (l2blockRowEnd-l2i) + (l1i-l2i)*(l2blockSizeEnd-l2k) - l2k*MaxBlockRows;
const Scalar* EIGEN_RESTRICT localB = &block[offsetblock];
for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
{
const Scalar* EIGEN_RESTRICT rhsColumn;
@@ -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
@@ -352,7 +352,7 @@ static void ei_cache_friendly_product(
* TODO: since rhs gets evaluated only once, no need to evaluate it
*/
template<typename Scalar, typename RhsType>
static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
int size,
const Scalar* lhs, int lhsStride,
const RhsType& rhs,
@@ -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);
@@ -396,8 +397,8 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
int skipColumns = 0;
if (PacketSize>1)
{
ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
ei_internal_assert(std::size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
while (skipColumns<PacketSize &&
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%PacketSize))
++skipColumns;
@@ -413,12 +414,12 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
// note that the skiped columns are processed later.
}
ei_internal_assert((alignmentPattern==NoneAligned) || (size_t(lhs+alignedStart+lhsStride*skipColumns)%sizeof(Packet))==0);
ei_internal_assert((alignmentPattern==NoneAligned) || (std::size_t(lhs+alignedStart+lhsStride*skipColumns)%sizeof(Packet))==0);
}
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,11 +512,11 @@ 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
if ((size_t(lhs0+alignedStart)%sizeof(Packet))==0)
if ((std::size_t(lhs0+alignedStart)%sizeof(Packet))==0)
for (int j = alignedStart;j<alignedSize;j+=PacketSize)
ei_pstore(&res[j], ei_pmadd(ptmp0,ei_pload(&lhs0[j]),ei_pload(&res[j])));
else
@@ -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)
@@ -541,7 +542,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
// TODO add peeling to mask unaligned load/stores
template<typename Scalar, typename ResType>
static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
const Scalar* lhs, int lhsStride,
const Scalar* rhs, int rhsSize,
ResType& res)
@@ -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);
ei_internal_assert(std::size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
while (skipRows<PacketSize &&
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%PacketSize))
++skipRows;
@@ -602,12 +603,12 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
// note that the skiped columns are processed later.
}
ei_internal_assert((alignmentPattern==NoneAligned) || PacketSize==1
|| (size_t(lhs+alignedStart+lhsStride*skipRows)%sizeof(Packet))==0);
|| (std::size_t(lhs+alignedStart+lhsStride*skipRows)%sizeof(Packet))==0);
}
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,20 +709,20 @@ 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)
{
// process aligned rhs coeffs
if ((size_t(lhs0+alignedStart)%sizeof(Packet))==0)
if ((std::size_t(lhs0+alignedStart)%sizeof(Packet))==0)
for (int j = alignedStart;j<alignedSize;j+=PacketSize)
ptmp0 = ei_pmadd(ei_pload(&rhs[j]), ei_pload(&lhs0[j]), ptmp0);
else
@@ -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;
}

View File

@@ -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,13 +306,15 @@ 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
@@ -322,7 +324,7 @@ inline void MatrixBase<Derived>::writePacket
*/
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());
@@ -338,7 +340,7 @@ inline void MatrixBase<Derived>::copyCoeff(int row, int col, const MatrixBase<Ot
*/
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);
@@ -353,7 +355,7 @@ inline void MatrixBase<Derived>::copyCoeff(int index, const MatrixBase<OtherDeri
*/
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());
@@ -370,11 +372,13 @@ inline void MatrixBase<Derived>::copyPacket(int row, int col, const MatrixBase<O
*/
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

View File

@@ -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>
@@ -116,6 +116,9 @@ struct CommaInitializer
int m_row; // current row id
int m_col; // current col id
int m_currentBlockRows; // current block height
private:
CommaInitializer& operator=(const CommaInitializer&);
};
/** \anchor MatrixBaseCommaInitRef
@@ -128,7 +131,7 @@ struct CommaInitializer
*
* Example: \include MatrixBase_set.cpp
* Output: \verbinclude MatrixBase_set.out
*
*
* \sa CommaInitializer::finished(), class CommaInitializer
*/
template<typename Derived>

View File

@@ -32,7 +32,7 @@ namespace Eigen
{
#define EIGEN_INSTANTIATE_PRODUCT(TYPE) \
template static void ei_cache_friendly_product<TYPE>( \
template void ei_cache_friendly_product<TYPE>( \
int _rows, int _cols, int depth, \
bool _lhsRowMajor, const TYPE* _lhs, int _lhsStride, \
bool _rhsRowMajor, const TYPE* _rhs, int _rhsStride, \

View File

@@ -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,8 +171,16 @@ 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;
private:
Cwise& operator=(const Cwise&);
};
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations

View File

@@ -54,7 +54,6 @@ struct ei_traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
typename Rhs::Scalar
)
>::type Scalar;
typedef typename Lhs::Nested LhsNested;
typedef typename Rhs::Nested RhsNested;
typedef typename ei_unref<LhsNested>::type _LhsNested;
@@ -87,45 +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
// 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_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)
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));
}
@@ -144,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
{
@@ -158,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;
@@ -174,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());
@@ -186,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;
@@ -201,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
@@ -216,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
@@ -231,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());
@@ -246,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());
@@ -267,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);

View File

@@ -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,7 +699,7 @@ 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)
return BasisReturnType(SquareMatrixType::Identity(size,size), i);
@@ -574,7 +714,7 @@ 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)
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

View File

@@ -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());
@@ -176,14 +169,14 @@ MatrixBase<Derived>::conjugate() const
*
* \sa imag() */
template<typename Derived>
inline const typename MatrixBase<Derived>::RealReturnType
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>
inline const typename MatrixBase<Derived>::ImagReturnType
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
@@ -195,7 +188,7 @@ MatrixBase<Derived>::imag() const { return derived(); }
*/
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();
@@ -203,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>
@@ -212,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>
@@ -220,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;

View File

@@ -47,11 +47,11 @@ struct ei_traits<DiagonalCoeffs<MatrixType> >
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
RowsAtCompileTime = int(MatrixType::SizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,
: EIGEN_SIZE_MIN(MatrixType::RowsAtCompileTime,
MatrixType::ColsAtCompileTime),
ColsAtCompileTime = 1,
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
: EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime,
: EIGEN_SIZE_MIN(MatrixType::MaxRowsAtCompileTime,
MatrixType::MaxColsAtCompileTime),
MaxColsAtCompileTime = 1,
Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit),

View File

@@ -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;

View File

@@ -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));
}
}

View File

@@ -156,7 +156,7 @@ struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
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;
}
@@ -211,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);
}
@@ -258,52 +258,30 @@ 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.
*
* \note This is \em not the \em l2 norm, but its square.
*
* \deprecated Use squaredNorm() instead. This norm2() function is kept only for compatibility and will be removed in Eigen 2.0.
*
* \only_for_vectors
*
* \sa dot(), norm()
*/
template<typename Derived>
EIGEN_DEPRECATED inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm2() const
{
return ei_real(dot(*this));
}
/** \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>::squaredNorm() const
{
return ei_real(dot(*this));
return ei_real((*this).cwise().abs2().sum());
}
/** \returns the \em l2 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(), normSquared()
* \sa dot(), squaredNorm()
*/
template<typename Derived>
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
@@ -318,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;
@@ -370,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).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;
}

View File

@@ -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
@@ -118,6 +109,9 @@ template<typename ExpressionType, unsigned int Added, unsigned int Removed> clas
protected:
ExpressionTypeNested m_matrix;
private:
Flagged& operator=(const Flagged&);
};
/** \returns an expression of *this with added flags

View File

@@ -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,7 +236,7 @@ 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> >
@@ -250,7 +250,7 @@ struct ei_functor_traits<ei_scalar_real_op<Scalar> >
template<typename Scalar>
struct ei_scalar_imag_op EIGEN_EMPTY_STRUCT {
typedef typename NumTraits<Scalar>::Real result_type;
inline result_type operator() (const Scalar& a) const { return ei_imag(a); }
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> >
@@ -273,12 +273,14 @@ 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;
private:
ei_scalar_multiple_op& operator=(const ei_scalar_multiple_op&);
};
template<typename Scalar>
struct ei_functor_traits<ei_scalar_multiple_op<Scalar> >
@@ -288,12 +290,14 @@ 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;
private:
ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
};
template<typename Scalar>
struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,true> >
@@ -302,10 +306,12 @@ 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;
private:
ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
};
template<typename Scalar>
struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,false> >
@@ -321,8 +327,10 @@ 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) {}
private:
ei_scalar_quotient1_op& operator=(const ei_scalar_quotient1_op&);
};
// nullary functors
@@ -330,29 +338,41 @@ 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;
private:
ei_scalar_constant_op& operator=(const ei_scalar_constant_op&);
};
template<typename Scalar>
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 }; };
// FIXME 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

View File

@@ -202,7 +202,7 @@ struct ei_fuzzy_selector<Derived,OtherDerived,false>
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++)
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;
@@ -211,7 +211,7 @@ struct ei_fuzzy_selector<Derived,OtherDerived,false>
static bool isMuchSmallerThan(const Derived& self, const RealScalar& other, RealScalar prec)
{
typename Derived::Nested nested(self);
for(int i = 0; i < self.cols(); i++)
for(int i = 0; i < self.cols(); ++i)
if(nested.col(i).squaredNorm() > ei_abs2(other * prec))
return false;
return true;
@@ -222,7 +222,7 @@ struct ei_fuzzy_selector<Derived,OtherDerived,false>
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++)
for(int i = 0; i < self.cols(); ++i)
if(nested.col(i).squaredNorm() > otherNested.col(i).squaredNorm() * prec * prec)
return false;
return true;

View File

@@ -6,12 +6,12 @@
//
// 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
@@ -19,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/>.
@@ -58,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 += ' ';
@@ -81,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
@@ -122,32 +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)
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);

View File

@@ -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,7 +82,7 @@ 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)
@@ -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 = Eigen::Map<Matrix>(data);
_set_noalias(Eigen::Map<Matrix>(data));
}
#endif // EIGEN_MAP_H

View File

@@ -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 {
static AlignedDerivedType run(MapBase& a) { return a.derived(); }
};
template<typename Dummy> struct force_aligned_impl<false,Dummy> {
static AlignedDerivedType 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,11 +95,11 @@ 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));
if ( ((RowsAtCompileTime == 1) == IsRowMajor) )
if ( ((RowsAtCompileTime == 1) == IsRowMajor) || !int(Derived::IsVectorAtCompileTime) )
return m_data[index];
else
return m_data[index*stride()];
@@ -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) || !int(Derived::IsVectorAtCompileTime) )
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; }

View File

@@ -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()
@@ -39,27 +40,24 @@ template<typename T> inline T ei_random_amplitude()
**************/
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; }
inline int ei_abs(int x) { return abs(x); }
inline int ei_abs(int x) { return std::abs(x); }
inline int ei_abs2(int x) { return x*x; }
inline int ei_sqrt(int) { ei_assert(false); return 0; }
inline int ei_exp(int) { ei_assert(false); return 0; }
inline int ei_log(int) { ei_assert(false); return 0; }
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); }
#else
inline int ei_atan2(int, int) { ei_assert(false); return 0; }
inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
#endif
template<> inline int ei_random(int a, int b)
{
// We can't just do rand()%n as only the high-order bits are really random
return a + static_cast<int>((b-a+1) * (rand() / (RAND_MAX + 1.0)));
return a + static_cast<int>((b-a+1) * (std::rand() / (RAND_MAX + 1.0)));
}
template<> inline int ei_random()
{
@@ -83,6 +81,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; }
@@ -93,6 +92,7 @@ inline float ei_exp(float x) { return std::exp(x); }
inline float ei_log(float x) { return std::log(x); }
inline float ei_sin(float x) { return std::sin(x); }
inline float ei_cos(float x) { return std::cos(x); }
inline float ei_atan2(float y, float x) { return std::atan2(y,x); }
inline float ei_pow(float x, float y) { return std::pow(x, y); }
template<> inline float ei_random(float a, float b)
@@ -101,9 +101,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 +128,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 +140,8 @@ 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_atan2(double y, double x) { return std::atan2(y,x); }
inline double ei_pow(double x, double y) { return std::pow(x, y); }
template<> inline double ei_random(double a, double b)
{
@@ -173,6 +176,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); }
@@ -181,6 +185,7 @@ inline float ei_abs2(const std::complex<float>& x) { return std::norm(x); }
inline std::complex<float> ei_exp(std::complex<float> x) { return std::exp(x); }
inline std::complex<float> ei_sin(std::complex<float> x) { return std::sin(x); }
inline std::complex<float> ei_cos(std::complex<float> x) { return std::cos(x); }
inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0; }
template<> inline std::complex<float> ei_random()
{
@@ -206,6 +211,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); }
@@ -214,6 +220,7 @@ inline double ei_abs2(const std::complex<double>& x) { return std::norm(x); }
inline std::complex<double> ei_exp(std::complex<double> x) { return std::exp(x); }
inline std::complex<double> ei_sin(std::complex<double> x) { return std::sin(x); }
inline std::complex<double> ei_cos(std::complex<double> x) { return std::cos(x); }
inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0; }
template<> inline std::complex<double> ei_random()
{
@@ -240,6 +247,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; }
@@ -250,11 +258,12 @@ inline long double ei_exp(long double x) { return std::exp(x); }
inline long double ei_log(long double x) { return std::log(x); }
inline long double ei_sin(long double x) { return std::sin(x); }
inline long double ei_cos(long double x) { return std::cos(x); }
inline long double ei_atan2(long double y, long double x) { return std::atan2(y,x); }
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()
{
@@ -273,4 +282,14 @@ inline bool ei_isApproxOrLessThan(long double a, long double b, long double prec
return a <= b || ei_isApprox(a, b, prec);
}
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);
}
#endif // EIGEN_MATHFUNCTIONS_H

View File

@@ -25,6 +25,12 @@
#ifndef EIGEN_MATRIX_H
#define EIGEN_MATRIX_H
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
#else
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#endif
/** \class Matrix
*
* \brief The matrix class, also used for vectors and row-vectors
@@ -40,7 +46,10 @@
* \param _Cols Number of columns, or \b Dynamic
*
* The remaining template parameters are optional -- in most cases you don't have to worry about them.
* \param _StorageOrder Either \b RowMajor or \b ColMajor. The default is \b ColMajor.
* \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").
*
@@ -85,7 +94,7 @@
* 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, typically on the heap (\ref alloca "note").
* 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>
@@ -96,16 +105,12 @@
* 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>
*
* <dt><b>\anchor alloca Usage of alloca():</b></dt>
* <dd>On the Linux platform, for small enough arrays, Eigen will avoid heap allocation and instead will use alloca() to perform a dynamic
* allocation on the stack.</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 {
@@ -113,35 +118,38 @@ 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)
Base& base() { return *static_cast<Base*>(this); }
const Base& base() const { return *static_cast<const Base*>(this); }
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();
@@ -149,7 +157,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()];
@@ -157,12 +165,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()];
@@ -170,13 +178,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
@@ -185,13 +193,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
@@ -200,17 +208,17 @@ 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.
@@ -226,13 +234,18 @@ class Matrix
*/
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));
m_storage.resize(rows * cols, rows, cols);
ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
int size = rows*cols;
bool size_changed = size != this->size();
m_storage.resize(size, rows, cols);
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#else
m_storage.resize(rows*cols, rows, cols);
#endif
}
/** Resizes \c *this to a vector of length \a size
@@ -241,65 +254,41 @@ class Matrix
*/
inline void resize(int size)
{
ei_assert(size>0 && "a vector cannot be resized to 0 length");
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
bool size_changed = size != this->size();
#endif
if(RowsAtCompileTime == 1)
m_storage.resize(size, 1, size);
else
m_storage.resize(size, size, 1);
}
/** Copies the value of the expression \a other into \c *this.
*
* \warning Note that the sizes of \c *this and \a other must match.
* If you want automatic resizing, then you must use the function set().
*
* As a special exception, copying a row-vector into a vector (and conversely)
* is allowed.
*
* \sa set()
*/
template<typename OtherDerived>
inline Matrix& operator=(const MatrixBase<OtherDerived>& other)
{
ei_assert(m_storage.data()!=0 && "you cannot use operator= with a non initialized matrix (instead use set()");
return Base::operator=(other.derived());
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#endif
}
/** Copies the value of the expression \a other into \c *this with automatic resizing.
*
* This function is the same than the assignment operator = excepted that \c *this might
* be resized 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.
*
* 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=()
*/
template<typename OtherDerived>
inline Matrix& set(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, +=)
@@ -311,44 +300,39 @@ class Matrix
*
* For fixed-size matrices, does nothing.
*
* For dynamic-size matrices, creates an empty matrix of size null.
* \warning while creating such an \em null matrix is allowed, it \b cannot
* \b be \b used before having being resized or initialized with the function set().
* In particular, initializing a null matrix with operator = is not supported.
* Finally, this constructor is the unique way to create null matrices: resizing
* 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.
* Here are some examples:
* \code
* MatrixXf r = MatrixXf::Random(3,4); // create a random matrix of floats
* MatrixXf m1, m2; // creates two null matrices of float
*
* m1 = r; // illegal (raise an assertion)
* r = m1; // illegal (raise an assertion)
* m1 = m2; // illegal (raise an assertion)
* m1.set(r); // OK
* m2.resize(3,4);
* m2 = r; // OK
* \endcode
*
* \sa resize(int,int), set()
* \sa resize(int,int)
*/
inline explicit Matrix() : m_storage()
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
{
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
_check_template_params();
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
Matrix(ei_constructor_without_unaligned_array_assert)
: m_storage(ei_constructor_without_unaligned_array_assert())
{EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED}
#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);
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
/** This constructor has two very different behaviors, depending on the type of *this.
@@ -361,8 +345,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))
{
@@ -373,33 +358,38 @@ class Matrix
{
ei_assert(x > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == x)
&& y > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == y));
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
}
/** 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)
{
_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)
{
_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)
{
_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)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
m_storage.data()[0] = x;
m_storage.data()[1] = y;
@@ -411,44 +401,33 @@ 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()"
*/
inline 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.
*/
inline void swap(Matrix& other)
{
if (Base::SizeAtCompileTime==Dynamic)
m_storage.swap(other.m_storage);
else
this->Base::swap(other);
}
template<typename OtherDerived>
void swap(const MatrixBase<OtherDerived>& 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.
* These are convenience functions returning Map objects.
*
* \warning Do not use MapAligned in the Eigen 2.0. Mapping aligned arrays will be fully
* supported in Eigen 3.0 (already implemented in the development branch)
*
* \see class Map
*/
@@ -480,6 +459,25 @@ class Matrix
{ 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>
@@ -491,8 +489,114 @@ class Matrix
#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)
{
// this enum introduced to fix compilation with gcc 3.3
enum { cond = int(OtherDerived::Flags) & EvalBeforeAssigningBit };
_set_selector(other.derived(), typename ei_meta_if<bool(cond), ei_meta_true, ei_meta_false>::ret());
return *this;
}
template<typename OtherDerived>
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_true&) { _set_noalias(other.eval()); }
template<typename OtherDerived>
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_false&) { _set_noalias(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)
}
template<typename MatrixType, typename OtherDerived, bool IsSameType, bool IsDynamicSize>
friend struct ei_matrix_swap_impl;
};
template<typename MatrixType, typename OtherDerived,
bool IsSameType = ei_is_same_type<MatrixType, OtherDerived>::ret,
bool IsDynamicSize = MatrixType::SizeAtCompileTime==Dynamic>
struct ei_matrix_swap_impl
{
static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
{
matrix.base().swap(other);
}
};
template<typename MatrixType, typename OtherDerived>
struct ei_matrix_swap_impl<MatrixType, OtherDerived, true, true>
{
static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
{
matrix.m_storage.swap(other.derived().m_storage);
}
};
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
template<typename OtherDerived>
inline void Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::swap(const MatrixBase<OtherDerived>& other)
{
// the Eigen:: here is to work around a stupid ICC 11.1 bug.
Eigen::ei_matrix_swap_impl<Matrix, OtherDerived>::run(*this, *const_cast<MatrixBase<OtherDerived>*>(&other));
}
/** \defgroup matrixtypedefs Global matrix typedefs
*
* \ingroup Core_Module

View File

@@ -136,12 +136,6 @@ template<typename Derived> class MatrixBase
*/
};
/** Default constructor. Just checks at compile-time for self-consistency of the flags. */
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
@@ -165,7 +159,7 @@ template<typename Derived> class MatrixBase
inline int size() const { return rows() * cols(); }
/** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */
inline int nonZeros() const { return derived.nonZeros(); }
inline int nonZeros() const { return size(); }
/** \returns true if either the number of rows or the number of columns is equal to 1.
* In other words, this function returns
* \code rows()==1 || cols()==1 \endcode
@@ -179,9 +173,20 @@ template<typename Derived> class MatrixBase
int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal the type to which the expression gets evaluated (needed by MSVC) */
typedef typename ei_eval<Derived>::type EvalType;
/** \internal Represents a constant matrix */
/** \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;
@@ -218,10 +223,6 @@ template<typename Derived> class MatrixBase
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)
*/
@@ -230,6 +231,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);
@@ -238,10 +244,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);
@@ -331,19 +334,18 @@ template<typename Derived> class MatrixBase
Derived& operator*=(const MatrixBase<OtherDerived>& other);
template<typename OtherDerived>
typename ei_eval_to_column_major<OtherDerived>::type
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 squaredNorm() const;
RealScalar norm2() const;
RealScalar norm() const;
const EvalType normalized() const;
const PlainMatrixType normalized() const;
void normalize();
Eigen::Transpose<Derived> transpose();
@@ -437,6 +439,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();
@@ -454,13 +457,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,
@@ -481,11 +485,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);
@@ -522,8 +526,11 @@ template<typename Derived> class MatrixBase
typename ei_traits<Derived>::Scalar minCoeff() const;
typename ei_traits<Derived>::Scalar maxCoeff() const;
typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col) const;
typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col) const;
typename ei_traits<Derived>::Scalar minCoeff(int* index) const;
typename ei_traits<Derived>::Scalar maxCoeff(int* index) const;
template<typename BinaryOp>
typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
@@ -548,6 +555,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;
@@ -573,40 +581,65 @@ template<typename Derived> class MatrixBase
/////////// 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;
template<typename ResultType>
void computeInverse(MatrixBase<ResultType> *result) const;
Scalar determinant() const;
/////////// Cholesky module ///////////
const LLT<EvalType> llt() const;
const LDLT<EvalType> ldlt() const;
// deprecated:
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
protected:
/** Default constructor. Do nothing. */
MatrixBase()
{
/* Just checks for self-consistency of the flags.
* Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down
*/
#ifdef EIGEN_INTERNAL_DEBUGGING
EIGEN_STATIC_ASSERT(ei_are_flags_consistent<Flags>::ret,
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS)
#endif
}
private:
explicit MatrixBase(int);
MatrixBase(int,int);
template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&);
};
#endif // EIGEN_MATRIXBASE_H

View File

@@ -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.benoit.1@gmail.com>
// 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-2.0/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 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,13 +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)
@@ -78,12 +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); }
@@ -98,18 +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;
}
@@ -118,16 +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;}
@@ -136,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;
@@ -147,14 +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 explicit ei_matrix_storage() : m_data(0), m_cols(0) {}
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 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;}
@@ -162,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;
}
@@ -172,14 +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 explicit ei_matrix_storage() : m_data(0), m_rows(0) {}
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 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;}
@@ -187,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;
}

View File

@@ -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

View File

@@ -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> >
@@ -110,6 +100,9 @@ template<typename ExpressionType> class NestByValue
protected:
const ExpressionType m_expression;
private:
NestByValue& operator=(const NestByValue&);
};
/** \returns an expression of the temporary version of *this.

View File

@@ -94,7 +94,7 @@ template<typename _Real> struct NumTraits<std::complex<_Real> >
enum {
IsComplex = 1,
HasFloatingPoint = NumTraits<Real>::HasFloatingPoint,
ReadCost = 2,
ReadCost = 2 * NumTraits<_Real>::ReadCost,
AddCost = 2 * NumTraits<Real>::AddCost,
MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
};

View File

@@ -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,18 +44,13 @@
* \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
CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ConditionalJumpCost
};
};
@@ -102,12 +98,12 @@ template<typename MatrixType, unsigned int Mode> class Part
inline Scalar& coeffRef(int row, int col)
{
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==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);
}
@@ -121,21 +117,24 @@ 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/*, int OtherMode*/>
template<typename OtherDerived>
void swap(const MatrixBase<OtherDerived>& other)
{
Part<SwapWrapper<MatrixType>,Mode>(SwapWrapper<MatrixType>(const_cast<MatrixType&>(m_matrix))).lazyAssign(other.derived());
Part<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
}
protected:
const typename MatrixType::Nested m_matrix;
private:
Part& operator=(const Part&);
};
/** \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
*
@@ -157,7 +156,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);
}
@@ -187,11 +186,11 @@ 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))
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);
}
}
@@ -215,44 +214,44 @@ 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++)
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++)
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++)
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++)
for(int j = 0; j < dst.cols(); ++j)
for(int i = j+1; i < dst.rows(); ++i)
dst.copyCoeff(i, j, src);
}
};
@@ -261,9 +260,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));
}
@@ -283,10 +282,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
*
@@ -305,44 +305,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;
}

View File

@@ -30,7 +30,7 @@
*** 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>
@@ -62,14 +62,12 @@ 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_eval_to_column_major<Rhs>::type
>::type RhsNested;
typedef const Lhs& LhsNested;
typedef const Rhs& RhsNested;
typedef Product<LhsNested, RhsNested, CacheFriendlyProduct> Type;
};
@@ -77,7 +75,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
{
@@ -85,13 +83,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,7 +115,7 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
// clean the nested types:
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
typedef typename ei_cleantype<RhsNested>::type _RhsNested;
typedef typename _LhsNested::Scalar Scalar;
typedef typename ei_scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
enum {
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
@@ -128,7 +125,7 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
InnerSize = EIGEN_ENUM_MIN(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
InnerSize = EIGEN_SIZE_MIN(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
@@ -144,12 +141,13 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
EvalToRowMajor = RhsRowMajor && (ProductMode==(int)CacheFriendlyProduct ? LhsRowMajor : (!CanVectorizeLhs)),
RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
RemovedBits = ~((EvalToRowMajor ? 0 : RowMajorBit)|DirectAccessBit),
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)
@@ -186,9 +184,20 @@ 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:
typedef typename ei_nested<_LhsNested,_RhsNested::ColsAtCompileTime>::type LhsNestedX;
typedef typename ei_nested<_RhsNested,_LhsNested::RowsAtCompileTime>::type RhsNestedX;
typedef typename ei_cleantype<LhsNestedX>::type _LhsNestedX;
typedef typename ei_cleantype<RhsNestedX>::type _RhsNestedX;
enum {
LhsNestedFlags = _LhsNestedX::Flags,
RhsNestedFlags = _RhsNestedX::Flags
};
template<typename Lhs, typename Rhs>
inline Product(const Lhs& lhs, const Rhs& rhs)
@@ -197,7 +206,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
// 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)
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");
@@ -212,17 +221,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);
@@ -232,7 +241,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;
@@ -242,7 +251,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,
@@ -252,8 +261,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;
@@ -282,10 +291,10 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
// * 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)
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)
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());
}
@@ -298,7 +307,7 @@ template<typename OtherDerived>
inline Derived &
MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
{
return *this = *this * other;
return derived() = derived() * other.derived();
}
/***************************************************************************
@@ -309,42 +318,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&) {}
};
/*******************************************
@@ -355,7 +364,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) ));
@@ -365,22 +374,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);
}
};
@@ -388,7 +397,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>,
@@ -402,7 +411,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,
@@ -414,7 +423,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>,
@@ -426,7 +435,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,
@@ -435,10 +444,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);
}
@@ -451,7 +460,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);
@@ -461,7 +470,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);
@@ -471,7 +480,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));
}
@@ -480,7 +489,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)));
}
@@ -489,11 +498,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);
}
};
@@ -501,11 +510,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);
}
};
@@ -524,11 +533,11 @@ static void ei_cache_friendly_product_rowmajor_times_vector(
template<typename ProductType,
int LhsRows = ei_traits<ProductType>::RowsAtCompileTime,
int LhsOrder = int(ei_traits<ProductType>::LhsFlags)&RowMajorBit ? RowMajor : ColMajor,
int LhsHasDirectAccess = int(ei_traits<ProductType>::LhsFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess,
int RhsCols = ei_traits<ProductType>::ColsAtCompileTime,
int RhsOrder = int(ei_traits<ProductType>::RhsFlags)&RowMajorBit ? RowMajor : ColMajor,
int RhsHasDirectAccess = int(ei_traits<ProductType>::RhsFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess>
int LhsOrder = int(ProductType::LhsNestedFlags)&RowMajorBit ? RowMajor : ColMajor,
int LhsHasDirectAccess = int(ProductType::LhsNestedFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess,
int RhsCols = ProductType::ColsAtCompileTime,
int RhsOrder = int(ProductType::RhsNestedFlags)&RowMajorBit ? RowMajor : ColMajor,
int RhsHasDirectAccess = int(ProductType::RhsNestedFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess>
struct ei_cache_friendly_product_selector
{
template<typename DestDerived>
@@ -545,9 +554,12 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,NoDirectA
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
const int size = product.rhs().rows();
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
const int size = rhs.rows();
for (int k=0; k<size; ++k)
res += product.rhs().coeff(k) * product.lhs().col(k);
res += rhs.coeff(k) * lhs.col(k);
}
};
@@ -561,6 +573,9 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
enum {
EvalToRes = (ei_packet_traits<Scalar>::size==1)
||((DestDerived::Flags&ActualPacketAccessBit) && (!(DestDerived::Flags & RowMajorBit))) };
@@ -569,17 +584,17 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
_res = &res.coeffRef(0);
else
{
_res = ei_alloc_stack(Scalar,res.size());
Map<Matrix<Scalar,DestDerived::RowsAtCompileTime,1> >(_res, res.size()) = res;
_res = ei_aligned_stack_new(Scalar,res.size());
Map<Matrix<Scalar,DestDerived::RowsAtCompileTime,1,ColMajor> >(_res, res.size()) = res;
}
ei_cache_friendly_product_colmajor_times_vector(res.size(),
&product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
product.rhs(), _res);
&lhs.const_cast_derived().coeffRef(0,0), lhs.stride(),
rhs, _res);
if (!EvalToRes)
{
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
ei_free_stack(_res, Scalar, res.size());
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1,ColMajor> >(_res, res.size());
ei_aligned_stack_delete(Scalar, _res, res.size());
}
}
};
@@ -591,9 +606,12 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
const int cols = product.lhs().cols();
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
const int cols = lhs.cols();
for (int j=0; j<cols; ++j)
res += product.lhs().coeff(j) * product.rhs().row(j);
res += lhs.coeff(j) * rhs.row(j);
}
};
@@ -607,6 +625,9 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
enum {
EvalToRes = (ei_packet_traits<Scalar>::size==1)
||((DestDerived::Flags & ActualPacketAccessBit) && (DestDerived::Flags & RowMajorBit)) };
@@ -615,17 +636,17 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
_res = &res.coeffRef(0);
else
{
_res = ei_alloc_stack(Scalar, res.size());
Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size()) = res;
_res = ei_aligned_stack_new(Scalar, res.size());
Map<Matrix<Scalar,1,DestDerived::SizeAtCompileTime,ColMajor> >(_res, res.size()) = res;
}
ei_cache_friendly_product_colmajor_times_vector(res.size(),
&product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
product.lhs().transpose(), _res);
&rhs.const_cast_derived().coeffRef(0,0), rhs.stride(),
lhs.transpose(), _res);
if (!EvalToRes)
{
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
ei_free_stack(_res, Scalar, res.size());
res = Map<Matrix<Scalar,1,DestDerived::SizeAtCompileTime,ColMajor> >(_res, res.size());
ei_aligned_stack_delete(Scalar, _res, res.size());
}
}
};
@@ -637,24 +658,28 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,RowMajor,HasDirect
typedef typename ProductType::Scalar Scalar;
typedef typename ei_traits<ProductType>::_RhsNested Rhs;
enum {
UseRhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (Rhs::Flags&ActualPacketAccessBit))
&& (!(Rhs::Flags & RowMajorBit)) };
UseRhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (ProductType::RhsNestedFlags&ActualPacketAccessBit))
&& (ProductType::RhsNestedFlags&DirectAccessBit)
&& (!(ProductType::RhsNestedFlags & RowMajorBit)) };
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
Scalar* EIGEN_RESTRICT _rhs;
if (UseRhsDirectly)
_rhs = &product.rhs().const_cast_derived().coeffRef(0);
_rhs = &rhs.const_cast_derived().coeffRef(0);
else
{
_rhs = ei_alloc_stack(Scalar, product.rhs().size());
Map<Matrix<Scalar,Rhs::SizeAtCompileTime,1> >(_rhs, product.rhs().size()) = product.rhs();
_rhs = ei_aligned_stack_new(Scalar, rhs.size());
Map<Matrix<Scalar,Rhs::SizeAtCompileTime,1,ColMajor> >(_rhs, rhs.size()) = rhs;
}
ei_cache_friendly_product_rowmajor_times_vector(&product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
_rhs, product.rhs().size(), res);
ei_cache_friendly_product_rowmajor_times_vector(&lhs.const_cast_derived().coeffRef(0,0), lhs.stride(),
_rhs, rhs.size(), res);
if (!UseRhsDirectly) ei_free_stack(_rhs, Scalar, product.rhs().size());
if (!UseRhsDirectly) ei_aligned_stack_delete(Scalar, _rhs, rhs.size());
}
};
@@ -665,24 +690,28 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
typedef typename ProductType::Scalar Scalar;
typedef typename ei_traits<ProductType>::_LhsNested Lhs;
enum {
UseLhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (Lhs::Flags&ActualPacketAccessBit))
&& (Lhs::Flags & RowMajorBit) };
UseLhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (ProductType::LhsNestedFlags&ActualPacketAccessBit))
&& (ProductType::LhsNestedFlags&DirectAccessBit)
&& (ProductType::LhsNestedFlags & RowMajorBit) };
template<typename DestDerived>
inline static void run(DestDerived& res, const ProductType& product)
{
typename ProductType::LhsNestedX lhs(product.lhs());
typename ProductType::RhsNestedX rhs(product.rhs());
Scalar* EIGEN_RESTRICT _lhs;
if (UseLhsDirectly)
_lhs = &product.lhs().const_cast_derived().coeffRef(0);
_lhs = &lhs.const_cast_derived().coeffRef(0);
else
{
_lhs = ei_alloc_stack(Scalar, product.lhs().size());
Map<Matrix<Scalar,Lhs::SizeAtCompileTime,1> >(_lhs, product.lhs().size()) = product.lhs();
_lhs = ei_aligned_stack_new(Scalar, lhs.size());
Map<Matrix<Scalar,1,Lhs::SizeAtCompileTime,ColMajor> >(_lhs, lhs.size()) = lhs;
}
ei_cache_friendly_product_rowmajor_times_vector(&product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
_lhs, product.lhs().size(), res);
ei_cache_friendly_product_rowmajor_times_vector(&rhs.const_cast_derived().coeffRef(0,0), rhs.stride(),
_lhs, lhs.size(), res);
if(!UseLhsDirectly) ei_free_stack(_lhs, Scalar, product.lhs().size());
if(!UseLhsDirectly) ei_aligned_stack_delete(Scalar, _lhs, lhs.size());
}
};
@@ -708,7 +737,17 @@ MatrixBase<Derived>::operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProdu
if (other._expression()._useCacheFriendlyProduct())
ei_cache_friendly_product_selector<Product<Lhs,Rhs,CacheFriendlyProduct> >::run(const_cast_derived(), other._expression());
else
lazyAssign(derived() + other._expression());
{
typedef typename ei_cleantype<Lhs>::type _Lhs;
typedef typename ei_cleantype<Rhs>::type _Rhs;
typedef typename ei_nested<_Lhs,_Rhs::ColsAtCompileTime>::type LhsNested;
typedef typename ei_nested<_Rhs,_Lhs::RowsAtCompileTime>::type RhsNested;
Product<LhsNested,RhsNested,NormalProduct> prod(other._expression().lhs(),other._expression().rhs());
lazyAssign(derived() + prod);
}
return derived();
}
@@ -723,26 +762,54 @@ inline Derived& MatrixBase<Derived>::lazyAssign(const Product<Lhs,Rhs,CacheFrien
}
else
{
lazyAssign<Product<Lhs,Rhs,CacheFriendlyProduct> >(product);
typedef typename ei_cleantype<Lhs>::type _Lhs;
typedef typename ei_cleantype<Rhs>::type _Rhs;
typedef typename ei_nested<_Lhs,_Rhs::ColsAtCompileTime>::type LhsNested;
typedef typename ei_nested<_Rhs,_Lhs::RowsAtCompileTime>::type RhsNested;
typedef Product<LhsNested,RhsNested,NormalProduct> NormalProduct;
NormalProduct normal_prod(product.lhs(),product.rhs());
lazyAssign<NormalProduct>(normal_prod);
}
return derived();
}
template<typename T> struct ei_product_copy_rhs
template<typename T,int StorageOrder> struct ei_product_copy_rhs
{
typedef typename ei_meta_if<
(ei_traits<T>::Flags & RowMajorBit)
|| (!(ei_traits<T>::Flags & DirectAccessBit)),
typename ei_eval_to_column_major<T>::type,
typename ei_plain_matrix_type_column_major<T>::type,
const T&
>::ret type;
};
template<typename T> struct ei_product_copy_lhs
template<typename T> struct ei_product_copy_rhs<T,RowMajorBit>
{
typedef typename ei_meta_if<
(!(ei_traits<T>::Flags & DirectAccessBit)),
typename ei_plain_matrix_type<T>::type,
const T&
>::ret type;
};
template<typename T,int StorageOrder> 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_row_major<T>::type,
const T&
>::ret type;
};
template<typename T> struct ei_product_copy_lhs<T,RowMajorBit>
{
typedef typename ei_meta_if<
((ei_traits<T>::Flags & RowMajorBit)==0)
|| (!(int(ei_traits<T>::Flags) & DirectAccessBit)),
typename ei_plain_matrix_type_row_major<T>::type,
const T&
>::ret type;
};
@@ -751,9 +818,9 @@ template<typename Lhs, typename Rhs, int ProductMode>
template<typename DestDerived>
inline void Product<Lhs,Rhs,ProductMode>::_cacheFriendlyEvalAndAdd(DestDerived& res) const
{
typedef typename ei_product_copy_lhs<_LhsNested>::type LhsCopy;
typedef typename ei_product_copy_lhs<_LhsNested,DestDerived::Flags&RowMajorBit>::type LhsCopy;
typedef typename ei_unref<LhsCopy>::type _LhsCopy;
typedef typename ei_product_copy_rhs<_RhsNested>::type RhsCopy;
typedef typename ei_product_copy_rhs<_RhsNested,DestDerived::Flags&RowMajorBit>::type RhsCopy;
typedef typename ei_unref<RhsCopy>::type _RhsCopy;
LhsCopy lhs(m_lhs);
RhsCopy rhs(m_rhs);
@@ -761,8 +828,9 @@ inline void Product<Lhs,Rhs,ProductMode>::_cacheFriendlyEvalAndAdd(DestDerived&
rows(), cols(), lhs.cols(),
_LhsCopy::Flags&RowMajorBit, (const Scalar*)&(lhs.const_cast_derived().coeffRef(0,0)), lhs.stride(),
_RhsCopy::Flags&RowMajorBit, (const Scalar*)&(rhs.const_cast_derived().coeffRef(0,0)), rhs.stride(),
Flags&RowMajorBit, (Scalar*)&(res.coeffRef(0,0)), res.stride()
DestDerived::Flags&RowMajorBit, (Scalar*)&(res.coeffRef(0,0)), res.stride()
);
}
#endif // EIGEN_PRODUCT_H

View File

@@ -68,10 +68,10 @@ struct ei_redux_impl<BinaryOp, Derived, Start, Dynamic>
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;
}

View File

@@ -30,12 +30,12 @@ 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)
: int(Lhs::Flags) & int(RowMajorBit|SparseBit)
>
struct ei_solve_triangular_selector;
@@ -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;
@@ -89,15 +89,15 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
}
// now let's process the remaining rows 4 at once
for(int i=blockyStart; IsLower ? i<size : i>0; )
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);
@@ -106,21 +106,21 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
* 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).segment(IsLower ? startBlock : i+1, remainingSize)
* other.col(c).segment(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).segment((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,11 +187,11 @@ 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)));
// if (IsLower)
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
@@ -201,7 +201,7 @@ struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
/* 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);
@@ -209,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);
@@ -221,13 +221,19 @@ 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));
@@ -236,7 +242,7 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
typedef typename ei_meta_if<copy,
typename ei_eval_to_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
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);
@@ -246,6 +252,8 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
}
/** \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
@@ -278,10 +286,10 @@ void MatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other
*/
template<typename Derived>
template<typename OtherDerived>
typename ei_eval_to_column_major<OtherDerived>::type
typename ei_plain_matrix_type_column_major<OtherDerived>::type
MatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
{
typename ei_eval_to_column_major<OtherDerived>::type res(other);
typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
solveTriangularInPlace(res);
return res;
}

View File

@@ -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
};
@@ -168,10 +162,10 @@ struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
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;
}
@@ -217,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;
@@ -231,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;
}
};

View File

@@ -117,6 +117,9 @@ template<typename ExpressionType> class SwapWrapper
protected:
ExpressionType& m_expression;
private:
SwapWrapper& operator=(const SwapWrapper&);
};
/** swaps *this with the expression \a other.

View File

@@ -63,15 +63,12 @@ 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)
inline int rows() const { return m_matrix.cols(); }
inline int cols() const { return m_matrix.rows(); }
inline int nonZeros() const { return m_matrix.nonZeros(); }
inline int stride(void) const { return m_matrix.stride(); }
inline Scalar& coeffRef(int row, int col)
@@ -127,7 +124,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 +145,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 +162,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
@@ -167,7 +190,7 @@ 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<StrictlyUpper>().swap(m.transpose());
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
}
};
@@ -175,9 +198,9 @@ 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<StrictlyUpper>().swap(m.transpose());
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
else
m.set(m.transpose().eval());
m = m.transpose().eval();
}
};
@@ -185,10 +208,10 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
*
* 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
* 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.set(m.transpose().eval()); \endcode
* \code m = m.transpose().eval(); \endcode
* - no temporary object is created (currently only for squared matrices)
* - it allows future optimizations (cache friendliness, etc.)
*

View File

@@ -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);
}
};
@@ -164,7 +164,7 @@ struct ei_functor_traits<ei_max_coeff_visitor<Scalar> > {
/** \returns the minimum of all coefficients of *this
* and puts in *row and *col its location.
*
* \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
* \sa MatrixBase::minCoeff(int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
@@ -177,6 +177,22 @@ MatrixBase<Derived>::minCoeff(int* row, int* col) const
return minVisitor.res;
}
/** \returns the minimum of all coefficients of *this
* and puts in *index its location.
*
* \sa MatrixBase::minCoeff(int*,int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::minCoeff(int* index) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
ei_min_coeff_visitor<Scalar> minVisitor;
this->visit(minVisitor);
*index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
return minVisitor.res;
}
/** \returns the maximum of all coefficients of *this
* and puts in *row and *col its location.
*
@@ -193,5 +209,20 @@ MatrixBase<Derived>::maxCoeff(int* row, int* col) const
return maxVisitor.res;
}
/** \returns the maximum of all coefficients of *this
* and puts in *index its location.
*
* \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::minCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::maxCoeff()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::maxCoeff(int* index) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
ei_max_coeff_visitor<Scalar> maxVisitor;
this->visit(maxVisitor);
*index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
return maxVisitor.res;
}
#endif // EIGEN_VISITOR_H

View File

@@ -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,117 @@ 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); }
#if defined(_MSC_VER) && (_MSC_VER <= 1500) && defined(_WIN64) && !defined(__INTEL_COMPILER)
// The temporary variable fixes an internal compilation error.
// Direct of the struct members fixed bug #62.
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return a.m128_f32[0]; }
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return a.m128d_f64[0]; }
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
#elif defined(_MSC_VER) && (_MSC_VER <= 1500) && !defined(__INTEL_COMPILER)
// The temporary variable fixes an 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 +187,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 +214,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 +233,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 +243,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 +253,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 +264,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 +287,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 +310,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)
{
@@ -308,4 +321,7 @@ struct ei_palign_impl<Offset,__m128d>
};
#endif
#define ei_vec4f_swizzle1(v,p,q,r,s) \
(_mm_castsi128_ps(_mm_shuffle_epi32( _mm_castps_si128(v), ((s)<<6|(r)<<4|(q)<<2|(p)))))
#endif // EIGEN_PACKET_MATH_SSE_H

View File

@@ -185,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
@@ -224,7 +224,12 @@ enum {
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 {
@@ -234,9 +239,16 @@ enum {
HasDirectAccess = DirectAccessBit
};
const int FullyCoherentAccessPattern = 0x1;
const int InnerCoherentAccessPattern = 0x2 | FullyCoherentAccessPattern;
const int OuterCoherentAccessPattern = 0x4 | InnerCoherentAccessPattern;
const int RandomAccessPattern = 0x8 | OuterCoherentAccessPattern;
const int EiArch_Generic = 0x0;
const int EiArch_SSE = 0x1;
const int EiArch_AltiVec = 0x2;
#if defined EIGEN_VECTORIZE_SSE
const int EiArch = EiArch_SSE;
#elif defined EIGEN_VECTORIZE_ALTIVEC
const int EiArch = EiArch_AltiVec;
#else
const int EiArch = EiArch_Generic;
#endif
#endif // EIGEN_CONSTANTS_H

View File

@@ -0,0 +1,5 @@
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4181 4244 4127 4211 4717 )
#endif

View File

@@ -0,0 +1,4 @@
#ifdef _MSC_VER
#pragma warning( pop )
#endif

View File

@@ -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;
@@ -105,9 +106,6 @@ template<typename MatrixType> class QR;
template<typename MatrixType> class SVD;
template<typename MatrixType> class LLT;
template<typename MatrixType> class LDLT;
// deprecated:
template<typename MatrixType> class Cholesky;
template<typename MatrixType> class CholeskyWithoutSquareRoot;
// Geometry module:
template<typename Derived, int _Dim> class RotationBase;
@@ -121,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

View File

@@ -28,6 +28,56 @@
#undef minor
#define EIGEN_WORLD_VERSION 2
#define EIGEN_MAJOR_VERSION 0
#define EIGEN_MINOR_VERSION 17
#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))))
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all
// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems
// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__))
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
#else
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0
#endif
#if defined(__GNUC__) && (__GNUC__ <= 3)
#define EIGEN_GCC3_OR_OLDER 1
#else
#define EIGEN_GCC3_OR_OLDER 0
#endif
// FIXME vectorization + alignment is completely disabled with sun studio
#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT && !EIGEN_GCC3_OR_OLDER && !defined(__SUNPRO_CC) && !defined(__QNXNTO__)
#define EIGEN_ARCH_WANTS_ALIGNMENT 1
#else
#define EIGEN_ARCH_WANTS_ALIGNMENT 0
#endif
// EIGEN_ALIGN is the true test whether we want to align or not. It takes into account both the user choice to explicitly disable
// alignment (EIGEN_DONT_ALIGN) and the architecture config (EIGEN_ARCH_WANTS_ALIGNMENT). Henceforth, only EIGEN_ALIGN should be used.
#if EIGEN_ARCH_WANTS_ALIGNMENT && !defined(EIGEN_DONT_ALIGN)
#define EIGEN_ALIGN 1
#else
#define EIGEN_ALIGN 0
#ifdef EIGEN_VECTORIZE
#error "Vectorization enabled, but our platform checks say that we don't do 16 byte alignment on this platform. If you added vectorization for another architecture, you also need to edit this platform check."
#endif
#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
@@ -36,10 +86,18 @@
#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 (sizeof(float)*256*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 \
@@ -84,35 +142,67 @@ 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_DEPRECATED __attribute__((deprecated))
#elif (defined _MSC_VER)
#define EIGEN_DEPRECATED __declspec(deprecated)
#else
#define EIGEN_DEPRECATED
#endif
#if (defined __GNUC__)
#define EIGEN_ALIGN_128 __attribute__ ((aligned(16)))
#else
/* 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_ALIGN
#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
#ifdef EIGEN_DONT_USE_RESTRICT_KEYWORD
#define EIGEN_RESTRICT
#endif
#ifndef EIGEN_RESTRICT
#define EIGEN_RESTRICT __restrict
#endif
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
#define EIGEN_STACK_ALLOCATION_LIMIT 1000000
#endif
#ifndef EIGEN_DEFAULT_IO_FORMAT
#define EIGEN_DEFAULT_IO_FORMAT Eigen::IOFormat()
@@ -124,20 +214,20 @@ using Eigen::ei_cos;
#define EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
template<typename OtherDerived> \
Derived& operator Op(const Eigen::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) \
@@ -153,7 +243,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, \
@@ -168,6 +257,20 @@ enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime, \
_EIGEN_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::MatrixBase<Derived>)
#define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
#define EIGEN_SIZE_MIN(a,b) (((int)a == 1 || (int)b == 1) ? 1 \
: ((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
: ((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

View File

@@ -1,8 +1,9 @@
// 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>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// 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,211 +27,391 @@
#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 ();
// FreeBSD 6 seems to have 16-byte aligned malloc
// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
#else
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
#endif
/** \internal
* Static array automatically aligned if the total byte size is a multiple of 16
#if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
#else
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
#endif
#if (defined __QNXNTO__) || (((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(std::size_t size)
{
EIGEN_ALIGN_128 T array[Size];
ei_aligned_array()
{
ei_assert((reinterpret_cast<unsigned int>(array) & 0xf) == 0
&& "this assertion is explained here: http://eigen.tuxfamily.org/api/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
}
};
template <typename T, int Size> struct ei_aligned_array<T,Size,false>
{
T array[Size];
};
/** \internal allocates \a size * sizeof(\a T) bytes with 16 bytes 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 = std::malloc(size+16);
void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::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
#endif
delete[] ptr;
if(ptr)
std::free(*(reinterpret_cast<void**>(ptr) - 1));
}
/** \internal \returns the number of elements which have to be skipped such that data are 16 bytes aligned */
template<typename Scalar>
inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
* On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
*/
inline void* ei_aligned_malloc(std::size_t size)
{
#ifdef EIGEN_NO_MALLOC
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *result;
#if !EIGEN_ALIGN
result = std::malloc(size);
#elif EIGEN_MALLOC_ALREADY_ALIGNED
result = std::malloc(size);
#elif EIGEN_HAS_POSIX_MEMALIGN
if(posix_memalign(&result, 16, size)) result = 0;
#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
if(result == 0)
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 null, and if exceptions are enabled then a std::bad_alloc is thrown.
*/
template<bool Align> inline void* ei_conditional_aligned_malloc(std::size_t size)
{
return ei_aligned_malloc(size);
}
template<> inline void* ei_conditional_aligned_malloc<false>(std::size_t size)
{
#ifdef EIGEN_NO_MALLOC
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *result = std::malloc(size);
#ifdef EIGEN_EXCEPTIONS
if(!result) throw std::bad_alloc();
#endif
return result;
}
/** \internal construct the elements of an array.
* The \a size parameter tells on how many objects to call the constructor of T.
*/
template<typename T> inline T* ei_construct_elements_of_array(T *ptr, std::size_t size)
{
for (std::size_t i=0; i < size; ++i) ::new (ptr + i) T;
return ptr;
}
/** 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(std::size_t size)
{
T *result = reinterpret_cast<T*>(ei_aligned_malloc(sizeof(T)*size));
return ei_construct_elements_of_array(result, size);
}
template<typename T, bool Align> inline T* ei_conditional_aligned_new(std::size_t size)
{
T *result = reinterpret_cast<T*>(ei_conditional_aligned_malloc<Align>(sizeof(T)*size));
return ei_construct_elements_of_array(result, size);
}
/** \internal free memory allocated with ei_aligned_malloc
*/
inline void ei_aligned_free(void *ptr)
{
#if !EIGEN_ALIGN
std::free(ptr);
#elif EIGEN_MALLOC_ALREADY_ALIGNED
std::free(ptr);
#elif EIGEN_HAS_POSIX_MEMALIGN
std::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)
{
std::free(ptr);
}
/** \internal destruct 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_destruct_elements_of_array(T *ptr, std::size_t size)
{
// always destruct an array starting from the end.
if(ptr)
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, std::size_t size)
{
ei_destruct_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, std::size_t size)
{
ei_destruct_elements_of_array<T>(ptr, size);
ei_conditional_aligned_free<Align>(ptr);
}
/** \internal \returns the index of the first element of the array that is well aligned for vectorization.
*
* \param array the address of the start of the array
* \param size the size of the array
*
* \note If no element of the array is well aligned, the size of the array is returned. Typically,
* for example with SSE, "well aligned" means 16-byte-aligned. If vectorization is disabled or if the
* packet size for the given scalar type is 1, then everything is considered well-aligned.
*
* \note If the scalar type is vectorizable, we rely on the following assumptions: sizeof(Scalar) is a
* power of 2, the packet size in bytes is also a power of 2, and is a multiple of sizeof(Scalar). On the
* other hand, we do not assume that the array address is a multiple of sizeof(Scalar), as that fails for
* example with Scalar=double on certain 32-bit platforms, see bug #79.
*
* There is also the variant ei_first_aligned(const MatrixBase&, Integer) defined in Coeffs.h.
*/
template<typename Scalar, typename Integer>
inline static Integer ei_alignmentOffset(const Scalar* array, Integer size)
{
typedef typename ei_packet_traits<Scalar>::type Packet;
const int PacketSize = ei_packet_traits<Scalar>::size;
const int PacketAlignedMask = PacketSize-1;
const bool Vectorized = PacketSize>1;
return Vectorized
? std::min<int>( (PacketSize - ((size_t(ptr)/sizeof(Scalar)) & PacketAlignedMask))
& PacketAlignedMask, maxOffset)
: 0;
enum { PacketSize = ei_packet_traits<Scalar>::size,
PacketAlignedMask = PacketSize-1
};
if(PacketSize==1)
{
// Either there is no vectorization, or a packet consists of exactly 1 scalar so that all elements
// of the array have the same aligment.
return 0;
}
else if(std::size_t(array) & (sizeof(Scalar)-1))
{
// There is vectorization for this scalar type, but the array is not aligned to the size of a single scalar.
// Consequently, no element of the array is well aligned.
return size;
}
else
{
return std::min<Integer>( (PacketSize - (Integer((std::size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
& PacketAlignedMask, size);
}
}
/** \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 by 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 instances of inherited classes to be 16 bytes aligned when 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. Those include all Matrix types having a sizeof multiple of 16 bytes, e.g.:
* - Vector2d, Vector4f, Vector4i, Vector4d,
* - Matrix2d, Matrix4f, Matrix4i, Matrix4d,
* - etc.
* When an object is statically allocated, the compiler will automatically and always enforces 16 bytes
* alignment of the data when needed. 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 returns 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 *pObj2 = new Foo; // dynamic allocation
* pObj2->some_vector = Vector4f(..); // => SAFE !
* \endcode
*
* \sa class ei_new_allocator
*/
struct WithAlignedOperatorNew
{
#ifdef EIGEN_VECTORIZE
#define ei_aligned_stack_new(TYPE,SIZE) ei_construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_destruct_elements_of_array<TYPE>(PTR, SIZE); \
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(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 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); }
#if EIGEN_ALIGN
#ifdef EIGEN_EXCEPTIONS
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
void* operator new(std::size_t size, const std::nothrow_t&) throw() { \
try { return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); } \
catch (...) { return 0; } \
return 0; \
}
#else
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
void* operator new(std::size_t size, const std::nothrow_t&) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
}
#endif
};
template<typename T, int SizeAtCompileTime,
bool NeedsToAlign = (SizeAtCompileTime!=Dynamic) && ((sizeof(T)*SizeAtCompileTime)%16==0)>
struct ei_with_aligned_operator_new : WithAlignedOperatorNew {};
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
void *operator new(std::size_t size) { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void *operator new[](std::size_t size) { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void operator delete(void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
void operator delete[](void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
/* in-place new and delete. since (at least afaik) there is no actual */ \
/* memory allocated we can safely let the default implementation handle */ \
/* this particular case. */ \
static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \
void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
void operator delete(void *ptr, const std::nothrow_t&) throw() { \
Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); \
} \
typedef void ei_operator_new_marker_type;
#else
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
#endif
template<typename T, int SizeAtCompileTime>
struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {};
#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 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
/** \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
{
public:
typedef T value_type;
public:
typedef std::size_t size_type;
typedef std::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 void* 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

View File

@@ -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

View File

@@ -55,27 +55,45 @@
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_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
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,
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS,
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
};
};
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
if (Eigen::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
#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
@@ -89,22 +107,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) \
@@ -112,7 +130,7 @@
(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)
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
((int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
@@ -126,6 +144,6 @@
#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)
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
#endif // EIGEN_STATIC_ASSERT_H

View File

@@ -37,6 +37,10 @@
//classes inheriting ei_no_assignment_operator don't generate a default operator=.
class ei_no_assignment_operator
{
#if EIGEN_GCC3_OR_OLDER
protected:
void nevermind_this_is_just_to_work_around_a_stupid_gcc3_warning();
#endif
private:
ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
};
@@ -85,22 +89,22 @@ 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,
inner_max_size = row_major_bit ? MaxCols : MaxRows,
row_major_bit = Options&RowMajor ? RowMajorBit : 0,
inner_max_size = int(MaxRows==1) ? int(MaxCols)
: int(MaxCols==1) ? int(MaxRows)
: int(row_major_bit) ? int(MaxCols) : int(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
storage_has_fixed_size = MaxRows != Dynamic && MaxCols != Dynamic,
storage_has_aligned_fixed_size = storage_has_fixed_size
&& ( (MaxCols*MaxRows) % ei_packet_traits<Scalar>::size == 0 ),
aligned_bit = ( (Options&AutoAlign)
&& (is_big || storage_has_aligned_fixed_size)
) ? AlignedBit : 0,
packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
};
public:
@@ -112,26 +116,65 @@ template<int _Rows, int _Cols> struct ei_size_at_compile_time
enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
};
template<typename T, int Sparseness = ei_traits<T>::Flags&SparseBit> class ei_eval;
/* 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> struct ei_eval;
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;
};
template<typename T> struct ei_eval_to_column_major
/* 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,
ColMajor,
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;
};
/* ei_plain_matrix_type_row_major : same as ei_plain_matrix_type but guaranteed to be row-major
*/
template<typename T> struct ei_plain_matrix_type_row_major
{
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
AutoAlign | RowMajor,
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;
@@ -158,7 +201,7 @@ template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret
* 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 EvalType = typename ei_eval<T>::type> struct ei_nested
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),
@@ -170,7 +213,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;

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_ALIGNEDBOX_H
#define EIGEN_ALIGNEDBOX_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
* \nonstableyet
*
* \class AlignedBox
@@ -39,12 +39,9 @@
*/
template <typename _Scalar, int _AmbientDim>
class AlignedBox
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
#endif
{
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;
@@ -59,7 +56,7 @@ public:
{ 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) {}
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) {}
@@ -142,8 +139,8 @@ public:
template<typename OtherScalarType>
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
{
m_min = other.min().template cast<OtherScalarType>();
m_max = other.max().template cast<OtherScalarType>();
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

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_ANGLEAXIS_H
#define EIGEN_ANGLEAXIS_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class AngleAxis
*
@@ -146,8 +146,8 @@ public:
template<typename OtherScalarType>
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
{
m_axis = other.axis().template cast<OtherScalarType>();
m_angle = other.angle();
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
@@ -158,10 +158,10 @@ public:
{ 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;

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_EULERANGLES_H
#define EIGEN_EULERANGLES_H
/** \geometry_module \ingroup GeometryModule
/** \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)
@@ -60,31 +60,31 @@ MatrixBase<Derived>::eulerAngles(int a0, int a1, int a2) const
if (a0==a2)
{
Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
res[1] = std::atan2(s, coeff(i,i));
res[1] = ei_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));
res[0] = ei_atan2(coeff(j,i), coeff(k,i));
res[2] = ei_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));
res[2] = (coeff(i,i)>0?1:-1)*ei_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);
res[1] = ei_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));
res[0] = ei_atan2(coeff(j,k), coeff(k,k));
res[2] = ei_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));
res[2] = (coeff(i,k)>0?1:-1)*ei_atan2(-coeff(k,j), coeff(j,j));
}
}
if (!odd)

View File

@@ -26,7 +26,7 @@
#ifndef EIGEN_HYPERPLANE_H
#define EIGEN_HYPERPLANE_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class Hyperplane
*
@@ -45,19 +45,16 @@
*/
template <typename _Scalar, int _AmbientDim>
class Hyperplane
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
#endif
{
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
typedef Matrix<Scalar,int(AmbientDimAtCompileTime)==Dynamic
? Dynamic
: AmbientDimAtCompileTime+1,1> Coefficients;
: int(AmbientDimAtCompileTime)+1,1> Coefficients;
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
/** Default constructor without initialization */
@@ -70,7 +67,7 @@ public:
/** 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)
inline Hyperplane(const VectorType& n, const VectorType& e)
: m_coeffs(n.size()+1)
{
normal() = n;
@@ -254,7 +251,7 @@ public:
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime>& other)
{ m_coeffs = other.coeffs().template cast<OtherScalarType>(); }
{ 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.

View File

@@ -34,7 +34,7 @@
*/
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)
@@ -43,7 +43,7 @@ MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
// 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)
@@ -53,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)
@@ -96,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(); }
};
@@ -109,7 +109,7 @@ 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)

View File

@@ -26,7 +26,7 @@
#ifndef EIGEN_PARAMETRIZEDLINE_H
#define EIGEN_PARAMETRIZEDLINE_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class ParametrizedLine
*
@@ -34,19 +34,16 @@
*
* 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$.
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ t \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.
*/
template <typename _Scalar, int _AmbientDim>
class ParametrizedLine
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim>
#endif
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
enum { AmbientDimAtCompileTime = _AmbientDim };
typedef _Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
@@ -118,8 +115,8 @@ public:
template<typename OtherScalarType>
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime>& other)
{
m_origin = other.origin().template cast<OtherScalarType>();
m_direction = other.direction().template cast<OtherScalarType>();
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

View File

@@ -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,9 +109,8 @@ 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.
@@ -151,7 +148,7 @@ 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::squaredNorm()
@@ -207,7 +204,7 @@ public:
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
inline explicit Quaternion(const Quaternion<OtherScalarType>& other)
{ m_coeffs = other.coeffs().template cast<OtherScalarType>(); }
{ 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.
@@ -216,26 +213,56 @@ public:
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;
// Generic Quaternion * Quaternion product
template<int Arch,typename Scalar> inline Quaternion<Scalar>
ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
{
return Quaternion<Scalar>
(
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
);
}
#ifdef EIGEN_VECTORIZE_SSE
template<> inline Quaternion<float>
ei_quaternion_product<EiArch_SSE,float>(const Quaternion<float>& _a, const Quaternion<float>& _b)
{
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000));
Quaternion<float> res;
__m128 a = _a.coeffs().packet<Aligned>(0);
__m128 b = _b.coeffs().packet<Aligned>(0);
__m128 flip1 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,1,2,0,2),
ei_vec4f_swizzle1(b,2,0,1,2)),mask);
__m128 flip2 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,3,3,3,1),
ei_vec4f_swizzle1(b,0,1,2,1)),mask);
ei_pstore(&res.x(),
_mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,ei_vec4f_swizzle1(b,3,3,3,3)),
_mm_mul_ps(ei_vec4f_swizzle1(a,2,0,1,0),
ei_vec4f_swizzle1(b,1,2,0,0))),
_mm_add_ps(flip1,flip2)));
return res;
}
#endif
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
template <typename Scalar>
inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const
{
return Quaternion
(
this->w() * other.w() - this->x() * other.x() - this->y() * other.y() - this->z() * other.z(),
this->w() * other.x() + this->x() * other.w() + this->y() * other.z() - this->z() * other.y(),
this->w() * other.y() + this->y() * other.w() + this->z() * other.x() - this->x() * other.z(),
this->w() * other.z() + this->z() * other.w() + this->x() * other.y() - this->y() * other.x()
);
return ei_quaternion_product<EiArch>(*this,other);
}
/** \sa operator*(Quaternion) */
@@ -279,7 +306,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;
@@ -347,7 +374,6 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
Vector3 v0 = a.normalized();
Vector3 v1 = b.normalized();
Vector3 axis = v0.cross(v1);
Scalar c = v0.dot(v1);
// if dot == 1, vectors are the same
@@ -355,8 +381,18 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
// set to identity
this->w() = 1; this->vec().setZero();
return *this;
}
Scalar s = ei_sqrt((1+c)*2);
// if dot == -1, vectors are opposites
if (ei_isApprox(c,Scalar(-1)))
{
this->vec() = v0.unitOrthogonal();
this->w() = 0;
return *this;
}
Vector3 axis = v0.cross(v1);
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
Scalar invs = Scalar(1)/s;
this->vec() = axis * invs;
this->w() = s * Scalar(0.5);
@@ -414,22 +450,31 @@ inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
template <typename Scalar>
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
{
static const Scalar one = Scalar(1) - precision<Scalar>();
static const Scalar one = Scalar(1) - machine_epsilon<Scalar>();
Scalar d = this->dot(other);
Scalar absD = ei_abs(d);
Scalar scale0;
Scalar scale1;
if (absD>=one)
return *this;
{
scale0 = Scalar(1) - t;
scale1 = t;
}
else
{
// theta is the angle between the 2 quaternions
Scalar theta = std::acos(absD);
Scalar sinTheta = ei_sin(theta);
// theta is the angle between the 2 quaternions
Scalar theta = std::acos(absD);
Scalar sinTheta = ei_sin(theta);
scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
scale1 = ei_sin( ( t * theta) ) / sinTheta;
if (d<0)
scale1 = -scale1;
}
Scalar scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
Scalar scale1 = ei_sin( ( t * theta) ) / sinTheta;
if (d<0)
scale1 = -scale1;
return Quaternion(scale0 * m_coeffs + scale1 * other.m_coeffs);
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
}
// set from a rotation matrix
@@ -461,7 +506,7 @@ 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);
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;

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_ROTATION2D_H
#define EIGEN_ROTATION2D_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class Rotation2D
*
@@ -85,7 +85,7 @@ public:
/** Concatenates two rotations */
inline Rotation2D& operator*=(const Rotation2D& other)
{ return m_angle += other.m_angle; }
{ return m_angle += other.m_angle; return *this; }
/** Applies the rotation to a 2D vector */
Vector2 operator* (const Vector2& vec) const
@@ -114,7 +114,7 @@ public:
template<typename OtherScalarType>
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
{
m_angle = other.angle();
m_angle = Scalar(other.angle());
}
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
@@ -125,10 +125,10 @@ public:
{ 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;
@@ -140,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_made_a_programming_mistake)
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;
}

View File

@@ -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_made_a_programming_mistake)
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_made_a_programming_mistake)
YOU_MADE_A_PROGRAMMING_MISTAKE)
return mat;
}

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_SCALING_H
#define EIGEN_SCALING_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class Scaling
*
@@ -41,11 +41,9 @@
*/
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)
{
@@ -140,7 +138,7 @@ public:
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
inline explicit Scaling(const Scaling<OtherScalarType,Dim>& other)
{ m_coeffs = other.coeffs().template cast<OtherScalarType>(); }
{ 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.
@@ -151,7 +149,7 @@ public:
};
/** \addtogroup GeometryModule */
/** \addtogroup Geometry_Module */
//@{
typedef Scaling<float, 2> Scaling2f;
typedef Scaling<double,2> Scaling2d;

View File

@@ -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,7 +96,9 @@ 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; }
@@ -108,7 +108,7 @@ public:
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)
@@ -132,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. */
@@ -184,13 +184,24 @@ 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(); }
static const typename MatrixType::IdentityReturnType Identity()
{
return MatrixType::Identity();
}
template<typename OtherDerived>
inline Transform& scale(const MatrixBase<OtherDerived> &other);
@@ -238,7 +249,11 @@ public:
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,
@@ -263,7 +278,7 @@ public:
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
{ m_matrix = other.matrix().template cast<OtherScalarType>(); }
{ 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.
@@ -272,17 +287,21 @@ public:
bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
{ return m_matrix.isApprox(other.m_matrix, prec); }
#ifdef EIGEN_TRANSFORM_PLUGIN
#include EIGEN_TRANSFORM_PLUGIN
#endif
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;
/**************************
@@ -307,7 +326,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_made_a_programming_mistake)
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;
@@ -323,10 +342,10 @@ 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_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));
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
m_matrix.coeff(0,1), m_matrix.coeff(1,1),
m_matrix.coeff(0,2), m_matrix.coeff(1,2));
}
/** Initialises \c *this from a QTransform assuming the dimension is 2.
@@ -346,7 +365,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_made_a_programming_mistake)
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();
@@ -358,12 +377,12 @@ Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
*/
template<typename Scalar, int Dim>
QMatrix Transform<Scalar,Dim>::toQTransform(void) const
QTransform Transform<Scalar,Dim>::toQTransform(void) const
{
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);
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
}
#endif
@@ -501,7 +520,7 @@ template<typename Scalar, int Dim>
Transform<Scalar,Dim>&
Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
{
EIGEN_STATIC_ASSERT(int(Dim)==2, you_made_a_programming_mistake)
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;
@@ -516,7 +535,7 @@ template<typename Scalar, int Dim>
Transform<Scalar,Dim>&
Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
{
EIGEN_STATIC_ASSERT(int(Dim)==2, you_made_a_programming_mistake)
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;
}
@@ -528,7 +547,7 @@ Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
template<typename Scalar, int Dim>
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
{
linear().setIdentity;
linear().setIdentity();
translation() = t.vector();
m_matrix.template block<1,Dim>(Dim,0).setZero();
m_matrix(Dim,Dim) = Scalar(1);
@@ -548,7 +567,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;
}
@@ -567,7 +586,7 @@ inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBas
linear() = ei_toRotationMatrix<Scalar,Dim>(r);
translation().setZero();
m_matrix.template block<1,Dim>(Dim,0).setZero();
m_matrix(Dim,Dim) = Scalar(1);
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
return *this;
}
@@ -580,47 +599,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
@@ -640,7 +673,9 @@ Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDer
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

View File

@@ -25,7 +25,7 @@
#ifndef EIGEN_TRANSLATION_H
#define EIGEN_TRANSLATION_H
/** \geometry_module \ingroup GeometryModule
/** \geometry_module \ingroup Geometry_Module
*
* \class Translation
*
@@ -41,11 +41,9 @@
*/
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 */
@@ -143,7 +141,7 @@ public:
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
{ m_coeffs = other.vector().template cast<OtherScalarType>(); }
{ 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.
@@ -154,7 +152,7 @@ public:
};
/** \addtogroup GeometryModule */
/** \addtogroup Geometry_Module */
//@{
typedef Translation<float, 2> Translation2f;
typedef Translation<double,2> Translation2d;

View File

@@ -29,8 +29,8 @@
*** Part 1 : optimized implementations for fixed-size 2,3,4 cases ***
********************************************************************/
template<typename MatrixType>
void ei_compute_inverse_in_size2_case(const MatrixType& matrix, MatrixType* result)
template<typename XprType, typename MatrixType>
void ei_compute_inverse_in_size2_case(const XprType& matrix, MatrixType* result)
{
typedef typename MatrixType::Scalar Scalar;
const Scalar invdet = Scalar(1) / matrix.determinant();
@@ -54,10 +54,10 @@ bool ei_compute_inverse_in_size2_case_with_check(const XprType& matrix, MatrixTy
return true;
}
template<typename MatrixType>
void ei_compute_inverse_in_size3_case(const MatrixType& matrix, MatrixType* result)
template<typename Derived, typename OtherDerived>
void ei_compute_inverse_in_size3_case(const Derived& matrix, OtherDerived* result)
{
typedef typename MatrixType::Scalar Scalar;
typedef typename Derived::Scalar Scalar;
const Scalar det_minor00 = matrix.minor(0,0).determinant();
const Scalar det_minor10 = matrix.minor(1,0).determinant();
const Scalar det_minor20 = matrix.minor(2,0).determinant();
@@ -75,130 +75,204 @@ void ei_compute_inverse_in_size3_case(const MatrixType& matrix, MatrixType* resu
result->coeffRef(2, 2) = matrix.minor(2,2).determinant() * invdet;
}
template<typename MatrixType>
bool ei_compute_inverse_in_size4_case_helper(const MatrixType& matrix, MatrixType* result)
template<typename Derived, typename OtherDerived, typename Scalar = typename Derived::Scalar>
struct ei_compute_inverse_in_size4_case
{
/* Let's split M into four 2x2 blocks:
* (P Q)
* (R S)
* If P is invertible, with inverse denoted by P_inverse, and if
* (S - R*P_inverse*Q) is also invertible, then the inverse of M is
* (P' Q')
* (R' S')
* where
* S' = (S - R*P_inverse*Q)^(-1)
* P' = P1 + (P1*Q) * S' *(R*P_inverse)
* Q' = -(P_inverse*Q) * S'
* R' = -S' * (R*P_inverse)
*/
typedef Block<MatrixType,2,2> XprBlock22;
typedef typename XprBlock22::Eval Block22;
Block22 P_inverse;
if(ei_compute_inverse_in_size2_case_with_check(matrix.template block<2,2>(0,0), &P_inverse))
static void run(const Derived& matrix, OtherDerived& result)
{
const Block22 Q = matrix.template block<2,2>(0,2);
const Block22 P_inverse_times_Q = P_inverse * Q;
const XprBlock22 R = matrix.template block<2,2>(2,0);
const Block22 R_times_P_inverse = R * P_inverse;
const Block22 R_times_P_inverse_times_Q = R_times_P_inverse * Q;
const XprBlock22 S = matrix.template block<2,2>(2,2);
const Block22 X = S - R_times_P_inverse_times_Q;
Block22 Y;
ei_compute_inverse_in_size2_case(X, &Y);
result->template block<2,2>(2,2) = Y;
result->template block<2,2>(2,0) = - Y * R_times_P_inverse;
const Block22 Z = P_inverse_times_Q * Y;
result->template block<2,2>(0,2) = - Z;
result->template block<2,2>(0,0) = P_inverse + Z * R_times_P_inverse;
return true;
result.coeffRef(0,0) = matrix.minor(0,0).determinant();
result.coeffRef(1,0) = -matrix.minor(0,1).determinant();
result.coeffRef(2,0) = matrix.minor(0,2).determinant();
result.coeffRef(3,0) = -matrix.minor(0,3).determinant();
result.coeffRef(0,2) = matrix.minor(2,0).determinant();
result.coeffRef(1,2) = -matrix.minor(2,1).determinant();
result.coeffRef(2,2) = matrix.minor(2,2).determinant();
result.coeffRef(3,2) = -matrix.minor(2,3).determinant();
result.coeffRef(0,1) = -matrix.minor(1,0).determinant();
result.coeffRef(1,1) = matrix.minor(1,1).determinant();
result.coeffRef(2,1) = -matrix.minor(1,2).determinant();
result.coeffRef(3,1) = matrix.minor(1,3).determinant();
result.coeffRef(0,3) = -matrix.minor(3,0).determinant();
result.coeffRef(1,3) = matrix.minor(3,1).determinant();
result.coeffRef(2,3) = -matrix.minor(3,2).determinant();
result.coeffRef(3,3) = matrix.minor(3,3).determinant();
result /= (matrix.col(0).cwise()*result.row(0).transpose()).sum();
}
else
{
return false;
}
}
};
template<typename MatrixType>
void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* result)
#ifdef EIGEN_VECTORIZE_SSE
// The SSE code for the 4x4 float matrix inverse in this file comes from the file
// ftp://download.intel.com/design/PentiumIII/sml/24504301.pdf
// its copyright information is:
// Copyright (C) 1999 Intel Corporation
// See page ii of that document for legal stuff. Not being lawyers, we just assume
// here that if Intel makes this document publically available, with source code
// and detailed explanations, it's because they want their CPUs to be fed with
// good code, and therefore they presumably don't mind us using it in Eigen.
template<typename Derived, typename OtherDerived>
struct ei_compute_inverse_in_size4_case<Derived, OtherDerived, float>
{
if(ei_compute_inverse_in_size4_case_helper(matrix, result))
static void run(const Derived& matrix, OtherDerived& result)
{
// good ! The topleft 2x2 block was invertible, so the 2x2 blocks approach is successful.
return;
// Variables (Streaming SIMD Extensions registers) which will contain cofactors and, later, the
// lines of the inverted matrix.
__m128 minor0, minor1, minor2, minor3;
// Variables which will contain the lines of the reference matrix and, later (after the transposition),
// the columns of the original matrix.
__m128 row0, row1, row2, row3;
// Temporary variables and the variable that will contain the matrix determinant.
__m128 det, tmp1;
// Matrix transposition
const float *src = matrix.data();
tmp1 = _mm_loadh_pi(_mm_castpd_ps(_mm_load_sd((double*)src)), (__m64*)(src+ 4));
row1 = _mm_loadh_pi(_mm_castpd_ps(_mm_load_sd((double*)(src+8))), (__m64*)(src+12));
row0 = _mm_shuffle_ps(tmp1, row1, 0x88);
row1 = _mm_shuffle_ps(row1, tmp1, 0xDD);
tmp1 = _mm_loadh_pi(_mm_castpd_ps(_mm_load_sd((double*)(src+ 2))), (__m64*)(src+ 6));
row3 = _mm_loadh_pi(_mm_castpd_ps(_mm_load_sd((double*)(src+10))), (__m64*)(src+14));
row2 = _mm_shuffle_ps(tmp1, row3, 0x88);
row3 = _mm_shuffle_ps(row3, tmp1, 0xDD);
// Cofactors calculation. Because in the process of cofactor computation some pairs in three-
// element products are repeated, it is not reasonable to load these pairs anew every time. The
// values in the registers with these pairs are formed using shuffle instruction. Cofactors are
// calculated row by row (4 elements are placed in 1 SP FP SIMD floating point register).
tmp1 = _mm_mul_ps(row2, row3);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
minor0 = _mm_mul_ps(row1, tmp1);
minor1 = _mm_mul_ps(row0, tmp1);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor0 = _mm_sub_ps(_mm_mul_ps(row1, tmp1), minor0);
minor1 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor1);
minor1 = _mm_shuffle_ps(minor1, minor1, 0x4E);
// -----------------------------------------------
tmp1 = _mm_mul_ps(row1, row2);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
minor0 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor0);
minor3 = _mm_mul_ps(row0, tmp1);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row3, tmp1));
minor3 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor3);
minor3 = _mm_shuffle_ps(minor3, minor3, 0x4E);
// -----------------------------------------------
tmp1 = _mm_mul_ps(_mm_shuffle_ps(row1, row1, 0x4E), row3);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
row2 = _mm_shuffle_ps(row2, row2, 0x4E);
minor0 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor0);
minor2 = _mm_mul_ps(row0, tmp1);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor0 = _mm_sub_ps(minor0, _mm_mul_ps(row2, tmp1));
minor2 = _mm_sub_ps(_mm_mul_ps(row0, tmp1), minor2);
minor2 = _mm_shuffle_ps(minor2, minor2, 0x4E);
// -----------------------------------------------
tmp1 = _mm_mul_ps(row0, row1);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
minor2 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor2);
minor3 = _mm_sub_ps(_mm_mul_ps(row2, tmp1), minor3);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor2 = _mm_sub_ps(_mm_mul_ps(row3, tmp1), minor2);
minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row2, tmp1));
// -----------------------------------------------
tmp1 = _mm_mul_ps(row0, row3);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row2, tmp1));
minor2 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor2);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor1 = _mm_add_ps(_mm_mul_ps(row2, tmp1), minor1);
minor2 = _mm_sub_ps(minor2, _mm_mul_ps(row1, tmp1));
// -----------------------------------------------
tmp1 = _mm_mul_ps(row0, row2);
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0xB1);
minor1 = _mm_add_ps(_mm_mul_ps(row3, tmp1), minor1);
minor3 = _mm_sub_ps(minor3, _mm_mul_ps(row1, tmp1));
tmp1 = _mm_shuffle_ps(tmp1, tmp1, 0x4E);
minor1 = _mm_sub_ps(minor1, _mm_mul_ps(row3, tmp1));
minor3 = _mm_add_ps(_mm_mul_ps(row1, tmp1), minor3);
// Evaluation of determinant and its reciprocal value. In the original Intel document,
// 1/det was evaluated using a fast rcpps command with subsequent approximation using
// the Newton-Raphson algorithm. Here, we go for a IEEE-compliant division instead,
// so as to not compromise precision at all.
det = _mm_mul_ps(row0, minor0);
det = _mm_add_ps(_mm_shuffle_ps(det, det, 0x4E), det);
det = _mm_add_ss(_mm_shuffle_ps(det, det, 0xB1), det);
// tmp1= _mm_rcp_ss(det);
// det= _mm_sub_ss(_mm_add_ss(tmp1, tmp1), _mm_mul_ss(det, _mm_mul_ss(tmp1, tmp1)));
det = _mm_div_ss(_mm_set_ss(1.0f), det); // <--- yay, one original line not copied from Intel
det = _mm_shuffle_ps(det, det, 0x00);
// warning, Intel's variable naming is very confusing: now 'det' is 1/det !
// Multiplication of cofactors by 1/det. Storing the inverse matrix to the address in pointer src.
minor0 = _mm_mul_ps(det, minor0);
float *dst = result.data();
_mm_storel_pi((__m64*)(dst), minor0);
_mm_storeh_pi((__m64*)(dst+2), minor0);
minor1 = _mm_mul_ps(det, minor1);
_mm_storel_pi((__m64*)(dst+4), minor1);
_mm_storeh_pi((__m64*)(dst+6), minor1);
minor2 = _mm_mul_ps(det, minor2);
_mm_storel_pi((__m64*)(dst+ 8), minor2);
_mm_storeh_pi((__m64*)(dst+10), minor2);
minor3 = _mm_mul_ps(det, minor3);
_mm_storel_pi((__m64*)(dst+12), minor3);
_mm_storeh_pi((__m64*)(dst+14), minor3);
}
else
{
// rare case: the topleft 2x2 block is not invertible (but the matrix itself is assumed to be).
// 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));
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
// 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));
}
else
{
// last possible case. Since matrix is assumed to be invertible, this last case has to work.
m.row(1).swap(m.row(2));
m.row(1).swap(m.row(3));
ei_compute_inverse_in_size4_case_helper(m, result);
result->col(1).swap(result->col(3));
}
}
}
};
#endif
/***********************************************
*** Part 2 : selector and MatrixBase methods ***
***********************************************/
template<typename MatrixType, int Size = MatrixType::RowsAtCompileTime>
template<typename Derived, typename OtherDerived, int Size = Derived::RowsAtCompileTime>
struct ei_compute_inverse
{
static inline void run(const MatrixType& matrix, MatrixType* result)
static inline void run(const Derived& matrix, OtherDerived* result)
{
LU<MatrixType> lu(matrix);
LU<Derived> lu(matrix);
lu.computeInverse(result);
}
};
template<typename MatrixType>
struct ei_compute_inverse<MatrixType, 1>
template<typename Derived, typename OtherDerived>
struct ei_compute_inverse<Derived, OtherDerived, 1>
{
static inline void run(const MatrixType& matrix, MatrixType* result)
static inline void run(const Derived& matrix, OtherDerived* result)
{
typedef typename MatrixType::Scalar Scalar;
typedef typename Derived::Scalar Scalar;
result->coeffRef(0,0) = Scalar(1) / matrix.coeff(0,0);
}
};
template<typename MatrixType>
struct ei_compute_inverse<MatrixType, 2>
template<typename Derived, typename OtherDerived>
struct ei_compute_inverse<Derived, OtherDerived, 2>
{
static inline void run(const MatrixType& matrix, MatrixType* result)
static inline void run(const Derived& matrix, OtherDerived* result)
{
ei_compute_inverse_in_size2_case(matrix, result);
}
};
template<typename MatrixType>
struct ei_compute_inverse<MatrixType, 3>
template<typename Derived, typename OtherDerived>
struct ei_compute_inverse<Derived, OtherDerived, 3>
{
static inline void run(const MatrixType& matrix, MatrixType* result)
static inline void run(const Derived& matrix, OtherDerived* result)
{
ei_compute_inverse_in_size3_case(matrix, result);
}
};
template<typename MatrixType>
struct ei_compute_inverse<MatrixType, 4>
template<typename Derived, typename OtherDerived>
struct ei_compute_inverse<Derived, OtherDerived, 4>
{
static inline void run(const MatrixType& matrix, MatrixType* result)
static inline void run(const Derived& matrix, OtherDerived* result)
{
ei_compute_inverse_in_size4_case(matrix, result);
ei_compute_inverse_in_size4_case<Derived, OtherDerived>::run(matrix, *result);
}
};
@@ -216,12 +290,12 @@ struct ei_compute_inverse<MatrixType, 4>
* \sa inverse()
*/
template<typename Derived>
inline void MatrixBase<Derived>::computeInverse(EvalType *result) const
template<typename OtherDerived>
inline void MatrixBase<Derived>::computeInverse(MatrixBase<OtherDerived> *result) const
{
typedef typename ei_eval<Derived>::type MatrixType;
ei_assert(rows() == cols());
EIGEN_STATIC_ASSERT(NumTraits<Scalar>::HasFloatingPoint,numeric_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, OtherDerived>::run(eval(), static_cast<OtherDerived*>(result));
}
/** \lu_module
@@ -239,9 +313,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;
}

View File

@@ -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()
*/
@@ -61,19 +63,34 @@ template<typename MatrixType> class LU
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
typedef Matrix<int, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> IntRowVectorType;
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> IntColVectorType;
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> RowVectorType;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> ColVectorType;
enum { MaxSmallDimAtCompileTime = EIGEN_ENUM_MIN(
enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN(
MatrixType::MaxColsAtCompileTime,
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.
*
@@ -270,7 +297,8 @@ template<typename MatrixType> class LU
*
* \sa MatrixBase::computeInverse(), inverse()
*/
inline void computeInverse(MatrixType *result) const
template<typename ResultType>
inline void computeInverse(ResultType *result) const
{
solve(MatrixType::Identity(m_lu.rows(), m_lu.cols()), result);
}
@@ -290,72 +318,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>
@@ -365,7 +407,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();
@@ -374,31 +417,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>
@@ -410,6 +452,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(
@@ -421,51 +482,48 @@ 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))
RealScalar biggest_in_c = m_rank>0 ? c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff() : RealScalar(0);
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);
if(m_rank>0)
m_lu.corner(TopLeft, m_rank, m_rank)
.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;
}
@@ -476,10 +534,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

View File

@@ -0,0 +1,6 @@
FILE(GLOB Eigen_LeastSquares_SRCS "*.h")
INSTALL(FILES
${Eigen_LeastSquares_SRCS}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/LeastSquares
)

View File

@@ -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.benoit.1@gmail.com>
// 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.
@@ -54,10 +54,13 @@
* constants \f$a,b,c\f$ so that the plane of equation \f$y=ax+bz+c\f$ fits
* best the five above points. To do that, call this function as follows:
* @code
// create a vector of pointers to the points
std::vector<Vector3d> points_ptrs(5);
for(int k=0; k<5; ++k) points_ptrs[k] = &points[k];
Vector3d coeffs; // will store the coefficients a, b, c
linearRegression(
5,
points,
&(points_ptrs[0]),
&coeffs,
1 // the coord to express as a function of
// the other ones. 0 means x, 1 means y, 2 means z.
@@ -80,11 +83,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 +104,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 +157,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 +182,4 @@ void fitHyperplane(int numPoints,
}
#endif // EIGEN_REGRESSION_H
#endif // EIGEN_LEASTSQUARES_H

View File

@@ -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>
//
@@ -53,9 +53,18 @@ template<typename _MatrixType> class EigenSolver
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);
}
@@ -94,12 +103,20 @@ template<typename _MatrixType> class EigenSolver
*
* \sa pseudoEigenvalueMatrix()
*/
const MatrixType& pseudoEigenvectors() const { return m_eivec; }
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 { return m_eivalues; }
EigenvalueType eigenvalues() const
{
ei_assert(m_isInitialized && "EigenSolver is not initialized.");
return m_eivalues;
}
void compute(const MatrixType& matrix);
@@ -111,6 +128,7 @@ 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.
@@ -120,9 +138,10 @@ template<typename _MatrixType> class EigenSolver
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++)
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));
@@ -130,7 +149,7 @@ MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
{
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++;
++i;
}
}
return matD;
@@ -143,26 +162,27 @@ MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
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++)
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);
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++)
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++;
++j;
}
}
return matV;
@@ -183,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.
@@ -198,7 +220,7 @@ 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.
RealScalar scale = matH.block(m, m-1, high-m+1, 1).cwise().abs().sum();
@@ -282,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;
@@ -290,13 +312,12 @@ 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.row(j).segment(std::max(j-1,0), nn-std::max(j-1,0)).cwise().abs().sum();
}
@@ -322,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;
@@ -345,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;
@@ -361,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);
@@ -369,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);
@@ -377,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);
@@ -386,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;
@@ -410,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);
}
}
@@ -463,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)
@@ -471,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)
{
@@ -510,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)
@@ -523,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)
@@ -536,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)
@@ -655,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));
@@ -686,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 !!

View File

@@ -243,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;
}

View File

@@ -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>
//
@@ -49,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;
@@ -110,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).squaredNorm(),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);
@@ -136,12 +257,52 @@ 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);
// enforce the computation of the rank
rank();
result->resize(m_qr.cols(), 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(m_rank==0)
return result->isZero();
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), ...]
@@ -169,10 +330,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());
}

View File

@@ -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>
//
@@ -52,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);
}
@@ -105,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;
@@ -170,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 ?
@@ -202,7 +229,7 @@ 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.segment(i,n-i).minCoeff(&k);
@@ -235,22 +262,22 @@ compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors
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();
}
@@ -267,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>
@@ -287,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(
@@ -315,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;
@@ -338,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

View File

@@ -164,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;
}
@@ -201,6 +201,7 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
// squared norm of the vector v skipping the first element
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.;
@@ -223,17 +224,17 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
/* 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
@@ -256,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
@@ -268,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
@@ -292,7 +293,7 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType&
{
int starti = i+1;
int alignedEnd = starti;
if (PacketSize>1)
if (PacketSize>1 && (int(MatrixType::Flags)&RowMajor) == 0)
{
int alignedStart = (starti) + ei_alignmentOffset(&matA.coeffRef(starti,j1), n-starti);
alignedEnd = alignedStart + ((n-alignedStart)/PacketSize)*PacketSize;
@@ -331,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
{
@@ -389,7 +391,7 @@ void Tridiagonalization<MatrixType>::_decomposeInPlace3x3(MatrixType& mat, Diago
{
diag[0] = ei_real(mat(0,0));
RealScalar v1norm2 = ei_abs2(mat(0,2));
if (ei_isMuchSmallerThan(v1norm2, RealScalar(1)))
if (v1norm2==RealScalar(0))
{
diag[1] = ei_real(mat(1,1));
diag[2] = ei_real(mat(2,2));

View File

@@ -1,6 +0,0 @@
FILE(GLOB Eigen_Regression_SRCS "*.h")
INSTALL(FILES
${Eigen_Regression_SRCS}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Regression
)

View File

@@ -49,7 +49,7 @@ template<typename MatrixType> class SVD
enum {
PacketSize = ei_packet_traits<Scalar>::size,
AlignmentMask = int(PacketSize)-1,
MinSize = EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
MinSize = EIGEN_SIZE_MIN(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
};
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVector;
@@ -61,6 +61,8 @@ template<typename MatrixType> class SVD
public:
SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
SVD(const MatrixType& matrix)
: m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())),
m_matV(matrix.cols(),matrix.cols()),
@@ -79,6 +81,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;
@@ -98,6 +109,8 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
const int m = matrix.rows();
const int n = matrix.cols();
const int nu = std::min(m,n);
ei_assert(m>=n && "In Eigen 2.0, SVD only works for MxN matrices with M>=N. Sorry!");
ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices");
m_matU.resize(m, nu);
m_matU.setZero();
@@ -115,7 +128,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)
{
@@ -132,7 +145,7 @@ 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))
{
@@ -168,7 +181,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);
}
@@ -192,7 +205,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;
@@ -201,14 +214,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();
}
@@ -227,7 +240,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);
@@ -242,7 +255,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;
@@ -260,7 +273,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;
@@ -277,11 +290,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;
@@ -302,7 +315,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
k = ks;
}
}
k++;
++k;
// Perform the task indicated by kase.
switch (kase)
@@ -313,9 +326,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;
@@ -326,7 +339,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);
@@ -342,9 +355,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;
@@ -352,7 +365,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);
@@ -375,7 +388,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))
@@ -390,9 +403,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)
@@ -403,14 +416,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;
@@ -420,7 +433,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);
@@ -439,7 +452,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);
}
@@ -456,7 +469,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--;
@@ -473,12 +486,12 @@ SVD<MatrixType>& SVD<MatrixType>::sort()
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;
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)
{
@@ -520,7 +533,7 @@ bool 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))
@@ -534,14 +547,103 @@ bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* resul
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

View File

@@ -98,7 +98,9 @@ template<typename _Scalar> class AmbiVector
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));
std::memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
delete[] m_buffer;
m_buffer = newBuffer;
}
protected:
@@ -202,7 +204,7 @@ Scalar& AmbiVector<Scalar>::coeffRef(int i)
// this is the first element
m_llStart = 0;
m_llCurrent = 0;
m_llSize++;
++m_llSize;
llElements[0].value = Scalar(0);
llElements[0].index = i;
llElements[0].next = -1;
@@ -216,7 +218,7 @@ Scalar& AmbiVector<Scalar>::coeffRef(int i)
el.index = i;
el.next = m_llStart;
m_llStart = m_llSize;
m_llSize++;
++m_llSize;
m_llCurrent = m_llStart;
return el.value;
}
@@ -238,15 +240,18 @@ Scalar& AmbiVector<Scalar>::coeffRef(int i)
else
{
if (m_llSize>=m_allocatedElements)
{
reallocateSparse();
ei_internal_assert(m_llSize<m_size && "internal error: overflow in sparse mode");
llElements = reinterpret_cast<ListEl*>(m_buffer);
}
ei_internal_assert(m_llSize<m_allocatedElements && "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++;
++m_llSize;
return el.value;
}
}
@@ -332,7 +337,7 @@ class AmbiVector<_Scalar>::Iterator
if (m_isDense)
{
do {
m_cachedIndex++;
++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];
@@ -365,6 +370,9 @@ class AmbiVector<_Scalar>::Iterator
int m_cachedIndex; // current coordinate
Scalar m_cachedValue; // current value
bool m_isDense; // mode of the vector
private:
Iterator& operator=(const Iterator&);
};

View File

@@ -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
)

Some files were not shown because too many files have changed in this diff Show More