Compare commits

..

200 Commits

Author SHA1 Message Date
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
183 changed files with 8289 additions and 2284 deletions

24
.hgignore Normal file
View File

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

View File

@@ -1,22 +1,15 @@
project(Eigen)
set(EIGEN_VERSION_NUMBER "2.0-beta6")
#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_SVNVERSION_OUTPUT)
#we only want EIGEN_SVN_REVISION if it is an actual revision number, not a string like "exported"
string(REGEX MATCH "^[0-9]+.*" EIGEN_SVN_REVISION "${EIGEN_SVNVERSION_OUTPUT}")
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.6.2)
set(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include/eigen2"
CACHE PATH
"The directory where we install the header files"
FORCE)
set(EIGEN_VERSION_NUMBER "2.0.9")
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
option(EIGEN_BUILD_TESTS "Build tests" OFF)
@@ -25,6 +18,9 @@ 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)
@@ -34,7 +30,12 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_SYSTEM_NAME MATCHES Linux)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wextra -fno-exceptions -fno-check-new -fno-common -fstrict-aliasing")
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)
@@ -76,9 +77,23 @@ if(MSVC)
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 lib/pkgconfig
)
endif(EIGEN_BUILD_PKGCONFIG)
add_subdirectory(Eigen)
add_subdirectory(unsupported)
if(EIGEN_BUILD_TESTS)
include(CTest)

View File

@@ -3,11 +3,11 @@
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(Dart)
set(CTEST_PROJECT_NAME "Eigen")
set(CTEST_NIGHTLY_START_TIME "05:00:00 UTC")
## 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 "www.cdash.org")
set(CTEST_DROP_LOCATION "/CDashPublic/submit.php?project=Eigen")
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

@@ -7,7 +7,7 @@
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:
@@ -26,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"

View File

@@ -1,4 +1,6 @@
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression LeastSquares StdVector)
set(Eigen_HEADERS Core LU Cholesky QR Geometry
Sparse Array SVD LeastSquares
QtAlignedMalloc StdVector NewStdVector)
if(EIGEN_BUILD_LIB)
set(Eigen_SRCS
@@ -20,12 +22,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

@@ -17,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(),
@@ -31,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); \

View File

@@ -7,11 +7,10 @@
#ifdef _MSC_VER
#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
#ifdef _M_IX86_FP
#if _M_IX86_FP >= 2
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
#endif
// 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
@@ -69,6 +68,13 @@
#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 {
/** \defgroup Core_Module Core module

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

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

View File

@@ -5,21 +5,20 @@
#include "src/Core/util/DisableMSVCWarnings.h"
#include "LU"
#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

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 size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template<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

@@ -19,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(),

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

@@ -1,5 +0,0 @@
#ifdef __GNUC__
#warning "The Eigen/Regression header file has been renamed to Eigen/LeastSquares. The old name is deprecated, please update your code."
#endif
#include "LeastSquares"

View File

@@ -8,6 +8,9 @@
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()

View File

@@ -22,7 +22,6 @@
#endif
#ifdef EIGEN_TAUCS_SUPPORT
// taucs.h declares a lot of mess
#define isnan
#define finite
@@ -40,7 +39,9 @@
#ifdef max
#undef max
#endif
#ifdef complex
#undef complex
#endif
#endif
#ifdef EIGEN_SUPERLU_SUPPORT
@@ -70,17 +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/DynamicSparseMatrix.h"
#include "src/Sparse/MappedSparseMatrix.h"
#include "src/Sparse/SparseVector.h"
#include "src/Sparse/CoreIterators.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"

View File

@@ -1,15 +1,147 @@
#ifdef EIGEN_USE_NEW_STDVECTOR
#include "NewStdVector"
#else
#ifndef EIGEN_STDVECTOR_MODULE_H
#define EIGEN_STDVECTOR_MODULE_H
#include "Core"
#include <vector>
#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 {
#include "src/StdVector/UnalignedType.h"
} // 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 {
#include "src/StdVector/StdVector.h"
} // 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;
@@ -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;
@@ -130,4 +130,16 @@ inline bool MatrixBase<Derived>::any(void) const
}
}
/** \array_module
*
* \returns the number of coefficients which evaluate to true
*
* \sa MatrixBase::all(), MatrixBase::any()
*/
template<typename Derived>
inline int MatrixBase<Derived>::count() const
{
return this->cast<bool>().cast<int>().sum();
}
#endif // EIGEN_ALLANDANY_H

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
@@ -173,7 +180,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
};
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */
@@ -246,6 +253,16 @@ 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.
@@ -275,6 +292,9 @@ template<typename ExpressionType, int Direction> class PartialRedux
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

@@ -108,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, LowerTriangular> matrixL(void) const { return m_matrix; }
/** \deprecated */
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
template<typename Derived>
EIGEN_DEPRECATED typename MatrixBase<Derived>::PlainMatrixType_ColMajor solve(const MatrixBase<Derived> &b) const;
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 MatrixBase<Derived>::PlainMatrixType_ColMajor Cholesky<MatrixType>::solve(const MatrixBase<Derived> &b) const
{
const int size = m_matrix.rows();
ei_assert(size==b.rows());
typename MatrixBase<Derived>::PlainMatrixType_ColMajor 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<UpperTriangular>().solveTriangularInPlace(bAndX);
return true;
}
/** \cholesky_module
* \deprecated has been renamed llt()
*/
template<typename Derived>
inline const Cholesky<typename MatrixBase<Derived>::PlainMatrixType>
MatrixBase<Derived>::cholesky() const
{
return Cholesky<PlainMatrixType>(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, 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(); }
/** \returns true if the matrix is positive definite */
inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
template<typename Derived>
EIGEN_DEPRECATED typename Derived::Eval solve(const MatrixBase<Derived> &b) const;
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<UnitUpperTriangular>()
.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<UnitUpperTriangular>().solveTriangularInPlace(bAndX);
return true;
}
/** \cholesky_module
* \deprecated has been renamed ldlt()
*/
template<typename Derived>
inline const CholeskyWithoutSquareRoot<typename MatrixBase<Derived>::PlainMatrixType>
MatrixBase<Derived>::choleskyNoSqrt() const
{
return derived();
}
#endif // EIGEN_CHOLESKY_WITHOUT_SQUARE_ROOT_H

View File

@@ -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;
@@ -152,9 +152,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");

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, LowerTriangular> 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,34 @@ 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);
if(size==1)
{
m_isInitialized = true;
return;
}
m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
for (int j = 1; j < size; ++j)
{
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 +156,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 +174,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 +187,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,10 +198,9 @@ 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<UpperTriangular>().solveTriangularInPlace(bAndX);
return true;

View File

@@ -353,7 +353,7 @@ 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)
{
@@ -401,6 +401,8 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
::lazyAssign(const MatrixBase<OtherDerived>& other)
{
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();
@@ -437,8 +439,6 @@ template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
::operator=(const MatrixBase<OtherDerived>& other)
{
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)
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==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

@@ -81,7 +81,7 @@ static void ei_cache_friendly_product(
MaxBlockRows_ClampingMask = 0xFFFFF8,
#endif
// maximal size of the blocks fitted in L2 cache
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_L2_CACHE_SIZE,Scalar>::width
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_CPU_CACHE_SIZE,Scalar>::width
};
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));
@@ -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;
@@ -361,13 +361,14 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
#ifdef _EIGEN_ACCUMULATE_PACKETS
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
#endif
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2,OFFSET) \
ei_pstore(&res[j OFFSET], \
ei_padd(ei_pload(&res[j OFFSET]), \
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) \
ei_pstore(&res[j], \
ei_padd(ei_pload(&res[j]), \
ei_padd( \
ei_padd(ei_pmul(ptmp0,ei_pload ## A0(&lhs0[j OFFSET])),ei_pmul(ptmp1,ei_pload ## A13(&lhs1[j OFFSET]))), \
ei_padd(ei_pmul(ptmp2,ei_pload ## A2(&lhs2[j OFFSET])),ei_pmul(ptmp3,ei_pload ## A13(&lhs3[j OFFSET]))) )))
ei_padd(ei_pmul(ptmp0,EIGEN_CAT(ei_ploa , A0)(&lhs0[j])), \
ei_pmul(ptmp1,EIGEN_CAT(ei_ploa , A13)(&lhs1[j]))), \
ei_padd(ei_pmul(ptmp2,EIGEN_CAT(ei_ploa , A2)(&lhs2[j])), \
ei_pmul(ptmp3,EIGEN_CAT(ei_ploa , A13)(&lhs3[j]))) )))
typedef typename ei_packet_traits<Scalar>::type Packet;
const int PacketSize = sizeof(Packet)/sizeof(Scalar);
@@ -397,7 +398,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
if (PacketSize>1)
{
ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
while (skipColumns<PacketSize &&
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%PacketSize))
++skipColumns;
@@ -418,7 +419,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
int offset1 = (FirstAligned && alignmentStep==1?3:1);
int offset3 = (FirstAligned && alignmentStep==1?1:3);
int columnBound = ((rhs.size()-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
for (int i=skipColumns; i<columnBound; i+=columnsAtOnce)
{
@@ -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,11 +483,11 @@ 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;
}
}
@@ -494,7 +495,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
/* process remaining coeffs (or all if there is no explicit vectorization) */
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];
res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
}
// process remaining first and last columns (at most columnsAtOnce-1)
@@ -550,12 +551,12 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
#endif
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2,OFFSET) {\
#define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) {\
Packet b = ei_pload(&rhs[j]); \
ptmp0 = ei_pmadd(b, ei_pload##A0 (&lhs0[j]), ptmp0); \
ptmp1 = ei_pmadd(b, ei_pload##A13(&lhs1[j]), ptmp1); \
ptmp2 = ei_pmadd(b, ei_pload##A2 (&lhs2[j]), ptmp2); \
ptmp3 = ei_pmadd(b, ei_pload##A13(&lhs3[j]), ptmp3); }
ptmp0 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A0) (&lhs0[j]), ptmp0); \
ptmp1 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs1[j]), ptmp1); \
ptmp2 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A2) (&lhs2[j]), ptmp2); \
ptmp3 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs3[j]), ptmp3); }
typedef typename ei_packet_traits<Scalar>::type Packet;
const int PacketSize = sizeof(Packet)/sizeof(Scalar);
@@ -580,13 +581,13 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
// we cannot assume the first element is aligned because of sub-matrices
const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
// find how many rows do we have to skip to be aligned with rhs (if possible)
int skipRows = 0;
if (PacketSize>1)
{
ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
while (skipRows<PacketSize &&
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%PacketSize))
++skipRows;
@@ -607,7 +608,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
int offset1 = (FirstAligned && alignmentStep==1?3:1);
int offset3 = (FirstAligned && alignmentStep==1?1:3);
int rowBound = ((res.size()-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
for (int i=skipRows; i<rowBound; i+=rowsAtOnce)
{
@@ -621,7 +622,7 @@ 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)
@@ -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);

View File

@@ -313,6 +313,8 @@ EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
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
@@ -377,4 +379,6 @@ EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int index, const Matrix
other.derived().template packet<LoadMode>(index));
}
#endif
#endif // EIGEN_COEFFS_H

View File

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

View File

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

@@ -86,14 +86,12 @@ class CwiseBinaryOp : ei_no_assignment_operator,
typedef typename ei_traits<CwiseBinaryOp>::LhsNested LhsNested;
typedef typename ei_traits<CwiseBinaryOp>::RhsNested RhsNested;
class InnerIterator;
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

View File

@@ -146,6 +146,7 @@ template<typename CustomNullaryOp>
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);
@@ -227,6 +228,7 @@ MatrixBase<Derived>::Constant(const Scalar& value)
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
@@ -238,9 +240,29 @@ bool MatrixBase<Derived>::isApproxToConstant
return true;
}
/** This is just an alias for isApproxToConstant().
*
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<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>
EIGEN_STRONG_INLINE void MatrixBase<Derived>::fill(const Scalar& value)
{
setConstant(value);
}
/** Sets all coefficients in this expression to \a value.
*
* \sa class CwiseNullaryOp, Zero(), Ones()
* \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)
@@ -248,6 +270,42 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setConstant(const Scalar& valu
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.
@@ -344,6 +402,41 @@ 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.
@@ -437,6 +530,41 @@ 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).
@@ -546,6 +674,24 @@ 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

View File

@@ -64,8 +64,6 @@ 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) {}

View File

@@ -26,6 +26,7 @@
#define EIGEN_DIAGONALMATRIX_H
/** \class DiagonalMatrix
* \nonstableyet
*
* \brief Expression of a diagonal matrix
*
@@ -61,6 +62,7 @@ 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>
@@ -91,7 +93,8 @@ class DiagonalMatrix : ei_no_assignment_operator,
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
*
@@ -109,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

View File

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

@@ -143,13 +143,12 @@ struct ei_dot_vec_unroller<Derived1, Derived2, Index, Stop, true>
template<typename Derived1, typename Derived2,
int Vectorization = ei_dot_traits<Derived1, Derived2>::Vectorization,
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling,
int Storage = (ei_traits<Derived1>::Flags | ei_traits<Derived2>::Flags) & SparseBit
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling
>
struct ei_dot_impl;
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling, IsDense>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
{
typedef typename Derived1::Scalar Scalar;
static Scalar run(const Derived1& v1, const Derived2& v2)
@@ -164,12 +163,12 @@ struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling, IsDense>
};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling, IsDense>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
: public ei_dot_novec_unroller<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
{};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling, IsDense>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
{
typedef typename Derived1::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -222,7 +221,7 @@ struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling, IsDense
};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling, IsDense>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
{
typedef typename Derived1::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -270,25 +269,7 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
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((*this).cwise().abs2().sum());
}
/** \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()
*/
@@ -298,9 +279,7 @@ inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<
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.
*
* \only_for_vectors
/** \returns the \em l2 norm of *this, i.e., for vectors, the square root of the dot product of *this with itself.
*
* \sa dot(), squaredNorm()
*/

View File

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

@@ -279,6 +279,8 @@ struct ei_scalar_multiple_op {
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> >
@@ -294,6 +296,8 @@ struct ei_scalar_quotient1_impl {
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> >
@@ -306,6 +310,8 @@ struct ei_scalar_quotient1_impl<Scalar,false> {
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> >
@@ -323,6 +329,8 @@ template<typename Scalar>
struct ei_scalar_quotient1_op : ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint > {
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
@@ -335,6 +343,8 @@ struct ei_scalar_constant_op {
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> >
@@ -348,6 +358,12 @@ template<typename Scalar>
struct ei_functor_traits<ei_scalar_identity_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
// 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.

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

@@ -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
{
@@ -95,7 +107,11 @@ template<typename Derived> class MapBase
inline Scalar& coeffRef(int index)
{
return *const_cast<Scalar*>(m_data + index);
ei_assert(Derived::IsVectorAtCompileTime || (ei_traits<Derived>::Flags & LinearAccessBit));
if ( ((RowsAtCompileTime == 1) == IsRowMajor) )
return const_cast<Scalar*>(m_data)[index];
else
return const_cast<Scalar*>(m_data)[index*stride()];
}
template<int LoadMode>
@@ -150,6 +166,19 @@ template<typename Derived> class MapBase
&& 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; }

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()
@@ -49,6 +50,7 @@ template<typename T> inline T ei_hypot(T x, T y)
**************/
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; }
@@ -59,12 +61,8 @@ 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 int(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)
{
@@ -93,6 +91,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; }
@@ -103,6 +102,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)
@@ -138,6 +138,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; }
@@ -148,6 +150,7 @@ inline double ei_exp(double x) { return std::exp(x); }
inline double ei_log(double x) { return std::log(x); }
inline double ei_sin(double x) { return std::sin(x); }
inline double ei_cos(double x) { return std::cos(x); }
inline double ei_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)
@@ -183,6 +186,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); }
@@ -191,6 +195,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()
{
@@ -216,6 +221,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); }
@@ -224,6 +230,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()
{
@@ -250,6 +257,7 @@ inline bool ei_isApprox(const std::complex<double>& a, const std::complex<double
******************/
template<> inline long double precision<long double>() { return precision<double>(); }
template<> inline long double machine_epsilon<long double>() { return 1.084e-19l; }
inline long double ei_real(long double x) { return x; }
inline long double ei_imag(long double) { return 0.; }
inline long double ei_conj(long double x) { return x; }
@@ -260,6 +268,7 @@ 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)

View File

@@ -100,6 +100,7 @@
* when the exact numbers of rows and columns are not known are compile-time, but it is known at compile-time that they cannot
* exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case _MaxRows and _MaxCols
* are the dimensions of the original matrix, while _Rows and _Cols are Dynamic.</dd>
* </dl>
*
* \see MatrixBase for the majority of the API methods for matrices
*/
@@ -113,8 +114,7 @@ struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
MaxRowsAtCompileTime = _MaxRows,
MaxColsAtCompileTime = _MaxCols,
Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
CoeffReadCost = NumTraits<Scalar>::ReadCost,
SupportedAccessPatterns = RandomAccessPattern
CoeffReadCost = NumTraits<Scalar>::ReadCost
};
};
@@ -137,6 +137,9 @@ class Matrix
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); }
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
EIGEN_STRONG_INLINE int cols() const { return m_storage.cols(); }
@@ -226,12 +229,10 @@ 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));
ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
m_storage.resize(rows * cols, rows, cols);
}
@@ -241,7 +242,6 @@ 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)
if(RowsAtCompileTime == 1)
m_storage.resize(size, 1, size);
@@ -249,49 +249,19 @@ class Matrix
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>
EIGEN_STRONG_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());
}
/** 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
@@ -299,7 +269,7 @@ class Matrix
*/
EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
{
return operator=<Matrix>(other);
return _set(other);
}
EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, +=)
@@ -311,34 +281,23 @@ 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)
*/
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
{
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
_check_template_params();
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
Matrix(ei_constructor_without_unaligned_array_assert)
: m_storage(ei_constructor_without_unaligned_array_assert()) {}
: m_storage(ei_constructor_without_unaligned_array_assert())
{}
#endif
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
*
@@ -349,6 +308,7 @@ class Matrix
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);
@@ -366,6 +326,7 @@ class Matrix
*/
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))
{
@@ -381,6 +342,7 @@ class Matrix
/** constructs an initialized 2D vector with given coefficients */
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;
@@ -388,6 +350,7 @@ class Matrix
/** constructs an initialized 2D vector with given coefficients */
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;
@@ -395,6 +358,7 @@ class Matrix
/** constructs an initialized 3D vector with given coefficients */
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;
@@ -403,6 +367,7 @@ class Matrix
/** constructs an initialized 4D vector with given coefficients */
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;
@@ -417,14 +382,15 @@ class Matrix
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 */
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() {}
@@ -432,13 +398,8 @@ class Matrix
/** 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,
@@ -475,6 +436,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>
@@ -486,8 +466,113 @@ 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)
{
ei_matrix_swap_impl<Matrix, OtherDerived>::run(*this, *const_cast<MatrixBase<OtherDerived>*>(&other));
}
/** \defgroup matrixtypedefs Global matrix typedefs
*
* \ingroup Core_Module

View File

@@ -229,10 +229,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)
*/
@@ -241,6 +237,11 @@ template<typename Derived> class MatrixBase
return this->operator=<Derived>(other);
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
template<typename OtherDerived>
Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
/** Overloaded for cache friendly product evaluation */
template<typename Lhs, typename Rhs>
Derived& lazyAssign(const Product<Lhs,Rhs,CacheFriendlyProduct>& product);
@@ -249,10 +250,7 @@ template<typename Derived> class MatrixBase
template<typename OtherDerived>
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
{ return lazyAssign(other._expression()); }
/** Overloaded for sparse product evaluation */
template<typename Derived1, typename Derived2>
Derived& lazyAssign(const Product<Derived1,Derived2,SparseProduct>& product);
#endif // not EIGEN_PARSED_BY_DOXYGEN
CommaInitializer<Derived> operator<< (const Scalar& s);
@@ -346,13 +344,12 @@ template<typename Derived> class MatrixBase
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 PlainMatrixType normalized() const;
void normalize();
@@ -448,6 +445,7 @@ template<typename Derived> class MatrixBase
const DiagonalMatrix<Derived> asDiagonal() const;
void fill(const Scalar& value);
Derived& setConstant(const Scalar& value);
Derived& setZero();
Derived& setOnes();
@@ -465,6 +463,7 @@ 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;
@@ -533,8 +532,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
@@ -559,6 +561,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;
@@ -593,9 +596,6 @@ template<typename Derived> class MatrixBase
const LLT<PlainMatrixType> llt() const;
const LDLT<PlainMatrixType> ldlt() const;
// deprecated:
const Cholesky<PlainMatrixType> cholesky() const;
const CholeskyWithoutSquareRoot<PlainMatrixType> choleskyNoSqrt() const;
/////////// QR module ///////////
@@ -615,6 +615,15 @@ template<typename Derived> class MatrixBase
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

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
@@ -41,7 +41,7 @@ template <typename T, int Size, int MatrixOptions,
{
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
ei_assert((reinterpret_cast<size_t>(array) & 0xf) == 0
&& "this assertion is explained here: http://eigen.tuxfamily.org/api/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
&& "this assertion is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
#endif
}
@@ -176,7 +176,10 @@ template<typename T, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic,
if(size != m_rows*m_cols)
{
ei_aligned_delete(m_data, m_rows*m_cols);
m_data = ei_aligned_new<T>(size);
if (size)
m_data = ei_aligned_new<T>(size);
else
m_data = 0;
}
m_rows = rows;
m_cols = cols;
@@ -203,7 +206,10 @@ template<typename T, int _Rows, int _Options> class ei_matrix_storage<T, Dynamic
if(size != _Rows*m_cols)
{
ei_aligned_delete(m_data, _Rows*m_cols);
m_data = ei_aligned_new<T>(size);
if (size)
m_data = ei_aligned_new<T>(size);
else
m_data = 0;
}
m_cols = cols;
}
@@ -229,7 +235,10 @@ template<typename T, int _Cols, int _Options> class ei_matrix_storage<T, Dynamic
if(size != m_rows*_Cols)
{
ei_aligned_delete(m_data, _Cols*m_rows);
m_data = ei_aligned_new<T>(size);
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

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

@@ -26,7 +26,8 @@
#ifndef EIGEN_PART_H
#define EIGEN_PART_H
/** \class Part
/** \nonstableyet
* \class Part
*
* \brief Expression of a triangular matrix extracted from a given matrix
*
@@ -116,18 +117,21 @@ 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 UpperTriangular, \c StrictlyUpperTriangular, \c UnitUpperTriangular,
* \c LowerTriangular, \c StrictlyLowerTriangular, \c UnitLowerTriangular.
@@ -278,7 +282,8 @@ 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 UpperTriangular, \c StrictlyUpperTriangular, \c LowerTriangular,
* \c StrictlyLowerTriangular, \c SelfAdjoint.

View File

@@ -79,7 +79,6 @@ struct ProductReturnType<Lhs,Rhs,CacheFriendlyProduct>
* - NormalProduct
* - CacheFriendlyProduct
* - DiagonalProduct
* - SparseProduct
*/
template<typename Lhs, typename Rhs> struct ei_product_mode
{
@@ -87,8 +86,6 @@ 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 == Dynamic
&& ( Lhs::MaxRowsAtCompileTime == Dynamic
|| Rhs::MaxColsAtCompileTime == Dynamic )
@@ -302,7 +299,7 @@ template<typename OtherDerived>
inline Derived &
MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
{
return *this = *this * other;
return derived() = derived() * other.derived();
}
/***************************************************************************
@@ -765,7 +762,7 @@ 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()
);
}

View File

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

View File

@@ -100,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;
@@ -120,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
};
@@ -154,13 +149,12 @@ struct ei_sum_vec_unroller<Derived, Index, Stop, true>
template<typename Derived,
int Vectorization = ei_sum_traits<Derived>::Vectorization,
int Unrolling = ei_sum_traits<Derived>::Unrolling,
int Storage = ei_traits<Derived>::Flags & SparseBit
int Unrolling = ei_sum_traits<Derived>::Unrolling
>
struct ei_sum_impl;
template<typename Derived>
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling, IsDense>
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
{
typedef typename Derived::Scalar Scalar;
static Scalar run(const Derived& mat)
@@ -178,12 +172,12 @@ struct ei_sum_impl<Derived, NoVectorization, NoUnrolling, IsDense>
};
template<typename Derived>
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling, IsDense>
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling>
: public ei_sum_novec_unroller<Derived, 0, Derived::SizeAtCompileTime>
{};
template<typename Derived>
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling,IsDense>
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
{
typedef typename Derived::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -228,7 +222,7 @@ struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling,IsDense>
};
template<typename Derived>
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling, IsDense>
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
{
typedef typename Derived::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -239,7 +233,7 @@ struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling, IsDense>
};
static Scalar run(const Derived& mat)
{
Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, VectorizationSize>::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,8 +63,6 @@ template<typename MatrixType> class Transpose
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
class InnerIterator;
inline Transpose(const MatrixType& matrix) : m_matrix(matrix) {}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
@@ -127,7 +125,20 @@ template<typename MatrixType> class Transpose
* Example: \include MatrixBase_transpose.cpp
* Output: \verbinclude MatrixBase_transpose.out
*
* \sa adjoint(), class DiagonalCoeffs */
* \warning If you want to replace a matrix by its own transpose, do \b NOT do this:
* \code
* m = m.transpose(); // bug!!! caused by aliasing effect
* \endcode
* Instead, use the transposeInPlace() method:
* \code
* m.transposeInPlace();
* \endcode
* which gives Eigen good opportunities for optimization, or alternatively you can also do:
* \code
* m = m.transpose().eval();
* \endcode
*
* \sa transposeInPlace(), adjoint() */
template<typename Derived>
inline Transpose<Derived>
MatrixBase<Derived>::transpose()
@@ -135,7 +146,11 @@ MatrixBase<Derived>::transpose()
return derived();
}
/** This is the const version of transpose(). \sa adjoint() */
/** This is the const version of transpose().
*
* Make sure you read the warning for transpose() !
*
* \sa transposeInPlace(), adjoint() */
template<typename Derived>
inline const Transpose<Derived>
MatrixBase<Derived>::transpose() const
@@ -148,6 +163,15 @@ MatrixBase<Derived>::transpose() const
* Example: \include MatrixBase_adjoint.cpp
* Output: \verbinclude MatrixBase_adjoint.out
*
* \warning If you want to replace a matrix by its own adjoint, do \b NOT do this:
* \code
* m = m.adjoint(); // bug!!! caused by aliasing effect
* \endcode
* Instead, do:
* \code
* m = m.adjoint().eval();
* \endcode
*
* \sa transpose(), conjugate(), class Transpose, class ei_scalar_conjugate_op */
template<typename Derived>
inline const typename MatrixBase<Derived>::AdjointReturnType
@@ -177,7 +201,7 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
if (m.rows()==m.cols())
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
else
m.set(m.transpose().eval());
m = m.transpose().eval();
}
};
@@ -185,10 +209,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

@@ -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,6 +37,10 @@ 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<> 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<> 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); }
@@ -63,7 +67,7 @@ template<> EIGEN_STRONG_INLINE __m128 ei_pdiv<__m128>(const __m128& a, const _
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;
}
@@ -102,10 +106,6 @@ template<> EIGEN_STRONG_INLINE __m128 ei_ploadu<float>(const float* from) { r
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<> 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<> 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); }
@@ -114,9 +114,16 @@ template<> EIGEN_STRONG_INLINE void ei_pstoreu<float>(float* to, const __m128&
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); }
#ifdef _MSC_VER
// this fix internal compilation error
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { double x = _mm_cvtsd_f64(a); return x; }
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
#else
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return _mm_cvtss_f32(a); }
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return _mm_cvtsd_f64(a); }
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { return _mm_cvtsi128_si32(a); }
#endif
#ifdef __SSE3__
// TODO implement SSE2 versions as well as integer versions
@@ -308,4 +315,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

@@ -201,7 +201,7 @@ 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
@@ -239,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

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

View File

@@ -106,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;
@@ -122,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

@@ -30,12 +30,48 @@
#define EIGEN_WORLD_VERSION 2
#define EIGEN_MAJOR_VERSION 0
#define EIGEN_MINOR_VERSION 0
#define EIGEN_MINOR_VERSION 9
#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(__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)
#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
@@ -50,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 \
@@ -139,18 +183,25 @@ using Eigen::ei_cos;
* 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 (defined __GNUC__)
#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
#define EIGEN_ALIGN_128
#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 16000000
#define EIGEN_STACK_ALLOCATION_LIMIT 1000000
#endif
#ifndef EIGEN_DEFAULT_IO_FORMAT
@@ -165,18 +216,18 @@ using Eigen::ei_cos;
template<typename OtherDerived> \
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()); \
} \
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> \
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) \
@@ -208,4 +259,15 @@ _EIGEN_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::MatrixBase<Derived>)
#define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
#define EIGEN_ENUM_MAX(a,b) (((int)a >= (int)b) ? (int)a : (int)b)
// just an empty macro !
#define EIGEN_EMPTY
// concatenate two tokens
#define EIGEN_CAT2(a,b) a ## b
#define EIGEN_CAT(a,b) EIGEN_CAT2(a,b)
// convert a token to a string
#define EIGEN_MAKESTRING2(a) #a
#define EIGEN_MAKESTRING(a) EIGEN_MAKESTRING2(a)
#endif // EIGEN_MACROS_H

View File

@@ -1,8 +1,8 @@
// 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
@@ -27,13 +27,23 @@
#ifndef EIGEN_MEMORY_H
#define EIGEN_MEMORY_H
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN64)
// 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
#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 _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))
#if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
#define EIGEN_HAS_POSIX_MEMALIGN 1
#else
#define EIGEN_HAS_POSIX_MEMALIGN 0
@@ -65,7 +75,7 @@ inline void ei_handmade_aligned_free(void *ptr)
}
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
* 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(size_t size)
{
@@ -73,35 +83,30 @@ inline void* ei_aligned_malloc(size_t size)
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *result;
#if EIGEN_HAS_POSIX_MEMALIGN && !EIGEN_MALLOC_ALREADY_ALIGNED
#ifdef EIGEN_EXCEPTIONS
const int failed =
#endif
posix_memalign(&result, 16, size);
void *result;
#if !EIGEN_ALIGN
result = malloc(size);
#elif EIGEN_MALLOC_ALREADY_ALIGNED
result = 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
#if EIGEN_MALLOC_ALREADY_ALIGNED
result = malloc(size);
#elif EIGEN_HAS_MM_MALLOC
result = _mm_malloc(size, 16);
#elif (defined _MSC_VER)
result = _aligned_malloc(size, 16);
#else
result = ei_handmade_aligned_malloc(size);
#endif
#ifdef EIGEN_EXCEPTIONS
const int failed = (result == 0);
#endif
result = ei_handmade_aligned_malloc(size);
#endif
#ifdef EIGEN_EXCEPTIONS
if(failed)
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 undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
* 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(size_t size)
{
@@ -114,11 +119,20 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *void_result = malloc(size);
void *result = malloc(size);
#ifdef EIGEN_EXCEPTIONS
if(!void_result) throw std::bad_alloc();
if(!result) throw std::bad_alloc();
#endif
return void_result;
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, size_t size)
{
for (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.
@@ -127,21 +141,23 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
*/
template<typename T> inline T* ei_aligned_new(size_t size)
{
void *void_result = ei_aligned_malloc(sizeof(T)*size);
return ::new(void_result) T[size];
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(size_t size)
{
void *void_result = ei_conditional_aligned_malloc<Align>(sizeof(T)*size);
return ::new(void_result) 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_MALLOC_ALREADY_ALIGNED
#if !EIGEN_ALIGN
free(ptr);
#elif EIGEN_MALLOC_ALREADY_ALIGNED
free(ptr);
#elif EIGEN_HAS_POSIX_MEMALIGN
free(ptr);
@@ -166,10 +182,10 @@ template<> inline void ei_conditional_aligned_free<false>(void *ptr)
free(ptr);
}
/** \internal delete the elements of an array.
/** \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_delete_elements_of_array(T *ptr, size_t size)
template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
{
// always destruct an array starting from the end.
while(size) ptr[--size].~T();
@@ -180,7 +196,7 @@ template<typename T> inline void ei_delete_elements_of_array(T *ptr, size_t size
*/
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
{
ei_delete_elements_of_array<T>(ptr, size);
ei_destruct_elements_of_array<T>(ptr, size);
ei_aligned_free(ptr);
}
@@ -189,7 +205,7 @@ template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
*/
template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
{
ei_delete_elements_of_array<T>(ptr, size);
ei_destruct_elements_of_array<T>(ptr, size);
ei_conditional_aligned_free<Align>(ptr);
}
@@ -228,89 +244,54 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
#define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
#endif
#define ei_aligned_stack_new(TYPE,SIZE) ::new(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)) TYPE[SIZE]
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_delete_elements_of_array<TYPE>(PTR, SIZE); \
#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)
/** Qt <= 4.4 has a bug where it calls new(ptr) T instead of ::new(ptr) T.
* This fails as we overload other operator new but not this one. What Qt really means is placement new.
* Since this is getting used only with fixed-size Eigen matrices where the ctor does nothing, it is OK to
* emulate placement new by just returning the ptr -- no need to call ctors. Good, because we don't know the
* class in this macro. So this can safely be used for QVector<Eigen::Vector4f> but definitely not for
* QVector<Eigen::VectorXf>.
*
* This macro will go away as soon as Qt >= 4.5 is prevalent -- most likely it should go away in Eigen 2.1.
*/
#ifdef EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW \
void *operator new(size_t, void *ptr) throw() { \
return ptr; \
} \
void *operator new[](size_t, void *ptr) throw() { \
return ptr; \
}
#else
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
#endif
/** \brief Overloads the operator new and delete of the class Type with operators that are aligned if NeedsToAlign is true
*
* 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 {
* EIGEN_MAKE_ALIGNED_OPERATOR_NEW
* char dummy;
* Vector4f some_vector;
* };
* Foo *pObj2 = new Foo; // dynamic allocation
* pObj2->some_vector = Vector4f(..); // => SAFE !
* \endcode
*
* \sa class ei_new_allocator
*/
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
void *operator new(size_t size) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void *operator new[](size_t size) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
#if EIGEN_ALIGN
#ifdef EIGEN_EXCEPTIONS
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
void* operator new(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(size_t size, const std::nothrow_t&) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
}
#endif
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
void *operator new(size_t size) { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void *operator new[](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(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
#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))
/** Deprecated, use the EIGEN_MAKE_ALIGNED_OPERATOR_NEW macro instead in your own class */
struct WithAlignedOperatorNew
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
/** \class aligned_allocator
*
@@ -343,34 +324,34 @@ public:
typedef aligned_allocator<U> other;
};
pointer address( reference value ) const
pointer address( reference value ) const
{
return &value;
}
const_pointer address( const_reference value ) const
const_pointer address( const_reference value ) const
{
return &value;
}
aligned_allocator() throw()
aligned_allocator() throw()
{
}
aligned_allocator( const aligned_allocator& ) throw()
aligned_allocator( const aligned_allocator& ) throw()
{
}
template<class U>
aligned_allocator( const aligned_allocator<U>& ) throw()
aligned_allocator( const aligned_allocator<U>& ) throw()
{
}
~aligned_allocator() throw()
~aligned_allocator() throw()
{
}
size_type max_size() const throw()
size_type max_size() const throw()
{
return std::numeric_limits<size_type>::max();
}
@@ -381,20 +362,26 @@ public:
return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
}
void construct( pointer p, const T& value )
void construct( pointer p, const T& value )
{
::new( p ) T( value );
}
void destroy( pointer p )
void destroy( pointer p )
{
p->~T();
}
void deallocate( pointer p, size_type /*num*/ )
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

@@ -71,7 +71,11 @@
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_COLUMN_MAJOR_MATRICES,
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
INVALID_MATRIX_TEMPLATE_PARAMETERS,
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
};
};

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

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

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

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
*

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
*
@@ -61,12 +61,12 @@ template<typename _Scalar>
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
{
typedef RotationBase<Quaternion<_Scalar>,3> Base;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4)
using Base::operator*;
/** the scalar type of the coefficients */
typedef _Scalar Scalar;
@@ -109,13 +109,9 @@ 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. */
/** Default constructor leaving the quaternion uninitialized. */
inline Quaternion() {}
inline Quaternion(ei_constructor_without_unaligned_array_assert)
: m_coeffs(ei_constructor_without_unaligned_array_assert()) {}
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
* its four coefficients \a w, \a x, \a y and \a z.
*
@@ -217,28 +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:
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) */
@@ -350,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
@@ -358,7 +381,17 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
// set to identity
this->w() = 1; this->vec().setZero();
return *this;
}
// 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;

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

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
*
@@ -118,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)
{
@@ -149,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
*
@@ -94,11 +95,8 @@ public:
/** Default constructor without initialization of the coefficients. */
inline Transform() { }
inline Transform(ei_constructor_without_unaligned_array_assert)
: m_matrix(ei_constructor_without_unaligned_array_assert()) {}
inline Transform(const Transform& other)
{
{
m_matrix = other.m_matrix;
}
@@ -200,6 +198,10 @@ public:
/** \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);
@@ -247,8 +249,11 @@ public:
template<typename Derived>
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
EIGEN_DEPRECATED LinearMatrixType extractRotation(TransformTraits traits = Affine) const { return rotation(traits); }
LinearMatrixType rotation(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,
@@ -282,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;
/**************************
@@ -334,9 +343,9 @@ 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));
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.
@@ -368,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);
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
@@ -590,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>::rotation(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.coeff(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
@@ -650,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
*
@@ -152,7 +152,7 @@ public:
};
/** \addtogroup GeometryModule */
/** \addtogroup Geometry_Module */
//@{
typedef Translation<float, 2> Translation2f;
typedef Translation<double,2> Translation2d;

View File

@@ -132,21 +132,31 @@ void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* resu
// since this is a rare case, we don't need to optimize it. We just want to handle it with little
// additional code.
MatrixType m(matrix);
m.row(1).swap(m.row(2));
m.row(0).swap(m.row(2));
m.row(1).swap(m.row(3));
if(ei_compute_inverse_in_size4_case_helper(m, result))
{
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that two
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that some
// rows were permuted, the actual inverse of matrix is derived from the inverse of m by permuting
// the corresponding columns.
result->col(1).swap(result->col(2));
result->col(0).swap(result->col(2));
result->col(1).swap(result->col(3));
}
else
{
// last possible case. Since matrix is assumed to be invertible, this last case has to work.
m.row(1).swap(m.row(2));
// first, undo the swaps previously made
m.row(0).swap(m.row(2));
m.row(1).swap(m.row(3));
// swap row 0 with the the row among 0 and 1 that has the biggest 2 first coeffs
int swap0with = ei_abs(m.coeff(0,0))+ei_abs(m.coeff(0,1))>ei_abs(m.coeff(1,0))+ei_abs(m.coeff(1,1)) ? 0 : 1;
m.row(0).swap(m.row(swap0with));
// swap row 1 with the the row among 2 and 3 that has the biggest 2 first coeffs
int swap1with = ei_abs(m.coeff(2,0))+ei_abs(m.coeff(2,1))>ei_abs(m.coeff(3,0))+ei_abs(m.coeff(3,1)) ? 2 : 3;
m.row(1).swap(m.row(swap1with));
ei_compute_inverse_in_size4_case_helper(m, result);
result->col(1).swap(result->col(3));
result->col(1).swap(result->col(swap1with));
result->col(0).swap(result->col(swap0with));
}
}
}

View File

@@ -42,17 +42,18 @@
* 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()
*/
@@ -108,26 +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, UnitLowerTriangular> matrixL() const
{
return m_lu;
}
/** \returns an expression of the U matrix, i.e. the upper-triangular part of the LU matrix.
*
* \sa matrixLU(), matrixL()
*/
inline const Part<MatrixType, UpperTriangular> 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.
@@ -342,6 +323,7 @@ template<typename MatrixType> class LU
IntRowVectorType m_q;
int m_det_pq;
int m_rank;
RealScalar m_precision;
};
template<typename MatrixType>
@@ -354,22 +336,41 @@ LU<MatrixType>::LU(const MatrixType& matrix)
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);
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) {
@@ -380,12 +381,8 @@ LU<MatrixType>::LU(const MatrixType& matrix)
m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
++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)
m_lu.col(col).end(rows-k-1) -= m_lu.col(k).end(rows-k-1) * m_lu.coeff(k,col);
@@ -400,10 +397,6 @@ LU<MatrixType>::LU(const MatrixType& matrix)
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>
@@ -444,8 +437,7 @@ void LU<MatrixType>::computeKernel(KernelMatrixType *result) const
.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 = 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);
}
@@ -489,13 +481,13 @@ 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::PlainMatrixType c(b.rows(), b.cols());
@@ -503,36 +495,32 @@ bool LU<MatrixType>::solve(
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::Options,
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<UnitLowerTriangular>().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();
RealScalar biggest_in_c = m_rank>0 ? c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff() : 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))
if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c, m_precision))
return false;
}
Matrix<Scalar, Dynamic, OtherDerived::ColsAtCompileTime,
MatrixType::Options,
MatrixType::MaxRowsAtCompileTime, OtherDerived::MaxColsAtCompileTime>
d(c.corner(TopLeft, m_rank, c.cols()));
m_lu.corner(TopLeft, m_rank, m_rank)
.template marked<UpperTriangular>()
.solveTriangularInPlace(d);
.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 = 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;
}

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.
@@ -57,7 +57,7 @@
Vector3d coeffs; // will store the coefficients a, b, c
linearRegression(
5,
points,
&points,
&coeffs,
1 // the coord to express as a function of
// the other ones. 0 means x, 1 means y, 2 means z.
@@ -80,11 +80,11 @@
This vector must be of the same type and size as the
data points. The meaning of its coords is as follows.
For brevity, let \f$n=Size\f$,
\f$r_i=retCoefficients[i]\f$,
\f$r_i=result[i]\f$,
and \f$f=funcOfOthers\f$. Denote by
\f$x_0,\ldots,x_{n-1}\f$
the n coordinates in the n-dimensional space.
Then the result equation is:
Then the resulting equation is:
\f[ x_f = r_0 x_0 + \cdots + r_{f-1}x_{f-1}
+ r_{f+1}x_{f+1} + \cdots + r_{n-1}x_{n-1} + r_n. \f]
* @param funcOfOthers Determines which coord to express as a function of the
@@ -101,36 +101,20 @@ void linearRegression(int numPoints,
int funcOfOthers )
{
typedef typename VectorType::Scalar Scalar;
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType)
ei_assert(numPoints >= 1);
int size = points[0]->size();
ei_assert(funcOfOthers >= 0 && funcOfOthers < size);
typedef Hyperplane<Scalar, VectorType::SizeAtCompileTime> HyperplaneType;
const int size = points[0]->size();
result->resize(size);
Matrix<Scalar, Dynamic, VectorType::SizeAtCompileTime,
Dynamic, VectorType::MaxSizeAtCompileTime, RowMajorBit>
m(numPoints, size);
if(funcOfOthers>0)
for(int i = 0; i < numPoints; ++i)
m.row(i).start(funcOfOthers) = points[i]->start(funcOfOthers);
if(funcOfOthers<size-1)
for(int i = 0; i < numPoints; ++i)
m.row(i).block(funcOfOthers, size-funcOfOthers-1)
= points[i]->end(size-funcOfOthers-1);
for(int i = 0; i < numPoints; ++i)
m.row(i).coeffRef(size-1) = Scalar(1);
VectorType v(size);
v.setZero();
for(int i = 0; i < numPoints; ++i)
v += m.row(i).adjoint() * points[i]->coeff(funcOfOthers);
ei_assert((m.adjoint()*m).lu().solve(v, result));
HyperplaneType h(size);
fitHyperplane(numPoints, points, &h);
for(int i = 0; i < funcOfOthers; i++)
result->coeffRef(i) = - h.coeffs()[i] / h.coeffs()[funcOfOthers];
for(int i = funcOfOthers; i < size; i++)
result->coeffRef(i) = - h.coeffs()[i+1] / h.coeffs()[funcOfOthers];
}
/** \ingroup Regression_Module
/** \ingroup LeastSquares_Module
*
* \regression_module
* \leastsquares_module
*
* This function is quite similar to linearRegression(), so we refer to the
* documentation of this function and only list here the differences.
@@ -195,4 +179,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,6 +138,7 @@ 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)
@@ -143,6 +162,7 @@ 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)
@@ -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.

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,43 +49,163 @@ 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>, 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<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)
{
@@ -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,46 @@ void QR<MatrixType>::_compute(const MatrixType& matrix)
m_hCoeffs.coeffRef(k) = 0;
}
}
m_isInitialized = true;
}
template<typename MatrixType>
template<typename OtherDerived, typename ResultType>
bool QR<MatrixType>::solve(
const MatrixBase<OtherDerived>& b,
ResultType *result
) const
{
ei_assert(m_isInitialized && "QR is not initialized.");
const int rows = m_qr.rows();
ei_assert(b.rows() == rows);
result->resize(rows, b.cols());
// TODO(keir): There is almost certainly a faster way to multiply by
// Q^T without explicitly forming matrixQ(). Investigate.
*result = matrixQ().transpose()*b;
if(!isSurjective())
{
// is result is in the image of R ?
RealScalar biggest_in_res = result->corner(TopLeft, m_rank, result->cols()).cwise().abs().maxCoeff();
for(int col = 0; col < result->cols(); ++col)
for(int row = m_rank; row < result->rows(); ++row)
if(!ei_isMuchSmallerThan(result->coeff(row,col), biggest_in_res))
return false;
}
m_qr.corner(TopLeft, m_rank, m_rank)
.template marked<UpperTriangular>()
.solveTriangularInPlace(result->corner(TopLeft, m_rank, result->cols()));
return true;
}
/** \returns the matrix Q */
template<typename MatrixType>
MatrixType QR<MatrixType>::matrixQ(void) const
MatrixType QR<MatrixType>::matrixQ() const
{
ei_assert(m_isInitialized && "QR is not initialized.");
// compute the product Q_0 Q_1 ... Q_n-1,
// where Q_k is the k-th Householder transformation I - h_k v_k v_k'
// and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]

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

View File

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

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

@@ -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();
@@ -534,6 +547,95 @@ 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
*/

View File

@@ -99,6 +99,8 @@ template<typename _Scalar> class AmbiVector
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
Scalar* newBuffer = new Scalar[allocSize];
memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
delete[] m_buffer;
m_buffer = newBuffer;
}
protected:
@@ -238,8 +240,11 @@ 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);
@@ -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
)

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) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -54,16 +54,17 @@ void ei_cholmod_configure_matrix(CholmodType& mat)
}
}
template<typename Scalar, int Flags>
cholmod_sparse SparseMatrix<Scalar,Flags>::asCholmodMatrix()
template<typename Derived>
cholmod_sparse SparseMatrixBase<Derived>::asCholmodMatrix()
{
typedef typename Derived::Scalar Scalar;
cholmod_sparse res;
res.nzmax = nonZeros();
res.nrow = rows();;
res.ncol = cols();
res.p = _outerIndexPtr();
res.i = _innerIndexPtr();
res.x = _valuePtr();
res.p = derived()._outerIndexPtr();
res.i = derived()._innerIndexPtr();
res.x = derived()._valuePtr();
res.xtype = CHOLMOD_REAL;
res.itype = CHOLMOD_INT;
res.sorted = 1;
@@ -73,11 +74,11 @@ cholmod_sparse SparseMatrix<Scalar,Flags>::asCholmodMatrix()
ei_cholmod_configure_matrix<Scalar>(res);
if (Flags & SelfAdjoint)
if (Derived::Flags & SelfAdjoint)
{
if (Flags & UpperTriangular)
if (Derived::Flags & UpperTriangular)
res.stype = 1;
else if (Flags & LowerTriangular)
else if (Derived::Flags & LowerTriangular)
res.stype = -1;
else
res.stype = 0;
@@ -108,19 +109,14 @@ cholmod_dense ei_cholmod_map_eigen_to_dense(MatrixBase<Derived>& mat)
}
template<typename Scalar, int Flags>
SparseMatrix<Scalar,Flags> SparseMatrix<Scalar,Flags>::Map(cholmod_sparse& cm)
MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(cholmod_sparse& cm)
{
SparseMatrix res;
res.m_innerSize = cm.nrow;
res.m_outerSize = cm.ncol;
res.m_outerIndex = reinterpret_cast<int*>(cm.p);
SparseArray<Scalar> data = SparseArray<Scalar>::Map(
reinterpret_cast<int*>(cm.i),
reinterpret_cast<Scalar*>(cm.x),
res.m_outerIndex[cm.ncol]);
res.m_data.swap(data);
res.markAsRValue();
return res;
m_innerSize = cm.nrow;
m_outerSize = cm.ncol;
m_outerIndex = reinterpret_cast<int*>(cm.p);
m_innerIndices = reinterpret_cast<int*>(cm.i);
m_values = reinterpret_cast<Scalar*>(cm.x);
m_nnz = m_outerIndex[cm.ncol];
}
template<typename MatrixType>
@@ -128,8 +124,8 @@ class SparseLLT<MatrixType,Cholmod> : public SparseLLT<MatrixType>
{
protected:
typedef SparseLLT<MatrixType> Base;
using typename Base::Scalar;
using Base::RealScalar;
typedef typename Base::Scalar Scalar;
typedef typename Base::RealScalar RealScalar;
using Base::MatrixLIsDirty;
using Base::SupernodalFactorIsDirty;
using Base::m_flags;
@@ -210,7 +206,7 @@ SparseLLT<MatrixType,Cholmod>::matrixL() const
ei_assert(!(m_status & SupernodalFactorIsDirty));
cholmod_sparse* cmRes = cholmod_factor_to_sparse(m_cholmodFactor, &m_cholmod);
const_cast<typename Base::CholMatrixType&>(m_matrix) = Base::CholMatrixType::Map(*cmRes);
const_cast<typename Base::CholMatrixType&>(m_matrix) = MappedSparseMatrix<Scalar>(*cmRes);
free(cmRes);
m_status = (m_status & ~MatrixLIsDirty);

View File

@@ -0,0 +1,230 @@
// 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_COMPRESSED_STORAGE_H
#define EIGEN_COMPRESSED_STORAGE_H
/** Stores a sparse set of values as a list of values and a list of indices.
*
*/
template<typename Scalar>
class CompressedStorage
{
typedef typename NumTraits<Scalar>::Real RealScalar;
public:
CompressedStorage()
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{}
CompressedStorage(size_t size)
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{
resize(size);
}
CompressedStorage(const CompressedStorage& other)
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{
*this = other;
}
CompressedStorage& operator=(const CompressedStorage& other)
{
resize(other.size());
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
memcpy(m_indices, other.m_indices, m_size * sizeof(int));
return *this;
}
void swap(CompressedStorage& other)
{
std::swap(m_values, other.m_values);
std::swap(m_indices, other.m_indices);
std::swap(m_size, other.m_size);
std::swap(m_allocatedSize, other.m_allocatedSize);
}
~CompressedStorage()
{
delete[] m_values;
delete[] m_indices;
}
void reserve(size_t size)
{
size_t newAllocatedSize = m_size + size;
if (newAllocatedSize > m_allocatedSize)
reallocate(newAllocatedSize);
}
void squeeze()
{
if (m_allocatedSize>m_size)
reallocate(m_size);
}
void resize(size_t size, float reserveSizeFactor = 0)
{
if (m_allocatedSize<size)
reallocate(size + size_t(reserveSizeFactor*size));
m_size = size;
}
void append(const Scalar& v, int i)
{
int id = m_size;
resize(m_size+1, 1);
m_values[id] = v;
m_indices[id] = i;
}
inline size_t size() const { return m_size; }
inline size_t allocatedSize() const { return m_allocatedSize; }
inline void clear() { m_size = 0; }
inline Scalar& value(size_t i) { return m_values[i]; }
inline const Scalar& value(size_t i) const { return m_values[i]; }
inline int& index(size_t i) { return m_indices[i]; }
inline const int& index(size_t i) const { return m_indices[i]; }
static CompressedStorage Map(int* indices, Scalar* values, size_t size)
{
CompressedStorage res;
res.m_indices = indices;
res.m_values = values;
res.m_allocatedSize = res.m_size = size;
return res;
}
/** \returns the largest \c k such that for all \c j in [0,k) index[\c j]\<\a key */
inline int searchLowerIndex(int key) const
{
return searchLowerIndex(0, m_size, key);
}
/** \returns the largest \c k in [start,end) such that for all \c j in [start,k) index[\c j]\<\a key */
inline int searchLowerIndex(size_t start, size_t end, int key) const
{
while(end>start)
{
size_t mid = (end+start)>>1;
if (m_indices[mid]<key)
start = mid+1;
else
end = mid;
}
return start;
}
/** \returns the stored value at index \a key
* If the value does not exist, then the value \a defaultValue is returned without any insertion. */
inline Scalar at(int key, Scalar defaultValue = Scalar(0)) const
{
if (m_size==0)
return defaultValue;
else if (key==m_indices[m_size-1])
return m_values[m_size-1];
// ^^ optimization: let's first check if it is the last coefficient
// (very common in high level algorithms)
const size_t id = searchLowerIndex(0,m_size-1,key);
return ((id<m_size) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
}
/** Like at(), but the search is performed in the range [start,end) */
inline Scalar atInRange(size_t start, size_t end, int key, Scalar defaultValue = Scalar(0)) const
{
if (start==end)
return Scalar(0);
else if (end>start && key==m_indices[end-1])
return m_values[end-1];
// ^^ optimization: let's first check if it is the last coefficient
// (very common in high level algorithms)
const size_t id = searchLowerIndex(start,end-1,key);
return ((id<end) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
}
/** \returns a reference to the value at index \a key
* If the value does not exist, then the value \a defaultValue is inserted
* such that the keys are sorted. */
inline Scalar& atWithInsertion(int key, Scalar defaultValue = Scalar(0))
{
size_t id = searchLowerIndex(0,m_size,key);
if (id>=m_size || m_indices[id]!=key)
{
resize(m_size+1,1);
for (size_t j=m_size-1; j>id; --j)
{
m_indices[j] = m_indices[j-1];
m_values[j] = m_values[j-1];
}
m_indices[id] = key;
m_values[id] = defaultValue;
}
return m_values[id];
}
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
{
size_t k = 0;
size_t n = size();
for (size_t i=0; i<n; ++i)
{
if (!ei_isMuchSmallerThan(value(i), reference, epsilon))
{
value(k) = value(i);
index(k) = index(i);
++k;
}
}
resize(k,0);
}
protected:
inline void reallocate(size_t size)
{
Scalar* newValues = new Scalar[size];
int* newIndices = new int[size];
size_t copySize = std::min(size, m_size);
// copy
memcpy(newValues, m_values, copySize * sizeof(Scalar));
memcpy(newIndices, m_indices, copySize * sizeof(int));
// delete old stuff
delete[] m_values;
delete[] m_indices;
m_values = newValues;
m_indices = newIndices;
m_allocatedSize = size;
}
protected:
Scalar* m_values;
int* m_indices;
size_t m_size;
size_t m_allocatedSize;
};
#endif // EIGEN_COMPRESSED_STORAGE_H

View File

@@ -28,307 +28,41 @@
/* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core
*/
template<typename Derived>
class MatrixBase<Derived>::InnerIterator
/** \class InnerIterator
* \brief An InnerIterator allows to loop over the element of a sparse (or dense) matrix or expression
*
* todo
*/
// generic version for dense matrix and expressions
template<typename Derived> class MatrixBase<Derived>::InnerIterator
{
typedef typename Derived::Scalar Scalar;
enum { IsRowMajor = (Derived::Flags&RowMajorBit)==RowMajorBit };
public:
EIGEN_STRONG_INLINE InnerIterator(const Derived& mat, int outer)
: m_matrix(mat), m_inner(0), m_outer(outer), m_end(mat.rows())
EIGEN_STRONG_INLINE InnerIterator(const Derived& expr, int outer)
: m_expression(expr), m_inner(0), m_outer(outer), m_end(expr.rows())
{}
EIGEN_STRONG_INLINE Scalar value() const
{
return (Derived::Flags&RowMajorBit) ? m_matrix.coeff(m_outer, m_inner)
: m_matrix.coeff(m_inner, m_outer);
return (IsRowMajor) ? m_expression.coeff(m_outer, m_inner)
: m_expression.coeff(m_inner, m_outer);
}
EIGEN_STRONG_INLINE InnerIterator& operator++() { m_inner++; return *this; }
EIGEN_STRONG_INLINE int index() const { return m_inner; }
inline int row() const { return IsRowMajor ? m_outer : index(); }
inline int col() const { return IsRowMajor ? index() : m_outer; }
EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; }
protected:
const Derived& m_matrix;
const Derived& m_expression;
int m_inner;
const int m_outer;
const int m_end;
};
template<typename MatrixType>
class Transpose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
{
public:
EIGEN_STRONG_INLINE InnerIterator(const Transpose& trans, int outer)
: MatrixType::InnerIterator(trans.m_matrix, outer)
{}
};
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, int _DirectAccessStatus>
class Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus>::InnerIterator
{
typedef typename Block::Scalar Scalar;
typedef typename ei_traits<Block>::_MatrixTypeNested _MatrixTypeNested;
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
m_offset( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value())
{
while (m_iter.index()>=0 && m_iter.index()<m_start)
++m_iter;
}
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
++m_iter;
return *this;
}
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
protected:
MatrixTypeIterator m_iter;
int m_start;
int m_end;
int m_offset;
};
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
class Block<MatrixType, BlockRows, BlockCols, PacketAccess, IsSparse>::InnerIterator
{
typedef typename Block::Scalar Scalar;
typedef typename ei_traits<Block>::_MatrixTypeNested _MatrixTypeNested;
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
m_offset( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value())
{
while (m_iter.index()>=0 && m_iter.index()<m_start)
++m_iter;
}
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
++m_iter;
return *this;
}
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
protected:
MatrixTypeIterator m_iter;
int m_start;
int m_end;
int m_offset;
};
template<typename UnaryOp, typename MatrixType>
class CwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
{
typedef typename CwiseUnaryOp::Scalar Scalar;
typedef typename ei_traits<CwiseUnaryOp>::_MatrixTypeNested _MatrixTypeNested;
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOp& unaryOp, int outer)
: m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor), m_id(-1)
{
this->operator++();
}
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
if (m_iter)
{
m_id = m_iter.index();
m_value = m_functor(m_iter.value());
++m_iter;
}
else
{
m_id = -1;
}
return *this;
}
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
EIGEN_STRONG_INLINE int index() const { return m_id; }
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
protected:
MatrixTypeIterator m_iter;
const UnaryOp& m_functor;
Scalar m_value;
int m_id;
};
template<typename T> struct ei_is_scalar_product { enum { ret = false }; };
template<typename T> struct ei_is_scalar_product<ei_scalar_product_op<T> > { enum { ret = true }; };
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator;
template<typename BinaryOp, typename Lhs, typename Rhs>
class CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
: public CwiseBinaryOpInnerIterator<BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
{
typedef CwiseBinaryOpInnerIterator<
BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator> Base;
public:
typedef typename CwiseBinaryOp::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
// public:
EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOp& binOp, int outer)
: Base(binOp.m_lhs,binOp.m_rhs,binOp.m_functor,outer)
{}
};
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator
{
typedef CwiseBinaryOp<BinaryOp,Lhs,Rhs> ExpressionType;
typedef typename ExpressionType::Scalar Scalar;
typedef typename ei_traits<ExpressionType>::_LhsNested _LhsNested;
// typedef typename ei_traits<ExpressionType>::LhsIterator LhsIterator;
typedef typename ei_traits<ExpressionType>::_RhsNested _RhsNested;
// typedef typename ei_traits<ExpressionType>::RhsIterator RhsIterator;
// typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
// typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
// enum { IsProduct = ei_is_scalar_product<BinaryOp>::ret };
public:
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const _LhsNested& lhs, const _RhsNested& rhs,
const BinaryOp& functor, int outer)
: m_lhsIter(lhs,outer), m_rhsIter(rhs,outer), m_functor(functor), m_id(-1)
{
this->operator++();
}
EIGEN_STRONG_INLINE Derived& operator++()
{
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
{
m_id = m_lhsIter.index();
m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
++m_lhsIter;
++m_rhsIter;
}
else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
{
m_id = m_lhsIter.index();
m_value = m_functor(m_lhsIter.value(), Scalar(0));
++m_lhsIter;
}
else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
{
m_id = m_rhsIter.index();
m_value = m_functor(Scalar(0), m_rhsIter.value());
++m_rhsIter;
}
else
{
m_id = -1;
}
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
EIGEN_STRONG_INLINE int index() const { return m_id; }
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
const BinaryOp& m_functor;
Scalar m_value;
int m_id;
};
/*
template<typename T, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator<ei_scalar_product_op<T>,Lhs,Rhs,Derived>
{
typedef typename CwiseBinaryOp::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
public:
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const CwiseBinaryOp& binOp, int outer)
: m_lhsIter(binOp.m_lhs,outer), m_rhsIter(binOp.m_rhs,outer), m_functor(binOp.m_functor)//, m_id(-1)
{
//this->operator++();
while (m_lhsIter && m_rhsIter && m_lhsIter.index() != m_rhsIter.index())
{
if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
}
EIGEN_STRONG_INLINE Derived& operator++()
{
// m_id = -1;
asm("#beginwhile");
while (m_lhsIter && m_rhsIter)
{
if (m_lhsIter.index() == m_rhsIter.index())
{
// m_id = m_lhsIter.index();
//m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
++m_lhsIter;
++m_rhsIter;
break;
}
else if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
asm("#endwhile");
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter && m_rhsIter; }
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
const BinaryOp& m_functor;
// Scalar m_value;
// int m_id;
};*/
#endif // EIGEN_COREITERATORS_H

View File

@@ -0,0 +1,299 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_DYNAMIC_SPARSEMATRIX_H
#define EIGEN_DYNAMIC_SPARSEMATRIX_H
/** \class DynamicSparseMatrix
*
* \brief A sparse matrix class designed for matrix assembly purpose
*
* \param _Scalar the scalar type, i.e. the type of the coefficients
*
* Unlike SparseMatrix, this class provides a much higher degree of flexibility. In particular, it allows
* random read/write accesses in log(rho*outer_size) where \c rho is the probability that a coefficient is
* nonzero and outer_size is the number of columns if the matrix is column-major and the number of rows
* otherwise.
*
* Internally, the data are stored as a std::vector of compressed vector. The performances of random writes might
* decrease as the number of nonzeros per inner-vector increase. In practice, we observed very good performance
* till about 100 nonzeros/vector, and the performance remains relatively good till 500 nonzeros/vectors.
*
* \see SparseMatrix
*/
template<typename _Scalar, int _Flags>
struct ei_traits<DynamicSparseMatrix<_Scalar, _Flags> >
{
typedef _Scalar Scalar;
enum {
RowsAtCompileTime = Dynamic,
ColsAtCompileTime = Dynamic,
MaxRowsAtCompileTime = Dynamic,
MaxColsAtCompileTime = Dynamic,
Flags = SparseBit | _Flags,
CoeffReadCost = NumTraits<Scalar>::ReadCost,
SupportedAccessPatterns = OuterRandomAccessPattern
};
};
template<typename _Scalar, int _Flags>
class DynamicSparseMatrix
: public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Flags> >
{
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(DynamicSparseMatrix)
// FIXME: why are these operator already alvailable ???
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=)
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=)
typedef MappedSparseMatrix<Scalar,Flags> Map;
protected:
enum { IsRowMajor = Base::IsRowMajor };
typedef DynamicSparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
int m_innerSize;
std::vector<CompressedStorage<Scalar> > m_data;
public:
inline int rows() const { return IsRowMajor ? outerSize() : m_innerSize; }
inline int cols() const { return IsRowMajor ? m_innerSize : outerSize(); }
inline int innerSize() const { return m_innerSize; }
inline int outerSize() const { return m_data.size(); }
inline int innerNonZeros(int j) const { return m_data[j].size(); }
std::vector<CompressedStorage<Scalar> >& _data() { return m_data; }
const std::vector<CompressedStorage<Scalar> >& _data() const { return m_data; }
/** \returns the coefficient value at given position \a row, \a col
* This operation involes a log(rho*outer_size) binary search.
*/
inline Scalar coeff(int row, int col) const
{
const int outer = IsRowMajor ? row : col;
const int inner = IsRowMajor ? col : row;
return m_data[outer].at(inner);
}
/** \returns a reference to the coefficient value at given position \a row, \a col
* This operation involes a log(rho*outer_size) binary search. If the coefficient does not
* exist yet, then a sorted insertion into a sequential buffer is performed.
*/
inline Scalar& coeffRef(int row, int col)
{
const int outer = IsRowMajor ? row : col;
const int inner = IsRowMajor ? col : row;
return m_data[outer].atWithInsertion(inner);
}
class InnerIterator;
inline void setZero()
{
for (int j=0; j<outerSize(); ++j)
m_data[j].clear();
}
/** \returns the number of non zero coefficients */
inline int nonZeros() const
{
int res = 0;
for (int j=0; j<outerSize(); ++j)
res += m_data[j].size();
return res;
}
/** Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */
inline void startFill(int reserveSize = 1000)
{
if (outerSize()>0)
{
int reserveSizePerVector = std::max(reserveSize/outerSize(),4);
for (int j=0; j<outerSize(); ++j)
{
m_data[j].clear();
m_data[j].reserve(reserveSizePerVector);
}
}
}
/** inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that:
* 1 - the coefficient does not exist yet
* 2 - this the coefficient with greater inner coordinate for the given outer coordinate.
* In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates
* \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid.
*
* \see fillrand(), coeffRef()
*/
inline Scalar& fill(int row, int col)
{
const int outer = IsRowMajor ? row : col;
const int inner = IsRowMajor ? col : row;
ei_assert(outer<int(m_data.size()) && inner<m_innerSize);
ei_assert((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner));
m_data[outer].append(0, inner);
return m_data[outer].value(m_data[outer].size()-1);
}
/** Like fill() but with random inner coordinates.
* Compared to the generic coeffRef(), the unique limitation is that we assume
* the coefficient does not exist yet.
*/
inline Scalar& fillrand(int row, int col)
{
const int outer = IsRowMajor ? row : col;
const int inner = IsRowMajor ? col : row;
int startId = 0;
int id = m_data[outer].size() - 1;
m_data[outer].resize(id+2,1);
while ( (id >= startId) && (m_data[outer].index(id) > inner) )
{
m_data[outer].index(id+1) = m_data[outer].index(id);
m_data[outer].value(id+1) = m_data[outer].value(id);
--id;
}
m_data[outer].index(id+1) = inner;
m_data[outer].value(id+1) = 0;
return m_data[outer].value(id+1);
}
/** Does nothing. Provided for compatibility with SparseMatrix. */
inline void endFill() {}
void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
{
for (int j=0; j<outerSize(); ++j)
m_data[j].prune(reference,epsilon);
}
/** Resize the matrix without preserving the data (the matrix is set to zero)
*/
void resize(int rows, int cols)
{
const int outerSize = IsRowMajor ? rows : cols;
m_innerSize = IsRowMajor ? cols : rows;
setZero();
if (int(m_data.size()) != outerSize)
{
m_data.resize(outerSize);
}
}
void resizeAndKeepData(int rows, int cols)
{
const int outerSize = IsRowMajor ? rows : cols;
const int innerSize = IsRowMajor ? cols : rows;
if (m_innerSize>innerSize)
{
// remove all coefficients with innerCoord>=innerSize
// TODO
std::cerr << "not implemented yet\n";
exit(2);
}
if (m_data.size() != outerSize)
{
m_data.resize(outerSize);
}
}
inline DynamicSparseMatrix()
: m_innerSize(0), m_data(0)
{
ei_assert(innerSize()==0 && outerSize()==0);
}
inline DynamicSparseMatrix(int rows, int cols)
: m_innerSize(0)
{
resize(rows, cols);
}
template<typename OtherDerived>
inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other)
: m_innerSize(0)
{
*this = other.derived();
}
inline DynamicSparseMatrix(const DynamicSparseMatrix& other)
: Base(), m_innerSize(0)
{
*this = other.derived();
}
inline void swap(DynamicSparseMatrix& other)
{
//EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
std::swap(m_innerSize, other.m_innerSize);
//std::swap(m_outerSize, other.m_outerSize);
m_data.swap(other.m_data);
}
inline DynamicSparseMatrix& operator=(const DynamicSparseMatrix& other)
{
if (other.isRValue())
{
swap(other.const_cast_derived());
}
else
{
resize(other.rows(), other.cols());
m_data = other.m_data;
}
return *this;
}
template<typename OtherDerived>
inline DynamicSparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
{
return SparseMatrixBase<DynamicSparseMatrix>::operator=(other.derived());
}
/** Destructor */
inline ~DynamicSparseMatrix() {}
};
template<typename Scalar, int _Flags>
class DynamicSparseMatrix<Scalar,_Flags>::InnerIterator : public SparseVector<Scalar,_Flags>::InnerIterator
{
typedef typename SparseVector<Scalar,_Flags>::InnerIterator Base;
public:
InnerIterator(const DynamicSparseMatrix& mat, int outer)
: Base(mat.m_data[outer]), m_outer(outer)
{}
inline int row() const { return IsRowMajor ? m_outer : Base::index(); }
inline int col() const { return IsRowMajor ? Base::index() : m_outer; }
protected:
const int m_outer;
private:
InnerIterator& operator=(const InnerIterator&);
};
#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H

View File

@@ -0,0 +1,175 @@
// 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_MAPPED_SPARSEMATRIX_H
#define EIGEN_MAPPED_SPARSEMATRIX_H
/** \class MappedSparseMatrix
*
* \brief Sparse matrix
*
* \param _Scalar the scalar type, i.e. the type of the coefficients
*
* See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
*
*/
template<typename _Scalar, int _Flags>
struct ei_traits<MappedSparseMatrix<_Scalar, _Flags> > : ei_traits<SparseMatrix<_Scalar, _Flags> >
{};
template<typename _Scalar, int _Flags>
class MappedSparseMatrix
: public SparseMatrixBase<MappedSparseMatrix<_Scalar, _Flags> >
{
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(MappedSparseMatrix)
protected:
enum { IsRowMajor = Base::IsRowMajor };
int m_outerSize;
int m_innerSize;
int m_nnz;
int* m_outerIndex;
int* m_innerIndices;
Scalar* m_values;
public:
inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
inline int innerSize() const { return m_innerSize; }
inline int outerSize() const { return m_outerSize; }
inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
//----------------------------------------
// direct access interface
inline const Scalar* _valuePtr() const { return m_values; }
inline Scalar* _valuePtr() { return m_values; }
inline const int* _innerIndexPtr() const { return m_innerIndices; }
inline int* _innerIndexPtr() { return m_innerIndices; }
inline const int* _outerIndexPtr() const { return m_outerIndex; }
inline int* _outerIndexPtr() { return m_outerIndex; }
//----------------------------------------
inline Scalar coeff(int row, int col) const
{
const int outer = RowMajor ? row : col;
const int inner = RowMajor ? col : row;
int start = m_outerIndex[outer];
int end = m_outerIndex[outer+1];
if (start==end)
return Scalar(0);
else if (end>0 && inner==m_innerIndices[end-1])
return m_values[end-1];
// ^^ optimization: let's first check if it is the last coefficient
// (very common in high level algorithms)
const int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
const int id = r-&m_innerIndices[0];
return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0);
}
inline Scalar& coeffRef(int row, int col)
{
const int outer = RowMajor ? row : col;
const int inner = RowMajor ? col : row;
int start = m_outerIndex[outer];
int end = m_outerIndex[outer+1];
ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end],inner);
const int id = r-&m_innerIndices[0];
ei_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
return m_values[id];
}
class InnerIterator;
/** \returns the number of non zero coefficients */
inline int nonZeros() const { return m_nnz; }
inline MappedSparseMatrix(int rows, int cols, int nnz, int* outerIndexPtr, int* innerIndexPtr, Scalar* valuePtr)
: m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_nnz(nnz), m_outerIndex(outerIndexPtr),
m_innerIndices(innerIndexPtr), m_values(valuePtr)
{}
#ifdef EIGEN_TAUCS_SUPPORT
explicit MappedSparseMatrix(taucs_ccs_matrix& taucsMatrix);
#endif
#ifdef EIGEN_CHOLMOD_SUPPORT
explicit MappedSparseMatrix(cholmod_sparse& cholmodMatrix);
#endif
#ifdef EIGEN_SUPERLU_SUPPORT
explicit MappedSparseMatrix(SluMatrix& sluMatrix);
#endif
/** Empty destructor */
inline ~MappedSparseMatrix() {}
};
template<typename Scalar, int _Flags>
class MappedSparseMatrix<Scalar,_Flags>::InnerIterator
{
public:
InnerIterator(const MappedSparseMatrix& mat, int outer)
: m_matrix(mat),
m_outer(outer),
m_id(mat._outerIndexPtr()[outer]),
m_start(m_id),
m_end(mat._outerIndexPtr()[outer+1])
{}
template<unsigned int Added, unsigned int Removed>
InnerIterator(const Flagged<MappedSparseMatrix,Added,Removed>& mat, int outer)
: m_matrix(mat._expression()), m_id(m_matrix._outerIndexPtr()[outer]),
m_start(m_id), m_end(m_matrix._outerIndexPtr()[outer+1])
{}
inline InnerIterator& operator++() { m_id++; return *this; }
inline Scalar value() const { return m_matrix._valuePtr()[m_id]; }
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix._valuePtr()[m_id]); }
inline int index() const { return m_matrix._innerIndexPtr()[m_id]; }
inline int row() const { return IsRowMajor ? m_outer : index(); }
inline int col() const { return IsRowMajor ? index() : m_outer; }
inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
protected:
const MappedSparseMatrix& m_matrix;
const int m_outer;
int m_id;
const int m_start;
const int m_end;
};
#endif // EIGEN_MAPPED_SPARSEMATRIX_H

View File

@@ -25,6 +25,10 @@
#ifndef EIGEN_RANDOMSETTER_H
#define EIGEN_RANDOMSETTER_H
/** Represents a std::map
*
* \see RandomSetter
*/
template<typename Scalar> struct StdMapTraits
{
typedef int KeyType;
@@ -36,20 +40,40 @@ template<typename Scalar> struct StdMapTraits
static void setInvalidKey(Type&, const KeyType&) {}
};
#ifdef _HASH_MAP
template<typename Scalar> struct GnuHashMapTraits
#ifdef EIGEN_UNORDERED_MAP_SUPPORT
/** Represents a std::unordered_map
*
* To use it you need to both define EIGEN_UNORDERED_MAP_SUPPORT and include the unordered_map header file
* yourself making sure that unordered_map is defined in the std namespace.
*
* For instance, with current version of gcc you can either enable C++0x standard (-std=c++0x) or do:
* \code
* #include <tr1/unordered_map>
* #define EIGEN_UNORDERED_MAP_SUPPORT
* namespace std {
* using std::tr1::unordered_map;
* }
* \endcode
*
* \see RandomSetter
*/
template<typename Scalar> struct StdUnorderedMapTraits
{
typedef int KeyType;
typedef __gnu_cxx::hash_map<KeyType,Scalar> Type;
typedef std::unordered_map<KeyType,Scalar> Type;
enum {
IsSorted = 0
};
static void setInvalidKey(Type&, const KeyType&) {}
};
#endif
#endif // EIGEN_UNORDERED_MAP_SUPPORT
#ifdef _DENSE_HASH_MAP_H_
/** Represents a google::dense_hash_map
*
* \see RandomSetter
*/
template<typename Scalar> struct GoogleDenseHashMapTraits
{
typedef int KeyType;
@@ -64,6 +88,10 @@ template<typename Scalar> struct GoogleDenseHashMapTraits
#endif
#ifdef _SPARSE_HASH_MAP_H_
/** Represents a google::sparse_hash_map
*
* \see RandomSetter
*/
template<typename Scalar> struct GoogleSparseHashMapTraits
{
typedef int KeyType;
@@ -78,7 +106,19 @@ template<typename Scalar> struct GoogleSparseHashMapTraits
/** \class RandomSetter
*
* Typical usage:
* \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access
*
* \param SparseMatrixType the type of the sparse matrix we are updating
* \param MapTraits a traits class representing the map implementation used for the temporary sparse storage.
* Its default value depends on the system.
* \param OuterPacketBits defines the number of rows (or columns) manage by a single map object
* as a power of two exponent.
*
* This class temporarily represents a sparse matrix object using a generic map implementation allowing for
* efficient random access. The conversion from the compressed representation to a hash_map object is performed
* in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy
* suggest the use of nested blocks as in this example:
*
* \code
* SparseMatrix<double> m(rows,cols);
* {
@@ -91,11 +131,28 @@ template<typename Scalar> struct GoogleSparseHashMapTraits
* // and m is ready to use.
* \endcode
*
* \note for performance and memory consumption reasons it is highly recommended to use
* Google's hash library. To do so you have two options:
* - include <google/dense_hash_map> yourself \b before Eigen/Sparse header
* Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would
* involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter
* use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order.
* To reach optimal performance, this value should be adjusted according to the average number of nonzeros
* per rows/columns.
*
* The possible values for the template parameter MapTraits are:
* - \b StdMapTraits: corresponds to std::map. (does not perform very well)
* - \b GnuHashMapTraits: corresponds to __gnu_cxx::hash_map (available only with GCC)
* - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory consumption)
* - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good performance)
*
* The default map implementation depends on the availability, and the preferred order is:
* GoogleSparseHashMapTraits, GnuHashMapTraits, and finally StdMapTraits.
*
* For performance and memory consumption reasons it is highly recommended to use one of
* the Google's hash_map implementation. To enable the support for them, you have two options:
* - \#include <google/dense_hash_map> yourself \b before Eigen/Sparse header
* - define EIGEN_GOOGLEHASH_SUPPORT
* In the later case the inclusion of <google/dense_hash_map> is made for you.
*
* \see http://code.google.com/p/google-sparsehash/
*/
template<typename SparseMatrixType,
template <typename T> class MapTraits =
@@ -121,11 +178,19 @@ class RandomSetter
enum {
SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor
SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor,
IsUpperTriangular = SparseMatrixType::Flags & UpperTriangularBit,
IsLowerTriangular = SparseMatrixType::Flags & LowerTriangularBit
};
public:
/** Constructs a random setter object from the sparse matrix \a target
*
* Note that the initial value of \a target are imported. If you want to re-set
* a sparse matrix from scratch, then you must set it to zero first using the
* setZero() function.
*/
inline RandomSetter(SparseMatrixType& target)
: mp_target(&target)
{
@@ -153,6 +218,7 @@ class RandomSetter
(*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value();
}
/** Destructor updating back the sparse matrix target */
~RandomSetter()
{
KeyType keyBitsMask = (1<<m_keyBitsOffset)-1;
@@ -226,8 +292,11 @@ class RandomSetter
delete[] m_hashmaps;
}
/** \returns a reference to the coefficient at given coordinates \a row, \a col */
Scalar& operator() (int row, int col)
{
ei_assert(((!IsUpperTriangular) || (row<=col)) && "Invalid access to an upper triangular matrix");
ei_assert(((!IsLowerTriangular) || (col<=row)) && "Invalid access to an upper triangular matrix");
const int outer = SetterRowMajor ? row : col;
const int inner = SetterRowMajor ? col : row;
const int outerMajor = outer >> OuterPacketBits; // index of the packet/map
@@ -236,7 +305,11 @@ class RandomSetter
return m_hashmaps[outerMajor][key].value;
}
// might be slow
/** \returns the number of non zero coefficients
*
* \note According to the underlying map/hash_map implementation,
* this function might be quite expensive.
*/
int nonZeros() const
{
int nz = 0;

View File

@@ -1,144 +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_SPARSE_ARRAY_H
#define EIGEN_SPARSE_ARRAY_H
/** Stores a sparse set of values as a list of values and a list of indices.
*
*/
template<typename Scalar>
class SparseArray
{
public:
SparseArray()
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{}
SparseArray(int size)
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{
resize(size);
}
SparseArray(const SparseArray& other)
{
*this = other;
}
SparseArray& operator=(const SparseArray& other)
{
resize(other.size());
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
memcpy(m_indices, other.m_indices, m_size * sizeof(int));
return *this;
}
void swap(SparseArray& other)
{
std::swap(m_values, other.m_values);
std::swap(m_indices, other.m_indices);
std::swap(m_size, other.m_size);
std::swap(m_allocatedSize, other.m_allocatedSize);
}
~SparseArray()
{
delete[] m_values;
delete[] m_indices;
}
void reserve(int size)
{
int newAllocatedSize = m_size + size;
if (newAllocatedSize > m_allocatedSize)
reallocate(newAllocatedSize);
}
void squeeze()
{
if (m_allocatedSize>m_size)
reallocate(m_size);
}
void resize(int size, int reserveSizeFactor = 0)
{
if (m_allocatedSize<size)
reallocate(size + reserveSizeFactor*size);
m_size = size;
}
void append(const Scalar& v, int i)
{
int id = m_size;
resize(m_size+1, 1);
m_values[id] = v;
m_indices[id] = i;
}
int size() const { return m_size; }
void clear() { m_size = 0; }
Scalar& value(int i) { return m_values[i]; }
const Scalar& value(int i) const { return m_values[i]; }
int& index(int i) { return m_indices[i]; }
const int& index(int i) const { return m_indices[i]; }
static SparseArray Map(int* indices, Scalar* values, int size)
{
SparseArray res;
res.m_indices = indices;
res.m_values = values;
res.m_allocatedSize = res.m_size = size;
return res;
}
protected:
void reallocate(int size)
{
Scalar* newValues = new Scalar[size];
int* newIndices = new int[size];
int copySize = std::min(size, m_size);
// copy
memcpy(newValues, m_values, copySize * sizeof(Scalar));
memcpy(newIndices, m_indices, copySize * sizeof(int));
// delete old stuff
delete[] m_values;
delete[] m_indices;
m_values = newValues;
m_indices = newIndices;
m_allocatedSize = size;
}
protected:
Scalar* m_values;
int* m_indices;
int m_size;
int m_allocatedSize;
};
#endif // EIGEN_SPARSE_ARRAY_H

View File

View File

@@ -23,9 +23,341 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_SPARSEBLOCK_H
#define EIGEN_SPARSEBLOCK_H
#ifndef EIGEN_SPARSE_BLOCK_H
#define EIGEN_SPARSE_BLOCK_H
template<typename MatrixType, int Size>
struct ei_traits<SparseInnerVectorSet<MatrixType, Size> >
{
typedef typename ei_traits<MatrixType>::Scalar Scalar;
enum {
IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit,
Flags = MatrixType::Flags,
RowsAtCompileTime = IsRowMajor ? Size : MatrixType::RowsAtCompileTime,
ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : Size,
CoeffReadCost = MatrixType::CoeffReadCost
};
};
template<typename MatrixType, int Size>
class SparseInnerVectorSet : ei_no_assignment_operator,
public SparseMatrixBase<SparseInnerVectorSet<MatrixType, Size> >
{
enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer)
{}
private:
InnerIterator& operator=(const InnerIterator&);
};
inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
: m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
{
ei_assert(Size!=Dynamic);
ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
// template<typename OtherDerived>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
// {
// return *this;
// }
// template<typename Sparse>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
// {
// return *this;
// }
EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
int m_outerStart;
const ei_int_if_dynamic<Size> m_outerSize;
};
/***************************************************************************
* specialisation for DynamicSparseMatrix
***************************************************************************/
template<typename _Scalar, int _Options, int Size>
class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
: public SparseMatrixBase<SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size> >
{
typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType;
enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer)
{}
private:
InnerIterator& operator=(const InnerIterator&);
};
inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
: m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
{
ei_assert(Size!=Dynamic);
ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
template<typename OtherDerived>
inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
{
if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit))
{
// need to transpose => perform a block evaluation followed by a big swap
DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other);
*this = aux.markAsRValue();
}
else
{
// evaluate/copy vector per vector
for (int j=0; j<m_outerSize.value(); ++j)
{
SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j));
m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data());
}
}
return *this;
}
inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other)
{
return operator=<SparseInnerVectorSet>(other);
}
// template<typename Sparse>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
// {
// return *this;
// }
EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
int m_outerStart;
const ei_int_if_dynamic<Size> m_outerSize;
};
/***************************************************************************
* specialisation for SparseMatrix
***************************************************************************/
/*
template<typename _Scalar, int _Options, int Size>
class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options>, Size>
: public SparseMatrixBase<SparseInnerVectorSet<SparseMatrix<_Scalar, _Options>, Size> >
{
typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType;
enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
: MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer)
{}
};
inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
: m_matrix(matrix), m_outerStart(outer)
{
ei_assert(Size==1);
ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
template<typename OtherDerived>
inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
{
if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit))
{
// need to transpose => perform a block evaluation followed by a big swap
DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other);
*this = aux.markAsRValue();
}
else
{
// evaluate/copy vector per vector
for (int j=0; j<m_outerSize.value(); ++j)
{
SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j));
m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data());
}
}
return *this;
}
inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other)
{
return operator=<SparseInnerVectorSet>(other);
}
inline const Scalar* _valuePtr() const
{ return m_matrix._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
inline const int* _innerIndexPtr() const
{ return m_matrix._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
inline const int* _outerIndexPtr() const { return m_matrix._outerIndexPtr() + m_outerStart; }
// template<typename Sparse>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
// {
// return *this;
// }
EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
int m_outerStart;
const ei_int_if_dynamic<Size> m_outerSize;
};
*/
//----------
/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
template<typename Derived>
SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i)
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVector(i);
}
/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
* (read-only version) */
template<typename Derived>
const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i) const
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVector(i);
}
/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
template<typename Derived>
SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i)
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVector(i);
}
/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
* (read-only version) */
template<typename Derived>
const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i) const
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVector(i);
}
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major).
*/
template<typename Derived>
SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer)
{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer) const
{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
//----------
/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
template<typename Derived>
SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size)
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVectors(start, size);
}
/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
* (read-only version) */
template<typename Derived>
const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size) const
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVectors(start, size);
}
/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
template<typename Derived>
SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size)
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVectors(start, size);
}
/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
* (read-only version) */
template<typename Derived>
const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size) const
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVectors(start, size);
}
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major).
*/
template<typename Derived>
SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize)
{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize) const
{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
# if 0
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
class Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse>
: public SparseMatrixBase<Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse> >
@@ -117,6 +449,6 @@ public:
const ei_int_if_dynamic<ColsAtCompileTime> m_blockCols;
};
#endif
#endif // EIGEN_SPARSEBLOCK_H
#endif // EIGEN_SPARSE_BLOCK_H

View File

@@ -0,0 +1,178 @@
// 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>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_SPARSE_CWISE_H
#define EIGEN_SPARSE_CWISE_H
/** \internal
* convenient macro to defined the return type of a cwise binary operation */
#define EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(OP) \
CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
#define EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE \
SparseCwiseBinaryOp< \
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_SPARSE_CWISE_UNOP_RETURN_TYPE(OP) \
SparseCwiseUnaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType>
/** \internal
* convenient macro to defined the return type of a cwise comparison to a scalar */
/*#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, \
NestByValue<typename ExpressionType::ConstantReturnType> >*/
template<typename ExpressionType> class SparseCwise
{
public:
typedef typename ei_traits<ExpressionType>::Scalar Scalar;
typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
typedef CwiseUnaryOp<ei_scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
inline SparseCwise(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */
inline const ExpressionType& _expression() const { return m_matrix; }
template<typename OtherDerived>
const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
operator*(const SparseMatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
operator*(const MatrixBase<OtherDerived> &other) const;
// template<typename OtherDerived>
// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
// operator/(const SparseMatrixBase<OtherDerived> &other) const;
//
// template<typename OtherDerived>
// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
// operator/(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
min(const SparseMatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
max(const SparseMatrixBase<OtherDerived> &other) const;
const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op) abs() const;
const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op) abs2() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_square_op) square() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cube_op) cube() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_inverse_op) inverse() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sqrt_op) sqrt() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_exp_op) exp() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_log_op) log() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cos_op) cos() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op) sin() const;
// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op) pow(const Scalar& exponent) const;
template<typename OtherDerived>
inline ExpressionType& operator*=(const SparseMatrixBase<OtherDerived> &other);
// template<typename OtherDerived>
// inline ExpressionType& operator/=(const SparseMatrixBase<OtherDerived> &other);
/*
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
operator<(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
operator<=(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
operator>(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
operator>=(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
operator==(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
operator!=(const MatrixBase<OtherDerived>& other) const;
// comparisons to a scalar value
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
operator<(Scalar s) const;
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
operator<=(Scalar s) const;
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
operator>(Scalar s) const;
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
operator>=(Scalar s) const;
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
operator==(Scalar s) const;
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
operator!=(Scalar s) const;
*/
// allow to extend SparseCwise outside Eigen
#ifdef EIGEN_SPARSE_CWISE_PLUGIN
#include EIGEN_SPARSE_CWISE_PLUGIN
#endif
protected:
ExpressionTypeNested m_matrix;
private:
SparseCwise& operator=(const SparseCwise&);
};
template<typename Derived>
inline const SparseCwise<Derived>
SparseMatrixBase<Derived>::cwise() const
{
return derived();
}
template<typename Derived>
inline SparseCwise<Derived>
SparseMatrixBase<Derived>::cwise()
{
return derived();
}
#endif // EIGEN_SPARSE_CWISE_H

View File

@@ -0,0 +1,453 @@
// 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_SPARSE_CWISE_BINARY_OP_H
#define EIGEN_SPARSE_CWISE_BINARY_OP_H
// Here we have to handle 3 cases:
// 1 - sparse op dense
// 2 - dense op sparse
// 3 - sparse op sparse
// We also need to implement a 4th iterator for:
// 4 - dense op dense
// Finally, we also need to distinguish between the product and other operations :
// configuration returned mode
// 1 - sparse op dense product sparse
// generic dense
// 2 - dense op sparse product sparse
// generic dense
// 3 - sparse op sparse product sparse
// generic sparse
// 4 - dense op dense product dense
// generic dense
template<typename BinaryOp, typename Lhs, typename Rhs>
struct ei_traits<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
typedef typename ei_result_of<
BinaryOp(
typename Lhs::Scalar,
typename Rhs::Scalar
)
>::type Scalar;
typedef typename Lhs::Nested LhsNested;
typedef typename Rhs::Nested RhsNested;
typedef typename ei_unref<LhsNested>::type _LhsNested;
typedef typename ei_unref<RhsNested>::type _RhsNested;
enum {
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
LhsFlags = _LhsNested::Flags,
RhsFlags = _RhsNested::Flags,
RowsAtCompileTime = Lhs::RowsAtCompileTime,
ColsAtCompileTime = Lhs::ColsAtCompileTime,
MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
MaxColsAtCompileTime = Lhs::MaxColsAtCompileTime,
Flags = (int(LhsFlags) | int(RhsFlags)) & HereditaryBits,
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
};
};
template<typename BinaryOp, typename Lhs, typename Rhs>
class SparseCwiseBinaryOp : ei_no_assignment_operator,
public SparseMatrixBase<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
public:
class InnerIterator;
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseBinaryOp)
typedef typename ei_traits<SparseCwiseBinaryOp>::LhsNested LhsNested;
typedef typename ei_traits<SparseCwiseBinaryOp>::RhsNested RhsNested;
typedef typename ei_unref<LhsNested>::type _LhsNested;
typedef typename ei_unref<RhsNested>::type _RhsNested;
EIGEN_STRONG_INLINE SparseCwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
: m_lhs(lhs), m_rhs(rhs), m_functor(func)
{
EIGEN_STATIC_ASSERT((_LhsNested::Flags&RowMajorBit)==(_RhsNested::Flags&RowMajorBit),
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER)
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());
}
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
EIGEN_STRONG_INLINE const BinaryOp& functor() const { return m_functor; }
protected:
const LhsNested m_lhs;
const RhsNested m_rhs;
const BinaryOp m_functor;
};
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
int _LhsStorageMode = int(Lhs::Flags) & SparseBit,
int _RhsStorageMode = int(Rhs::Flags) & SparseBit>
class ei_sparse_cwise_binary_op_inner_iterator_selector;
template<typename BinaryOp, typename Lhs, typename Rhs>
class SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
: public ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs, typename SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
{
public:
typedef ei_sparse_cwise_binary_op_inner_iterator_selector<
BinaryOp,Lhs,Rhs, InnerIterator> Base;
EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseBinaryOp& binOp, int outer)
: Base(binOp,outer)
{}
private:
InnerIterator& operator=(const InnerIterator&);
};
/***************************************************************************
* Implementation of inner-iterators
***************************************************************************/
// template<typename T> struct ei_func_is_conjunction { enum { ret = false }; };
// template<typename T> struct ei_func_is_conjunction<ei_scalar_product_op<T> > { enum { ret = true }; };
// TODO generalize the ei_scalar_product_op specialization to all conjunctions if any !
// sparse - sparse (generic)
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
class ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, IsSparse, IsSparse>
{
typedef SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
typedef typename ei_traits<CwiseBinaryXpr>::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename _RhsNested::InnerIterator RhsIterator;
public:
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
: m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
{
this->operator++();
}
EIGEN_STRONG_INLINE Derived& operator++()
{
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
{
m_id = m_lhsIter.index();
m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
++m_lhsIter;
++m_rhsIter;
}
else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
{
m_id = m_lhsIter.index();
m_value = m_functor(m_lhsIter.value(), Scalar(0));
++m_lhsIter;
}
else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
{
m_id = m_rhsIter.index();
m_value = m_functor(Scalar(0), m_rhsIter.value());
++m_rhsIter;
}
else
{
m_id = -1;
}
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
EIGEN_STRONG_INLINE int index() const { return m_id; }
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
const BinaryOp& m_functor;
Scalar m_value;
int m_id;
private:
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
};
// sparse - sparse (product)
template<typename T, typename Lhs, typename Rhs, typename Derived>
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsSparse>
{
typedef ei_scalar_product_op<T> BinaryFunc;
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
typedef typename CwiseBinaryXpr::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
public:
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
: m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
{
while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
{
if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
}
EIGEN_STRONG_INLINE Derived& operator++()
{
++m_lhsIter;
++m_rhsIter;
while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
{
if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
const BinaryFunc& m_functor;
private:
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
};
// sparse - dense (product)
template<typename T, typename Lhs, typename Rhs, typename Derived>
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsDense>
{
typedef ei_scalar_product_op<T> BinaryFunc;
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
typedef typename CwiseBinaryXpr::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
typedef typename ei_traits<CwiseBinaryXpr>::RhsNested RhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
public:
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
: m_rhs(xpr.rhs()), m_lhsIter(xpr.lhs(),outer), m_functor(xpr.functor()), m_outer(outer)
{}
EIGEN_STRONG_INLINE Derived& operator++()
{
++m_lhsIter;
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const
{ return m_functor(m_lhsIter.value(),
m_rhs.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
protected:
const RhsNested m_rhs;
LhsIterator m_lhsIter;
const BinaryFunc m_functor;
const int m_outer;
private:
ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
};
// sparse - dense (product)
template<typename T, typename Lhs, typename Rhs, typename Derived>
class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsDense, IsSparse>
{
typedef ei_scalar_product_op<T> BinaryFunc;
typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
typedef typename CwiseBinaryXpr::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
public:
EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
: m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
{}
EIGEN_STRONG_INLINE Derived& operator++()
{
++m_rhsIter;
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const
{ return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
EIGEN_STRONG_INLINE int index() const { return m_rhsIter.index(); }
EIGEN_STRONG_INLINE int row() const { return m_rhsIter.row(); }
EIGEN_STRONG_INLINE int col() const { return m_rhsIter.col(); }
EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
protected:
const CwiseBinaryXpr& m_xpr;
RhsIterator m_rhsIter;
const BinaryFunc& m_functor;
const int m_outer;
};
/***************************************************************************
* Implementation of SparseMatrixBase and SparseCwise functions/operators
***************************************************************************/
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
Derived, OtherDerived>
SparseMatrixBase<Derived>::operator-(const SparseMatrixBase<OtherDerived> &other) const
{
return SparseCwiseBinaryOp<ei_scalar_difference_op<Scalar>,
Derived, OtherDerived>(derived(), other.derived());
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived &
SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
{
return *this = derived() - other.derived();
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
SparseMatrixBase<Derived>::operator+(const SparseMatrixBase<OtherDerived> &other) const
{
return SparseCwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived &
SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
{
return *this = derived() + other.derived();
}
template<typename ExpressionType>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
SparseCwise<ExpressionType>::operator*(const SparseMatrixBase<OtherDerived> &other) const
{
return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
}
template<typename ExpressionType>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
SparseCwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
{
return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
}
// template<typename ExpressionType>
// template<typename OtherDerived>
// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
// SparseCwise<ExpressionType>::operator/(const SparseMatrixBase<OtherDerived> &other) const
// {
// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
// }
//
// template<typename ExpressionType>
// template<typename OtherDerived>
// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
// SparseCwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
// {
// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
// }
template<typename ExpressionType>
template<typename OtherDerived>
inline ExpressionType& SparseCwise<ExpressionType>::operator*=(const SparseMatrixBase<OtherDerived> &other)
{
return m_matrix.const_cast_derived() = _expression() * other.derived();
}
// template<typename ExpressionType>
// template<typename OtherDerived>
// inline ExpressionType& SparseCwise<ExpressionType>::operator/=(const SparseMatrixBase<OtherDerived> &other)
// {
// return m_matrix.const_cast_derived() = *this / other;
// }
template<typename ExpressionType>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
SparseCwise<ExpressionType>::min(const SparseMatrixBase<OtherDerived> &other) const
{
return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
}
template<typename ExpressionType>
template<typename OtherDerived>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
SparseCwise<ExpressionType>::max(const SparseMatrixBase<OtherDerived> &other) const
{
return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
}
// template<typename Derived>
// template<typename CustomBinaryOp, typename OtherDerived>
// EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
// SparseMatrixBase<Derived>::binaryExpr(const SparseMatrixBase<OtherDerived> &other, const CustomBinaryOp& func) const
// {
// return CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>(derived(), other.derived(), func);
// }
#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H

View File

@@ -0,0 +1,186 @@
// 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_SPARSE_CWISE_UNARY_OP_H
#define EIGEN_SPARSE_CWISE_UNARY_OP_H
template<typename UnaryOp, typename MatrixType>
struct ei_traits<SparseCwiseUnaryOp<UnaryOp, MatrixType> > : ei_traits<MatrixType>
{
typedef typename ei_result_of<
UnaryOp(typename MatrixType::Scalar)
>::type Scalar;
typedef typename MatrixType::Nested MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
};
};
template<typename UnaryOp, typename MatrixType>
class SparseCwiseUnaryOp : ei_no_assignment_operator,
public SparseMatrixBase<SparseCwiseUnaryOp<UnaryOp, MatrixType> >
{
public:
class InnerIterator;
// typedef typename ei_unref<LhsNested>::type _LhsNested;
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseUnaryOp)
inline SparseCwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
: m_matrix(mat), m_functor(func) {}
EIGEN_STRONG_INLINE int rows() const { return m_matrix.rows(); }
EIGEN_STRONG_INLINE int cols() const { return m_matrix.cols(); }
// EIGEN_STRONG_INLINE const typename MatrixType::Nested& _matrix() const { return m_matrix; }
// EIGEN_STRONG_INLINE const UnaryOp& _functor() const { return m_functor; }
protected:
const typename MatrixType::Nested m_matrix;
const UnaryOp m_functor;
};
template<typename UnaryOp, typename MatrixType>
class SparseCwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
{
typedef typename SparseCwiseUnaryOp::Scalar Scalar;
typedef typename ei_traits<SparseCwiseUnaryOp>::_MatrixTypeNested _MatrixTypeNested;
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseUnaryOp& unaryOp, int outer)
: m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor)
{}
EIGEN_STRONG_INLINE InnerIterator& operator++()
{ ++m_iter; return *this; }
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); }
EIGEN_STRONG_INLINE int index() const { return m_iter.index(); }
EIGEN_STRONG_INLINE int row() const { return m_iter.row(); }
EIGEN_STRONG_INLINE int col() const { return m_iter.col(); }
EIGEN_STRONG_INLINE operator bool() const { return m_iter; }
protected:
MatrixTypeIterator m_iter;
const UnaryOp m_functor;
private:
InnerIterator& operator=(const InnerIterator&);
};
template<typename Derived>
template<typename CustomUnaryOp>
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<CustomUnaryOp, Derived>
SparseMatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
{
return SparseCwiseUnaryOp<CustomUnaryOp, Derived>(derived(), func);
}
template<typename Derived>
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
SparseMatrixBase<Derived>::operator-() const
{
return derived();
}
template<typename ExpressionType>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
SparseCwise<ExpressionType>::abs() const
{
return _expression();
}
template<typename ExpressionType>
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
SparseCwise<ExpressionType>::abs2() const
{
return _expression();
}
template<typename Derived>
EIGEN_STRONG_INLINE typename SparseMatrixBase<Derived>::ConjugateReturnType
SparseMatrixBase<Derived>::conjugate() const
{
return ConjugateReturnType(derived());
}
template<typename Derived>
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::RealReturnType
SparseMatrixBase<Derived>::real() const { return derived(); }
template<typename Derived>
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::ImagReturnType
SparseMatrixBase<Derived>::imag() const { return derived(); }
template<typename Derived>
template<typename NewType>
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
SparseMatrixBase<Derived>::cast() const
{
return derived();
}
template<typename Derived>
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
SparseMatrixBase<Derived>::operator*(const Scalar& scalar) const
{
return SparseCwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived>
(derived(), ei_scalar_multiple_op<Scalar>(scalar));
}
template<typename Derived>
EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
SparseMatrixBase<Derived>::operator/(const Scalar& scalar) const
{
return SparseCwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived>
(derived(), ei_scalar_quotient1_op<Scalar>(scalar));
}
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
SparseMatrixBase<Derived>::operator*=(const Scalar& other)
{
for (int j=0; j<outerSize(); ++j)
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
i.valueRef() *= other;
return derived();
}
template<typename Derived>
EIGEN_STRONG_INLINE Derived&
SparseMatrixBase<Derived>::operator/=(const Scalar& other)
{
for (int j=0; j<outerSize(); ++j)
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
i.valueRef() /= other;
return derived();
}
#endif // EIGEN_SPARSE_CWISE_UNARY_OP_H

View File

@@ -0,0 +1,159 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H
#define EIGEN_SPARSE_DIAGONAL_PRODUCT_H
// the product a diagonal matrix with a sparse matrix can be easily
// implemented using expression template. We have two very different cases:
// 1 - diag * row-major sparse
// => each inner vector <=> scalar * sparse vector product
// => so we can reuse CwiseUnaryOp::InnerIterator
// 2 - diag * col-major sparse
// => each inner vector <=> densevector * sparse vector cwise product
// => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
// for that particular case
// The two other cases are symmetric.
template<typename Lhs, typename Rhs>
struct ei_traits<SparseDiagonalProduct<Lhs, Rhs> > : ei_traits<SparseProduct<Lhs, Rhs, DiagonalProduct> >
{
typedef typename ei_cleantype<Lhs>::type _Lhs;
typedef typename ei_cleantype<Rhs>::type _Rhs;
enum {
SparseFlags = ((int(_Lhs::Flags)&Diagonal)==Diagonal) ? int(_Rhs::Flags) : int(_Lhs::Flags),
Flags = SparseBit | (SparseFlags&RowMajorBit)
};
};
enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode>
class ei_sparse_diagonal_product_inner_iterator_selector;
template<typename LhsNested, typename RhsNested>
class SparseDiagonalProduct : public SparseMatrixBase<SparseDiagonalProduct<LhsNested,RhsNested> >, ei_no_assignment_operator
{
typedef typename ei_traits<SparseDiagonalProduct>::_LhsNested _LhsNested;
typedef typename ei_traits<SparseDiagonalProduct>::_RhsNested _RhsNested;
enum {
LhsMode = (_LhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
: (_LhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor,
RhsMode = (_RhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
: (_RhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor
};
public:
EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseDiagonalProduct)
typedef ei_sparse_diagonal_product_inner_iterator_selector
<_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
template<typename Lhs, typename Rhs>
EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
: m_lhs(lhs), m_rhs(rhs)
{
ei_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
}
EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
protected:
LhsNested m_lhs;
RhsNested m_rhs;
};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
class ei_sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
: public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator
{
typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator Base;
public:
inline ei_sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, int outer)
: Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
{}
};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
class ei_sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
: public SparseCwiseBinaryOp<
ei_scalar_product_op<typename Lhs::Scalar>,
SparseInnerVectorSet<Rhs,1>,
typename Lhs::_CoeffsVectorType>::InnerIterator
{
typedef typename SparseCwiseBinaryOp<
ei_scalar_product_op<typename Lhs::Scalar>,
SparseInnerVectorSet<Rhs,1>,
typename Lhs::_CoeffsVectorType>::InnerIterator Base;
public:
inline ei_sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, int outer)
: Base(expr.rhs().innerVector(outer) .cwise()* expr.lhs().diagonal(), 0)
{}
private:
ei_sparse_diagonal_product_inner_iterator_selector& operator=(const ei_sparse_diagonal_product_inner_iterator_selector&);
};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
class ei_sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
: public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator
{
typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator Base;
public:
inline ei_sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, int outer)
: Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
{}
};
template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
class ei_sparse_diagonal_product_inner_iterator_selector
<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
: public SparseCwiseBinaryOp<
ei_scalar_product_op<typename Rhs::Scalar>,
SparseInnerVectorSet<Lhs,1>,
NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator
{
typedef typename SparseCwiseBinaryOp<
ei_scalar_product_op<typename Rhs::Scalar>,
SparseInnerVectorSet<Lhs,1>,
NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator Base;
public:
inline ei_sparse_diagonal_product_inner_iterator_selector(
const SparseDiagonalProductType& expr, int outer)
: Base(expr.lhs().innerVector(outer) .cwise()* expr.rhs().diagonal().transpose().nestByValue(), 0)
{}
};
#endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H

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