mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
1396 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc2f92ba4a | ||
|
|
2eb8b99a32 | ||
|
|
83c726b343 | ||
|
|
473e70e8be | ||
|
|
80e72a2653 | ||
|
|
201a317912 | ||
|
|
2a3680da3d | ||
|
|
4f7baefa81 | ||
|
|
38b9ff8b6f | ||
|
|
87112908be | ||
|
|
d5c2a01031 | ||
|
|
4c8f0cbc1f | ||
|
|
538bc98b33 | ||
|
|
29f5f098cc | ||
|
|
c21f2cde34 | ||
|
|
909747d6b2 | ||
|
|
1cff196837 | ||
|
|
4ecd782c31 | ||
|
|
84a65f996f | ||
|
|
17c40e5524 | ||
|
|
51f763eaba | ||
|
|
f5e01a2cde | ||
|
|
8d16e2aa27 | ||
|
|
547a3c0d28 | ||
|
|
a432b017fb | ||
|
|
b4669f9036 | ||
|
|
4854326ae8 | ||
|
|
ea12669f7a | ||
|
|
b4388ee38b | ||
|
|
04d9fe13c6 | ||
|
|
4bf0765d71 | ||
|
|
0e35730e0b | ||
|
|
2f9b1bf398 | ||
|
|
18a13c65fe | ||
|
|
bd6e042f49 | ||
|
|
b71ee76d8d | ||
|
|
8d4d85161e | ||
|
|
e4ed2566d5 | ||
|
|
8fb4069b2a | ||
|
|
ed48e38578 | ||
|
|
83f2c809ed | ||
|
|
c090c6544b | ||
|
|
bb0fad0c70 | ||
|
|
a87cd61c13 | ||
|
|
3b29688ca2 | ||
|
|
f32ad79b41 | ||
|
|
d039c88096 | ||
|
|
cc26185d91 | ||
|
|
e6fd3fa177 | ||
|
|
249d2f360b | ||
|
|
34da70e0ce | ||
|
|
55565a0da4 | ||
|
|
4daa1292d7 | ||
|
|
c47fb1f35f | ||
|
|
2ee4b8e945 | ||
|
|
81912b3c41 | ||
|
|
efc7c2121a | ||
|
|
f22036f5f8 | ||
|
|
14fcbfb009 | ||
|
|
0b18ffe175 | ||
|
|
0f20aa3073 | ||
|
|
2de7f0f97a | ||
|
|
2c329453b1 | ||
|
|
2beec14503 | ||
|
|
5f35869461 | ||
|
|
c134d75351 | ||
|
|
092681132c | ||
|
|
0d807dce07 | ||
|
|
e8559eaed6 | ||
|
|
ffadb5b9b0 | ||
|
|
fa30d77188 | ||
|
|
7dc0c4e8f6 | ||
|
|
b3b9d7a14c | ||
|
|
32f0c782c3 | ||
|
|
7031f4e783 | ||
|
|
deea165867 | ||
|
|
406a7889b3 | ||
|
|
2f41f887d0 | ||
|
|
b9827c495e | ||
|
|
6056f4404c | ||
|
|
efd484546e | ||
|
|
a92681e0d2 | ||
|
|
47592d31ea | ||
|
|
1a9dda6bfd | ||
|
|
4c1a2b5614 | ||
|
|
c308cb1b24 | ||
|
|
85e9e6e780 | ||
|
|
c030925a66 | ||
|
|
fd074be1a0 | ||
|
|
e685bd7f46 | ||
|
|
e82f507747 | ||
|
|
1eea595550 | ||
|
|
d0980c7706 | ||
|
|
9055400f3d | ||
|
|
acb3c60295 | ||
|
|
f8b88d21a6 | ||
|
|
89a222ce50 | ||
|
|
960ec7aef2 | ||
|
|
e8bd2d49b3 | ||
|
|
f444996a7a | ||
|
|
a7c2e62a52 | ||
|
|
9ff967199a | ||
|
|
dc0ef2cbed | ||
|
|
7aa90a3b0f | ||
|
|
56488ddc0f | ||
|
|
165b69ca74 | ||
|
|
7abf6d02db | ||
|
|
73cb54835c | ||
|
|
cfe315476f | ||
|
|
f1583e86f6 | ||
|
|
4bd69750ed | ||
|
|
d40e32c94e | ||
|
|
a0bf1b4242 | ||
|
|
cf645db95b | ||
|
|
13135a82bd | ||
|
|
769cb99845 | ||
|
|
ba9add3c59 | ||
|
|
ddfb72a92f | ||
|
|
8c7e281c9e | ||
|
|
66c092e44e | ||
|
|
3ec6d38f35 | ||
|
|
96f64441f7 | ||
|
|
5af4d77511 | ||
|
|
88ac8ffad5 | ||
|
|
edb0183e0c | ||
|
|
befa141699 | ||
|
|
5c70b43abd | ||
|
|
6a3797f46f | ||
|
|
c4432aad15 | ||
|
|
ea0168c5a5 | ||
|
|
05fad4959a | ||
|
|
98eedb0c9a | ||
|
|
71424c4bf8 | ||
|
|
e59b246b08 | ||
|
|
4aa7038074 | ||
|
|
d9c80169e0 | ||
|
|
b514c943c7 | ||
|
|
8ba643a903 | ||
|
|
595c00157c | ||
|
|
1c6b224fb3 | ||
|
|
2361ec9c0e | ||
|
|
fcd213a297 | ||
|
|
37ed0d991a | ||
|
|
62b08cf9f9 | ||
|
|
46f011466b | ||
|
|
f600bdd76b | ||
|
|
421aa4f358 | ||
|
|
554356b034 | ||
|
|
97119f854f | ||
|
|
51ab034f63 | ||
|
|
0ebce69424 | ||
|
|
a748673bbb | ||
|
|
8597ee502b | ||
|
|
ac66f1c73d | ||
|
|
b392e6b21c | ||
|
|
e88aaae5f4 | ||
|
|
2d217a60a7 | ||
|
|
ef1439252c | ||
|
|
847bb317cd | ||
|
|
62d334c7d3 | ||
|
|
7713b29084 | ||
|
|
a08df3ff34 | ||
|
|
5bb9459124 | ||
|
|
80fd8fab87 | ||
|
|
84eeabd223 | ||
|
|
058fa781d7 | ||
|
|
b03209a7a6 | ||
|
|
71590d0ac7 | ||
|
|
1e1b4b6678 | ||
|
|
2e3353634f | ||
|
|
2461531e5a | ||
|
|
a68917594b | ||
|
|
3b93b1afb3 | ||
|
|
0fb74c1f8b | ||
|
|
bf650a3686 | ||
|
|
8fa951e31d | ||
|
|
1b64edbfd4 | ||
|
|
c74284ed81 | ||
|
|
b09316fbea | ||
|
|
c5fc8e6bdc | ||
|
|
88c844ae2f | ||
|
|
500c36de61 | ||
|
|
26234720bd | ||
|
|
0e38796e1c | ||
|
|
a2d9a4806a | ||
|
|
a72bf09e6d | ||
|
|
bb3e5c29cc | ||
|
|
81b3d29b26 | ||
|
|
f0b1b1df9b | ||
|
|
e061b7a538 | ||
|
|
8768ff3c31 | ||
|
|
77af14fb62 | ||
|
|
64b29e06b9 | ||
|
|
1c0e8bcf09 | ||
|
|
69fa405096 | ||
|
|
0f464d9d87 | ||
|
|
470d26d580 | ||
|
|
4dded73227 | ||
|
|
953d5ccfd5 | ||
|
|
98604576d1 | ||
|
|
45cbb0bbb1 | ||
|
|
cc641aabb7 | ||
|
|
aa6c516ec1 | ||
|
|
b39413794e | ||
|
|
bd511dde9d | ||
|
|
e2cfddf75f | ||
|
|
0927801a84 | ||
|
|
e972b55ec4 | ||
|
|
fc202bab39 | ||
|
|
fe51319980 | ||
|
|
0918c51e60 | ||
|
|
409547a0c8 | ||
|
|
4470c99975 | ||
|
|
6620aaa4b3 | ||
|
|
f669f5656a | ||
|
|
029d236ceb | ||
|
|
fe25f3b8e3 | ||
|
|
ceb4c9c10b | ||
|
|
cc5d7ff523 | ||
|
|
d771295554 | ||
|
|
fefec723aa | ||
|
|
780b2422e2 | ||
|
|
c21e45fbc5 | ||
|
|
057cfd2f02 | ||
|
|
114e863f08 | ||
|
|
410895a7e4 | ||
|
|
4716c2c666 | ||
|
|
91fe3a3004 | ||
|
|
84bba80916 | ||
|
|
91953d2d37 | ||
|
|
7b35b4cacc | ||
|
|
c3f3580b8f | ||
|
|
deecff97ed | ||
|
|
c6e8caf090 | ||
|
|
d10d6a40dd | ||
|
|
87629cd639 | ||
|
|
bde98df03f | ||
|
|
d4ec48575e | ||
|
|
554aa9b31d | ||
|
|
3af29caae8 | ||
|
|
f2ff8c091e | ||
|
|
f3be317614 | ||
|
|
08081f8293 | ||
|
|
7838fda82c | ||
|
|
3ba6647398 | ||
|
|
01f7918788 | ||
|
|
b50ffaddf2 | ||
|
|
74e460b995 | ||
|
|
c03c73c9b7 | ||
|
|
668518aed6 | ||
|
|
c739102ef9 | ||
|
|
2559fa9b0f | ||
|
|
dcb2a8b184 | ||
|
|
a8f2c6eec7 | ||
|
|
b1eca55328 | ||
|
|
f9931a0392 | ||
|
|
ebdf6a2dbb | ||
|
|
f64045a060 | ||
|
|
590f4b0aa3 | ||
|
|
5ef95fabee | ||
|
|
0f21613698 | ||
|
|
340b8afb14 | ||
|
|
9f99f61e69 | ||
|
|
759bd92a85 | ||
|
|
f89ba2a58b | ||
|
|
f1092d2f73 | ||
|
|
8296c4aaed | ||
|
|
9d82f7e30d | ||
|
|
e896c0ade7 | ||
|
|
5a6ea4edf6 | ||
|
|
b613173350 | ||
|
|
a727a2c4ed | ||
|
|
9dfdbd7e56 | ||
|
|
46fc881e4a | ||
|
|
c6eb84aabc | ||
|
|
e1f1091fde | ||
|
|
638c6948d7 | ||
|
|
e6952a51ba | ||
|
|
b9d314ae19 | ||
|
|
0039cd9cf9 | ||
|
|
14f537c296 | ||
|
|
641e824c56 | ||
|
|
b5124e7cfd | ||
|
|
54e3633b43 | ||
|
|
f697df7237 | ||
|
|
6559d09c60 | ||
|
|
8a382aa119 | ||
|
|
703c526355 | ||
|
|
4cdf3fe427 | ||
|
|
0feff6e987 | ||
|
|
cd679f2c47 | ||
|
|
f074d43f4b | ||
|
|
1ac8600126 | ||
|
|
378bdfb7f0 | ||
|
|
0526dc1bb4 | ||
|
|
1a36590e84 | ||
|
|
7e0b6c56b4 | ||
|
|
b12dd1ae3c | ||
|
|
71676eaddd | ||
|
|
0a0ab6dd15 | ||
|
|
5692723c58 | ||
|
|
8f4b8d204b | ||
|
|
3bd2b41b2e | ||
|
|
4928ea1212 | ||
|
|
b00fe1590d | ||
|
|
c94174b4fe | ||
|
|
91dd53e54d | ||
|
|
279786e987 | ||
|
|
699c80e404 | ||
|
|
ae4644cc68 | ||
|
|
36f7c1337f | ||
|
|
5023afc0af | ||
|
|
63974bcb88 | ||
|
|
79f4a59ed9 | ||
|
|
9f98650d0a | ||
|
|
8638dbb809 | ||
|
|
db5b0741b5 | ||
|
|
8efa5bb439 | ||
|
|
f5f6e2c6f4 | ||
|
|
a5a3a994c8 | ||
|
|
25c7d9164f | ||
|
|
ba44761435 | ||
|
|
1a96594607 | ||
|
|
61db9a0e89 | ||
|
|
b8d9eaa19b | ||
|
|
f806c23012 | ||
|
|
99501a2c4c | ||
|
|
7dad5f797e | ||
|
|
dcad508986 | ||
|
|
608733415a | ||
|
|
57ec399ec9 | ||
|
|
56ca44ad1a | ||
|
|
e8cdbedefb | ||
|
|
6ccf97f3e6 | ||
|
|
433bce5c3a | ||
|
|
775f7e5fbb | ||
|
|
a819fa148d | ||
|
|
1a8dc85142 | ||
|
|
4974d1d2b4 | ||
|
|
e2f3e4e4aa | ||
|
|
b26e697182 | ||
|
|
b1f9f603a0 | ||
|
|
5384e89147 | ||
|
|
8518ba0bbc | ||
|
|
80cae358b0 | ||
|
|
0efaff9b3b | ||
|
|
41a20994cc | ||
|
|
a910a7466e | ||
|
|
4371911861 | ||
|
|
5fc4ce6449 | ||
|
|
77294047d6 | ||
|
|
bea36925db | ||
|
|
7f7a712062 | ||
|
|
30c849669d | ||
|
|
e0a8615b94 | ||
|
|
8efd9142b3 | ||
|
|
80ed5bd90c | ||
|
|
eb3695d2fc | ||
|
|
48db34a7b9 | ||
|
|
da584912b6 | ||
|
|
509e4ddc02 | ||
|
|
b33cf92878 | ||
|
|
1d3c8306f8 | ||
|
|
ec785b0180 | ||
|
|
eeabf7975e | ||
|
|
c2d1074932 | ||
|
|
722916e19d | ||
|
|
cb37f818ca | ||
|
|
9a06a71627 | ||
|
|
c6fefe5d8e | ||
|
|
ee06f78679 | ||
|
|
9ea09179b5 | ||
|
|
b1789c112b | ||
|
|
2dde63499c | ||
|
|
7f2c6ed2fa | ||
|
|
c5a3777666 | ||
|
|
0833b82efd | ||
|
|
85c3389b28 | ||
|
|
67fcf47ecb | ||
|
|
fcecafde3a | ||
|
|
d62bfe73a9 | ||
|
|
bc99c5f7db | ||
|
|
1946cc4478 | ||
|
|
5e62427e22 | ||
|
|
4ec2f07a5b | ||
|
|
883168ed94 | ||
|
|
e5f134006b | ||
|
|
d2fc597d5b | ||
|
|
3d25b1f5b8 | ||
|
|
acecb7b09f | ||
|
|
21c0a2ce0c | ||
|
|
debc97821c | ||
|
|
e2e7ba9f85 | ||
|
|
bd2d330b25 | ||
|
|
79225db0b6 | ||
|
|
c426054767 | ||
|
|
1fa793cb97 | ||
|
|
04ffb9956e | ||
|
|
94ed7c81e6 | ||
|
|
fcb3573d17 | ||
|
|
fae4fd7a26 | ||
|
|
cf09c5f687 | ||
|
|
b508619392 | ||
|
|
0f65f2762d | ||
|
|
87524922dc | ||
|
|
a303b6a733 | ||
|
|
fe57b2f963 | ||
|
|
c12b7896d0 | ||
|
|
973e6a035f | ||
|
|
84aaa03182 | ||
|
|
aa5f79206f | ||
|
|
b4a9b3f496 | ||
|
|
d04f23260d | ||
|
|
8838b0a1ff | ||
|
|
f786897e4b | ||
|
|
7acd38d19e | ||
|
|
b50e5bc816 | ||
|
|
a370b1f2e2 | ||
|
|
a13bc22204 | ||
|
|
4b7c3abbea | ||
|
|
feacfa5f83 | ||
|
|
8472e697ca | ||
|
|
65af852b54 | ||
|
|
ae697b471c | ||
|
|
94e47798f4 | ||
|
|
d853adffdb | ||
|
|
880e72c130 | ||
|
|
bfdd9f3ac9 | ||
|
|
c566cfe2ba | ||
|
|
dba55041ab | ||
|
|
fd1aaf4772 | ||
|
|
c806009453 | ||
|
|
2cc41dbe83 | ||
|
|
c26e8a1af3 | ||
|
|
0ec1fc9e11 | ||
|
|
99d75235a9 | ||
|
|
4c70b0a762 | ||
|
|
d3f52debc6 | ||
|
|
0219f8aed4 | ||
|
|
2ed1838aeb | ||
|
|
4b36c3591f | ||
|
|
a991f94c0e | ||
|
|
498b7eed25 | ||
|
|
767424af18 | ||
|
|
a80e17cfe8 | ||
|
|
349c2c9235 | ||
|
|
48d537f59f | ||
|
|
538c059aa4 | ||
|
|
a48b82eece | ||
|
|
ccd70ba123 | ||
|
|
44beee9d68 | ||
|
|
0a07ac574e | ||
|
|
6c047d398d | ||
|
|
4b886e6b39 | ||
|
|
5741349294 | ||
|
|
118b1113d9 | ||
|
|
503c176d8e | ||
|
|
dbdd8b0883 | ||
|
|
d44d432baa | ||
|
|
893bfcf95f | ||
|
|
fb53ff1eda | ||
|
|
7a17639953 | ||
|
|
bbce6fa65d | ||
|
|
95a430a2ca | ||
|
|
152f3218ac | ||
|
|
af2e5995e2 | ||
|
|
1269392822 | ||
|
|
b7271dffb5 | ||
|
|
8b2afe33a1 | ||
|
|
5cc23199be | ||
|
|
7caaf6453b | ||
|
|
1c236f4c9a | ||
|
|
1fa6fe2abd | ||
|
|
9d3c69952b | ||
|
|
5180bb5e47 | ||
|
|
0187504912 | ||
|
|
6d26deb894 | ||
|
|
81517eebc1 | ||
|
|
12d59465cb | ||
|
|
e404841235 | ||
|
|
15c946338f | ||
|
|
56a0bbbbee | ||
|
|
842e31cf5c | ||
|
|
abd3502e9e | ||
|
|
76c3cf6949 | ||
|
|
bc34ee3365 | ||
|
|
9a04cd307c | ||
|
|
f0a62c90bc | ||
|
|
2946992ad4 | ||
|
|
821ff0ecfb | ||
|
|
2c4cace56c | ||
|
|
8a502233d8 | ||
|
|
b2755edcdd | ||
|
|
d1ef3c3546 | ||
|
|
edaefeb978 | ||
|
|
3bd31e21b5 | ||
|
|
75e269c77b | ||
|
|
74cde0c925 | ||
|
|
ce2035af86 | ||
|
|
6d0f0b8cec | ||
|
|
4ba8aa1482 | ||
|
|
27d6b4daf9 | ||
|
|
446001ef51 | ||
|
|
13cbc751c9 | ||
|
|
421feea3b2 | ||
|
|
7817bc19a4 | ||
|
|
eb13ada3aa | ||
|
|
36448c9e28 | ||
|
|
de0d8a010e | ||
|
|
72569f17ec | ||
|
|
3878e6f170 | ||
|
|
ff46ec0f24 | ||
|
|
ae514ddfe5 | ||
|
|
f9d6d3780f | ||
|
|
abba11bdcf | ||
|
|
d9e0336a78 | ||
|
|
333905b0c2 | ||
|
|
5fa69422a2 | ||
|
|
de38ff2499 | ||
|
|
60e093a9dc | ||
|
|
56408504e4 | ||
|
|
974fe38ca3 | ||
|
|
c0205ca4af | ||
|
|
10f8aabb61 | ||
|
|
80de35b6c5 | ||
|
|
60663a510a | ||
|
|
03dd4dd91a | ||
|
|
0a18eecab3 | ||
|
|
7b044c0ead | ||
|
|
755e77266f | ||
|
|
07c5500d70 | ||
|
|
e70506dd8f | ||
|
|
2ae20d558b | ||
|
|
62bce6e5e6 | ||
|
|
060e835ee9 | ||
|
|
0ca43f7e9a | ||
|
|
8b3be4907d | ||
|
|
0bf5894861 | ||
|
|
e44d78dab3 | ||
|
|
c2f66c65aa | ||
|
|
125619146b | ||
|
|
341ae8665d | ||
|
|
fc23e93707 | ||
|
|
0f0580b97c | ||
|
|
486ca277a0 | ||
|
|
10a79ca3a3 | ||
|
|
466d6d41c6 | ||
|
|
8514179aa3 | ||
|
|
0403d49006 | ||
|
|
c83e01f2d6 | ||
|
|
26db954776 | ||
|
|
fda680f9cf | ||
|
|
dfc54e1bbf | ||
|
|
749b56f6af | ||
|
|
af9c9f7706 | ||
|
|
9452eb38f8 | ||
|
|
470aa15c35 | ||
|
|
188a13f9fe | ||
|
|
efdff15749 | ||
|
|
dacd39ea76 | ||
|
|
74db22455a | ||
|
|
b23556bbbd | ||
|
|
1abe4ed14c | ||
|
|
d43f737b4a | ||
|
|
f50548e86a | ||
|
|
15bad3670b | ||
|
|
8846aa6d1b | ||
|
|
80993b95d3 | ||
|
|
b24fe22b1a | ||
|
|
c82dc227f1 | ||
|
|
a96f3d629c | ||
|
|
47829e2d16 | ||
|
|
1f398dfc82 | ||
|
|
b3a0365429 | ||
|
|
eb39296028 | ||
|
|
72c4f8ca8f | ||
|
|
b121eecf60 | ||
|
|
8754341848 | ||
|
|
daad9585a3 | ||
|
|
b051bbd64f | ||
|
|
b3d63b4db2 | ||
|
|
1c4b69c5fb | ||
|
|
8a74ce922c | ||
|
|
863b7362bc | ||
|
|
1bf3b34849 | ||
|
|
f9580a3473 | ||
|
|
fbb53b6cbb | ||
|
|
85c7659574 | ||
|
|
bc065c75d2 | ||
|
|
e6cc24cbd6 | ||
|
|
0369db12af | ||
|
|
7ff266e3ce | ||
|
|
b4a709520d | ||
|
|
c1d0f15bde | ||
|
|
124d12a915 | ||
|
|
f29dbec321 | ||
|
|
01f3ca3e8d | ||
|
|
aec3d90ca6 | ||
|
|
460662cbcc | ||
|
|
1ed9e2d004 | ||
|
|
e49e84d979 | ||
|
|
c3e4080474 | ||
|
|
2959045f2f | ||
|
|
36fffe48f7 | ||
|
|
fb5c1e9097 | ||
|
|
0ba490cf80 | ||
|
|
25a3e65a68 | ||
|
|
be3477e206 | ||
|
|
2e50289ba3 | ||
|
|
b49ef99617 | ||
|
|
9c0aa81fbf | ||
|
|
3d298da269 | ||
|
|
eeadc06e83 | ||
|
|
4403800e11 | ||
|
|
9062f74d13 | ||
|
|
6a3423da80 | ||
|
|
9ac3c821ea | ||
|
|
33c702c79f | ||
|
|
756292f8aa | ||
|
|
8c8db49331 | ||
|
|
eeb43f9e2b | ||
|
|
16047c8d4a | ||
|
|
916ef48846 | ||
|
|
f1d8c13dbc | ||
|
|
9faad2932f | ||
|
|
f8fad09301 | ||
|
|
72e7529708 | ||
|
|
1aa2bf8274 | ||
|
|
b1892ab14d | ||
|
|
439feca139 | ||
|
|
e6d55c081b | ||
|
|
57f71a5552 | ||
|
|
5e890d3ad7 | ||
|
|
2d90484450 | ||
|
|
84a7ead059 | ||
|
|
d6236d3b26 | ||
|
|
921a645481 | ||
|
|
4b678b96eb | ||
|
|
51b3f558bb | ||
|
|
6162672dc5 | ||
|
|
e54898f53e | ||
|
|
fafc829424 | ||
|
|
abb33258ce | ||
|
|
25bceefb4e | ||
|
|
60314beb38 | ||
|
|
280661e67d | ||
|
|
ff9bfc45f7 | ||
|
|
42e27d41a2 | ||
|
|
a44a343f03 | ||
|
|
18fbe7e7d4 | ||
|
|
3eb5253ca1 | ||
|
|
305aa1f9c5 | ||
|
|
50085d2c28 | ||
|
|
e51da9c3a8 | ||
|
|
953ec08089 | ||
|
|
3e59163a24 | ||
|
|
4dd55a2958 | ||
|
|
f25338f4d7 | ||
|
|
51357a6622 | ||
|
|
107bb308c3 | ||
|
|
c2ff44cbf3 | ||
|
|
c53f88297c | ||
|
|
6f58a41097 | ||
|
|
2a3c3c49a1 | ||
|
|
fc13b37c55 | ||
|
|
db76193bc7 | ||
|
|
647622281e | ||
|
|
d79516660c | ||
|
|
26d2cdefd4 | ||
|
|
db183ca7b3 | ||
|
|
702a3c17db | ||
|
|
5f5a8d97c0 | ||
|
|
bae2e3327b | ||
|
|
cd0ff253ec | ||
|
|
929e77192c | ||
|
|
ba694ce8cf | ||
|
|
2116e261fb | ||
|
|
5f3d542b8a | ||
|
|
a0a87410d0 | ||
|
|
2c625ec9ba | ||
|
|
1f371e78e6 | ||
|
|
f7bb7ee3f3 | ||
|
|
d1e9f39a9a | ||
|
|
7f15f27a9e | ||
|
|
922694a2d1 | ||
|
|
baa77ffe38 | ||
|
|
a8283e0ed2 | ||
|
|
4aac87251f | ||
|
|
6daa6a0d16 | ||
|
|
2a251ffab0 | ||
|
|
9b729f93a1 | ||
|
|
946b99dd5c | ||
|
|
50eef6dfc3 | ||
|
|
62f332fc04 | ||
|
|
3eba5e1101 | ||
|
|
529e6cb552 | ||
|
|
36e6c9064f | ||
|
|
a325d1cb1e | ||
|
|
da62eb22e4 | ||
|
|
77af4cc3c9 | ||
|
|
5e72151ca5 | ||
|
|
2cd38a6634 | ||
|
|
84ad8ce7e3 | ||
|
|
40b74411e4 | ||
|
|
14c8793a70 | ||
|
|
424c3ad266 | ||
|
|
a53f2b0e43 | ||
|
|
cd0b433540 | ||
|
|
338d2ec42b | ||
|
|
0a945687b7 | ||
|
|
a0d1aac6c5 | ||
|
|
2bdb3b1afd | ||
|
|
3c7686630d | ||
|
|
4f440b8123 | ||
|
|
a20e2462bf | ||
|
|
c0f76ce2cf | ||
|
|
df604e4f49 | ||
|
|
5f1eedd655 | ||
|
|
296cb40161 | ||
|
|
40bb98e76a | ||
|
|
9b7a6f0122 | ||
|
|
ffd3654f67 | ||
|
|
b1169ce40c | ||
|
|
d1460d9278 | ||
|
|
cf7cf7b490 | ||
|
|
f27f55bee3 | ||
|
|
e955725ff1 | ||
|
|
25b2f6624d | ||
|
|
23bb592a2d | ||
|
|
75d19bb087 | ||
|
|
62f948c56a | ||
|
|
da1e356306 | ||
|
|
54fbbe7b4e | ||
|
|
ea0906dfd8 | ||
|
|
cc1bacea5b | ||
|
|
c285fda7f4 | ||
|
|
1967e7f2f3 | ||
|
|
77d57cd681 | ||
|
|
e3557e8dd2 | ||
|
|
5214466b7a | ||
|
|
5c4733f6e4 | ||
|
|
b47ef1431f | ||
|
|
e25e674852 | ||
|
|
4b6b76463a | ||
|
|
904509fbb6 | ||
|
|
0dfb73d46a | ||
|
|
7fa83e7374 | ||
|
|
7d53633e05 | ||
|
|
bc072c5cba | ||
|
|
47981c5925 | ||
|
|
1eefa5a841 | ||
|
|
e4b6979334 | ||
|
|
b9ee880f07 | ||
|
|
2bf58316ee | ||
|
|
85777fc131 | ||
|
|
58687aa5e6 | ||
|
|
339f14b8d1 | ||
|
|
d4cc1bdc7f | ||
|
|
8e19027130 | ||
|
|
ef4a86d6b8 | ||
|
|
68eafc10b1 | ||
|
|
1cb71a8782 | ||
|
|
ac1bb3e5b3 | ||
|
|
4860da2de1 | ||
|
|
7a915f6846 | ||
|
|
1a817d3b70 | ||
|
|
8ee38d2db6 | ||
|
|
f365380496 | ||
|
|
3a9f9faada | ||
|
|
998455a570 | ||
|
|
0a8e4712d1 | ||
|
|
61b88d2feb | ||
|
|
bf334b8ae5 | ||
|
|
8f4cdbbc8f | ||
|
|
7390af91b6 | ||
|
|
1e6f53e070 | ||
|
|
6f846ef9c6 | ||
|
|
324e7e8fc9 | ||
|
|
3c63446507 | ||
|
|
746d2db6ed | ||
|
|
441f97b2df | ||
|
|
0ad7a644df | ||
|
|
7ffd55c980 | ||
|
|
75e574275c | ||
|
|
c401167712 | ||
|
|
73e686c6a4 | ||
|
|
ae039dde13 | ||
|
|
f0648f8860 | ||
|
|
08c615f1e4 | ||
|
|
54607665ab | ||
|
|
d73ee84d37 | ||
|
|
a7bd4c455a | ||
|
|
b868bfb84a | ||
|
|
3b19b466a7 | ||
|
|
199ac3f2e7 | ||
|
|
e3ba5329ff | ||
|
|
17f119689e | ||
|
|
f9496d341f | ||
|
|
e745a450de | ||
|
|
e86adc87e9 | ||
|
|
b59f045c07 | ||
|
|
755be9016a | ||
|
|
957c2c291b | ||
|
|
15c2c083e8 | ||
|
|
3117036b80 | ||
|
|
1c3843bf86 | ||
|
|
0ddde223e9 | ||
|
|
3849cc65ee | ||
|
|
5dbbe6b400 | ||
|
|
ec0a8b2e6d | ||
|
|
7fa87a8b12 | ||
|
|
b29b81a1f4 | ||
|
|
47585c8ab2 | ||
|
|
c415b627a7 | ||
|
|
78bb808337 | ||
|
|
963d338922 | ||
|
|
98ef44fe55 | ||
|
|
1fdef63d1f | ||
|
|
de150b1e14 | ||
|
|
55453c51e8 | ||
|
|
eb49100de9 | ||
|
|
afb1a8c124 | ||
|
|
c06ec0f464 | ||
|
|
95ecd582a3 | ||
|
|
b0979b8598 | ||
|
|
774c3c1e0a | ||
|
|
f80c8e17eb | ||
|
|
38ab7e6ed0 | ||
|
|
1ee4e2db15 | ||
|
|
aa664eabb9 | ||
|
|
4304c73542 | ||
|
|
925fb6b937 | ||
|
|
a77458a8ff | ||
|
|
a669052f12 | ||
|
|
36a2b2e9dc | ||
|
|
2859a31ac8 | ||
|
|
d13711a363 | ||
|
|
fe102248ac | ||
|
|
8c8ae2d819 | ||
|
|
29aebf96e6 | ||
|
|
79085e08e9 | ||
|
|
a961d72e65 | ||
|
|
abc1ca0af1 | ||
|
|
c331ce6b8e | ||
|
|
ed37c44765 | ||
|
|
8998f4099e | ||
|
|
96cb58fa3b | ||
|
|
ea99433523 | ||
|
|
cee62018fc | ||
|
|
58cfac9a12 | ||
|
|
45515779d3 | ||
|
|
6fa6cdd2b9 | ||
|
|
0f1e321dd4 | ||
|
|
789674809f | ||
|
|
eb56461ac2 | ||
|
|
736267cf6b | ||
|
|
7402fea0a8 | ||
|
|
e3ab46b8c9 | ||
|
|
c794099e69 | ||
|
|
aa524604b7 | ||
|
|
c55c5763fe | ||
|
|
eda79321be | ||
|
|
df92649379 | ||
|
|
0f94607947 | ||
|
|
edebb15275 | ||
|
|
9aa3dc4e21 | ||
|
|
881aab14b4 | ||
|
|
0320f7e3a7 | ||
|
|
5811e68dd1 | ||
|
|
9217de8bf2 | ||
|
|
84cb1d72b8 | ||
|
|
56de8d3816 | ||
|
|
b4beba72a2 | ||
|
|
b5e3d76aa5 | ||
|
|
0b7f95a03f | ||
|
|
d67aa1549b | ||
|
|
07986189b7 | ||
|
|
c0f2cb016e | ||
|
|
2fb64578aa | ||
|
|
ecf1f1d589 | ||
|
|
e7ef26fa44 | ||
|
|
450d0c3de0 | ||
|
|
f9d2f3903e | ||
|
|
6f64b0b487 | ||
|
|
c20e3641de | ||
|
|
2dbfd83424 | ||
|
|
7388fdf560 | ||
|
|
c9788d55b9 | ||
|
|
ae4d9434e2 | ||
|
|
4def7b1fa5 | ||
|
|
c79bd4b64b | ||
|
|
cf7eaed38d | ||
|
|
3d8d0f6269 | ||
|
|
b0e19db1cf | ||
|
|
8d85ce88e1 | ||
|
|
4eb92e5647 | ||
|
|
ccb4dec719 | ||
|
|
82b09fcb91 | ||
|
|
ecbd67a15a | ||
|
|
934ce93886 | ||
|
|
5c5231ab71 | ||
|
|
2606abed53 | ||
|
|
a7d20038df | ||
|
|
3454b4e5f1 | ||
|
|
94684721bd | ||
|
|
1388f4f9fd | ||
|
|
6d665d446b | ||
|
|
2c3c95990d | ||
|
|
6d6df90c9a | ||
|
|
c354bd47f7 | ||
|
|
9777a5ca60 | ||
|
|
9746396d1b | ||
|
|
e5d0cb54a5 | ||
|
|
1dd015fea6 | ||
|
|
45a4aad572 | ||
|
|
e1d461352e | ||
|
|
11fbdcbc38 | ||
|
|
0fa8290366 | ||
|
|
d936ddc3d1 | ||
|
|
de8336a9bc | ||
|
|
ffc995c9e4 | ||
|
|
d5a795f673 | ||
|
|
b30706bd5c | ||
|
|
e0dbb68c2f | ||
|
|
59f5f155c2 | ||
|
|
20c840be15 | ||
|
|
1afd50e0f3 | ||
|
|
3c66bb136b | ||
|
|
7098e6d976 | ||
|
|
feaf7c7e6d | ||
|
|
d567e3b893 | ||
|
|
148acf8e4f | ||
|
|
0587db8bf5 | ||
|
|
7903d3f27b | ||
|
|
a803ff18a9 | ||
|
|
91288e9bf9 | ||
|
|
fbd5eac7cf | ||
|
|
1b333c89c9 | ||
|
|
a1fcf599fa | ||
|
|
a91a7a1964 | ||
|
|
3b2321e3ab | ||
|
|
b446ff037e | ||
|
|
5afcb4965c | ||
|
|
096af59799 | ||
|
|
8044b00a7f | ||
|
|
aecc78325a | ||
|
|
1cb8de1250 | ||
|
|
56c4851323 | ||
|
|
ceae5b4145 | ||
|
|
ec65e6648c | ||
|
|
d992634fbc | ||
|
|
5e8622477b | ||
|
|
1221dd90aa | ||
|
|
93870d95b7 | ||
|
|
f603823ef3 | ||
|
|
8d0441052e | ||
|
|
82c8163067 | ||
|
|
1c0728043a | ||
|
|
e497a27ddc | ||
|
|
ad59ade116 | ||
|
|
39bfbd43f0 | ||
|
|
10aa14592a | ||
|
|
8d2bb2c20d | ||
|
|
c94fde118a | ||
|
|
51e85c936d | ||
|
|
8a94cb3edd | ||
|
|
7f3162f707 | ||
|
|
ee86679096 | ||
|
|
58fe2fc2b2 | ||
|
|
729363114f | ||
|
|
1697d7a179 | ||
|
|
3e1fe8e416 | ||
|
|
b776458ccb | ||
|
|
c4902a3d01 | ||
|
|
7d73c7f18b | ||
|
|
6f123d209e | ||
|
|
052aedd394 | ||
|
|
fb03b56647 | ||
|
|
6a81594771 | ||
|
|
9ce0d78513 | ||
|
|
a419cea4a0 | ||
|
|
ba3457cab2 | ||
|
|
14bc4b9704 | ||
|
|
e45a6bed45 | ||
|
|
cc73164aa8 | ||
|
|
f0a4c9d5ab | ||
|
|
8be011e776 | ||
|
|
a078f442a3 | ||
|
|
cf1a7bfbe1 | ||
|
|
bc401eb6fa | ||
|
|
b286a1e75c | ||
|
|
6bf3cc2732 | ||
|
|
7ae9b0805d | ||
|
|
08f7b3221d | ||
|
|
72707a8664 | ||
|
|
8a0845ebd7 | ||
|
|
3e42b775ea | ||
|
|
dead9085c0 | ||
|
|
4fe56a0e02 | ||
|
|
35a2c9cde7 | ||
|
|
bb4b67cf39 | ||
|
|
0a6c472335 | ||
|
|
2db792852f | ||
|
|
847d801a4c | ||
|
|
aceae8314b | ||
|
|
16d4c7a5e8 | ||
|
|
a395024d44 | ||
|
|
f74ed34539 | ||
|
|
5e26b7cf9d | ||
|
|
74b1d79d77 | ||
|
|
0b362e0c9a | ||
|
|
a6be1952f4 | ||
|
|
2379ccffcb | ||
|
|
88aa18df64 | ||
|
|
0bd5671b9e | ||
|
|
8dd3b716e3 | ||
|
|
7eefdb948c | ||
|
|
082f7ddc37 | ||
|
|
bbc0ada12a | ||
|
|
9be72cda2a | ||
|
|
ae40583965 | ||
|
|
5806e73800 | ||
|
|
2bf63c6b4a | ||
|
|
1b3d7fc04c | ||
|
|
da6ec81282 | ||
|
|
354bd8a428 | ||
|
|
5c0f294098 | ||
|
|
804ef2350d | ||
|
|
a6b130c63c | ||
|
|
8eac97138a | ||
|
|
1dd176b0b0 | ||
|
|
131027ee0a | ||
|
|
db7d49efbb | ||
|
|
9fdc6258cf | ||
|
|
21fecd5252 | ||
|
|
6fecb6f1b6 | ||
|
|
3e439889e0 | ||
|
|
cbc572caf7 | ||
|
|
1e0c2f6ddb | ||
|
|
c98881e130 | ||
|
|
d67548f345 | ||
|
|
6c7ab50811 | ||
|
|
728c3d2cb9 | ||
|
|
af31b6c37a | ||
|
|
93125e372d | ||
|
|
b2e1453e1e | ||
|
|
9621333545 | ||
|
|
5f6ec95291 | ||
|
|
ecd2c8f37b | ||
|
|
5960befc20 | ||
|
|
2eee6eaf3c | ||
|
|
8af02d19b2 | ||
|
|
95b0a6707b | ||
|
|
b1ab6a8e0b | ||
|
|
61cff28618 | ||
|
|
68e8ddaf94 | ||
|
|
3a735a6cf1 | ||
|
|
ccc41128fb | ||
|
|
b3a07eecc5 | ||
|
|
c16b80746a | ||
|
|
cbd7e98174 | ||
|
|
7ed9441ea4 | ||
|
|
5b78780def | ||
|
|
8169c6ac59 | ||
|
|
463554c254 | ||
|
|
82c066b3c4 | ||
|
|
0543cb51b5 | ||
|
|
99e27916cf | ||
|
|
37a1d736bf | ||
|
|
06545058bb | ||
|
|
7002aa858f | ||
|
|
8cfb138e73 | ||
|
|
1b5de5a37b | ||
|
|
a08cba6b5f | ||
|
|
573c587e3d | ||
|
|
551bf5c66a | ||
|
|
2d136d3d7f | ||
|
|
873401032b | ||
|
|
d595fd31f5 | ||
|
|
bffa15142c | ||
|
|
b14a4628af | ||
|
|
3573a10712 | ||
|
|
bd6eca059d | ||
|
|
ed461ba9bc | ||
|
|
3bb57e21a8 | ||
|
|
4b6b3f310f | ||
|
|
cd606bbc94 | ||
|
|
0508af4287 | ||
|
|
3283d98d13 | ||
|
|
0d3f496233 | ||
|
|
6df3bee687 | ||
|
|
97965dde9b | ||
|
|
0b1430ae10 | ||
|
|
c0e08e9e4b | ||
|
|
0715d49908 | ||
|
|
3291580630 | ||
|
|
14422decc2 | ||
|
|
7ea6ef8969 | ||
|
|
31c63ef0b4 | ||
|
|
e170e7070b | ||
|
|
c1921ad3e2 | ||
|
|
c4f08cfc05 | ||
|
|
9e71ecbeec | ||
|
|
ff8d81762d | ||
|
|
6c527bd811 | ||
|
|
e722f36ffa | ||
|
|
febfc7b9b4 | ||
|
|
64a85800bd | ||
|
|
94acccc126 | ||
|
|
34694d8828 | ||
|
|
ee1c55f923 | ||
|
|
f54e62e4a9 | ||
|
|
5fa7262e4c | ||
|
|
fef534f52e | ||
|
|
a7621809fe | ||
|
|
6cf938df53 | ||
|
|
afcfb560a2 | ||
|
|
40c42d9788 | ||
|
|
deab937d45 | ||
|
|
66f1c56aab | ||
|
|
aa0db35185 | ||
|
|
4c08385b74 | ||
|
|
4ccff2d028 | ||
|
|
3a4616d6e3 | ||
|
|
92190a1caf | ||
|
|
ac409f51f1 | ||
|
|
a6a57748dd | ||
|
|
c8c81c1e74 | ||
|
|
60cd361ebe | ||
|
|
c8bfbf4a7e | ||
|
|
01fd880424 | ||
|
|
e3fb190edf | ||
|
|
cfd3d6ce9c | ||
|
|
c39a3fa7a1 | ||
|
|
2a564695f0 | ||
|
|
a58325ac2f | ||
|
|
4cd4be97a7 | ||
|
|
548216b7ca | ||
|
|
e15cb9f4f8 | ||
|
|
bbf373bbe9 | ||
|
|
1200bd2ef0 | ||
|
|
8a49dd5626 | ||
|
|
ce99b502ce | ||
|
|
033ee7f6d9 | ||
|
|
ba2f79e680 | ||
|
|
72461be962 | ||
|
|
33ca9b4ee6 | ||
|
|
ce41b72eb8 | ||
|
|
d5cc083782 | ||
|
|
7313f32efa | ||
|
|
04e1e38eed | ||
|
|
47679c50ae | ||
|
|
76d2ca27e5 | ||
|
|
41e89c73c7 | ||
|
|
ac69d8769f | ||
|
|
6b6071866b | ||
|
|
d357bbd9c0 | ||
|
|
27c068e9d6 | ||
|
|
e94fe4cc3e | ||
|
|
2ca0ccd2f2 | ||
|
|
8d8acc3ab4 | ||
|
|
6c5e915e9a | ||
|
|
f0b82c3ab9 | ||
|
|
6f1a0479b3 | ||
|
|
b5fd774775 | ||
|
|
34ca81b1bf | ||
|
|
7f917807c6 | ||
|
|
8af1ba5346 | ||
|
|
c6f7337032 | ||
|
|
626821b0e3 | ||
|
|
27ca9437a1 | ||
|
|
d0261bd26c | ||
|
|
276801b25a | ||
|
|
d61345f366 | ||
|
|
c15c65990f | ||
|
|
fb6e32a62f | ||
|
|
d331def6cc | ||
|
|
5584275325 | ||
|
|
cc6dd878ee | ||
|
|
fc6ecebc69 | ||
|
|
49034d1570 | ||
|
|
230f5c3aa9 | ||
|
|
c550a0e634 | ||
|
|
28b2abdbea | ||
|
|
654eab3bd6 | ||
|
|
5d1291a4de | ||
|
|
8b4dd78d57 | ||
|
|
f6bac196d5 | ||
|
|
46dd1bb1be | ||
|
|
6b471f205e | ||
|
|
03a956925a | ||
|
|
f97b3cd024 | ||
|
|
5e28c41549 | ||
|
|
e59b38abef | ||
|
|
8f2d068e84 | ||
|
|
5c2d1b4710 | ||
|
|
b93520b1a5 | ||
|
|
cb8da751a0 | ||
|
|
fe0b44e876 | ||
|
|
ae83f5ede9 | ||
|
|
76c230a84d | ||
|
|
57327cc2d5 | ||
|
|
5887e82729 | ||
|
|
af9851d1d7 | ||
|
|
8fe609311d | ||
|
|
8edc964734 | ||
|
|
a37bdfc955 | ||
|
|
03de5c2410 | ||
|
|
4f572e4c14 | ||
|
|
87aee5fda1 | ||
|
|
1bb1a57ef7 | ||
|
|
7c9cdd6030 | ||
|
|
a236e15048 | ||
|
|
ad1dc50b57 | ||
|
|
019dcfc21d | ||
|
|
19521c83b8 | ||
|
|
bbd49d194a | ||
|
|
8f496cd3a3 | ||
|
|
6dc0e59b1e | ||
|
|
2702788da7 | ||
|
|
58c0a6f0fd | ||
|
|
5974685866 | ||
|
|
7fae9b358d | ||
|
|
e14f529dac | ||
|
|
fe2f437642 | ||
|
|
90b5d303db | ||
|
|
9b863c1830 | ||
|
|
11fbbc51fa | ||
|
|
d3e84b747a | ||
|
|
2e606394b1 | ||
|
|
285112fc55 | ||
|
|
9f3f42d66a | ||
|
|
a0e8577b49 | ||
|
|
a6bff116f9 | ||
|
|
36052c4911 | ||
|
|
3d2a3bc755 | ||
|
|
ad9dc05663 | ||
|
|
ff075def5c | ||
|
|
4d7dfafbe7 | ||
|
|
3390db099a | ||
|
|
c6da881849 | ||
|
|
b61facb08b | ||
|
|
4a42843513 | ||
|
|
b433fb2857 | ||
|
|
2c0303c89e | ||
|
|
0bce534c8f | ||
|
|
6bef527f9d | ||
|
|
2d186da58a | ||
|
|
3736e00ae7 | ||
|
|
40f1548b32 | ||
|
|
446320b226 | ||
|
|
54e576c88a | ||
|
|
fe19f972e1 | ||
|
|
00dc45d0f9 | ||
|
|
4bb1c48f25 | ||
|
|
bd21c82a94 | ||
|
|
1b4623e713 | ||
|
|
a1f056cf2a | ||
|
|
4612a1cd87 | ||
|
|
07417bd03f | ||
|
|
7fa007e8bf | ||
|
|
ed78a76161 | ||
|
|
eda2f8948a | ||
|
|
16cbd3d72d | ||
|
|
86daf2f75c | ||
|
|
69c057ccb1 | ||
|
|
94a7a1ec00 | ||
|
|
5864e3fbd5 | ||
|
|
d2c4f4ab21 | ||
|
|
41321e4366 | ||
|
|
e6462c2ce3 | ||
|
|
1472f4bc61 | ||
|
|
a147500dee | ||
|
|
d1c48f1606 | ||
|
|
1b8394f71f | ||
|
|
4ecfdc4716 | ||
|
|
d9381598bc | ||
|
|
403be74861 | ||
|
|
1c61e28b32 | ||
|
|
c06e373beb | ||
|
|
7bca2910c7 | ||
|
|
2cf513e973 | ||
|
|
150c9fe536 | ||
|
|
6f7f0ab6c2 | ||
|
|
e4ffb7729a | ||
|
|
68069af969 | ||
|
|
d908ccc01c | ||
|
|
2b15e00106 | ||
|
|
127d7f2071 | ||
|
|
c47010e3d2 | ||
|
|
d4dd6aaed2 | ||
|
|
d3635b08da | ||
|
|
ebd6a7a46c | ||
|
|
e0dbc2913a | ||
|
|
1d89554f1b | ||
|
|
ace2ed7b87 | ||
|
|
956251b738 | ||
|
|
6f5f488a80 | ||
|
|
916d29e58f | ||
|
|
bffdc491b3 | ||
|
|
6719e56b5b | ||
|
|
c13e9bbabf | ||
|
|
e4acd6e2fd | ||
|
|
8a89ba9275 | ||
|
|
097a105603 | ||
|
|
306ce33e1c | ||
|
|
616f9cc593 | ||
|
|
2f0faf117e | ||
|
|
8710440951 | ||
|
|
8fdffdd573 | ||
|
|
3444f06f68 | ||
|
|
8f4d93a4b7 | ||
|
|
51b361b3bb | ||
|
|
7c99b38b7c | ||
|
|
b72a686830 | ||
|
|
e3058dd88b | ||
|
|
8ea7413a64 | ||
|
|
e90229a429 | ||
|
|
cf884a9815 | ||
|
|
ddf7753631 | ||
|
|
222eedf5f3 | ||
|
|
d0e543be26 | ||
|
|
8e6d0cba5f | ||
|
|
32d46dd9b8 | ||
|
|
e41bc6cbbf | ||
|
|
55b57fcba6 | ||
|
|
39491e3b75 | ||
|
|
68168e9eae | ||
|
|
6126ad801f | ||
|
|
43df1e707c | ||
|
|
b1f4601bf9 | ||
|
|
acb82c7f16 | ||
|
|
9ef3645cc7 | ||
|
|
5f11db695b | ||
|
|
2437215221 | ||
|
|
dd27b5c4a8 | ||
|
|
70131120ab | ||
|
|
6d86cd7224 | ||
|
|
75dab1ce5e | ||
|
|
e43934d60f | ||
|
|
75edc7cc8b | ||
|
|
5897695e8a | ||
|
|
a3a55357db | ||
|
|
084dc63b4c | ||
|
|
463343fb37 | ||
|
|
5879937f58 | ||
|
|
01190b3544 | ||
|
|
c00f688c64 | ||
|
|
51573da3a4 | ||
|
|
1191949e87 | ||
|
|
3d94ed9fa0 | ||
|
|
ede27f5780 | ||
|
|
dda869051d | ||
|
|
2320073e41 | ||
|
|
c587e63631 | ||
|
|
660b905e12 | ||
|
|
4f0bd557a4 | ||
|
|
736fe99fbf | ||
|
|
6fab4012a3 | ||
|
|
2f593ee67c | ||
|
|
20e535e142 | ||
|
|
4b780553e0 | ||
|
|
9be658f701 | ||
|
|
b8f0364a1c | ||
|
|
cbe92de2b5 | ||
|
|
eeb744dc8d | ||
|
|
d5501d3a90 | ||
|
|
3c423ccfe2 | ||
|
|
738d75d3eb | ||
|
|
a992fa74eb | ||
|
|
4466875d54 | ||
|
|
5c95892b83 | ||
|
|
639d03d900 | ||
|
|
d204bb57d0 | ||
|
|
c52cbd9de9 | ||
|
|
159a3bed9e | ||
|
|
25544dbec3 | ||
|
|
04bd1e3fc0 | ||
|
|
00e30a5fc4 | ||
|
|
55ec3cc6d5 | ||
|
|
9e2b4eeac0 | ||
|
|
c273a6c37c | ||
|
|
04a9ad6e10 | ||
|
|
4e26057f66 | ||
|
|
cce68d4e91 | ||
|
|
75b3391e3f | ||
|
|
231d4a6fda | ||
|
|
64054ee396 | ||
|
|
12e69ec896 | ||
|
|
8556ca3de5 | ||
|
|
9cd2d14005 | ||
|
|
4e2e615a7c | ||
|
|
12439e1249 | ||
|
|
d93c1c113b | ||
|
|
968f7591f8 | ||
|
|
5adcc6c7b4 |
@@ -1,6 +1,5 @@
|
|||||||
project(Eigen)
|
project(Eigen)
|
||||||
|
cmake_minimum_required(VERSION 2.8.5)
|
||||||
cmake_minimum_required(VERSION 2.8.2)
|
|
||||||
|
|
||||||
# guard against in-source builds
|
# guard against in-source builds
|
||||||
|
|
||||||
@@ -55,6 +54,7 @@ endif(EIGEN_HG_CHANGESET)
|
|||||||
|
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
@@ -288,25 +288,26 @@ option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF)
|
|||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# the user modifiable install path for header files
|
# Backward compatibility support for EIGEN_INCLUDE_INSTALL_DIR
|
||||||
set(EIGEN_INCLUDE_INSTALL_DIR ${EIGEN_INCLUDE_INSTALL_DIR} CACHE PATH "The directory where we install the header files (optional)")
|
if(EIGEN_INCLUDE_INSTALL_DIR AND NOT INCLUDE_INSTALL_DIR)
|
||||||
|
set(INCLUDE_INSTALL_DIR ${EIGEN_INCLUDE_INSTALL_DIR}
|
||||||
# set the internal install path for header files which depends on wether the user modifiable
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen header files are installed")
|
||||||
# EIGEN_INCLUDE_INSTALL_DIR has been set by the user or not.
|
|
||||||
if(EIGEN_INCLUDE_INSTALL_DIR)
|
|
||||||
set(INCLUDE_INSTALL_DIR
|
|
||||||
${EIGEN_INCLUDE_INSTALL_DIR}
|
|
||||||
CACHE INTERNAL
|
|
||||||
"The directory where we install the header files (internal)"
|
|
||||||
)
|
|
||||||
else()
|
else()
|
||||||
set(INCLUDE_INSTALL_DIR
|
set(INCLUDE_INSTALL_DIR
|
||||||
"${CMAKE_INSTALL_PREFIX}/include/eigen3"
|
"${CMAKE_INSTALL_INCLUDEDIR}/eigen3"
|
||||||
CACHE INTERNAL
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen header files are installed"
|
||||||
"The directory where we install the header files (internal)"
|
)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKEPACKAGE_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_LIBDIR}/cmake/eigen3"
|
||||||
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen3Config.cmake is installed"
|
||||||
|
)
|
||||||
|
set(PKGCONFIG_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_DATADIR}/pkgconfig"
|
||||||
|
CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where eigen3.pc is installed"
|
||||||
|
)
|
||||||
|
|
||||||
# similar to set_target_properties but append the property instead of overwriting it
|
# similar to set_target_properties but append the property instead of overwriting it
|
||||||
macro(ei_add_target_property target prop value)
|
macro(ei_add_target_property target prop value)
|
||||||
|
|
||||||
@@ -324,21 +325,9 @@ install(FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(EIGEN_BUILD_PKGCONFIG)
|
if(EIGEN_BUILD_PKGCONFIG)
|
||||||
SET(path_separator ":")
|
configure_file(eigen3.pc.in eigen3.pc @ONLY)
|
||||||
STRING(REPLACE ${path_separator} ";" pkg_config_libdir_search "$ENV{PKG_CONFIG_LIBDIR}")
|
|
||||||
message(STATUS "searching for 'pkgconfig' directory in PKG_CONFIG_LIBDIR ( $ENV{PKG_CONFIG_LIBDIR} ), ${CMAKE_INSTALL_PREFIX}/share, and ${CMAKE_INSTALL_PREFIX}/lib")
|
|
||||||
FIND_PATH(pkg_config_libdir pkgconfig ${pkg_config_libdir_search} ${CMAKE_INSTALL_PREFIX}/share ${CMAKE_INSTALL_PREFIX}/lib ${pkg_config_libdir_search})
|
|
||||||
if(pkg_config_libdir)
|
|
||||||
SET(pkg_config_install_dir ${pkg_config_libdir})
|
|
||||||
message(STATUS "found ${pkg_config_libdir}/pkgconfig" )
|
|
||||||
else(pkg_config_libdir)
|
|
||||||
SET(pkg_config_install_dir ${CMAKE_INSTALL_PREFIX}/share)
|
|
||||||
message(STATUS "pkgconfig not found; installing in ${pkg_config_install_dir}" )
|
|
||||||
endif(pkg_config_libdir)
|
|
||||||
|
|
||||||
configure_file(eigen3.pc.in eigen3.pc)
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen3.pc
|
||||||
DESTINATION ${pkg_config_install_dir}/pkgconfig
|
DESTINATION ${PKGCONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
endif(EIGEN_BUILD_PKGCONFIG)
|
endif(EIGEN_BUILD_PKGCONFIG)
|
||||||
|
|
||||||
@@ -401,12 +390,15 @@ if(cmake_generator_tolower MATCHES "makefile")
|
|||||||
message(STATUS "--------------+--------------------------------------------------------------")
|
message(STATUS "--------------+--------------------------------------------------------------")
|
||||||
message(STATUS "Command | Description")
|
message(STATUS "Command | Description")
|
||||||
message(STATUS "--------------+--------------------------------------------------------------")
|
message(STATUS "--------------+--------------------------------------------------------------")
|
||||||
message(STATUS "make install | Install to ${CMAKE_INSTALL_PREFIX}. To change that:")
|
message(STATUS "make install | Install Eigen. Headers will be installed to:")
|
||||||
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourpath")
|
message(STATUS " | <CMAKE_INSTALL_PREFIX>/<INCLUDE_INSTALL_DIR>")
|
||||||
message(STATUS " | Eigen headers will then be installed to:")
|
message(STATUS " | Using the following values:")
|
||||||
message(STATUS " | ${INCLUDE_INSTALL_DIR}")
|
message(STATUS " | CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
|
||||||
message(STATUS " | To install Eigen headers to a separate location, do:")
|
message(STATUS " | INCLUDE_INSTALL_DIR: ${INCLUDE_INSTALL_DIR}")
|
||||||
message(STATUS " | cmake . -DEIGEN_INCLUDE_INSTALL_DIR=yourpath")
|
message(STATUS " | Change the install location of Eigen headers using:")
|
||||||
|
message(STATUS " | cmake . -DCMAKE_INSTALL_PREFIX=yourprefix")
|
||||||
|
message(STATUS " | Or:")
|
||||||
|
message(STATUS " | cmake . -DINCLUDE_INSTALL_DIR=yourdir")
|
||||||
message(STATUS "make doc | Generate the API documentation, requires Doxygen & LaTeX")
|
message(STATUS "make doc | Generate the API documentation, requires Doxygen & LaTeX")
|
||||||
message(STATUS "make check | Build and run the unit-tests. Read this page:")
|
message(STATUS "make check | Build and run the unit-tests. Read this page:")
|
||||||
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
message(STATUS " | http://eigen.tuxfamily.org/index.php?title=Tests")
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ extern "C" {
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup CholmodSupport_Module CholmodSupport module
|
* \defgroup CholmodSupport_Module CholmodSupport module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
* It provides the two following main factorization classes:
|
* It provides the two following main factorization classes:
|
||||||
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
|
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
|
||||||
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
#undef bool
|
#undef bool
|
||||||
#undef vector
|
#undef vector
|
||||||
#undef pixel
|
#undef pixel
|
||||||
#elif defined __ARM_NEON__
|
#elif defined __ARM_NEON
|
||||||
#define EIGEN_VECTORIZE
|
#define EIGEN_VECTORIZE
|
||||||
#define EIGEN_VECTORIZE_NEON
|
#define EIGEN_VECTORIZE_NEON
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup SPQRSupport_Module SuiteSparseQR module
|
* \defgroup SPQRSupport_Module SuiteSparseQR module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
*
|
*
|
||||||
* \code
|
* \code
|
||||||
* #include <Eigen/SPQRSupport>
|
* #include <Eigen/SPQRSupport>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
/**
|
/**
|
||||||
* \defgroup SparseCore_Module SparseCore module
|
* \defgroup SparseCore_Module SparseCore module
|
||||||
*
|
*
|
||||||
* This module provides a sparse matrix representation, and basic associatd matrix manipulations
|
* This module provides a sparse matrix representation, and basic associated matrix manipulations
|
||||||
* and operations.
|
* and operations.
|
||||||
*
|
*
|
||||||
* See the \ref TutorialSparse "Sparse tutorial"
|
* See the \ref TutorialSparse "Sparse tutorial"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ extern "C" {
|
|||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup UmfPackSupport_Module UmfPackSupport module
|
* \defgroup UmfPackSupport_Module UmfPackSupport module
|
||||||
*
|
*
|
||||||
* This module provides an interface to the UmfPack library which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
|
* This module provides an interface to the UmfPack library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||||
* It provides the following factorization class:
|
* It provides the following factorization class:
|
||||||
* - class UmfPackLU: a multifrontal sequential LU factorization.
|
* - class UmfPackLU: a multifrontal sequential LU factorization.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -235,6 +235,11 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
|
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
|
||||||
@@ -434,6 +439,8 @@ template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
|
|||||||
template<typename MatrixType, int _UpLo>
|
template<typename MatrixType, int _UpLo>
|
||||||
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
eigen_assert(a.rows()==a.cols());
|
eigen_assert(a.rows()==a.cols());
|
||||||
const Index size = a.rows();
|
const Index size = a.rows();
|
||||||
|
|
||||||
@@ -457,7 +464,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
|||||||
*/
|
*/
|
||||||
template<typename MatrixType, int _UpLo>
|
template<typename MatrixType, int _UpLo>
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma)
|
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename LDLT<MatrixType,_UpLo>::RealScalar& sigma)
|
||||||
{
|
{
|
||||||
const Index size = w.rows();
|
const Index size = w.rows();
|
||||||
if (m_isInitialized)
|
if (m_isInitialized)
|
||||||
|
|||||||
@@ -174,6 +174,12 @@ template<typename _MatrixType, int _UpLo> class LLT
|
|||||||
LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
|
LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* Used to compute and store L
|
* Used to compute and store L
|
||||||
* The strict upper part is not used and even not initialized.
|
* The strict upper part is not used and even not initialized.
|
||||||
@@ -283,7 +289,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
|
|||||||
return k;
|
return k;
|
||||||
mat.coeffRef(k,k) = x = sqrt(x);
|
mat.coeffRef(k,k) = x = sqrt(x);
|
||||||
if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint();
|
if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint();
|
||||||
if (rs>0) A21 *= RealScalar(1)/x;
|
if (rs>0) A21 /= x;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -384,6 +390,8 @@ template<typename MatrixType> struct LLT_Traits<MatrixType,Upper>
|
|||||||
template<typename MatrixType, int _UpLo>
|
template<typename MatrixType, int _UpLo>
|
||||||
LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
eigen_assert(a.rows()==a.cols());
|
eigen_assert(a.rows()==a.cols());
|
||||||
const Index size = a.rows();
|
const Index size = a.rows();
|
||||||
m_matrix.resize(size, size);
|
m_matrix.resize(size, size);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ template<> struct mkl_llt<EIGTYPE> \
|
|||||||
lda = m.outerStride(); \
|
lda = m.outerStride(); \
|
||||||
\
|
\
|
||||||
info = LAPACKE_##MKLPREFIX##potrf( matrix_order, uplo, size, (MKLTYPE*)a, lda ); \
|
info = LAPACKE_##MKLPREFIX##potrf( matrix_order, uplo, size, (MKLTYPE*)a, lda ); \
|
||||||
info = (info==0) ? Success : NumericalIssue; \
|
info = (info==0) ? -1 : info>0 ? info-1 : size; \
|
||||||
return info; \
|
return info; \
|
||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
|
|||||||
{
|
{
|
||||||
res.itype = CHOLMOD_INT;
|
res.itype = CHOLMOD_INT;
|
||||||
}
|
}
|
||||||
else if (internal::is_same<_Index,UF_long>::value)
|
else if (internal::is_same<_Index,SuiteSparse_long>::value)
|
||||||
{
|
{
|
||||||
res.itype = CHOLMOD_LONG;
|
res.itype = CHOLMOD_LONG;
|
||||||
}
|
}
|
||||||
@@ -395,7 +395,7 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
|
|||||||
CholmodSimplicialLLT(const MatrixType& matrix) : Base()
|
CholmodSimplicialLLT(const MatrixType& matrix) : Base()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(matrix);
|
Base::compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CholmodSimplicialLLT() {}
|
~CholmodSimplicialLLT() {}
|
||||||
@@ -442,7 +442,7 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
|
|||||||
CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
|
CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(matrix);
|
Base::compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CholmodSimplicialLDLT() {}
|
~CholmodSimplicialLDLT() {}
|
||||||
@@ -487,7 +487,7 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
|
|||||||
CholmodSupernodalLLT(const MatrixType& matrix) : Base()
|
CholmodSupernodalLLT(const MatrixType& matrix) : Base()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(matrix);
|
Base::compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CholmodSupernodalLLT() {}
|
~CholmodSupernodalLLT() {}
|
||||||
@@ -534,7 +534,7 @@ class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecom
|
|||||||
CholmodDecomposition(const MatrixType& matrix) : Base()
|
CholmodDecomposition(const MatrixType& matrix) : Base()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(matrix);
|
Base::compute(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CholmodDecomposition() {}
|
~CholmodDecomposition() {}
|
||||||
|
|||||||
@@ -124,6 +124,21 @@ class Array
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
|
Array(Array&& other)
|
||||||
|
: Base(std::move(other))
|
||||||
|
{
|
||||||
|
Base::_check_template_params();
|
||||||
|
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
|
||||||
|
Base::_set_noalias(other);
|
||||||
|
}
|
||||||
|
Array& operator=(Array&& other)
|
||||||
|
{
|
||||||
|
other.swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
|
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
|
||||||
*
|
*
|
||||||
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
|
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ template<typename Derived> class ArrayBase
|
|||||||
|
|
||||||
typedef ArrayBase Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl;
|
typedef ArrayBase Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl;
|
||||||
|
|
||||||
using internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
|
|
||||||
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>::operator*;
|
|
||||||
|
|
||||||
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
||||||
typedef typename internal::traits<Derived>::Index Index;
|
typedef typename internal::traits<Derived>::Index Index;
|
||||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||||
@@ -56,6 +53,7 @@ template<typename Derived> class ArrayBase
|
|||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
|
||||||
typedef DenseBase<Derived> Base;
|
typedef DenseBase<Derived> Base;
|
||||||
|
using Base::operator*;
|
||||||
using Base::RowsAtCompileTime;
|
using Base::RowsAtCompileTime;
|
||||||
using Base::ColsAtCompileTime;
|
using Base::ColsAtCompileTime;
|
||||||
using Base::SizeAtCompileTime;
|
using Base::SizeAtCompileTime;
|
||||||
|
|||||||
@@ -439,19 +439,26 @@ struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling, Ve
|
|||||||
typedef typename Derived1::Index Index;
|
typedef typename Derived1::Index Index;
|
||||||
static inline void run(Derived1 &dst, const Derived2 &src)
|
static inline void run(Derived1 &dst, const Derived2 &src)
|
||||||
{
|
{
|
||||||
typedef packet_traits<typename Derived1::Scalar> PacketTraits;
|
typedef typename Derived1::Scalar Scalar;
|
||||||
|
typedef packet_traits<Scalar> PacketTraits;
|
||||||
enum {
|
enum {
|
||||||
packetSize = PacketTraits::size,
|
packetSize = PacketTraits::size,
|
||||||
alignable = PacketTraits::AlignedOnScalar,
|
alignable = PacketTraits::AlignedOnScalar,
|
||||||
dstAlignment = alignable ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
|
dstIsAligned = assign_traits<Derived1,Derived2>::DstIsAligned,
|
||||||
|
dstAlignment = alignable ? Aligned : int(dstIsAligned),
|
||||||
srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
|
srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
|
||||||
};
|
};
|
||||||
|
const Scalar *dst_ptr = &dst.coeffRef(0,0);
|
||||||
|
if((!bool(dstIsAligned)) && (size_t(dst_ptr) % sizeof(Scalar))>0)
|
||||||
|
{
|
||||||
|
// the pointer is not aligend-on scalar, so alignment is not possible
|
||||||
|
return assign_impl<Derived1,Derived2,DefaultTraversal,NoUnrolling>::run(dst, src);
|
||||||
|
}
|
||||||
const Index packetAlignedMask = packetSize - 1;
|
const Index packetAlignedMask = packetSize - 1;
|
||||||
const Index innerSize = dst.innerSize();
|
const Index innerSize = dst.innerSize();
|
||||||
const Index outerSize = dst.outerSize();
|
const Index outerSize = dst.outerSize();
|
||||||
const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
|
const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
|
||||||
Index alignedStart = ((!alignable) || assign_traits<Derived1,Derived2>::DstIsAligned) ? 0
|
Index alignedStart = ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned(dst_ptr, innerSize);
|
||||||
: internal::first_aligned(&dst.coeffRef(0,0), innerSize);
|
|
||||||
|
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
for(Index outer = 0; outer < outerSize; ++outer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,8 +66,9 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
|||||||
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
|
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
|
||||||
: int(traits<XprType>::MaxColsAtCompileTime),
|
: int(traits<XprType>::MaxColsAtCompileTime),
|
||||||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
||||||
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
IsDense = is_same<StorageKind,Dense>::value,
|
||||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
IsRowMajor = (IsDense&&MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||||
|
: (IsDense&&MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||||
: XprTypeIsRowMajor,
|
: XprTypeIsRowMajor,
|
||||||
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
||||||
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
||||||
|
|||||||
@@ -76,8 +76,11 @@ struct CommaInitializer
|
|||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
if(other.cols()==0 || other.rows()==0)
|
if(other.rows()==0)
|
||||||
|
{
|
||||||
|
m_col += other.cols();
|
||||||
return *this;
|
return *this;
|
||||||
|
}
|
||||||
if (m_col==m_xpr.cols())
|
if (m_col==m_xpr.cols())
|
||||||
{
|
{
|
||||||
m_row+=m_currentBlockRows;
|
m_row+=m_currentBlockRows;
|
||||||
@@ -86,7 +89,7 @@ struct CommaInitializer
|
|||||||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
|
||||||
&& "Too many rows passed to comma initializer (operator<<)");
|
&& "Too many rows passed to comma initializer (operator<<)");
|
||||||
}
|
}
|
||||||
eigen_assert(m_col<m_xpr.cols()
|
eigen_assert((m_col<m_xpr.cols() || (m_xpr.cols()==0 && m_col==0))
|
||||||
&& "Too many coefficients passed to comma initializer (operator<<)");
|
&& "Too many coefficients passed to comma initializer (operator<<)");
|
||||||
eigen_assert(m_currentBlockRows==other.rows());
|
eigen_assert(m_currentBlockRows==other.rows());
|
||||||
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
if (OtherDerived::SizeAtCompileTime != Dynamic)
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
|
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
|
||||||
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
|
Cost0 = EIGEN_ADD_COST(LhsCoeffReadCost,RhsCoeffReadCost),
|
||||||
|
CoeffReadCost = EIGEN_ADD_COST(Cost0,functor_traits<BinaryOp>::Cost)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ struct traits<CwiseUnaryOp<UnaryOp, XprType> >
|
|||||||
Flags = _XprTypeNested::Flags & (
|
Flags = _XprTypeNested::Flags & (
|
||||||
HereditaryBits | LinearAccessBit | AlignedBit
|
HereditaryBits | LinearAccessBit | AlignedBit
|
||||||
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
|
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
|
||||||
CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits<UnaryOp>::Cost
|
CoeffReadCost = EIGEN_ADD_COST(_XprTypeNested::CoeffReadCost, functor_traits<UnaryOp>::Cost)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct traits<CwiseUnaryView<ViewOp, MatrixType> >
|
|||||||
typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
|
typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
|
||||||
enum {
|
enum {
|
||||||
Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
|
Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
|
||||||
CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits<ViewOp>::Cost,
|
CoeffReadCost = EIGEN_ADD_COST(traits<_MatrixTypeNested>::CoeffReadCost, functor_traits<ViewOp>::Cost),
|
||||||
MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
|
MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
|
||||||
// need to cast the sizeof's from size_t to int explicitly, otherwise:
|
// need to cast the sizeof's from size_t to int explicitly, otherwise:
|
||||||
// "error: no integral type can represent all of the enumerator values
|
// "error: no integral type can represent all of the enumerator values
|
||||||
|
|||||||
@@ -40,15 +40,14 @@ static inline void check_DenseIndex_is_signed() {
|
|||||||
*/
|
*/
|
||||||
template<typename Derived> class DenseBase
|
template<typename Derived> class DenseBase
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
: public internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
|
: public internal::special_scalar_op_base<Derived, typename internal::traits<Derived>::Scalar,
|
||||||
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>
|
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real,
|
||||||
|
DenseCoeffsBase<Derived> >
|
||||||
#else
|
#else
|
||||||
: public DenseCoeffsBase<Derived>
|
: public DenseCoeffsBase<Derived>
|
||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar,
|
|
||||||
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>::operator*;
|
|
||||||
|
|
||||||
class InnerIterator;
|
class InnerIterator;
|
||||||
|
|
||||||
@@ -63,8 +62,9 @@ template<typename Derived> class DenseBase
|
|||||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||||
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
|
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
typedef internal::special_scalar_op_base<Derived,Scalar,RealScalar, DenseCoeffsBase<Derived> > Base;
|
||||||
|
|
||||||
typedef DenseCoeffsBase<Derived> Base;
|
using Base::operator*;
|
||||||
using Base::derived;
|
using Base::derived;
|
||||||
using Base::const_cast_derived;
|
using Base::const_cast_derived;
|
||||||
using Base::rows;
|
using Base::rows;
|
||||||
@@ -183,10 +183,6 @@ template<typename Derived> class DenseBase
|
|||||||
/** \returns the number of nonzero coefficients which is in practice the number
|
/** \returns the number of nonzero coefficients which is in practice the number
|
||||||
* of stored coefficients. */
|
* of stored coefficients. */
|
||||||
inline Index nonZeros() const { return size(); }
|
inline Index nonZeros() const { return size(); }
|
||||||
/** \returns true if either the number of rows or the number of columns is equal to 1.
|
|
||||||
* In other words, this function returns
|
|
||||||
* \code rows()==1 || cols()==1 \endcode
|
|
||||||
* \sa rows(), cols(), IsVectorAtCompileTime. */
|
|
||||||
|
|
||||||
/** \returns the outer size.
|
/** \returns the outer size.
|
||||||
*
|
*
|
||||||
@@ -266,11 +262,13 @@ template<typename Derived> class DenseBase
|
|||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Derived& operator=(const ReturnByValue<OtherDerived>& func);
|
Derived& operator=(const ReturnByValue<OtherDerived>& func);
|
||||||
|
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
/** \internal Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Derived& lazyAssign(const DenseBase<OtherDerived>& other);
|
Derived& lazyAssign(const DenseBase<OtherDerived>& other);
|
||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
|
||||||
|
/** \internal Evaluates \a other into *this. \returns a reference to *this. */
|
||||||
|
template<typename OtherDerived>
|
||||||
|
Derived& lazyAssign(const ReturnByValue<OtherDerived>& other);
|
||||||
|
|
||||||
CommaInitializer<Derived> operator<< (const Scalar& s);
|
CommaInitializer<Derived> operator<< (const Scalar& s);
|
||||||
|
|
||||||
|
|||||||
@@ -122,33 +122,41 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
|||||||
{
|
{
|
||||||
internal::plain_array<T,Size,_Options> m_data;
|
internal::plain_array<T,Size,_Options> m_data;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() {}
|
DenseStorage() {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||||
: m_data(internal::constructor_without_unaligned_array_assert()) {}
|
: m_data(internal::constructor_without_unaligned_array_assert()) {}
|
||||||
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {}
|
||||||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
static inline DenseIndex rows(void) {return _Rows;}
|
{
|
||||||
static inline DenseIndex cols(void) {return _Cols;}
|
if (this != &other) m_data = other.m_data;
|
||||||
inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
|
return *this;
|
||||||
inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
|
}
|
||||||
inline const T *data() const { return m_data.array; }
|
DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
inline T *data() { return m_data.array; }
|
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
|
||||||
|
static DenseIndex rows(void) {return _Rows;}
|
||||||
|
static DenseIndex cols(void) {return _Cols;}
|
||||||
|
void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
|
void resize(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
|
const T *data() const { return m_data.array; }
|
||||||
|
T *data() { return m_data.array; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// null matrix
|
// null matrix
|
||||||
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
|
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() {}
|
DenseStorage() {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
|
DenseStorage(internal::constructor_without_unaligned_array_assert) {}
|
||||||
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
DenseStorage(const DenseStorage&) {}
|
||||||
inline void swap(DenseStorage& ) {}
|
DenseStorage& operator=(const DenseStorage&) { return *this; }
|
||||||
static inline DenseIndex rows(void) {return _Rows;}
|
DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
static inline DenseIndex cols(void) {return _Cols;}
|
void swap(DenseStorage& ) {}
|
||||||
inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
|
static DenseIndex rows(void) {return _Rows;}
|
||||||
inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
|
static DenseIndex cols(void) {return _Cols;}
|
||||||
inline const T *data() const { return 0; }
|
void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
inline T *data() { return 0; }
|
void resize(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
|
const T *data() const { return 0; }
|
||||||
|
T *data() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// more specializations for null matrices; these are necessary to resolve ambiguities
|
// more specializations for null matrices; these are necessary to resolve ambiguities
|
||||||
@@ -168,18 +176,29 @@ template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic
|
|||||||
DenseIndex m_rows;
|
DenseIndex m_rows;
|
||||||
DenseIndex m_cols;
|
DenseIndex m_cols;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_rows(0), m_cols(0) {}
|
DenseStorage() : m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
|
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
|
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
|
||||||
inline void swap(DenseStorage& other)
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
m_data = other.m_data;
|
||||||
|
m_rows = other.m_rows;
|
||||||
|
m_cols = other.m_cols;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
|
||||||
|
void swap(DenseStorage& other)
|
||||||
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
|
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
|
||||||
inline DenseIndex rows() const {return m_rows;}
|
DenseIndex rows() const {return m_rows;}
|
||||||
inline DenseIndex cols() const {return m_cols;}
|
DenseIndex cols() const {return m_cols;}
|
||||||
inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
|
void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
|
||||||
inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
|
void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
|
||||||
inline const T *data() const { return m_data.array; }
|
const T *data() const { return m_data.array; }
|
||||||
inline T *data() { return m_data.array; }
|
T *data() { return m_data.array; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// dynamic-size matrix with fixed-size storage and fixed width
|
// dynamic-size matrix with fixed-size storage and fixed width
|
||||||
@@ -188,17 +207,27 @@ template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Si
|
|||||||
internal::plain_array<T,Size,_Options> m_data;
|
internal::plain_array<T,Size,_Options> m_data;
|
||||||
DenseIndex m_rows;
|
DenseIndex m_rows;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_rows(0) {}
|
DenseStorage() : m_rows(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
|
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
|
||||||
inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
|
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
|
||||||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
inline DenseIndex rows(void) const {return m_rows;}
|
{
|
||||||
inline DenseIndex cols(void) const {return _Cols;}
|
if (this != &other)
|
||||||
inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
|
{
|
||||||
inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
|
m_data = other.m_data;
|
||||||
inline const T *data() const { return m_data.array; }
|
m_rows = other.m_rows;
|
||||||
inline T *data() { return m_data.array; }
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
|
||||||
|
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||||
|
DenseIndex rows(void) const {return m_rows;}
|
||||||
|
DenseIndex cols(void) const {return _Cols;}
|
||||||
|
void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
|
||||||
|
void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
|
||||||
|
const T *data() const { return m_data.array; }
|
||||||
|
T *data() { return m_data.array; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// dynamic-size matrix with fixed-size storage and fixed height
|
// dynamic-size matrix with fixed-size storage and fixed height
|
||||||
@@ -207,17 +236,27 @@ template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Si
|
|||||||
internal::plain_array<T,Size,_Options> m_data;
|
internal::plain_array<T,Size,_Options> m_data;
|
||||||
DenseIndex m_cols;
|
DenseIndex m_cols;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_cols(0) {}
|
DenseStorage() : m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
|
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
|
||||||
inline DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
|
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
|
||||||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
inline DenseIndex rows(void) const {return _Rows;}
|
{
|
||||||
inline DenseIndex cols(void) const {return m_cols;}
|
if (this != &other)
|
||||||
inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
|
{
|
||||||
inline void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
|
m_data = other.m_data;
|
||||||
inline const T *data() const { return m_data.array; }
|
m_cols = other.m_cols;
|
||||||
inline T *data() { return m_data.array; }
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
|
||||||
|
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||||
|
DenseIndex rows(void) const {return _Rows;}
|
||||||
|
DenseIndex cols(void) const {return m_cols;}
|
||||||
|
void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
|
||||||
|
void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
|
||||||
|
const T *data() const { return m_data.array; }
|
||||||
|
T *data() { return m_data.array; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// purely dynamic matrix.
|
// purely dynamic matrix.
|
||||||
@@ -227,18 +266,35 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
|||||||
DenseIndex m_rows;
|
DenseIndex m_rows;
|
||||||
DenseIndex m_cols;
|
DenseIndex m_cols;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
|
DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||||
: m_data(0), m_rows(0), m_cols(0) {}
|
: m_data(0), m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
|
DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
|
||||||
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
|
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
|
||||||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
||||||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
inline void swap(DenseStorage& other)
|
DenseStorage(DenseStorage&& other)
|
||||||
|
: m_data(std::move(other.m_data))
|
||||||
|
, m_rows(std::move(other.m_rows))
|
||||||
|
, m_cols(std::move(other.m_cols))
|
||||||
|
{
|
||||||
|
other.m_data = nullptr;
|
||||||
|
}
|
||||||
|
DenseStorage& operator=(DenseStorage&& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(m_data, other.m_data);
|
||||||
|
swap(m_rows, other.m_rows);
|
||||||
|
swap(m_cols, other.m_cols);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
|
||||||
|
void swap(DenseStorage& other)
|
||||||
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
|
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
|
||||||
inline DenseIndex rows(void) const {return m_rows;}
|
DenseIndex rows(void) const {return m_rows;}
|
||||||
inline DenseIndex cols(void) const {return m_cols;}
|
DenseIndex cols(void) const {return m_cols;}
|
||||||
inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
|
void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
|
||||||
{
|
{
|
||||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
|
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
|
||||||
m_rows = nbRows;
|
m_rows = nbRows;
|
||||||
@@ -258,8 +314,11 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
|||||||
m_rows = nbRows;
|
m_rows = nbRows;
|
||||||
m_cols = nbCols;
|
m_cols = nbCols;
|
||||||
}
|
}
|
||||||
inline const T *data() const { return m_data; }
|
const T *data() const { return m_data; }
|
||||||
inline T *data() { return m_data; }
|
T *data() { return m_data; }
|
||||||
|
private:
|
||||||
|
DenseStorage(const DenseStorage&);
|
||||||
|
DenseStorage& operator=(const DenseStorage&);
|
||||||
};
|
};
|
||||||
|
|
||||||
// matrix with dynamic width and fixed height (so that matrix has dynamic size).
|
// matrix with dynamic width and fixed height (so that matrix has dynamic size).
|
||||||
@@ -268,15 +327,30 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
|||||||
T *m_data;
|
T *m_data;
|
||||||
DenseIndex m_cols;
|
DenseIndex m_cols;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_data(0), m_cols(0) {}
|
DenseStorage() : m_data(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
|
DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
|
||||||
inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
|
DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
|
||||||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
||||||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
DenseStorage(DenseStorage&& other)
|
||||||
static inline DenseIndex rows(void) {return _Rows;}
|
: m_data(std::move(other.m_data))
|
||||||
inline DenseIndex cols(void) const {return m_cols;}
|
, m_cols(std::move(other.m_cols))
|
||||||
inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
|
{
|
||||||
|
other.m_data = nullptr;
|
||||||
|
}
|
||||||
|
DenseStorage& operator=(DenseStorage&& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(m_data, other.m_data);
|
||||||
|
swap(m_cols, other.m_cols);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
|
||||||
|
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||||
|
static DenseIndex rows(void) {return _Rows;}
|
||||||
|
DenseIndex cols(void) const {return m_cols;}
|
||||||
|
void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
|
||||||
{
|
{
|
||||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
|
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
|
||||||
m_cols = nbCols;
|
m_cols = nbCols;
|
||||||
@@ -294,8 +368,11 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
|||||||
}
|
}
|
||||||
m_cols = nbCols;
|
m_cols = nbCols;
|
||||||
}
|
}
|
||||||
inline const T *data() const { return m_data; }
|
const T *data() const { return m_data; }
|
||||||
inline T *data() { return m_data; }
|
T *data() { return m_data; }
|
||||||
|
private:
|
||||||
|
DenseStorage(const DenseStorage&);
|
||||||
|
DenseStorage& operator=(const DenseStorage&);
|
||||||
};
|
};
|
||||||
|
|
||||||
// matrix with dynamic height and fixed width (so that matrix has dynamic size).
|
// matrix with dynamic height and fixed width (so that matrix has dynamic size).
|
||||||
@@ -304,15 +381,30 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
|||||||
T *m_data;
|
T *m_data;
|
||||||
DenseIndex m_rows;
|
DenseIndex m_rows;
|
||||||
public:
|
public:
|
||||||
inline DenseStorage() : m_data(0), m_rows(0) {}
|
DenseStorage() : m_data(0), m_rows(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
|
DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
|
||||||
inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
|
DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
|
||||||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
|
||||||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
DenseStorage(DenseStorage&& other)
|
||||||
inline DenseIndex rows(void) const {return m_rows;}
|
: m_data(std::move(other.m_data))
|
||||||
static inline DenseIndex cols(void) {return _Cols;}
|
, m_rows(std::move(other.m_rows))
|
||||||
inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
|
{
|
||||||
|
other.m_data = nullptr;
|
||||||
|
}
|
||||||
|
DenseStorage& operator=(DenseStorage&& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(m_data, other.m_data);
|
||||||
|
swap(m_rows, other.m_rows);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
|
||||||
|
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||||
|
DenseIndex rows(void) const {return m_rows;}
|
||||||
|
static DenseIndex cols(void) {return _Cols;}
|
||||||
|
void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
|
||||||
{
|
{
|
||||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
|
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
|
||||||
m_rows = nbRows;
|
m_rows = nbRows;
|
||||||
@@ -330,8 +422,11 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
|||||||
}
|
}
|
||||||
m_rows = nbRows;
|
m_rows = nbRows;
|
||||||
}
|
}
|
||||||
inline const T *data() const { return m_data; }
|
const T *data() const { return m_data; }
|
||||||
inline T *data() { return m_data; }
|
T *data() { return m_data; }
|
||||||
|
private:
|
||||||
|
DenseStorage(const DenseStorage&);
|
||||||
|
DenseStorage& operator=(const DenseStorage&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ class DiagonalBase : public EigenBase<Derived>
|
|||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void evalTo(MatrixBase<DenseDerived> &other) const;
|
void evalTo(MatrixBase<DenseDerived> &other) const;
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void addTo(MatrixBase<DenseDerived> &other) const
|
inline void addTo(MatrixBase<DenseDerived> &other) const
|
||||||
{ other.diagonal() += diagonal(); }
|
{ other.diagonal() += diagonal(); }
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void subTo(MatrixBase<DenseDerived> &other) const
|
inline void subTo(MatrixBase<DenseDerived> &other) const
|
||||||
{ other.diagonal() -= diagonal(); }
|
{ other.diagonal() -= diagonal(); }
|
||||||
|
|
||||||
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
||||||
@@ -98,7 +98,7 @@ class DiagonalBase : public EigenBase<Derived>
|
|||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename DenseDerived>
|
template<typename DenseDerived>
|
||||||
void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
|
inline void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
|
||||||
{
|
{
|
||||||
other.setZero();
|
other.setZero();
|
||||||
other.diagonal() = diagonal();
|
other.diagonal() = diagonal();
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
|
|||||||
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
|
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
|
||||||
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
|
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
|
||||||
|
|
||||||
Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
|
Flags = ((HereditaryBits|_LinearAccessMask|AlignedBit) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
|
||||||
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
|
Cost0 = EIGEN_ADD_COST(NumTraits<Scalar>::MulCost, MatrixType::CoeffReadCost),
|
||||||
|
CoeffReadCost = EIGEN_ADD_COST(Cost0,DiagonalType::DiagonalVectorType::CoeffReadCost)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ struct dot_nocheck<T, U, true>
|
|||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
inline typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
||||||
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||||
|
|||||||
@@ -259,6 +259,47 @@ template<> struct functor_traits<scalar_boolean_or_op> {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \internal
|
||||||
|
* \brief Template functors for comparison of two scalars
|
||||||
|
* \todo Implement packet-comparisons
|
||||||
|
*/
|
||||||
|
template<typename Scalar, ComparisonName cmp> struct scalar_cmp_op;
|
||||||
|
|
||||||
|
template<typename Scalar, ComparisonName cmp>
|
||||||
|
struct functor_traits<scalar_cmp_op<Scalar, cmp> > {
|
||||||
|
enum {
|
||||||
|
Cost = NumTraits<Scalar>::AddCost,
|
||||||
|
PacketAccess = false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<ComparisonName Cmp, typename Scalar>
|
||||||
|
struct result_of<scalar_cmp_op<Scalar, Cmp>(Scalar,Scalar)> {
|
||||||
|
typedef bool type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_EQ> {
|
||||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
|
||||||
|
EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a==b;}
|
||||||
|
};
|
||||||
|
template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LT> {
|
||||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
|
||||||
|
EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<b;}
|
||||||
|
};
|
||||||
|
template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LE> {
|
||||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
|
||||||
|
EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<=b;}
|
||||||
|
};
|
||||||
|
template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_UNORD> {
|
||||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
|
||||||
|
EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return !(a<=b || b<=a);}
|
||||||
|
};
|
||||||
|
template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_NEQ> {
|
||||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
|
||||||
|
EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a!=b;}
|
||||||
|
};
|
||||||
|
|
||||||
// unary functors:
|
// unary functors:
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
|
|||||||
@@ -205,9 +205,6 @@ class GeneralProduct<Lhs, Rhs, InnerProduct>
|
|||||||
public:
|
public:
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
|
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
|
||||||
|
|
||||||
Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
|
Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,15 +254,13 @@ template<typename Lhs, typename Rhs>
|
|||||||
class GeneralProduct<Lhs, Rhs, OuterProduct>
|
class GeneralProduct<Lhs, Rhs, OuterProduct>
|
||||||
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
|
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
|
||||||
{
|
{
|
||||||
template<typename T> struct IsRowMajor : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
|
template<typename T> struct is_row_major : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
|
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
|
||||||
|
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
|
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
||||||
@@ -281,22 +276,22 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
|
|||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void evalTo(Dest& dest) const {
|
inline void evalTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, set(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, set(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void addTo(Dest& dest) const {
|
inline void addTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, add(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, add(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest>
|
template<typename Dest>
|
||||||
inline void subTo(Dest& dest) const {
|
inline void subTo(Dest& dest) const {
|
||||||
internal::outer_product_selector_run(*this, dest, sub(), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, sub(), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
|
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
|
||||||
{
|
{
|
||||||
internal::outer_product_selector_run(*this, dest, adds(alpha), IsRowMajor<Dest>());
|
internal::outer_product_selector_run(*this, dest, adds(alpha), is_row_major<Dest>());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -425,15 +420,18 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
|||||||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
|
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
|
||||||
* RhsBlasTraits::extractScalarFactor(prod.rhs());
|
* RhsBlasTraits::extractScalarFactor(prod.rhs());
|
||||||
|
|
||||||
|
// make sure Dest is a compile-time vector type (bug 1166)
|
||||||
|
typedef typename conditional<Dest::IsVectorAtCompileTime, Dest, typename Dest::ColXpr>::type ActualDest;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
|
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
|
||||||
// on, the other hand it is good for the cache to pack the vector anyways...
|
// on, the other hand it is good for the cache to pack the vector anyways...
|
||||||
EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
|
EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
|
||||||
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
|
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
|
||||||
MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
|
MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal
|
||||||
};
|
};
|
||||||
|
|
||||||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
||||||
|
|
||||||
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
||||||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
||||||
@@ -522,7 +520,7 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
|
|||||||
actualLhs.rows(), actualLhs.cols(),
|
actualLhs.rows(), actualLhs.cols(),
|
||||||
actualLhs.data(), actualLhs.outerStride(),
|
actualLhs.data(), actualLhs.outerStride(),
|
||||||
actualRhsPtr, 1,
|
actualRhsPtr, 1,
|
||||||
dest.data(), dest.innerStride(),
|
dest.data(), dest.col(0).innerStride(), //NOTE if dest is not a vector at compile-time, then dest.innerStride() might be wrong. (bug 1166)
|
||||||
actualAlpha);
|
actualAlpha);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
|
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
|
explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||||
checkSanity();
|
checkSanity();
|
||||||
@@ -149,6 +149,10 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
checkSanity();
|
checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EIGEN_MAPBASE_PLUGIN
|
||||||
|
#include EIGEN_MAPBASE_PLUGIN
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void checkSanity() const
|
void checkSanity() const
|
||||||
@@ -157,7 +161,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
internal::inner_stride_at_compile_time<Derived>::ret==1),
|
internal::inner_stride_at_compile_time<Derived>::ret==1),
|
||||||
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
|
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
|
||||||
eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0)
|
eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0)
|
||||||
&& "data is not aligned");
|
&& "input pointer is not aligned on a 16 byte boundary");
|
||||||
}
|
}
|
||||||
|
|
||||||
PointerType m_data;
|
PointerType m_data;
|
||||||
@@ -168,6 +172,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
|||||||
template<typename Derived> class MapBase<Derived, WriteAccessors>
|
template<typename Derived> class MapBase<Derived, WriteAccessors>
|
||||||
: public MapBase<Derived, ReadOnlyAccessors>
|
: public MapBase<Derived, ReadOnlyAccessors>
|
||||||
{
|
{
|
||||||
|
typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef MapBase<Derived, ReadOnlyAccessors> Base;
|
typedef MapBase<Derived, ReadOnlyAccessors> Base;
|
||||||
@@ -230,15 +235,13 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
|
|||||||
|
|
||||||
Derived& operator=(const MapBase& other)
|
Derived& operator=(const MapBase& other)
|
||||||
{
|
{
|
||||||
Base::Base::operator=(other);
|
ReadOnlyMapBase::Base::operator=(other);
|
||||||
return derived();
|
return derived();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In theory MapBase<Derived, ReadOnlyAccessors> should not make a using Base::operator=,
|
// In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
|
||||||
// and thus we should directly do: using Base::Base::operator=;
|
// see bugs 821 and 920.
|
||||||
// However, this would confuse recent MSVC 2013 (bug 821), and since MapBase<Derived, ReadOnlyAccessors>
|
using ReadOnlyMapBase::Base::operator=;
|
||||||
// has operator= to make ICC 11 happy, we can also make MSVC 2013 happy as follow:
|
|
||||||
using Base::operator=;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
|
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
|
||||||
|
|||||||
@@ -218,8 +218,8 @@ struct conj_retval
|
|||||||
* Implementation of abs2 *
|
* Implementation of abs2 *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar,bool IsComplex>
|
||||||
struct abs2_impl
|
struct abs2_impl_default
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const Scalar& x)
|
static inline RealScalar run(const Scalar& x)
|
||||||
@@ -228,15 +228,26 @@ struct abs2_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar>
|
template<typename Scalar>
|
||||||
struct abs2_impl<std::complex<RealScalar> >
|
struct abs2_impl_default<Scalar, true> // IsComplex
|
||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
return real(x)*real(x) + imag(x)*imag(x);
|
return real(x)*real(x) + imag(x)*imag(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
struct abs2_impl
|
||||||
|
{
|
||||||
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
|
{
|
||||||
|
return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct abs2_retval
|
struct abs2_retval
|
||||||
{
|
{
|
||||||
@@ -294,7 +305,7 @@ struct hypot_impl
|
|||||||
RealScalar _x = abs(x);
|
RealScalar _x = abs(x);
|
||||||
RealScalar _y = abs(y);
|
RealScalar _y = abs(y);
|
||||||
RealScalar p = (max)(_x, _y);
|
RealScalar p = (max)(_x, _y);
|
||||||
if(p==RealScalar(0)) return 0;
|
if(p==RealScalar(0)) return RealScalar(0);
|
||||||
RealScalar q = (min)(_x, _y);
|
RealScalar q = (min)(_x, _y);
|
||||||
RealScalar qp = q/p;
|
RealScalar qp = q/p;
|
||||||
return p * sqrt(RealScalar(1) + qp*qp);
|
return p * sqrt(RealScalar(1) + qp*qp);
|
||||||
@@ -707,21 +718,21 @@ struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::
|
|||||||
|
|
||||||
template<typename Scalar, typename OtherScalar>
|
template<typename Scalar, typename OtherScalar>
|
||||||
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
inline bool isApprox(const Scalar& x, const Scalar& y,
|
inline bool isApprox(const Scalar& x, const Scalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
||||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
|
return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,6 +211,21 @@ class Matrix
|
|||||||
: Base(internal::constructor_without_unaligned_array_assert())
|
: Base(internal::constructor_without_unaligned_array_assert())
|
||||||
{ Base::_check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
|
{ Base::_check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED }
|
||||||
|
|
||||||
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
|
Matrix(Matrix&& other)
|
||||||
|
: Base(std::move(other))
|
||||||
|
{
|
||||||
|
Base::_check_template_params();
|
||||||
|
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
|
||||||
|
Base::_set_noalias(other);
|
||||||
|
}
|
||||||
|
Matrix& operator=(Matrix&& other)
|
||||||
|
{
|
||||||
|
other.swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
|
/** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
|
||||||
*
|
*
|
||||||
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
|
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
|
||||||
|
|||||||
@@ -159,13 +159,11 @@ template<typename Derived> class MatrixBase
|
|||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Derived& operator=(const ReturnByValue<OtherDerived>& other);
|
Derived& operator=(const ReturnByValue<OtherDerived>& other);
|
||||||
|
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other);
|
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other);
|
||||||
|
|
||||||
template<typename MatrixPower, typename Lhs, typename Rhs>
|
template<typename MatrixPower, typename Lhs, typename Rhs>
|
||||||
Derived& lazyAssign(const MatrixPowerProduct<MatrixPower, Lhs,Rhs>& other);
|
Derived& lazyAssign(const MatrixPowerProduct<MatrixPower, Lhs,Rhs>& other);
|
||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Derived& operator+=(const MatrixBase<OtherDerived>& other);
|
Derived& operator+=(const MatrixBase<OtherDerived>& other);
|
||||||
@@ -442,6 +440,15 @@ template<typename Derived> class MatrixBase
|
|||||||
template<typename OtherScalar>
|
template<typename OtherScalar>
|
||||||
void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j);
|
void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j);
|
||||||
|
|
||||||
|
///////// SparseCore module /////////
|
||||||
|
|
||||||
|
template<typename OtherDerived>
|
||||||
|
EIGEN_STRONG_INLINE const typename SparseMatrixBase<OtherDerived>::template CwiseProductDenseReturnType<Derived>::Type
|
||||||
|
cwiseProduct(const SparseMatrixBase<OtherDerived> &other) const
|
||||||
|
{
|
||||||
|
return other.cwiseProduct(derived());
|
||||||
|
}
|
||||||
|
|
||||||
///////// MatrixFunctions module /////////
|
///////// MatrixFunctions module /////////
|
||||||
|
|
||||||
typedef typename internal::stem_function<Scalar>::type StemFunction;
|
typedef typename internal::stem_function<Scalar>::type StemFunction;
|
||||||
|
|||||||
@@ -250,6 +250,35 @@ class PermutationBase : public EigenBase<Derived>
|
|||||||
template<typename Other> friend
|
template<typename Other> friend
|
||||||
inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm)
|
inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm)
|
||||||
{ return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); }
|
{ return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); }
|
||||||
|
|
||||||
|
/** \returns the determinant of the permutation matrix, which is either 1 or -1 depending on the parity of the permutation.
|
||||||
|
*
|
||||||
|
* This function is O(\c n) procedure allocating a buffer of \c n booleans.
|
||||||
|
*/
|
||||||
|
Index determinant() const
|
||||||
|
{
|
||||||
|
Index res = 1;
|
||||||
|
Index n = size();
|
||||||
|
Matrix<bool,RowsAtCompileTime,1,0,MaxRowsAtCompileTime> mask(n);
|
||||||
|
mask.fill(false);
|
||||||
|
Index r = 0;
|
||||||
|
while(r < n)
|
||||||
|
{
|
||||||
|
// search for the next seed
|
||||||
|
while(r<n && mask[r]) r++;
|
||||||
|
if(r>=n)
|
||||||
|
break;
|
||||||
|
// we got one, let's follow it until we are back to the seed
|
||||||
|
Index k0 = r++;
|
||||||
|
mask.coeffRef(k0) = true;
|
||||||
|
for(Index k=indices().coeff(k0); k!=k0; k=indices().coeff(k))
|
||||||
|
{
|
||||||
|
mask.coeffRef(k) = true;
|
||||||
|
res = -res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -555,10 +584,11 @@ struct permut_matrix_product_retval
|
|||||||
const Index n = Side==OnTheLeft ? rows() : cols();
|
const Index n = Side==OnTheLeft ? rows() : cols();
|
||||||
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
|
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
|
||||||
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
|
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
|
||||||
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
if( is_same<MatrixTypeNestedCleaned,Dest>::value
|
if( is_same<MatrixTypeNestedCleaned,Dest>::value
|
||||||
&& blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
|
&& blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
|
||||||
&& blas_traits<Dest>::HasUsableDirectAccess
|
&& blas_traits<Dest>::HasUsableDirectAccess
|
||||||
&& extract_data(dst) == extract_data(m_matrix))
|
&& dst_data!=0 && dst_data == extract_data(m_matrix))
|
||||||
{
|
{
|
||||||
// apply the permutation inplace
|
// apply the permutation inplace
|
||||||
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
|
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
|
||||||
|
|||||||
@@ -315,8 +315,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
|
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
|
||||||
{
|
{
|
||||||
const OtherDerived& other = _other.derived();
|
const OtherDerived& other = _other.derived();
|
||||||
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.rows(), other.cols());
|
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(Index(other.rows()), Index(other.cols()));
|
||||||
const Index othersize = other.rows()*other.cols();
|
const Index othersize = Index(other.rows())*Index(other.cols());
|
||||||
if(RowsAtCompileTime == 1)
|
if(RowsAtCompileTime == 1)
|
||||||
{
|
{
|
||||||
eigen_assert(other.rows() == 1 || other.cols() == 1);
|
eigen_assert(other.rows() == 1 || other.cols() == 1);
|
||||||
@@ -437,6 +437,36 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
|
PlainObjectBase(PlainObjectBase&& other)
|
||||||
|
: m_storage( std::move(other.m_storage) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PlainObjectBase& operator=(PlainObjectBase&& other)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(m_storage, other.m_storage);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Copy constructor */
|
||||||
|
EIGEN_STRONG_INLINE PlainObjectBase(const PlainObjectBase& other)
|
||||||
|
: m_storage()
|
||||||
|
{
|
||||||
|
_check_template_params();
|
||||||
|
lazyAssign(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherDerived>
|
||||||
|
EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase<OtherDerived> &other)
|
||||||
|
: m_storage()
|
||||||
|
{
|
||||||
|
_check_template_params();
|
||||||
|
lazyAssign(other);
|
||||||
|
}
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
|
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
|
||||||
: m_storage(a_size, nbRows, nbCols)
|
: m_storage(a_size, nbRows, nbCols)
|
||||||
{
|
{
|
||||||
@@ -457,7 +487,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
|
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
|
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
|
||||||
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
: m_storage(Index(other.derived().rows()) * Index(other.derived().cols()), other.derived().rows(), other.derived().cols())
|
||||||
{
|
{
|
||||||
_check_template_params();
|
_check_template_params();
|
||||||
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols());
|
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols());
|
||||||
@@ -573,6 +603,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
: (rows() == other.rows() && cols() == other.cols())))
|
: (rows() == other.rows() && cols() == other.cols())))
|
||||||
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
|
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
|
||||||
EIGEN_ONLY_USED_FOR_DEBUG(other);
|
EIGEN_ONLY_USED_FOR_DEBUG(other);
|
||||||
|
if(this->size()==0)
|
||||||
|
resizeLike(other);
|
||||||
#else
|
#else
|
||||||
resizeLike(other);
|
resizeLike(other);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -247,8 +247,9 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Func, typename Derived>
|
// NOTE: for SliceVectorizedTraversal we simply bypass unrolling
|
||||||
struct redux_impl<Func, Derived, SliceVectorizedTraversal, NoUnrolling>
|
template<typename Func, typename Derived, int Unrolling>
|
||||||
|
struct redux_impl<Func, Derived, SliceVectorizedTraversal, Unrolling>
|
||||||
{
|
{
|
||||||
typedef typename Derived::Scalar Scalar;
|
typedef typename Derived::Scalar Scalar;
|
||||||
typedef typename packet_traits<Scalar>::type PacketScalar;
|
typedef typename packet_traits<Scalar>::type PacketScalar;
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
|||||||
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
||||||
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
||||||
AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
|
AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
|
||||||
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch
|
ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
|
||||||
|
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
|
||||||
};
|
};
|
||||||
typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
|
typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
|
||||||
};
|
};
|
||||||
@@ -187,9 +188,11 @@ protected:
|
|||||||
template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
||||||
: public RefBase<Ref<PlainObjectType, Options, StrideType> >
|
: public RefBase<Ref<PlainObjectType, Options, StrideType> >
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
typedef internal::traits<Ref> Traits;
|
typedef internal::traits<Ref> Traits;
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(const PlainObjectBase<Derived>& expr);
|
inline Ref(const PlainObjectBase<Derived>& expr,
|
||||||
|
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef RefBase<Ref> Base;
|
typedef RefBase<Ref> Base;
|
||||||
@@ -198,13 +201,15 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
|||||||
|
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(PlainObjectBase<Derived>& expr)
|
inline Ref(PlainObjectBase<Derived>& expr,
|
||||||
|
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||||
Base::construct(expr.derived());
|
Base::construct(expr.derived());
|
||||||
}
|
}
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(const DenseBase<Derived>& expr)
|
inline Ref(const DenseBase<Derived>& expr,
|
||||||
|
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
||||||
#else
|
#else
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(DenseBase<Derived>& expr)
|
inline Ref(DenseBase<Derived>& expr)
|
||||||
@@ -231,13 +236,23 @@ template<typename TPlainObjectType, int Options, typename StrideType> class Ref<
|
|||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
|
EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(const DenseBase<Derived>& expr)
|
inline Ref(const DenseBase<Derived>& expr,
|
||||||
|
typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0)
|
||||||
{
|
{
|
||||||
// std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
|
// std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
|
||||||
// std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
|
// std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
|
||||||
// std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
|
// std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
|
||||||
construct(expr.derived(), typename Traits::template match<Derived>::type());
|
construct(expr.derived(), typename Traits::template match<Derived>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Ref(const Ref& other) : Base(other) {
|
||||||
|
// copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherRef>
|
||||||
|
inline Ref(const RefBase<OtherRef>& other) {
|
||||||
|
construct(other.derived(), typename Traits::template match<OtherRef>::type());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ template<typename Derived> class ReturnByValue
|
|||||||
const Unusable& coeff(Index,Index) const { return *reinterpret_cast<const Unusable*>(this); }
|
const Unusable& coeff(Index,Index) const { return *reinterpret_cast<const Unusable*>(this); }
|
||||||
Unusable& coeffRef(Index) { return *reinterpret_cast<Unusable*>(this); }
|
Unusable& coeffRef(Index) { return *reinterpret_cast<Unusable*>(this); }
|
||||||
Unusable& coeffRef(Index,Index) { return *reinterpret_cast<Unusable*>(this); }
|
Unusable& coeffRef(Index,Index) { return *reinterpret_cast<Unusable*>(this); }
|
||||||
|
template<int LoadMode> Unusable& packet(Index) const;
|
||||||
|
template<int LoadMode> Unusable& packet(Index, Index) const;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,6 +85,15 @@ Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
|||||||
return derived();
|
return derived();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
template<typename OtherDerived>
|
||||||
|
Derived& DenseBase<Derived>::lazyAssign(const ReturnByValue<OtherDerived>& other)
|
||||||
|
{
|
||||||
|
other.evalTo(derived());
|
||||||
|
return derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_RETURNBYVALUE_H
|
#endif // EIGEN_RETURNBYVALUE_H
|
||||||
|
|||||||
@@ -180,15 +180,9 @@ inline Derived& DenseBase<Derived>::operator*=(const Scalar& other)
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Derived& DenseBase<Derived>::operator/=(const Scalar& other)
|
inline Derived& DenseBase<Derived>::operator/=(const Scalar& other)
|
||||||
{
|
{
|
||||||
typedef typename internal::conditional<NumTraits<Scalar>::IsInteger,
|
|
||||||
internal::scalar_quotient_op<Scalar>,
|
|
||||||
internal::scalar_product_op<Scalar> >::type BinOp;
|
|
||||||
typedef typename Derived::PlainObject PlainObject;
|
typedef typename Derived::PlainObject PlainObject;
|
||||||
SelfCwiseBinaryOp<BinOp, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
|
SelfCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
|
||||||
Scalar actual_other;
|
tmp = PlainObject::Constant(rows(),cols(), other);
|
||||||
if(NumTraits<Scalar>::IsInteger) actual_other = other;
|
|
||||||
else actual_other = Scalar(1)/other;
|
|
||||||
tmp = PlainObject::Constant(rows(),cols(), actual_other);
|
|
||||||
return derived();
|
return derived();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,17 +116,17 @@ template<typename Lhs, typename Rhs, int Mode, int Index, int Size>
|
|||||||
struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
|
struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
|
||||||
enum {
|
enum {
|
||||||
IsLower = ((Mode&Lower)==Lower),
|
IsLower = ((Mode&Lower)==Lower),
|
||||||
I = IsLower ? Index : Size - Index - 1,
|
RowIndex = IsLower ? Index : Size - Index - 1,
|
||||||
S = IsLower ? 0 : I+1
|
S = IsLower ? 0 : RowIndex+1
|
||||||
};
|
};
|
||||||
static void run(const Lhs& lhs, Rhs& rhs)
|
static void run(const Lhs& lhs, Rhs& rhs)
|
||||||
{
|
{
|
||||||
if (Index>0)
|
if (Index>0)
|
||||||
rhs.coeffRef(I) -= lhs.row(I).template segment<Index>(S).transpose()
|
rhs.coeffRef(RowIndex) -= lhs.row(RowIndex).template segment<Index>(S).transpose()
|
||||||
.cwiseProduct(rhs.template segment<Index>(S)).sum();
|
.cwiseProduct(rhs.template segment<Index>(S)).sum();
|
||||||
|
|
||||||
if(!(Mode & UnitDiag))
|
if(!(Mode & UnitDiag))
|
||||||
rhs.coeffRef(I) /= lhs.coeff(I,I);
|
rhs.coeffRef(RowIndex) /= lhs.coeff(RowIndex,RowIndex);
|
||||||
|
|
||||||
triangular_solver_unroller<Lhs,Rhs,Mode,Index+1,Size>::run(lhs,rhs);
|
triangular_solver_unroller<Lhs,Rhs,Mode,Index+1,Size>::run(lhs,rhs);
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,8 @@ template<int Side, typename TriangularType, typename Rhs> struct triangular_solv
|
|||||||
|
|
||||||
template<typename Dest> inline void evalTo(Dest& dst) const
|
template<typename Dest> inline void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
if(!(is_same<RhsNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_rhs)))
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
|
if(!(is_same<RhsNestedCleaned,Dest>::value && dst_data!=0 && extract_data(dst) == extract_data(m_rhs)))
|
||||||
dst = m_rhs;
|
dst = m_rhs;
|
||||||
m_triangularMatrix.template solveInPlace<Side>(dst);
|
m_triangularMatrix.template solveInPlace<Side>(dst);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,11 +331,11 @@ inline void MatrixBase<Derived>::adjointInPlace()
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<typename BinOp,typename NestedXpr,typename Rhs>
|
template<typename BinOp,typename Xpr,typename Rhs>
|
||||||
struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
|
struct blas_traits<SelfCwiseBinaryOp<BinOp,Xpr,Rhs> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType;
|
typedef SelfCwiseBinaryOp<BinOp,Xpr,Rhs> XprType;
|
||||||
static inline const XprType extract(const XprType& x) { return x; }
|
static inline const XprType extract(const XprType& x) { return x; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -392,7 +392,6 @@ struct checkTransposeAliasing_impl
|
|||||||
::run(extract_data(dst), other))
|
::run(extract_data(dst), other))
|
||||||
&& "aliasing detected during transposition, use transposeInPlace() "
|
&& "aliasing detected during transposition, use transposeInPlace() "
|
||||||
"or evaluate the rhs into a temporary using .eval()");
|
"or evaluate the rhs into a temporary using .eval()");
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -376,7 +376,8 @@ struct transposition_matrix_product_retval
|
|||||||
const int size = m_transpositions.size();
|
const int size = m_transpositions.size();
|
||||||
Index j = 0;
|
Index j = 0;
|
||||||
|
|
||||||
if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
|
if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && dst_data!=0 && dst_data == extract_data(m_matrix)))
|
||||||
dst = m_matrix;
|
dst = m_matrix;
|
||||||
|
|
||||||
for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
|
for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
|
||||||
|
|||||||
@@ -76,14 +76,17 @@ template<typename Derived>
|
|||||||
template<typename Visitor>
|
template<typename Visitor>
|
||||||
void DenseBase<Derived>::visit(Visitor& visitor) const
|
void DenseBase<Derived>::visit(Visitor& visitor) const
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Derived::Nested>::type ThisNested;
|
||||||
|
typename Derived::Nested thisNested(derived());
|
||||||
|
|
||||||
enum { unroll = SizeAtCompileTime != Dynamic
|
enum { unroll = SizeAtCompileTime != Dynamic
|
||||||
&& CoeffReadCost != Dynamic
|
&& CoeffReadCost != Dynamic
|
||||||
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
|
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
|
||||||
&& SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
|
&& SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
|
||||||
<= EIGEN_UNROLLING_LIMIT };
|
<= EIGEN_UNROLLING_LIMIT };
|
||||||
return internal::visitor_impl<Visitor, Derived,
|
return internal::visitor_impl<Visitor, ThisNested,
|
||||||
unroll ? int(SizeAtCompileTime) : Dynamic
|
unroll ? int(SizeAtCompileTime) : Dynamic
|
||||||
>::run(derived(), visitor);
|
>::run(thisNested, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<
|
|||||||
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((float*)to, from.v); }
|
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((float*)to, from.v); }
|
||||||
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((float*)to, from.v); }
|
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((float*)to, from.v); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { __pld((float *)addr); }
|
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { EIGEN_ARM_PREFETCH((float *)addr); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
|
template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -218,8 +218,8 @@ template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& f
|
|||||||
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); }
|
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); }
|
||||||
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); }
|
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { __pld(addr); }
|
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||||
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { __pld(addr); }
|
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||||
|
|
||||||
// FIXME only store the 2 first elements ?
|
// FIXME only store the 2 first elements ?
|
||||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; }
|
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; }
|
||||||
@@ -384,6 +384,7 @@ template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
|||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
a_hi = vget_high_s32(a);
|
a_hi = vget_high_s32(a);
|
||||||
max = vpmax_s32(a_lo, a_hi);
|
max = vpmax_s32(a_lo, a_hi);
|
||||||
|
max = vpmax_s32(max, max);
|
||||||
|
|
||||||
return vget_lane_s32(max, 0);
|
return vget_lane_s32(max, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
|
|||||||
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f);
|
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f);
|
||||||
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f);
|
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f);
|
||||||
|
|
||||||
Packet4f tmp = _mm_setzero_ps(), fx;
|
Packet4f tmp, fx;
|
||||||
Packet4i emm0;
|
Packet4i emm0;
|
||||||
|
|
||||||
// clamp x
|
// clamp x
|
||||||
@@ -195,7 +195,7 @@ Packet2d pexp<Packet2d>(const Packet2d& _x)
|
|||||||
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C2, 1.42860682030941723212e-6);
|
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C2, 1.42860682030941723212e-6);
|
||||||
static const __m128i p4i_1023_0 = _mm_setr_epi32(1023, 1023, 0, 0);
|
static const __m128i p4i_1023_0 = _mm_setr_epi32(1023, 1023, 0, 0);
|
||||||
|
|
||||||
Packet2d tmp = _mm_setzero_pd(), fx;
|
Packet2d tmp, fx;
|
||||||
Packet4i emm0;
|
Packet4i emm0;
|
||||||
|
|
||||||
// clamp x
|
// clamp x
|
||||||
@@ -279,7 +279,7 @@ Packet4f psin<Packet4f>(const Packet4f& _x)
|
|||||||
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
|
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
|
||||||
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
|
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
|
||||||
|
|
||||||
Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y;
|
Packet4f xmm1, xmm2, xmm3, sign_bit, y;
|
||||||
|
|
||||||
Packet4i emm0, emm2;
|
Packet4i emm0, emm2;
|
||||||
sign_bit = x;
|
sign_bit = x;
|
||||||
@@ -378,7 +378,7 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
|
|||||||
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
|
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
|
||||||
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
|
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
|
||||||
|
|
||||||
Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, y;
|
Packet4f xmm1, xmm2, xmm3, y;
|
||||||
Packet4i emm0, emm2;
|
Packet4i emm0, emm2;
|
||||||
|
|
||||||
x = pabs(x);
|
x = pabs(x);
|
||||||
|
|||||||
@@ -235,63 +235,27 @@ template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { E
|
|||||||
return _mm_loadu_ps(from);
|
return _mm_loadu_ps(from);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); }
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from)); }
|
|
||||||
#else
|
#else
|
||||||
// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would
|
|
||||||
// require pointer casting to incompatible pointer types and leads to invalid code
|
|
||||||
// because of the strict aliasing rule. The "dummy" stuff are required to enforce
|
|
||||||
// a correct instruction dependency.
|
|
||||||
// TODO: do the same for MSVC (ICC is compatible)
|
|
||||||
// NOTE: with the code below, MSVC's compiler crashes!
|
// NOTE: with the code below, MSVC's compiler crashes!
|
||||||
|
|
||||||
#if defined(__GNUC__) && defined(__i386__)
|
|
||||||
// bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
|
|
||||||
#elif defined(__clang__)
|
|
||||||
// bug 201: Segfaults in __mm_loadh_pd with clang 2.8
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
|
|
||||||
#else
|
|
||||||
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
|
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
|
||||||
return _mm_loadu_ps(from);
|
return _mm_loadu_ps(from);
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd((const double*)(from)) ;
|
|
||||||
res = _mm_loadh_pd(res, (const double*)(from+2)) ;
|
|
||||||
return _mm_castpd_ps(res);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
|
||||||
return _mm_loadu_pd(from);
|
return _mm_loadu_pd(from);
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd(from) ;
|
|
||||||
res = _mm_loadh_pd(res,from+1);
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
|
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
|
||||||
{
|
{
|
||||||
EIGEN_DEBUG_UNALIGNED_LOAD
|
EIGEN_DEBUG_UNALIGNED_LOAD
|
||||||
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
|
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from));
|
||||||
return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from));
|
|
||||||
#else
|
|
||||||
__m128d res;
|
|
||||||
res = _mm_load_sd((const double*)(from)) ;
|
|
||||||
res = _mm_loadh_pd(res, (const double*)(from+2)) ;
|
|
||||||
return _mm_castpd_si128(res);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class CoeffBasedProduct
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
||||||
Unroll ? (InnerSize==0 ? 0 : InnerSize-1) : Dynamic,
|
Unroll ? InnerSize : Dynamic,
|
||||||
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||||
|
|
||||||
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
|
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
|
||||||
@@ -185,7 +185,7 @@ class CoeffBasedProduct
|
|||||||
{
|
{
|
||||||
PacketScalar res;
|
PacketScalar res;
|
||||||
internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
|
internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
|
||||||
Unroll ? (InnerSize==0 ? 0 : InnerSize-1) : Dynamic,
|
Unroll ? InnerSize : Dynamic,
|
||||||
_LhsNested, _RhsNested, PacketScalar, LoadMode>
|
_LhsNested, _RhsNested, PacketScalar, LoadMode>
|
||||||
::run(row, col, m_lhs, m_rhs, res);
|
::run(row, col, m_lhs, m_rhs, res);
|
||||||
return res;
|
return res;
|
||||||
@@ -243,7 +243,17 @@ struct product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
|||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||||
{
|
{
|
||||||
product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
|
product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
|
||||||
res += lhs.coeff(row, UnrollingIndex) * rhs.coeff(UnrollingIndex, col);
|
res += lhs.coeff(row, UnrollingIndex-1) * rhs.coeff(UnrollingIndex-1, col);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
|
struct product_coeff_impl<DefaultTraversal, 1, Lhs, Rhs, RetScalar>
|
||||||
|
{
|
||||||
|
typedef typename Lhs::Index Index;
|
||||||
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||||
|
{
|
||||||
|
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,9 +261,9 @@ template<typename Lhs, typename Rhs, typename RetScalar>
|
|||||||
struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
|
struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
|
||||||
{
|
{
|
||||||
typedef typename Lhs::Index Index;
|
typedef typename Lhs::Index Index;
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
|
||||||
{
|
{
|
||||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
res = RetScalar(0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -293,6 +303,16 @@ struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
|
struct product_coeff_impl<InnerVectorizedTraversal, 0, Lhs, Rhs, RetScalar>
|
||||||
|
{
|
||||||
|
typedef typename Lhs::Index Index;
|
||||||
|
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
|
||||||
|
{
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
||||||
{
|
{
|
||||||
@@ -302,8 +322,7 @@ struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, Re
|
|||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||||
{
|
{
|
||||||
Packet pres;
|
Packet pres;
|
||||||
product_coeff_vectorized_unroller<UnrollingIndex+1-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
|
product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
|
||||||
product_coeff_impl<DefaultTraversal,UnrollingIndex,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, res);
|
|
||||||
res = predux(pres);
|
res = predux(pres);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -371,7 +390,7 @@ struct product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
|||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||||
{
|
{
|
||||||
product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
||||||
res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex)), rhs.template packet<LoadMode>(UnrollingIndex, col), res);
|
res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex-1)), rhs.template packet<LoadMode>(UnrollingIndex-1, col), res);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -382,12 +401,12 @@ struct product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
|||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||||
{
|
{
|
||||||
product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
||||||
res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex), pset1<Packet>(rhs.coeff(UnrollingIndex, col)), res);
|
res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex-1), pset1<Packet>(rhs.coeff(UnrollingIndex-1, col)), res);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||||
struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
struct product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||||
{
|
{
|
||||||
typedef typename Lhs::Index Index;
|
typedef typename Lhs::Index Index;
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||||
@@ -397,7 +416,7 @@ struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||||
struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
struct product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||||
{
|
{
|
||||||
typedef typename Lhs::Index Index;
|
typedef typename Lhs::Index Index;
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||||
@@ -406,16 +425,35 @@ struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||||
|
struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||||
|
{
|
||||||
|
typedef typename Lhs::Index Index;
|
||||||
|
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
|
||||||
|
{
|
||||||
|
res = pset1<Packet>(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||||
|
struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||||
|
{
|
||||||
|
typedef typename Lhs::Index Index;
|
||||||
|
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
|
||||||
|
{
|
||||||
|
res = pset1<Packet>(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||||
struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||||
{
|
{
|
||||||
typedef typename Lhs::Index Index;
|
typedef typename Lhs::Index Index;
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
||||||
{
|
{
|
||||||
eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
res = pset1<Packet>(0);
|
||||||
res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
for(Index i = 0; i < lhs.cols(); ++i)
|
||||||
for(Index i = 1; i < lhs.cols(); ++i)
|
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
|
||||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -425,10 +463,9 @@ struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
|||||||
typedef typename Lhs::Index Index;
|
typedef typename Lhs::Index Index;
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
||||||
{
|
{
|
||||||
eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
res = pset1<Packet>(0);
|
||||||
res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
|
for(Index i = 0; i < lhs.cols(); ++i)
|
||||||
for(Index i = 1; i < lhs.cols(); ++i)
|
res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
||||||
res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -140,8 +140,10 @@ static void run(Index rows, Index cols, Index depth,
|
|||||||
// Release all the sub blocks B'_j of B' for the current thread,
|
// Release all the sub blocks B'_j of B' for the current thread,
|
||||||
// i.e., we simply decrement the number of users by 1
|
// i.e., we simply decrement the number of users by 1
|
||||||
for(Index j=0; j<threads; ++j)
|
for(Index j=0; j<threads; ++j)
|
||||||
|
{
|
||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
--(info[j].users);
|
info[j].users -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -390,13 +392,17 @@ class GeneralProduct<Lhs, Rhs, GemmProduct>
|
|||||||
|
|
||||||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
|
||||||
{
|
{
|
||||||
|
#if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG))
|
||||||
typedef internal::scalar_product_op<LhsScalar,RhsScalar> BinOp;
|
typedef internal::scalar_product_op<LhsScalar,RhsScalar> BinOp;
|
||||||
EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
|
EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
|
template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const
|
||||||
{
|
{
|
||||||
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
|
||||||
|
if(m_lhs.cols()==0 || m_lhs.rows()==0 || m_rhs.cols()==0)
|
||||||
|
return;
|
||||||
|
|
||||||
typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(m_lhs);
|
typename internal::add_const_on_value_type<ActualLhsType>::type lhs = LhsBlasTraits::extract(m_lhs);
|
||||||
typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(m_rhs);
|
typename internal::add_const_on_value_type<ActualRhsType>::type rhs = RhsBlasTraits::extract(m_rhs);
|
||||||
|
|||||||
@@ -125,19 +125,22 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos
|
|||||||
if(transpose)
|
if(transpose)
|
||||||
std::swap(rows,cols);
|
std::swap(rows,cols);
|
||||||
|
|
||||||
Index blockCols = (cols / threads) & ~Index(0x3);
|
|
||||||
Index blockRows = (rows / threads) & ~Index(0x7);
|
|
||||||
|
|
||||||
GemmParallelInfo<Index>* info = new GemmParallelInfo<Index>[threads];
|
GemmParallelInfo<Index>* info = new GemmParallelInfo<Index>[threads];
|
||||||
|
|
||||||
#pragma omp parallel for schedule(static,1) num_threads(threads)
|
#pragma omp parallel num_threads(threads)
|
||||||
for(Index i=0; i<threads; ++i)
|
|
||||||
{
|
{
|
||||||
|
Index i = omp_get_thread_num();
|
||||||
|
// Note that the actual number of threads might be lower than the number of request ones.
|
||||||
|
Index actual_threads = omp_get_num_threads();
|
||||||
|
|
||||||
|
Index blockCols = (cols / actual_threads) & ~Index(0x3);
|
||||||
|
Index blockRows = (rows / actual_threads) & ~Index(0x7);
|
||||||
|
|
||||||
Index r0 = i*blockRows;
|
Index r0 = i*blockRows;
|
||||||
Index actualBlockRows = (i+1==threads) ? rows-r0 : blockRows;
|
Index actualBlockRows = (i+1==actual_threads) ? rows-r0 : blockRows;
|
||||||
|
|
||||||
Index c0 = i*blockCols;
|
Index c0 = i*blockCols;
|
||||||
Index actualBlockCols = (i+1==threads) ? cols-c0 : blockCols;
|
Index actualBlockCols = (i+1==actual_threads) ? cols-c0 : blockCols;
|
||||||
|
|
||||||
info[i].rhs_start = c0;
|
info[i].rhs_start = c0;
|
||||||
info[i].rhs_length = actualBlockCols;
|
info[i].rhs_length = actualBlockCols;
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
|
|||||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||||
if (rows != depth) { \
|
if (rows != depth) { \
|
||||||
\
|
\
|
||||||
int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
|
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||||
\
|
\
|
||||||
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
|
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
|
||||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||||
@@ -223,7 +223,7 @@ struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
|
|||||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||||
if (cols != depth) { \
|
if (cols != depth) { \
|
||||||
\
|
\
|
||||||
int nthr = mkl_domain_get_max_threads(MKL_BLAS); \
|
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||||
\
|
\
|
||||||
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
|
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
|
||||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
// coherence when accessing the rhs elements
|
// coherence when accessing the rhs elements
|
||||||
std::ptrdiff_t l1, l2;
|
std::ptrdiff_t l1, l2;
|
||||||
manage_caching_sizes(GetAction, &l1, &l2);
|
manage_caching_sizes(GetAction, &l1, &l2);
|
||||||
Index subcols = cols>0 ? l2/(4 * sizeof(Scalar) * otherStride) : 0;
|
Index subcols = cols>0 ? l2/(4 * sizeof(Scalar) * std::max<Index>(otherStride,size)) : 0;
|
||||||
subcols = std::max<Index>((subcols/Traits::nr)*Traits::nr, Traits::nr);
|
subcols = std::max<Index>((subcols/Traits::nr)*Traits::nr, Traits::nr);
|
||||||
|
|
||||||
for(Index k2=IsLower ? 0 : size;
|
for(Index k2=IsLower ? 0 : size;
|
||||||
@@ -115,8 +115,9 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
{
|
{
|
||||||
// TODO write a small kernel handling this (can be shared with trsv)
|
// TODO write a small kernel handling this (can be shared with trsv)
|
||||||
Index i = IsLower ? k2+k1+k : k2-k1-k-1;
|
Index i = IsLower ? k2+k1+k : k2-k1-k-1;
|
||||||
Index s = IsLower ? k2+k1 : i+1;
|
|
||||||
Index rs = actualPanelWidth - k - 1; // remaining size
|
Index rs = actualPanelWidth - k - 1; // remaining size
|
||||||
|
Index s = TriStorageOrder==RowMajor ? (IsLower ? k2+k1 : i+1)
|
||||||
|
: IsLower ? i+1 : i-rs;
|
||||||
|
|
||||||
Scalar a = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(tri(i,i));
|
Scalar a = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(tri(i,i));
|
||||||
for (Index j=j2; j<j2+actual_cols; ++j)
|
for (Index j=j2; j<j2+actual_cols; ++j)
|
||||||
@@ -133,7 +134,6 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conju
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Index s = IsLower ? i+1 : i-rs;
|
|
||||||
Scalar b = (other(i,j) *= a);
|
Scalar b = (other(i,j) *= a);
|
||||||
Scalar* r = &other(s,j);
|
Scalar* r = &other(s,j);
|
||||||
const Scalar* l = &tri(s,i);
|
const Scalar* l = &tri(s,i);
|
||||||
@@ -302,9 +302,12 @@ EIGEN_DONT_INLINE void triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conj
|
|||||||
for (Index i=0; i<actual_mc; ++i)
|
for (Index i=0; i<actual_mc; ++i)
|
||||||
r[i] -= a[i] * b;
|
r[i] -= a[i] * b;
|
||||||
}
|
}
|
||||||
Scalar b = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(rhs(j,j));
|
if((Mode & UnitDiag)==0)
|
||||||
for (Index i=0; i<actual_mc; ++i)
|
{
|
||||||
r[i] *= b;
|
Scalar b = conj(rhs(j,j));
|
||||||
|
for (Index i=0; i<actual_mc; ++i)
|
||||||
|
r[i] /= b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pack the just computed part of lhs to A
|
// pack the just computed part of lhs to A
|
||||||
|
|||||||
@@ -171,12 +171,13 @@ template<typename XprType> struct blas_traits
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop conjugate
|
// pop conjugate
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -188,12 +189,13 @@ struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop scalar multiple
|
// pop scalar multiple
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_multiple_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
||||||
static inline Scalar extractScalarFactor(const XprType& x)
|
static inline Scalar extractScalarFactor(const XprType& x)
|
||||||
@@ -201,12 +203,13 @@ struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop opposite
|
// pop opposite
|
||||||
template<typename Scalar, typename NestedXpr>
|
template<typename Scalar, typename Xpr>
|
||||||
struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
|
struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> XprType;
|
typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, Xpr> XprType;
|
||||||
typedef typename Base::ExtractType ExtractType;
|
typedef typename Base::ExtractType ExtractType;
|
||||||
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
|
||||||
static inline Scalar extractScalarFactor(const XprType& x)
|
static inline Scalar extractScalarFactor(const XprType& x)
|
||||||
@@ -214,13 +217,14 @@ struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
|
|||||||
};
|
};
|
||||||
|
|
||||||
// pop/push transpose
|
// pop/push transpose
|
||||||
template<typename NestedXpr>
|
template<typename Xpr>
|
||||||
struct blas_traits<Transpose<NestedXpr> >
|
struct blas_traits<Transpose<Xpr> >
|
||||||
: blas_traits<NestedXpr>
|
: blas_traits<typename internal::remove_all<typename Xpr::Nested>::type>
|
||||||
{
|
{
|
||||||
|
typedef typename internal::remove_all<typename Xpr::Nested>::type NestedXpr;
|
||||||
typedef typename NestedXpr::Scalar Scalar;
|
typedef typename NestedXpr::Scalar Scalar;
|
||||||
typedef blas_traits<NestedXpr> Base;
|
typedef blas_traits<NestedXpr> Base;
|
||||||
typedef Transpose<NestedXpr> XprType;
|
typedef Transpose<Xpr> XprType;
|
||||||
typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
|
typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
|
||||||
typedef Transpose<const typename Base::_ExtractType> _ExtractType;
|
typedef Transpose<const typename Base::_ExtractType> _ExtractType;
|
||||||
typedef typename conditional<bool(Base::HasUsableDirectAccess),
|
typedef typename conditional<bool(Base::HasUsableDirectAccess),
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const unsigned int HereditaryBits = RowMajorBit
|
|||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum containing possible values for the \p Mode parameter of
|
* Enum containing possible values for the \p Mode parameter of
|
||||||
* MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
|
* MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
|
||||||
enum {
|
enum UpLoType {
|
||||||
/** View matrix as a lower triangular matrix. */
|
/** View matrix as a lower triangular matrix. */
|
||||||
Lower=0x1,
|
Lower=0x1,
|
||||||
/** View matrix as an upper triangular matrix. */
|
/** View matrix as an upper triangular matrix. */
|
||||||
@@ -187,7 +187,7 @@ enum {
|
|||||||
|
|
||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum for indicating whether an object is aligned or not. */
|
* Enum for indicating whether an object is aligned or not. */
|
||||||
enum {
|
enum AlignmentType {
|
||||||
/** Object is not correctly aligned for vectorization. */
|
/** Object is not correctly aligned for vectorization. */
|
||||||
Unaligned=0,
|
Unaligned=0,
|
||||||
/** Object is aligned for vectorization. */
|
/** Object is aligned for vectorization. */
|
||||||
@@ -217,7 +217,7 @@ enum DirectionType {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify how to traverse the entries of a matrix. */
|
* Enum to specify how to traverse the entries of a matrix. */
|
||||||
enum {
|
enum TraversalType {
|
||||||
/** \internal Default traversal, no vectorization, no index-based access */
|
/** \internal Default traversal, no vectorization, no index-based access */
|
||||||
DefaultTraversal,
|
DefaultTraversal,
|
||||||
/** \internal No vectorization, use index-based access to have only one for loop instead of 2 nested loops */
|
/** \internal No vectorization, use index-based access to have only one for loop instead of 2 nested loops */
|
||||||
@@ -239,7 +239,7 @@ enum {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
|
* Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
|
||||||
enum {
|
enum UnrollingType {
|
||||||
/** \internal Do not unroll loops. */
|
/** \internal Do not unroll loops. */
|
||||||
NoUnrolling,
|
NoUnrolling,
|
||||||
/** \internal Unroll only the inner loop, but not the outer loop. */
|
/** \internal Unroll only the inner loop, but not the outer loop. */
|
||||||
@@ -251,7 +251,7 @@ enum {
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum to specify whether to use the default (built-in) implementation or the specialization. */
|
* Enum to specify whether to use the default (built-in) implementation or the specialization. */
|
||||||
enum {
|
enum SpecializedType {
|
||||||
Specialized,
|
Specialized,
|
||||||
BuiltIn
|
BuiltIn
|
||||||
};
|
};
|
||||||
@@ -259,7 +259,7 @@ enum {
|
|||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum containing possible values for the \p _Options template parameter of
|
* Enum containing possible values for the \p _Options template parameter of
|
||||||
* Matrix, Array and BandMatrix. */
|
* Matrix, Array and BandMatrix. */
|
||||||
enum {
|
enum StorageOptions {
|
||||||
/** Storage order is column major (see \ref TopicStorageOrders). */
|
/** Storage order is column major (see \ref TopicStorageOrders). */
|
||||||
ColMajor = 0,
|
ColMajor = 0,
|
||||||
/** Storage order is row major (see \ref TopicStorageOrders). */
|
/** Storage order is row major (see \ref TopicStorageOrders). */
|
||||||
@@ -272,7 +272,7 @@ enum {
|
|||||||
|
|
||||||
/** \ingroup enums
|
/** \ingroup enums
|
||||||
* Enum for specifying whether to apply or solve on the left or right. */
|
* Enum for specifying whether to apply or solve on the left or right. */
|
||||||
enum {
|
enum SideType {
|
||||||
/** Apply transformation on the left. */
|
/** Apply transformation on the left. */
|
||||||
OnTheLeft = 1,
|
OnTheLeft = 1,
|
||||||
/** Apply transformation on the right. */
|
/** Apply transformation on the right. */
|
||||||
@@ -418,7 +418,7 @@ namespace Architecture
|
|||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum used as template parameter in GeneralProduct. */
|
* Enum used as template parameter in GeneralProduct. */
|
||||||
enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
enum ProductImplType { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
|
||||||
|
|
||||||
/** \internal \ingroup enums
|
/** \internal \ingroup enums
|
||||||
* Enum used in experimental parallel implementation. */
|
* Enum used in experimental parallel implementation. */
|
||||||
@@ -433,6 +433,19 @@ struct MatrixXpr {};
|
|||||||
/** The type used to identify an array expression */
|
/** The type used to identify an array expression */
|
||||||
struct ArrayXpr {};
|
struct ArrayXpr {};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
/** \internal
|
||||||
|
* Constants for comparison functors
|
||||||
|
*/
|
||||||
|
enum ComparisonName {
|
||||||
|
cmp_EQ = 0,
|
||||||
|
cmp_LT = 1,
|
||||||
|
cmp_LE = 2,
|
||||||
|
cmp_UNORD = 3,
|
||||||
|
cmp_NEQ = 4
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_CONSTANTS_H
|
#endif // EIGEN_CONSTANTS_H
|
||||||
|
|||||||
@@ -35,6 +35,14 @@
|
|||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#endif
|
#endif
|
||||||
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||||
|
|
||||||
|
#elif defined __GNUC__ && __GNUC__>=6
|
||||||
|
|
||||||
|
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
|
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // not EIGEN_WARNINGS_DISABLED
|
#endif // not EIGEN_WARNINGS_DISABLED
|
||||||
|
|||||||
@@ -235,6 +235,9 @@ template<typename Scalar> class Rotation2D;
|
|||||||
template<typename Scalar> class AngleAxis;
|
template<typename Scalar> class AngleAxis;
|
||||||
template<typename Scalar,int Dim> class Translation;
|
template<typename Scalar,int Dim> class Translation;
|
||||||
|
|
||||||
|
// Sparse module:
|
||||||
|
template<typename Derived> class SparseMatrixBase;
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
template<typename Derived, int _Dim> class eigen2_RotationBase;
|
template<typename Derived, int _Dim> class eigen2_RotationBase;
|
||||||
template<typename Lhs, typename Rhs> class eigen2_Cross;
|
template<typename Lhs, typename Rhs> class eigen2_Cross;
|
||||||
|
|||||||
@@ -76,6 +76,38 @@
|
|||||||
#include <mkl_lapacke.h>
|
#include <mkl_lapacke.h>
|
||||||
#define EIGEN_MKL_VML_THRESHOLD 128
|
#define EIGEN_MKL_VML_THRESHOLD 128
|
||||||
|
|
||||||
|
/* MKL_DOMAIN_BLAS, etc are defined only in 10.3 update 7 */
|
||||||
|
/* MKL_BLAS, etc are not defined in 11.2 */
|
||||||
|
#ifdef MKL_DOMAIN_ALL
|
||||||
|
#define EIGEN_MKL_DOMAIN_ALL MKL_DOMAIN_ALL
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_ALL MKL_ALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_BLAS
|
||||||
|
#define EIGEN_MKL_DOMAIN_BLAS MKL_DOMAIN_BLAS
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_BLAS MKL_BLAS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_FFT
|
||||||
|
#define EIGEN_MKL_DOMAIN_FFT MKL_DOMAIN_FFT
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_FFT MKL_FFT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_VML
|
||||||
|
#define EIGEN_MKL_DOMAIN_VML MKL_DOMAIN_VML
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_VML MKL_VML
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MKL_DOMAIN_PARDISO
|
||||||
|
#define EIGEN_MKL_DOMAIN_PARDISO MKL_DOMAIN_PARDISO
|
||||||
|
#else
|
||||||
|
#define EIGEN_MKL_DOMAIN_PARDISO MKL_PARDISO
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
typedef std::complex<double> dcomplex;
|
typedef std::complex<double> dcomplex;
|
||||||
|
|||||||
@@ -13,23 +13,292 @@
|
|||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 3
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 2
|
#define EIGEN_MAJOR_VERSION 2
|
||||||
#define EIGEN_MINOR_VERSION 3
|
#define EIGEN_MINOR_VERSION 9
|
||||||
|
|
||||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
#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_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||||
EIGEN_MINOR_VERSION>=z))))
|
EIGEN_MINOR_VERSION>=z))))
|
||||||
|
|
||||||
|
|
||||||
|
// Compiler identification, EIGEN_COMP_*
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_GNUC set to 1 for all compilers compatible with GCC
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
#define EIGEN_COMP_GNUC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_GNUC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_CLANG set to 1 if the compiler is clang (alias for __clang__)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define EIGEN_COMP_CLANG 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_CLANG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_LLVM set to 1 if the compiler backend is llvm
|
||||||
|
#if defined(__llvm__)
|
||||||
|
#define EIGEN_COMP_LLVM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_LLVM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_ICC set to __INTEL_COMPILER if the compiler is Intel compiler, 0 otherwise
|
||||||
|
#if defined(__INTEL_COMPILER)
|
||||||
|
#define EIGEN_COMP_ICC __INTEL_COMPILER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_ICC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MINGW set to 1 if the compiler is mingw
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
#define EIGEN_COMP_MINGW 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MINGW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_SUNCC set to 1 if the compiler is Solaris Studio
|
||||||
|
#if defined(__SUNPRO_CC)
|
||||||
|
#define EIGEN_COMP_SUNCC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_SUNCC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MSVC set to _MSC_VER if the compiler is Microsoft Visual C++, 0 otherwise.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define EIGEN_COMP_MSVC _MSC_VER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MSVC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC
|
||||||
|
#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC)
|
||||||
|
#define EIGEN_COMP_MSVC_STRICT _MSC_VER
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_MSVC_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_IBM set to 1 if the compiler is IBM XL C++
|
||||||
|
#if defined(__IBMCPP__) || defined(__xlc__)
|
||||||
|
#define EIGEN_COMP_IBM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_IBM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_PGI set to 1 if the compiler is Portland Group Compiler
|
||||||
|
#if defined(__PGI)
|
||||||
|
#define EIGEN_COMP_PGI 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_PGI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_COMP_ARM set to 1 if the compiler is ARM Compiler
|
||||||
|
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||||
|
#define EIGEN_COMP_ARM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_ARM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// \internal EIGEN_GNUC_STRICT set to 1 if the compiler is really GCC and not a compatible compiler (e.g., ICC, clang, mingw, etc.)
|
||||||
|
#if EIGEN_COMP_GNUC && !(EIGEN_COMP_CLANG || EIGEN_COMP_ICC || EIGEN_COMP_MINGW || EIGEN_COMP_PGI || EIGEN_COMP_IBM || EIGEN_COMP_ARM )
|
||||||
|
#define EIGEN_COMP_GNUC_STRICT 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_COMP_GNUC_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if EIGEN_COMP_GNUC
|
||||||
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x)
|
||||||
|
#define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__<x)
|
||||||
|
#define EIGEN_GNUC_AT(x,y) ( __GNUC__==x && __GNUC_MINOR__==y )
|
||||||
#else
|
#else
|
||||||
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
#define EIGEN_GNUC_AT_LEAST(x,y) 0
|
||||||
|
#define EIGEN_GNUC_AT_MOST(x,y) 0
|
||||||
|
#define EIGEN_GNUC_AT(x,y) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
// FIXME: could probably be removed as we do not support gcc 3.x anymore
|
||||||
#define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__<x)
|
#if EIGEN_COMP_GNUC && (__GNUC__ <= 3)
|
||||||
|
#define EIGEN_GCC3_OR_OLDER 1
|
||||||
#else
|
#else
|
||||||
#define EIGEN_GNUC_AT_MOST(x,y) 0
|
#define EIGEN_GCC3_OR_OLDER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Architecture identification, EIGEN_ARCH_*
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64)
|
||||||
|
#define EIGEN_ARCH_x86_64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_x86_64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__i386)
|
||||||
|
#define EIGEN_ARCH_i386 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_i386 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EIGEN_ARCH_x86_64 || EIGEN_ARCH_i386
|
||||||
|
#define EIGEN_ARCH_i386_OR_x86_64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_i386_OR_x86_64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_ARM set to 1 if the architecture is ARM
|
||||||
|
#if defined(__arm__)
|
||||||
|
#define EIGEN_ARCH_ARM 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_ARM64 set to 1 if the architecture is ARM64
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
#define EIGEN_ARCH_ARM64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EIGEN_ARCH_ARM || EIGEN_ARCH_ARM64
|
||||||
|
#define EIGEN_ARCH_ARM_OR_ARM64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_ARM_OR_ARM64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_MIPS set to 1 if the architecture is MIPS
|
||||||
|
#if defined(__mips__) || defined(__mips)
|
||||||
|
#define EIGEN_ARCH_MIPS 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_MIPS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_SPARC set to 1 if the architecture is SPARC
|
||||||
|
#if defined(__sparc__) || defined(__sparc)
|
||||||
|
#define EIGEN_ARCH_SPARC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_SPARC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_IA64 set to 1 if the architecture is Intel Itanium
|
||||||
|
#if defined(__ia64__)
|
||||||
|
#define EIGEN_ARCH_IA64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_IA64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_ARCH_PPC set to 1 if the architecture is PowerPC
|
||||||
|
#if defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
|
||||||
|
#define EIGEN_ARCH_PPC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_ARCH_PPC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Operating system identification, EIGEN_OS_*
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_UNIX set to 1 if the OS is a unix variant
|
||||||
|
#if defined(__unix__) || defined(__unix)
|
||||||
|
#define EIGEN_OS_UNIX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_UNIX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_LINUX set to 1 if the OS is based on Linux kernel
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define EIGEN_OS_LINUX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_LINUX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_ANDROID set to 1 if the OS is Android
|
||||||
|
// note: ANDROID is defined when using ndk_build, __ANDROID__ is defined when using a standalone toolchain.
|
||||||
|
#if defined(__ANDROID__) || defined(ANDROID)
|
||||||
|
#define EIGEN_OS_ANDROID 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_ANDROID 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_GNULINUX set to 1 if the OS is GNU Linux and not Linux-based OS (e.g., not android)
|
||||||
|
#if defined(__gnu_linux__) && !(EIGEN_OS_ANDROID)
|
||||||
|
#define EIGEN_OS_GNULINUX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_GNULINUX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_BSD set to 1 if the OS is a BSD variant
|
||||||
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)
|
||||||
|
#define EIGEN_OS_BSD 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_BSD 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_MAC set to 1 if the OS is MacOS
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define EIGEN_OS_MAC 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_MAC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_QNX set to 1 if the OS is QNX
|
||||||
|
#if defined(__QNX__)
|
||||||
|
#define EIGEN_OS_QNX 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_QNX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN set to 1 if the OS is Windows based
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define EIGEN_OS_WIN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN64 set to 1 if the OS is Windows 64bits
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define EIGEN_OS_WIN64 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN64 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WINCE set to 1 if the OS is Windows CE
|
||||||
|
#if defined(_WIN32_WCE)
|
||||||
|
#define EIGEN_OS_WINCE 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WINCE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_CYGWIN set to 1 if the OS is Windows/Cygwin
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
#define EIGEN_OS_CYGWIN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_CYGWIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_WIN_STRICT set to 1 if the OS is really Windows and not some variants
|
||||||
|
#if EIGEN_OS_WIN && !( EIGEN_OS_WINCE || EIGEN_OS_CYGWIN )
|
||||||
|
#define EIGEN_OS_WIN_STRICT 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_WIN_STRICT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_SUN set to 1 if the OS is SUN
|
||||||
|
#if (defined(sun) || defined(__sun)) && !(defined(__SVR4) || defined(__svr4__))
|
||||||
|
#define EIGEN_OS_SUN 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_SUN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// \internal EIGEN_OS_SOLARIS set to 1 if the OS is Solaris
|
||||||
|
#if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
|
||||||
|
#define EIGEN_OS_SOLARIS 1
|
||||||
|
#else
|
||||||
|
#define EIGEN_OS_SOLARIS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if EIGEN_GNUC_AT_MOST(4,3) && !defined(__clang__)
|
#if EIGEN_GNUC_AT_MOST(4,3) && !defined(__clang__)
|
||||||
// see bug 89
|
// see bug 89
|
||||||
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 0
|
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 0
|
||||||
@@ -37,12 +306,6 @@
|
|||||||
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 1
|
#define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ <= 3)
|
|
||||||
#define EIGEN_GCC3_OR_OLDER 1
|
|
||||||
#else
|
|
||||||
#define EIGEN_GCC3_OR_OLDER 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable
|
// 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
|
// 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
|
// enable alignment, but it can be a cause of problems on some platforms, so we just disable it in
|
||||||
@@ -96,6 +359,20 @@
|
|||||||
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
|
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// A Clang feature extension to determine compiler features.
|
||||||
|
// We use it to determine 'cxx_rvalue_references'
|
||||||
|
#ifndef __has_feature
|
||||||
|
# define __has_feature(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Do we support r-value references?
|
||||||
|
#if (__has_feature(cxx_rvalue_references) || \
|
||||||
|
(defined(__cplusplus) && __cplusplus >= 201103L) || \
|
||||||
|
(defined(_MSC_VER) && _MSC_VER >= 1600))
|
||||||
|
#define EIGEN_HAVE_RVALUE_REFERENCES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Cross compiler wrapper around LLVM's __has_builtin
|
// Cross compiler wrapper around LLVM's __has_builtin
|
||||||
#ifdef __has_builtin
|
#ifdef __has_builtin
|
||||||
# define EIGEN_HAS_BUILTIN(x) __has_builtin(x)
|
# define EIGEN_HAS_BUILTIN(x) __has_builtin(x)
|
||||||
@@ -278,6 +555,7 @@ namespace Eigen {
|
|||||||
#error Please tell me what is the equivalent of __attribute__((aligned(n))) for your compiler
|
#error Please tell me what is the equivalent of __attribute__((aligned(n))) for your compiler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define EIGEN_ALIGN8 EIGEN_ALIGN_TO_BOUNDARY(8)
|
||||||
#define EIGEN_ALIGN16 EIGEN_ALIGN_TO_BOUNDARY(16)
|
#define EIGEN_ALIGN16 EIGEN_ALIGN_TO_BOUNDARY(16)
|
||||||
|
|
||||||
#if EIGEN_ALIGN_STATICALLY
|
#if EIGEN_ALIGN_STATICALLY
|
||||||
@@ -313,7 +591,7 @@ namespace Eigen {
|
|||||||
// just an empty macro !
|
// just an empty macro !
|
||||||
#define EIGEN_EMPTY
|
#define EIGEN_EMPTY
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (!defined(__INTEL_COMPILER))
|
#if defined(_MSC_VER) && (_MSC_VER < 1900) && (!defined(__INTEL_COMPILER))
|
||||||
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||||
using Base::operator =;
|
using Base::operator =;
|
||||||
#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
#elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
||||||
@@ -332,8 +610,11 @@ namespace Eigen {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
|
/** \internal
|
||||||
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived)
|
* \brief Macro to manually inherit assignment operators.
|
||||||
|
* This is necessary, because the implicitly defined assignment operator gets deleted when a custom operator= is defined.
|
||||||
|
*/
|
||||||
|
#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just a side note. Commenting within defines works only by documenting
|
* Just a side note. Commenting within defines works only by documenting
|
||||||
@@ -405,6 +686,8 @@ namespace Eigen {
|
|||||||
#define EIGEN_SIZE_MAX(a,b) (((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
|
#define EIGEN_SIZE_MAX(a,b) (((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
|
||||||
: ((int)a >= (int)b) ? (int)a : (int)b)
|
: ((int)a >= (int)b) ? (int)a : (int)b)
|
||||||
|
|
||||||
|
#define EIGEN_ADD_COST(a,b) int(a)==Dynamic || int(b)==Dynamic ? Dynamic : int(a)+int(b)
|
||||||
|
|
||||||
#define EIGEN_LOGICAL_XOR(a,b) (((a) || (b)) && !((a) && (b)))
|
#define EIGEN_LOGICAL_XOR(a,b) (((a) || (b)) && !((a) && (b)))
|
||||||
|
|
||||||
#define EIGEN_IMPLIES(a,b) (!(a) || (b))
|
#define EIGEN_IMPLIES(a,b) (!(a) || (b))
|
||||||
|
|||||||
@@ -466,9 +466,8 @@ template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *
|
|||||||
template<typename Scalar, typename Index>
|
template<typename Scalar, typename Index>
|
||||||
static inline Index first_aligned(const Scalar* array, Index size)
|
static inline Index first_aligned(const Scalar* array, Index size)
|
||||||
{
|
{
|
||||||
enum { PacketSize = packet_traits<Scalar>::size,
|
static const Index PacketSize = packet_traits<Scalar>::size;
|
||||||
PacketAlignedMask = PacketSize-1
|
static const Index PacketAlignedMask = PacketSize-1;
|
||||||
};
|
|
||||||
|
|
||||||
if(PacketSize==1)
|
if(PacketSize==1)
|
||||||
{
|
{
|
||||||
@@ -508,7 +507,12 @@ template<typename T> void smart_copy(const T* start, const T* end, T* target)
|
|||||||
|
|
||||||
template<typename T> struct smart_copy_helper<T,true> {
|
template<typename T> struct smart_copy_helper<T,true> {
|
||||||
static inline void run(const T* start, const T* end, T* target)
|
static inline void run(const T* start, const T* end, T* target)
|
||||||
{ memcpy(target, start, std::ptrdiff_t(end)-std::ptrdiff_t(start)); }
|
{
|
||||||
|
std::ptrdiff_t size = std::ptrdiff_t(end)-std::ptrdiff_t(start);
|
||||||
|
if(size==0) return;
|
||||||
|
eigen_internal_assert(start!=0 && end!=0 && target!=0);
|
||||||
|
memcpy(target, start, size);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct smart_copy_helper<T,false> {
|
template<typename T> struct smart_copy_helper<T,false> {
|
||||||
@@ -516,7 +520,6 @@ template<typename T> struct smart_copy_helper<T,false> {
|
|||||||
{ std::copy(start, end, target); }
|
{ std::copy(start, end, target); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@@ -524,7 +527,7 @@ template<typename T> struct smart_copy_helper<T,false> {
|
|||||||
// you can overwrite Eigen's default behavior regarding alloca by defining EIGEN_ALLOCA
|
// you can overwrite Eigen's default behavior regarding alloca by defining EIGEN_ALLOCA
|
||||||
// to the appropriate stack allocation function
|
// to the appropriate stack allocation function
|
||||||
#ifndef EIGEN_ALLOCA
|
#ifndef EIGEN_ALLOCA
|
||||||
#if (defined __linux__)
|
#if (defined __linux__) || (defined __APPLE__) || (defined alloca)
|
||||||
#define EIGEN_ALLOCA alloca
|
#define EIGEN_ALLOCA alloca
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define EIGEN_ALLOCA _alloca
|
#define EIGEN_ALLOCA _alloca
|
||||||
@@ -631,6 +634,8 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
} \
|
} \
|
||||||
void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
|
void operator delete(void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
|
void operator delete[](void * ptr, std::size_t /* sz */) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||||
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
||||||
/* memory allocated we can safely let the default implementation handle */ \
|
/* memory allocated we can safely let the default implementation handle */ \
|
||||||
/* this particular case. */ \
|
/* this particular case. */ \
|
||||||
@@ -654,99 +659,60 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/** \class aligned_allocator
|
/** \class aligned_allocator
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
*
|
*
|
||||||
* \brief STL compatible allocator to use with with 16 byte aligned types
|
* \brief STL compatible allocator to use with with 16 byte aligned types
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* \code
|
* \code
|
||||||
* // Matrix4f requires 16 bytes alignment:
|
* // Matrix4f requires 16 bytes alignment:
|
||||||
* std::map< int, Matrix4f, std::less<int>,
|
* std::map< int, Matrix4f, std::less<int>,
|
||||||
* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
|
* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
|
||||||
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
|
||||||
* std::map< int, Vector3f > my_map_vec3;
|
* std::map< int, Vector3f > my_map_vec3;
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* \sa \ref TopicStlContainers.
|
* \sa \blank \ref TopicStlContainers.
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
class aligned_allocator
|
class aligned_allocator : public std::allocator<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef size_t size_type;
|
typedef size_t size_type;
|
||||||
typedef std::ptrdiff_t difference_type;
|
typedef std::ptrdiff_t difference_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
typedef const T* const_pointer;
|
typedef const T* const_pointer;
|
||||||
typedef T& reference;
|
typedef T& reference;
|
||||||
typedef const T& const_reference;
|
typedef const T& const_reference;
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
struct rebind
|
struct rebind
|
||||||
{
|
{
|
||||||
typedef aligned_allocator<U> other;
|
typedef aligned_allocator<U> other;
|
||||||
};
|
};
|
||||||
|
|
||||||
pointer address( reference value ) const
|
aligned_allocator() : std::allocator<T>() {}
|
||||||
{
|
|
||||||
return &value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_pointer address( const_reference value ) const
|
aligned_allocator(const aligned_allocator& other) : std::allocator<T>(other) {}
|
||||||
{
|
|
||||||
return &value;
|
|
||||||
}
|
|
||||||
|
|
||||||
aligned_allocator()
|
template<class U>
|
||||||
{
|
aligned_allocator(const aligned_allocator<U>& other) : std::allocator<T>(other) {}
|
||||||
}
|
|
||||||
|
|
||||||
aligned_allocator( const aligned_allocator& )
|
~aligned_allocator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class U>
|
pointer allocate(size_type num, const void* /*hint*/ = 0)
|
||||||
aligned_allocator( const aligned_allocator<U>& )
|
{
|
||||||
{
|
internal::check_size_for_overflow<T>(num);
|
||||||
}
|
return static_cast<pointer>( internal::aligned_malloc(num * sizeof(T)) );
|
||||||
|
}
|
||||||
|
|
||||||
~aligned_allocator()
|
void deallocate(pointer p, size_type /*num*/)
|
||||||
{
|
{
|
||||||
}
|
internal::aligned_free(p);
|
||||||
|
}
|
||||||
size_type max_size() const
|
|
||||||
{
|
|
||||||
return (std::numeric_limits<size_type>::max)();
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer allocate( size_type num, const void* hint = 0 )
|
|
||||||
{
|
|
||||||
EIGEN_UNUSED_VARIABLE(hint);
|
|
||||||
internal::check_size_for_overflow<T>(num);
|
|
||||||
return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void construct( pointer p, const T& value )
|
|
||||||
{
|
|
||||||
::new( p ) T( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy( pointer p )
|
|
||||||
{
|
|
||||||
p->~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate( pointer p, size_type /*num*/ )
|
|
||||||
{
|
|
||||||
internal::aligned_free( p );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const aligned_allocator<T>& ) const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
bool operator==(const aligned_allocator<T>& ) const
|
|
||||||
{ return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------- Cache sizes ----------
|
//---------- Cache sizes ----------
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
#pragma warning pop
|
#pragma warning pop
|
||||||
#elif defined __clang__
|
#elif defined __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined __GNUC__ && __GNUC__>=6
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // EIGEN_WARNINGS_DISABLED
|
#endif // EIGEN_WARNINGS_DISABLED
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#ifndef EIGEN_NO_STATIC_ASSERT
|
#ifndef EIGEN_NO_STATIC_ASSERT
|
||||||
|
|
||||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
|
#if __has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600)
|
||||||
|
|
||||||
// if native static_assert is enabled, let's use it
|
// if native static_assert is enabled, let's use it
|
||||||
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
||||||
|
|||||||
@@ -366,17 +366,17 @@ struct dense_xpr_base<Derived, ArrayXpr>
|
|||||||
|
|
||||||
/** \internal Helper base class to add a scalar multiple operator
|
/** \internal Helper base class to add a scalar multiple operator
|
||||||
* overloads for complex types */
|
* overloads for complex types */
|
||||||
template<typename Derived,typename Scalar,typename OtherScalar,
|
template<typename Derived, typename Scalar, typename OtherScalar, typename BaseType,
|
||||||
bool EnableIt = !is_same<Scalar,OtherScalar>::value >
|
bool EnableIt = !is_same<Scalar,OtherScalar>::value >
|
||||||
struct special_scalar_op_base : public DenseCoeffsBase<Derived>
|
struct special_scalar_op_base : public BaseType
|
||||||
{
|
{
|
||||||
// dummy operator* so that the
|
// dummy operator* so that the
|
||||||
// "using special_scalar_op_base::operator*" compiles
|
// "using special_scalar_op_base::operator*" compiles
|
||||||
void operator*() const;
|
void operator*() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived,typename Scalar,typename OtherScalar>
|
template<typename Derived,typename Scalar,typename OtherScalar, typename BaseType>
|
||||||
struct special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCoeffsBase<Derived>
|
struct special_scalar_op_base<Derived,Scalar,OtherScalar,BaseType,true> : public BaseType
|
||||||
{
|
{
|
||||||
const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
|
const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
|
||||||
operator*(const OtherScalar& scalar) const
|
operator*(const OtherScalar& scalar) const
|
||||||
|
|||||||
@@ -234,6 +234,12 @@ template<typename _MatrixType> class ComplexEigenSolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
EigenvectorType m_eivec;
|
EigenvectorType m_eivec;
|
||||||
EigenvalueType m_eivalues;
|
EigenvalueType m_eivalues;
|
||||||
ComplexSchur<MatrixType> m_schur;
|
ComplexSchur<MatrixType> m_schur;
|
||||||
@@ -251,6 +257,8 @@ template<typename MatrixType>
|
|||||||
ComplexEigenSolver<MatrixType>&
|
ComplexEigenSolver<MatrixType>&
|
||||||
ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
|
ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
// this code is inspired from Jampack
|
// this code is inspired from Jampack
|
||||||
eigen_assert(matrix.cols() == matrix.rows());
|
eigen_assert(matrix.cols() == matrix.rows());
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
|||||||
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
ComplexSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
typedef MatrixType::RealScalar RealScalar; \
|
||||||
typedef std::complex<RealScalar> ComplexScalar; \
|
typedef std::complex<RealScalar> ComplexScalar; \
|
||||||
\
|
\
|
||||||
|
|||||||
@@ -298,6 +298,13 @@ template<typename _MatrixType> class EigenSolver
|
|||||||
void doComputeEigenvectors();
|
void doComputeEigenvectors();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_eivec;
|
MatrixType m_eivec;
|
||||||
EigenvalueType m_eivalues;
|
EigenvalueType m_eivalues;
|
||||||
bool m_isInitialized;
|
bool m_isInitialized;
|
||||||
@@ -364,6 +371,8 @@ template<typename MatrixType>
|
|||||||
EigenSolver<MatrixType>&
|
EigenSolver<MatrixType>&
|
||||||
EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
|
EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
using std::abs;
|
using std::abs;
|
||||||
eigen_assert(matrix.cols() == matrix.rows());
|
eigen_assert(matrix.cols() == matrix.rows());
|
||||||
|
|||||||
@@ -263,6 +263,13 @@ template<typename _MatrixType> class GeneralizedEigenSolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_eivec;
|
MatrixType m_eivec;
|
||||||
ComplexVectorType m_alphas;
|
ComplexVectorType m_alphas;
|
||||||
VectorType m_betas;
|
VectorType m_betas;
|
||||||
@@ -290,6 +297,8 @@ template<typename MatrixType>
|
|||||||
GeneralizedEigenSolver<MatrixType>&
|
GeneralizedEigenSolver<MatrixType>&
|
||||||
GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
|
GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
using std::abs;
|
using std::abs;
|
||||||
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
|
eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
|
||||||
@@ -318,13 +327,33 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Scalar p = Scalar(0.5) * (m_matS.coeff(i, i) - m_matS.coeff(i+1, i+1));
|
// We need to extract the generalized eigenvalues of the pair of a general 2x2 block S and a triangular 2x2 block T
|
||||||
Scalar z = sqrt(abs(p * p + m_matS.coeff(i+1, i) * m_matS.coeff(i, i+1)));
|
// From the eigen decomposition of T = U * E * U^-1,
|
||||||
m_alphas.coeffRef(i) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, z);
|
// we can extract the eigenvalues of (U^-1 * S * U) / E
|
||||||
m_alphas.coeffRef(i+1) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, -z);
|
// Here, we can take advantage that E = diag(T), and U = [ 1 T_01 ; 0 T_11-T_00], and U^-1 = [1 -T_11/(T_11-T_00) ; 0 1/(T_11-T_00)].
|
||||||
|
// Then taking beta=T_00*T_11*(T_11-T_00), we can avoid any division, and alpha is the eigenvalues of A = (U^-1 * S * U) * diag(T_11,T_00) * (T_11-T_00):
|
||||||
|
|
||||||
|
// T = [a b ; 0 c]
|
||||||
|
// S = [e f ; g h]
|
||||||
|
RealScalar a = m_realQZ.matrixT().coeff(i, i), b = m_realQZ.matrixT().coeff(i, i+1), c = m_realQZ.matrixT().coeff(i+1, i+1);
|
||||||
|
RealScalar e = m_matS.coeff(i, i), f = m_matS.coeff(i, i+1), g = m_matS.coeff(i+1, i), h = m_matS.coeff(i+1, i+1);
|
||||||
|
RealScalar d = c-a;
|
||||||
|
RealScalar gb = g*b;
|
||||||
|
Matrix<RealScalar,2,2> A;
|
||||||
|
A << (e*d-gb)*c, ((e*b+f*d-h*b)*d-gb*b)*a,
|
||||||
|
g*c , (gb+h*d)*a;
|
||||||
|
|
||||||
|
// NOTE, we could also compute the SVD of T's block during the QZ factorization so that the respective T block is guaranteed to be diagonal,
|
||||||
|
// and then we could directly apply the formula below (while taking care of scaling S columns by T11,T00):
|
||||||
|
|
||||||
|
Scalar p = Scalar(0.5) * (A.coeff(i, i) - A.coeff(i+1, i+1));
|
||||||
|
Scalar z = sqrt(abs(p * p + A.coeff(i+1, i) * A.coeff(i, i+1)));
|
||||||
|
m_alphas.coeffRef(i) = ComplexScalar(A.coeff(i+1, i+1) + p, z);
|
||||||
|
m_alphas.coeffRef(i+1) = ComplexScalar(A.coeff(i+1, i+1) + p, -z);
|
||||||
|
|
||||||
|
m_betas.coeffRef(i) =
|
||||||
|
m_betas.coeffRef(i+1) = a*c*d;
|
||||||
|
|
||||||
m_betas.coeffRef(i) = m_realQZ.matrixT().coeff(i,i);
|
|
||||||
m_betas.coeffRef(i+1) = m_realQZ.matrixT().coeff(i,i);
|
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,10 +240,10 @@ namespace Eigen {
|
|||||||
m_S.coeffRef(i,j) = Scalar(0.0);
|
m_S.coeffRef(i,j) = Scalar(0.0);
|
||||||
m_S.rightCols(dim-j-1).applyOnTheLeft(i-1,i,G.adjoint());
|
m_S.rightCols(dim-j-1).applyOnTheLeft(i-1,i,G.adjoint());
|
||||||
m_T.rightCols(dim-i+1).applyOnTheLeft(i-1,i,G.adjoint());
|
m_T.rightCols(dim-i+1).applyOnTheLeft(i-1,i,G.adjoint());
|
||||||
|
// update Q
|
||||||
|
if (m_computeQZ)
|
||||||
|
m_Q.applyOnTheRight(i-1,i,G);
|
||||||
}
|
}
|
||||||
// update Q
|
|
||||||
if (m_computeQZ)
|
|
||||||
m_Q.applyOnTheRight(i-1,i,G);
|
|
||||||
// kill T(i,i-1)
|
// kill T(i,i-1)
|
||||||
if(m_T.coeff(i,i-1)!=Scalar(0))
|
if(m_T.coeff(i,i-1)!=Scalar(0))
|
||||||
{
|
{
|
||||||
@@ -251,10 +251,10 @@ namespace Eigen {
|
|||||||
m_T.coeffRef(i,i-1) = Scalar(0.0);
|
m_T.coeffRef(i,i-1) = Scalar(0.0);
|
||||||
m_S.applyOnTheRight(i,i-1,G);
|
m_S.applyOnTheRight(i,i-1,G);
|
||||||
m_T.topRows(i).applyOnTheRight(i,i-1,G);
|
m_T.topRows(i).applyOnTheRight(i,i-1,G);
|
||||||
|
// update Z
|
||||||
|
if (m_computeQZ)
|
||||||
|
m_Z.applyOnTheLeft(i,i-1,G.adjoint());
|
||||||
}
|
}
|
||||||
// update Z
|
|
||||||
if (m_computeQZ)
|
|
||||||
m_Z.applyOnTheLeft(i,i-1,G.adjoint());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ namespace Eigen {
|
|||||||
using std::abs;
|
using std::abs;
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
const Index dim=m_S.cols();
|
const Index dim=m_S.cols();
|
||||||
if (abs(m_S.coeff(i+1,i)==Scalar(0)))
|
if (abs(m_S.coeff(i+1,i))==Scalar(0))
|
||||||
return;
|
return;
|
||||||
Index z = findSmallDiagEntry(i,i+1);
|
Index z = findSmallDiagEntry(i,i+1);
|
||||||
if (z==i-1)
|
if (z==i-1)
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ template<typename _MatrixType> class RealSchur
|
|||||||
typedef Matrix<Scalar,3,1> Vector3s;
|
typedef Matrix<Scalar,3,1> Vector3s;
|
||||||
|
|
||||||
Scalar computeNormOfT();
|
Scalar computeNormOfT();
|
||||||
Index findSmallSubdiagEntry(Index iu, const Scalar& norm);
|
Index findSmallSubdiagEntry(Index iu);
|
||||||
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
|
void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift);
|
||||||
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
|
void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo);
|
||||||
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
|
void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector);
|
||||||
@@ -286,7 +286,7 @@ RealSchur<MatrixType>& RealSchur<MatrixType>::computeFromHessenberg(const HessMa
|
|||||||
{
|
{
|
||||||
while (iu >= 0)
|
while (iu >= 0)
|
||||||
{
|
{
|
||||||
Index il = findSmallSubdiagEntry(iu, norm);
|
Index il = findSmallSubdiagEntry(iu);
|
||||||
|
|
||||||
// Check for convergence
|
// Check for convergence
|
||||||
if (il == iu) // One root found
|
if (il == iu) // One root found
|
||||||
@@ -343,16 +343,14 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
|
|||||||
|
|
||||||
/** \internal Look for single small sub-diagonal element and returns its index */
|
/** \internal Look for single small sub-diagonal element and returns its index */
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, const Scalar& norm)
|
inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu)
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
Index res = iu;
|
Index res = iu;
|
||||||
while (res > 0)
|
while (res > 0)
|
||||||
{
|
{
|
||||||
Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res));
|
Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res));
|
||||||
if (s == 0.0)
|
if (abs(m_matT.coeff(res,res-1)) <= NumTraits<Scalar>::epsilon() * s)
|
||||||
s = norm;
|
|
||||||
if (abs(m_matT.coeff(res,res-1)) < NumTraits<Scalar>::epsilon() * s)
|
|
||||||
break;
|
break;
|
||||||
res--;
|
res--;
|
||||||
}
|
}
|
||||||
@@ -457,9 +455,7 @@ inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const V
|
|||||||
const Scalar lhs = m_matT.coeff(im,im-1) * (abs(v.coeff(1)) + abs(v.coeff(2)));
|
const Scalar lhs = m_matT.coeff(im,im-1) * (abs(v.coeff(1)) + abs(v.coeff(2)));
|
||||||
const Scalar rhs = v.coeff(0) * (abs(m_matT.coeff(im-1,im-1)) + abs(Tmm) + abs(m_matT.coeff(im+1,im+1)));
|
const Scalar rhs = v.coeff(0) * (abs(m_matT.coeff(im-1,im-1)) + abs(Tmm) + abs(m_matT.coeff(im+1,im+1)));
|
||||||
if (abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
|
if (abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ template<> inline \
|
|||||||
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >& \
|
||||||
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
RealSchur<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW>& matrix, bool computeU) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> MatrixType; \
|
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
|
||||||
\
|
|
||||||
eigen_assert(matrix.cols() == matrix.rows()); \
|
eigen_assert(matrix.cols() == matrix.rows()); \
|
||||||
\
|
\
|
||||||
lapack_int n = matrix.cols(), sdim, info; \
|
lapack_int n = matrix.cols(), sdim, info; \
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
/** \brief Scalar type for matrices of type \p _MatrixType. */
|
/** \brief Scalar type for matrices of type \p _MatrixType. */
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
|
typedef Matrix<Scalar,Size,Size,ColMajor,MaxColsAtCompileTime,MaxColsAtCompileTime> EigenvectorsType;
|
||||||
|
|
||||||
/** \brief Real scalar type for \p _MatrixType.
|
/** \brief Real scalar type for \p _MatrixType.
|
||||||
*
|
*
|
||||||
@@ -225,7 +227,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
*
|
*
|
||||||
* \sa eigenvalues()
|
* \sa eigenvalues()
|
||||||
*/
|
*/
|
||||||
const MatrixType& eigenvectors() const
|
const EigenvectorsType& eigenvectors() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
|
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
|
||||||
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
|
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
|
||||||
@@ -351,7 +353,12 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
#endif // EIGEN2_SUPPORT
|
#endif // EIGEN2_SUPPORT
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixType m_eivec;
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
EigenvectorsType m_eivec;
|
||||||
RealVectorType m_eivalues;
|
RealVectorType m_eivalues;
|
||||||
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
||||||
ComputationInfo m_info;
|
ComputationInfo m_info;
|
||||||
@@ -376,7 +383,7 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
* "implicit symmetric QR step with Wilkinson shift"
|
* "implicit symmetric QR step with Wilkinson shift"
|
||||||
*/
|
*/
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
|
template<typename RealScalar, typename Scalar, typename Index>
|
||||||
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
|
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,6 +391,8 @@ template<typename MatrixType>
|
|||||||
SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
||||||
::compute(const MatrixType& matrix, int options)
|
::compute(const MatrixType& matrix, int options)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::abs;
|
using std::abs;
|
||||||
eigen_assert(matrix.cols() == matrix.rows());
|
eigen_assert(matrix.cols() == matrix.rows());
|
||||||
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
||||||
@@ -406,7 +415,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
|
|
||||||
// declare some aliases
|
// declare some aliases
|
||||||
RealVectorType& diag = m_eivalues;
|
RealVectorType& diag = m_eivalues;
|
||||||
MatrixType& mat = m_eivec;
|
EigenvectorsType& mat = m_eivec;
|
||||||
|
|
||||||
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
mat = matrix.template triangularView<Lower>();
|
mat = matrix.template triangularView<Lower>();
|
||||||
@@ -442,7 +451,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
while (start>0 && m_subdiag[start-1]!=0)
|
while (start>0 && m_subdiag[start-1]!=0)
|
||||||
start--;
|
start--;
|
||||||
|
|
||||||
internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
|
internal::tridiagonal_qr_step(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter <= m_maxIterations * n)
|
if (iter <= m_maxIterations * n)
|
||||||
@@ -490,7 +499,13 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
typedef typename SolverType::MatrixType MatrixType;
|
typedef typename SolverType::MatrixType MatrixType;
|
||||||
typedef typename SolverType::RealVectorType VectorType;
|
typedef typename SolverType::RealVectorType VectorType;
|
||||||
typedef typename SolverType::Scalar Scalar;
|
typedef typename SolverType::Scalar Scalar;
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef typename SolverType::EigenvectorsType EigenvectorsType;
|
||||||
|
|
||||||
|
/** \internal
|
||||||
|
* Computes the roots of the characteristic polynomial of \a m.
|
||||||
|
* For numerical stability m.trace() should be near zero and to avoid over- or underflow m should be normalized.
|
||||||
|
*/
|
||||||
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
@@ -510,158 +525,123 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
// Construct the parameters used in classifying the roots of the equation
|
// Construct the parameters used in classifying the roots of the equation
|
||||||
// and in solving the equation for the roots in closed form.
|
// and in solving the equation for the roots in closed form.
|
||||||
Scalar c2_over_3 = c2*s_inv3;
|
Scalar c2_over_3 = c2*s_inv3;
|
||||||
Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
|
Scalar a_over_3 = (c2*c2_over_3 - c1)*s_inv3;
|
||||||
if (a_over_3 > Scalar(0))
|
if(a_over_3<Scalar(0))
|
||||||
a_over_3 = Scalar(0);
|
a_over_3 = Scalar(0);
|
||||||
|
|
||||||
Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
|
Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
|
||||||
|
|
||||||
Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
|
Scalar q = a_over_3*a_over_3*a_over_3 - half_b*half_b;
|
||||||
if (q > Scalar(0))
|
if(q<Scalar(0))
|
||||||
q = Scalar(0);
|
q = Scalar(0);
|
||||||
|
|
||||||
// Compute the eigenvalues by solving for the roots of the polynomial.
|
// Compute the eigenvalues by solving for the roots of the polynomial.
|
||||||
Scalar rho = sqrt(-a_over_3);
|
Scalar rho = sqrt(a_over_3);
|
||||||
Scalar theta = atan2(sqrt(-q),half_b)*s_inv3;
|
Scalar theta = atan2(sqrt(q),half_b)*s_inv3; // since sqrt(q) > 0, atan2 is in [0, pi] and theta is in [0, pi/3]
|
||||||
Scalar cos_theta = cos(theta);
|
Scalar cos_theta = cos(theta);
|
||||||
Scalar sin_theta = sin(theta);
|
Scalar sin_theta = sin(theta);
|
||||||
roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
|
// roots are already sorted, since cos is monotonically decreasing on [0, pi]
|
||||||
roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
|
roots(0) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta); // == 2*rho*cos(theta+2pi/3)
|
||||||
roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);
|
roots(1) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta); // == 2*rho*cos(theta+ pi/3)
|
||||||
|
roots(2) = c2_over_3 + Scalar(2)*rho*cos_theta;
|
||||||
// Sort in increasing order.
|
|
||||||
if (roots(0) >= roots(1))
|
|
||||||
std::swap(roots(0),roots(1));
|
|
||||||
if (roots(1) >= roots(2))
|
|
||||||
{
|
|
||||||
std::swap(roots(1),roots(2));
|
|
||||||
if (roots(0) >= roots(1))
|
|
||||||
std::swap(roots(0),roots(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool extract_kernel(MatrixType& mat, Ref<VectorType> res, Ref<VectorType> representative)
|
||||||
|
{
|
||||||
|
using std::abs;
|
||||||
|
Index i0;
|
||||||
|
// Find non-zero column i0 (by construction, there must exist a non zero coefficient on the diagonal):
|
||||||
|
mat.diagonal().cwiseAbs().maxCoeff(&i0);
|
||||||
|
// mat.col(i0) is a good candidate for an orthogonal vector to the current eigenvector,
|
||||||
|
// so let's save it:
|
||||||
|
representative = mat.col(i0);
|
||||||
|
Scalar n0, n1;
|
||||||
|
VectorType c0, c1;
|
||||||
|
n0 = (c0 = representative.cross(mat.col((i0+1)%3))).squaredNorm();
|
||||||
|
n1 = (c1 = representative.cross(mat.col((i0+2)%3))).squaredNorm();
|
||||||
|
if(n0>n1) res = c0/std::sqrt(n0);
|
||||||
|
else res = c1/std::sqrt(n1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void run(SolverType& solver, const MatrixType& mat, int options)
|
static inline void run(SolverType& solver, const MatrixType& mat, int options)
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
|
||||||
eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
|
eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
|
||||||
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
||||||
&& (options&EigVecMask)!=EigVecMask
|
&& (options&EigVecMask)!=EigVecMask
|
||||||
&& "invalid option parameter");
|
&& "invalid option parameter");
|
||||||
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
||||||
|
|
||||||
MatrixType& eivecs = solver.m_eivec;
|
EigenvectorsType& eivecs = solver.m_eivec;
|
||||||
VectorType& eivals = solver.m_eivalues;
|
VectorType& eivals = solver.m_eivalues;
|
||||||
|
|
||||||
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// Shift the matrix to the mean eigenvalue and map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
Scalar scale = mat.cwiseAbs().maxCoeff();
|
Scalar shift = mat.trace() / Scalar(3);
|
||||||
MatrixType scaledMat = mat / scale;
|
// TODO Avoid this copy. Currently it is necessary to suppress bogus values when determining maxCoeff and for computing the eigenvectors later
|
||||||
|
MatrixType scaledMat = mat.template selfadjointView<Lower>();
|
||||||
|
scaledMat.diagonal().array() -= shift;
|
||||||
|
Scalar scale = scaledMat.cwiseAbs().maxCoeff();
|
||||||
|
if(scale > 0) scaledMat /= scale; // TODO for scale==0 we could save the remaining operations
|
||||||
|
|
||||||
// compute the eigenvalues
|
// compute the eigenvalues
|
||||||
computeRoots(scaledMat,eivals);
|
computeRoots(scaledMat,eivals);
|
||||||
|
|
||||||
// compute the eigen vectors
|
// compute the eigenvectors
|
||||||
if(computeEigenvectors)
|
if(computeEigenvectors)
|
||||||
{
|
{
|
||||||
Scalar safeNorm2 = Eigen::NumTraits<Scalar>::epsilon();
|
|
||||||
if((eivals(2)-eivals(0))<=Eigen::NumTraits<Scalar>::epsilon())
|
if((eivals(2)-eivals(0))<=Eigen::NumTraits<Scalar>::epsilon())
|
||||||
{
|
{
|
||||||
|
// All three eigenvalues are numerically the same
|
||||||
eivecs.setIdentity();
|
eivecs.setIdentity();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scaledMat = scaledMat.template selfadjointView<Lower>();
|
|
||||||
MatrixType tmp;
|
MatrixType tmp;
|
||||||
tmp = scaledMat;
|
tmp = scaledMat;
|
||||||
|
|
||||||
|
// Compute the eigenvector of the most distinct eigenvalue
|
||||||
Scalar d0 = eivals(2) - eivals(1);
|
Scalar d0 = eivals(2) - eivals(1);
|
||||||
Scalar d1 = eivals(1) - eivals(0);
|
Scalar d1 = eivals(1) - eivals(0);
|
||||||
int k = d0 > d1 ? 2 : 0;
|
Index k(0), l(2);
|
||||||
d0 = d0 > d1 ? d0 : d1;
|
if(d0 > d1)
|
||||||
|
|
||||||
tmp.diagonal().array () -= eivals(k);
|
|
||||||
VectorType cross;
|
|
||||||
Scalar n;
|
|
||||||
n = (cross = tmp.row(0).cross(tmp.row(1))).squaredNorm();
|
|
||||||
|
|
||||||
if(n>safeNorm2)
|
|
||||||
{
|
{
|
||||||
eivecs.col(k) = cross / sqrt(n);
|
std::swap(k,l);
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the eigenvector of index k
|
||||||
|
{
|
||||||
|
tmp.diagonal().array () -= eivals(k);
|
||||||
|
// By construction, 'tmp' is of rank 2, and its kernel corresponds to the respective eigenvector.
|
||||||
|
extract_kernel(tmp, eivecs.col(k), eivecs.col(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute eigenvector of index l
|
||||||
|
if(d0<=2*Eigen::NumTraits<Scalar>::epsilon()*d1)
|
||||||
|
{
|
||||||
|
// If d0 is too small, then the two other eigenvalues are numerically the same,
|
||||||
|
// and thus we only have to ortho-normalize the near orthogonal vector we saved above.
|
||||||
|
eivecs.col(l) -= eivecs.col(k).dot(eivecs.col(l))*eivecs.col(l);
|
||||||
|
eivecs.col(l).normalize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm();
|
tmp = scaledMat;
|
||||||
|
tmp.diagonal().array () -= eivals(l);
|
||||||
|
|
||||||
if(n>safeNorm2)
|
VectorType dummy;
|
||||||
{
|
extract_kernel(tmp, eivecs.col(l), dummy);
|
||||||
eivecs.col(k) = cross / sqrt(n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = (cross = tmp.row(1).cross(tmp.row(2))).squaredNorm();
|
|
||||||
|
|
||||||
if(n>safeNorm2)
|
|
||||||
{
|
|
||||||
eivecs.col(k) = cross / sqrt(n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the input matrix and/or the eigenvaues probably contains some inf/NaN,
|
|
||||||
// => exit
|
|
||||||
// scale back to the original size.
|
|
||||||
eivals *= scale;
|
|
||||||
|
|
||||||
solver.m_info = NumericalIssue;
|
|
||||||
solver.m_isInitialized = true;
|
|
||||||
solver.m_eigenvectorsOk = computeEigenvectors;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = scaledMat;
|
// Compute last eigenvector from the other two
|
||||||
tmp.diagonal().array() -= eivals(1);
|
eivecs.col(1) = eivecs.col(2).cross(eivecs.col(0)).normalized();
|
||||||
|
|
||||||
if(d0<=Eigen::NumTraits<Scalar>::epsilon())
|
|
||||||
{
|
|
||||||
eivecs.col(1) = eivecs.col(k).unitOrthogonal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = (cross = eivecs.col(k).cross(tmp.row(0))).squaredNorm();
|
|
||||||
if(n>safeNorm2)
|
|
||||||
{
|
|
||||||
eivecs.col(1) = cross / sqrt(n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = (cross = eivecs.col(k).cross(tmp.row(1))).squaredNorm();
|
|
||||||
if(n>safeNorm2)
|
|
||||||
eivecs.col(1) = cross / sqrt(n);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = (cross = eivecs.col(k).cross(tmp.row(2))).squaredNorm();
|
|
||||||
if(n>safeNorm2)
|
|
||||||
eivecs.col(1) = cross / sqrt(n);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we should never reach this point,
|
|
||||||
// if so the last two eigenvalues are likely to be very close to each other
|
|
||||||
eivecs.col(1) = eivecs.col(k).unitOrthogonal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure that eivecs[1] is orthogonal to eivecs[2]
|
|
||||||
// FIXME: this step should not be needed
|
|
||||||
Scalar d = eivecs.col(1).dot(eivecs.col(k));
|
|
||||||
eivecs.col(1) = (eivecs.col(1) - d * eivecs.col(k)).normalized();
|
|
||||||
}
|
|
||||||
|
|
||||||
eivecs.col(k==2 ? 0 : 2) = eivecs.col(k).cross(eivecs.col(1)).normalized();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rescale back to the original size.
|
// Rescale back to the original size.
|
||||||
eivals *= scale;
|
eivals *= scale;
|
||||||
|
eivals.array() += shift;
|
||||||
|
|
||||||
solver.m_info = Success;
|
solver.m_info = Success;
|
||||||
solver.m_isInitialized = true;
|
solver.m_isInitialized = true;
|
||||||
@@ -675,11 +655,12 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
typedef typename SolverType::MatrixType MatrixType;
|
typedef typename SolverType::MatrixType MatrixType;
|
||||||
typedef typename SolverType::RealVectorType VectorType;
|
typedef typename SolverType::RealVectorType VectorType;
|
||||||
typedef typename SolverType::Scalar Scalar;
|
typedef typename SolverType::Scalar Scalar;
|
||||||
|
typedef typename SolverType::EigenvectorsType EigenvectorsType;
|
||||||
|
|
||||||
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
static inline void computeRoots(const MatrixType& m, VectorType& roots)
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0));
|
const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*numext::abs2(m(1,0)));
|
||||||
const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
|
const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
|
||||||
roots(0) = t1 - t0;
|
roots(0) = t1 - t0;
|
||||||
roots(1) = t1 + t0;
|
roots(1) = t1 + t0;
|
||||||
@@ -688,13 +669,15 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
static inline void run(SolverType& solver, const MatrixType& mat, int options)
|
static inline void run(SolverType& solver, const MatrixType& mat, int options)
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
|
using std::abs;
|
||||||
|
|
||||||
eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
|
eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
|
||||||
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
eigen_assert((options&~(EigVecMask|GenEigMask))==0
|
||||||
&& (options&EigVecMask)!=EigVecMask
|
&& (options&EigVecMask)!=EigVecMask
|
||||||
&& "invalid option parameter");
|
&& "invalid option parameter");
|
||||||
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
|
||||||
|
|
||||||
MatrixType& eivecs = solver.m_eivec;
|
EigenvectorsType& eivecs = solver.m_eivec;
|
||||||
VectorType& eivals = solver.m_eivalues;
|
VectorType& eivals = solver.m_eivalues;
|
||||||
|
|
||||||
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
// map the matrix coefficients to [-1:1] to avoid over- and underflow.
|
||||||
@@ -708,22 +691,29 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
// compute the eigen vectors
|
// compute the eigen vectors
|
||||||
if(computeEigenvectors)
|
if(computeEigenvectors)
|
||||||
{
|
{
|
||||||
scaledMat.diagonal().array () -= eivals(1);
|
if((eivals(1)-eivals(0))<=abs(eivals(1))*Eigen::NumTraits<Scalar>::epsilon())
|
||||||
Scalar a2 = numext::abs2(scaledMat(0,0));
|
|
||||||
Scalar c2 = numext::abs2(scaledMat(1,1));
|
|
||||||
Scalar b2 = numext::abs2(scaledMat(1,0));
|
|
||||||
if(a2>c2)
|
|
||||||
{
|
{
|
||||||
eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
|
eivecs.setIdentity();
|
||||||
eivecs.col(1) /= sqrt(a2+b2);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
|
scaledMat.diagonal().array () -= eivals(1);
|
||||||
eivecs.col(1) /= sqrt(c2+b2);
|
Scalar a2 = numext::abs2(scaledMat(0,0));
|
||||||
}
|
Scalar c2 = numext::abs2(scaledMat(1,1));
|
||||||
|
Scalar b2 = numext::abs2(scaledMat(1,0));
|
||||||
|
if(a2>c2)
|
||||||
|
{
|
||||||
|
eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
|
||||||
|
eivecs.col(1) /= sqrt(a2+b2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
|
||||||
|
eivecs.col(1) /= sqrt(c2+b2);
|
||||||
|
}
|
||||||
|
|
||||||
eivecs.col(0) << eivecs.col(1).unitOrthogonal();
|
eivecs.col(0) << eivecs.col(1).unitOrthogonal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rescale back to the original size.
|
// Rescale back to the original size.
|
||||||
@@ -746,7 +736,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
|
template<typename RealScalar, typename Scalar, typename Index>
|
||||||
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
|
static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
@@ -798,8 +788,7 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
|
|||||||
// apply the givens rotation to the unit matrix Q = Q * G
|
// apply the givens rotation to the unit matrix Q = Q * G
|
||||||
if (matrixQ)
|
if (matrixQ)
|
||||||
{
|
{
|
||||||
// FIXME if StorageOrder == RowMajor this operation is not very efficient
|
Map<Matrix<Scalar,Dynamic,Dynamic,ColMajor> > q(matrixQ,n,n);
|
||||||
Map<Matrix<Scalar,Dynamic,Dynamic,StorageOrder> > q(matrixQ,n,n);
|
|
||||||
q.applyOnTheRight(k,k+1,rot);
|
q.applyOnTheRight(k,k+1,rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,10 +367,10 @@ void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
|
|||||||
hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
|
hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
|
||||||
* (conj(h) * matA.col(i).tail(remainingSize)));
|
* (conj(h) * matA.col(i).tail(remainingSize)));
|
||||||
|
|
||||||
hCoeffs.tail(n-i-1) += (conj(h)*Scalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
|
hCoeffs.tail(n-i-1) += (conj(h)*RealScalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
|
||||||
|
|
||||||
matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
|
matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
|
||||||
.rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), -1);
|
.rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
|
||||||
|
|
||||||
matA.col(i).coeffRef(i+1) = beta;
|
matA.col(i).coeffRef(i+1) = beta;
|
||||||
hCoeffs.coeffRef(i) = h;
|
hCoeffs.coeffRef(i) = h;
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ namespace Eigen {
|
|||||||
*
|
*
|
||||||
* \brief An axis aligned box
|
* \brief An axis aligned box
|
||||||
*
|
*
|
||||||
* \param _Scalar the type of the scalar coefficients
|
* \tparam _Scalar the type of the scalar coefficients
|
||||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
* \tparam _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||||
*
|
*
|
||||||
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
||||||
|
* \warning The result of most methods is undefined when applied to an empty box. You can check for empty boxes using isEmpty().
|
||||||
|
* \sa alignedboxtypedefs
|
||||||
*/
|
*/
|
||||||
template <typename _Scalar, int _AmbientDim>
|
template <typename _Scalar, int _AmbientDim>
|
||||||
class AlignedBox
|
class AlignedBox
|
||||||
@@ -40,18 +42,21 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
/** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */
|
/** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */
|
||||||
enum CornerType
|
enum CornerType
|
||||||
{
|
{
|
||||||
/** 1D names */
|
/** 1D names @{ */
|
||||||
Min=0, Max=1,
|
Min=0, Max=1,
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/** Added names for 2D */
|
/** Identifier for 2D corner @{ */
|
||||||
BottomLeft=0, BottomRight=1,
|
BottomLeft=0, BottomRight=1,
|
||||||
TopLeft=2, TopRight=3,
|
TopLeft=2, TopRight=3,
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/** Added names for 3D */
|
/** Identifier for 3D corner @{ */
|
||||||
BottomLeftFloor=0, BottomRightFloor=1,
|
BottomLeftFloor=0, BottomRightFloor=1,
|
||||||
TopLeftFloor=2, TopRightFloor=3,
|
TopLeftFloor=2, TopRightFloor=3,
|
||||||
BottomLeftCeil=4, BottomRightCeil=5,
|
BottomLeftCeil=4, BottomRightCeil=5,
|
||||||
TopLeftCeil=6, TopRightCeil=7
|
TopLeftCeil=6, TopRightCeil=7
|
||||||
|
/** @} */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -63,34 +68,33 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
|
inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
|
||||||
{ setEmpty(); }
|
{ setEmpty(); }
|
||||||
|
|
||||||
/** Constructs a box with extremities \a _min and \a _max. */
|
/** Constructs a box with extremities \a _min and \a _max.
|
||||||
|
* \warning If either component of \a _min is larger than the same component of \a _max, the constructed box is empty. */
|
||||||
template<typename OtherVectorType1, typename OtherVectorType2>
|
template<typename OtherVectorType1, typename OtherVectorType2>
|
||||||
inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
|
inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
|
||||||
|
|
||||||
/** Constructs a box containing a single point \a p. */
|
/** Constructs a box containing a single point \a p. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline explicit AlignedBox(const MatrixBase<Derived>& a_p)
|
inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min)
|
||||||
{
|
{ }
|
||||||
typename internal::nested<Derived,2>::type p(a_p.derived());
|
|
||||||
m_min = p;
|
|
||||||
m_max = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
~AlignedBox() {}
|
~AlignedBox() {}
|
||||||
|
|
||||||
/** \returns the dimension in which the box holds */
|
/** \returns the dimension in which the box holds */
|
||||||
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
|
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
|
||||||
|
|
||||||
/** \deprecated use isEmpty */
|
/** \deprecated use isEmpty() */
|
||||||
inline bool isNull() const { return isEmpty(); }
|
inline bool isNull() const { return isEmpty(); }
|
||||||
|
|
||||||
/** \deprecated use setEmpty */
|
/** \deprecated use setEmpty() */
|
||||||
inline void setNull() { setEmpty(); }
|
inline void setNull() { setEmpty(); }
|
||||||
|
|
||||||
/** \returns true if the box is empty. */
|
/** \returns true if the box is empty.
|
||||||
|
* \sa setEmpty */
|
||||||
inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
|
inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
|
||||||
|
|
||||||
/** Makes \c *this an empty box. */
|
/** Makes \c *this an empty box.
|
||||||
|
* \sa isEmpty */
|
||||||
inline void setEmpty()
|
inline void setEmpty()
|
||||||
{
|
{
|
||||||
m_min.setConstant( ScalarTraits::highest() );
|
m_min.setConstant( ScalarTraits::highest() );
|
||||||
@@ -159,7 +163,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
* a uniform distribution */
|
* a uniform distribution */
|
||||||
inline VectorType sample() const
|
inline VectorType sample() const
|
||||||
{
|
{
|
||||||
VectorType r;
|
VectorType r(dim());
|
||||||
for(Index d=0; d<dim(); ++d)
|
for(Index d=0; d<dim(); ++d)
|
||||||
{
|
{
|
||||||
if(!ScalarTraits::IsInteger)
|
if(!ScalarTraits::IsInteger)
|
||||||
@@ -175,27 +179,34 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
|
|
||||||
/** \returns true if the point \a p is inside the box \c *this. */
|
/** \returns true if the point \a p is inside the box \c *this. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline bool contains(const MatrixBase<Derived>& a_p) const
|
inline bool contains(const MatrixBase<Derived>& p) const
|
||||||
{
|
{
|
||||||
typename internal::nested<Derived,2>::type p(a_p.derived());
|
typename internal::nested<Derived,2>::type p_n(p.derived());
|
||||||
return (m_min.array()<=p.array()).all() && (p.array()<=m_max.array()).all();
|
return (m_min.array()<=p_n.array()).all() && (p_n.array()<=m_max.array()).all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||||
inline bool contains(const AlignedBox& b) const
|
inline bool contains(const AlignedBox& b) const
|
||||||
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
|
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
|
||||||
|
|
||||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
/** \returns true if the box \a b is intersecting the box \c *this.
|
||||||
|
* \sa intersection, clamp */
|
||||||
|
inline bool intersects(const AlignedBox& b) const
|
||||||
|
{ return (m_min.array()<=(b.max)().array()).all() && ((b.min)().array()<=m_max.array()).all(); }
|
||||||
|
|
||||||
|
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this.
|
||||||
|
* \sa extend(const AlignedBox&) */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline AlignedBox& extend(const MatrixBase<Derived>& a_p)
|
inline AlignedBox& extend(const MatrixBase<Derived>& p)
|
||||||
{
|
{
|
||||||
typename internal::nested<Derived,2>::type p(a_p.derived());
|
typename internal::nested<Derived,2>::type p_n(p.derived());
|
||||||
m_min = m_min.cwiseMin(p);
|
m_min = m_min.cwiseMin(p_n);
|
||||||
m_max = m_max.cwiseMax(p);
|
m_max = m_max.cwiseMax(p_n);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this.
|
||||||
|
* \sa merged, extend(const MatrixBase&) */
|
||||||
inline AlignedBox& extend(const AlignedBox& b)
|
inline AlignedBox& extend(const AlignedBox& b)
|
||||||
{
|
{
|
||||||
m_min = m_min.cwiseMin(b.m_min);
|
m_min = m_min.cwiseMin(b.m_min);
|
||||||
@@ -203,7 +214,9 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
/** Clamps \c *this by the box \a b and returns a reference to \c *this.
|
||||||
|
* \note If the boxes don't intersect, the resulting box is empty.
|
||||||
|
* \sa intersection(), intersects() */
|
||||||
inline AlignedBox& clamp(const AlignedBox& b)
|
inline AlignedBox& clamp(const AlignedBox& b)
|
||||||
{
|
{
|
||||||
m_min = m_min.cwiseMax(b.m_min);
|
m_min = m_min.cwiseMax(b.m_min);
|
||||||
@@ -211,11 +224,15 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an AlignedBox that is the intersection of \a b and \c *this */
|
/** Returns an AlignedBox that is the intersection of \a b and \c *this
|
||||||
|
* \note If the boxes don't intersect, the resulting box is empty.
|
||||||
|
* \sa intersects(), clamp, contains() */
|
||||||
inline AlignedBox intersection(const AlignedBox& b) const
|
inline AlignedBox intersection(const AlignedBox& b) const
|
||||||
{return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); }
|
{return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); }
|
||||||
|
|
||||||
/** Returns an AlignedBox that is the union of \a b and \c *this */
|
/** Returns an AlignedBox that is the union of \a b and \c *this.
|
||||||
|
* \note Merging with an empty box may result in a box bigger than \c *this.
|
||||||
|
* \sa extend(const AlignedBox&) */
|
||||||
inline AlignedBox merged(const AlignedBox& b) const
|
inline AlignedBox merged(const AlignedBox& b) const
|
||||||
{ return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
|
{ return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
|
||||||
|
|
||||||
@@ -231,20 +248,20 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
|
|
||||||
/** \returns the squared distance between the point \a p and the box \c *this,
|
/** \returns the squared distance between the point \a p and the box \c *this,
|
||||||
* and zero if \a p is inside the box.
|
* and zero if \a p is inside the box.
|
||||||
* \sa exteriorDistance()
|
* \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&)
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& a_p) const;
|
inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& p) const;
|
||||||
|
|
||||||
/** \returns the squared distance between the boxes \a b and \c *this,
|
/** \returns the squared distance between the boxes \a b and \c *this,
|
||||||
* and zero if the boxes intersect.
|
* and zero if the boxes intersect.
|
||||||
* \sa exteriorDistance()
|
* \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&)
|
||||||
*/
|
*/
|
||||||
inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
|
inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
|
||||||
|
|
||||||
/** \returns the distance between the point \a p and the box \c *this,
|
/** \returns the distance between the point \a p and the box \c *this,
|
||||||
* and zero if \a p is inside the box.
|
* and zero if \a p is inside the box.
|
||||||
* \sa squaredExteriorDistance()
|
* \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
||||||
@@ -252,7 +269,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
|||||||
|
|
||||||
/** \returns the distance between the boxes \a b and \c *this,
|
/** \returns the distance between the boxes \a b and \c *this,
|
||||||
* and zero if the boxes intersect.
|
* and zero if the boxes intersect.
|
||||||
* \sa squaredExteriorDistance()
|
* \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
|
||||||
*/
|
*/
|
||||||
inline NonInteger exteriorDistance(const AlignedBox& b) const
|
inline NonInteger exteriorDistance(const AlignedBox& b) const
|
||||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
||||||
|
|||||||
@@ -83,10 +83,17 @@ public:
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||||
|
|
||||||
|
/** \returns the value of the rotation angle in radian */
|
||||||
Scalar angle() const { return m_angle; }
|
Scalar angle() const { return m_angle; }
|
||||||
|
/** \returns a read-write reference to the stored angle in radian */
|
||||||
Scalar& angle() { return m_angle; }
|
Scalar& angle() { return m_angle; }
|
||||||
|
|
||||||
|
/** \returns the rotation axis */
|
||||||
const Vector3& axis() const { return m_axis; }
|
const Vector3& axis() const { return m_axis; }
|
||||||
|
/** \returns a read-write reference to the stored rotation axis.
|
||||||
|
*
|
||||||
|
* \warning The rotation axis must remain a \b unit vector.
|
||||||
|
*/
|
||||||
Vector3& axis() { return m_axis; }
|
Vector3& axis() { return m_axis; }
|
||||||
|
|
||||||
/** Concatenates two rotations */
|
/** Concatenates two rotations */
|
||||||
@@ -131,7 +138,7 @@ public:
|
|||||||
m_angle = Scalar(other.angle());
|
m_angle = Scalar(other.angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); }
|
static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); }
|
||||||
|
|
||||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
@@ -165,8 +172,8 @@ AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived
|
|||||||
Scalar n2 = q.vec().squaredNorm();
|
Scalar n2 = q.vec().squaredNorm();
|
||||||
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
|
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
|
||||||
{
|
{
|
||||||
m_angle = 0;
|
m_angle = Scalar(0);
|
||||||
m_axis << 1, 0, 0;
|
m_axis << Scalar(1), Scalar(0), Scalar(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,11 +75,11 @@ template<typename MatrixType,int _Direction> class Homogeneous
|
|||||||
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
||||||
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
||||||
|
|
||||||
inline Scalar coeff(Index row, Index col) const
|
inline Scalar coeff(Index row, Index col=0) const
|
||||||
{
|
{
|
||||||
if( (int(Direction)==Vertical && row==m_matrix.rows())
|
if( (int(Direction)==Vertical && row==m_matrix.rows())
|
||||||
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
|
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
|
||||||
return 1;
|
return Scalar(1);
|
||||||
return m_matrix.coeff(row, col);
|
return m_matrix.coeff(row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
|
bool isApprox(const ParametrizedLine& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ public:
|
|||||||
/** \returns a quaternion representing an identity rotation
|
/** \returns a quaternion representing an identity rotation
|
||||||
* \sa MatrixBase::Identity()
|
* \sa MatrixBase::Identity()
|
||||||
*/
|
*/
|
||||||
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); }
|
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
|
||||||
|
|
||||||
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
||||||
*/
|
*/
|
||||||
inline QuaternionBase& setIdentity() { coeffs() << 0, 0, 0, 1; return *this; }
|
inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
|
||||||
|
|
||||||
/** \returns the squared norm of the quaternion's coefficients
|
/** \returns the squared norm of the quaternion's coefficients
|
||||||
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
||||||
@@ -161,7 +161,7 @@ public:
|
|||||||
{ return coeffs().isApprox(other.coeffs(), prec); }
|
{ return coeffs().isApprox(other.coeffs(), prec); }
|
||||||
|
|
||||||
/** return the result vector of \a v through the rotation*/
|
/** return the result vector of \a v through the rotation*/
|
||||||
EIGEN_STRONG_INLINE Vector3 _transformVector(Vector3 v) const;
|
EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
|
||||||
|
|
||||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||||
*
|
*
|
||||||
@@ -231,7 +231,7 @@ class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
|
|||||||
public:
|
public:
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
|
|
||||||
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
|
||||||
using Base::operator*=;
|
using Base::operator*=;
|
||||||
|
|
||||||
typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
|
typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
|
||||||
@@ -276,7 +276,7 @@ public:
|
|||||||
inline Coefficients& coeffs() { return m_coeffs;}
|
inline Coefficients& coeffs() { return m_coeffs;}
|
||||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||||
|
|
||||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(IsAligned)
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(IsAligned))
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Coefficients m_coeffs;
|
Coefficients m_coeffs;
|
||||||
@@ -341,7 +341,7 @@ class Map<const Quaternion<_Scalar>, _Options >
|
|||||||
public:
|
public:
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
||||||
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
|
||||||
using Base::operator*=;
|
using Base::operator*=;
|
||||||
|
|
||||||
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
||||||
@@ -378,7 +378,7 @@ class Map<Quaternion<_Scalar>, _Options >
|
|||||||
public:
|
public:
|
||||||
typedef _Scalar Scalar;
|
typedef _Scalar Scalar;
|
||||||
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
||||||
EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
|
||||||
using Base::operator*=;
|
using Base::operator*=;
|
||||||
|
|
||||||
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
||||||
@@ -461,7 +461,7 @@ EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const Quaterni
|
|||||||
*/
|
*/
|
||||||
template <class Derived>
|
template <class Derived>
|
||||||
EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
|
EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
|
||||||
QuaternionBase<Derived>::_transformVector(Vector3 v) const
|
QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
||||||
{
|
{
|
||||||
// Note that this algorithm comes from the optimization by hand
|
// Note that this algorithm comes from the optimization by hand
|
||||||
// of the conversion to a Matrix followed by a Matrix/Vector product.
|
// of the conversion to a Matrix followed by a Matrix/Vector product.
|
||||||
@@ -637,7 +637,7 @@ inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Der
|
|||||||
{
|
{
|
||||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||||
Scalar n2 = this->squaredNorm();
|
Scalar n2 = this->squaredNorm();
|
||||||
if (n2 > 0)
|
if (n2 > Scalar(0))
|
||||||
return Quaternion<Scalar>(conjugate().coeffs() / n2);
|
return Quaternion<Scalar>(conjugate().coeffs() / n2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -667,12 +667,10 @@ template <class OtherDerived>
|
|||||||
inline typename internal::traits<Derived>::Scalar
|
inline typename internal::traits<Derived>::Scalar
|
||||||
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
||||||
{
|
{
|
||||||
using std::acos;
|
using std::atan2;
|
||||||
using std::abs;
|
using std::abs;
|
||||||
Scalar d = abs(this->dot(other));
|
Quaternion<Scalar> d = (*this) * other.conjugate();
|
||||||
if (d>=Scalar(1))
|
return Scalar(2) * atan2( d.vec().norm(), abs(d.w()) );
|
||||||
return Scalar(0);
|
|
||||||
return Scalar(2) * acos(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -712,7 +710,7 @@ QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerive
|
|||||||
scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||||
scale1 = sin( ( t * theta) ) / sinTheta;
|
scale1 = sin( ( t * theta) ) / sinTheta;
|
||||||
}
|
}
|
||||||
if(d<0) scale1 = -scale1;
|
if(d<Scalar(0)) scale1 = -scale1;
|
||||||
|
|
||||||
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
||||||
explicit inline Rotation2D(const Scalar& a) : m_angle(a) {}
|
inline Rotation2D(const Scalar& a) : m_angle(a) {}
|
||||||
|
|
||||||
/** Default constructor wihtout initialization. The represented rotation is undefined. */
|
/** Default constructor wihtout initialization. The represented rotation is undefined. */
|
||||||
Rotation2D() {}
|
Rotation2D() {}
|
||||||
|
|||||||
@@ -102,15 +102,15 @@ template<int Mode> struct transform_make_affine;
|
|||||||
*
|
*
|
||||||
* However, unlike a plain matrix, the Transform class provides many features
|
* However, unlike a plain matrix, the Transform class provides many features
|
||||||
* simplifying both its assembly and usage. In particular, it can be composed
|
* simplifying both its assembly and usage. In particular, it can be composed
|
||||||
* with any other transformations (Transform,Translation,RotationBase,Matrix)
|
* with any other transformations (Transform,Translation,RotationBase,DiagonalMatrix)
|
||||||
* and can be directly used to transform implicit homogeneous vectors. All these
|
* and can be directly used to transform implicit homogeneous vectors. All these
|
||||||
* operations are handled via the operator*. For the composition of transformations,
|
* operations are handled via the operator*. For the composition of transformations,
|
||||||
* its principle consists to first convert the right/left hand sides of the product
|
* its principle consists to first convert the right/left hand sides of the product
|
||||||
* to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
|
* to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
|
||||||
* Of course, internally, operator* tries to perform the minimal number of operations
|
* Of course, internally, operator* tries to perform the minimal number of operations
|
||||||
* according to the nature of each terms. Likewise, when applying the transform
|
* according to the nature of each terms. Likewise, when applying the transform
|
||||||
* to non homogeneous vectors, the latters are automatically promoted to homogeneous
|
* to points, the latters are automatically promoted to homogeneous vectors
|
||||||
* one before doing the matrix product. The convertions to homogeneous representations
|
* before doing the matrix product. The conventions to homogeneous representations
|
||||||
* are performed as follow:
|
* are performed as follow:
|
||||||
*
|
*
|
||||||
* \b Translation t (Dim)x(1):
|
* \b Translation t (Dim)x(1):
|
||||||
@@ -124,7 +124,7 @@ template<int Mode> struct transform_make_affine;
|
|||||||
* R & 0\\
|
* R & 0\\
|
||||||
* 0\,...\,0 & 1
|
* 0\,...\,0 & 1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
*
|
*<!--
|
||||||
* \b Linear \b Matrix L (Dim)x(Dim):
|
* \b Linear \b Matrix L (Dim)x(Dim):
|
||||||
* \f$ \left( \begin{array}{cc}
|
* \f$ \left( \begin{array}{cc}
|
||||||
* L & 0\\
|
* L & 0\\
|
||||||
@@ -136,14 +136,20 @@ template<int Mode> struct transform_make_affine;
|
|||||||
* A\\
|
* A\\
|
||||||
* 0\,...\,0\,1
|
* 0\,...\,0\,1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
|
*-->
|
||||||
|
* \b Scaling \b DiagonalMatrix S (Dim)x(Dim):
|
||||||
|
* \f$ \left( \begin{array}{cc}
|
||||||
|
* S & 0\\
|
||||||
|
* 0\,...\,0 & 1
|
||||||
|
* \end{array} \right) \f$
|
||||||
*
|
*
|
||||||
* \b Column \b vector v (Dim)x(1):
|
* \b Column \b point v (Dim)x(1):
|
||||||
* \f$ \left( \begin{array}{c}
|
* \f$ \left( \begin{array}{c}
|
||||||
* v\\
|
* v\\
|
||||||
* 1
|
* 1
|
||||||
* \end{array} \right) \f$
|
* \end{array} \right) \f$
|
||||||
*
|
*
|
||||||
* \b Set \b of \b column \b vectors V1...Vn (Dim)x(n):
|
* \b Set \b of \b column \b points V1...Vn (Dim)x(n):
|
||||||
* \f$ \left( \begin{array}{ccc}
|
* \f$ \left( \begin{array}{ccc}
|
||||||
* v_1 & ... & v_n\\
|
* v_1 & ... & v_n\\
|
||||||
* 1 & ... & 1
|
* 1 & ... & 1
|
||||||
@@ -384,26 +390,39 @@ public:
|
|||||||
/** \returns a writable expression of the translation vector of the transformation */
|
/** \returns a writable expression of the translation vector of the transformation */
|
||||||
inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
|
||||||
|
|
||||||
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other
|
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other.
|
||||||
*
|
*
|
||||||
* The right hand side \a other might be either:
|
* The right-hand-side \a other can be either:
|
||||||
* \li a vector of size Dim,
|
|
||||||
* \li an homogeneous vector of size Dim+1,
|
* \li an homogeneous vector of size Dim+1,
|
||||||
* \li a set of vectors of size Dim x Dynamic,
|
* \li a set of homogeneous vectors of size Dim+1 x N,
|
||||||
* \li a set of homogeneous vectors of size Dim+1 x Dynamic,
|
|
||||||
* \li a linear transformation matrix of size Dim x Dim,
|
|
||||||
* \li an affine transformation matrix of size Dim x Dim+1,
|
|
||||||
* \li a transformation matrix of size Dim+1 x Dim+1.
|
* \li a transformation matrix of size Dim+1 x Dim+1.
|
||||||
|
*
|
||||||
|
* Moreover, if \c *this represents an affine transformation (i.e., Mode!=Projective), then \a other can also be:
|
||||||
|
* \li a point of size Dim (computes: \code this->linear() * other + this->translation()\endcode),
|
||||||
|
* \li a set of N points as a Dim x N matrix (computes: \code (this->linear() * other).colwise() + this->translation()\endcode),
|
||||||
|
*
|
||||||
|
* In all cases, the return type is a matrix or vector of same sizes as the right-hand-side \a other.
|
||||||
|
*
|
||||||
|
* If you want to interpret \a other as a linear or affine transformation, then first convert it to a Transform<> type,
|
||||||
|
* or do your own cooking.
|
||||||
|
*
|
||||||
|
* Finally, if you want to apply Affine transformations to vectors, then explicitly apply the linear part only:
|
||||||
|
* \code
|
||||||
|
* Affine3f A;
|
||||||
|
* Vector3f v1, v2;
|
||||||
|
* v2 = A.linear() * v1;
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
// note: this function is defined here because some compilers cannot find the respective declaration
|
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
|
EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject
|
||||||
operator * (const EigenBase<OtherDerived> &other) const
|
operator * (const EigenBase<OtherDerived> &other) const
|
||||||
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
{ return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
|
||||||
|
|
||||||
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
||||||
*
|
*
|
||||||
* The left hand side \a other might be either:
|
* The left hand side \a other can be either:
|
||||||
* \li a linear transformation matrix of size Dim x Dim,
|
* \li a linear transformation matrix of size Dim x Dim,
|
||||||
* \li an affine transformation matrix of size Dim x Dim+1,
|
* \li an affine transformation matrix of size Dim x Dim+1,
|
||||||
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
* \li a general transformation matrix of size Dim+1 x Dim+1.
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
* determined by \a prec.
|
* determined by \a prec.
|
||||||
*
|
*
|
||||||
* \sa MatrixBase::isApprox() */
|
* \sa MatrixBase::isApprox() */
|
||||||
bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
|
bool isApprox(const Translation& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,8 +75,9 @@ void MatrixBase<Derived>::makeHouseholder(
|
|||||||
|
|
||||||
RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
|
RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
|
||||||
Scalar c0 = coeff(0);
|
Scalar c0 = coeff(0);
|
||||||
|
const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
|
||||||
|
|
||||||
if(tailSqNorm == RealScalar(0) && numext::imag(c0)==RealScalar(0))
|
if(tailSqNorm <= tol && numext::abs2(numext::imag(c0))<=tol)
|
||||||
{
|
{
|
||||||
tau = RealScalar(0);
|
tau = RealScalar(0);
|
||||||
beta = numext::real(c0);
|
beta = numext::real(c0);
|
||||||
|
|||||||
@@ -237,8 +237,9 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
{
|
{
|
||||||
workspace.resize(rows());
|
workspace.resize(rows());
|
||||||
Index vecs = m_length;
|
Index vecs = m_length;
|
||||||
|
const typename Dest::Scalar *dst_data = internal::extract_data(dst);
|
||||||
if( internal::is_same<typename internal::remove_all<VectorsType>::type,Dest>::value
|
if( internal::is_same<typename internal::remove_all<VectorsType>::type,Dest>::value
|
||||||
&& internal::extract_data(dst) == internal::extract_data(m_vectors))
|
&& dst_data!=0 && dst_data == internal::extract_data(m_vectors))
|
||||||
{
|
{
|
||||||
// in-place
|
// in-place
|
||||||
dst.diagonal().setOnes();
|
dst.diagonal().setOnes();
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ class DiagonalPreconditioner
|
|||||||
{
|
{
|
||||||
typename MatType::InnerIterator it(mat,j);
|
typename MatType::InnerIterator it(mat,j);
|
||||||
while(it && it.index()!=j) ++it;
|
while(it && it.index()!=j) ++it;
|
||||||
if(it && it.index()==j)
|
if(it && it.index()==j && it.value()!=Scalar(0))
|
||||||
m_invdiag(j) = Scalar(1)/it.value();
|
m_invdiag(j) = Scalar(1)/it.value();
|
||||||
else
|
else
|
||||||
m_invdiag(j) = 0;
|
m_invdiag(j) = Scalar(1);
|
||||||
}
|
}
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -151,20 +151,7 @@ struct traits<BiCGSTAB<_MatrixType,_Preconditioner> >
|
|||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* By default the iterations start with x=0 as an initial guess of the solution.
|
* By default the iterations start with x=0 as an initial guess of the solution.
|
||||||
* One can control the start using the solveWithGuess() method. Here is a step by
|
* One can control the start using the solveWithGuess() method.
|
||||||
* step execution example starting with a random guess and printing the evolution
|
|
||||||
* of the estimated error:
|
|
||||||
* * \code
|
|
||||||
* x = VectorXd::Random(n);
|
|
||||||
* solver.setMaxIterations(1);
|
|
||||||
* int i = 0;
|
|
||||||
* do {
|
|
||||||
* x = solver.solveWithGuess(b,x);
|
|
||||||
* std::cout << i << " : " << solver.error() << std::endl;
|
|
||||||
* ++i;
|
|
||||||
* } while (solver.info()!=Success && i<100);
|
|
||||||
* \endcode
|
|
||||||
* Note that such a step by step excution is slightly slower.
|
|
||||||
*
|
*
|
||||||
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
||||||
*/
|
*/
|
||||||
@@ -199,7 +186,8 @@ public:
|
|||||||
* this class becomes invalid. Call compute() to update it with the new
|
* this class becomes invalid. Call compute() to update it with the new
|
||||||
* matrix A, or modify a copy of A.
|
* matrix A, or modify a copy of A.
|
||||||
*/
|
*/
|
||||||
BiCGSTAB(const MatrixType& A) : Base(A) {}
|
template<typename MatrixDerived>
|
||||||
|
explicit BiCGSTAB(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
|
||||||
|
|
||||||
~BiCGSTAB() {}
|
~BiCGSTAB() {}
|
||||||
|
|
||||||
|
|||||||
@@ -112,9 +112,9 @@ struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
|
|||||||
* This class allows to solve for A.x = b sparse linear problems using a conjugate gradient algorithm.
|
* This class allows to solve for A.x = b sparse linear problems using a conjugate gradient algorithm.
|
||||||
* The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or sparse.
|
* The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or sparse.
|
||||||
*
|
*
|
||||||
* \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
|
* \tparam _MatrixType the type of the matrix A, can be a dense or a sparse matrix.
|
||||||
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
|
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower,
|
||||||
* or Upper. Default is Lower.
|
* Upper, or Lower|Upper in which the full matrix entries will be considered. Default is Lower.
|
||||||
* \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
|
* \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
|
||||||
*
|
*
|
||||||
* The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
|
* The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
|
||||||
@@ -137,21 +137,10 @@ struct traits<ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> >
|
|||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* By default the iterations start with x=0 as an initial guess of the solution.
|
* By default the iterations start with x=0 as an initial guess of the solution.
|
||||||
* One can control the start using the solveWithGuess() method. Here is a step by
|
* One can control the start using the solveWithGuess() method.
|
||||||
* step execution example starting with a random guess and printing the evolution
|
|
||||||
* of the estimated error:
|
|
||||||
* * \code
|
|
||||||
* x = VectorXd::Random(n);
|
|
||||||
* cg.setMaxIterations(1);
|
|
||||||
* int i = 0;
|
|
||||||
* do {
|
|
||||||
* x = cg.solveWithGuess(b,x);
|
|
||||||
* std::cout << i << " : " << cg.error() << std::endl;
|
|
||||||
* ++i;
|
|
||||||
* } while (cg.info()!=Success && i<100);
|
|
||||||
* \endcode
|
|
||||||
* Note that such a step by step excution is slightly slower.
|
|
||||||
*
|
*
|
||||||
|
* ConjugateGradient can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink.
|
||||||
|
*
|
||||||
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
* \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
|
||||||
*/
|
*/
|
||||||
template< typename _MatrixType, int _UpLo, typename _Preconditioner>
|
template< typename _MatrixType, int _UpLo, typename _Preconditioner>
|
||||||
@@ -189,7 +178,8 @@ public:
|
|||||||
* this class becomes invalid. Call compute() to update it with the new
|
* this class becomes invalid. Call compute() to update it with the new
|
||||||
* matrix A, or modify a copy of A.
|
* matrix A, or modify a copy of A.
|
||||||
*/
|
*/
|
||||||
ConjugateGradient(const MatrixType& A) : Base(A) {}
|
template<typename MatrixDerived>
|
||||||
|
explicit ConjugateGradient(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
|
||||||
|
|
||||||
~ConjugateGradient() {}
|
~ConjugateGradient() {}
|
||||||
|
|
||||||
@@ -213,6 +203,10 @@ public:
|
|||||||
template<typename Rhs,typename Dest>
|
template<typename Rhs,typename Dest>
|
||||||
void _solveWithGuess(const Rhs& b, Dest& x) const
|
void _solveWithGuess(const Rhs& b, Dest& x) const
|
||||||
{
|
{
|
||||||
|
typedef typename internal::conditional<UpLo==(Lower|Upper),
|
||||||
|
const MatrixType&,
|
||||||
|
SparseSelfAdjointView<const MatrixType, UpLo>
|
||||||
|
>::type MatrixWrapperType;
|
||||||
m_iterations = Base::maxIterations();
|
m_iterations = Base::maxIterations();
|
||||||
m_error = Base::m_tolerance;
|
m_error = Base::m_tolerance;
|
||||||
|
|
||||||
@@ -222,8 +216,7 @@ public:
|
|||||||
m_error = Base::m_tolerance;
|
m_error = Base::m_tolerance;
|
||||||
|
|
||||||
typename Dest::ColXpr xj(x,j);
|
typename Dest::ColXpr xj(x,j);
|
||||||
internal::conjugate_gradient(mp_matrix->template selfadjointView<UpLo>(), b.col(j), xj,
|
internal::conjugate_gradient(MatrixWrapperType(*mp_matrix), b.col(j), xj, Base::m_preconditioner, m_iterations, m_error);
|
||||||
Base::m_preconditioner, m_iterations, m_error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
@@ -234,7 +227,7 @@ public:
|
|||||||
template<typename Rhs,typename Dest>
|
template<typename Rhs,typename Dest>
|
||||||
void _solve(const Rhs& b, Dest& x) const
|
void _solve(const Rhs& b, Dest& x) const
|
||||||
{
|
{
|
||||||
x.setOnes();
|
x.setZero();
|
||||||
_solveWithGuess(b,x);
|
_solveWithGuess(b,x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ class IncompleteLUT : internal::noncopyable
|
|||||||
{
|
{
|
||||||
analyzePattern(amat);
|
analyzePattern(amat);
|
||||||
factorize(amat);
|
factorize(amat);
|
||||||
m_isInitialized = m_factorizationIsOk;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +159,7 @@ class IncompleteLUT : internal::noncopyable
|
|||||||
template<typename Rhs, typename Dest>
|
template<typename Rhs, typename Dest>
|
||||||
void _solve(const Rhs& b, Dest& x) const
|
void _solve(const Rhs& b, Dest& x) const
|
||||||
{
|
{
|
||||||
x = m_Pinv * b;
|
x = m_Pinv * b;
|
||||||
x = m_lu.template triangularView<UnitLower>().solve(x);
|
x = m_lu.template triangularView<UnitLower>().solve(x);
|
||||||
x = m_lu.template triangularView<Upper>().solve(x);
|
x = m_lu.template triangularView<Upper>().solve(x);
|
||||||
x = m_P * x;
|
x = m_P * x;
|
||||||
@@ -223,18 +222,29 @@ template<typename _MatrixType>
|
|||||||
void IncompleteLUT<Scalar>::analyzePattern(const _MatrixType& amat)
|
void IncompleteLUT<Scalar>::analyzePattern(const _MatrixType& amat)
|
||||||
{
|
{
|
||||||
// Compute the Fill-reducing permutation
|
// Compute the Fill-reducing permutation
|
||||||
|
// Since ILUT does not perform any numerical pivoting,
|
||||||
|
// it is highly preferable to keep the diagonal through symmetric permutations.
|
||||||
|
#ifndef EIGEN_MPL2_ONLY
|
||||||
|
// To this end, let's symmetrize the pattern and perform AMD on it.
|
||||||
SparseMatrix<Scalar,ColMajor, Index> mat1 = amat;
|
SparseMatrix<Scalar,ColMajor, Index> mat1 = amat;
|
||||||
SparseMatrix<Scalar,ColMajor, Index> mat2 = amat.transpose();
|
SparseMatrix<Scalar,ColMajor, Index> mat2 = amat.transpose();
|
||||||
// Symmetrize the pattern
|
|
||||||
// FIXME for a matrix with nearly symmetric pattern, mat2+mat1 is the appropriate choice.
|
// FIXME for a matrix with nearly symmetric pattern, mat2+mat1 is the appropriate choice.
|
||||||
// on the other hand for a really non-symmetric pattern, mat2*mat1 should be prefered...
|
// on the other hand for a really non-symmetric pattern, mat2*mat1 should be prefered...
|
||||||
SparseMatrix<Scalar,ColMajor, Index> AtA = mat2 + mat1;
|
SparseMatrix<Scalar,ColMajor, Index> AtA = mat2 + mat1;
|
||||||
AtA.prune(keep_diag());
|
AMDOrdering<Index> ordering;
|
||||||
internal::minimum_degree_ordering<Scalar, Index>(AtA, m_P); // Then compute the AMD ordering...
|
ordering(AtA,m_P);
|
||||||
|
m_Pinv = m_P.inverse(); // cache the inverse permutation
|
||||||
m_Pinv = m_P.inverse(); // ... and the inverse permutation
|
#else
|
||||||
|
// If AMD is not available, (MPL2-only), then let's use the slower COLAMD routine.
|
||||||
|
SparseMatrix<Scalar,ColMajor, Index> mat1 = amat;
|
||||||
|
COLAMDOrdering<Index> ordering;
|
||||||
|
ordering(mat1,m_Pinv);
|
||||||
|
m_P = m_Pinv.inverse();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_analysisIsOk = true;
|
m_analysisIsOk = true;
|
||||||
|
m_factorizationIsOk = false;
|
||||||
|
m_isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
@@ -442,6 +452,7 @@ void IncompleteLUT<Scalar>::factorize(const _MatrixType& amat)
|
|||||||
m_lu.makeCompressed();
|
m_lu.makeCompressed();
|
||||||
|
|
||||||
m_factorizationIsOk = true;
|
m_factorizationIsOk = true;
|
||||||
|
m_isInitialized = m_factorizationIsOk;
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,11 @@ public:
|
|||||||
* this class becomes invalid. Call compute() to update it with the new
|
* this class becomes invalid. Call compute() to update it with the new
|
||||||
* matrix A, or modify a copy of A.
|
* matrix A, or modify a copy of A.
|
||||||
*/
|
*/
|
||||||
IterativeSolverBase(const MatrixType& A)
|
template<typename InputDerived>
|
||||||
|
IterativeSolverBase(const EigenBase<InputDerived>& A)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
compute(A);
|
compute(A.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
~IterativeSolverBase() {}
|
~IterativeSolverBase() {}
|
||||||
@@ -62,9 +63,11 @@ public:
|
|||||||
* Currently, this function mostly call analyzePattern on the preconditioner. In the future
|
* Currently, this function mostly call analyzePattern on the preconditioner. In the future
|
||||||
* we might, for instance, implement column reodering for faster matrix vector products.
|
* we might, for instance, implement column reodering for faster matrix vector products.
|
||||||
*/
|
*/
|
||||||
Derived& analyzePattern(const MatrixType& A)
|
template<typename InputDerived>
|
||||||
|
Derived& analyzePattern(const EigenBase<InputDerived>& A)
|
||||||
{
|
{
|
||||||
m_preconditioner.analyzePattern(A);
|
grabInput(A.derived());
|
||||||
|
m_preconditioner.analyzePattern(*mp_matrix);
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
m_analysisIsOk = true;
|
m_analysisIsOk = true;
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
@@ -80,11 +83,12 @@ public:
|
|||||||
* this class becomes invalid. Call compute() to update it with the new
|
* this class becomes invalid. Call compute() to update it with the new
|
||||||
* matrix A, or modify a copy of A.
|
* matrix A, or modify a copy of A.
|
||||||
*/
|
*/
|
||||||
Derived& factorize(const MatrixType& A)
|
template<typename InputDerived>
|
||||||
|
Derived& factorize(const EigenBase<InputDerived>& A)
|
||||||
{
|
{
|
||||||
|
grabInput(A.derived());
|
||||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||||
mp_matrix = &A;
|
m_preconditioner.factorize(*mp_matrix);
|
||||||
m_preconditioner.factorize(A);
|
|
||||||
m_factorizationIsOk = true;
|
m_factorizationIsOk = true;
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
return derived();
|
return derived();
|
||||||
@@ -100,10 +104,11 @@ public:
|
|||||||
* this class becomes invalid. Call compute() to update it with the new
|
* this class becomes invalid. Call compute() to update it with the new
|
||||||
* matrix A, or modify a copy of A.
|
* matrix A, or modify a copy of A.
|
||||||
*/
|
*/
|
||||||
Derived& compute(const MatrixType& A)
|
template<typename InputDerived>
|
||||||
|
Derived& compute(const EigenBase<InputDerived>& A)
|
||||||
{
|
{
|
||||||
mp_matrix = &A;
|
grabInput(A.derived());
|
||||||
m_preconditioner.compute(A);
|
m_preconditioner.compute(*mp_matrix);
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
m_analysisIsOk = true;
|
m_analysisIsOk = true;
|
||||||
m_factorizationIsOk = true;
|
m_factorizationIsOk = true;
|
||||||
@@ -212,6 +217,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
template<typename InputDerived>
|
||||||
|
void grabInput(const EigenBase<InputDerived>& A)
|
||||||
|
{
|
||||||
|
// we const cast to prevent the creation of a MatrixType temporary by the compiler.
|
||||||
|
grabInput_impl(A.const_cast_derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InputDerived>
|
||||||
|
void grabInput_impl(const EigenBase<InputDerived>& A)
|
||||||
|
{
|
||||||
|
m_copyMatrix = A;
|
||||||
|
mp_matrix = &m_copyMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grabInput_impl(MatrixType& A)
|
||||||
|
{
|
||||||
|
if(MatrixType::RowsAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==Dynamic)
|
||||||
|
m_copyMatrix.resize(0,0);
|
||||||
|
mp_matrix = &A;
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
m_isInitialized = false;
|
m_isInitialized = false;
|
||||||
@@ -220,6 +247,7 @@ protected:
|
|||||||
m_maxIterations = -1;
|
m_maxIterations = -1;
|
||||||
m_tolerance = NumTraits<Scalar>::epsilon();
|
m_tolerance = NumTraits<Scalar>::epsilon();
|
||||||
}
|
}
|
||||||
|
MatrixType m_copyMatrix;
|
||||||
const MatrixType* mp_matrix;
|
const MatrixType* mp_matrix;
|
||||||
Preconditioner m_preconditioner;
|
Preconditioner m_preconditioner;
|
||||||
|
|
||||||
|
|||||||
@@ -374,6 +374,12 @@ template<typename _MatrixType> class FullPivLU
|
|||||||
inline Index cols() const { return m_lu.cols(); }
|
inline Index cols() const { return m_lu.cols(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_lu;
|
MatrixType m_lu;
|
||||||
PermutationPType m_p;
|
PermutationPType m_p;
|
||||||
PermutationQType m_q;
|
PermutationQType m_q;
|
||||||
@@ -418,6 +424,8 @@ FullPivLU<MatrixType>::FullPivLU(const MatrixType& matrix)
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
|
FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
// the permutations are stored as int indices, so just to be sure:
|
// the permutations are stored as int indices, so just to be sure:
|
||||||
eigen_assert(matrix.rows()<=NumTraits<int>::highest() && matrix.cols()<=NumTraits<int>::highest());
|
eigen_assert(matrix.rows()<=NumTraits<int>::highest() && matrix.cols()<=NumTraits<int>::highest());
|
||||||
|
|
||||||
@@ -680,7 +688,7 @@ struct solve_retval<FullPivLU<_MatrixType>, Rhs>
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const Index rows = dec().rows(), cols = dec().cols(),
|
const Index rows = dec().rows(), cols = dec().cols(),
|
||||||
nonzero_pivots = dec().nonzeroPivots();
|
nonzero_pivots = dec().rank();
|
||||||
eigen_assert(rhs().rows() == rows);
|
eigen_assert(rhs().rows() == rows);
|
||||||
const Index smalldim = (std::min)(rows, cols);
|
const Index smalldim = (std::min)(rows, cols);
|
||||||
|
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ struct inverse_impl : public ReturnByValue<inverse_impl<MatrixType> >
|
|||||||
{
|
{
|
||||||
const int Size = EIGEN_PLAIN_ENUM_MIN(MatrixType::ColsAtCompileTime,Dest::ColsAtCompileTime);
|
const int Size = EIGEN_PLAIN_ENUM_MIN(MatrixType::ColsAtCompileTime,Dest::ColsAtCompileTime);
|
||||||
EIGEN_ONLY_USED_FOR_DEBUG(Size);
|
EIGEN_ONLY_USED_FOR_DEBUG(Size);
|
||||||
eigen_assert(( (Size<=1) || (Size>4) || (extract_data(m_matrix)!=extract_data(dst)))
|
eigen_assert(( (Size<=1) || (Size>4) || (extract_data(m_matrix)!=0 && extract_data(m_matrix)!=extract_data(dst)))
|
||||||
&& "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
&& "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
|
||||||
|
|
||||||
compute_inverse<MatrixTypeNestedCleaned, Dest>::run(m_matrix, dst);
|
compute_inverse<MatrixTypeNestedCleaned, Dest>::run(m_matrix, dst);
|
||||||
|
|||||||
@@ -171,6 +171,12 @@ template<typename _MatrixType> class PartialPivLU
|
|||||||
inline Index cols() const { return m_lu.cols(); }
|
inline Index cols() const { return m_lu.cols(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_lu;
|
MatrixType m_lu;
|
||||||
PermutationType m_p;
|
PermutationType m_p;
|
||||||
TranspositionType m_rowsTranspositions;
|
TranspositionType m_rowsTranspositions;
|
||||||
@@ -386,6 +392,8 @@ void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions, t
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
PartialPivLU<MatrixType>& PartialPivLU<MatrixType>::compute(const MatrixType& matrix)
|
PartialPivLU<MatrixType>& PartialPivLU<MatrixType>::compute(const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
// the row permutation is stored as int indices, so just to be sure:
|
// the row permutation is stored as int indices, so just to be sure:
|
||||||
eigen_assert(matrix.rows()<NumTraits<int>::highest());
|
eigen_assert(matrix.rows()<NumTraits<int>::highest());
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
NOTE: this routine has been adapted from the CSparse library:
|
NOTE: this routine has been adapted from the CSparse library:
|
||||||
|
|
||||||
Copyright (c) 2006, Timothy A. Davis.
|
Copyright (c) 2006, Timothy A. Davis.
|
||||||
http://www.cise.ufl.edu/research/sparse/CSparse
|
http://www.suitesparse.com
|
||||||
|
|
||||||
CSparse is free software; you can redistribute it and/or
|
CSparse is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
@@ -137,22 +137,27 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
|
|||||||
degree[i] = len[i]; // degree of node i
|
degree[i] = len[i]; // degree of node i
|
||||||
}
|
}
|
||||||
mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */
|
mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */
|
||||||
elen[n] = -2; /* n is a dead element */
|
|
||||||
Cp[n] = -1; /* n is a root of assembly tree */
|
|
||||||
w[n] = 0; /* n is a dead element */
|
|
||||||
|
|
||||||
/* --- Initialize degree lists ------------------------------------------ */
|
/* --- Initialize degree lists ------------------------------------------ */
|
||||||
for(i = 0; i < n; i++)
|
for(i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
|
bool has_diag = false;
|
||||||
|
for(p = Cp[i]; p<Cp[i+1]; ++p)
|
||||||
|
if(Ci[p]==i)
|
||||||
|
{
|
||||||
|
has_diag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
d = degree[i];
|
d = degree[i];
|
||||||
if(d == 0) /* node i is empty */
|
if(d == 1 && has_diag) /* node i is empty */
|
||||||
{
|
{
|
||||||
elen[i] = -2; /* element i is dead */
|
elen[i] = -2; /* element i is dead */
|
||||||
nel++;
|
nel++;
|
||||||
Cp[i] = -1; /* i is a root of assembly tree */
|
Cp[i] = -1; /* i is a root of assembly tree */
|
||||||
w[i] = 0;
|
w[i] = 0;
|
||||||
}
|
}
|
||||||
else if(d > dense) /* node i is dense */
|
else if(d > dense || !has_diag) /* node i is dense or has no structural diagonal element */
|
||||||
{
|
{
|
||||||
nv[i] = 0; /* absorb i into element n */
|
nv[i] = 0; /* absorb i into element n */
|
||||||
elen[i] = -1; /* node i is dead */
|
elen[i] = -1; /* node i is dead */
|
||||||
@@ -168,6 +173,10 @@ void minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, Permutation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elen[n] = -2; /* n is a dead element */
|
||||||
|
Cp[n] = -1; /* n is a root of assembly tree */
|
||||||
|
w[n] = 0; /* n is a dead element */
|
||||||
|
|
||||||
while (nel < n) /* while (selecting pivots) do */
|
while (nel < n) /* while (selecting pivots) do */
|
||||||
{
|
{
|
||||||
/* --- Select node of minimum approximate degree -------------------- */
|
/* --- Select node of minimum approximate degree -------------------- */
|
||||||
|
|||||||
@@ -41,12 +41,8 @@
|
|||||||
//
|
//
|
||||||
// The colamd/symamd library is available at
|
// The colamd/symamd library is available at
|
||||||
//
|
//
|
||||||
// http://www.cise.ufl.edu/research/sparse/colamd/
|
// http://www.suitesparse.com
|
||||||
|
|
||||||
// This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
|
|
||||||
// file. It is required by the colamd.c, colamdmex.c, and symamdmex.c
|
|
||||||
// files, and by any C code that calls the routines whose prototypes are
|
|
||||||
// listed below, or that uses the colamd/symamd definitions listed below.
|
|
||||||
|
|
||||||
#ifndef EIGEN_COLAMD_H
|
#ifndef EIGEN_COLAMD_H
|
||||||
#define EIGEN_COLAMD_H
|
#define EIGEN_COLAMD_H
|
||||||
@@ -102,9 +98,6 @@ namespace internal {
|
|||||||
/* === Definitions ========================================================== */
|
/* === Definitions ========================================================== */
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
#define COLAMD_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define COLAMD_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#define ONES_COMPLEMENT(r) (-(r)-1)
|
#define ONES_COMPLEMENT(r) (-(r)-1)
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -516,7 +509,7 @@ static Index init_rows_cols /* returns true if OK, or false otherwise */
|
|||||||
Col [col].start = p [col] ;
|
Col [col].start = p [col] ;
|
||||||
Col [col].length = p [col+1] - p [col] ;
|
Col [col].length = p [col+1] - p [col] ;
|
||||||
|
|
||||||
if (Col [col].length < 0)
|
if ((Col [col].length) < 0) // extra parentheses to work-around gcc bug 10200
|
||||||
{
|
{
|
||||||
/* column pointers must be non-decreasing */
|
/* column pointers must be non-decreasing */
|
||||||
stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
|
stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;
|
||||||
@@ -739,8 +732,8 @@ static void init_scoring
|
|||||||
|
|
||||||
/* === Extract knobs ==================================================== */
|
/* === Extract knobs ==================================================== */
|
||||||
|
|
||||||
dense_row_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;
|
dense_row_count = std::max<Index>(0, (std::min)(Index(knobs [COLAMD_DENSE_ROW] * n_col), n_col)) ;
|
||||||
dense_col_count = COLAMD_MAX (0, COLAMD_MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;
|
dense_col_count = std::max<Index>(0, (std::min)(Index(knobs [COLAMD_DENSE_COL] * n_row), n_row)) ;
|
||||||
COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
|
COLAMD_DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ;
|
||||||
max_deg = 0 ;
|
max_deg = 0 ;
|
||||||
n_col2 = n_col ;
|
n_col2 = n_col ;
|
||||||
@@ -804,7 +797,7 @@ static void init_scoring
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* keep track of max degree of remaining rows */
|
/* keep track of max degree of remaining rows */
|
||||||
max_deg = COLAMD_MAX (max_deg, deg) ;
|
max_deg = (std::max)(max_deg, deg) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
|
COLAMD_DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ;
|
||||||
@@ -842,7 +835,7 @@ static void init_scoring
|
|||||||
/* add row's external degree */
|
/* add row's external degree */
|
||||||
score += Row [row].shared1.degree - 1 ;
|
score += Row [row].shared1.degree - 1 ;
|
||||||
/* guard against integer overflow */
|
/* guard against integer overflow */
|
||||||
score = COLAMD_MIN (score, n_col) ;
|
score = (std::min)(score, n_col) ;
|
||||||
}
|
}
|
||||||
/* determine pruned column length */
|
/* determine pruned column length */
|
||||||
col_length = (Index) (new_cp - &A [Col [c].start]) ;
|
col_length = (Index) (new_cp - &A [Col [c].start]) ;
|
||||||
@@ -914,7 +907,7 @@ static void init_scoring
|
|||||||
head [score] = c ;
|
head [score] = c ;
|
||||||
|
|
||||||
/* see if this score is less than current min */
|
/* see if this score is less than current min */
|
||||||
min_score = COLAMD_MIN (min_score, score) ;
|
min_score = (std::min)(min_score, score) ;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1033,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
|
|
||||||
/* === Garbage_collection, if necessary ============================= */
|
/* === Garbage_collection, if necessary ============================= */
|
||||||
|
|
||||||
needed_memory = COLAMD_MIN (pivot_col_score, n_col - k) ;
|
needed_memory = (std::min)(pivot_col_score, n_col - k) ;
|
||||||
if (pfree + needed_memory >= Alen)
|
if (pfree + needed_memory >= Alen)
|
||||||
{
|
{
|
||||||
pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
|
pfree = Eigen::internal::garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;
|
||||||
@@ -1099,7 +1092,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
|
|
||||||
/* clear tag on pivot column */
|
/* clear tag on pivot column */
|
||||||
Col [pivot_col].shared1.thickness = pivot_col_thickness ;
|
Col [pivot_col].shared1.thickness = pivot_col_thickness ;
|
||||||
max_deg = COLAMD_MAX (max_deg, pivot_row_degree) ;
|
max_deg = (std::max)(max_deg, pivot_row_degree) ;
|
||||||
|
|
||||||
|
|
||||||
/* === Kill all rows used to construct pivot row ==================== */
|
/* === Kill all rows used to construct pivot row ==================== */
|
||||||
@@ -1273,7 +1266,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
/* add set difference */
|
/* add set difference */
|
||||||
cur_score += row_mark - tag_mark ;
|
cur_score += row_mark - tag_mark ;
|
||||||
/* integer overflow... */
|
/* integer overflow... */
|
||||||
cur_score = COLAMD_MIN (cur_score, n_col) ;
|
cur_score = (std::min)(cur_score, n_col) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recompute the column's length */
|
/* recompute the column's length */
|
||||||
@@ -1386,7 +1379,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
cur_score -= Col [col].shared1.thickness ;
|
cur_score -= Col [col].shared1.thickness ;
|
||||||
|
|
||||||
/* make sure score is less or equal than the max score */
|
/* make sure score is less or equal than the max score */
|
||||||
cur_score = COLAMD_MIN (cur_score, max_score) ;
|
cur_score = (std::min)(cur_score, max_score) ;
|
||||||
COLAMD_ASSERT (cur_score >= 0) ;
|
COLAMD_ASSERT (cur_score >= 0) ;
|
||||||
|
|
||||||
/* store updated score */
|
/* store updated score */
|
||||||
@@ -1409,7 +1402,7 @@ static Index find_ordering /* return the number of garbage collections */
|
|||||||
head [cur_score] = col ;
|
head [cur_score] = col ;
|
||||||
|
|
||||||
/* see if this score is less than current min */
|
/* see if this score is less than current min */
|
||||||
min_score = COLAMD_MIN (min_score, cur_score) ;
|
min_score = (std::min)(min_score, cur_score) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
#ifndef EIGEN_PASTIXSUPPORT_H
|
#ifndef EIGEN_PASTIXSUPPORT_H
|
||||||
#define EIGEN_PASTIXSUPPORT_H
|
#define EIGEN_PASTIXSUPPORT_H
|
||||||
|
|
||||||
|
#if defined(DCOMPLEX)
|
||||||
|
#define PASTIX_COMPLEX COMPLEX
|
||||||
|
#define PASTIX_DCOMPLEX DCOMPLEX
|
||||||
|
#else
|
||||||
|
#define PASTIX_COMPLEX std::complex<float>
|
||||||
|
#define PASTIX_DCOMPLEX std::complex<double>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
/** \ingroup PaStiXSupport_Module
|
/** \ingroup PaStiXSupport_Module
|
||||||
@@ -74,14 +82,14 @@ namespace internal
|
|||||||
{
|
{
|
||||||
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
||||||
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
||||||
c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<COMPLEX*>(vals), perm, invp, reinterpret_cast<COMPLEX*>(x), nbrhs, iparm, dparm);
|
c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_COMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_COMPLEX*>(x), nbrhs, iparm, dparm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
|
void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
|
||||||
{
|
{
|
||||||
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
|
||||||
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
if (nbrhs == 0) {x = NULL; nbrhs=1;}
|
||||||
z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<DCOMPLEX*>(vals), perm, invp, reinterpret_cast<DCOMPLEX*>(x), nbrhs, iparm, dparm);
|
z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_DCOMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_DCOMPLEX*>(x), nbrhs, iparm, dparm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the matrix to Fortran-style Numbering
|
// Convert the matrix to Fortran-style Numbering
|
||||||
|
|||||||
@@ -221,11 +221,11 @@ class PardisoImpl
|
|||||||
m_type = type;
|
m_type = type;
|
||||||
bool symmetric = std::abs(m_type) < 10;
|
bool symmetric = std::abs(m_type) < 10;
|
||||||
m_iparm[0] = 1; // No solver default
|
m_iparm[0] = 1; // No solver default
|
||||||
m_iparm[1] = 3; // use Metis for the ordering
|
m_iparm[1] = 2; // use Metis for the ordering
|
||||||
m_iparm[2] = 1; // Numbers of processors, value of OMP_NUM_THREADS
|
m_iparm[2] = 0; // Reserved. Set to zero. (??Numbers of processors, value of OMP_NUM_THREADS??)
|
||||||
m_iparm[3] = 0; // No iterative-direct algorithm
|
m_iparm[3] = 0; // No iterative-direct algorithm
|
||||||
m_iparm[4] = 0; // No user fill-in reducing permutation
|
m_iparm[4] = 0; // No user fill-in reducing permutation
|
||||||
m_iparm[5] = 0; // Write solution into x
|
m_iparm[5] = 0; // Write solution into x, b is left unchanged
|
||||||
m_iparm[6] = 0; // Not in use
|
m_iparm[6] = 0; // Not in use
|
||||||
m_iparm[7] = 2; // Max numbers of iterative refinement steps
|
m_iparm[7] = 2; // Max numbers of iterative refinement steps
|
||||||
m_iparm[8] = 0; // Not in use
|
m_iparm[8] = 0; // Not in use
|
||||||
@@ -246,7 +246,10 @@ class PardisoImpl
|
|||||||
m_iparm[26] = 0; // No matrix checker
|
m_iparm[26] = 0; // No matrix checker
|
||||||
m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
|
m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
|
||||||
m_iparm[34] = 1; // C indexing
|
m_iparm[34] = 1; // C indexing
|
||||||
m_iparm[59] = 1; // Automatic switch between In-Core and Out-of-Core modes
|
m_iparm[36] = 0; // CSR
|
||||||
|
m_iparm[59] = 0; // 0 - In-Core ; 1 - Automatic switch between In-Core and Out-of-Core modes ; 2 - Out-of-Core
|
||||||
|
|
||||||
|
memset(m_pt, 0, sizeof(m_pt));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -384,7 +387,6 @@ bool PardisoImpl<Base>::_solve(const MatrixBase<BDerived> &b, MatrixBase<XDerive
|
|||||||
m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(),
|
m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(),
|
||||||
m_perm.data(), nrhs, m_iparm.data(), m_msglvl,
|
m_perm.data(), nrhs, m_iparm.data(), m_msglvl,
|
||||||
rhs_ptr, x.derived().data());
|
rhs_ptr, x.derived().data());
|
||||||
|
|
||||||
return error==0;
|
return error==0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,6 +399,9 @@ bool PardisoImpl<Base>::_solve(const MatrixBase<BDerived> &b, MatrixBase<XDerive
|
|||||||
* using the Intel MKL PARDISO library. The sparse matrix A must be squared and invertible.
|
* using the Intel MKL PARDISO library. The sparse matrix A must be squared and invertible.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
*
|
*
|
||||||
* \sa \ref TutorialSparseDirectSolvers
|
* \sa \ref TutorialSparseDirectSolvers
|
||||||
@@ -447,6 +452,9 @@ class PardisoLU : public PardisoImpl< PardisoLU<MatrixType> >
|
|||||||
* using the Intel MKL PARDISO library. The sparse matrix A must be selfajoint and positive definite.
|
* using the Intel MKL PARDISO library. The sparse matrix A must be selfajoint and positive definite.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
* \tparam UpLo can be any bitwise combination of Upper, Lower. The default is Upper, meaning only the upper triangular part has to be used.
|
* \tparam UpLo can be any bitwise combination of Upper, Lower. The default is Upper, meaning only the upper triangular part has to be used.
|
||||||
* Upper|Lower can be used to tell both triangular parts can be used as input.
|
* Upper|Lower can be used to tell both triangular parts can be used as input.
|
||||||
@@ -507,6 +515,9 @@ class PardisoLLT : public PardisoImpl< PardisoLLT<MatrixType,_UpLo> >
|
|||||||
* For complex matrices, A can also be symmetric only, see the \a Options template parameter.
|
* For complex matrices, A can also be symmetric only, see the \a Options template parameter.
|
||||||
* The vectors or matrices X and B can be either dense or sparse.
|
* The vectors or matrices X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
|
* By default, it runs in in-core mode. To enable PARDISO's out-of-core feature, set:
|
||||||
|
* \code solver.pardisoParameterArray()[59] = 1; \endcode
|
||||||
|
*
|
||||||
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
* \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
|
||||||
* \tparam Options can be any bitwise combination of Upper, Lower, and Symmetric. The default is Upper, meaning only the upper triangular part has to be used.
|
* \tparam Options can be any bitwise combination of Upper, Lower, and Symmetric. The default is Upper, meaning only the upper triangular part has to be used.
|
||||||
* Symmetric can be used for symmetric, non-selfadjoint complex matrices, the default being to assume a selfadjoint matrix.
|
* Symmetric can be used for symmetric, non-selfadjoint complex matrices, the default being to assume a selfadjoint matrix.
|
||||||
|
|||||||
@@ -384,6 +384,12 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
PermutationType m_colsPermutation;
|
PermutationType m_colsPermutation;
|
||||||
@@ -422,6 +428,8 @@ typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDetermina
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::abs;
|
using std::abs;
|
||||||
Index rows = matrix.rows();
|
Index rows = matrix.rows();
|
||||||
Index cols = matrix.cols();
|
Index cols = matrix.cols();
|
||||||
@@ -463,20 +471,10 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
|
|||||||
// we store that back into our table: it can't hurt to correct our table.
|
// we store that back into our table: it can't hurt to correct our table.
|
||||||
m_colSqNorms.coeffRef(biggest_col_index) = biggest_col_sq_norm;
|
m_colSqNorms.coeffRef(biggest_col_index) = biggest_col_sq_norm;
|
||||||
|
|
||||||
// if the current biggest column is smaller than epsilon times the initial biggest column,
|
// Track the number of meaningful pivots but do not stop the decomposition to make
|
||||||
// terminate to avoid generating nan/inf values.
|
// sure that the initial matrix is properly reproduced. See bug 941.
|
||||||
// Note that here, if we test instead for "biggest == 0", we get a failure every 1000 (or so)
|
if(m_nonzero_pivots==size && biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
|
||||||
// repetitions of the unit test, with the result of solve() filled with large values of the order
|
|
||||||
// of 1/(size*epsilon).
|
|
||||||
if(biggest_col_sq_norm < threshold_helper * RealScalar(rows-k))
|
|
||||||
{
|
|
||||||
m_nonzero_pivots = k;
|
m_nonzero_pivots = k;
|
||||||
m_hCoeffs.tail(size-k).setZero();
|
|
||||||
m_qr.bottomRightCorner(rows-k,cols-k)
|
|
||||||
.template triangularView<StrictlyLower>()
|
|
||||||
.setZero();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply the transposition to the columns
|
// apply the transposition to the columns
|
||||||
m_colsTranspositions.coeffRef(k) = biggest_col_index;
|
m_colsTranspositions.coeffRef(k) = biggest_col_index;
|
||||||
@@ -505,7 +503,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_colsPermutation.setIdentity(PermIndexType(cols));
|
m_colsPermutation.setIdentity(PermIndexType(cols));
|
||||||
for(PermIndexType k = 0; k < m_nonzero_pivots; ++k)
|
for(PermIndexType k = 0; k < size/*m_nonzero_pivots*/; ++k)
|
||||||
m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k)));
|
m_colsPermutation.applyTranspositionOnTheRight(k, PermIndexType(m_colsTranspositions.coeff(k)));
|
||||||
|
|
||||||
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
m_det_pq = (number_of_transpositions%2) ? -1 : 1;
|
||||||
@@ -555,13 +553,15 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
/** \returns the matrix Q as a sequence of householder transformations */
|
/** \returns the matrix Q as a sequence of householder transformations.
|
||||||
|
* You can extract the meaningful part only by using:
|
||||||
|
* \code qr.householderQ().setLength(qr.nonzeroPivots()) \endcode*/
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType>
|
typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHouseholderQR<MatrixType>
|
||||||
::householderQ() const
|
::householderQ() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()).setLength(m_nonzero_pivots);
|
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \return the column-pivoting Householder QR decomposition of \c *this.
|
/** \return the column-pivoting Householder QR decomposition of \c *this.
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ ColPivHouseholderQR<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynami
|
|||||||
{ \
|
{ \
|
||||||
using std::abs; \
|
using std::abs; \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
typedef MatrixType::RealScalar RealScalar; \
|
||||||
Index rows = matrix.rows();\
|
Index rows = matrix.rows();\
|
||||||
Index cols = matrix.cols();\
|
Index cols = matrix.cols();\
|
||||||
|
|||||||
@@ -368,6 +368,12 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
|||||||
RealScalar maxPivot() const { return m_maxpivot; }
|
RealScalar maxPivot() const { return m_maxpivot; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
IntDiagSizeVectorType m_rows_transpositions;
|
IntDiagSizeVectorType m_rows_transpositions;
|
||||||
@@ -407,6 +413,8 @@ typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::logAbsDetermin
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::abs;
|
using std::abs;
|
||||||
Index rows = matrix.rows();
|
Index rows = matrix.rows();
|
||||||
Index cols = matrix.cols();
|
Index cols = matrix.cols();
|
||||||
|
|||||||
@@ -189,6 +189,12 @@ template<typename _MatrixType> class HouseholderQR
|
|||||||
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_qr;
|
MatrixType m_qr;
|
||||||
HCoeffsType m_hCoeffs;
|
HCoeffsType m_hCoeffs;
|
||||||
RowVectorType m_temp;
|
RowVectorType m_temp;
|
||||||
@@ -251,56 +257,62 @@ void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** \internal */
|
/** \internal */
|
||||||
template<typename MatrixQR, typename HCoeffs>
|
template<typename MatrixQR, typename HCoeffs,
|
||||||
void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs,
|
typename MatrixQRScalar = typename MatrixQR::Scalar,
|
||||||
typename MatrixQR::Index maxBlockSize=32,
|
bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
|
||||||
typename MatrixQR::Scalar* tempData = 0)
|
struct householder_qr_inplace_blocked
|
||||||
{
|
{
|
||||||
typedef typename MatrixQR::Index Index;
|
// This is specialized for MKL-supported Scalar types in HouseholderQR_MKL.h
|
||||||
typedef typename MatrixQR::Scalar Scalar;
|
static void run(MatrixQR& mat, HCoeffs& hCoeffs,
|
||||||
typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
|
typename MatrixQR::Index maxBlockSize=32,
|
||||||
|
typename MatrixQR::Scalar* tempData = 0)
|
||||||
Index rows = mat.rows();
|
|
||||||
Index cols = mat.cols();
|
|
||||||
Index size = (std::min)(rows, cols);
|
|
||||||
|
|
||||||
typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
|
|
||||||
TempType tempVector;
|
|
||||||
if(tempData==0)
|
|
||||||
{
|
{
|
||||||
tempVector.resize(cols);
|
typedef typename MatrixQR::Index Index;
|
||||||
tempData = tempVector.data();
|
typedef typename MatrixQR::Scalar Scalar;
|
||||||
}
|
typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
|
||||||
|
|
||||||
Index blockSize = (std::min)(maxBlockSize,size);
|
Index rows = mat.rows();
|
||||||
|
Index cols = mat.cols();
|
||||||
|
Index size = (std::min)(rows, cols);
|
||||||
|
|
||||||
Index k = 0;
|
typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
|
||||||
for (k = 0; k < size; k += blockSize)
|
TempType tempVector;
|
||||||
{
|
if(tempData==0)
|
||||||
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
|
||||||
Index tcols = cols - k - bs; // trailing columns
|
|
||||||
Index brows = rows-k; // rows of the block
|
|
||||||
|
|
||||||
// partition the matrix:
|
|
||||||
// A00 | A01 | A02
|
|
||||||
// mat = A10 | A11 | A12
|
|
||||||
// A20 | A21 | A22
|
|
||||||
// and performs the qr dec of [A11^T A12^T]^T
|
|
||||||
// and update [A21^T A22^T]^T using level 3 operations.
|
|
||||||
// Finally, the algorithm continue on A22
|
|
||||||
|
|
||||||
BlockType A11_21 = mat.block(k,k,brows,bs);
|
|
||||||
Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
|
|
||||||
|
|
||||||
householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
|
|
||||||
|
|
||||||
if(tcols)
|
|
||||||
{
|
{
|
||||||
BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
|
tempVector.resize(cols);
|
||||||
apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
|
tempData = tempVector.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
Index blockSize = (std::min)(maxBlockSize,size);
|
||||||
|
|
||||||
|
Index k = 0;
|
||||||
|
for (k = 0; k < size; k += blockSize)
|
||||||
|
{
|
||||||
|
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
||||||
|
Index tcols = cols - k - bs; // trailing columns
|
||||||
|
Index brows = rows-k; // rows of the block
|
||||||
|
|
||||||
|
// partition the matrix:
|
||||||
|
// A00 | A01 | A02
|
||||||
|
// mat = A10 | A11 | A12
|
||||||
|
// A20 | A21 | A22
|
||||||
|
// and performs the qr dec of [A11^T A12^T]^T
|
||||||
|
// and update [A21^T A22^T]^T using level 3 operations.
|
||||||
|
// Finally, the algorithm continue on A22
|
||||||
|
|
||||||
|
BlockType A11_21 = mat.block(k,k,brows,bs);
|
||||||
|
Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
|
||||||
|
|
||||||
|
householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
|
||||||
|
|
||||||
|
if(tcols)
|
||||||
|
{
|
||||||
|
BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
|
||||||
|
apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment.adjoint());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
template<typename _MatrixType, typename Rhs>
|
template<typename _MatrixType, typename Rhs>
|
||||||
struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
||||||
@@ -343,6 +355,8 @@ struct solve_retval<HouseholderQR<_MatrixType>, Rhs>
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
Index rows = matrix.rows();
|
Index rows = matrix.rows();
|
||||||
Index cols = matrix.cols();
|
Index cols = matrix.cols();
|
||||||
Index size = (std::min)(rows,cols);
|
Index size = (std::min)(rows,cols);
|
||||||
@@ -352,7 +366,7 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType&
|
|||||||
|
|
||||||
m_temp.resize(cols);
|
m_temp.resize(cols);
|
||||||
|
|
||||||
internal::householder_qr_inplace_blocked(m_qr, m_hCoeffs, 48, m_temp.data());
|
internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, 48, m_temp.data());
|
||||||
|
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -34,28 +34,30 @@
|
|||||||
#ifndef EIGEN_QR_MKL_H
|
#ifndef EIGEN_QR_MKL_H
|
||||||
#define EIGEN_QR_MKL_H
|
#define EIGEN_QR_MKL_H
|
||||||
|
|
||||||
#include "Eigen/src/Core/util/MKL_support.h"
|
#include "../Core/util/MKL_support.h"
|
||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
/** \internal Specialization for the data types supported by MKL */
|
/** \internal Specialization for the data types supported by MKL */
|
||||||
|
|
||||||
#define EIGEN_MKL_QR_NOPIV(EIGTYPE, MKLTYPE, MKLPREFIX) \
|
#define EIGEN_MKL_QR_NOPIV(EIGTYPE, MKLTYPE, MKLPREFIX) \
|
||||||
template<typename MatrixQR, typename HCoeffs> \
|
template<typename MatrixQR, typename HCoeffs> \
|
||||||
void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs, \
|
struct householder_qr_inplace_blocked<MatrixQR, HCoeffs, EIGTYPE, true> \
|
||||||
typename MatrixQR::Index maxBlockSize=32, \
|
|
||||||
EIGTYPE* tempData = 0) \
|
|
||||||
{ \
|
{ \
|
||||||
lapack_int m = mat.rows(); \
|
static void run(MatrixQR& mat, HCoeffs& hCoeffs, \
|
||||||
lapack_int n = mat.cols(); \
|
typename MatrixQR::Index = 32, \
|
||||||
lapack_int lda = mat.outerStride(); \
|
typename MatrixQR::Scalar* = 0) \
|
||||||
lapack_int matrix_order = (MatrixQR::IsRowMajor) ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
|
{ \
|
||||||
LAPACKE_##MKLPREFIX##geqrf( matrix_order, m, n, (MKLTYPE*)mat.data(), lda, (MKLTYPE*)hCoeffs.data()); \
|
lapack_int m = (lapack_int) mat.rows(); \
|
||||||
hCoeffs.adjointInPlace(); \
|
lapack_int n = (lapack_int) mat.cols(); \
|
||||||
\
|
lapack_int lda = (lapack_int) mat.outerStride(); \
|
||||||
}
|
lapack_int matrix_order = (MatrixQR::IsRowMajor) ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
|
||||||
|
LAPACKE_##MKLPREFIX##geqrf( matrix_order, m, n, (MKLTYPE*)mat.data(), lda, (MKLTYPE*)hCoeffs.data()); \
|
||||||
|
hCoeffs.adjointInPlace(); \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
EIGEN_MKL_QR_NOPIV(double, double, d)
|
EIGEN_MKL_QR_NOPIV(double, double, d)
|
||||||
EIGEN_MKL_QR_NOPIV(float, float, s)
|
EIGEN_MKL_QR_NOPIV(float, float, s)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Eigen {
|
|||||||
* You can then apply it to a vector.
|
* You can then apply it to a vector.
|
||||||
*
|
*
|
||||||
* R is the sparse triangular factor. Use matrixQR() to get it as SparseMatrix.
|
* R is the sparse triangular factor. Use matrixQR() to get it as SparseMatrix.
|
||||||
* NOTE : The Index type of R is always UF_long. You can get it with SPQR::Index
|
* NOTE : The Index type of R is always SuiteSparse_long. You can get it with SPQR::Index
|
||||||
*
|
*
|
||||||
* \tparam _MatrixType The type of the sparse matrix A, must be a column-major SparseMatrix<>
|
* \tparam _MatrixType The type of the sparse matrix A, must be a column-major SparseMatrix<>
|
||||||
* NOTE
|
* NOTE
|
||||||
@@ -59,24 +59,18 @@ class SPQR
|
|||||||
public:
|
public:
|
||||||
typedef typename _MatrixType::Scalar Scalar;
|
typedef typename _MatrixType::Scalar Scalar;
|
||||||
typedef typename _MatrixType::RealScalar RealScalar;
|
typedef typename _MatrixType::RealScalar RealScalar;
|
||||||
typedef UF_long Index ;
|
typedef SuiteSparse_long Index ;
|
||||||
typedef SparseMatrix<Scalar, ColMajor, Index> MatrixType;
|
typedef SparseMatrix<Scalar, ColMajor, Index> MatrixType;
|
||||||
typedef PermutationMatrix<Dynamic, Dynamic> PermutationType;
|
typedef PermutationMatrix<Dynamic, Dynamic> PermutationType;
|
||||||
public:
|
public:
|
||||||
SPQR()
|
SPQR()
|
||||||
: m_isInitialized(false),
|
: m_isInitialized(false), m_ordering(SPQR_ORDERING_DEFAULT), m_allow_tol(SPQR_DEFAULT_TOL), m_tolerance (NumTraits<Scalar>::epsilon()), m_useDefaultThreshold(true)
|
||||||
m_ordering(SPQR_ORDERING_DEFAULT),
|
|
||||||
m_allow_tol(SPQR_DEFAULT_TOL),
|
|
||||||
m_tolerance (NumTraits<Scalar>::epsilon())
|
|
||||||
{
|
{
|
||||||
cholmod_l_start(&m_cc);
|
cholmod_l_start(&m_cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPQR(const _MatrixType& matrix)
|
SPQR(const _MatrixType& matrix)
|
||||||
: m_isInitialized(false),
|
: m_isInitialized(false), m_ordering(SPQR_ORDERING_DEFAULT), m_allow_tol(SPQR_DEFAULT_TOL), m_tolerance (NumTraits<Scalar>::epsilon()), m_useDefaultThreshold(true)
|
||||||
m_ordering(SPQR_ORDERING_DEFAULT),
|
|
||||||
m_allow_tol(SPQR_DEFAULT_TOL),
|
|
||||||
m_tolerance (NumTraits<Scalar>::epsilon())
|
|
||||||
{
|
{
|
||||||
cholmod_l_start(&m_cc);
|
cholmod_l_start(&m_cc);
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
@@ -101,10 +95,26 @@ class SPQR
|
|||||||
if(m_isInitialized) SPQR_free();
|
if(m_isInitialized) SPQR_free();
|
||||||
|
|
||||||
MatrixType mat(matrix);
|
MatrixType mat(matrix);
|
||||||
|
|
||||||
|
/* Compute the default threshold as in MatLab, see:
|
||||||
|
* Tim Davis, "Algorithm 915, SuiteSparseQR: Multifrontal Multithreaded Rank-Revealing
|
||||||
|
* Sparse QR Factorization, ACM Trans. on Math. Soft. 38(1), 2011, Page 8:3
|
||||||
|
*/
|
||||||
|
RealScalar pivotThreshold = m_tolerance;
|
||||||
|
if(m_useDefaultThreshold)
|
||||||
|
{
|
||||||
|
using std::max;
|
||||||
|
RealScalar max2Norm = 0.0;
|
||||||
|
for (int j = 0; j < mat.cols(); j++) max2Norm = (max)(max2Norm, mat.col(j).norm());
|
||||||
|
if(max2Norm==RealScalar(0))
|
||||||
|
max2Norm = RealScalar(1);
|
||||||
|
pivotThreshold = 20 * (mat.rows() + mat.cols()) * max2Norm * NumTraits<RealScalar>::epsilon();
|
||||||
|
}
|
||||||
|
|
||||||
cholmod_sparse A;
|
cholmod_sparse A;
|
||||||
A = viewAsCholmod(mat);
|
A = viewAsCholmod(mat);
|
||||||
Index col = matrix.cols();
|
Index col = matrix.cols();
|
||||||
m_rank = SuiteSparseQR<Scalar>(m_ordering, m_tolerance, col, &A,
|
m_rank = SuiteSparseQR<Scalar>(m_ordering, pivotThreshold, col, &A,
|
||||||
&m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
|
&m_cR, &m_E, &m_H, &m_HPinv, &m_HTau, &m_cc);
|
||||||
|
|
||||||
if (!m_cR)
|
if (!m_cR)
|
||||||
@@ -120,7 +130,7 @@ class SPQR
|
|||||||
/**
|
/**
|
||||||
* Get the number of rows of the input matrix and the Q matrix
|
* Get the number of rows of the input matrix and the Q matrix
|
||||||
*/
|
*/
|
||||||
inline Index rows() const {return m_H->nrow; }
|
inline Index rows() const {return m_cR->nrow; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of columns of the input matrix.
|
* Get the number of columns of the input matrix.
|
||||||
@@ -145,16 +155,25 @@ class SPQR
|
|||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
|
eigen_assert(m_isInitialized && " The QR factorization should be computed first, call compute()");
|
||||||
eigen_assert(b.cols()==1 && "This method is for vectors only");
|
eigen_assert(b.cols()==1 && "This method is for vectors only");
|
||||||
|
|
||||||
//Compute Q^T * b
|
//Compute Q^T * b
|
||||||
typename Dest::PlainObject y;
|
typename Dest::PlainObject y, y2;
|
||||||
y = matrixQ().transpose() * b;
|
y = matrixQ().transpose() * b;
|
||||||
// Solves with the triangular matrix R
|
|
||||||
|
// Solves with the triangular matrix R
|
||||||
Index rk = this->rank();
|
Index rk = this->rank();
|
||||||
y.topRows(rk) = this->matrixR().topLeftCorner(rk, rk).template triangularView<Upper>().solve(y.topRows(rk));
|
y2 = y;
|
||||||
y.bottomRows(cols()-rk).setZero();
|
y.resize((std::max)(cols(),Index(y.rows())),y.cols());
|
||||||
|
y.topRows(rk) = this->matrixR().topLeftCorner(rk, rk).template triangularView<Upper>().solve(y2.topRows(rk));
|
||||||
|
|
||||||
// Apply the column permutation
|
// Apply the column permutation
|
||||||
dest.topRows(cols()) = colsPermutation() * y.topRows(cols());
|
// colsPermutation() performs a copy of the permutation,
|
||||||
|
// so let's apply it manually:
|
||||||
|
for(Index i = 0; i < rk; ++i) dest.row(m_E[i]) = y.row(i);
|
||||||
|
for(Index i = rk; i < cols(); ++i) dest.row(m_E[i]).setZero();
|
||||||
|
|
||||||
|
// y.bottomRows(y.rows()-rk).setZero();
|
||||||
|
// dest = colsPermutation() * y.topRows(cols());
|
||||||
|
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
}
|
}
|
||||||
@@ -197,7 +216,11 @@ class SPQR
|
|||||||
/// Set the fill-reducing ordering method to be used
|
/// Set the fill-reducing ordering method to be used
|
||||||
void setSPQROrdering(int ord) { m_ordering = ord;}
|
void setSPQROrdering(int ord) { m_ordering = ord;}
|
||||||
/// Set the tolerance tol to treat columns with 2-norm < =tol as zero
|
/// Set the tolerance tol to treat columns with 2-norm < =tol as zero
|
||||||
void setPivotThreshold(const RealScalar& tol) { m_tolerance = tol; }
|
void setPivotThreshold(const RealScalar& tol)
|
||||||
|
{
|
||||||
|
m_useDefaultThreshold = false;
|
||||||
|
m_tolerance = tol;
|
||||||
|
}
|
||||||
|
|
||||||
/** \returns a pointer to the SPQR workspace */
|
/** \returns a pointer to the SPQR workspace */
|
||||||
cholmod_common *cholmodCommon() const { return &m_cc; }
|
cholmod_common *cholmodCommon() const { return &m_cc; }
|
||||||
@@ -230,6 +253,7 @@ class SPQR
|
|||||||
mutable cholmod_dense *m_HTau; // The Householder coefficients
|
mutable cholmod_dense *m_HTau; // The Householder coefficients
|
||||||
mutable Index m_rank; // The rank of the matrix
|
mutable Index m_rank; // The rank of the matrix
|
||||||
mutable cholmod_common m_cc; // Workspace and parameters
|
mutable cholmod_common m_cc; // Workspace and parameters
|
||||||
|
bool m_useDefaultThreshold; // Use default threshold
|
||||||
template<typename ,typename > friend struct SPQR_QProduct;
|
template<typename ,typename > friend struct SPQR_QProduct;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -359,29 +359,42 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false
|
|||||||
{
|
{
|
||||||
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
||||||
typedef typename SVD::Index Index;
|
typedef typename SVD::Index Index;
|
||||||
static void run(typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
|
static bool run(typename SVD::WorkMatrixType&, SVD&, Index, Index, RealScalar&) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
||||||
{
|
{
|
||||||
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
|
||||||
|
typedef typename SVD::Index Index;
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::RealScalar RealScalar;
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
typedef typename SVD::Index Index;
|
static bool run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q, RealScalar& maxDiagEntry)
|
||||||
static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
|
|
||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
|
using std::abs;
|
||||||
|
using std::max;
|
||||||
Scalar z;
|
Scalar z;
|
||||||
JacobiRotation<Scalar> rot;
|
JacobiRotation<Scalar> rot;
|
||||||
RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
|
RealScalar n = sqrt(numext::abs2(work_matrix.coeff(p,p)) + numext::abs2(work_matrix.coeff(q,p)));
|
||||||
|
|
||||||
|
const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
|
||||||
|
const RealScalar precision = NumTraits<Scalar>::epsilon();
|
||||||
|
|
||||||
if(n==0)
|
if(n==0)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
// make sure first column is zero
|
||||||
work_matrix.row(p) *= z;
|
work_matrix.coeffRef(p,p) = work_matrix.coeffRef(q,p) = Scalar(0);
|
||||||
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
|
|
||||||
if(work_matrix.coeff(q,q)!=Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
|
||||||
|
{
|
||||||
|
// work_matrix.coeff(p,q) can be zero if work_matrix.coeff(q,p) is not zero but small enough to underflow when computing n
|
||||||
|
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
||||||
|
work_matrix.row(p) *= z;
|
||||||
|
if(svd.computeU()) svd.m_matrixU.col(p) *= conj(z);
|
||||||
|
}
|
||||||
|
if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
||||||
work_matrix.row(q) *= z;
|
work_matrix.row(q) *= z;
|
||||||
@@ -395,19 +408,25 @@ struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
|
|||||||
rot.s() = work_matrix.coeff(q,p) / n;
|
rot.s() = work_matrix.coeff(q,p) / n;
|
||||||
work_matrix.applyOnTheLeft(p,q,rot);
|
work_matrix.applyOnTheLeft(p,q,rot);
|
||||||
if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
|
if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
|
||||||
if(work_matrix.coeff(p,q) != Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(p,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
Scalar z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
|
||||||
work_matrix.col(q) *= z;
|
work_matrix.col(q) *= z;
|
||||||
if(svd.computeV()) svd.m_matrixV.col(q) *= z;
|
if(svd.computeV()) svd.m_matrixV.col(q) *= z;
|
||||||
}
|
}
|
||||||
if(work_matrix.coeff(q,q) != Scalar(0))
|
if(abs(numext::imag(work_matrix.coeff(q,q)))>considerAsZero)
|
||||||
{
|
{
|
||||||
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
|
||||||
work_matrix.row(q) *= z;
|
work_matrix.row(q) *= z;
|
||||||
if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
|
if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update largest diagonal entry
|
||||||
|
maxDiagEntry = max EIGEN_EMPTY (maxDiagEntry,max EIGEN_EMPTY (abs(work_matrix.coeff(p,p)), abs(work_matrix.coeff(q,q))));
|
||||||
|
// and check whether the 2x2 block is already diagonal
|
||||||
|
RealScalar threshold = max EIGEN_EMPTY (considerAsZero, precision * maxDiagEntry);
|
||||||
|
return abs(work_matrix.coeff(p,q))>threshold || abs(work_matrix.coeff(q,p)) > threshold;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -424,22 +443,23 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
|
|||||||
JacobiRotation<RealScalar> rot1;
|
JacobiRotation<RealScalar> rot1;
|
||||||
RealScalar t = m.coeff(0,0) + m.coeff(1,1);
|
RealScalar t = m.coeff(0,0) + m.coeff(1,1);
|
||||||
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
RealScalar d = m.coeff(1,0) - m.coeff(0,1);
|
||||||
if(t == RealScalar(0))
|
if(d == RealScalar(0))
|
||||||
{
|
{
|
||||||
rot1.c() = RealScalar(0);
|
rot1.s() = RealScalar(0);
|
||||||
rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
|
rot1.c() = RealScalar(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar t2d2 = numext::hypot(t,d);
|
// If d!=0, then t/d cannot overflow because the magnitude of the
|
||||||
rot1.c() = abs(t)/t2d2;
|
// entries forming d are not too small compared to the ones forming t.
|
||||||
rot1.s() = d/t2d2;
|
RealScalar u = t / d;
|
||||||
if(t<RealScalar(0))
|
RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u));
|
||||||
rot1.s() = -rot1.s();
|
rot1.s() = RealScalar(1) / tmp;
|
||||||
|
rot1.c() = u / tmp;
|
||||||
}
|
}
|
||||||
m.applyOnTheLeft(0,1,rot1);
|
m.applyOnTheLeft(0,1,rot1);
|
||||||
j_right->makeJacobi(m,0,1);
|
j_right->makeJacobi(m,0,1);
|
||||||
*j_left = rot1 * j_right->transpose();
|
*j_left = rot1 * j_right->transpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
@@ -742,6 +762,11 @@ template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void allocate(Index rows, Index cols, unsigned int computationOptions);
|
void allocate(Index rows, Index cols, unsigned int computationOptions);
|
||||||
|
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatrixUType m_matrixU;
|
MatrixUType m_matrixU;
|
||||||
@@ -811,14 +836,17 @@ void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, u
|
|||||||
|
|
||||||
if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
|
if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this);
|
||||||
if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
|
if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this);
|
||||||
if(m_cols!=m_cols) m_scaledMatrix.resize(rows,cols);
|
if(m_rows!=m_cols) m_scaledMatrix.resize(rows,cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename MatrixType, int QRPreconditioner>
|
template<typename MatrixType, int QRPreconditioner>
|
||||||
JacobiSVD<MatrixType, QRPreconditioner>&
|
JacobiSVD<MatrixType, QRPreconditioner>&
|
||||||
JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
|
JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
|
||||||
{
|
{
|
||||||
|
check_template_parameters();
|
||||||
|
|
||||||
using std::abs;
|
using std::abs;
|
||||||
|
using std::max;
|
||||||
allocate(matrix.rows(), matrix.cols(), computationOptions);
|
allocate(matrix.rows(), matrix.cols(), computationOptions);
|
||||||
|
|
||||||
// currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
|
// currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
|
||||||
@@ -850,6 +878,7 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*** step 2. The main Jacobi SVD iteration. ***/
|
/*** step 2. The main Jacobi SVD iteration. ***/
|
||||||
|
RealScalar maxDiagEntry = m_workMatrix.cwiseAbs().diagonal().maxCoeff();
|
||||||
|
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while(!finished)
|
while(!finished)
|
||||||
@@ -865,25 +894,27 @@ JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsig
|
|||||||
// if this 2x2 sub-matrix is not diagonal already...
|
// if this 2x2 sub-matrix is not diagonal already...
|
||||||
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
// notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
|
||||||
// keep us iterating forever. Similarly, small denormal numbers are considered zero.
|
// keep us iterating forever. Similarly, small denormal numbers are considered zero.
|
||||||
using std::max;
|
RealScalar threshold = max EIGEN_EMPTY (considerAsZero, precision * maxDiagEntry);
|
||||||
RealScalar threshold = (max)(considerAsZero, precision * (max)(abs(m_workMatrix.coeff(p,p)),
|
|
||||||
abs(m_workMatrix.coeff(q,q))));
|
|
||||||
// We compare both values to threshold instead of calling max to be robust to NaN (See bug 791)
|
|
||||||
if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
|
if(abs(m_workMatrix.coeff(p,q))>threshold || abs(m_workMatrix.coeff(q,p)) > threshold)
|
||||||
{
|
{
|
||||||
finished = false;
|
finished = false;
|
||||||
|
|
||||||
// perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
|
// perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
|
||||||
internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q);
|
// the complex to real operation returns true is the updated 2x2 block is not already diagonal
|
||||||
JacobiRotation<RealScalar> j_left, j_right;
|
if(internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q, maxDiagEntry))
|
||||||
internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
|
{
|
||||||
|
JacobiRotation<RealScalar> j_left, j_right;
|
||||||
|
internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
|
||||||
|
|
||||||
// accumulate resulting Jacobi rotations
|
// accumulate resulting Jacobi rotations
|
||||||
m_workMatrix.applyOnTheLeft(p,q,j_left);
|
m_workMatrix.applyOnTheLeft(p,q,j_left);
|
||||||
if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
|
if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
|
||||||
|
|
||||||
m_workMatrix.applyOnTheRight(p,q,j_right);
|
m_workMatrix.applyOnTheRight(p,q,j_right);
|
||||||
if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
|
if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
|
||||||
|
|
||||||
|
// keep track of the largest diagonal coefficient
|
||||||
|
maxDiagEntry = max EIGEN_EMPTY (maxDiagEntry,max EIGEN_EMPTY (abs(m_workMatrix.coeff(p,p)), abs(m_workMatrix.coeff(q,q))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPiv
|
|||||||
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix, unsigned int computationOptions) \
|
JacobiSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, ColPivHouseholderQRPreconditioner>::compute(const Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>& matrix, unsigned int computationOptions) \
|
||||||
{ \
|
{ \
|
||||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
typedef Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic> MatrixType; \
|
||||||
typedef MatrixType::Scalar Scalar; \
|
/*typedef MatrixType::Scalar Scalar;*/ \
|
||||||
typedef MatrixType::RealScalar RealScalar; \
|
/*typedef MatrixType::RealScalar RealScalar;*/ \
|
||||||
allocate(matrix.rows(), matrix.cols(), computationOptions); \
|
allocate(matrix.rows(), matrix.cols(), computationOptions); \
|
||||||
\
|
\
|
||||||
/*const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();*/ \
|
/*const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();*/ \
|
||||||
|
|||||||
@@ -102,6 +102,11 @@ class CompressedStorage
|
|||||||
inline size_t allocatedSize() const { return m_allocatedSize; }
|
inline size_t allocatedSize() const { return m_allocatedSize; }
|
||||||
inline void clear() { m_size = 0; }
|
inline void clear() { m_size = 0; }
|
||||||
|
|
||||||
|
const Scalar* valuePtr() const { return m_values; }
|
||||||
|
Scalar* valuePtr() { return m_values; }
|
||||||
|
const Index* indexPtr() const { return m_indices; }
|
||||||
|
Index* indexPtr() { return m_indices; }
|
||||||
|
|
||||||
inline Scalar& value(size_t i) { return m_values[i]; }
|
inline Scalar& value(size_t i) { return m_values[i]; }
|
||||||
inline const Scalar& value(size_t i) const { return m_values[i]; }
|
inline const Scalar& value(size_t i) const { return m_values[i]; }
|
||||||
|
|
||||||
@@ -208,8 +213,10 @@ class CompressedStorage
|
|||||||
Index* newIndices = new Index[size];
|
Index* newIndices = new Index[size];
|
||||||
size_t copySize = (std::min)(size, m_size);
|
size_t copySize = (std::min)(size, m_size);
|
||||||
// copy
|
// copy
|
||||||
internal::smart_copy(m_values, m_values+copySize, newValues);
|
if (copySize>0) {
|
||||||
internal::smart_copy(m_indices, m_indices+copySize, newIndices);
|
internal::smart_copy(m_values, m_values+copySize, newValues);
|
||||||
|
internal::smart_copy(m_indices, m_indices+copySize, newIndices);
|
||||||
|
}
|
||||||
// delete old stuff
|
// delete old stuff
|
||||||
delete[] m_values;
|
delete[] m_values;
|
||||||
delete[] m_indices;
|
delete[] m_indices;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -55,10 +55,9 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
|
|||||||
EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
|
EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
|
||||||
CwiseBinaryOpImpl()
|
CwiseBinaryOpImpl()
|
||||||
{
|
{
|
||||||
typedef typename internal::traits<Lhs>::StorageKind LhsStorageKind;
|
|
||||||
typedef typename internal::traits<Rhs>::StorageKind RhsStorageKind;
|
|
||||||
EIGEN_STATIC_ASSERT((
|
EIGEN_STATIC_ASSERT((
|
||||||
(!internal::is_same<LhsStorageKind,RhsStorageKind>::value)
|
(!internal::is_same<typename internal::traits<Lhs>::StorageKind,
|
||||||
|
typename internal::traits<Rhs>::StorageKind>::value)
|
||||||
|| ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
|
|| ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
|
||||||
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
|
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
|
||||||
}
|
}
|
||||||
@@ -314,10 +313,10 @@ SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& othe
|
|||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
|
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
|
||||||
SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
|
SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
|
||||||
{
|
{
|
||||||
return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(derived(), other.derived());
|
return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user