mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
1647 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
bc129ad79c | ||
|
|
f5328be65a | ||
|
|
735f1fda39 | ||
|
|
57ab550a17 | ||
|
|
e887c61b3d | ||
|
|
b8d9eaa19b | ||
|
|
f806c23012 | ||
|
|
99501a2c4c | ||
|
|
7dad5f797e | ||
|
|
dcad508986 | ||
|
|
26977e281e | ||
|
|
1e109e1757 | ||
|
|
e469ac55c3 | ||
|
|
874f345562 | ||
|
|
608733415a | ||
|
|
57ec399ec9 | ||
|
|
d85abc89c5 | ||
|
|
309620ee1f | ||
|
|
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 | ||
|
|
4577bafb91 | ||
|
|
739ed32222 | ||
|
|
58f0647f96 | ||
|
|
d0c3fcd382 | ||
|
|
19e16fe15f | ||
|
|
8f87be9e03 | ||
|
|
58725ff08c | ||
|
|
15bff016d1 | ||
|
|
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 | ||
|
|
547d660f1d | ||
|
|
5633cde9ad | ||
|
|
fe8757a576 | ||
|
|
ff29221951 | ||
|
|
7fbc9d8409 | ||
|
|
79c3cfabe3 | ||
|
|
e0f390793c | ||
|
|
97812ad0d3 | ||
|
|
d66b5a1d91 | ||
|
|
b0152fdb1d | ||
|
|
e9c5418249 | ||
|
|
b25b517817 | ||
|
|
ce0fb1bca1 | ||
|
|
92fce631ed | ||
|
|
238308e0f7 | ||
|
|
719ac0d6b0 | ||
|
|
8e61a7aab6 | ||
|
|
09e992ce9f | ||
|
|
cdd401f743 | ||
|
|
59b7615d31 | ||
|
|
a8cb0dfcf5 | ||
|
|
0e7a26c19f | ||
|
|
13c636d864 | ||
|
|
00ec1629ca | ||
|
|
a72eabec9b | ||
|
|
235c97ba92 | ||
|
|
4126cb6369 | ||
|
|
8ea2ab4829 | ||
|
|
9b79607579 | ||
|
|
aadbfe78c2 | ||
|
|
7d5e16c733 | ||
|
|
e395a8042a | ||
|
|
91f1a161ca | ||
|
|
16bca3bfe2 | ||
|
|
e0ab58d815 | ||
|
|
c67a7148c4 | ||
|
|
38dc683901 | ||
|
|
cad0fa5d77 | ||
|
|
5daebe0a27 | ||
|
|
05fb735d1d | ||
|
|
7443d8b4e9 | ||
|
|
36506511a1 | ||
|
|
3afdc6d95a | ||
|
|
c14c03490f | ||
|
|
c880590d27 | ||
|
|
54294e2293 | ||
|
|
c7331ebb06 | ||
|
|
0321449944 | ||
|
|
44c390a370 | ||
|
|
bbaf01712c | ||
|
|
8e875d3c38 | ||
|
|
8d69b87c53 | ||
|
|
49cbaf3856 | ||
|
|
9b00035438 | ||
|
|
e215740e8e | ||
|
|
0cc67589d3 | ||
|
|
51e2e93019 | ||
|
|
9d3e0da385 | ||
|
|
6ff72f40cf | ||
|
|
75d19bb087 | ||
|
|
62f948c56a | ||
|
|
da1e356306 | ||
|
|
54fbbe7b4e | ||
|
|
ea0906dfd8 | ||
|
|
cc1bacea5b | ||
|
|
c285fda7f4 | ||
|
|
160034bba1 | ||
|
|
1967e7f2f3 | ||
|
|
6eb16aae2d | ||
|
|
77d57cd681 | ||
|
|
4777ca1afb | ||
|
|
e3557e8dd2 | ||
|
|
5214466b7a | ||
|
|
0e0ae40084 | ||
|
|
5c4733f6e4 | ||
|
|
b73908000c | ||
|
|
b47ef1431f | ||
|
|
e25e674852 | ||
|
|
4b6b76463a | ||
|
|
904509fbb6 | ||
|
|
08b0c08e5e | ||
|
|
0dfb73d46a | ||
|
|
7fa83e7374 | ||
|
|
7d53633e05 | ||
|
|
bc072c5cba | ||
|
|
47981c5925 | ||
|
|
1eefa5a841 | ||
|
|
e4b6979334 | ||
|
|
b9ee880f07 | ||
|
|
2bf58316ee | ||
|
|
85777fc131 | ||
|
|
58687aa5e6 | ||
|
|
339f14b8d1 | ||
|
|
d4cc1bdc7f | ||
|
|
8e19027130 | ||
|
|
ef4a86d6b8 | ||
|
|
68eafc10b1 | ||
|
|
1cb71a8782 | ||
|
|
ac1bb3e5b3 | ||
|
|
4860da2de1 | ||
|
|
7a915f6846 | ||
|
|
1a817d3b70 | ||
|
|
8ee38d2db6 | ||
|
|
f365380496 | ||
|
|
3a9f9faada | ||
|
|
bbe9e22d60 | ||
|
|
998455a570 | ||
|
|
b18a7ff6be | ||
|
|
0a8e4712d1 | ||
|
|
61b88d2feb | ||
|
|
e84bdbb445 | ||
|
|
bf334b8ae5 | ||
|
|
8f4cdbbc8f | ||
|
|
7390af91b6 | ||
|
|
1e6f53e070 | ||
|
|
6f846ef9c6 | ||
|
|
324e7e8fc9 | ||
|
|
3c63446507 | ||
|
|
746d2db6ed | ||
|
|
441f97b2df | ||
|
|
0ad7a644df | ||
|
|
7ffd55c980 | ||
|
|
065344a06b | ||
|
|
75e574275c | ||
|
|
c401167712 | ||
|
|
73e686c6a4 | ||
|
|
ae039dde13 | ||
|
|
e1f1f66a52 | ||
|
|
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 | ||
|
|
caf4936661 | ||
|
|
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 | ||
|
|
0c4fc69d62 | ||
|
|
019dcfc21d | ||
|
|
19521c83b8 | ||
|
|
e16e52d493 | ||
|
|
c49421a82b | ||
|
|
ccd7beba90 | ||
|
|
84a99f3a93 | ||
|
|
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 | ||
|
|
43c2747e92 | ||
|
|
d9381598bc | ||
|
|
403be74861 | ||
|
|
1c61e28b32 | ||
|
|
c06e373beb | ||
|
|
3c5e82ee0b | ||
|
|
d132159ba3 | ||
|
|
075b1168b4 | ||
|
|
be027bede8 | ||
|
|
f1ed1b7d11 | ||
|
|
20b0747bdb | ||
|
|
11462c1a29 | ||
|
|
e667819055 | ||
|
|
35c9f8779d | ||
|
|
da81e863e2 | ||
|
|
c5c4269961 | ||
|
|
b734863536 | ||
|
|
1046ea7a89 | ||
|
|
8b10081dea | ||
|
|
042bd9cbe2 | ||
|
|
93e867b63c | ||
|
|
e702934dfa | ||
|
|
eef44fb2a5 | ||
|
|
eb9c8cffd6 | ||
|
|
240e2f4162 | ||
|
|
b0702dca05 | ||
|
|
7191f31961 | ||
|
|
6d7bd066e0 | ||
|
|
66078fbd58 | ||
|
|
4e80704c53 | ||
|
|
043ece9730 | ||
|
|
48db2b8799 | ||
|
|
593a82202f | ||
|
|
f24ba33c2d | ||
|
|
ef807ea020 | ||
|
|
da19c48d61 | ||
|
|
cef49d21f0 | ||
|
|
53726663c7 | ||
|
|
2ad3dac422 | ||
|
|
e3d34064bf | ||
|
|
3f5591981f | ||
|
|
6def9fd52b | ||
|
|
76ee39485f | ||
|
|
0c6b931cbc | ||
|
|
fd96ff166d | ||
|
|
9a09b75df3 | ||
|
|
52dc1d7ffd | ||
|
|
24e33a0d86 | ||
|
|
b5333b6760 | ||
|
|
6a4489c523 | ||
|
|
7958d92c23 | ||
|
|
044f27546f | ||
|
|
cd4ea5151f | ||
|
|
f9276f9f90 | ||
|
|
88ec3fdef4 | ||
|
|
5b93c59198 | ||
|
|
fd5be2f9cc | ||
|
|
598776b088 | ||
|
|
cdedc9e90d | ||
|
|
7c1fc0ee7c | ||
|
|
baf2b13589 | ||
|
|
12504a79d1 | ||
|
|
ae360a9ec0 | ||
|
|
516304cd90 | ||
|
|
4c5da3b03a | ||
|
|
b8020d11de | ||
|
|
6b931b3e47 | ||
|
|
d21708172a | ||
|
|
8946e0cb80 | ||
|
|
bf9747b9ff | ||
|
|
a5522a1381 | ||
|
|
d646cc95ad | ||
|
|
8ea9e762d6 | ||
|
|
0a44b5249c | ||
|
|
fbc5beadc8 | ||
|
|
b2368b3408 | ||
|
|
965ee4e853 | ||
|
|
d51c9f1e93 | ||
|
|
56f4144035 | ||
|
|
609ef90213 | ||
|
|
f407a86a3f | ||
|
|
0257cf1cef | ||
|
|
941319a198 | ||
|
|
273a952099 | ||
|
|
551d20a824 | ||
|
|
f5ed3421e9 | ||
|
|
945b0802c9 | ||
|
|
2a0ca0131d | ||
|
|
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 | ||
|
|
af74b16b0f | ||
|
|
f707f15842 | ||
|
|
a443b3d98d | ||
|
|
811ec5bfcb | ||
|
|
31d40ebc9d | ||
|
|
0c5f4fd8da | ||
|
|
2b50ade6ca | ||
|
|
f9149f9ba0 | ||
|
|
76d05e8236 | ||
|
|
fa81676d64 | ||
|
|
b56348046f | ||
|
|
47a7de7b53 | ||
|
|
8607779757 | ||
|
|
be71c46a3c | ||
|
|
4219db123e | ||
|
|
b1f4601bf9 | ||
|
|
acb82c7f16 | ||
|
|
9ef3645cc7 | ||
|
|
5f11db695b | ||
|
|
2437215221 | ||
|
|
dd27b5c4a8 | ||
|
|
70131120ab | ||
|
|
6d86cd7224 | ||
|
|
75dab1ce5e | ||
|
|
e43934d60f | ||
|
|
75edc7cc8b | ||
|
|
5897695e8a | ||
|
|
a3a55357db | ||
|
|
f003a6df38 | ||
|
|
56f9b810ab | ||
|
|
084dc63b4c | ||
|
|
463343fb37 | ||
|
|
5879937f58 | ||
|
|
01190b3544 | ||
|
|
c00f688c64 | ||
|
|
51573da3a4 | ||
|
|
1191949e87 | ||
|
|
3d94ed9fa0 | ||
|
|
ede27f5780 | ||
|
|
dda869051d | ||
|
|
2320073e41 | ||
|
|
c587e63631 | ||
|
|
12815309a6 | ||
|
|
207747a518 | ||
|
|
660b905e12 | ||
|
|
5ecfdf2c00 | ||
|
|
4f0bd557a4 | ||
|
|
e788869cf5 | ||
|
|
736fe99fbf | ||
|
|
9df04bcede | ||
|
|
6fab4012a3 | ||
|
|
2f593ee67c | ||
|
|
20e535e142 | ||
|
|
c31606c88a | ||
|
|
2872d964f4 | ||
|
|
2c288b3949 | ||
|
|
bbaef8ebba | ||
|
|
bd689ccc28 | ||
|
|
e3774e93b7 | ||
|
|
db8e88c936 | ||
|
|
cfd7f9b84a | ||
|
|
3e094af410 | ||
|
|
adeaa657eb | ||
|
|
f2aba7a768 | ||
|
|
d02e329218 | ||
|
|
c76990664b | ||
|
|
4b780553e0 | ||
|
|
9be658f701 | ||
|
|
b8f0364a1c | ||
|
|
ee244d54f4 | ||
|
|
cbe92de2b5 | ||
|
|
eeb744dc8d | ||
|
|
4bb0fff151 | ||
|
|
d5501d3a90 | ||
|
|
3c423ccfe2 | ||
|
|
738d75d3eb | ||
|
|
9a16519d62 | ||
|
|
06a5bcecf6 | ||
|
|
7ee378d89d | ||
|
|
61c3f55362 | ||
|
|
5431473d67 | ||
|
|
444c09e313 | ||
|
|
84f52ad317 | ||
|
|
6d1f5dbaae | ||
|
|
71cccf0ed8 | ||
|
|
5a4519d2b4 | ||
|
|
a992fa74eb | ||
|
|
4466875d54 | ||
|
|
5c95892b83 | ||
|
|
639d03d900 | ||
|
|
d204bb57d0 | ||
|
|
c52cbd9de9 | ||
|
|
159a3bed9e | ||
|
|
25544dbec3 | ||
|
|
f850550e3e | ||
|
|
04bd1e3fc0 | ||
|
|
0567cf96cc | ||
|
|
00e30a5fc4 | ||
|
|
55ec3cc6d5 | ||
|
|
4f28ccdd0e | ||
|
|
9b833aff42 | ||
|
|
3edd4681f2 | ||
|
|
d0142e963b | ||
|
|
8ba7ccf16a | ||
|
|
cc03c9d683 | ||
|
|
4f14b3fa72 | ||
|
|
9e2b4eeac0 | ||
|
|
9b9177f1ce | ||
|
|
7d8823c8b7 | ||
|
|
c273a6c37c | ||
|
|
04a9ad6e10 | ||
|
|
4e26057f66 | ||
|
|
edba612f68 | ||
|
|
cce68d4e91 | ||
|
|
75b3391e3f | ||
|
|
4020d4286f | ||
|
|
3cda1deb52 | ||
|
|
eaf92ef48c | ||
|
|
155fa0ca83 | ||
|
|
4e458d309c | ||
|
|
419b5cff44 | ||
|
|
1caeb814f0 | ||
|
|
f8e325356a | ||
|
|
65cc51288a | ||
|
|
22820e950e | ||
|
|
99bef0957b | ||
|
|
9f035c876a | ||
|
|
fc27cbd914 | ||
|
|
a915f0292e | ||
|
|
4cf742525f | ||
|
|
487d94f495 | ||
|
|
74beb218d2 | ||
|
|
ffbe04ae78 | ||
|
|
95f8a738ea | ||
|
|
231d4a6fda | ||
|
|
7b6e94fb58 | ||
|
|
b9543ce237 | ||
|
|
b9fc9d8f32 | ||
|
|
4cc9377941 | ||
|
|
ee8a28fb85 | ||
|
|
1330ca611b | ||
|
|
c21a04bcf9 | ||
|
|
c695cbf0fa | ||
|
|
8bbde351e7 | ||
|
|
d1d7a1ade9 | ||
|
|
fab0235369 | ||
|
|
bea4a67c92 | ||
|
|
260a923334 | ||
|
|
3ed919e0ed | ||
|
|
dd964ec08c | ||
|
|
620e4277bc | ||
|
|
8cc9b12589 | ||
|
|
cf5c5ed725 | ||
|
|
7adfca5af2 | ||
|
|
c0cad44da6 | ||
|
|
8105b5ed3f | ||
|
|
ba79e39c5c | ||
|
|
eef8d98139 | ||
|
|
4e6d746514 | ||
|
|
e37ff98bbb | ||
|
|
05da15bf40 | ||
|
|
33788b97dd | ||
|
|
79bd6fa5ee | ||
|
|
a8494787f4 | ||
|
|
437e26d000 | ||
|
|
55365566b2 | ||
|
|
9f11f80db1 | ||
|
|
5f178e54e9 | ||
|
|
d5fa5001a7 | ||
|
|
3352b8d873 | ||
|
|
d541765e85 | ||
|
|
f75419c711 | ||
|
|
f3a029e957 | ||
|
|
1b92d2ca33 | ||
|
|
f6c1841316 | ||
|
|
65c59307e2 | ||
|
|
62670c83a0 | ||
|
|
827843bbbd | ||
|
|
76f4820560 | ||
|
|
f0efe60924 | ||
|
|
92eb807c30 | ||
|
|
7742eacfeb | ||
|
|
f3af423c70 | ||
|
|
1bf18bd57f | ||
|
|
9266f65318 | ||
|
|
4cd8245c96 | ||
|
|
b3fff170a0 | ||
|
|
18e476107e | ||
|
|
ca67c60150 | ||
|
|
05c9be65ce | ||
|
|
a4a575e2a3 | ||
|
|
26c35b95c7 | ||
|
|
0525874a03 | ||
|
|
2b6528effc | ||
|
|
47e89026d0 | ||
|
|
e8c963568c | ||
|
|
b6d3fcf6f2 | ||
|
|
e392948548 | ||
|
|
4811b4526c | ||
|
|
a69b4b092b | ||
|
|
c98fd7a6ca | ||
|
|
e04b59929e | ||
|
|
64054ee396 | ||
|
|
b3adc4face | ||
|
|
62e337eb01 | ||
|
|
d7cd957f10 | ||
|
|
e0566a817f | ||
|
|
8e050bd681 | ||
|
|
cf939f154f | ||
|
|
bd7511fc36 | ||
|
|
bd0474adbb | ||
|
|
9ab3811cc5 | ||
|
|
b5e5b6aa57 | ||
|
|
12e69ec896 | ||
|
|
8556ca3de5 | ||
|
|
f7bdbf69e1 | ||
|
|
83736e9c61 | ||
|
|
122b16d841 | ||
|
|
43bb942365 | ||
|
|
fcdbfabf7a | ||
|
|
aa8b897607 | ||
|
|
9cd2d14005 | ||
|
|
4e2e615a7c | ||
|
|
46755648ec | ||
|
|
41b3c56e61 | ||
|
|
9a4caf2b0f | ||
|
|
94e20f485c | ||
|
|
d4b0c19a46 | ||
|
|
db43205dc6 | ||
|
|
9816e8532e | ||
|
|
43f4fd4d71 | ||
|
|
7450b23fbb | ||
|
|
6eaff5a098 | ||
|
|
1e38928c64 | ||
|
|
ff661a7b6f | ||
|
|
899c0c2b6c | ||
|
|
7e04d7db02 | ||
|
|
f7e52d22d4 | ||
|
|
84637ca58c | ||
|
|
d7f3cfb56e | ||
|
|
3cb6e21f80 | ||
|
|
d8f1035355 | ||
|
|
bff264283d | ||
|
|
8f44205671 | ||
|
|
d97cd746ae | ||
|
|
12439e1249 | ||
|
|
9b33ab62da | ||
|
|
c3a6fa03a2 | ||
|
|
0a1d9fb9ae | ||
|
|
225fd0f579 | ||
|
|
c519be2bac | ||
|
|
f350f34560 | ||
|
|
d63712163c | ||
|
|
da6219b19d | ||
|
|
22460edb49 | ||
|
|
4107b371e3 | ||
|
|
9bfeeba1c5 | ||
|
|
11a9091084 | ||
|
|
aba50d842e | ||
|
|
f29b4c435b | ||
|
|
0d5a418048 | ||
|
|
d6d638c751 | ||
|
|
6357fd68da | ||
|
|
f8addac4e1 | ||
|
|
5d1a74da0a | ||
|
|
6c68f1d787 | ||
|
|
79f93247c5 | ||
|
|
97c9e3c74f | ||
|
|
03373f41cb | ||
|
|
f82ee241ac | ||
|
|
d93c1c113b | ||
|
|
968f7591f8 | ||
|
|
5adcc6c7b4 |
@@ -1,6 +1,6 @@
|
|||||||
project(Eigen)
|
project(Eigen)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.6.2)
|
cmake_minimum_required(VERSION 2.8.2)
|
||||||
|
|
||||||
# guard against in-source builds
|
# guard against in-source builds
|
||||||
|
|
||||||
@@ -107,27 +107,64 @@ endif()
|
|||||||
|
|
||||||
set(EIGEN_TEST_MAX_SIZE "320" CACHE STRING "Maximal matrix/vector size, default is 320")
|
set(EIGEN_TEST_MAX_SIZE "320" CACHE STRING "Maximal matrix/vector size, default is 320")
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
macro(ei_add_cxx_compiler_flag FLAG)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fexceptions -fno-check-new -fno-common -fstrict-aliasing")
|
string(REGEX REPLACE "-" "" SFLAG ${FLAG})
|
||||||
|
check_cxx_compiler_flag(${FLAG} COMPILER_SUPPORT_${SFLAG})
|
||||||
|
if(COMPILER_SUPPORT_${SFLAG})
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}")
|
||||||
|
endif()
|
||||||
|
endmacro(ei_add_cxx_compiler_flag)
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
# We assume that other compilers are partly compatible with GNUCC
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g3")
|
set(CMAKE_CXX_FLAGS_DEBUG "-g3")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2")
|
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2")
|
||||||
|
|
||||||
check_cxx_compiler_flag("-Wno-psabi" COMPILER_SUPPORT_WNOPSABI)
|
# clang outputs some warnings for unknwon flags that are not caught by check_cxx_compiler_flag
|
||||||
if(COMPILER_SUPPORT_WNOPSABI)
|
# adding -Werror turns such warnings into errors
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi")
|
check_cxx_compiler_flag("-Werror" COMPILER_SUPPORT_WERROR)
|
||||||
|
if(COMPILER_SUPPORT_WERROR)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_cxx_compiler_flag("-Wno-variadic-macros" COMPILER_SUPPORT_WNOVARIADICMACRO)
|
ei_add_cxx_compiler_flag("-pedantic")
|
||||||
if(COMPILER_SUPPORT_WNOVARIADICMACRO)
|
ei_add_cxx_compiler_flag("-Wall")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros")
|
ei_add_cxx_compiler_flag("-Wextra")
|
||||||
|
#ei_add_cxx_compiler_flag("-Weverything") # clang
|
||||||
|
|
||||||
|
ei_add_cxx_compiler_flag("-Wundef")
|
||||||
|
ei_add_cxx_compiler_flag("-Wcast-align")
|
||||||
|
ei_add_cxx_compiler_flag("-Wchar-subscripts")
|
||||||
|
ei_add_cxx_compiler_flag("-Wnon-virtual-dtor")
|
||||||
|
ei_add_cxx_compiler_flag("-Wunused-local-typedefs")
|
||||||
|
ei_add_cxx_compiler_flag("-Wpointer-arith")
|
||||||
|
ei_add_cxx_compiler_flag("-Wwrite-strings")
|
||||||
|
ei_add_cxx_compiler_flag("-Wformat-security")
|
||||||
|
|
||||||
|
ei_add_cxx_compiler_flag("-Wno-psabi")
|
||||||
|
ei_add_cxx_compiler_flag("-Wno-variadic-macros")
|
||||||
|
ei_add_cxx_compiler_flag("-Wno-long-long")
|
||||||
|
|
||||||
|
ei_add_cxx_compiler_flag("-fno-check-new")
|
||||||
|
ei_add_cxx_compiler_flag("-fno-common")
|
||||||
|
ei_add_cxx_compiler_flag("-fstrict-aliasing")
|
||||||
|
ei_add_cxx_compiler_flag("-wd981") # disable ICC's "operands are evaluated in unspecified order" remark
|
||||||
|
ei_add_cxx_compiler_flag("-wd2304") # disbale ICC's "warning #2304: non-explicit constructor with single argument may cause implicit type conversion" produced by -Wnon-virtual-dtor
|
||||||
|
|
||||||
|
# The -ansi flag must be added last, otherwise it is also used as a linker flag by check_cxx_compiler_flag making it fails
|
||||||
|
# Moreover we should not set both -strict-ansi and -ansi
|
||||||
|
check_cxx_compiler_flag("-strict-ansi" COMPILER_SUPPORT_STRICTANSI)
|
||||||
|
ei_add_cxx_compiler_flag("-Qunused-arguments") # disable clang warning: argument unused during compilation: '-ansi'
|
||||||
|
|
||||||
|
if(COMPILER_SUPPORT_STRICTANSI)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -strict-ansi")
|
||||||
|
else()
|
||||||
|
ei_add_cxx_compiler_flag("-ansi")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_cxx_compiler_flag("-Wextra" COMPILER_SUPPORT_WEXTRA)
|
set(CMAKE_REQUIRED_FLAGS "")
|
||||||
if(COMPILER_SUPPORT_WEXTRA)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
||||||
|
|
||||||
option(EIGEN_TEST_SSE2 "Enable/Disable SSE2 in tests/examples" OFF)
|
option(EIGEN_TEST_SSE2 "Enable/Disable SSE2 in tests/examples" OFF)
|
||||||
if(EIGEN_TEST_SSE2)
|
if(EIGEN_TEST_SSE2)
|
||||||
@@ -167,7 +204,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
|
|
||||||
option(EIGEN_TEST_NEON "Enable/Disable Neon in tests/examples" OFF)
|
option(EIGEN_TEST_NEON "Enable/Disable Neon in tests/examples" OFF)
|
||||||
if(EIGEN_TEST_NEON)
|
if(EIGEN_TEST_NEON)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -mcpu=cortex-a"8)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -mcpu=cortex-a8")
|
||||||
message(STATUS "Enabling NEON in tests/examples")
|
message(STATUS "Enabling NEON in tests/examples")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -180,9 +217,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
else(NOT MSVC)
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
# C4127 - conditional expression is constant
|
# C4127 - conditional expression is constant
|
||||||
# C4714 - marked as __forceinline not inlined (I failed to deactivate it selectively)
|
# C4714 - marked as __forceinline not inlined (I failed to deactivate it selectively)
|
||||||
# We can disable this warning in the unit tests since it is clear that it occurs
|
# We can disable this warning in the unit tests since it is clear that it occurs
|
||||||
@@ -212,7 +248,7 @@ if(MSVC)
|
|||||||
endif(NOT CMAKE_CL_64)
|
endif(NOT CMAKE_CL_64)
|
||||||
message(STATUS "Enabling SSE2 in tests/examples")
|
message(STATUS "Enabling SSE2 in tests/examples")
|
||||||
endif(EIGEN_TEST_SSE2)
|
endif(EIGEN_TEST_SSE2)
|
||||||
endif(MSVC)
|
endif(NOT MSVC)
|
||||||
|
|
||||||
option(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION "Disable explicit vectorization in tests/examples" OFF)
|
option(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION "Disable explicit vectorization in tests/examples" OFF)
|
||||||
option(EIGEN_TEST_X87 "Force using X87 instructions. Implies no vectorization." OFF)
|
option(EIGEN_TEST_X87 "Force using X87 instructions. Implies no vectorization." OFF)
|
||||||
@@ -311,6 +347,7 @@ add_subdirectory(Eigen)
|
|||||||
add_subdirectory(doc EXCLUDE_FROM_ALL)
|
add_subdirectory(doc EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
include(EigenConfigureTesting)
|
include(EigenConfigureTesting)
|
||||||
|
|
||||||
# fixme, not sure this line is still needed:
|
# fixme, not sure this line is still needed:
|
||||||
enable_testing() # must be called from the root CMakeLists, see man page
|
enable_testing() # must be called from the root CMakeLists, see man page
|
||||||
|
|
||||||
@@ -345,6 +382,8 @@ if(NOT WIN32)
|
|||||||
add_subdirectory(bench/spbench EXCLUDE_FROM_ALL)
|
add_subdirectory(bench/spbench EXCLUDE_FROM_ALL)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
configure_file(scripts/cdashtesting.cmake.in cdashtesting.cmake @ONLY)
|
||||||
|
|
||||||
ei_testing_print_summary()
|
ei_testing_print_summary()
|
||||||
|
|
||||||
message(STATUS "")
|
message(STATUS "")
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
## # The following are required to uses Dart and the Cdash dashboard
|
## # The following are required to uses Dart and the Cdash dashboard
|
||||||
## ENABLE_TESTING()
|
## ENABLE_TESTING()
|
||||||
## INCLUDE(CTest)
|
## INCLUDE(CTest)
|
||||||
set(CTEST_PROJECT_NAME "Eigen")
|
set(CTEST_PROJECT_NAME "Eigen3.2")
|
||||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
|
set(CTEST_NIGHTLY_START_TIME "00:00:00 UTC")
|
||||||
|
|
||||||
set(CTEST_DROP_METHOD "http")
|
set(CTEST_DROP_METHOD "http")
|
||||||
set(CTEST_DROP_SITE "manao.inria.fr")
|
set(CTEST_DROP_SITE "manao.inria.fr")
|
||||||
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen")
|
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen3.2")
|
||||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
## A tribute to Dynamic!
|
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "2000")
|
||||||
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "33331")
|
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "2000")
|
||||||
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "33331")
|
|
||||||
|
|||||||
23
Eigen/Core
23
Eigen/Core
@@ -19,6 +19,12 @@
|
|||||||
// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
|
// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
|
||||||
#include "src/Core/util/Macros.h"
|
#include "src/Core/util/Macros.h"
|
||||||
|
|
||||||
|
// Disable the ipa-cp-clone optimization flag with MinGW 6.x or newer (enabled by default with -O3)
|
||||||
|
// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details.
|
||||||
|
#if defined(__MINGW32__) && EIGEN_GNUC_AT_LEAST(4,6)
|
||||||
|
#pragma GCC optimize ("-fno-ipa-cp-clone")
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <complex>
|
#include <complex>
|
||||||
|
|
||||||
// this include file manages BLAS and MKL related macros
|
// this include file manages BLAS and MKL related macros
|
||||||
@@ -44,7 +50,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
// Remember that usage of defined() in a #define is undefined by the standard
|
// Remember that usage of defined() in a #define is undefined by the standard
|
||||||
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
|
#if (defined __SSE2__) && ( (!defined __GNUC__) || (defined __INTEL_COMPILER) || EIGEN_GNUC_AT_LEAST(4,2) )
|
||||||
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
|
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -89,7 +95,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
// In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
|
// In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
|
||||||
// Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
|
// Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
|
||||||
#ifdef __INTEL_COMPILER
|
#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1110
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#else
|
#else
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
@@ -117,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>
|
||||||
@@ -159,7 +165,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// required for __cpuid, needs to be included after cmath
|
// required for __cpuid, needs to be included after cmath
|
||||||
#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64))
|
#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64)) && (!defined(_WIN32_WCE))
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -245,8 +251,8 @@ using std::ptrdiff_t;
|
|||||||
#include "src/Core/util/Constants.h"
|
#include "src/Core/util/Constants.h"
|
||||||
#include "src/Core/util/ForwardDeclarations.h"
|
#include "src/Core/util/ForwardDeclarations.h"
|
||||||
#include "src/Core/util/Meta.h"
|
#include "src/Core/util/Meta.h"
|
||||||
#include "src/Core/util/XprHelper.h"
|
|
||||||
#include "src/Core/util/StaticAssert.h"
|
#include "src/Core/util/StaticAssert.h"
|
||||||
|
#include "src/Core/util/XprHelper.h"
|
||||||
#include "src/Core/util/Memory.h"
|
#include "src/Core/util/Memory.h"
|
||||||
|
|
||||||
#include "src/Core/NumTraits.h"
|
#include "src/Core/NumTraits.h"
|
||||||
@@ -344,13 +350,6 @@ using std::ptrdiff_t;
|
|||||||
#include "src/Core/ArrayBase.h"
|
#include "src/Core/ArrayBase.h"
|
||||||
#include "src/Core/ArrayWrapper.h"
|
#include "src/Core/ArrayWrapper.h"
|
||||||
|
|
||||||
#ifdef EIGEN_ENABLE_EVALUATORS
|
|
||||||
#include "src/Core/Product.h"
|
|
||||||
#include "src/Core/CoreEvaluators.h"
|
|
||||||
#include "src/Core/AssignEvaluator.h"
|
|
||||||
#include "src/Core/ProductEvaluators.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EIGEN_USE_BLAS
|
#ifdef EIGEN_USE_BLAS
|
||||||
#include "src/Core/products/GeneralMatrixMatrix_MKL.h"
|
#include "src/Core/products/GeneralMatrixMatrix_MKL.h"
|
||||||
#include "src/Core/products/GeneralMatrixVector_MKL.h"
|
#include "src/Core/products/GeneralMatrixVector_MKL.h"
|
||||||
|
|||||||
@@ -14,12 +14,25 @@
|
|||||||
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
|
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EIGEN_NO_EIGEN2_DEPRECATED_WARNING
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||||
|
#warning "Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)"
|
||||||
|
#else
|
||||||
|
#pragma message ("Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // EIGEN_NO_EIGEN2_DEPRECATED_WARNING
|
||||||
|
|
||||||
#include "src/Core/util/DisableStupidWarnings.h"
|
#include "src/Core/util/DisableStupidWarnings.h"
|
||||||
|
|
||||||
/** \ingroup Support_modules
|
/** \ingroup Support_modules
|
||||||
* \defgroup Eigen2Support_Module Eigen2 support module
|
* \defgroup Eigen2Support_Module Eigen2 support module
|
||||||
* This module provides a couple of deprecated functions improving the compatibility with Eigen2.
|
|
||||||
*
|
*
|
||||||
|
* \warning Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3.
|
||||||
|
*
|
||||||
|
* This module provides a couple of deprecated functions improving the compatibility with Eigen2.
|
||||||
|
*
|
||||||
* To use it, define EIGEN2_SUPPORT before including any Eigen header
|
* To use it, define EIGEN2_SUPPORT before including any Eigen header
|
||||||
* \code
|
* \code
|
||||||
* #define EIGEN2_SUPPORT
|
* #define EIGEN2_SUPPORT
|
||||||
|
|||||||
@@ -26,4 +26,4 @@
|
|||||||
#include "src/CholmodSupport/CholmodSupport.h"
|
#include "src/CholmodSupport/CholmodSupport.h"
|
||||||
#include "src/SPQRSupport/SuiteSparseQRSupport.h"
|
#include "src/SPQRSupport/SuiteSparseQRSupport.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
14
Eigen/Sparse
14
Eigen/Sparse
@@ -1,13 +1,15 @@
|
|||||||
#ifndef EIGEN_SPARSE_MODULE_H
|
#ifndef EIGEN_SPARSE_MODULE_H
|
||||||
#define EIGEN_SPARSE_MODULE_H
|
#define EIGEN_SPARSE_MODULE_H
|
||||||
|
|
||||||
/** defgroup Sparse_modules Sparse modules
|
/** \defgroup Sparse_Module Sparse meta-module
|
||||||
*
|
*
|
||||||
* Meta-module including all related modules:
|
* Meta-module including all related modules:
|
||||||
* - SparseCore
|
* - \ref SparseCore_Module
|
||||||
* - OrderingMethods
|
* - \ref OrderingMethods_Module
|
||||||
* - SparseCholesky
|
* - \ref SparseCholesky_Module
|
||||||
* - IterativeLinearSolvers
|
* - \ref SparseLU_Module
|
||||||
|
* - \ref SparseQR_Module
|
||||||
|
* - \ref IterativeLinearSolvers_Module
|
||||||
*
|
*
|
||||||
* \code
|
* \code
|
||||||
* #include <Eigen/Sparse>
|
* #include <Eigen/Sparse>
|
||||||
@@ -17,6 +19,8 @@
|
|||||||
#include "SparseCore"
|
#include "SparseCore"
|
||||||
#include "OrderingMethods"
|
#include "OrderingMethods"
|
||||||
#include "SparseCholesky"
|
#include "SparseCholesky"
|
||||||
|
#include "SparseLU"
|
||||||
|
#include "SparseQR"
|
||||||
#include "IterativeLinearSolvers"
|
#include "IterativeLinearSolvers"
|
||||||
|
|
||||||
#endif // EIGEN_SPARSE_MODULE_H
|
#endif // EIGEN_SPARSE_MODULE_H
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
|
// This file is part of Eigen, a lightweight C++ template library
|
||||||
|
// for linear algebra.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2008-2013 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla
|
||||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
#ifndef EIGEN_SPARSECHOLESKY_MODULE_H
|
#ifndef EIGEN_SPARSECHOLESKY_MODULE_H
|
||||||
#define EIGEN_SPARSECHOLESKY_MODULE_H
|
#define EIGEN_SPARSECHOLESKY_MODULE_H
|
||||||
|
|
||||||
#include "SparseCore"
|
#include "SparseCore"
|
||||||
|
#include "OrderingMethods"
|
||||||
|
|
||||||
#include "src/Core/util/DisableStupidWarnings.h"
|
#include "src/Core/util/DisableStupidWarnings.h"
|
||||||
|
|
||||||
@@ -26,7 +36,6 @@
|
|||||||
|
|
||||||
#include "src/misc/Solve.h"
|
#include "src/misc/Solve.h"
|
||||||
#include "src/misc/SparseSolve.h"
|
#include "src/misc/SparseSolve.h"
|
||||||
|
|
||||||
#include "src/SparseCholesky/SimplicialCholesky.h"
|
#include "src/SparseCholesky/SimplicialCholesky.h"
|
||||||
|
|
||||||
#ifndef EIGEN_MPL2_ONLY
|
#ifndef EIGEN_MPL2_ONLY
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
* Please, see the documentation of the SparseLU class for more details.
|
* Please, see the documentation of the SparseLU class for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "src/misc/Solve.h"
|
||||||
|
#include "src/misc/SparseSolve.h"
|
||||||
|
|
||||||
// Ordering interface
|
// Ordering interface
|
||||||
#include "OrderingMethods"
|
#include "OrderingMethods"
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "src/misc/Solve.h"
|
||||||
|
#include "src/misc/SparseSolve.h"
|
||||||
|
|
||||||
#include "OrderingMethods"
|
#include "OrderingMethods"
|
||||||
#include "src/SparseCore/SparseColEtree.h"
|
#include "src/SparseCore/SparseColEtree.h"
|
||||||
#include "src/SparseQR/SparseQR.h"
|
#include "src/SparseQR/SparseQR.h"
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template<typename MatrixType, int UpLo> struct LDLT_Traits;
|
template<typename MatrixType, int UpLo> struct LDLT_Traits;
|
||||||
|
|
||||||
|
// PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
|
||||||
|
enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \ingroup Cholesky_Module
|
/** \ingroup Cholesky_Module
|
||||||
@@ -69,7 +72,12 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
* The default constructor is useful in cases in which the user intends to
|
* The default constructor is useful in cases in which the user intends to
|
||||||
* perform decompositions via LDLT::compute(const MatrixType&).
|
* perform decompositions via LDLT::compute(const MatrixType&).
|
||||||
*/
|
*/
|
||||||
LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {}
|
LDLT()
|
||||||
|
: m_matrix(),
|
||||||
|
m_transpositions(),
|
||||||
|
m_sign(internal::ZeroSign),
|
||||||
|
m_isInitialized(false)
|
||||||
|
{}
|
||||||
|
|
||||||
/** \brief Default Constructor with memory preallocation
|
/** \brief Default Constructor with memory preallocation
|
||||||
*
|
*
|
||||||
@@ -81,6 +89,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
: m_matrix(size, size),
|
: m_matrix(size, size),
|
||||||
m_transpositions(size),
|
m_transpositions(size),
|
||||||
m_temporary(size),
|
m_temporary(size),
|
||||||
|
m_sign(internal::ZeroSign),
|
||||||
m_isInitialized(false)
|
m_isInitialized(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -93,6 +102,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
: m_matrix(matrix.rows(), matrix.cols()),
|
: m_matrix(matrix.rows(), matrix.cols()),
|
||||||
m_transpositions(matrix.rows()),
|
m_transpositions(matrix.rows()),
|
||||||
m_temporary(matrix.rows()),
|
m_temporary(matrix.rows()),
|
||||||
|
m_sign(internal::ZeroSign),
|
||||||
m_isInitialized(false)
|
m_isInitialized(false)
|
||||||
{
|
{
|
||||||
compute(matrix);
|
compute(matrix);
|
||||||
@@ -139,7 +149,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
inline bool isPositive() const
|
inline bool isPositive() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
return m_sign == 1;
|
return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
@@ -153,7 +163,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
inline bool isNegative(void) const
|
inline bool isNegative(void) const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||||
return m_sign == -1;
|
return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
|
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||||
@@ -225,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.
|
||||||
@@ -235,7 +250,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
|||||||
MatrixType m_matrix;
|
MatrixType m_matrix;
|
||||||
TranspositionType m_transpositions;
|
TranspositionType m_transpositions;
|
||||||
TmpMatrixType m_temporary;
|
TmpMatrixType m_temporary;
|
||||||
int m_sign;
|
internal::SignMatrix m_sign;
|
||||||
bool m_isInitialized;
|
bool m_isInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -246,7 +261,7 @@ template<int UpLo> struct ldlt_inplace;
|
|||||||
template<> struct ldlt_inplace<Lower>
|
template<> struct ldlt_inplace<Lower>
|
||||||
{
|
{
|
||||||
template<typename MatrixType, typename TranspositionType, typename Workspace>
|
template<typename MatrixType, typename TranspositionType, typename Workspace>
|
||||||
static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
|
static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
|
||||||
{
|
{
|
||||||
using std::abs;
|
using std::abs;
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
@@ -258,45 +273,19 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
if (size <= 1)
|
if (size <= 1)
|
||||||
{
|
{
|
||||||
transpositions.setIdentity();
|
transpositions.setIdentity();
|
||||||
if(sign)
|
if (numext::real(mat.coeff(0,0)) > 0) sign = PositiveSemiDef;
|
||||||
*sign = real(mat.coeff(0,0))>0 ? 1:-1;
|
else if (numext::real(mat.coeff(0,0)) < 0) sign = NegativeSemiDef;
|
||||||
|
else sign = ZeroSign;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RealScalar cutoff(0), biggest_in_corner;
|
|
||||||
|
|
||||||
for (Index k = 0; k < size; ++k)
|
for (Index k = 0; k < size; ++k)
|
||||||
{
|
{
|
||||||
// Find largest diagonal element
|
// Find largest diagonal element
|
||||||
Index index_of_biggest_in_corner;
|
Index index_of_biggest_in_corner;
|
||||||
biggest_in_corner = mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
|
mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
|
||||||
index_of_biggest_in_corner += k;
|
index_of_biggest_in_corner += k;
|
||||||
|
|
||||||
if(k == 0)
|
|
||||||
{
|
|
||||||
// The biggest overall is the point of reference to which further diagonals
|
|
||||||
// are compared; if any diagonal is negligible compared
|
|
||||||
// to the largest overall, the algorithm bails.
|
|
||||||
cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner);
|
|
||||||
|
|
||||||
if(sign)
|
|
||||||
*sign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0 ? 1 : -1;
|
|
||||||
}
|
|
||||||
else if(sign)
|
|
||||||
{
|
|
||||||
// LDLT is not guaranteed to work for indefinite matrices, but let's try to get the sign right
|
|
||||||
int newSign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0;
|
|
||||||
if(newSign != *sign)
|
|
||||||
*sign = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish early if the matrix is not full rank.
|
|
||||||
if(biggest_in_corner < cutoff)
|
|
||||||
{
|
|
||||||
for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
transpositions.coeffRef(k) = index_of_biggest_in_corner;
|
transpositions.coeffRef(k) = index_of_biggest_in_corner;
|
||||||
if(k != index_of_biggest_in_corner)
|
if(k != index_of_biggest_in_corner)
|
||||||
{
|
{
|
||||||
@@ -309,11 +298,11 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
for(int i=k+1;i<index_of_biggest_in_corner;++i)
|
for(int i=k+1;i<index_of_biggest_in_corner;++i)
|
||||||
{
|
{
|
||||||
Scalar tmp = mat.coeffRef(i,k);
|
Scalar tmp = mat.coeffRef(i,k);
|
||||||
mat.coeffRef(i,k) = conj(mat.coeffRef(index_of_biggest_in_corner,i));
|
mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
|
||||||
mat.coeffRef(index_of_biggest_in_corner,i) = conj(tmp);
|
mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
|
||||||
}
|
}
|
||||||
if(NumTraits<Scalar>::IsComplex)
|
if(NumTraits<Scalar>::IsComplex)
|
||||||
mat.coeffRef(index_of_biggest_in_corner,k) = conj(mat.coeff(index_of_biggest_in_corner,k));
|
mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
|
||||||
}
|
}
|
||||||
|
|
||||||
// partition the matrix:
|
// partition the matrix:
|
||||||
@@ -327,13 +316,28 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
|
|
||||||
if(k>0)
|
if(k>0)
|
||||||
{
|
{
|
||||||
temp.head(k) = mat.diagonal().head(k).asDiagonal() * A10.adjoint();
|
temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
|
||||||
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
|
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
|
||||||
if(rs>0)
|
if(rs>0)
|
||||||
A21.noalias() -= A20 * temp.head(k);
|
A21.noalias() -= A20 * temp.head(k);
|
||||||
}
|
}
|
||||||
if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff))
|
|
||||||
A21 /= mat.coeffRef(k,k);
|
// In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
|
||||||
|
// was smaller than the cutoff value. However, soince LDLT is not rank-revealing
|
||||||
|
// we should only make sure we do not introduce INF or NaN values.
|
||||||
|
// LAPACK also uses 0 as the cutoff value.
|
||||||
|
RealScalar realAkk = numext::real(mat.coeffRef(k,k));
|
||||||
|
if((rs>0) && (abs(realAkk) > RealScalar(0)))
|
||||||
|
A21 /= realAkk;
|
||||||
|
|
||||||
|
if (sign == PositiveSemiDef) {
|
||||||
|
if (realAkk < 0) sign = Indefinite;
|
||||||
|
} else if (sign == NegativeSemiDef) {
|
||||||
|
if (realAkk > 0) sign = Indefinite;
|
||||||
|
} else if (sign == ZeroSign) {
|
||||||
|
if (realAkk > 0) sign = PositiveSemiDef;
|
||||||
|
else if (realAkk < 0) sign = NegativeSemiDef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -349,7 +353,7 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
template<typename MatrixType, typename WDerived>
|
template<typename MatrixType, typename WDerived>
|
||||||
static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
|
static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
|
||||||
{
|
{
|
||||||
using internal::isfinite;
|
using numext::isfinite;
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::RealScalar RealScalar;
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
@@ -367,9 +371,9 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// Update the diagonal terms
|
// Update the diagonal terms
|
||||||
RealScalar dj = real(mat.coeff(j,j));
|
RealScalar dj = numext::real(mat.coeff(j,j));
|
||||||
Scalar wj = w.coeff(j);
|
Scalar wj = w.coeff(j);
|
||||||
RealScalar swj2 = sigma*abs2(wj);
|
RealScalar swj2 = sigma*numext::abs2(wj);
|
||||||
RealScalar gamma = dj*alpha + swj2;
|
RealScalar gamma = dj*alpha + swj2;
|
||||||
|
|
||||||
mat.coeffRef(j,j) += swj2/alpha;
|
mat.coeffRef(j,j) += swj2/alpha;
|
||||||
@@ -380,7 +384,7 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
Index rs = size-j-1;
|
Index rs = size-j-1;
|
||||||
w.tail(rs) -= wj * mat.col(j).tail(rs);
|
w.tail(rs) -= wj * mat.col(j).tail(rs);
|
||||||
if(gamma != 0)
|
if(gamma != 0)
|
||||||
mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs);
|
mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -398,7 +402,7 @@ template<> struct ldlt_inplace<Lower>
|
|||||||
template<> struct ldlt_inplace<Upper>
|
template<> struct ldlt_inplace<Upper>
|
||||||
{
|
{
|
||||||
template<typename MatrixType, typename TranspositionType, typename Workspace>
|
template<typename MatrixType, typename TranspositionType, typename Workspace>
|
||||||
static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
|
static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
|
||||||
{
|
{
|
||||||
Transpose<MatrixType> matt(mat);
|
Transpose<MatrixType> matt(mat);
|
||||||
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
|
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
|
||||||
@@ -435,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();
|
||||||
|
|
||||||
@@ -443,8 +449,9 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
|||||||
m_transpositions.resize(size);
|
m_transpositions.resize(size);
|
||||||
m_isInitialized = false;
|
m_isInitialized = false;
|
||||||
m_temporary.resize(size);
|
m_temporary.resize(size);
|
||||||
|
m_sign = internal::ZeroSign;
|
||||||
|
|
||||||
internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, &m_sign);
|
internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign);
|
||||||
|
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -472,7 +479,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Deri
|
|||||||
for (Index i = 0; i < size; i++)
|
for (Index i = 0; i < size; i++)
|
||||||
m_transpositions.coeffRef(i) = i;
|
m_transpositions.coeffRef(i) = i;
|
||||||
m_temporary.resize(size);
|
m_temporary.resize(size);
|
||||||
m_sign = sigma>=0 ? 1 : -1;
|
m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
|
||||||
m_isInitialized = true;
|
m_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,16 +510,21 @@ struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
|
|||||||
using std::abs;
|
using std::abs;
|
||||||
using std::max;
|
using std::max;
|
||||||
typedef typename LDLTType::MatrixType MatrixType;
|
typedef typename LDLTType::MatrixType MatrixType;
|
||||||
typedef typename LDLTType::Scalar Scalar;
|
|
||||||
typedef typename LDLTType::RealScalar RealScalar;
|
typedef typename LDLTType::RealScalar RealScalar;
|
||||||
const Diagonal<const MatrixType> vectorD = dec().vectorD();
|
const typename Diagonal<const MatrixType>::RealReturnType vectorD(dec().vectorD());
|
||||||
RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
|
// In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon
|
||||||
RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS
|
// as motivated by LAPACK's xGELSS:
|
||||||
|
// RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() *NumTraits<RealScalar>::epsilon(),RealScalar(1) / NumTraits<RealScalar>::highest());
|
||||||
|
// However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest
|
||||||
|
// diagonal element is not well justified and to numerical issues in some cases.
|
||||||
|
// Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
|
||||||
|
RealScalar tolerance = RealScalar(1) / NumTraits<RealScalar>::highest();
|
||||||
|
|
||||||
for (Index i = 0; i < vectorD.size(); ++i) {
|
for (Index i = 0; i < vectorD.size(); ++i) {
|
||||||
if(abs(vectorD(i)) > tolerance)
|
if(abs(vectorD(i)) > tolerance)
|
||||||
dst.row(i) /= vectorD(i);
|
dst.row(i) /= vectorD(i);
|
||||||
else
|
else
|
||||||
dst.row(i).setZero();
|
dst.row(i).setZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// dst = L^-T (D^-1 L^-1 P b)
|
// dst = L^-T (D^-1 L^-1 P b)
|
||||||
@@ -565,7 +577,7 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
|
|||||||
// L^* P
|
// L^* P
|
||||||
res = matrixU() * res;
|
res = matrixU() * res;
|
||||||
// D(L^*P)
|
// D(L^*P)
|
||||||
res = vectorD().asDiagonal() * res;
|
res = vectorD().real().asDiagonal() * res;
|
||||||
// L(DL^*P)
|
// L(DL^*P)
|
||||||
res = matrixL() * res;
|
res = matrixL() * res;
|
||||||
// P^T (LDL^*P)
|
// P^T (LDL^*P)
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -200,7 +206,7 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
|
|||||||
typedef Matrix<Scalar,Dynamic,1> TempVectorType;
|
typedef Matrix<Scalar,Dynamic,1> TempVectorType;
|
||||||
typedef typename TempVectorType::SegmentReturnType TempVecSegment;
|
typedef typename TempVectorType::SegmentReturnType TempVecSegment;
|
||||||
|
|
||||||
int n = mat.cols();
|
Index n = mat.cols();
|
||||||
eigen_assert(mat.rows()==n && vec.size()==n);
|
eigen_assert(mat.rows()==n && vec.size()==n);
|
||||||
|
|
||||||
TempVectorType temp;
|
TempVectorType temp;
|
||||||
@@ -212,12 +218,12 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
|
|||||||
// i.e., for sigma > 0
|
// i.e., for sigma > 0
|
||||||
temp = sqrt(sigma) * vec;
|
temp = sqrt(sigma) * vec;
|
||||||
|
|
||||||
for(int i=0; i<n; ++i)
|
for(Index i=0; i<n; ++i)
|
||||||
{
|
{
|
||||||
JacobiRotation<Scalar> g;
|
JacobiRotation<Scalar> g;
|
||||||
g.makeGivens(mat(i,i), -temp(i), &mat(i,i));
|
g.makeGivens(mat(i,i), -temp(i), &mat(i,i));
|
||||||
|
|
||||||
int rs = n-i-1;
|
Index rs = n-i-1;
|
||||||
if(rs>0)
|
if(rs>0)
|
||||||
{
|
{
|
||||||
ColXprSegment x(mat.col(i).tail(rs));
|
ColXprSegment x(mat.col(i).tail(rs));
|
||||||
@@ -230,12 +236,12 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
|
|||||||
{
|
{
|
||||||
temp = vec;
|
temp = vec;
|
||||||
RealScalar beta = 1;
|
RealScalar beta = 1;
|
||||||
for(int j=0; j<n; ++j)
|
for(Index j=0; j<n; ++j)
|
||||||
{
|
{
|
||||||
RealScalar Ljj = real(mat.coeff(j,j));
|
RealScalar Ljj = numext::real(mat.coeff(j,j));
|
||||||
RealScalar dj = abs2(Ljj);
|
RealScalar dj = numext::abs2(Ljj);
|
||||||
Scalar wj = temp.coeff(j);
|
Scalar wj = temp.coeff(j);
|
||||||
RealScalar swj2 = sigma*abs2(wj);
|
RealScalar swj2 = sigma*numext::abs2(wj);
|
||||||
RealScalar gamma = dj*beta + swj2;
|
RealScalar gamma = dj*beta + swj2;
|
||||||
|
|
||||||
RealScalar x = dj + swj2/beta;
|
RealScalar x = dj + swj2/beta;
|
||||||
@@ -251,7 +257,7 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
|
|||||||
{
|
{
|
||||||
temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs);
|
temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs);
|
||||||
if(gamma != 0)
|
if(gamma != 0)
|
||||||
mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*conj(wj)/gamma)*temp.tail(rs);
|
mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*numext::conj(wj)/gamma)*temp.tail(rs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +283,7 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
|
|||||||
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
|
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
|
||||||
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
|
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
|
||||||
|
|
||||||
RealScalar x = real(mat.coeff(k,k));
|
RealScalar x = numext::real(mat.coeff(k,k));
|
||||||
if (k>0) x -= A10.squaredNorm();
|
if (k>0) x -= A10.squaredNorm();
|
||||||
if (x<=RealScalar(0))
|
if (x<=RealScalar(0))
|
||||||
return k;
|
return k;
|
||||||
@@ -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; \
|
||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ void cholmod_configure_matrix(CholmodType& mat)
|
|||||||
template<typename _Scalar, int _Options, typename _Index>
|
template<typename _Scalar, int _Options, typename _Index>
|
||||||
cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
|
cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
|
||||||
{
|
{
|
||||||
typedef SparseMatrix<_Scalar,_Options,_Index> MatrixType;
|
|
||||||
cholmod_sparse res;
|
cholmod_sparse res;
|
||||||
res.nzmax = mat.nonZeros();
|
res.nzmax = mat.nonZeros();
|
||||||
res.nrow = mat.rows();;
|
res.nrow = mat.rows();;
|
||||||
@@ -59,10 +58,12 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
|
|||||||
res.p = mat.outerIndexPtr();
|
res.p = mat.outerIndexPtr();
|
||||||
res.i = mat.innerIndexPtr();
|
res.i = mat.innerIndexPtr();
|
||||||
res.x = mat.valuePtr();
|
res.x = mat.valuePtr();
|
||||||
|
res.z = 0;
|
||||||
res.sorted = 1;
|
res.sorted = 1;
|
||||||
if(mat.isCompressed())
|
if(mat.isCompressed())
|
||||||
{
|
{
|
||||||
res.packed = 1;
|
res.packed = 1;
|
||||||
|
res.nz = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -127,7 +128,7 @@ cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
|
|||||||
res.ncol = mat.cols();
|
res.ncol = mat.cols();
|
||||||
res.nzmax = res.nrow * res.ncol;
|
res.nzmax = res.nrow * res.ncol;
|
||||||
res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
|
res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
|
||||||
res.x = mat.derived().data();
|
res.x = (void*)(mat.derived().data());
|
||||||
res.z = 0;
|
res.z = 0;
|
||||||
|
|
||||||
internal::cholmod_configure_matrix<Scalar>(res);
|
internal::cholmod_configure_matrix<Scalar>(res);
|
||||||
@@ -171,6 +172,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
CholmodBase()
|
CholmodBase()
|
||||||
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
|
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
|
||||||
{
|
{
|
||||||
|
m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
|
||||||
cholmod_start(&m_cholmod);
|
cholmod_start(&m_cholmod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +244,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
return internal::sparse_solve_retval<CholmodBase, Rhs>(*this, b.derived());
|
return internal::sparse_solve_retval<CholmodBase, Rhs>(*this, b.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
/** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
|
||||||
*
|
*
|
||||||
* This function is particularly useful when solving for several problems having the same structure.
|
* This function is particularly useful when solving for several problems having the same structure.
|
||||||
*
|
*
|
||||||
@@ -266,7 +268,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
|
|
||||||
/** Performs a numeric decomposition of \a matrix
|
/** Performs a numeric decomposition of \a matrix
|
||||||
*
|
*
|
||||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
* The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed.
|
||||||
*
|
*
|
||||||
* \sa analyzePattern()
|
* \sa analyzePattern()
|
||||||
*/
|
*/
|
||||||
@@ -296,13 +298,14 @@ class CholmodBase : internal::noncopyable
|
|||||||
eigen_assert(size==b.rows());
|
eigen_assert(size==b.rows());
|
||||||
|
|
||||||
// note: cd stands for Cholmod Dense
|
// note: cd stands for Cholmod Dense
|
||||||
cholmod_dense b_cd = viewAsCholmod(b.const_cast_derived());
|
Rhs& b_ref(b.const_cast_derived());
|
||||||
|
cholmod_dense b_cd = viewAsCholmod(b_ref);
|
||||||
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
|
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
|
||||||
if(!x_cd)
|
if(!x_cd)
|
||||||
{
|
{
|
||||||
this->m_info = NumericalIssue;
|
this->m_info = NumericalIssue;
|
||||||
}
|
}
|
||||||
// TODO optimize this copy by swapping when possible (be carreful with alignment, etc.)
|
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||||
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
|
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
|
||||||
cholmod_free_dense(&x_cd, &m_cholmod);
|
cholmod_free_dense(&x_cd, &m_cholmod);
|
||||||
}
|
}
|
||||||
@@ -313,6 +316,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
{
|
{
|
||||||
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
|
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
|
||||||
const Index size = m_cholmodFactor->n;
|
const Index size = m_cholmodFactor->n;
|
||||||
|
EIGEN_UNUSED_VARIABLE(size);
|
||||||
eigen_assert(size==b.rows());
|
eigen_assert(size==b.rows());
|
||||||
|
|
||||||
// note: cs stands for Cholmod Sparse
|
// note: cs stands for Cholmod Sparse
|
||||||
@@ -322,7 +326,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
{
|
{
|
||||||
this->m_info = NumericalIssue;
|
this->m_info = NumericalIssue;
|
||||||
}
|
}
|
||||||
// TODO optimize this copy by swapping when possible (be carreful with alignment, etc.)
|
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||||
dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs);
|
dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs);
|
||||||
cholmod_free_sparse(&x_cs, &m_cholmod);
|
cholmod_free_sparse(&x_cs, &m_cholmod);
|
||||||
}
|
}
|
||||||
@@ -345,7 +349,7 @@ class CholmodBase : internal::noncopyable
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
void dumpMemory(Stream& s)
|
void dumpMemory(Stream& /*s*/)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -364,8 +368,8 @@ class CholmodBase : internal::noncopyable
|
|||||||
*
|
*
|
||||||
* This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
|
* This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
|
||||||
* using the Cholmod library.
|
* using the Cholmod library.
|
||||||
* This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Thefore, it has little practical interest.
|
* This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest.
|
||||||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
|
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
|
||||||
* X and B can be either dense or sparse.
|
* X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
* \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<>
|
||||||
@@ -411,8 +415,8 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
|
|||||||
*
|
*
|
||||||
* This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
|
* This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
|
||||||
* using the Cholmod library.
|
* using the Cholmod library.
|
||||||
* This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Thefore, it has little practical interest.
|
* This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest.
|
||||||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
|
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
|
||||||
* X and B can be either dense or sparse.
|
* X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
* \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<>
|
||||||
@@ -457,7 +461,7 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
|
|||||||
* This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
|
* This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
|
||||||
* using the Cholmod library.
|
* using the Cholmod library.
|
||||||
* This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
|
* This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
|
||||||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
|
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
|
||||||
* X and B can be either dense or sparse.
|
* X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
* \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<>
|
||||||
@@ -500,7 +504,7 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
|
|||||||
* \brief A general Cholesky factorization and solver based on Cholmod
|
* \brief A general Cholesky factorization and solver based on Cholmod
|
||||||
*
|
*
|
||||||
* This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
|
* This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
|
||||||
* using the Cholmod library. The sparse matrix A must be selfajoint and positive definite. The vectors or matrices
|
* using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
|
||||||
* X and B can be either dense or sparse.
|
* X and B can be either dense or sparse.
|
||||||
*
|
*
|
||||||
* This variant permits to change the underlying Cholesky method at runtime.
|
* This variant permits to change the underlying Cholesky method at runtime.
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class Array
|
|||||||
*
|
*
|
||||||
* \sa resize(Index,Index)
|
* \sa resize(Index,Index)
|
||||||
*/
|
*/
|
||||||
EIGEN_STRONG_INLINE explicit Array() : Base()
|
EIGEN_STRONG_INLINE Array() : Base()
|
||||||
{
|
{
|
||||||
Base::_check_template_params();
|
Base::_check_template_params();
|
||||||
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||||
@@ -210,7 +210,7 @@ class Array
|
|||||||
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
||||||
{
|
{
|
||||||
Base::_check_template_params();
|
Base::_check_template_params();
|
||||||
Base::resize(other.rows(), other.cols());
|
Base::_resize_to_match(other);
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ struct traits<ArrayWrapper<ExpressionType> >
|
|||||||
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
|
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
|
||||||
{
|
{
|
||||||
typedef ArrayXpr XprKind;
|
typedef ArrayXpr XprKind;
|
||||||
|
// Let's remove NestByRefBit
|
||||||
|
enum {
|
||||||
|
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
|
||||||
|
Flags = Flags0 & ~NestByRefBit
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +60,7 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
|||||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||||
|
|
||||||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
|
||||||
inline const Scalar* data() const { return m_expression.data(); }
|
inline const Scalar* data() const { return m_expression.data(); }
|
||||||
|
|
||||||
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
||||||
@@ -149,6 +154,11 @@ struct traits<MatrixWrapper<ExpressionType> >
|
|||||||
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
|
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
|
||||||
{
|
{
|
||||||
typedef MatrixXpr XprKind;
|
typedef MatrixXpr XprKind;
|
||||||
|
// Let's remove NestByRefBit
|
||||||
|
enum {
|
||||||
|
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
|
||||||
|
Flags = Flags0 & ~NestByRefBit
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +185,7 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
|||||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||||
|
|
||||||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
|
||||||
inline const Scalar* data() const { return m_expression.data(); }
|
inline const Scalar* data() const { return m_expression.data(); }
|
||||||
|
|
||||||
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
inline CoeffReturnType coeff(Index rowId, Index colId) const
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
|
|||||||
template<typename Derived1, typename Derived2, int Index, int Stop>
|
template<typename Derived1, typename Derived2, int Index, int Stop>
|
||||||
struct assign_DefaultTraversal_InnerUnrolling
|
struct assign_DefaultTraversal_InnerUnrolling
|
||||||
{
|
{
|
||||||
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
|
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, typename Derived1::Index outer)
|
||||||
{
|
{
|
||||||
dst.copyCoeffByOuterInner(outer, Index, src);
|
dst.copyCoeffByOuterInner(outer, Index, src);
|
||||||
assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
|
assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
|
||||||
@@ -165,7 +165,7 @@ struct assign_DefaultTraversal_InnerUnrolling
|
|||||||
template<typename Derived1, typename Derived2, int Stop>
|
template<typename Derived1, typename Derived2, int Stop>
|
||||||
struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
||||||
{
|
{
|
||||||
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
|
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, typename Derived1::Index) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/***********************
|
/***********************
|
||||||
@@ -218,7 +218,7 @@ struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
|
|||||||
template<typename Derived1, typename Derived2, int Index, int Stop>
|
template<typename Derived1, typename Derived2, int Index, int Stop>
|
||||||
struct assign_innervec_InnerUnrolling
|
struct assign_innervec_InnerUnrolling
|
||||||
{
|
{
|
||||||
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
|
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, typename Derived1::Index outer)
|
||||||
{
|
{
|
||||||
dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
|
dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
|
||||||
assign_innervec_InnerUnrolling<Derived1, Derived2,
|
assign_innervec_InnerUnrolling<Derived1, Derived2,
|
||||||
@@ -229,7 +229,7 @@ struct assign_innervec_InnerUnrolling
|
|||||||
template<typename Derived1, typename Derived2, int Stop>
|
template<typename Derived1, typename Derived2, int Stop>
|
||||||
struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
|
||||||
{
|
{
|
||||||
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
|
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, typename Derived1::Index) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
@@ -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)) && (Index(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)
|
||||||
{
|
{
|
||||||
@@ -507,19 +514,19 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<typename Derived, typename OtherDerived,
|
template<typename Derived, typename OtherDerived,
|
||||||
bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
|
bool EvalBeforeAssigning = (int(internal::traits<OtherDerived>::Flags) & EvalBeforeAssigningBit) != 0,
|
||||||
bool NeedToTranspose = Derived::IsVectorAtCompileTime
|
bool NeedToTranspose = ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
|
||||||
&& OtherDerived::IsVectorAtCompileTime
|
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
|
||||||
&& ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
|
// revert to || as soon as not needed anymore.
|
||||||
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
|
(int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
|
||||||
// revert to || as soon as not needed anymore.
|
&& int(Derived::SizeAtCompileTime) != 1>
|
||||||
(int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
|
|
||||||
&& int(Derived::SizeAtCompileTime) != 1>
|
|
||||||
struct assign_selector;
|
struct assign_selector;
|
||||||
|
|
||||||
template<typename Derived, typename OtherDerived>
|
template<typename Derived, typename OtherDerived>
|
||||||
struct assign_selector<Derived,OtherDerived,false,false> {
|
struct assign_selector<Derived,OtherDerived,false,false> {
|
||||||
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
|
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
|
||||||
|
template<typename ActualDerived, typename ActualOtherDerived>
|
||||||
|
static EIGEN_STRONG_INLINE Derived& evalTo(ActualDerived& dst, const ActualOtherDerived& other) { other.evalTo(dst); return dst; }
|
||||||
};
|
};
|
||||||
template<typename Derived, typename OtherDerived>
|
template<typename Derived, typename OtherDerived>
|
||||||
struct assign_selector<Derived,OtherDerived,true,false> {
|
struct assign_selector<Derived,OtherDerived,true,false> {
|
||||||
@@ -528,6 +535,8 @@ struct assign_selector<Derived,OtherDerived,true,false> {
|
|||||||
template<typename Derived, typename OtherDerived>
|
template<typename Derived, typename OtherDerived>
|
||||||
struct assign_selector<Derived,OtherDerived,false,true> {
|
struct assign_selector<Derived,OtherDerived,false,true> {
|
||||||
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
|
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
|
||||||
|
template<typename ActualDerived, typename ActualOtherDerived>
|
||||||
|
static EIGEN_STRONG_INLINE Derived& evalTo(ActualDerived& dst, const ActualOtherDerived& other) { Transpose<ActualDerived> dstTrans(dst); other.evalTo(dstTrans); return dst; }
|
||||||
};
|
};
|
||||||
template<typename Derived, typename OtherDerived>
|
template<typename Derived, typename OtherDerived>
|
||||||
struct assign_selector<Derived,OtherDerived,true,true> {
|
struct assign_selector<Derived,OtherDerived,true,true> {
|
||||||
@@ -566,16 +575,14 @@ template<typename Derived>
|
|||||||
template <typename OtherDerived>
|
template <typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
|
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
other.derived().evalTo(derived());
|
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
|
||||||
return derived();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
||||||
{
|
{
|
||||||
other.evalTo(derived());
|
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
|
||||||
return derived();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -1,755 +0,0 @@
|
|||||||
// This file is part of Eigen, a lightweight C++ template library
|
|
||||||
// for linear algebra.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
|
||||||
// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
|
|
||||||
// Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla
|
|
||||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
|
||||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
#ifndef EIGEN_ASSIGN_EVALUATOR_H
|
|
||||||
#define EIGEN_ASSIGN_EVALUATOR_H
|
|
||||||
|
|
||||||
namespace Eigen {
|
|
||||||
|
|
||||||
// This implementation is based on Assign.h
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Part 1 : the logic deciding a strategy for traversal and unrolling *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
// copy_using_evaluator_traits is based on assign_traits
|
|
||||||
|
|
||||||
template <typename Derived, typename OtherDerived>
|
|
||||||
struct copy_using_evaluator_traits
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
DstIsAligned = Derived::Flags & AlignedBit,
|
|
||||||
DstHasDirectAccess = Derived::Flags & DirectAccessBit,
|
|
||||||
SrcIsAligned = OtherDerived::Flags & AlignedBit,
|
|
||||||
JointAlignment = bool(DstIsAligned) && bool(SrcIsAligned) ? Aligned : Unaligned,
|
|
||||||
SrcEvalBeforeAssign = (evaluator_traits<OtherDerived>::HasEvalTo == 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime)
|
|
||||||
: int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime)
|
|
||||||
: int(Derived::RowsAtCompileTime),
|
|
||||||
InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime)
|
|
||||||
: int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime)
|
|
||||||
: int(Derived::MaxRowsAtCompileTime),
|
|
||||||
MaxSizeAtCompileTime = Derived::SizeAtCompileTime,
|
|
||||||
PacketSize = packet_traits<typename Derived::Scalar>::size
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
StorageOrdersAgree = (int(Derived::IsRowMajor) == int(OtherDerived::IsRowMajor)),
|
|
||||||
MightVectorize = StorageOrdersAgree
|
|
||||||
&& (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit),
|
|
||||||
MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
|
|
||||||
&& int(DstIsAligned) && int(SrcIsAligned),
|
|
||||||
MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
|
|
||||||
MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess
|
|
||||||
&& (DstIsAligned || MaxSizeAtCompileTime == Dynamic),
|
|
||||||
/* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
|
|
||||||
so it's only good for large enough sizes. */
|
|
||||||
MaySliceVectorize = MightVectorize && DstHasDirectAccess
|
|
||||||
&& (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=3*PacketSize)
|
|
||||||
/* slice vectorization can be slow, so we only want it if the slices are big, which is
|
|
||||||
indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
|
|
||||||
in a fixed-size matrix */
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
Traversal = int(SrcEvalBeforeAssign) ? int(AllAtOnceTraversal)
|
|
||||||
: int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
|
|
||||||
: int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
|
|
||||||
: int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
|
|
||||||
: int(MayLinearize) ? int(LinearTraversal)
|
|
||||||
: int(DefaultTraversal),
|
|
||||||
Vectorized = int(Traversal) == InnerVectorizedTraversal
|
|
||||||
|| int(Traversal) == LinearVectorizedTraversal
|
|
||||||
|| int(Traversal) == SliceVectorizedTraversal
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1),
|
|
||||||
MayUnrollCompletely = int(Derived::SizeAtCompileTime) != Dynamic
|
|
||||||
&& int(OtherDerived::CoeffReadCost) != Dynamic
|
|
||||||
&& int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
|
|
||||||
MayUnrollInner = int(InnerSize) != Dynamic
|
|
||||||
&& int(OtherDerived::CoeffReadCost) != Dynamic
|
|
||||||
&& int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
|
|
||||||
? (
|
|
||||||
int(MayUnrollCompletely) ? int(CompleteUnrolling)
|
|
||||||
: int(MayUnrollInner) ? int(InnerUnrolling)
|
|
||||||
: int(NoUnrolling)
|
|
||||||
)
|
|
||||||
: int(Traversal) == int(LinearVectorizedTraversal)
|
|
||||||
? ( bool(MayUnrollCompletely) && bool(DstIsAligned) ? int(CompleteUnrolling)
|
|
||||||
: int(NoUnrolling) )
|
|
||||||
: int(Traversal) == int(LinearTraversal)
|
|
||||||
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
|
||||||
: int(NoUnrolling) )
|
|
||||||
: int(NoUnrolling)
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef EIGEN_DEBUG_ASSIGN
|
|
||||||
static void debug()
|
|
||||||
{
|
|
||||||
EIGEN_DEBUG_VAR(DstIsAligned)
|
|
||||||
EIGEN_DEBUG_VAR(SrcIsAligned)
|
|
||||||
EIGEN_DEBUG_VAR(JointAlignment)
|
|
||||||
EIGEN_DEBUG_VAR(InnerSize)
|
|
||||||
EIGEN_DEBUG_VAR(InnerMaxSize)
|
|
||||||
EIGEN_DEBUG_VAR(PacketSize)
|
|
||||||
EIGEN_DEBUG_VAR(StorageOrdersAgree)
|
|
||||||
EIGEN_DEBUG_VAR(MightVectorize)
|
|
||||||
EIGEN_DEBUG_VAR(MayLinearize)
|
|
||||||
EIGEN_DEBUG_VAR(MayInnerVectorize)
|
|
||||||
EIGEN_DEBUG_VAR(MayLinearVectorize)
|
|
||||||
EIGEN_DEBUG_VAR(MaySliceVectorize)
|
|
||||||
EIGEN_DEBUG_VAR(Traversal)
|
|
||||||
EIGEN_DEBUG_VAR(UnrollingLimit)
|
|
||||||
EIGEN_DEBUG_VAR(MayUnrollCompletely)
|
|
||||||
EIGEN_DEBUG_VAR(MayUnrollInner)
|
|
||||||
EIGEN_DEBUG_VAR(Unrolling)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Part 2 : meta-unrollers
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/************************
|
|
||||||
*** Default traversal ***
|
|
||||||
************************/
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Index, int Stop>
|
|
||||||
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
|
||||||
{
|
|
||||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
outer = Index / DstXprType::InnerSizeAtCompileTime,
|
|
||||||
inner = Index % DstXprType::InnerSizeAtCompileTime
|
|
||||||
};
|
|
||||||
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
SrcEvaluatorType &srcEvaluator)
|
|
||||||
{
|
|
||||||
dstEvaluator.copyCoeffByOuterInner(outer, inner, srcEvaluator);
|
|
||||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, Index+1, Stop>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Stop>
|
|
||||||
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<DstEvaluatorType, SrcEvaluatorType, Stop, Stop>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType&, SrcEvaluatorType&) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Index, int Stop>
|
|
||||||
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
SrcEvaluatorType &srcEvaluator,
|
|
||||||
int outer)
|
|
||||||
{
|
|
||||||
dstEvaluator.copyCoeffByOuterInner(outer, Index, srcEvaluator);
|
|
||||||
copy_using_evaluator_DefaultTraversal_InnerUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, Index+1, Stop>
|
|
||||||
::run(dstEvaluator, srcEvaluator, outer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Stop>
|
|
||||||
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling<DstEvaluatorType, SrcEvaluatorType, Stop, Stop>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType&, SrcEvaluatorType&, int) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
/***********************
|
|
||||||
*** Linear traversal ***
|
|
||||||
***********************/
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Index, int Stop>
|
|
||||||
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
SrcEvaluatorType &srcEvaluator)
|
|
||||||
{
|
|
||||||
dstEvaluator.copyCoeff(Index, srcEvaluator);
|
|
||||||
copy_using_evaluator_LinearTraversal_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, Index+1, Stop>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Stop>
|
|
||||||
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling<DstEvaluatorType, SrcEvaluatorType, Stop, Stop>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType&, SrcEvaluatorType&) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
*** Inner vectorization ***
|
|
||||||
**************************/
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Index, int Stop>
|
|
||||||
struct copy_using_evaluator_innervec_CompleteUnrolling
|
|
||||||
{
|
|
||||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
|
||||||
typedef typename SrcEvaluatorType::XprType SrcXprType;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
outer = Index / DstXprType::InnerSizeAtCompileTime,
|
|
||||||
inner = Index % DstXprType::InnerSizeAtCompileTime,
|
|
||||||
JointAlignment = copy_using_evaluator_traits<DstXprType,SrcXprType>::JointAlignment
|
|
||||||
};
|
|
||||||
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
SrcEvaluatorType &srcEvaluator)
|
|
||||||
{
|
|
||||||
dstEvaluator.template copyPacketByOuterInner<Aligned, JointAlignment>(outer, inner, srcEvaluator);
|
|
||||||
enum { NextIndex = Index + packet_traits<typename DstXprType::Scalar>::size };
|
|
||||||
copy_using_evaluator_innervec_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, NextIndex, Stop>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Stop>
|
|
||||||
struct copy_using_evaluator_innervec_CompleteUnrolling<DstEvaluatorType, SrcEvaluatorType, Stop, Stop>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType&, SrcEvaluatorType&) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Index, int Stop>
|
|
||||||
struct copy_using_evaluator_innervec_InnerUnrolling
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
SrcEvaluatorType &srcEvaluator,
|
|
||||||
int outer)
|
|
||||||
{
|
|
||||||
dstEvaluator.template copyPacketByOuterInner<Aligned, Aligned>(outer, Index, srcEvaluator);
|
|
||||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
|
||||||
enum { NextIndex = Index + packet_traits<typename DstXprType::Scalar>::size };
|
|
||||||
copy_using_evaluator_innervec_InnerUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, NextIndex, Stop>
|
|
||||||
::run(dstEvaluator, srcEvaluator, outer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename SrcEvaluatorType, int Stop>
|
|
||||||
struct copy_using_evaluator_innervec_InnerUnrolling<DstEvaluatorType, SrcEvaluatorType, Stop, Stop>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType&, SrcEvaluatorType&, int) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Part 3 : implementation of all cases
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
// copy_using_evaluator_impl is based on assign_impl
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType,
|
|
||||||
int Traversal = copy_using_evaluator_traits<DstXprType, SrcXprType>::Traversal,
|
|
||||||
int Unrolling = copy_using_evaluator_traits<DstXprType, SrcXprType>::Unrolling>
|
|
||||||
struct copy_using_evaluator_impl;
|
|
||||||
|
|
||||||
/************************
|
|
||||||
*** Default traversal ***
|
|
||||||
************************/
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, DefaultTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
static void run(DstXprType& dst, const SrcXprType& src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
for(Index outer = 0; outer < dst.outerSize(); ++outer) {
|
|
||||||
for(Index inner = 0; inner < dst.innerSize(); ++inner) {
|
|
||||||
dstEvaluator.copyCoeffByOuterInner(outer, inner, srcEvaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, DefaultTraversal, CompleteUnrolling>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, DstXprType::SizeAtCompileTime>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, DefaultTraversal, InnerUnrolling>
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
const Index outerSize = dst.outerSize();
|
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
|
||||||
copy_using_evaluator_DefaultTraversal_InnerUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, DstXprType::InnerSizeAtCompileTime>
|
|
||||||
::run(dstEvaluator, srcEvaluator, outer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************
|
|
||||||
*** Linear vectorization ***
|
|
||||||
***************************/
|
|
||||||
|
|
||||||
template <bool IsAligned = false>
|
|
||||||
struct unaligned_copy_using_evaluator_impl
|
|
||||||
{
|
|
||||||
// if IsAligned = true, then do nothing
|
|
||||||
template <typename SrcEvaluatorType, typename DstEvaluatorType>
|
|
||||||
static EIGEN_STRONG_INLINE void run(const SrcEvaluatorType&, DstEvaluatorType&,
|
|
||||||
typename SrcEvaluatorType::Index, typename SrcEvaluatorType::Index) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct unaligned_copy_using_evaluator_impl<false>
|
|
||||||
{
|
|
||||||
// MSVC must not inline this functions. If it does, it fails to optimize the
|
|
||||||
// packet access path.
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
template <typename DstEvaluatorType, typename SrcEvaluatorType>
|
|
||||||
static EIGEN_DONT_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
const SrcEvaluatorType &srcEvaluator,
|
|
||||||
typename DstEvaluatorType::Index start,
|
|
||||||
typename DstEvaluatorType::Index end)
|
|
||||||
#else
|
|
||||||
template <typename DstEvaluatorType, typename SrcEvaluatorType>
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstEvaluatorType &dstEvaluator,
|
|
||||||
const SrcEvaluatorType &srcEvaluator,
|
|
||||||
typename DstEvaluatorType::Index start,
|
|
||||||
typename DstEvaluatorType::Index end)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
for (typename DstEvaluatorType::Index index = start; index < end; ++index)
|
|
||||||
dstEvaluator.copyCoeff(index, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, LinearVectorizedTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
const Index size = dst.size();
|
|
||||||
typedef packet_traits<typename DstXprType::Scalar> PacketTraits;
|
|
||||||
enum {
|
|
||||||
packetSize = PacketTraits::size,
|
|
||||||
dstIsAligned = int(copy_using_evaluator_traits<DstXprType,SrcXprType>::DstIsAligned),
|
|
||||||
dstAlignment = PacketTraits::AlignedOnScalar ? Aligned : dstIsAligned,
|
|
||||||
srcAlignment = copy_using_evaluator_traits<DstXprType,SrcXprType>::JointAlignment
|
|
||||||
};
|
|
||||||
const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned(&dstEvaluator.coeffRef(0), size);
|
|
||||||
const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
|
|
||||||
|
|
||||||
unaligned_copy_using_evaluator_impl<dstIsAligned!=0>::run(dstEvaluator, srcEvaluator, 0, alignedStart);
|
|
||||||
|
|
||||||
for(Index index = alignedStart; index < alignedEnd; index += packetSize)
|
|
||||||
{
|
|
||||||
dstEvaluator.template copyPacket<dstAlignment, srcAlignment>(index, srcEvaluator);
|
|
||||||
}
|
|
||||||
|
|
||||||
unaligned_copy_using_evaluator_impl<>::run(dstEvaluator, srcEvaluator, alignedEnd, size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, LinearVectorizedTraversal, CompleteUnrolling>
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
enum { size = DstXprType::SizeAtCompileTime,
|
|
||||||
packetSize = packet_traits<typename DstXprType::Scalar>::size,
|
|
||||||
alignedSize = (size/packetSize)*packetSize };
|
|
||||||
|
|
||||||
copy_using_evaluator_innervec_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, alignedSize>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, alignedSize, size>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
*** Inner vectorization ***
|
|
||||||
**************************/
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, InnerVectorizedTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
inline static void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
const Index innerSize = dst.innerSize();
|
|
||||||
const Index outerSize = dst.outerSize();
|
|
||||||
const Index packetSize = packet_traits<typename DstXprType::Scalar>::size;
|
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
|
||||||
for(Index inner = 0; inner < innerSize; inner+=packetSize) {
|
|
||||||
dstEvaluator.template copyPacketByOuterInner<Aligned, Aligned>(outer, inner, srcEvaluator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, InnerVectorizedTraversal, CompleteUnrolling>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
copy_using_evaluator_innervec_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, DstXprType::SizeAtCompileTime>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, InnerVectorizedTraversal, InnerUnrolling>
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
const Index outerSize = dst.outerSize();
|
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
|
||||||
copy_using_evaluator_innervec_InnerUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, DstXprType::InnerSizeAtCompileTime>
|
|
||||||
::run(dstEvaluator, srcEvaluator, outer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/***********************
|
|
||||||
*** Linear traversal ***
|
|
||||||
***********************/
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, LinearTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
inline static void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
const Index size = dst.size();
|
|
||||||
for(Index i = 0; i < size; ++i)
|
|
||||||
dstEvaluator.copyCoeff(i, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, LinearTraversal, CompleteUnrolling>
|
|
||||||
{
|
|
||||||
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
copy_using_evaluator_LinearTraversal_CompleteUnrolling
|
|
||||||
<DstEvaluatorType, SrcEvaluatorType, 0, DstXprType::SizeAtCompileTime>
|
|
||||||
::run(dstEvaluator, srcEvaluator);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
*** Slice vectorization ***
|
|
||||||
***************************/
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, SliceVectorizedTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
inline static void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
typedef packet_traits<typename DstXprType::Scalar> PacketTraits;
|
|
||||||
enum {
|
|
||||||
packetSize = PacketTraits::size,
|
|
||||||
alignable = PacketTraits::AlignedOnScalar,
|
|
||||||
dstAlignment = alignable ? Aligned : int(copy_using_evaluator_traits<DstXprType,SrcXprType>::DstIsAligned)
|
|
||||||
};
|
|
||||||
const Index packetAlignedMask = packetSize - 1;
|
|
||||||
const Index innerSize = dst.innerSize();
|
|
||||||
const Index outerSize = dst.outerSize();
|
|
||||||
const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
|
|
||||||
Index alignedStart = ((!alignable) || copy_using_evaluator_traits<DstXprType,SrcXprType>::DstIsAligned) ? 0
|
|
||||||
: internal::first_aligned(&dstEvaluator.coeffRef(0,0), innerSize);
|
|
||||||
|
|
||||||
for(Index outer = 0; outer < outerSize; ++outer)
|
|
||||||
{
|
|
||||||
const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
|
|
||||||
// do the non-vectorizable part of the assignment
|
|
||||||
for(Index inner = 0; inner<alignedStart ; ++inner) {
|
|
||||||
dstEvaluator.copyCoeffByOuterInner(outer, inner, srcEvaluator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the vectorizable part of the assignment
|
|
||||||
for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize) {
|
|
||||||
dstEvaluator.template copyPacketByOuterInner<dstAlignment, Unaligned>(outer, inner, srcEvaluator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the non-vectorizable part of the assignment
|
|
||||||
for(Index inner = alignedEnd; inner<innerSize ; ++inner) {
|
|
||||||
dstEvaluator.copyCoeffByOuterInner(outer, inner, srcEvaluator);
|
|
||||||
}
|
|
||||||
|
|
||||||
alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************
|
|
||||||
*** All-at-once traversal ***
|
|
||||||
****************************/
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
struct copy_using_evaluator_impl<DstXprType, SrcXprType, AllAtOnceTraversal, NoUnrolling>
|
|
||||||
{
|
|
||||||
inline static void run(DstXprType &dst, const SrcXprType &src)
|
|
||||||
{
|
|
||||||
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
|
|
||||||
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
|
|
||||||
typedef typename DstXprType::Index Index;
|
|
||||||
|
|
||||||
DstEvaluatorType dstEvaluator(dst);
|
|
||||||
SrcEvaluatorType srcEvaluator(src);
|
|
||||||
|
|
||||||
// Evaluate rhs in temporary to prevent aliasing problems in a = a * a;
|
|
||||||
// TODO: Do not pass the xpr object to evalTo()
|
|
||||||
srcEvaluator.evalTo(dstEvaluator, dst);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Part 4 : Entry points
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
// Based on DenseBase::LazyAssign()
|
|
||||||
|
|
||||||
template<typename DstXprType, template <typename> class StorageBase, typename SrcXprType>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& dst,
|
|
||||||
const EigenBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
return noalias_copy_using_evaluator(dst.expression(), src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename XprType, int AssumeAliasing = evaluator_traits<XprType>::AssumeAliasing>
|
|
||||||
struct AddEvalIfAssumingAliasing;
|
|
||||||
|
|
||||||
template<typename XprType>
|
|
||||||
struct AddEvalIfAssumingAliasing<XprType, 0>
|
|
||||||
{
|
|
||||||
static const XprType& run(const XprType& xpr)
|
|
||||||
{
|
|
||||||
return xpr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename XprType>
|
|
||||||
struct AddEvalIfAssumingAliasing<XprType, 1>
|
|
||||||
{
|
|
||||||
static const EvalToTemp<XprType> run(const XprType& xpr)
|
|
||||||
{
|
|
||||||
return EvalToTemp<XprType>(xpr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
return noalias_copy_using_evaluator(dst.const_cast_derived(),
|
|
||||||
AddEvalIfAssumingAliasing<SrcXprType>::run(src.derived()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& noalias_copy_using_evaluator(const PlainObjectBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
#ifdef EIGEN_DEBUG_ASSIGN
|
|
||||||
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
|
|
||||||
#endif
|
|
||||||
#ifdef EIGEN_NO_AUTOMATIC_RESIZING
|
|
||||||
eigen_assert((dst.size()==0 || (IsVectorAtCompileTime ? (dst.size() == src.size())
|
|
||||||
: (dst.rows() == src.rows() && dst.cols() == src.cols())))
|
|
||||||
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
|
|
||||||
#else
|
|
||||||
dst.const_cast_derived().resizeLike(src.derived());
|
|
||||||
#endif
|
|
||||||
return copy_using_evaluator_without_resizing(dst.const_cast_derived(), src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
EIGEN_STRONG_INLINE
|
|
||||||
const DstXprType& noalias_copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
return copy_using_evaluator_without_resizing(dst.const_cast_derived(), src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
const DstXprType& copy_using_evaluator_without_resizing(const DstXprType& dst, const SrcXprType& src)
|
|
||||||
{
|
|
||||||
#ifdef EIGEN_DEBUG_ASSIGN
|
|
||||||
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
|
|
||||||
#endif
|
|
||||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
|
||||||
copy_using_evaluator_impl<DstXprType, SrcXprType>::run(const_cast<DstXprType&>(dst), src);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on DenseBase::swap()
|
|
||||||
// TODO: Chech whether we need to do something special for swapping two
|
|
||||||
// Arrays or Matrices.
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void swap_using_evaluator(const DstXprType& dst, const SrcXprType& src)
|
|
||||||
{
|
|
||||||
copy_using_evaluator(SwapWrapper<DstXprType>(const_cast<DstXprType&>(dst)), src);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on MatrixBase::operator+= (in CwiseBinaryOp.h)
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void add_assign_using_evaluator(const MatrixBase<DstXprType>& dst, const MatrixBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on ArrayBase::operator+=
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void add_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Add add_assign_using_evaluator for EigenBase ?
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void subtract_assign_using_evaluator(const MatrixBase<DstXprType>& dst, const MatrixBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void subtract_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void multiply_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_product_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstXprType, typename SrcXprType>
|
|
||||||
void divide_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
|
|
||||||
{
|
|
||||||
typedef typename DstXprType::Scalar Scalar;
|
|
||||||
SelfCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, DstXprType, SrcXprType> tmp(dst.const_cast_derived());
|
|
||||||
copy_using_evaluator(tmp, src.derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
|
||||||
|
|
||||||
#endif // EIGEN_ASSIGN_EVALUATOR_H
|
|
||||||
@@ -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),
|
||||||
@@ -81,7 +82,7 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
|||||||
&& (InnerStrideAtCompileTime == 1)
|
&& (InnerStrideAtCompileTime == 1)
|
||||||
? PacketAccessBit : 0,
|
? PacketAccessBit : 0,
|
||||||
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
|
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
|
||||||
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
|
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (traits<XprType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
|
||||||
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
|
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
|
||||||
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
|
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
|
||||||
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
|
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ struct all_unroller
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
struct all_unroller<Derived, 1>
|
struct all_unroller<Derived, 0>
|
||||||
{
|
{
|
||||||
static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
|
static inline bool run(const Derived &/*mat*/) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -55,9 +55,9 @@ struct any_unroller
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
struct any_unroller<Derived, 1>
|
struct any_unroller<Derived, 0>
|
||||||
{
|
{
|
||||||
static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
|
static inline bool run(const Derived & /*mat*/) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -129,6 +129,26 @@ inline typename DenseBase<Derived>::Index DenseBase<Derived>::count() const
|
|||||||
return derived().template cast<bool>().template cast<Index>().sum();
|
return derived().template cast<bool>().template cast<Index>().sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \returns true is \c *this contains at least one Not A Number (NaN).
|
||||||
|
*
|
||||||
|
* \sa allFinite()
|
||||||
|
*/
|
||||||
|
template<typename Derived>
|
||||||
|
inline bool DenseBase<Derived>::hasNaN() const
|
||||||
|
{
|
||||||
|
return !((derived().array()==derived().array()).all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \returns true if \c *this contains only finite numbers, i.e., no NaN and no +/-INF values.
|
||||||
|
*
|
||||||
|
* \sa hasNaN()
|
||||||
|
*/
|
||||||
|
template<typename Derived>
|
||||||
|
inline bool DenseBase<Derived>::allFinite() const
|
||||||
|
{
|
||||||
|
return !((derived()-derived()).hasNaN());
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_ALLANDANY_H
|
#endif // EIGEN_ALLANDANY_H
|
||||||
|
|||||||
@@ -43,6 +43,17 @@ struct CommaInitializer
|
|||||||
m_xpr.block(0, 0, other.rows(), other.cols()) = other;
|
m_xpr.block(0, 0, other.rows(), other.cols()) = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy/Move constructor which transfers ownership. This is crucial in
|
||||||
|
* absence of return value optimization to avoid assertions during destruction. */
|
||||||
|
// FIXME in C++11 mode this could be replaced by a proper RValue constructor
|
||||||
|
inline CommaInitializer(const CommaInitializer& o)
|
||||||
|
: m_xpr(o.m_xpr), m_row(o.m_row), m_col(o.m_col), m_currentBlockRows(o.m_currentBlockRows) {
|
||||||
|
// Mark original object as finished. In absence of R-value references we need to const_cast:
|
||||||
|
const_cast<CommaInitializer&>(o).m_row = m_xpr.rows();
|
||||||
|
const_cast<CommaInitializer&>(o).m_col = m_xpr.cols();
|
||||||
|
const_cast<CommaInitializer&>(o).m_currentBlockRows = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* inserts a scalar value in the target matrix */
|
/* inserts a scalar value in the target matrix */
|
||||||
CommaInitializer& operator,(const Scalar& s)
|
CommaInitializer& operator,(const Scalar& s)
|
||||||
{
|
{
|
||||||
@@ -118,6 +129,8 @@ struct CommaInitializer
|
|||||||
*
|
*
|
||||||
* Example: \include MatrixBase_set.cpp
|
* Example: \include MatrixBase_set.cpp
|
||||||
* Output: \verbinclude MatrixBase_set.out
|
* Output: \verbinclude MatrixBase_set.out
|
||||||
|
*
|
||||||
|
* \note According the c++ standard, the argument expressions of this comma initializer are evaluated in arbitrary order.
|
||||||
*
|
*
|
||||||
* \sa CommaInitializer::finished(), class CommaInitializer
|
* \sa CommaInitializer::finished(), class CommaInitializer
|
||||||
*/
|
*/
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -94,8 +94,8 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
|||||||
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
|
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
|
||||||
// add together a float matrix and a double matrix.
|
// add together a float matrix and a double matrix.
|
||||||
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
|
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
|
||||||
EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
|
EIGEN_STATIC_ASSERT((internal::functor_is_product_like<BINOP>::ret \
|
||||||
? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
|
? int(internal::scalar_product_traits<LHS, RHS>::Defined) \
|
||||||
: int(internal::is_same<LHS, RHS>::value)), \
|
: int(internal::is_same<LHS, RHS>::value)), \
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ template<typename ViewOp, typename MatrixType, typename StorageKind>
|
|||||||
class CwiseUnaryViewImpl;
|
class CwiseUnaryViewImpl;
|
||||||
|
|
||||||
template<typename ViewOp, typename MatrixType>
|
template<typename ViewOp, typename MatrixType>
|
||||||
class CwiseUnaryView : internal::no_assignment_operator,
|
class CwiseUnaryView : public CwiseUnaryViewImpl<ViewOp, MatrixType, typename internal::traits<MatrixType>::StorageKind>
|
||||||
public CwiseUnaryViewImpl<ViewOp, MatrixType, typename internal::traits<MatrixType>::StorageKind>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -99,6 +98,7 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
|
|||||||
typedef typename internal::dense_xpr_base< CwiseUnaryView<ViewOp, MatrixType> >::type Base;
|
typedef typename internal::dense_xpr_base< CwiseUnaryView<ViewOp, MatrixType> >::type Base;
|
||||||
|
|
||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
|
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
|
||||||
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl)
|
||||||
|
|
||||||
inline Scalar* data() { return &coeffRef(0); }
|
inline Scalar* data() { return &coeffRef(0); }
|
||||||
inline const Scalar* data() const { return &coeff(0); }
|
inline const Scalar* data() const { return &coeff(0); }
|
||||||
|
|||||||
@@ -13,6 +13,16 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// The index type defined by EIGEN_DEFAULT_DENSE_INDEX_TYPE must be a signed type.
|
||||||
|
// This dummy function simply aims at checking that at compile time.
|
||||||
|
static inline void check_DenseIndex_is_signed() {
|
||||||
|
EIGEN_STATIC_ASSERT(NumTraits<DenseIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
|
||||||
/** \class DenseBase
|
/** \class DenseBase
|
||||||
* \ingroup Core_Module
|
* \ingroup Core_Module
|
||||||
*
|
*
|
||||||
@@ -256,11 +266,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);
|
||||||
|
|
||||||
@@ -271,7 +283,7 @@ template<typename Derived> class DenseBase
|
|||||||
CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other);
|
CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other);
|
||||||
|
|
||||||
Eigen::Transpose<Derived> transpose();
|
Eigen::Transpose<Derived> transpose();
|
||||||
typedef const Transpose<const Derived> ConstTransposeReturnType;
|
typedef typename internal::add_const<Transpose<const Derived> >::type ConstTransposeReturnType;
|
||||||
ConstTransposeReturnType transpose() const;
|
ConstTransposeReturnType transpose() const;
|
||||||
void transposeInPlace();
|
void transposeInPlace();
|
||||||
#ifndef EIGEN_NO_DEBUG
|
#ifndef EIGEN_NO_DEBUG
|
||||||
@@ -336,6 +348,9 @@ template<typename Derived> class DenseBase
|
|||||||
bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||||
bool isZero(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
bool isZero(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||||
bool isOnes(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
bool isOnes(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||||
|
|
||||||
|
inline bool hasNaN() const;
|
||||||
|
inline bool allFinite() const;
|
||||||
|
|
||||||
inline Derived& operator*=(const Scalar& other);
|
inline Derived& operator*=(const Scalar& other);
|
||||||
inline Derived& operator/=(const Scalar& other);
|
inline Derived& operator/=(const Scalar& other);
|
||||||
@@ -415,8 +430,6 @@ template<typename Derived> class DenseBase
|
|||||||
return derived().coeff(0,0);
|
return derived().coeff(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// Array module ///////////
|
|
||||||
|
|
||||||
bool all(void) const;
|
bool all(void) const;
|
||||||
bool any(void) const;
|
bool any(void) const;
|
||||||
Index count() const;
|
Index count() const;
|
||||||
@@ -442,17 +455,19 @@ template<typename Derived> class DenseBase
|
|||||||
|
|
||||||
template<typename ThenDerived>
|
template<typename ThenDerived>
|
||||||
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
||||||
select(const DenseBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
|
select(const DenseBase<ThenDerived>& thenMatrix, const typename ThenDerived::Scalar& elseScalar) const;
|
||||||
|
|
||||||
template<typename ElseDerived>
|
template<typename ElseDerived>
|
||||||
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
||||||
select(typename ElseDerived::Scalar thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
|
select(const typename ElseDerived::Scalar& thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
|
||||||
|
|
||||||
template<int p> RealScalar lpNorm() const;
|
template<int p> RealScalar lpNorm() const;
|
||||||
|
|
||||||
template<int RowFactor, int ColFactor>
|
template<int RowFactor, int ColFactor>
|
||||||
const Replicate<Derived,RowFactor,ColFactor> replicate() const;
|
inline const Replicate<Derived,RowFactor,ColFactor> replicate() const;
|
||||||
const Replicate<Derived,Dynamic,Dynamic> replicate(Index rowFacor,Index colFactor) const;
|
|
||||||
|
typedef Replicate<Derived,Dynamic,Dynamic> ReplicateReturnType;
|
||||||
|
inline const ReplicateReturnType replicate(Index rowFacor,Index colFactor) const;
|
||||||
|
|
||||||
typedef Reverse<Derived, BothDirections> ReverseReturnType;
|
typedef Reverse<Derived, BothDirections> ReverseReturnType;
|
||||||
typedef const Reverse<const Derived, BothDirections> ConstReverseReturnType;
|
typedef const Reverse<const Derived, BothDirections> ConstReverseReturnType;
|
||||||
|
|||||||
@@ -24,6 +24,14 @@ namespace internal {
|
|||||||
|
|
||||||
struct constructor_without_unaligned_array_assert {};
|
struct constructor_without_unaligned_array_assert {};
|
||||||
|
|
||||||
|
template<typename T, int Size> void check_static_allocation_size()
|
||||||
|
{
|
||||||
|
// if EIGEN_STACK_ALLOCATION_LIMIT is defined to 0, then no limit
|
||||||
|
#if EIGEN_STACK_ALLOCATION_LIMIT
|
||||||
|
EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
* Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
|
* Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
|
||||||
* to 16 bytes boundary if the total size is a multiple of 16 bytes.
|
* to 16 bytes boundary if the total size is a multiple of 16 bytes.
|
||||||
@@ -38,12 +46,12 @@ struct plain_array
|
|||||||
|
|
||||||
plain_array()
|
plain_array()
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
|
check_static_allocation_size<T,Size>();
|
||||||
}
|
}
|
||||||
|
|
||||||
plain_array(constructor_without_unaligned_array_assert)
|
plain_array(constructor_without_unaligned_array_assert)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
|
check_static_allocation_size<T,Size>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,12 +84,12 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 16>
|
|||||||
plain_array()
|
plain_array()
|
||||||
{
|
{
|
||||||
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
|
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
|
||||||
EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
|
check_static_allocation_size<T,Size>();
|
||||||
}
|
}
|
||||||
|
|
||||||
plain_array(constructor_without_unaligned_array_assert)
|
plain_array(constructor_without_unaligned_array_assert)
|
||||||
{
|
{
|
||||||
EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
|
check_static_allocation_size<T,Size>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,7 +122,7 @@ 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 explicit DenseStorage() {}
|
inline DenseStorage() {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
inline 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) {}
|
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
@@ -131,7 +139,7 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
|||||||
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 explicit DenseStorage() {}
|
inline DenseStorage() {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
|
inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
|
||||||
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
|
||||||
inline void swap(DenseStorage& ) {}
|
inline void swap(DenseStorage& ) {}
|
||||||
@@ -160,7 +168,7 @@ 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 explicit DenseStorage() : m_rows(0), m_cols(0) {}
|
inline DenseStorage() : m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
inline 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) {}
|
inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
|
||||||
@@ -180,7 +188,7 @@ 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 explicit DenseStorage() : m_rows(0) {}
|
inline DenseStorage() : m_rows(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
inline 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) {}
|
inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
|
||||||
@@ -199,7 +207,7 @@ 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 explicit DenseStorage() : m_cols(0) {}
|
inline DenseStorage() : m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
inline 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) {}
|
inline DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
|
||||||
@@ -219,7 +227,7 @@ 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 explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
|
inline DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert)
|
inline 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)
|
inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
|
||||||
@@ -260,7 +268,7 @@ 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 explicit DenseStorage() : m_data(0), m_cols(0) {}
|
inline DenseStorage() : m_data(0), m_cols(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
|
inline 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)
|
inline 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 }
|
||||||
@@ -296,7 +304,7 @@ 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 explicit DenseStorage() : m_data(0), m_rows(0) {}
|
inline DenseStorage() : m_data(0), m_rows(0) {}
|
||||||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
|
inline 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)
|
inline 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 }
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
|||||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
|
||||||
|
|
||||||
inline Index rows() const
|
inline Index rows() const
|
||||||
{ return m_index.value()<0 ? (std::min)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
|
{ return m_index.value()<0 ? (std::min<Index>)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min<Index>)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
|
||||||
|
|
||||||
inline Index cols() const { return 1; }
|
inline Index cols() const { return 1; }
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ MatrixBase<Derived>::diagonal()
|
|||||||
|
|
||||||
/** This is the const version of diagonal(). */
|
/** This is the const version of diagonal(). */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline const typename MatrixBase<Derived>::ConstDiagonalReturnType
|
inline typename MatrixBase<Derived>::ConstDiagonalReturnType
|
||||||
MatrixBase<Derived>::diagonal() const
|
MatrixBase<Derived>::diagonal() const
|
||||||
{
|
{
|
||||||
return ConstDiagonalReturnType(derived());
|
return ConstDiagonalReturnType(derived());
|
||||||
@@ -190,18 +190,18 @@ MatrixBase<Derived>::diagonal() const
|
|||||||
*
|
*
|
||||||
* \sa MatrixBase::diagonal(), class Diagonal */
|
* \sa MatrixBase::diagonal(), class Diagonal */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<DynamicIndex>::Type
|
inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
|
||||||
MatrixBase<Derived>::diagonal(Index index)
|
MatrixBase<Derived>::diagonal(Index index)
|
||||||
{
|
{
|
||||||
return typename DiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
|
return DiagonalDynamicIndexReturnType(derived(), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This is the const version of diagonal(Index). */
|
/** This is the const version of diagonal(Index). */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<DynamicIndex>::Type
|
inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
|
||||||
MatrixBase<Derived>::diagonal(Index index) const
|
MatrixBase<Derived>::diagonal(Index index) const
|
||||||
{
|
{
|
||||||
return typename ConstDiagonalIndexReturnType<DynamicIndex>::Type(derived(), index);
|
return ConstDiagonalDynamicIndexReturnType(derived(), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
|
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
|
||||||
|
|||||||
@@ -26,14 +26,15 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
|
|||||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||||
|
|
||||||
_StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
|
_StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
|
||||||
_PacketOnDiag = !((int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
|
_ScalarAccessOnDiag = !((int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheLeft)
|
||||||
||(int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)),
|
||(int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheRight)),
|
||||||
_SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
|
_SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
|
||||||
// FIXME currently we need same types, but in the future the next rule should be the one
|
// FIXME currently we need same types, but in the future the next rule should be the one
|
||||||
//_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::Flags)&PacketAccessBit))),
|
//_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
|
||||||
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && ((!_PacketOnDiag) || (bool(int(DiagonalType::Flags)&PacketAccessBit))),
|
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
|
||||||
|
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
|
||||||
|
|
||||||
Flags = (HereditaryBits & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),
|
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
|
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -54,13 +55,21 @@ class DiagonalProduct : internal::no_assignment_operator,
|
|||||||
eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols()));
|
eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols()));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Index rows() const { return m_matrix.rows(); }
|
EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); }
|
||||||
inline Index cols() const { return m_matrix.cols(); }
|
EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); }
|
||||||
|
|
||||||
const Scalar coeff(Index row, Index col) const
|
EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
|
||||||
{
|
{
|
||||||
return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col);
|
return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
|
||||||
|
};
|
||||||
|
return coeff(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
|
||||||
|
}
|
||||||
|
|
||||||
template<int LoadMode>
|
template<int LoadMode>
|
||||||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
|
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
|
||||||
@@ -69,11 +78,19 @@ class DiagonalProduct : internal::no_assignment_operator,
|
|||||||
StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor
|
StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor
|
||||||
};
|
};
|
||||||
const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col;
|
const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col;
|
||||||
|
|
||||||
return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional<
|
return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional<
|
||||||
((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
|
((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
|
||||||
||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type());
|
||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<int LoadMode>
|
||||||
|
EIGEN_STRONG_INLINE PacketScalar packet(Index idx) const
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
StorageOrder = int(MatrixType::Flags) & RowMajorBit ? RowMajor : ColMajor
|
||||||
|
};
|
||||||
|
return packet<LoadMode>(int(StorageOrder)==ColMajor?idx:0,int(StorageOrder)==ColMajor?0:idx);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<int LoadMode>
|
template<int LoadMode>
|
||||||
@@ -88,7 +105,7 @@ class DiagonalProduct : internal::no_assignment_operator,
|
|||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
|
InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
|
||||||
DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? Aligned : Unaligned
|
DiagonalVectorPacketLoadMode = (LoadMode == Aligned && (((InnerSize%16) == 0) || (int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit)==AlignedBit) ? Aligned : Unaligned)
|
||||||
};
|
};
|
||||||
return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
|
return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
|
||||||
m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id));
|
m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id));
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
|
EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
|
||||||
{
|
{
|
||||||
return internal::real((*this).cwiseAbs2().sum());
|
return numext::real((*this).cwiseAbs2().sum());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
||||||
@@ -166,6 +166,7 @@ struct lpNorm_selector
|
|||||||
typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
|
typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const MatrixBase<Derived>& m)
|
static inline RealScalar run(const MatrixBase<Derived>& m)
|
||||||
{
|
{
|
||||||
|
using std::pow;
|
||||||
return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
|
return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -228,7 +229,7 @@ bool MatrixBase<Derived>::isOrthogonal
|
|||||||
{
|
{
|
||||||
typename internal::nested<Derived,2>::type nested(derived());
|
typename internal::nested<Derived,2>::type nested(derived());
|
||||||
typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
|
typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
|
||||||
return internal::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
|
return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns true if *this is approximately an unitary matrix,
|
/** \returns true if *this is approximately an unitary matrix,
|
||||||
|
|||||||
@@ -126,36 +126,6 @@ Derived& DenseBase<Derived>::operator-=(const EigenBase<OtherDerived> &other)
|
|||||||
return derived();
|
return derived();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** replaces \c *this by \c *this * \a other.
|
|
||||||
*
|
|
||||||
* \returns a reference to \c *this
|
|
||||||
*/
|
|
||||||
template<typename Derived>
|
|
||||||
template<typename OtherDerived>
|
|
||||||
inline Derived&
|
|
||||||
MatrixBase<Derived>::operator*=(const EigenBase<OtherDerived> &other)
|
|
||||||
{
|
|
||||||
other.derived().applyThisOnTheRight(derived());
|
|
||||||
return derived();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=().
|
|
||||||
*/
|
|
||||||
template<typename Derived>
|
|
||||||
template<typename OtherDerived>
|
|
||||||
inline void MatrixBase<Derived>::applyOnTheRight(const EigenBase<OtherDerived> &other)
|
|
||||||
{
|
|
||||||
other.derived().applyThisOnTheRight(derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** replaces \c *this by \c *this * \a other. */
|
|
||||||
template<typename Derived>
|
|
||||||
template<typename OtherDerived>
|
|
||||||
inline void MatrixBase<Derived>::applyOnTheLeft(const EigenBase<OtherDerived> &other)
|
|
||||||
{
|
|
||||||
other.derived().applyThisOnTheLeft(derived());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_EIGENBASE_H
|
#endif // EIGEN_EIGENBASE_H
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ struct functor_traits<scalar_hypot_op<Scalar> > {
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
|
template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
|
||||||
inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); }
|
inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
|
||||||
};
|
};
|
||||||
template<typename Scalar, typename OtherScalar>
|
template<typename Scalar, typename OtherScalar>
|
||||||
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
|
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
|
||||||
@@ -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
|
||||||
@@ -310,7 +351,7 @@ struct functor_traits<scalar_abs_op<Scalar> >
|
|||||||
template<typename Scalar> struct scalar_abs2_op {
|
template<typename Scalar> struct scalar_abs2_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
|
||||||
typedef typename NumTraits<Scalar>::Real result_type;
|
typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); }
|
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs2(a); }
|
||||||
template<typename Packet>
|
template<typename Packet>
|
||||||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
|
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
|
||||||
{ return internal::pmul(a,a); }
|
{ return internal::pmul(a,a); }
|
||||||
@@ -326,7 +367,7 @@ struct functor_traits<scalar_abs2_op<Scalar> >
|
|||||||
*/
|
*/
|
||||||
template<typename Scalar> struct scalar_conjugate_op {
|
template<typename Scalar> struct scalar_conjugate_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
|
||||||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using internal::conj; return conj(a); }
|
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { using numext::conj; return conj(a); }
|
||||||
template<typename Packet>
|
template<typename Packet>
|
||||||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
|
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
|
||||||
};
|
};
|
||||||
@@ -363,7 +404,7 @@ template<typename Scalar>
|
|||||||
struct scalar_real_op {
|
struct scalar_real_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
|
||||||
typedef typename NumTraits<Scalar>::Real result_type;
|
typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); }
|
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_real_op<Scalar> >
|
struct functor_traits<scalar_real_op<Scalar> >
|
||||||
@@ -378,7 +419,7 @@ template<typename Scalar>
|
|||||||
struct scalar_imag_op {
|
struct scalar_imag_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
|
||||||
typedef typename NumTraits<Scalar>::Real result_type;
|
typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); }
|
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_imag_op<Scalar> >
|
struct functor_traits<scalar_imag_op<Scalar> >
|
||||||
@@ -393,7 +434,7 @@ template<typename Scalar>
|
|||||||
struct scalar_real_ref_op {
|
struct scalar_real_ref_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
|
||||||
typedef typename NumTraits<Scalar>::Real result_type;
|
typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast<Scalar*>(&a)); }
|
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_real_ref_op<Scalar> >
|
struct functor_traits<scalar_real_ref_op<Scalar> >
|
||||||
@@ -408,7 +449,7 @@ template<typename Scalar>
|
|||||||
struct scalar_imag_ref_op {
|
struct scalar_imag_ref_op {
|
||||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
|
||||||
typedef typename NumTraits<Scalar>::Real result_type;
|
typedef typename NumTraits<Scalar>::Real result_type;
|
||||||
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast<Scalar*>(&a)); }
|
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); }
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct functor_traits<scalar_imag_ref_op<Scalar> >
|
struct functor_traits<scalar_imag_ref_op<Scalar> >
|
||||||
@@ -560,7 +601,7 @@ struct linspaced_op_impl<Scalar,false>
|
|||||||
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
|
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
|
||||||
{
|
{
|
||||||
m_base = padd(m_base, pset1<Packet>(m_step));
|
m_base = padd(m_base, pset1<Packet>(m_step));
|
||||||
return m_low+i*m_step;
|
return m_low+Scalar(i)*m_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Index>
|
template<typename Index>
|
||||||
@@ -589,7 +630,7 @@ struct linspaced_op_impl<Scalar,true>
|
|||||||
|
|
||||||
template<typename Index>
|
template<typename Index>
|
||||||
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
|
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
|
||||||
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
|
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(Scalar(i)),m_interPacket))); }
|
||||||
|
|
||||||
const Scalar m_low;
|
const Scalar m_low;
|
||||||
const Scalar m_step;
|
const Scalar m_step;
|
||||||
@@ -609,7 +650,7 @@ template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_o
|
|||||||
template <typename Scalar, bool RandomAccess> struct linspaced_op
|
template <typename Scalar, bool RandomAccess> struct linspaced_op
|
||||||
{
|
{
|
||||||
typedef typename packet_traits<Scalar>::type Packet;
|
typedef typename packet_traits<Scalar>::type Packet;
|
||||||
linspaced_op(const Scalar& low, const Scalar& high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {}
|
linspaced_op(const Scalar& low, const Scalar& high, DenseIndex num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1))) {}
|
||||||
|
|
||||||
template<typename Index>
|
template<typename Index>
|
||||||
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
|
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
|
||||||
@@ -648,13 +689,14 @@ template <typename Scalar, bool RandomAccess> struct linspaced_op
|
|||||||
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
|
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
|
||||||
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
|
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
|
||||||
|
|
||||||
// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
|
// In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication
|
||||||
// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
|
// where the mixing of different types is handled by scalar_product_traits
|
||||||
|
// In particular, real * complex<real> is allowed.
|
||||||
// FIXME move this to functor_traits adding a functor_default
|
// FIXME move this to functor_traits adding a functor_default
|
||||||
template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
|
template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
|
||||||
template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
||||||
template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
||||||
template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_quotient_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_quotient_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
|
||||||
|
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -800,7 +842,7 @@ struct scalar_pow_op {
|
|||||||
// FIXME default copy constructors seems bugged with std::complex<>
|
// FIXME default copy constructors seems bugged with std::complex<>
|
||||||
inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
|
inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
|
||||||
inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
|
inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
|
||||||
inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
|
inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
|
||||||
const Scalar m_exponent;
|
const Scalar m_exponent;
|
||||||
};
|
};
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct isMuchSmallerThan_object_selector
|
|||||||
{
|
{
|
||||||
static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
|
static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
|
||||||
{
|
{
|
||||||
return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum();
|
return x.cwiseAbs2().sum() <= numext::abs2(prec) * y.cwiseAbs2().sum();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ struct isMuchSmallerThan_scalar_selector
|
|||||||
{
|
{
|
||||||
static bool run(const Derived& x, const typename Derived::RealScalar& y, const typename Derived::RealScalar& prec)
|
static bool run(const Derived& x, const typename Derived::RealScalar& y, const typename Derived::RealScalar& prec)
|
||||||
{
|
{
|
||||||
return x.cwiseAbs2().sum() <= abs2(prec * y);
|
return x.cwiseAbs2().sum() <= numext::abs2(prec * y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest&
|
|||||||
// FIXME not very good if rhs is real and lhs complex while alpha is real too
|
// FIXME not very good if rhs is real and lhs complex while alpha is real too
|
||||||
const Index cols = dest.cols();
|
const Index cols = dest.cols();
|
||||||
for (Index j=0; j<cols; ++j)
|
for (Index j=0; j<cols; ++j)
|
||||||
func(dest.col(j), prod.rhs().coeff(j) * prod.lhs());
|
func(dest.col(j), prod.rhs().coeff(0,j) * prod.lhs());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Row major
|
// Row major
|
||||||
@@ -243,7 +243,7 @@ EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest&
|
|||||||
// FIXME not very good if lhs is real and rhs complex while alpha is real too
|
// FIXME not very good if lhs is real and rhs complex while alpha is real too
|
||||||
const Index rows = dest.rows();
|
const Index rows = dest.rows();
|
||||||
for (Index i=0; i<rows; ++i)
|
for (Index i=0; i<rows; ++i)
|
||||||
func(dest.row(i), prod.lhs().coeff(i) * prod.rhs());
|
func(dest.row(i), prod.lhs().coeff(i,0) * prod.rhs());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
@@ -435,7 +435,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
|
|||||||
|
|
||||||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
||||||
|
|
||||||
bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
|
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
||||||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
||||||
|
|
||||||
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ pnegate(const Packet& a) { return -a; }
|
|||||||
|
|
||||||
/** \internal \returns conj(a) (coeff-wise) */
|
/** \internal \returns conj(a) (coeff-wise) */
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
pconj(const Packet& a) { return conj(a); }
|
pconj(const Packet& a) { return numext::conj(a); }
|
||||||
|
|
||||||
/** \internal \returns a * b (coeff-wise) */
|
/** \internal \returns a * b (coeff-wise) */
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
@@ -156,7 +156,11 @@ pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
|||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||||
|
|
||||||
/** \internal \returns a packet with elements of \a *from duplicated, e.g.: (from[0],from[0],from[1],from[1]) */
|
/** \internal \returns a packet with elements of \a *from duplicated.
|
||||||
|
* For instance, for a packet of 8 elements, 4 scalar will be read from \a *from and
|
||||||
|
* duplicated to form: {from[0],from[0],from[1],from[1],,from[2],from[2],,from[3],from[3]}
|
||||||
|
* Currently, this function is only used for scalar * complex products.
|
||||||
|
*/
|
||||||
template<typename Packet> inline Packet
|
template<typename Packet> inline Packet
|
||||||
ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||||
|
|
||||||
@@ -307,8 +311,21 @@ struct palign_impl
|
|||||||
static inline void run(PacketType&, const PacketType&) {}
|
static inline void run(PacketType&, const PacketType&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \internal update \a first using the concatenation of the \a Offset last elements
|
/** \internal update \a first using the concatenation of the packet_size minus \a Offset last elements
|
||||||
* of \a first and packet_size minus \a Offset first elements of \a second */
|
* of \a first and \a Offset first elements of \a second.
|
||||||
|
*
|
||||||
|
* This function is currently only used to optimize matrix-vector products on unligned matrices.
|
||||||
|
* It takes 2 packets that represent a contiguous memory array, and returns a packet starting
|
||||||
|
* at the position \a Offset. For instance, for packets of 4 elements, we have:
|
||||||
|
* Input:
|
||||||
|
* - first = {f0,f1,f2,f3}
|
||||||
|
* - second = {s0,s1,s2,s3}
|
||||||
|
* Output:
|
||||||
|
* - if Offset==0 then {f0,f1,f2,f3}
|
||||||
|
* - if Offset==1 then {f1,f2,f3,s0}
|
||||||
|
* - if Offset==2 then {f2,f3,s0,s1}
|
||||||
|
* - if Offset==3 then {f3,s0,s1,s3}
|
||||||
|
*/
|
||||||
template<int Offset,typename PacketType>
|
template<int Offset,typename PacketType>
|
||||||
inline void palign(PacketType& first, const PacketType& second)
|
inline void palign(PacketType& first, const PacketType& second)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace Eigen
|
|||||||
{
|
{
|
||||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real,scalar_real_op)
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real,scalar_real_op)
|
||||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag,scalar_imag_op)
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag,scalar_imag_op)
|
||||||
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(conj,scalar_conjugate_op)
|
||||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin,scalar_sin_op)
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin,scalar_sin_op)
|
||||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos,scalar_cos_op)
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos,scalar_cos_op)
|
||||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op)
|
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op)
|
||||||
@@ -70,7 +71,7 @@ namespace Eigen
|
|||||||
**/
|
**/
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>
|
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>
|
||||||
operator/(typename Derived::Scalar s, const Eigen::ArrayBase<Derived>& a)
|
operator/(const typename Derived::Scalar& s, const Eigen::ArrayBase<Derived>& a)
|
||||||
{
|
{
|
||||||
return Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>(
|
return Eigen::CwiseUnaryOp<Eigen::internal::scalar_inverse_mult_op<typename Derived::Scalar>, const Derived>(
|
||||||
a.derived(),
|
a.derived(),
|
||||||
@@ -86,6 +87,6 @@ namespace Eigen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cleanly disable those functions that are not supported on Array (internal::real_ref, internal::random, internal::isApprox...)
|
// TODO: cleanly disable those functions that are not supported on Array (numext::real_ref, internal::random, internal::isApprox...)
|
||||||
|
|
||||||
#endif // EIGEN_GLOBAL_FUNCTIONS_H
|
#endif // EIGEN_GLOBAL_FUNCTIONS_H
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ struct IOFormat
|
|||||||
const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
|
const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
|
||||||
const std::string& _matPrefix="", const std::string& _matSuffix="")
|
const std::string& _matPrefix="", const std::string& _matSuffix="")
|
||||||
: matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
|
: matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
|
||||||
coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
|
rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
|
||||||
{
|
{
|
||||||
int i = int(matSuffix.length())-1;
|
int i = int(matSuffix.length())-1;
|
||||||
while (i>=0 && matSuffix[i]!='\n')
|
while (i>=0 && matSuffix[i]!='\n')
|
||||||
@@ -185,21 +185,22 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
|
|||||||
explicit_precision = fmt.precision;
|
explicit_precision = fmt.precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::streamsize old_precision = 0;
|
||||||
|
if(explicit_precision) old_precision = s.precision(explicit_precision);
|
||||||
|
|
||||||
bool align_cols = !(fmt.flags & DontAlignCols);
|
bool align_cols = !(fmt.flags & DontAlignCols);
|
||||||
if(align_cols)
|
if(align_cols)
|
||||||
{
|
{
|
||||||
// compute the largest width
|
// compute the largest width
|
||||||
for(Index j = 1; j < m.cols(); ++j)
|
for(Index j = 0; j < m.cols(); ++j)
|
||||||
for(Index i = 0; i < m.rows(); ++i)
|
for(Index i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
if(explicit_precision) sstr.precision(explicit_precision);
|
sstr.copyfmt(s);
|
||||||
sstr << m.coeff(i,j);
|
sstr << m.coeff(i,j);
|
||||||
width = std::max<Index>(width, Index(sstr.str().length()));
|
width = std::max<Index>(width, Index(sstr.str().length()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::streamsize old_precision = 0;
|
|
||||||
if(explicit_precision) old_precision = s.precision(explicit_precision);
|
|
||||||
s << fmt.matPrefix;
|
s << fmt.matPrefix;
|
||||||
for(Index i = 0; i < m.rows(); ++i)
|
for(Index i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -157,7 +157,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 +168,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,13 +231,17 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
using Base::Base::operator=;
|
// In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
|
||||||
|
// see bugs 821 and 920.
|
||||||
|
using ReadOnlyMapBase::Base::operator=;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_MAPBASE_H
|
#endif // EIGEN_MAPBASE_H
|
||||||
|
|||||||
@@ -51,16 +51,15 @@ struct global_math_functions_filtering_base
|
|||||||
typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
|
typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EIGEN_MATHFUNC_IMPL(func, scalar) func##_impl<typename global_math_functions_filtering_base<scalar>::type>
|
#define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>
|
||||||
#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type
|
#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of real *
|
* Implementation of real *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
|
||||||
struct real_impl
|
struct real_default_impl
|
||||||
{
|
{
|
||||||
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)
|
||||||
@@ -69,34 +68,32 @@ struct real_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar>
|
template<typename Scalar>
|
||||||
struct real_impl<std::complex<RealScalar> >
|
struct real_default_impl<Scalar,true>
|
||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
using std::real;
|
using std::real;
|
||||||
return real(x);
|
return real(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Scalar> struct real_impl : real_default_impl<Scalar> {};
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct real_retval
|
struct real_retval
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real type;
|
typedef typename NumTraits<Scalar>::Real type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of imag *
|
* Implementation of imag *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
|
||||||
struct imag_impl
|
struct imag_default_impl
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
static inline RealScalar run(const Scalar&)
|
static inline RealScalar run(const Scalar&)
|
||||||
@@ -105,28 +102,25 @@ struct imag_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar>
|
template<typename Scalar>
|
||||||
struct imag_impl<std::complex<RealScalar> >
|
struct imag_default_impl<Scalar,true>
|
||||||
{
|
{
|
||||||
static inline RealScalar run(const std::complex<RealScalar>& x)
|
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||||
|
static inline RealScalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
using std::imag;
|
using std::imag;
|
||||||
return imag(x);
|
return imag(x);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
struct imag_retval
|
struct imag_retval
|
||||||
{
|
{
|
||||||
typedef typename NumTraits<Scalar>::Real type;
|
typedef typename NumTraits<Scalar>::Real type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of real_ref *
|
* Implementation of real_ref *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -151,18 +145,6 @@ struct real_ref_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real & type;
|
typedef typename NumTraits<Scalar>::Real & type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
|
|
||||||
{
|
|
||||||
return real_ref_impl<Scalar>::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of imag_ref *
|
* Implementation of imag_ref *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -203,23 +185,11 @@ struct imag_ref_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real & type;
|
typedef typename NumTraits<Scalar>::Real & type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
|
|
||||||
{
|
|
||||||
return imag_ref_impl<Scalar>::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of conj *
|
* Implementation of conj *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
|
||||||
struct conj_impl
|
struct conj_impl
|
||||||
{
|
{
|
||||||
static inline Scalar run(const Scalar& x)
|
static inline Scalar run(const Scalar& x)
|
||||||
@@ -228,10 +198,10 @@ struct conj_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar>
|
template<typename Scalar>
|
||||||
struct conj_impl<std::complex<RealScalar> >
|
struct conj_impl<Scalar,true>
|
||||||
{
|
{
|
||||||
static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x)
|
static inline Scalar run(const Scalar& x)
|
||||||
{
|
{
|
||||||
using std::conj;
|
using std::conj;
|
||||||
return conj(x);
|
return conj(x);
|
||||||
@@ -244,12 +214,6 @@ struct conj_retval
|
|||||||
typedef Scalar type;
|
typedef Scalar type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of abs2 *
|
* Implementation of abs2 *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -279,12 +243,6 @@ struct abs2_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real type;
|
typedef typename NumTraits<Scalar>::Real type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of norm1 *
|
* Implementation of norm1 *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -319,12 +277,6 @@ struct norm1_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real type;
|
typedef typename NumTraits<Scalar>::Real type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of hypot *
|
* Implementation of hypot *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -342,6 +294,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;
|
||||||
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);
|
||||||
@@ -354,12 +307,6 @@ struct hypot_retval
|
|||||||
typedef typename NumTraits<Scalar>::Real type;
|
typedef typename NumTraits<Scalar>::Real type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of cast *
|
* Implementation of cast *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -396,7 +343,7 @@ struct atanh2_default_impl
|
|||||||
using std::log;
|
using std::log;
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
Scalar z = x / y;
|
Scalar z = x / y;
|
||||||
if (abs(z) > sqrt(NumTraits<RealScalar>::epsilon()))
|
if (y == Scalar(0) || abs(z) > sqrt(NumTraits<RealScalar>::epsilon()))
|
||||||
return RealScalar(0.5) * log((y + x) / (y - x));
|
return RealScalar(0.5) * log((y + x) / (y - x));
|
||||||
else
|
else
|
||||||
return z + z*z*z / RealScalar(3);
|
return z + z*z*z / RealScalar(3);
|
||||||
@@ -422,12 +369,6 @@ struct atanh2_retval
|
|||||||
typedef Scalar type;
|
typedef Scalar type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of pow *
|
* Implementation of pow *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -471,12 +412,6 @@ struct pow_retval
|
|||||||
typedef Scalar type;
|
typedef Scalar type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar>
|
|
||||||
inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
|
|
||||||
{
|
|
||||||
return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of random *
|
* Implementation of random *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -575,11 +510,10 @@ struct random_default_impl<Scalar, false, true>
|
|||||||
#else
|
#else
|
||||||
enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
|
enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
|
||||||
scalar_bits = sizeof(Scalar) * CHAR_BIT,
|
scalar_bits = sizeof(Scalar) * CHAR_BIT,
|
||||||
shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits))
|
shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)),
|
||||||
|
offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0
|
||||||
};
|
};
|
||||||
Scalar x = Scalar(std::rand() >> shift);
|
return Scalar((std::rand() >> shift) - offset);
|
||||||
Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0);
|
|
||||||
return x - offset;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -611,6 +545,97 @@ inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
|
|||||||
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
|
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // end namespace internal
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Generic math function *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
namespace numext {
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
|
||||||
|
{
|
||||||
|
return internal::real_ref_impl<Scalar>::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
|
||||||
|
{
|
||||||
|
return internal::imag_ref_impl<Scalar>::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Scalar>
|
||||||
|
inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
|
||||||
|
{
|
||||||
|
return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::isfinite is non standard, so let's define our own version,
|
||||||
|
// even though it is not very efficient.
|
||||||
|
template<typename T> bool (isfinite)(const T& x)
|
||||||
|
{
|
||||||
|
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace numext
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Implementation of fuzzy comparisons *
|
* Implementation of fuzzy comparisons *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -668,12 +693,12 @@ struct scalar_fuzzy_default_impl<Scalar, true, false>
|
|||||||
template<typename OtherScalar>
|
template<typename OtherScalar>
|
||||||
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
|
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
return abs2(x) <= abs2(y) * prec * prec;
|
return numext::abs2(x) <= numext::abs2(y) * prec * prec;
|
||||||
}
|
}
|
||||||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
|
||||||
{
|
{
|
||||||
using std::min;
|
using std::min;
|
||||||
return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec;
|
return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -735,17 +760,7 @@ template<> struct scalar_fuzzy_impl<bool>
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Special functions *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
// std::isfinite is non standard, so let's define our own version,
|
|
||||||
// even though it is not very efficient.
|
|
||||||
template<typename T> bool (isfinite)(const T& x)
|
|
||||||
{
|
|
||||||
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ class Matrix
|
|||||||
*
|
*
|
||||||
* \sa resize(Index,Index)
|
* \sa resize(Index,Index)
|
||||||
*/
|
*/
|
||||||
EIGEN_STRONG_INLINE explicit Matrix() : Base()
|
EIGEN_STRONG_INLINE Matrix() : Base()
|
||||||
{
|
{
|
||||||
Base::_check_template_params();
|
Base::_check_template_params();
|
||||||
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||||
@@ -304,7 +304,7 @@ class Matrix
|
|||||||
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
||||||
{
|
{
|
||||||
Base::_check_template_params();
|
Base::_check_template_params();
|
||||||
Base::resize(other.rows(), other.cols());
|
Base::_resize_to_match(other);
|
||||||
// FIXME/CHECK: isn't *this = other.derived() more efficient. it allows to
|
// FIXME/CHECK: isn't *this = other.derived() more efficient. it allows to
|
||||||
// go for pure _set() implementations, right?
|
// go for pure _set() implementations, right?
|
||||||
*this = other;
|
*this = other;
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -215,24 +213,20 @@ template<typename Derived> class MatrixBase
|
|||||||
|
|
||||||
typedef Diagonal<Derived> DiagonalReturnType;
|
typedef Diagonal<Derived> DiagonalReturnType;
|
||||||
DiagonalReturnType diagonal();
|
DiagonalReturnType diagonal();
|
||||||
typedef const Diagonal<const Derived> ConstDiagonalReturnType;
|
typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType;
|
||||||
const ConstDiagonalReturnType diagonal() const;
|
ConstDiagonalReturnType diagonal() const;
|
||||||
|
|
||||||
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
|
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
|
||||||
template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; };
|
template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; };
|
||||||
|
|
||||||
template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal();
|
template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal();
|
||||||
template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
|
template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
|
||||||
|
|
||||||
|
typedef Diagonal<Derived,DynamicIndex> DiagonalDynamicIndexReturnType;
|
||||||
|
typedef typename internal::add_const<Diagonal<const Derived,DynamicIndex> >::type ConstDiagonalDynamicIndexReturnType;
|
||||||
|
|
||||||
// Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
|
DiagonalDynamicIndexReturnType diagonal(Index index);
|
||||||
// On the other hand they confuse MSVC8...
|
ConstDiagonalDynamicIndexReturnType diagonal(Index index) const;
|
||||||
#if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later
|
|
||||||
typename MatrixBase::template DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
|
|
||||||
typename MatrixBase::template ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
|
|
||||||
#else
|
|
||||||
typename DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index);
|
|
||||||
typename ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
|
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
|
||||||
@@ -457,7 +451,7 @@ template<typename Derived> class MatrixBase
|
|||||||
const MatrixFunctionReturnValue<Derived> sin() const;
|
const MatrixFunctionReturnValue<Derived> sin() const;
|
||||||
const MatrixSquareRootReturnValue<Derived> sqrt() const;
|
const MatrixSquareRootReturnValue<Derived> sqrt() const;
|
||||||
const MatrixLogarithmReturnValue<Derived> log() const;
|
const MatrixLogarithmReturnValue<Derived> log() const;
|
||||||
const MatrixPowerReturnValue<Derived> pow(RealScalar p) const;
|
const MatrixPowerReturnValue<Derived> pow(const RealScalar& p) const;
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
@@ -510,6 +504,51 @@ template<typename Derived> class MatrixBase
|
|||||||
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;}
|
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Implementation of matrix base methods
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/** replaces \c *this by \c *this * \a other.
|
||||||
|
*
|
||||||
|
* \returns a reference to \c *this
|
||||||
|
*
|
||||||
|
* Example: \include MatrixBase_applyOnTheRight.cpp
|
||||||
|
* Output: \verbinclude MatrixBase_applyOnTheRight.out
|
||||||
|
*/
|
||||||
|
template<typename Derived>
|
||||||
|
template<typename OtherDerived>
|
||||||
|
inline Derived&
|
||||||
|
MatrixBase<Derived>::operator*=(const EigenBase<OtherDerived> &other)
|
||||||
|
{
|
||||||
|
other.derived().applyThisOnTheRight(derived());
|
||||||
|
return derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=().
|
||||||
|
*
|
||||||
|
* Example: \include MatrixBase_applyOnTheRight.cpp
|
||||||
|
* Output: \verbinclude MatrixBase_applyOnTheRight.out
|
||||||
|
*/
|
||||||
|
template<typename Derived>
|
||||||
|
template<typename OtherDerived>
|
||||||
|
inline void MatrixBase<Derived>::applyOnTheRight(const EigenBase<OtherDerived> &other)
|
||||||
|
{
|
||||||
|
other.derived().applyThisOnTheRight(derived());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** replaces \c *this by \a other * \c *this.
|
||||||
|
*
|
||||||
|
* Example: \include MatrixBase_applyOnTheLeft.cpp
|
||||||
|
* Output: \verbinclude MatrixBase_applyOnTheLeft.out
|
||||||
|
*/
|
||||||
|
template<typename Derived>
|
||||||
|
template<typename OtherDerived>
|
||||||
|
inline void MatrixBase<Derived>::applyOnTheLeft(const EigenBase<OtherDerived> &other)
|
||||||
|
{
|
||||||
|
other.derived().applyThisOnTheLeft(derived());
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|
||||||
#endif // EIGEN_MATRIXBASE_H
|
#endif // EIGEN_MATRIXBASE_H
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ class NoAlias
|
|||||||
template<typename Lhs, typename Rhs, int NestingFlags>
|
template<typename Lhs, typename Rhs, int NestingFlags>
|
||||||
EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
|
EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
|
||||||
{ return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
|
{ return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
|
||||||
|
|
||||||
|
template<typename OtherDerived>
|
||||||
|
ExpressionType& operator=(const ReturnByValue<OtherDerived>& func)
|
||||||
|
{ return m_expression = func; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExpressionType& expression() const
|
ExpressionType& expression() const
|
||||||
|
|||||||
@@ -140,6 +140,9 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
|||||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
||||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||||
|
static inline RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
@@ -541,24 +570,29 @@ struct permut_matrix_product_retval
|
|||||||
: public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> >
|
: public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> >
|
||||||
{
|
{
|
||||||
typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
|
typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
|
||||||
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix)
|
permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix)
|
||||||
: m_permutation(perm), m_matrix(matrix)
|
: m_permutation(perm), m_matrix(matrix)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline int rows() const { return m_matrix.rows(); }
|
inline Index rows() const { return m_matrix.rows(); }
|
||||||
inline int cols() const { return m_matrix.cols(); }
|
inline Index cols() const { return m_matrix.cols(); }
|
||||||
|
|
||||||
template<typename Dest> inline void evalTo(Dest& dst) const
|
template<typename Dest> inline void evalTo(Dest& dst) const
|
||||||
{
|
{
|
||||||
const int 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
|
||||||
if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix))
|
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
|
||||||
|
if( is_same<MatrixTypeNestedCleaned,Dest>::value
|
||||||
|
&& blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess
|
||||||
|
&& blas_traits<Dest>::HasUsableDirectAccess
|
||||||
|
&& extract_data(dst) == 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());
|
||||||
mask.fill(false);
|
mask.fill(false);
|
||||||
int r = 0;
|
Index r = 0;
|
||||||
while(r < m_permutation.size())
|
while(r < m_permutation.size())
|
||||||
{
|
{
|
||||||
// search for the next seed
|
// search for the next seed
|
||||||
@@ -566,10 +600,10 @@ struct permut_matrix_product_retval
|
|||||||
if(r>=m_permutation.size())
|
if(r>=m_permutation.size())
|
||||||
break;
|
break;
|
||||||
// we got one, let's follow it until we are back to the seed
|
// we got one, let's follow it until we are back to the seed
|
||||||
int k0 = r++;
|
Index k0 = r++;
|
||||||
int kPrev = k0;
|
Index kPrev = k0;
|
||||||
mask.coeffRef(k0) = true;
|
mask.coeffRef(k0) = true;
|
||||||
for(int k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
|
for(Index k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
|
||||||
{
|
{
|
||||||
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
|
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
|
||||||
.swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
|
.swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ template<> struct check_rows_cols_for_overflow<Dynamic> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
|
template <typename Derived,
|
||||||
|
typename OtherDerived = Derived,
|
||||||
|
bool IsVector = bool(Derived::IsVectorAtCompileTime) && bool(OtherDerived::IsVectorAtCompileTime)>
|
||||||
|
struct conservative_resize_like_impl;
|
||||||
|
|
||||||
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
|
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
|
||||||
|
|
||||||
@@ -418,7 +421,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||||||
return Base::operator=(func);
|
return Base::operator=(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
|
EIGEN_STRONG_INLINE PlainObjectBase() : m_storage()
|
||||||
{
|
{
|
||||||
// _check_template_params();
|
// _check_template_params();
|
||||||
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||||
@@ -570,6 +573,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
|
||||||
@@ -668,8 +673,10 @@ private:
|
|||||||
enum { ThisConstantIsPrivateInPlainObjectBase };
|
enum { ThisConstantIsPrivateInPlainObjectBase };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
template <typename Derived, typename OtherDerived, bool IsVector>
|
template <typename Derived, typename OtherDerived, bool IsVector>
|
||||||
struct internal::conservative_resize_like_impl
|
struct conservative_resize_like_impl
|
||||||
{
|
{
|
||||||
typedef typename Derived::Index Index;
|
typedef typename Derived::Index Index;
|
||||||
static void run(DenseBase<Derived>& _this, Index rows, Index cols)
|
static void run(DenseBase<Derived>& _this, Index rows, Index cols)
|
||||||
@@ -729,11 +736,14 @@ struct internal::conservative_resize_like_impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
// Here, the specialization for vectors inherits from the general matrix case
|
||||||
|
// to allow calling .conservativeResize(rows,cols) on vectors.
|
||||||
template <typename Derived, typename OtherDerived>
|
template <typename Derived, typename OtherDerived>
|
||||||
struct conservative_resize_like_impl<Derived,OtherDerived,true>
|
struct conservative_resize_like_impl<Derived,OtherDerived,true>
|
||||||
|
: conservative_resize_like_impl<Derived,OtherDerived,false>
|
||||||
{
|
{
|
||||||
|
using conservative_resize_like_impl<Derived,OtherDerived,false>::run;
|
||||||
|
|
||||||
typedef typename Derived::Index Index;
|
typedef typename Derived::Index Index;
|
||||||
static void run(DenseBase<Derived>& _this, Index size)
|
static void run(DenseBase<Derived>& _this, Index size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
// This file is part of Eigen, a lightweight C++ template library
|
|
||||||
// for linear algebra.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla
|
|
||||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
|
||||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
#ifndef EIGEN_PRODUCT_H
|
|
||||||
#define EIGEN_PRODUCT_H
|
|
||||||
|
|
||||||
namespace Eigen {
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs> class Product;
|
|
||||||
template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl;
|
|
||||||
|
|
||||||
/** \class Product
|
|
||||||
* \ingroup Core_Module
|
|
||||||
*
|
|
||||||
* \brief Expression of the product of two arbitrary matrices or vectors
|
|
||||||
*
|
|
||||||
* \param Lhs the type of the left-hand side expression
|
|
||||||
* \param Rhs the type of the right-hand side expression
|
|
||||||
*
|
|
||||||
* This class represents an expression of the product of two arbitrary matrices.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Use ProductReturnType to get correct traits, in particular vectorization flags
|
|
||||||
namespace internal {
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct traits<Product<Lhs, Rhs> >
|
|
||||||
: traits<typename ProductReturnType<Lhs, Rhs>::Type>
|
|
||||||
{
|
|
||||||
// We want A+B*C to be of type Product<Matrix, Sum> and not Product<Matrix, Matrix>
|
|
||||||
// TODO: This flag should eventually go in a separate evaluator traits class
|
|
||||||
enum {
|
|
||||||
Flags = traits<typename ProductReturnType<Lhs, Rhs>::Type>::Flags & ~EvalBeforeNestingBit
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} // end namespace internal
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
class Product : public ProductImpl<Lhs,Rhs,typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
|
|
||||||
typename internal::traits<Rhs>::StorageKind>::ret>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef typename ProductImpl<
|
|
||||||
Lhs, Rhs,
|
|
||||||
typename internal::promote_storage_type<typename Lhs::StorageKind,
|
|
||||||
typename Rhs::StorageKind>::ret>::Base Base;
|
|
||||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
|
|
||||||
|
|
||||||
typedef typename Lhs::Nested LhsNested;
|
|
||||||
typedef typename Rhs::Nested RhsNested;
|
|
||||||
typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned;
|
|
||||||
typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned;
|
|
||||||
|
|
||||||
Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs)
|
|
||||||
{
|
|
||||||
eigen_assert(lhs.cols() == rhs.rows()
|
|
||||||
&& "invalid matrix product"
|
|
||||||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Index rows() const { return m_lhs.rows(); }
|
|
||||||
inline Index cols() const { return m_rhs.cols(); }
|
|
||||||
|
|
||||||
const LhsNestedCleaned& lhs() const { return m_lhs; }
|
|
||||||
const RhsNestedCleaned& rhs() const { return m_rhs; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
LhsNested m_lhs;
|
|
||||||
RhsNested m_rhs;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
class ProductImpl<Lhs,Rhs,Dense> : public internal::dense_xpr_base<Product<Lhs,Rhs> >::type
|
|
||||||
{
|
|
||||||
typedef Product<Lhs, Rhs> Derived;
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef typename internal::dense_xpr_base<Product<Lhs, Rhs> >::type Base;
|
|
||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Implementation of matrix base methods
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/** \internal used to test the evaluator only
|
|
||||||
*/
|
|
||||||
template<typename Lhs,typename Rhs>
|
|
||||||
const Product<Lhs,Rhs>
|
|
||||||
prod(const Lhs& lhs, const Rhs& rhs)
|
|
||||||
{
|
|
||||||
return Product<Lhs,Rhs>(lhs,rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
|
||||||
|
|
||||||
#endif // EIGEN_PRODUCT_H
|
|
||||||
@@ -85,7 +85,14 @@ class ProductBase : public MatrixBase<Derived>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#ifndef EIGEN_NO_MALLOC
|
||||||
|
typedef typename Base::PlainObject BasePlainObject;
|
||||||
|
typedef Matrix<Scalar,RowsAtCompileTime==1?1:Dynamic,ColsAtCompileTime==1?1:Dynamic,BasePlainObject::Options> DynPlainObject;
|
||||||
|
typedef typename internal::conditional<(BasePlainObject::SizeAtCompileTime==Dynamic) || (BasePlainObject::SizeAtCompileTime*int(sizeof(Scalar)) < int(EIGEN_STACK_ALLOCATION_LIMIT)),
|
||||||
|
BasePlainObject, DynPlainObject>::type PlainObject;
|
||||||
|
#else
|
||||||
typedef typename Base::PlainObject PlainObject;
|
typedef typename Base::PlainObject PlainObject;
|
||||||
|
#endif
|
||||||
|
|
||||||
ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
|
ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
|
||||||
: m_lhs(a_lhs), m_rhs(a_rhs)
|
: m_lhs(a_lhs), m_rhs(a_rhs)
|
||||||
@@ -180,7 +187,12 @@ namespace internal {
|
|||||||
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
|
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
|
||||||
struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
|
struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
|
||||||
{
|
{
|
||||||
typedef PlainObject const& type;
|
typedef typename GeneralProduct<Lhs,Rhs,Mode>::PlainObject const& type;
|
||||||
|
};
|
||||||
|
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
|
||||||
|
struct nested<const GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
|
||||||
|
{
|
||||||
|
typedef typename GeneralProduct<Lhs,Rhs,Mode>::PlainObject const& type;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +207,7 @@ class ScaledProduct;
|
|||||||
// Also note that here we accept any compatible scalar types
|
// Also note that here we accept any compatible scalar types
|
||||||
template<typename Derived,typename Lhs,typename Rhs>
|
template<typename Derived,typename Lhs,typename Rhs>
|
||||||
const ScaledProduct<Derived>
|
const ScaledProduct<Derived>
|
||||||
operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::Scalar x)
|
operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::Scalar& x)
|
||||||
{ return ScaledProduct<Derived>(prod.derived(), x); }
|
{ return ScaledProduct<Derived>(prod.derived(), x); }
|
||||||
|
|
||||||
template<typename Derived,typename Lhs,typename Rhs>
|
template<typename Derived,typename Lhs,typename Rhs>
|
||||||
@@ -207,7 +219,7 @@ operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::Real
|
|||||||
|
|
||||||
template<typename Derived,typename Lhs,typename Rhs>
|
template<typename Derived,typename Lhs,typename Rhs>
|
||||||
const ScaledProduct<Derived>
|
const ScaledProduct<Derived>
|
||||||
operator*(typename Derived::Scalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
|
operator*(const typename Derived::Scalar& x,const ProductBase<Derived,Lhs,Rhs>& prod)
|
||||||
{ return ScaledProduct<Derived>(prod.derived(), x); }
|
{ return ScaledProduct<Derived>(prod.derived(), x); }
|
||||||
|
|
||||||
template<typename Derived,typename Lhs,typename Rhs>
|
template<typename Derived,typename Lhs,typename Rhs>
|
||||||
|
|||||||
@@ -1,411 +0,0 @@
|
|||||||
// This file is part of Eigen, a lightweight C++ template library
|
|
||||||
// for linear algebra.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
|
||||||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
|
||||||
// Copyright (C) 2011 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the Mozilla
|
|
||||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
|
||||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef EIGEN_PRODUCTEVALUATORS_H
|
|
||||||
#define EIGEN_PRODUCTEVALUATORS_H
|
|
||||||
|
|
||||||
namespace Eigen {
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// We can evaluate the product either all at once, like GeneralProduct and its evalTo() function, or
|
|
||||||
// traverse the matrix coefficient by coefficient, like CoeffBasedProduct. Use the existing logic
|
|
||||||
// in ProductReturnType to decide.
|
|
||||||
|
|
||||||
template<typename XprType, typename ProductType>
|
|
||||||
struct product_evaluator_dispatcher;
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct evaluator_impl<Product<Lhs, Rhs> >
|
|
||||||
: product_evaluator_dispatcher<Product<Lhs, Rhs>, typename ProductReturnType<Lhs, Rhs>::Type>
|
|
||||||
{
|
|
||||||
typedef Product<Lhs, Rhs> XprType;
|
|
||||||
typedef product_evaluator_dispatcher<XprType, typename ProductReturnType<Lhs, Rhs>::Type> Base;
|
|
||||||
|
|
||||||
evaluator_impl(const XprType& xpr) : Base(xpr)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename XprType, typename ProductType>
|
|
||||||
struct product_evaluator_traits_dispatcher;
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct evaluator_traits<Product<Lhs, Rhs> >
|
|
||||||
: product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, typename ProductReturnType<Lhs, Rhs>::Type>
|
|
||||||
{
|
|
||||||
static const int AssumeAliasing = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Case 1: Evaluate all at once
|
|
||||||
//
|
|
||||||
// We can view the GeneralProduct class as a part of the product evaluator.
|
|
||||||
// Four sub-cases: InnerProduct, OuterProduct, GemmProduct and GemvProduct.
|
|
||||||
// InnerProduct is special because GeneralProduct does not have an evalTo() method in this case.
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, GeneralProduct<Lhs, Rhs, InnerProduct> >
|
|
||||||
{
|
|
||||||
static const int HasEvalTo = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct product_evaluator_dispatcher<Product<Lhs, Rhs>, GeneralProduct<Lhs, Rhs, InnerProduct> >
|
|
||||||
: public evaluator<typename Product<Lhs, Rhs>::PlainObject>::type
|
|
||||||
{
|
|
||||||
typedef Product<Lhs, Rhs> XprType;
|
|
||||||
typedef typename XprType::PlainObject PlainObject;
|
|
||||||
typedef typename evaluator<PlainObject>::type evaluator_base;
|
|
||||||
|
|
||||||
// TODO: Computation is too early (?)
|
|
||||||
product_evaluator_dispatcher(const XprType& xpr) : evaluator_base(m_result)
|
|
||||||
{
|
|
||||||
m_result.coeffRef(0,0) = (xpr.lhs().transpose().cwiseProduct(xpr.rhs())).sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PlainObject m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// For the other three subcases, simply call the evalTo() method of GeneralProduct
|
|
||||||
// TODO: GeneralProduct should take evaluators, not expression objects.
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, int ProductType>
|
|
||||||
struct product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, GeneralProduct<Lhs, Rhs, ProductType> >
|
|
||||||
{
|
|
||||||
static const int HasEvalTo = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, int ProductType>
|
|
||||||
struct product_evaluator_dispatcher<Product<Lhs, Rhs>, GeneralProduct<Lhs, Rhs, ProductType> >
|
|
||||||
{
|
|
||||||
typedef Product<Lhs, Rhs> XprType;
|
|
||||||
typedef typename XprType::PlainObject PlainObject;
|
|
||||||
typedef typename evaluator<PlainObject>::type evaluator_base;
|
|
||||||
|
|
||||||
product_evaluator_dispatcher(const XprType& xpr) : m_xpr(xpr)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
template<typename DstEvaluatorType, typename DstXprType>
|
|
||||||
void evalTo(DstEvaluatorType /* not used */, DstXprType& dst)
|
|
||||||
{
|
|
||||||
dst.resize(m_xpr.rows(), m_xpr.cols());
|
|
||||||
GeneralProduct<Lhs, Rhs, ProductType>(m_xpr.lhs(), m_xpr.rhs()).evalTo(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const XprType& m_xpr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Case 2: Evaluate coeff by coeff
|
|
||||||
//
|
|
||||||
// This is mostly taken from CoeffBasedProduct.h
|
|
||||||
// The main difference is that we add an extra argument to the etor_product_*_impl::run() function
|
|
||||||
// for the inner dimension of the product, because evaluator object do not know their size.
|
|
||||||
|
|
||||||
template<int Traversal, int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl;
|
|
||||||
|
|
||||||
template<int StorageOrder, int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_product_packet_impl;
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename LhsNested, typename RhsNested, int Flags>
|
|
||||||
struct product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, CoeffBasedProduct<LhsNested, RhsNested, Flags> >
|
|
||||||
{
|
|
||||||
static const int HasEvalTo = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename LhsNested, typename RhsNested, int Flags>
|
|
||||||
struct product_evaluator_dispatcher<Product<Lhs, Rhs>, CoeffBasedProduct<LhsNested, RhsNested, Flags> >
|
|
||||||
: evaluator_impl_base<Product<Lhs, Rhs> >
|
|
||||||
{
|
|
||||||
typedef Product<Lhs, Rhs> XprType;
|
|
||||||
typedef CoeffBasedProduct<LhsNested, RhsNested, Flags> CoeffBasedProductType;
|
|
||||||
|
|
||||||
product_evaluator_dispatcher(const XprType& xpr)
|
|
||||||
: m_lhsImpl(xpr.lhs()),
|
|
||||||
m_rhsImpl(xpr.rhs()),
|
|
||||||
m_innerDim(xpr.lhs().cols())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
typedef typename XprType::Index Index;
|
|
||||||
typedef typename XprType::Scalar Scalar;
|
|
||||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
|
||||||
typedef typename XprType::PacketScalar PacketScalar;
|
|
||||||
typedef typename XprType::PacketReturnType PacketReturnType;
|
|
||||||
|
|
||||||
// Everything below here is taken from CoeffBasedProduct.h
|
|
||||||
|
|
||||||
enum {
|
|
||||||
RowsAtCompileTime = traits<CoeffBasedProductType>::RowsAtCompileTime,
|
|
||||||
PacketSize = packet_traits<Scalar>::size,
|
|
||||||
InnerSize = traits<CoeffBasedProductType>::InnerSize,
|
|
||||||
CoeffReadCost = traits<CoeffBasedProductType>::CoeffReadCost,
|
|
||||||
Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
|
|
||||||
CanVectorizeInner = traits<CoeffBasedProductType>::CanVectorizeInner
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef typename evaluator<Lhs>::type LhsEtorType;
|
|
||||||
typedef typename evaluator<Rhs>::type RhsEtorType;
|
|
||||||
typedef etor_product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
|
||||||
Unroll ? InnerSize-1 : Dynamic,
|
|
||||||
LhsEtorType, RhsEtorType, Scalar> CoeffImpl;
|
|
||||||
|
|
||||||
const CoeffReturnType coeff(Index row, Index col) const
|
|
||||||
{
|
|
||||||
Scalar res;
|
|
||||||
CoeffImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow index-based non-packet access. It is impossible though to allow index-based packed access,
|
|
||||||
* which is why we don't set the LinearAccessBit.
|
|
||||||
*/
|
|
||||||
const CoeffReturnType coeff(Index index) const
|
|
||||||
{
|
|
||||||
Scalar res;
|
|
||||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
|
||||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
|
||||||
CoeffImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int LoadMode>
|
|
||||||
const PacketReturnType packet(Index row, Index col) const
|
|
||||||
{
|
|
||||||
PacketScalar res;
|
|
||||||
typedef etor_product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
|
|
||||||
Unroll ? InnerSize-1 : Dynamic,
|
|
||||||
LhsEtorType, RhsEtorType, PacketScalar, LoadMode> PacketImpl;
|
|
||||||
PacketImpl::run(row, col, m_lhsImpl, m_rhsImpl, m_innerDim, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typename evaluator<Lhs>::type m_lhsImpl;
|
|
||||||
typename evaluator<Rhs>::type m_rhsImpl;
|
|
||||||
|
|
||||||
// TODO: Get rid of m_innerDim if known at compile time
|
|
||||||
Index m_innerDim;
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Normal product .coeff() implementation (with meta-unrolling)
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/**************************************
|
|
||||||
*** Scalar path - no vectorization ***
|
|
||||||
**************************************/
|
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, RetScalar &res)
|
|
||||||
{
|
|
||||||
etor_product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, innerDim, res);
|
|
||||||
res += lhs.coeff(row, UnrollingIndex) * rhs.coeff(UnrollingIndex, col);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl<DefaultTraversal, 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, Index /*innerDim*/, RetScalar &res)
|
|
||||||
{
|
|
||||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, RetScalar& res)
|
|
||||||
{
|
|
||||||
eigen_assert(innerDim>0 && "you are using a non initialized matrix");
|
|
||||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
|
||||||
for(Index i = 1; i < innerDim; ++i)
|
|
||||||
res += lhs.coeff(row, i) * rhs.coeff(i, col);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*******************************************
|
|
||||||
*** Scalar path with inner vectorization ***
|
|
||||||
*******************************************/
|
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet>
|
|
||||||
struct etor_product_coeff_vectorized_unroller
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, typename Lhs::PacketScalar &pres)
|
|
||||||
{
|
|
||||||
etor_product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, innerDim, pres);
|
|
||||||
pres = padd(pres, pmul( lhs.template packet<Aligned>(row, UnrollingIndex) , rhs.template packet<Aligned>(UnrollingIndex, col) ));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet>
|
|
||||||
struct etor_product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, typename Lhs::PacketScalar &pres)
|
|
||||||
{
|
|
||||||
pres = pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::PacketScalar Packet;
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, RetScalar &res)
|
|
||||||
{
|
|
||||||
Packet pres;
|
|
||||||
etor_product_coeff_vectorized_unroller<UnrollingIndex+1-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, innerDim, pres);
|
|
||||||
etor_product_coeff_impl<DefaultTraversal,UnrollingIndex,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, innerDim, res);
|
|
||||||
res = predux(pres);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime>
|
|
||||||
struct etor_product_coeff_vectorized_dyn_selector
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, typename Lhs::Scalar &res)
|
|
||||||
{
|
|
||||||
res = lhs.row(row).transpose().cwiseProduct(rhs.col(col)).sum();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// NOTE the 3 following specializations are because taking .col(0) on a vector is a bit slower
|
|
||||||
// NOTE maybe they are now useless since we have a specialization for Block<Matrix>
|
|
||||||
template<typename Lhs, typename Rhs, int RhsCols>
|
|
||||||
struct etor_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, typename Lhs::Scalar &res)
|
|
||||||
{
|
|
||||||
res = lhs.transpose().cwiseProduct(rhs.col(col)).sum();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, int LhsRows>
|
|
||||||
struct etor_product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, typename Lhs::Scalar &res)
|
|
||||||
{
|
|
||||||
res = lhs.row(row).transpose().cwiseProduct(rhs).sum();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
|
||||||
struct etor_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, typename Lhs::Scalar &res)
|
|
||||||
{
|
|
||||||
res = lhs.transpose().cwiseProduct(rhs).sum();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
|
||||||
struct etor_product_coeff_impl<InnerVectorizedTraversal, Dynamic, Lhs, Rhs, RetScalar>
|
|
||||||
{
|
|
||||||
typedef typename Lhs::Index Index;
|
|
||||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, typename Lhs::Scalar &res)
|
|
||||||
{
|
|
||||||
etor_product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, innerDim, res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*******************
|
|
||||||
*** Packet path ***
|
|
||||||
*******************/
|
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_product_packet_impl<RowMajor, UnrollingIndex, 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, Index innerDim, Packet &res)
|
|
||||||
{
|
|
||||||
etor_product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, innerDim, res);
|
|
||||||
res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex)), rhs.template packet<LoadMode>(UnrollingIndex, col), res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_product_packet_impl<ColMajor, UnrollingIndex, 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, Index innerDim, Packet &res)
|
|
||||||
{
|
|
||||||
etor_product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, innerDim, res);
|
|
||||||
res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex), pset1<Packet>(rhs.coeff(UnrollingIndex, col)), res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_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, Index /*innerDim*/, Packet &res)
|
|
||||||
{
|
|
||||||
res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_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, Index /*innerDim*/, Packet &res)
|
|
||||||
{
|
|
||||||
res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_product_packet_impl<RowMajor, Dynamic, 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, Index innerDim, Packet& res)
|
|
||||||
{
|
|
||||||
eigen_assert(innerDim>0 && "you are using a non initialized matrix");
|
|
||||||
res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
|
||||||
for(Index i = 1; i < innerDim; ++i)
|
|
||||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
|
||||||
struct etor_product_packet_impl<ColMajor, Dynamic, 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, Index innerDim, Packet& res)
|
|
||||||
{
|
|
||||||
eigen_assert(innerDim>0 && "you are using a non initialized matrix");
|
|
||||||
res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
|
|
||||||
for(Index i = 1; i < innerDim; ++i)
|
|
||||||
res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace internal
|
|
||||||
|
|
||||||
} // end namespace Eigen
|
|
||||||
|
|
||||||
#endif // EIGEN_PRODUCT_EVALUATORS_H
|
|
||||||
@@ -330,7 +330,8 @@ DenseBase<Derived>::redux(const Func& func) const
|
|||||||
::run(derived(), func);
|
::run(derived(), func);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the minimum of all coefficients of *this
|
/** \returns the minimum of all coefficients of \c *this.
|
||||||
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||||
@@ -339,7 +340,8 @@ DenseBase<Derived>::minCoeff() const
|
|||||||
return this->redux(Eigen::internal::scalar_min_op<Scalar>());
|
return this->redux(Eigen::internal::scalar_min_op<Scalar>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the maximum of all coefficients of *this
|
/** \returns the maximum of all coefficients of \c *this.
|
||||||
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||||
|
|||||||
@@ -94,24 +94,26 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
|||||||
typedef _PlainObjectType PlainObjectType;
|
typedef _PlainObjectType PlainObjectType;
|
||||||
typedef _StrideType StrideType;
|
typedef _StrideType StrideType;
|
||||||
enum {
|
enum {
|
||||||
Options = _Options
|
Options = _Options,
|
||||||
|
Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived> struct match {
|
template<typename Derived> struct match {
|
||||||
enum {
|
enum {
|
||||||
HasDirectAccess = internal::has_direct_access<Derived>::ret,
|
HasDirectAccess = internal::has_direct_access<Derived>::ret,
|
||||||
StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
|
StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
|
||||||
InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
|
InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
|
||||||
|| int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
|
|| int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
|
||||||
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -171,8 +173,12 @@ protected:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
|
::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
|
||||||
::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
|
|
||||||
StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
|
if(Expression::IsVectorAtCompileTime && (!PlainObjectType::IsVectorAtCompileTime) && ((Expression::Flags&RowMajorBit)!=(PlainObjectType::Flags&RowMajorBit)))
|
||||||
|
::new (&m_stride) StrideBase(expr.innerStride(), StrideType::InnerStrideAtCompileTime==0?0:1);
|
||||||
|
else
|
||||||
|
::new (&m_stride) StrideBase(StrideType::OuterStrideAtCompileTime==0?0:expr.outerStride(),
|
||||||
|
StrideType::InnerStrideAtCompileTime==0?0:expr.innerStride());
|
||||||
}
|
}
|
||||||
|
|
||||||
StrideBase m_stride;
|
StrideBase m_stride;
|
||||||
@@ -182,7 +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>
|
||||||
|
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;
|
||||||
@@ -194,17 +204,20 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
|||||||
inline Ref(PlainObjectBase<Derived>& expr,
|
inline Ref(PlainObjectBase<Derived>& expr,
|
||||||
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
||||||
{
|
{
|
||||||
Base::construct(expr);
|
EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||||
|
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(internal::is_lvalue<Derived>::value&&bool(Traits::template match<Derived>::MatchAtCompileTime)),Derived>::type* = 0,
|
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
||||||
int = Derived::ThisConstantIsPrivateInPlainObjectBase)
|
|
||||||
#else
|
#else
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Ref(DenseBase<Derived>& expr)
|
inline Ref(DenseBase<Derived>& expr)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
EIGEN_STATIC_ASSERT(static_cast<bool>(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||||
|
EIGEN_STATIC_ASSERT(static_cast<bool>(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||||
|
enum { THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY = Derived::ThisConstantIsPrivateInPlainObjectBase};
|
||||||
Base::construct(expr.const_cast_derived());
|
Base::construct(expr.const_cast_derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +236,8 @@ 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";
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
|
|||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<int RowFactor, int ColFactor>
|
template<int RowFactor, int ColFactor>
|
||||||
inline const Replicate<Derived,RowFactor,ColFactor>
|
const Replicate<Derived,RowFactor,ColFactor>
|
||||||
DenseBase<Derived>::replicate() const
|
DenseBase<Derived>::replicate() const
|
||||||
{
|
{
|
||||||
return Replicate<Derived,RowFactor,ColFactor>(derived());
|
return Replicate<Derived,RowFactor,ColFactor>(derived());
|
||||||
@@ -150,7 +150,7 @@ DenseBase<Derived>::replicate() const
|
|||||||
* \sa VectorwiseOp::replicate(), DenseBase::replicate<int,int>(), class Replicate
|
* \sa VectorwiseOp::replicate(), DenseBase::replicate<int,int>(), class Replicate
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline const Replicate<Derived,Dynamic,Dynamic>
|
const typename DenseBase<Derived>::ReplicateReturnType
|
||||||
DenseBase<Derived>::replicate(Index rowFactor,Index colFactor) const
|
DenseBase<Derived>::replicate(Index rowFactor,Index colFactor) const
|
||||||
{
|
{
|
||||||
return Replicate<Derived,Dynamic,Dynamic>(derived(),rowFactor,colFactor);
|
return Replicate<Derived,Dynamic,Dynamic>(derived(),rowFactor,colFactor);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ struct nested<ReturnByValue<Derived>, n, PlainObject>
|
|||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
template<typename Derived> class ReturnByValue
|
template<typename Derived> class ReturnByValue
|
||||||
: public internal::dense_xpr_base< ReturnByValue<Derived> >::type
|
: internal::no_assignment_operator, public internal::dense_xpr_base< ReturnByValue<Derived> >::type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename internal::traits<Derived>::ReturnType ReturnType;
|
typedef typename internal::traits<Derived>::ReturnType ReturnType;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ template<typename Derived>
|
|||||||
template<typename ThenDerived>
|
template<typename ThenDerived>
|
||||||
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
||||||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
|
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
|
||||||
typename ThenDerived::Scalar elseScalar) const
|
const typename ThenDerived::Scalar& elseScalar) const
|
||||||
{
|
{
|
||||||
return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>(
|
return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>(
|
||||||
derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar));
|
derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar));
|
||||||
@@ -150,8 +150,8 @@ DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
|
|||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename ElseDerived>
|
template<typename ElseDerived>
|
||||||
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
||||||
DenseBase<Derived>::select(typename ElseDerived::Scalar thenScalar,
|
DenseBase<Derived>::select(const typename ElseDerived::Scalar& thenScalar,
|
||||||
const DenseBase<ElseDerived>& elseMatrix) const
|
const DenseBase<ElseDerived>& elseMatrix) const
|
||||||
{
|
{
|
||||||
return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>(
|
return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>(
|
||||||
derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived());
|
derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived());
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
|
|||||||
* \sa rankUpdate(const MatrixBase<DerivedU>&, Scalar)
|
* \sa rankUpdate(const MatrixBase<DerivedU>&, Scalar)
|
||||||
*/
|
*/
|
||||||
template<typename DerivedU, typename DerivedV>
|
template<typename DerivedU, typename DerivedV>
|
||||||
SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha = Scalar(1));
|
SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, const Scalar& alpha = Scalar(1));
|
||||||
|
|
||||||
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
|
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
|
||||||
* \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
|
* \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
|
||||||
@@ -145,7 +145,7 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
|
|||||||
* \sa rankUpdate(const MatrixBase<DerivedU>&, const MatrixBase<DerivedV>&, Scalar)
|
* \sa rankUpdate(const MatrixBase<DerivedU>&, const MatrixBase<DerivedV>&, Scalar)
|
||||||
*/
|
*/
|
||||||
template<typename DerivedU>
|
template<typename DerivedU>
|
||||||
SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
|
SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const Scalar& alpha = Scalar(1));
|
||||||
|
|
||||||
/////////// Cholesky module ///////////
|
/////////// Cholesky module ///////////
|
||||||
|
|
||||||
@@ -214,9 +214,9 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), U
|
|||||||
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount-1, ClearOpposite>::run(dst, src);
|
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount-1, ClearOpposite>::run(dst, src);
|
||||||
|
|
||||||
if(row == col)
|
if(row == col)
|
||||||
dst.coeffRef(row, col) = real(src.coeff(row, col));
|
dst.coeffRef(row, col) = numext::real(src.coeff(row, col));
|
||||||
else if(row < col)
|
else if(row < col)
|
||||||
dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
|
dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -239,9 +239,9 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), U
|
|||||||
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), UnrollCount-1, ClearOpposite>::run(dst, src);
|
triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), UnrollCount-1, ClearOpposite>::run(dst, src);
|
||||||
|
|
||||||
if(row == col)
|
if(row == col)
|
||||||
dst.coeffRef(row, col) = real(src.coeff(row, col));
|
dst.coeffRef(row, col) = numext::real(src.coeff(row, col));
|
||||||
else if(row > col)
|
else if(row > col)
|
||||||
dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
|
dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dyn
|
|||||||
for(Index i = 0; i < j; ++i)
|
for(Index i = 0; i < j; ++i)
|
||||||
{
|
{
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
dst.coeffRef(j,i) = conj(dst.coeff(i,j));
|
dst.coeffRef(j,i) = numext::conj(dst.coeff(i,j));
|
||||||
}
|
}
|
||||||
dst.copyCoeff(j, j, src);
|
dst.copyCoeff(j, j, src);
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dyn
|
|||||||
for(Index j = 0; j < i; ++j)
|
for(Index j = 0; j < i; ++j)
|
||||||
{
|
{
|
||||||
dst.copyCoeff(i, j, src);
|
dst.copyCoeff(i, j, src);
|
||||||
dst.coeffRef(j,i) = conj(dst.coeff(i,j));
|
dst.coeffRef(j,i) = numext::conj(dst.coeff(i,j));
|
||||||
}
|
}
|
||||||
dst.copyCoeff(i, i, src);
|
dst.copyCoeff(i, i, src);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,26 +13,39 @@
|
|||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template<typename ExpressionType, typename Scalar>
|
template<typename ExpressionType, typename Scalar>
|
||||||
inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale)
|
inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale)
|
||||||
{
|
{
|
||||||
Scalar max = bl.cwiseAbs().maxCoeff();
|
using std::max;
|
||||||
if (max>scale)
|
Scalar maxCoeff = bl.cwiseAbs().maxCoeff();
|
||||||
|
|
||||||
|
if (maxCoeff>scale)
|
||||||
{
|
{
|
||||||
ssq = ssq * abs2(scale/max);
|
ssq = ssq * numext::abs2(scale/maxCoeff);
|
||||||
scale = max;
|
Scalar tmp = Scalar(1)/maxCoeff;
|
||||||
invScale = Scalar(1)/scale;
|
if(tmp > NumTraits<Scalar>::highest())
|
||||||
|
{
|
||||||
|
invScale = NumTraits<Scalar>::highest();
|
||||||
|
scale = Scalar(1)/invScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scale = maxCoeff;
|
||||||
|
invScale = tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO if the max is much much smaller than the current scale,
|
|
||||||
|
// TODO if the maxCoeff is much much smaller than the current scale,
|
||||||
// then we can neglect this sub vector
|
// then we can neglect this sub vector
|
||||||
ssq += (bl*invScale).squaredNorm();
|
if(scale>Scalar(0)) // if scale==0, then bl is 0
|
||||||
|
ssq += (bl*invScale).squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline typename NumTraits<typename traits<Derived>::Scalar>::Real
|
inline typename NumTraits<typename traits<Derived>::Scalar>::Real
|
||||||
blueNorm_impl(const EigenBase<Derived>& _vec)
|
blueNorm_impl(const EigenBase<Derived>& _vec)
|
||||||
{
|
{
|
||||||
typedef typename Derived::Scalar Scalar;
|
|
||||||
typedef typename Derived::RealScalar RealScalar;
|
typedef typename Derived::RealScalar RealScalar;
|
||||||
typedef typename Derived::Index Index;
|
typedef typename Derived::Index Index;
|
||||||
using std::pow;
|
using std::pow;
|
||||||
@@ -41,43 +54,40 @@ blueNorm_impl(const EigenBase<Derived>& _vec)
|
|||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
using std::abs;
|
using std::abs;
|
||||||
const Derived& vec(_vec.derived());
|
const Derived& vec(_vec.derived());
|
||||||
static Index nmax = -1;
|
static bool initialized = false;
|
||||||
static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
|
static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
|
||||||
if(nmax <= 0)
|
if(!initialized)
|
||||||
{
|
{
|
||||||
int nbig, ibeta, it, iemin, iemax, iexp;
|
int ibeta, it, iemin, iemax, iexp;
|
||||||
RealScalar abig, eps;
|
RealScalar eps;
|
||||||
// This program calculates the machine-dependent constants
|
// This program calculates the machine-dependent constants
|
||||||
// bl, b2, slm, s2m, relerr overfl, nmax
|
// bl, b2, slm, s2m, relerr overfl
|
||||||
// from the "basic" machine-dependent numbers
|
// from the "basic" machine-dependent numbers
|
||||||
// nbig, ibeta, it, iemin, iemax, rbig.
|
// nbig, ibeta, it, iemin, iemax, rbig.
|
||||||
// The following define the basic machine-dependent constants.
|
// The following define the basic machine-dependent constants.
|
||||||
// For portability, the PORT subprograms "ilmaeh" and "rlmach"
|
// For portability, the PORT subprograms "ilmaeh" and "rlmach"
|
||||||
// are used. For any specific computer, each of the assignment
|
// are used. For any specific computer, each of the assignment
|
||||||
// statements can be replaced
|
// statements can be replaced
|
||||||
nbig = (std::numeric_limits<Index>::max)(); // largest integer
|
ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
|
||||||
ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
|
it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
|
||||||
it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
|
iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
|
||||||
iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
|
iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
|
||||||
iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
|
rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
|
||||||
rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
|
|
||||||
|
|
||||||
iexp = -((1-iemin)/2);
|
iexp = -((1-iemin)/2);
|
||||||
b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
|
b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
|
||||||
iexp = (iemax + 1 - it)/2;
|
iexp = (iemax + 1 - it)/2;
|
||||||
b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
|
b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
|
||||||
|
|
||||||
iexp = (2-iemin)/2;
|
iexp = (2-iemin)/2;
|
||||||
s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
|
s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
|
||||||
iexp = - ((iemax+it)/2);
|
iexp = - ((iemax+it)/2);
|
||||||
s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
|
s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
|
||||||
|
|
||||||
overfl = rbig*s2m; // overflow boundary for abig
|
overfl = rbig*s2m; // overflow boundary for abig
|
||||||
eps = RealScalar(pow(double(ibeta), 1-it));
|
eps = RealScalar(pow(double(ibeta), 1-it));
|
||||||
relerr = sqrt(eps); // tolerance for neglecting asml
|
relerr = sqrt(eps); // tolerance for neglecting asml
|
||||||
abig = RealScalar(1.0/eps - 1.0);
|
initialized = true;
|
||||||
if (RealScalar(nbig)>abig) nmax = int(abig); // largest safe n
|
|
||||||
else nmax = nbig;
|
|
||||||
}
|
}
|
||||||
Index n = vec.size();
|
Index n = vec.size();
|
||||||
RealScalar ab2 = b2 / RealScalar(n);
|
RealScalar ab2 = b2 / RealScalar(n);
|
||||||
@@ -87,9 +97,9 @@ blueNorm_impl(const EigenBase<Derived>& _vec)
|
|||||||
for(typename Derived::InnerIterator it(vec, 0); it; ++it)
|
for(typename Derived::InnerIterator it(vec, 0); it; ++it)
|
||||||
{
|
{
|
||||||
RealScalar ax = abs(it.value());
|
RealScalar ax = abs(it.value());
|
||||||
if(ax > ab2) abig += internal::abs2(ax*s2m);
|
if(ax > ab2) abig += numext::abs2(ax*s2m);
|
||||||
else if(ax < b1) asml += internal::abs2(ax*s1m);
|
else if(ax < b1) asml += numext::abs2(ax*s1m);
|
||||||
else amed += internal::abs2(ax);
|
else amed += numext::abs2(ax);
|
||||||
}
|
}
|
||||||
if(abig > RealScalar(0))
|
if(abig > RealScalar(0))
|
||||||
{
|
{
|
||||||
@@ -123,8 +133,9 @@ blueNorm_impl(const EigenBase<Derived>& _vec)
|
|||||||
if(asml <= abig*relerr)
|
if(asml <= abig*relerr)
|
||||||
return abig;
|
return abig;
|
||||||
else
|
else
|
||||||
return abig * sqrt(RealScalar(1) + internal::abs2(asml/abig));
|
return abig * sqrt(RealScalar(1) + numext::abs2(asml/abig));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
|
/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
|
|||||||
|
|
||||||
typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
|
typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
|
||||||
EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
|
EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
|
||||||
|
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
|
||||||
|
|
||||||
inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
|
inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
|
||||||
inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
|
inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
|
||||||
@@ -206,7 +207,7 @@ DenseBase<Derived>::transpose()
|
|||||||
*
|
*
|
||||||
* \sa transposeInPlace(), adjoint() */
|
* \sa transposeInPlace(), adjoint() */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline const typename DenseBase<Derived>::ConstTransposeReturnType
|
inline typename DenseBase<Derived>::ConstTransposeReturnType
|
||||||
DenseBase<Derived>::transpose() const
|
DenseBase<Derived>::transpose() const
|
||||||
{
|
{
|
||||||
return ConstTransposeReturnType(derived());
|
return ConstTransposeReturnType(derived());
|
||||||
@@ -252,7 +253,7 @@ struct inplace_transpose_selector;
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
struct inplace_transpose_selector<MatrixType,true> { // square matrix
|
struct inplace_transpose_selector<MatrixType,true> { // square matrix
|
||||||
static void run(MatrixType& m) {
|
static void run(MatrixType& m) {
|
||||||
m.template triangularView<StrictlyUpper>().swap(m.transpose());
|
m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -260,7 +261,7 @@ template<typename MatrixType>
|
|||||||
struct inplace_transpose_selector<MatrixType,false> { // non square matrix
|
struct inplace_transpose_selector<MatrixType,false> { // non square matrix
|
||||||
static void run(MatrixType& m) {
|
static void run(MatrixType& m) {
|
||||||
if (m.rows()==m.cols())
|
if (m.rows()==m.cols())
|
||||||
m.template triangularView<StrictlyUpper>().swap(m.transpose());
|
m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
|
||||||
else
|
else
|
||||||
m = m.transpose().eval();
|
m = m.transpose().eval();
|
||||||
}
|
}
|
||||||
@@ -283,7 +284,8 @@ struct inplace_transpose_selector<MatrixType,false> { // non square matrix
|
|||||||
* Notice however that this method is only useful if you want to replace a matrix by its own transpose.
|
* Notice however that this method is only useful if you want to replace a matrix by its own transpose.
|
||||||
* If you just need the transpose of a matrix, use transpose().
|
* If you just need the transpose of a matrix, use transpose().
|
||||||
*
|
*
|
||||||
* \note if the matrix is not square, then \c *this must be a resizable matrix.
|
* \note if the matrix is not square, then \c *this must be a resizable matrix.
|
||||||
|
* This excludes (non-square) fixed-size matrices, block-expressions and maps.
|
||||||
*
|
*
|
||||||
* \sa transpose(), adjoint(), adjointInPlace() */
|
* \sa transpose(), adjoint(), adjointInPlace() */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -314,6 +316,7 @@ inline void DenseBase<Derived>::transposeInPlace()
|
|||||||
* If you just need the adjoint of a matrix, use adjoint().
|
* If you just need the adjoint of a matrix, use adjoint().
|
||||||
*
|
*
|
||||||
* \note if the matrix is not square, then \c *this must be a resizable matrix.
|
* \note if the matrix is not square, then \c *this must be a resizable matrix.
|
||||||
|
* This excludes (non-square) fixed-size matrices, block-expressions and maps.
|
||||||
*
|
*
|
||||||
* \sa transpose(), adjoint(), transposeInPlace() */
|
* \sa transpose(), adjoint(), transposeInPlace() */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
@@ -387,7 +390,7 @@ struct checkTransposeAliasing_impl
|
|||||||
eigen_assert((!check_transpose_aliasing_run_time_selector
|
eigen_assert((!check_transpose_aliasing_run_time_selector
|
||||||
<typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
|
<typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
|
||||||
::run(extract_data(dst), other))
|
::run(extract_data(dst), other))
|
||||||
&& "aliasing detected during tranposition, 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()");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,21 +278,21 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
|||||||
|
|
||||||
/** Efficient triangular matrix times vector/matrix product */
|
/** Efficient triangular matrix times vector/matrix product */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
TriangularProduct<Mode,true,MatrixType,false,OtherDerived, OtherDerived::IsVectorAtCompileTime>
|
TriangularProduct<Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
|
||||||
operator*(const MatrixBase<OtherDerived>& rhs) const
|
operator*(const MatrixBase<OtherDerived>& rhs) const
|
||||||
{
|
{
|
||||||
return TriangularProduct
|
return TriangularProduct
|
||||||
<Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
|
<Mode, true, MatrixType, false, OtherDerived, OtherDerived::ColsAtCompileTime==1>
|
||||||
(m_matrix, rhs.derived());
|
(m_matrix, rhs.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Efficient vector/matrix times triangular matrix product */
|
/** Efficient vector/matrix times triangular matrix product */
|
||||||
template<typename OtherDerived> friend
|
template<typename OtherDerived> friend
|
||||||
TriangularProduct<Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
|
TriangularProduct<Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
|
||||||
operator*(const MatrixBase<OtherDerived>& lhs, const TriangularView& rhs)
|
operator*(const MatrixBase<OtherDerived>& lhs, const TriangularView& rhs)
|
||||||
{
|
{
|
||||||
return TriangularProduct
|
return TriangularProduct
|
||||||
<Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
|
<Mode, false, OtherDerived, OtherDerived::RowsAtCompileTime==1, MatrixType, false>
|
||||||
(lhs.derived(),rhs.m_matrix);
|
(lhs.derived(),rhs.m_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,19 +380,19 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
|||||||
EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
||||||
{
|
{
|
||||||
setZero();
|
setZero();
|
||||||
return assignProduct(other,1);
|
return assignProduct(other.derived(),1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
EIGEN_STRONG_INLINE TriangularView& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
||||||
{
|
{
|
||||||
return assignProduct(other,1);
|
return assignProduct(other.derived(),1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
EIGEN_STRONG_INLINE TriangularView& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
||||||
{
|
{
|
||||||
return assignProduct(other,-1);
|
return assignProduct(other.derived(),-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -400,25 +400,34 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
|||||||
EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other)
|
||||||
{
|
{
|
||||||
setZero();
|
setZero();
|
||||||
return assignProduct(other,other.alpha());
|
return assignProduct(other.derived(),other.alpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ProductDerived>
|
template<typename ProductDerived>
|
||||||
EIGEN_STRONG_INLINE TriangularView& operator+=(const ScaledProduct<ProductDerived>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator+=(const ScaledProduct<ProductDerived>& other)
|
||||||
{
|
{
|
||||||
return assignProduct(other,other.alpha());
|
return assignProduct(other.derived(),other.alpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ProductDerived>
|
template<typename ProductDerived>
|
||||||
EIGEN_STRONG_INLINE TriangularView& operator-=(const ScaledProduct<ProductDerived>& other)
|
EIGEN_STRONG_INLINE TriangularView& operator-=(const ScaledProduct<ProductDerived>& other)
|
||||||
{
|
{
|
||||||
return assignProduct(other,-other.alpha());
|
return assignProduct(other.derived(),-other.alpha());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
EIGEN_STRONG_INLINE TriangularView& assignProduct(const ProductBase<ProductDerived, Lhs,Rhs>& prod, const Scalar& alpha);
|
EIGEN_STRONG_INLINE TriangularView& assignProduct(const ProductBase<ProductDerived, Lhs,Rhs>& prod, const Scalar& alpha);
|
||||||
|
|
||||||
|
template<int Mode, bool LhsIsTriangular,
|
||||||
|
typename Lhs, bool LhsIsVector,
|
||||||
|
typename Rhs, bool RhsIsVector>
|
||||||
|
EIGEN_STRONG_INLINE TriangularView& assignProduct(const TriangularProduct<Mode, LhsIsTriangular, Lhs, LhsIsVector, Rhs, RhsIsVector>& prod, const Scalar& alpha)
|
||||||
|
{
|
||||||
|
lazyAssign(alpha*prod.eval());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
MatrixTypeNested m_matrix;
|
MatrixTypeNested m_matrix;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
|
|||||||
MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
|
MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
|
||||||
Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
|
Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
|
||||||
Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
|
Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
|
||||||
TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
|
TraversalSize = Direction==Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime
|
||||||
};
|
};
|
||||||
#if EIGEN_GNUC_AT_LEAST(3,4)
|
#if EIGEN_GNUC_AT_LEAST(3,4)
|
||||||
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
|
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
|
||||||
@@ -58,7 +58,8 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
|
|||||||
typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
|
typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
|
||||||
#endif
|
#endif
|
||||||
enum {
|
enum {
|
||||||
CoeffReadCost = TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
|
CoeffReadCost = TraversalSize==Dynamic ? Dynamic
|
||||||
|
: TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -233,6 +234,28 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
Direction==Vertical ? 1 : m_matrix.rows(),
|
Direction==Vertical ? 1 : m_matrix.rows(),
|
||||||
Direction==Horizontal ? 1 : m_matrix.cols());
|
Direction==Horizontal ? 1 : m_matrix.cols());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename OtherDerived> struct OppositeExtendedType {
|
||||||
|
typedef Replicate<OtherDerived,
|
||||||
|
Direction==Horizontal ? 1 : ExpressionType::RowsAtCompileTime,
|
||||||
|
Direction==Vertical ? 1 : ExpressionType::ColsAtCompileTime> Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \internal
|
||||||
|
* Replicates a vector in the opposite direction to match the size of \c *this */
|
||||||
|
template<typename OtherDerived>
|
||||||
|
typename OppositeExtendedType<OtherDerived>::Type
|
||||||
|
extendedToOpposite(const DenseBase<OtherDerived>& other) const
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxColsAtCompileTime==1),
|
||||||
|
YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED)
|
||||||
|
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxRowsAtCompileTime==1),
|
||||||
|
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED)
|
||||||
|
return typename OppositeExtendedType<OtherDerived>::Type
|
||||||
|
(other.derived(),
|
||||||
|
Direction==Horizontal ? 1 : m_matrix.rows(),
|
||||||
|
Direction==Vertical ? 1 : m_matrix.cols());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -255,6 +278,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
|
|
||||||
/** \returns a row (or column) vector expression of the smallest coefficient
|
/** \returns a row (or column) vector expression of the smallest coefficient
|
||||||
* of each column (or row) of the referenced expression.
|
* of each column (or row) of the referenced expression.
|
||||||
|
*
|
||||||
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* Example: \include PartialRedux_minCoeff.cpp
|
* Example: \include PartialRedux_minCoeff.cpp
|
||||||
* Output: \verbinclude PartialRedux_minCoeff.out
|
* Output: \verbinclude PartialRedux_minCoeff.out
|
||||||
@@ -265,6 +290,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
|
|
||||||
/** \returns a row (or column) vector expression of the largest coefficient
|
/** \returns a row (or column) vector expression of the largest coefficient
|
||||||
* of each column (or row) of the referenced expression.
|
* of each column (or row) of the referenced expression.
|
||||||
|
*
|
||||||
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* Example: \include PartialRedux_maxCoeff.cpp
|
* Example: \include PartialRedux_maxCoeff.cpp
|
||||||
* Output: \verbinclude PartialRedux_maxCoeff.out
|
* Output: \verbinclude PartialRedux_maxCoeff.out
|
||||||
@@ -504,6 +531,23 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
|||||||
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
|
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
|
||||||
return m_matrix / extendedTo(other.derived());
|
return m_matrix / extendedTo(other.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \returns an expression where each column of row of the referenced matrix are normalized.
|
||||||
|
* The referenced matrix is \b not modified.
|
||||||
|
* \sa MatrixBase::normalized(), normalize()
|
||||||
|
*/
|
||||||
|
CwiseBinaryOp<internal::scalar_quotient_op<Scalar>,
|
||||||
|
const ExpressionTypeNestedCleaned,
|
||||||
|
const typename OppositeExtendedType<typename ReturnType<internal::member_norm,RealScalar>::Type>::Type>
|
||||||
|
normalized() const { return m_matrix.cwiseQuotient(extendedToOpposite(this->norm())); }
|
||||||
|
|
||||||
|
|
||||||
|
/** Normalize in-place each row or columns of the referenced matrix.
|
||||||
|
* \sa MatrixBase::normalize(), normalized()
|
||||||
|
*/
|
||||||
|
void normalize() {
|
||||||
|
m_matrix = this->normalized();
|
||||||
|
}
|
||||||
|
|
||||||
/////////// Geometry module ///////////
|
/////////// Geometry module ///////////
|
||||||
|
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ struct functor_traits<max_coeff_visitor<Scalar> > {
|
|||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
/** \returns the minimum of all coefficients of *this
|
/** \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||||
* and puts in *row and *col its location.
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
|
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
|
||||||
*/
|
*/
|
||||||
@@ -181,8 +181,8 @@ DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
|||||||
return minVisitor.res;
|
return minVisitor.res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the minimum of all coefficients of *this
|
/** \returns the minimum of all coefficients of *this and puts in *index its location.
|
||||||
* and puts in *index its location.
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff()
|
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff()
|
||||||
*/
|
*/
|
||||||
@@ -198,8 +198,8 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
|
|||||||
return minVisitor.res;
|
return minVisitor.res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the maximum of all coefficients of *this
|
/** \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||||
* and puts in *row and *col its location.
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
|
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
|
||||||
*/
|
*/
|
||||||
@@ -215,8 +215,8 @@ DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
|
|||||||
return maxVisitor.res;
|
return maxVisitor.res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \returns the maximum of all coefficients of *this
|
/** \returns the maximum of all coefficients of *this and puts in *index its location.
|
||||||
* and puts in *index its location.
|
* \warning the result is undefined if \c *this contains NaN.
|
||||||
*
|
*
|
||||||
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
|
* \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -173,6 +173,9 @@ template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const
|
|||||||
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return psub<Packet4f>(p4f_ZERO, a); }
|
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return psub<Packet4f>(p4f_ZERO, a); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return psub<Packet4i>(p4i_ZERO, a); }
|
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return psub<Packet4i>(p4i_ZERO, a); }
|
||||||
|
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_madd(a,b,p4f_ZERO); }
|
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_madd(a,b,p4f_ZERO); }
|
||||||
/* Commented out: it's actually slower than processing it scalar
|
/* Commented out: it's actually slower than processing it scalar
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a)
|
|||||||
template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
|
||||||
{
|
{
|
||||||
Packet4f v1, v2;
|
Packet4f v1, v2;
|
||||||
float32x2_t a_lo, a_hi;
|
|
||||||
|
|
||||||
// Get the real values of a | a1_re | a1_re | a2_re | a2_re |
|
// Get the real values of a | a1_re | a1_re | a2_re | a2_re |
|
||||||
v1 = vcombine_f32(vdup_lane_f32(vget_low_f32(a.v), 0), vdup_lane_f32(vget_high_f32(a.v), 0));
|
v1 = vcombine_f32(vdup_lane_f32(vget_low_f32(a.v), 0), vdup_lane_f32(vget_high_f32(a.v), 0));
|
||||||
@@ -81,9 +80,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, con
|
|||||||
// Conjugate v2
|
// Conjugate v2
|
||||||
v2 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(v2), p4ui_CONJ_XOR));
|
v2 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(v2), p4ui_CONJ_XOR));
|
||||||
// Swap real/imag elements in v2.
|
// Swap real/imag elements in v2.
|
||||||
a_lo = vrev64_f32(vget_low_f32(v2));
|
v2 = vrev64q_f32(v2);
|
||||||
a_hi = vrev64_f32(vget_high_f32(v2));
|
|
||||||
v2 = vcombine_f32(a_lo, a_hi);
|
|
||||||
// Add and return the result
|
// Add and return the result
|
||||||
return Packet2cf(vaddq_f32(v1, v2));
|
return Packet2cf(vaddq_f32(v1, v2));
|
||||||
}
|
}
|
||||||
@@ -113,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)
|
||||||
{
|
{
|
||||||
@@ -241,13 +238,10 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, con
|
|||||||
// TODO optimize it for AltiVec
|
// TODO optimize it for AltiVec
|
||||||
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
|
Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
|
||||||
Packet4f s, rev_s;
|
Packet4f s, rev_s;
|
||||||
float32x2_t a_lo, a_hi;
|
|
||||||
|
|
||||||
// this computes the norm
|
// this computes the norm
|
||||||
s = vmulq_f32(b.v, b.v);
|
s = vmulq_f32(b.v, b.v);
|
||||||
a_lo = vrev64_f32(vget_low_f32(s));
|
rev_s = vrev64q_f32(s);
|
||||||
a_hi = vrev64_f32(vget_high_f32(s));
|
|
||||||
rev_s = vcombine_f32(a_lo, a_hi);
|
|
||||||
|
|
||||||
return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s)));
|
return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,18 @@ typedef uint32x4_t Packet4ui;
|
|||||||
#define EIGEN_INIT_NEON_PACKET2(X, Y) {X, Y}
|
#define EIGEN_INIT_NEON_PACKET2(X, Y) {X, Y}
|
||||||
#define EIGEN_INIT_NEON_PACKET4(X, Y, Z, W) {X, Y, Z, W}
|
#define EIGEN_INIT_NEON_PACKET4(X, Y, Z, W) {X, Y, Z, W}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __pld
|
// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function
|
||||||
#define __pld(x) asm volatile ( " pld [%[addr]]\n" :: [addr] "r" (x) : "cc" );
|
// which available on LLVM and GCC (at least)
|
||||||
|
#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
|
||||||
|
#define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR);
|
||||||
|
#elif defined __pld
|
||||||
|
#define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR)
|
||||||
|
#elif !defined(__aarch64__)
|
||||||
|
#define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" );
|
||||||
|
#else
|
||||||
|
// by default no explicit prefetching
|
||||||
|
#define EIGEN_ARM_PREFETCH(ADDR)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<> struct packet_traits<float> : default_packet_traits
|
template<> struct packet_traits<float> : default_packet_traits
|
||||||
@@ -115,6 +124,9 @@ template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const
|
|||||||
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return vnegq_f32(a); }
|
template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return vnegq_f32(a); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return vnegq_s32(a); }
|
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return vnegq_s32(a); }
|
||||||
|
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vmulq_f32(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vmulq_f32(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b) { return vmulq_s32(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b) { return vmulq_s32(a,b); }
|
||||||
|
|
||||||
@@ -188,15 +200,15 @@ template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EI
|
|||||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||||
{
|
{
|
||||||
float32x2_t lo, hi;
|
float32x2_t lo, hi;
|
||||||
lo = vdup_n_f32(*from);
|
lo = vld1_dup_f32(from);
|
||||||
hi = vdup_n_f32(*(from+1));
|
hi = vld1_dup_f32(from+1);
|
||||||
return vcombine_f32(lo, hi);
|
return vcombine_f32(lo, hi);
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
||||||
{
|
{
|
||||||
int32x2_t lo, hi;
|
int32x2_t lo, hi;
|
||||||
lo = vdup_n_s32(*from);
|
lo = vld1_dup_s32(from);
|
||||||
hi = vdup_n_s32(*(from+1));
|
hi = vld1_dup_s32(from+1);
|
||||||
return vcombine_s32(lo, hi);
|
return vcombine_s32(lo, hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,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]; }
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a,
|
|||||||
template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_xor_ps(a.v,b.v)); }
|
template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_xor_ps(a.v,b.v)); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_andnot_ps(a.v,b.v)); }
|
template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_andnot_ps(a.v,b.v)); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>(&real_ref(*from))); }
|
template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>(&numext::real_ref(*from))); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>(&real_ref(*from))); }
|
template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>(&numext::real_ref(*from))); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
|
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
|
||||||
{
|
{
|
||||||
@@ -104,8 +104,8 @@ template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<flo
|
|||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
|
template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore(&real_ref(*to), from.v); }
|
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore(&numext::real_ref(*to), from.v); }
|
||||||
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&real_ref(*to), from.v); }
|
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), from.v); }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
|
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
|
|||||||
|
|
||||||
Packet4i emm0;
|
Packet4i emm0;
|
||||||
|
|
||||||
Packet4f invalid_mask = _mm_cmplt_ps(x, _mm_setzero_ps());
|
Packet4f invalid_mask = _mm_cmpnge_ps(x, _mm_setzero_ps()); // not greater equal is true if x is NaN
|
||||||
Packet4f iszero_mask = _mm_cmpeq_ps(x, _mm_setzero_ps());
|
Packet4f iszero_mask = _mm_cmpeq_ps(x, _mm_setzero_ps());
|
||||||
|
|
||||||
x = pmax(x, p4f_min_norm_pos); /* cut off denormalized stuff */
|
x = pmax(x, p4f_min_norm_pos); /* cut off denormalized stuff */
|
||||||
@@ -166,7 +166,7 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
|
|||||||
emm0 = _mm_cvttps_epi32(fx);
|
emm0 = _mm_cvttps_epi32(fx);
|
||||||
emm0 = _mm_add_epi32(emm0, p4i_0x7f);
|
emm0 = _mm_add_epi32(emm0, p4i_0x7f);
|
||||||
emm0 = _mm_slli_epi32(emm0, 23);
|
emm0 = _mm_slli_epi32(emm0, 23);
|
||||||
return pmul(y, _mm_castsi128_ps(emm0));
|
return pmax(pmul(y, Packet4f(_mm_castsi128_ps(emm0))), _x);
|
||||||
}
|
}
|
||||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||||
Packet2d pexp<Packet2d>(const Packet2d& _x)
|
Packet2d pexp<Packet2d>(const Packet2d& _x)
|
||||||
@@ -239,7 +239,7 @@ Packet2d pexp<Packet2d>(const Packet2d& _x)
|
|||||||
emm0 = _mm_add_epi32(emm0, p4i_1023_0);
|
emm0 = _mm_add_epi32(emm0, p4i_1023_0);
|
||||||
emm0 = _mm_slli_epi32(emm0, 20);
|
emm0 = _mm_slli_epi32(emm0, 20);
|
||||||
emm0 = _mm_shuffle_epi32(emm0, _MM_SHUFFLE(1,2,0,3));
|
emm0 = _mm_shuffle_epi32(emm0, _MM_SHUFFLE(1,2,0,3));
|
||||||
return pmul(x, _mm_castsi128_pd(emm0));
|
return pmax(pmul(x, Packet2d(_mm_castsi128_pd(emm0))), _x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* evaluation of 4 sines at onces, using SSE2 intrinsics.
|
/* evaluation of 4 sines at onces, using SSE2 intrinsics.
|
||||||
@@ -442,21 +442,32 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
|
|||||||
return _mm_xor_ps(y, sign_bit);
|
return _mm_xor_ps(y, sign_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EIGEN_FAST_MATH
|
||||||
|
|
||||||
// This is based on Quake3's fast inverse square root.
|
// This is based on Quake3's fast inverse square root.
|
||||||
// For detail see here: http://www.beyond3d.com/content/articles/8/
|
// For detail see here: http://www.beyond3d.com/content/articles/8/
|
||||||
|
// It lacks 1 (or 2 bits in some rare cases) of precision, and does not handle negative, +inf, or denormalized numbers correctly.
|
||||||
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
|
||||||
Packet4f psqrt<Packet4f>(const Packet4f& _x)
|
Packet4f psqrt<Packet4f>(const Packet4f& _x)
|
||||||
{
|
{
|
||||||
Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
|
Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
|
||||||
|
|
||||||
/* select only the inverse sqrt of non-zero inputs */
|
/* select only the inverse sqrt of non-zero inputs */
|
||||||
Packet4f non_zero_mask = _mm_cmpgt_ps(_x, pset1<Packet4f>(std::numeric_limits<float>::epsilon()));
|
Packet4f non_zero_mask = _mm_cmpge_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)()));
|
||||||
Packet4f x = _mm_and_ps(non_zero_mask, _mm_rsqrt_ps(_x));
|
Packet4f x = _mm_and_ps(non_zero_mask, _mm_rsqrt_ps(_x));
|
||||||
|
|
||||||
x = pmul(x, psub(pset1<Packet4f>(1.5f), pmul(half, pmul(x,x))));
|
x = pmul(x, psub(pset1<Packet4f>(1.5f), pmul(half, pmul(x,x))));
|
||||||
return pmul(_x,x);
|
return pmul(_x,x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4f psqrt<Packet4f>(const Packet4f& x) { return _mm_sqrt_ps(x); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet2d psqrt<Packet2d>(const Packet2d& x) { return _mm_sqrt_pd(x); }
|
||||||
|
|
||||||
} // end namespace internal
|
} // end namespace internal
|
||||||
|
|
||||||
} // end namespace Eigen
|
} // end namespace Eigen
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ template<> struct packet_traits<double> : default_packet_traits
|
|||||||
size=2,
|
size=2,
|
||||||
|
|
||||||
HasDiv = 1,
|
HasDiv = 1,
|
||||||
HasExp = 1
|
HasExp = 1,
|
||||||
|
HasSqrt = 1
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
template<> struct packet_traits<int> : default_packet_traits
|
template<> struct packet_traits<int> : default_packet_traits
|
||||||
@@ -141,6 +142,10 @@ template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a)
|
|||||||
return psub(_mm_setr_epi32(0,0,0,0), a);
|
return psub(_mm_setr_epi32(0,0,0,0), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet2d pconj(const Packet2d& a) { return a; }
|
||||||
|
template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_mul_ps(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_mul_ps(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d pmul<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_mul_pd(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet2d pmul<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_mul_pd(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b)
|
template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b)
|
||||||
@@ -173,18 +178,26 @@ template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const
|
|||||||
template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_min_pd(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_min_pd(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b)
|
template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b)
|
||||||
{
|
{
|
||||||
|
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||||
|
return _mm_min_epi32(a,b);
|
||||||
|
#else
|
||||||
// after some bench, this version *is* faster than a scalar implementation
|
// after some bench, this version *is* faster than a scalar implementation
|
||||||
Packet4i mask = _mm_cmplt_epi32(a,b);
|
Packet4i mask = _mm_cmplt_epi32(a,b);
|
||||||
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_max_ps(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_max_ps(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_max_pd(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_max_pd(a,b); }
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b)
|
template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b)
|
||||||
{
|
{
|
||||||
|
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||||
|
return _mm_max_epi32(a,b);
|
||||||
|
#else
|
||||||
// after some bench, this version *is* faster than a scalar implementation
|
// after some bench, this version *is* faster than a scalar implementation
|
||||||
Packet4i mask = _mm_cmpgt_epi32(a,b);
|
Packet4i mask = _mm_cmpgt_epi32(a,b);
|
||||||
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_and_ps(a,b); }
|
template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_and_ps(a,b); }
|
||||||
@@ -495,8 +508,8 @@ template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
|
|||||||
// for GCC (eg., it does not like using std::min after the pstore !!)
|
// for GCC (eg., it does not like using std::min after the pstore !!)
|
||||||
EIGEN_ALIGN16 int aux[4];
|
EIGEN_ALIGN16 int aux[4];
|
||||||
pstore(aux, a);
|
pstore(aux, a);
|
||||||
register int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
|
int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
|
||||||
register int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
|
int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
|
||||||
return aux0<aux2 ? aux0 : aux2;
|
return aux0<aux2 ? aux0 : aux2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,8 +529,8 @@ template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
|||||||
// for GCC (eg., it does not like using std::min after the pstore !!)
|
// for GCC (eg., it does not like using std::min after the pstore !!)
|
||||||
EIGEN_ALIGN16 int aux[4];
|
EIGEN_ALIGN16 int aux[4];
|
||||||
pstore(aux, a);
|
pstore(aux, a);
|
||||||
register int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
|
int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
|
||||||
register int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
|
int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
|
||||||
return aux0>aux2 ? aux0 : aux2;
|
return aux0>aux2 ? aux0 : aux2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
|
|||||||
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
|
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
|
||||||
|
|
||||||
CoeffReadCost = InnerSize == Dynamic ? Dynamic
|
CoeffReadCost = InnerSize == Dynamic ? Dynamic
|
||||||
|
: InnerSize == 0 ? 0
|
||||||
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
||||||
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
|
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
|
||||||
|
|
||||||
@@ -133,7 +134,7 @@ class CoeffBasedProduct
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
||||||
Unroll ? 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;
|
||||||
@@ -150,7 +151,7 @@ class CoeffBasedProduct
|
|||||||
{
|
{
|
||||||
// we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
|
// we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
|
||||||
// We still allow to mix T and complex<T>.
|
// We still allow to mix T and complex<T>.
|
||||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
|
EIGEN_STATIC_ASSERT((internal::scalar_product_traits<typename Lhs::RealScalar, typename Rhs::RealScalar>::Defined),
|
||||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||||
eigen_assert(lhs.cols() == rhs.rows()
|
eigen_assert(lhs.cols() == rhs.rows()
|
||||||
&& "invalid matrix product"
|
&& "invalid matrix product"
|
||||||
@@ -184,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-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;
|
||||||
@@ -242,12 +243,12 @@ 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>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
|
struct product_coeff_impl<DefaultTraversal, 1, 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)
|
||||||
@@ -256,16 +257,23 @@ struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
|
struct product_coeff_impl<DefaultTraversal, 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 = RetScalar(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar>
|
struct product_coeff_impl<DefaultTraversal, Dynamic, 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)
|
||||||
{
|
{
|
||||||
eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
res = (lhs.row(row).transpose().cwiseProduct( rhs.col(col) )).sum();
|
||||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
|
||||||
for(Index i = 1; i < lhs.cols(); ++i)
|
|
||||||
res += lhs.coeff(row, i) * rhs.coeff(i, col);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -295,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>
|
||||||
{
|
{
|
||||||
@@ -304,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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -373,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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -384,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)
|
||||||
@@ -399,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)
|
||||||
@@ -408,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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -427,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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1128,6 +1128,8 @@ EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, Pack1, Pack2, StorageOrder,
|
|||||||
enum { PacketSize = packet_traits<Scalar>::size };
|
enum { PacketSize = packet_traits<Scalar>::size };
|
||||||
|
|
||||||
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS");
|
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS");
|
||||||
|
EIGEN_UNUSED_VARIABLE(stride)
|
||||||
|
EIGEN_UNUSED_VARIABLE(offset)
|
||||||
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
||||||
eigen_assert( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) );
|
eigen_assert( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) );
|
||||||
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
||||||
@@ -1215,6 +1217,8 @@ EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, ColMajor, Conjugate, Pan
|
|||||||
::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
|
::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
|
||||||
{
|
{
|
||||||
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS COLMAJOR");
|
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS COLMAJOR");
|
||||||
|
EIGEN_UNUSED_VARIABLE(stride)
|
||||||
|
EIGEN_UNUSED_VARIABLE(offset)
|
||||||
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
||||||
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
||||||
Index packet_cols = (cols/nr) * nr;
|
Index packet_cols = (cols/nr) * nr;
|
||||||
@@ -1266,6 +1270,8 @@ EIGEN_DONT_INLINE void gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, Pan
|
|||||||
::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
|
::operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride, Index offset)
|
||||||
{
|
{
|
||||||
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS ROWMAJOR");
|
EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS ROWMAJOR");
|
||||||
|
EIGEN_UNUSED_VARIABLE(stride)
|
||||||
|
EIGEN_UNUSED_VARIABLE(offset)
|
||||||
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
|
||||||
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
|
||||||
Index packet_cols = (cols/nr) * nr;
|
Index packet_cols = (cols/nr) * nr;
|
||||||
|
|||||||
@@ -238,7 +238,6 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
|
|||||||
{
|
{
|
||||||
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
|
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
|
||||||
{
|
{
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
|
|
||||||
typedef typename internal::remove_all<typename ProductType::LhsNested>::type Lhs;
|
typedef typename internal::remove_all<typename ProductType::LhsNested>::type Lhs;
|
||||||
|
|||||||
@@ -52,11 +52,7 @@ EIGEN_DONT_INLINE static void run(
|
|||||||
Index rows, Index cols,
|
Index rows, Index cols,
|
||||||
const LhsScalar* lhs, Index lhsStride,
|
const LhsScalar* lhs, Index lhsStride,
|
||||||
const RhsScalar* rhs, Index rhsIncr,
|
const RhsScalar* rhs, Index rhsIncr,
|
||||||
ResScalar* res, Index
|
ResScalar* res, Index resIncr, RhsScalar alpha);
|
||||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
|
||||||
resIncr
|
|
||||||
#endif
|
|
||||||
, RhsScalar alpha);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs, int Version>
|
template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs, int Version>
|
||||||
@@ -64,12 +60,9 @@ EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,ColMajor,Co
|
|||||||
Index rows, Index cols,
|
Index rows, Index cols,
|
||||||
const LhsScalar* lhs, Index lhsStride,
|
const LhsScalar* lhs, Index lhsStride,
|
||||||
const RhsScalar* rhs, Index rhsIncr,
|
const RhsScalar* rhs, Index rhsIncr,
|
||||||
ResScalar* res, Index
|
ResScalar* res, Index resIncr, RhsScalar alpha)
|
||||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
|
||||||
resIncr
|
|
||||||
#endif
|
|
||||||
, RhsScalar alpha)
|
|
||||||
{
|
{
|
||||||
|
EIGEN_UNUSED_VARIABLE(resIncr)
|
||||||
eigen_internal_assert(resIncr==1);
|
eigen_internal_assert(resIncr==1);
|
||||||
#ifdef _EIGEN_ACCUMULATE_PACKETS
|
#ifdef _EIGEN_ACCUMULATE_PACKETS
|
||||||
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
||||||
@@ -86,7 +79,7 @@ EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,ColMajor,Co
|
|||||||
conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
|
conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
|
||||||
conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
|
conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
|
||||||
if(ConjugateRhs)
|
if(ConjugateRhs)
|
||||||
alpha = conj(alpha);
|
alpha = numext::conj(alpha);
|
||||||
|
|
||||||
enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
|
enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
|
||||||
const Index columnsAtOnce = 4;
|
const Index columnsAtOnce = 4;
|
||||||
@@ -265,7 +258,7 @@ EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,ColMajor,Co
|
|||||||
// process aligned result's coeffs
|
// process aligned result's coeffs
|
||||||
if ((size_t(lhs0+alignedStart)%sizeof(LhsPacket))==0)
|
if ((size_t(lhs0+alignedStart)%sizeof(LhsPacket))==0)
|
||||||
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
||||||
pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
|
pstore(&res[i], pcj.pmadd(pload<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
|
||||||
else
|
else
|
||||||
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
||||||
pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
|
pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ struct symm_pack_lhs
|
|||||||
for(Index k=i; k<i+BlockRows; k++)
|
for(Index k=i; k<i+BlockRows; k++)
|
||||||
{
|
{
|
||||||
for(Index w=0; w<h; w++)
|
for(Index w=0; w<h; w++)
|
||||||
blockA[count++] = conj(lhs(k, i+w)); // transposed
|
blockA[count++] = numext::conj(lhs(k, i+w)); // transposed
|
||||||
|
|
||||||
blockA[count++] = real(lhs(k,k)); // real (diagonal)
|
blockA[count++] = numext::real(lhs(k,k)); // real (diagonal)
|
||||||
|
|
||||||
for(Index w=h+1; w<BlockRows; w++)
|
for(Index w=h+1; w<BlockRows; w++)
|
||||||
blockA[count++] = lhs(i+w, k); // normal
|
blockA[count++] = lhs(i+w, k); // normal
|
||||||
@@ -41,7 +41,7 @@ struct symm_pack_lhs
|
|||||||
// transposed copy
|
// transposed copy
|
||||||
for(Index k=i+BlockRows; k<cols; k++)
|
for(Index k=i+BlockRows; k<cols; k++)
|
||||||
for(Index w=0; w<BlockRows; w++)
|
for(Index w=0; w<BlockRows; w++)
|
||||||
blockA[count++] = conj(lhs(k, i+w)); // transposed
|
blockA[count++] = numext::conj(lhs(k, i+w)); // transposed
|
||||||
}
|
}
|
||||||
void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows)
|
void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows)
|
||||||
{
|
{
|
||||||
@@ -65,10 +65,10 @@ struct symm_pack_lhs
|
|||||||
for(Index k=0; k<i; k++)
|
for(Index k=0; k<i; k++)
|
||||||
blockA[count++] = lhs(i, k); // normal
|
blockA[count++] = lhs(i, k); // normal
|
||||||
|
|
||||||
blockA[count++] = real(lhs(i, i)); // real (diagonal)
|
blockA[count++] = numext::real(lhs(i, i)); // real (diagonal)
|
||||||
|
|
||||||
for(Index k=i+1; k<cols; k++)
|
for(Index k=i+1; k<cols; k++)
|
||||||
blockA[count++] = conj(lhs(k, i)); // transposed
|
blockA[count++] = numext::conj(lhs(k, i)); // transposed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -107,12 +107,12 @@ struct symm_pack_rhs
|
|||||||
// transpose
|
// transpose
|
||||||
for(Index k=k2; k<j2; k++)
|
for(Index k=k2; k<j2; k++)
|
||||||
{
|
{
|
||||||
blockB[count+0] = conj(rhs(j2+0,k));
|
blockB[count+0] = numext::conj(rhs(j2+0,k));
|
||||||
blockB[count+1] = conj(rhs(j2+1,k));
|
blockB[count+1] = numext::conj(rhs(j2+1,k));
|
||||||
if (nr==4)
|
if (nr==4)
|
||||||
{
|
{
|
||||||
blockB[count+2] = conj(rhs(j2+2,k));
|
blockB[count+2] = numext::conj(rhs(j2+2,k));
|
||||||
blockB[count+3] = conj(rhs(j2+3,k));
|
blockB[count+3] = numext::conj(rhs(j2+3,k));
|
||||||
}
|
}
|
||||||
count += nr;
|
count += nr;
|
||||||
}
|
}
|
||||||
@@ -124,11 +124,11 @@ struct symm_pack_rhs
|
|||||||
for (Index w=0 ; w<h; ++w)
|
for (Index w=0 ; w<h; ++w)
|
||||||
blockB[count+w] = rhs(k,j2+w);
|
blockB[count+w] = rhs(k,j2+w);
|
||||||
|
|
||||||
blockB[count+h] = real(rhs(k,k));
|
blockB[count+h] = numext::real(rhs(k,k));
|
||||||
|
|
||||||
// transpose
|
// transpose
|
||||||
for (Index w=h+1 ; w<nr; ++w)
|
for (Index w=h+1 ; w<nr; ++w)
|
||||||
blockB[count+w] = conj(rhs(j2+w,k));
|
blockB[count+w] = numext::conj(rhs(j2+w,k));
|
||||||
count += nr;
|
count += nr;
|
||||||
++h;
|
++h;
|
||||||
}
|
}
|
||||||
@@ -151,12 +151,12 @@ struct symm_pack_rhs
|
|||||||
{
|
{
|
||||||
for(Index k=k2; k<end_k; k++)
|
for(Index k=k2; k<end_k; k++)
|
||||||
{
|
{
|
||||||
blockB[count+0] = conj(rhs(j2+0,k));
|
blockB[count+0] = numext::conj(rhs(j2+0,k));
|
||||||
blockB[count+1] = conj(rhs(j2+1,k));
|
blockB[count+1] = numext::conj(rhs(j2+1,k));
|
||||||
if (nr==4)
|
if (nr==4)
|
||||||
{
|
{
|
||||||
blockB[count+2] = conj(rhs(j2+2,k));
|
blockB[count+2] = numext::conj(rhs(j2+2,k));
|
||||||
blockB[count+3] = conj(rhs(j2+3,k));
|
blockB[count+3] = numext::conj(rhs(j2+3,k));
|
||||||
}
|
}
|
||||||
count += nr;
|
count += nr;
|
||||||
}
|
}
|
||||||
@@ -169,13 +169,13 @@ struct symm_pack_rhs
|
|||||||
Index half = (std::min)(end_k,j2);
|
Index half = (std::min)(end_k,j2);
|
||||||
for(Index k=k2; k<half; k++)
|
for(Index k=k2; k<half; k++)
|
||||||
{
|
{
|
||||||
blockB[count] = conj(rhs(j2,k));
|
blockB[count] = numext::conj(rhs(j2,k));
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(half==j2 && half<k2+rows)
|
if(half==j2 && half<k2+rows)
|
||||||
{
|
{
|
||||||
blockB[count] = real(rhs(j2,j2));
|
blockB[count] = numext::real(rhs(j2,j2));
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
Scalar alpha)
|
Scalar alpha)
|
||||||
{
|
{
|
||||||
typedef typename packet_traits<Scalar>::type Packet;
|
typedef typename packet_traits<Scalar>::type Packet;
|
||||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
|
||||||
const Index PacketSize = sizeof(Packet)/sizeof(Scalar);
|
const Index PacketSize = sizeof(Packet)/sizeof(Scalar);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -60,7 +59,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> pcj0;
|
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> pcj0;
|
||||||
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> pcj1;
|
conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> pcj1;
|
||||||
|
|
||||||
Scalar cjAlpha = ConjugateRhs ? conj(alpha) : alpha;
|
Scalar cjAlpha = ConjugateRhs ? numext::conj(alpha) : alpha;
|
||||||
|
|
||||||
// FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
|
// FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
|
||||||
// if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
|
// if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
|
||||||
@@ -80,8 +79,8 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
for (Index j=FirstTriangular ? bound : 0;
|
for (Index j=FirstTriangular ? bound : 0;
|
||||||
j<(FirstTriangular ? size : bound);j+=2)
|
j<(FirstTriangular ? size : bound);j+=2)
|
||||||
{
|
{
|
||||||
register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
|
const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
|
||||||
register const Scalar* EIGEN_RESTRICT A1 = lhs + (j+1)*lhsStride;
|
const Scalar* EIGEN_RESTRICT A1 = lhs + (j+1)*lhsStride;
|
||||||
|
|
||||||
Scalar t0 = cjAlpha * rhs[j];
|
Scalar t0 = cjAlpha * rhs[j];
|
||||||
Packet ptmp0 = pset1<Packet>(t0);
|
Packet ptmp0 = pset1<Packet>(t0);
|
||||||
@@ -99,8 +98,8 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
|
size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
|
||||||
|
|
||||||
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
|
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
|
||||||
res[j] += cjd.pmul(internal::real(A0[j]), t0);
|
res[j] += cjd.pmul(numext::real(A0[j]), t0);
|
||||||
res[j+1] += cjd.pmul(internal::real(A1[j+1]), t1);
|
res[j+1] += cjd.pmul(numext::real(A1[j+1]), t1);
|
||||||
if(FirstTriangular)
|
if(FirstTriangular)
|
||||||
{
|
{
|
||||||
res[j] += cj0.pmul(A1[j], t1);
|
res[j] += cj0.pmul(A1[j], t1);
|
||||||
@@ -115,8 +114,8 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
for (size_t i=starti; i<alignedStart; ++i)
|
for (size_t i=starti; i<alignedStart; ++i)
|
||||||
{
|
{
|
||||||
res[i] += t0 * A0[i] + t1 * A1[i];
|
res[i] += t0 * A0[i] + t1 * A1[i];
|
||||||
t2 += conj(A0[i]) * rhs[i];
|
t2 += numext::conj(A0[i]) * rhs[i];
|
||||||
t3 += conj(A1[i]) * rhs[i];
|
t3 += numext::conj(A1[i]) * rhs[i];
|
||||||
}
|
}
|
||||||
// Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up)
|
// Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up)
|
||||||
// gcc 4.2 does this optimization automatically.
|
// gcc 4.2 does this optimization automatically.
|
||||||
@@ -148,12 +147,12 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||||||
}
|
}
|
||||||
for (Index j=FirstTriangular ? 0 : bound;j<(FirstTriangular ? bound : size);j++)
|
for (Index j=FirstTriangular ? 0 : bound;j<(FirstTriangular ? bound : size);j++)
|
||||||
{
|
{
|
||||||
register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
|
const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
|
||||||
|
|
||||||
Scalar t1 = cjAlpha * rhs[j];
|
Scalar t1 = cjAlpha * rhs[j];
|
||||||
Scalar t2(0);
|
Scalar t2(0);
|
||||||
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
|
// TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
|
||||||
res[j] += cjd.pmul(internal::real(A0[j]), t1);
|
res[j] += cjd.pmul(numext::real(A0[j]), t1);
|
||||||
for (Index i=FirstTriangular ? 0 : j+1; i<(FirstTriangular ? j : size); i++)
|
for (Index i=FirstTriangular ? 0 : j+1; i<(FirstTriangular ? j : size); i++)
|
||||||
{
|
{
|
||||||
res[i] += cj0.pmul(A0[i], t1);
|
res[i] += cj0.pmul(A0[i], t1);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,false>
|
|||||||
template<typename MatrixType, unsigned int UpLo>
|
template<typename MatrixType, unsigned int UpLo>
|
||||||
template<typename DerivedU>
|
template<typename DerivedU>
|
||||||
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
|
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
|
||||||
::rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
|
::rankUpdate(const MatrixBase<DerivedU>& u, const Scalar& alpha)
|
||||||
{
|
{
|
||||||
selfadjoint_product_selector<MatrixType,DerivedU,UpLo>::run(_expression().const_cast_derived(), u.derived(), alpha);
|
selfadjoint_product_selector<MatrixType,DerivedU,UpLo>::run(_expression().const_cast_derived(), u.derived(), alpha);
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Lower>
|
|||||||
for (Index i=0; i<size; ++i)
|
for (Index i=0; i<size; ++i)
|
||||||
{
|
{
|
||||||
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+i, size-i) +=
|
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+i, size-i) +=
|
||||||
(conj(alpha) * conj(u.coeff(i))) * v.tail(size-i)
|
(numext::conj(alpha) * numext::conj(u.coeff(i))) * v.tail(size-i)
|
||||||
+ (alpha * conj(v.coeff(i))) * u.tail(size-i);
|
+ (alpha * numext::conj(v.coeff(i))) * u.tail(size-i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -44,8 +44,8 @@ struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Upper>
|
|||||||
const Index size = u.size();
|
const Index size = u.size();
|
||||||
for (Index i=0; i<size; ++i)
|
for (Index i=0; i<size; ++i)
|
||||||
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i, i+1) +=
|
Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i, i+1) +=
|
||||||
(conj(alpha) * conj(u.coeff(i))) * v.head(i+1)
|
(numext::conj(alpha) * numext::conj(u.coeff(i))) * v.head(i+1)
|
||||||
+ (alpha * conj(v.coeff(i))) * u.head(i+1);
|
+ (alpha * numext::conj(v.coeff(i))) * u.head(i+1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ template<bool Cond, typename T> struct conj_expr_if
|
|||||||
template<typename MatrixType, unsigned int UpLo>
|
template<typename MatrixType, unsigned int UpLo>
|
||||||
template<typename DerivedU, typename DerivedV>
|
template<typename DerivedU, typename DerivedV>
|
||||||
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
|
SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
|
||||||
::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha)
|
::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, const Scalar& alpha)
|
||||||
{
|
{
|
||||||
typedef internal::blas_traits<DerivedU> UBlasTraits;
|
typedef internal::blas_traits<DerivedU> UBlasTraits;
|
||||||
typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
|
typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
|
||||||
@@ -75,9 +75,9 @@ SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
|
|||||||
|
|
||||||
enum { IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
|
enum { IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
|
||||||
Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u.derived())
|
Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u.derived())
|
||||||
* internal::conj(VBlasTraits::extractScalarFactor(v.derived()));
|
* numext::conj(VBlasTraits::extractScalarFactor(v.derived()));
|
||||||
if (IsRowMajor)
|
if (IsRowMajor)
|
||||||
actualAlpha = internal::conj(actualAlpha);
|
actualAlpha = numext::conj(actualAlpha);
|
||||||
|
|
||||||
internal::selfadjoint_rank2_update_selector<Scalar, Index,
|
internal::selfadjoint_rank2_update_selector<Scalar, Index,
|
||||||
typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::type>::type,
|
typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::type>::type,
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ template<> struct trmv_selector<ColMajor>
|
|||||||
|
|
||||||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
|
||||||
|
|
||||||
bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
|
bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
|
||||||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
|
||||||
|
|
||||||
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
|
||||||
@@ -256,7 +256,7 @@ template<> struct trmv_selector<ColMajor>
|
|||||||
if(!evalToDest)
|
if(!evalToDest)
|
||||||
{
|
{
|
||||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
int size = dest.size();
|
Index size = dest.size();
|
||||||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
if(!alphaIsCompatible)
|
if(!alphaIsCompatible)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ template<bool Conjugate> struct conj_if;
|
|||||||
|
|
||||||
template<> struct conj_if<true> {
|
template<> struct conj_if<true> {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T operator()(const T& x) { return conj(x); }
|
inline T operator()(const T& x) { return numext::conj(x); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T pconj(const T& x) { return internal::pconj(x); }
|
inline T pconj(const T& x) { return internal::pconj(x); }
|
||||||
};
|
};
|
||||||
@@ -67,7 +67,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
|
|||||||
{ return c + pmul(x,y); }
|
{ return c + pmul(x,y); }
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||||
{ return Scalar(real(x)*real(y) + imag(x)*imag(y), imag(x)*real(y) - real(x)*imag(y)); }
|
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::imag(x)*numext::real(y) - numext::real(x)*numext::imag(y)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
|
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
|
||||||
@@ -77,7 +77,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
|
|||||||
{ return c + pmul(x,y); }
|
{ return c + pmul(x,y); }
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||||
{ return Scalar(real(x)*real(y) + imag(x)*imag(y), real(x)*imag(y) - imag(x)*real(y)); }
|
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
|
template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
|
||||||
@@ -87,7 +87,7 @@ template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::
|
|||||||
{ return c + pmul(x,y); }
|
{ return c + pmul(x,y); }
|
||||||
|
|
||||||
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
|
||||||
{ return Scalar(real(x)*real(y) - imag(x)*imag(y), - real(x)*imag(y) - imag(x)*real(y)); }
|
{ return Scalar(numext::real(x)*numext::real(y) - numext::imag(x)*numext::imag(y), - numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
|
template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
|
||||||
@@ -113,7 +113,7 @@ template<typename From,typename To> struct get_factor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Scalar> struct get_factor<Scalar,typename NumTraits<Scalar>::Real> {
|
template<typename Scalar> struct get_factor<Scalar,typename NumTraits<Scalar>::Real> {
|
||||||
static EIGEN_STRONG_INLINE typename NumTraits<Scalar>::Real run(const Scalar& x) { return real(x); }
|
static EIGEN_STRONG_INLINE typename NumTraits<Scalar>::Real run(const Scalar& x) { return numext::real(x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lightweight helper class to access matrix coefficients.
|
// Lightweight helper class to access matrix coefficients.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -54,8 +54,25 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined EIGEN_USE_MKL
|
#if defined EIGEN_USE_MKL
|
||||||
|
# include <mkl.h>
|
||||||
|
/*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/
|
||||||
|
# ifndef INTEL_MKL_VERSION
|
||||||
|
# undef EIGEN_USE_MKL /* INTEL_MKL_VERSION is not even defined on older versions */
|
||||||
|
# elif INTEL_MKL_VERSION < 100305 /* the intel-mkl-103-release-notes say this was when the lapacke.h interface was added*/
|
||||||
|
# undef EIGEN_USE_MKL
|
||||||
|
# endif
|
||||||
|
# ifndef EIGEN_USE_MKL
|
||||||
|
/*If the MKL version is too old, undef everything*/
|
||||||
|
# undef EIGEN_USE_MKL_ALL
|
||||||
|
# undef EIGEN_USE_BLAS
|
||||||
|
# undef EIGEN_USE_LAPACKE
|
||||||
|
# undef EIGEN_USE_MKL_VML
|
||||||
|
# undef EIGEN_USE_LAPACKE_STRICT
|
||||||
|
# undef EIGEN_USE_LAPACKE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <mkl.h>
|
#if defined EIGEN_USE_MKL
|
||||||
#include <mkl_lapacke.h>
|
#include <mkl_lapacke.h>
|
||||||
#define EIGEN_MKL_VML_THRESHOLD 128
|
#define EIGEN_MKL_VML_THRESHOLD 128
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
#define EIGEN_MACROS_H
|
#define EIGEN_MACROS_H
|
||||||
|
|
||||||
#define EIGEN_WORLD_VERSION 3
|
#define EIGEN_WORLD_VERSION 3
|
||||||
#define EIGEN_MAJOR_VERSION 1
|
#define EIGEN_MAJOR_VERSION 2
|
||||||
#define EIGEN_MINOR_VERSION 91
|
#define EIGEN_MINOR_VERSION 5
|
||||||
|
|
||||||
#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 && \
|
||||||
@@ -96,6 +96,13 @@
|
|||||||
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
|
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Cross compiler wrapper around LLVM's __has_builtin
|
||||||
|
#ifdef __has_builtin
|
||||||
|
# define EIGEN_HAS_BUILTIN(x) __has_builtin(x)
|
||||||
|
#else
|
||||||
|
# define EIGEN_HAS_BUILTIN(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Allows to disable some optimizations which might affect the accuracy of the result.
|
/** Allows to disable some optimizations which might affect the accuracy of the result.
|
||||||
* Such optimization are enabled by default, and set EIGEN_FAST_MATH to 0 to disable them.
|
* Such optimization are enabled by default, and set EIGEN_FAST_MATH to 0 to disable them.
|
||||||
* They currently include:
|
* They currently include:
|
||||||
@@ -238,12 +245,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Suppresses 'unused variable' warnings.
|
// Suppresses 'unused variable' warnings.
|
||||||
#define EIGEN_UNUSED_VARIABLE(var) (void)var;
|
namespace Eigen {
|
||||||
|
namespace internal {
|
||||||
|
template<typename T> void ignore_unused_variable(const T&) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define EIGEN_UNUSED_VARIABLE(var) Eigen::internal::ignore_unused_variable(var);
|
||||||
|
|
||||||
#if !defined(EIGEN_ASM_COMMENT) && (defined __GNUC__)
|
#if !defined(EIGEN_ASM_COMMENT)
|
||||||
#define EIGEN_ASM_COMMENT(X) asm("#" X)
|
#if (defined __GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
|
||||||
#else
|
#define EIGEN_ASM_COMMENT(X) __asm__("#" X)
|
||||||
#define EIGEN_ASM_COMMENT(X)
|
#else
|
||||||
|
#define EIGEN_ASM_COMMENT(X)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* EIGEN_ALIGN_TO_BOUNDARY(n) forces data to be n-byte aligned. This is used to satisfy SIMD requirements.
|
/* EIGEN_ALIGN_TO_BOUNDARY(n) forces data to be n-byte aligned. This is used to satisfy SIMD requirements.
|
||||||
@@ -264,6 +278,7 @@
|
|||||||
#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
|
||||||
@@ -282,7 +297,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
|
#ifndef EIGEN_STACK_ALLOCATION_LIMIT
|
||||||
#define EIGEN_STACK_ALLOCATION_LIMIT 20000
|
// 131072 == 128 KB
|
||||||
|
#define EIGEN_STACK_ALLOCATION_LIMIT 131072
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EIGEN_DEFAULT_IO_FORMAT
|
#ifndef EIGEN_DEFAULT_IO_FORMAT
|
||||||
@@ -298,7 +314,7 @@
|
|||||||
// 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 < 1800) && (!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)
|
||||||
@@ -317,8 +333,11 @@
|
|||||||
}
|
}
|
||||||
#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
|
||||||
|
|||||||
@@ -58,10 +58,17 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
|
// See bug 554 (http://eigen.tuxfamily.org/bz/show_bug.cgi?id=554)
|
||||||
&& (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
|
// It seems to be unsafe to check _POSIX_ADVISORY_INFO without including unistd.h first.
|
||||||
#define EIGEN_HAS_POSIX_MEMALIGN 1
|
// Currently, let's include it only on unix systems:
|
||||||
#else
|
#if defined(__unix__) || defined(__unix)
|
||||||
|
#include <unistd.h>
|
||||||
|
#if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || (defined __PGI) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
|
||||||
|
#define EIGEN_HAS_POSIX_MEMALIGN 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EIGEN_HAS_POSIX_MEMALIGN
|
||||||
#define EIGEN_HAS_POSIX_MEMALIGN 0
|
#define EIGEN_HAS_POSIX_MEMALIGN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -94,11 +101,11 @@ inline void throw_std_bad_alloc()
|
|||||||
/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
|
/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
|
||||||
* Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
|
* Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
|
||||||
*/
|
*/
|
||||||
inline void* handmade_aligned_malloc(size_t size)
|
inline void* handmade_aligned_malloc(std::size_t size)
|
||||||
{
|
{
|
||||||
void *original = std::malloc(size+16);
|
void *original = std::malloc(size+16);
|
||||||
if (original == 0) return 0;
|
if (original == 0) return 0;
|
||||||
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
|
void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
|
||||||
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
||||||
return aligned;
|
return aligned;
|
||||||
}
|
}
|
||||||
@@ -114,13 +121,18 @@ inline void handmade_aligned_free(void *ptr)
|
|||||||
* Since we know that our handmade version is based on std::realloc
|
* Since we know that our handmade version is based on std::realloc
|
||||||
* we can use std::realloc to implement efficient reallocation.
|
* we can use std::realloc to implement efficient reallocation.
|
||||||
*/
|
*/
|
||||||
inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
|
inline void* handmade_aligned_realloc(void* ptr, std::size_t size, std::size_t = 0)
|
||||||
{
|
{
|
||||||
if (ptr == 0) return handmade_aligned_malloc(size);
|
if (ptr == 0) return handmade_aligned_malloc(size);
|
||||||
void *original = *(reinterpret_cast<void**>(ptr) - 1);
|
void *original = *(reinterpret_cast<void**>(ptr) - 1);
|
||||||
|
std::ptrdiff_t previous_offset = static_cast<char *>(ptr)-static_cast<char *>(original);
|
||||||
original = std::realloc(original,size+16);
|
original = std::realloc(original,size+16);
|
||||||
if (original == 0) return 0;
|
if (original == 0) return 0;
|
||||||
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
|
void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
|
||||||
|
void *previous_aligned = static_cast<char *>(original)+previous_offset;
|
||||||
|
if(aligned!=previous_aligned)
|
||||||
|
std::memmove(aligned, previous_aligned, size);
|
||||||
|
|
||||||
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
||||||
return aligned;
|
return aligned;
|
||||||
}
|
}
|
||||||
@@ -129,7 +141,7 @@ inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
|
|||||||
*** Implementation of generic aligned realloc (when no realloc can be used)***
|
*** Implementation of generic aligned realloc (when no realloc can be used)***
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
void* aligned_malloc(size_t size);
|
void* aligned_malloc(std::size_t size);
|
||||||
void aligned_free(void *ptr);
|
void aligned_free(void *ptr);
|
||||||
|
|
||||||
/** \internal
|
/** \internal
|
||||||
@@ -210,7 +222,7 @@ inline void* aligned_malloc(size_t size)
|
|||||||
if(posix_memalign(&result, 16, size)) result = 0;
|
if(posix_memalign(&result, 16, size)) result = 0;
|
||||||
#elif EIGEN_HAS_MM_MALLOC
|
#elif EIGEN_HAS_MM_MALLOC
|
||||||
result = _mm_malloc(size, 16);
|
result = _mm_malloc(size, 16);
|
||||||
#elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
|
#elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
|
||||||
result = _aligned_malloc(size, 16);
|
result = _aligned_malloc(size, 16);
|
||||||
#else
|
#else
|
||||||
result = handmade_aligned_malloc(size);
|
result = handmade_aligned_malloc(size);
|
||||||
@@ -260,12 +272,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
|
|||||||
// The defined(_mm_free) is just here to verify that this MSVC version
|
// The defined(_mm_free) is just here to verify that this MSVC version
|
||||||
// implements _mm_malloc/_mm_free based on the corresponding _aligned_
|
// implements _mm_malloc/_mm_free based on the corresponding _aligned_
|
||||||
// functions. This may not always be the case and we just try to be safe.
|
// functions. This may not always be the case and we just try to be safe.
|
||||||
#if defined(_MSC_VER) && defined(_mm_free)
|
#if defined(_MSC_VER) && (!defined(_WIN32_WCE)) && defined(_mm_free)
|
||||||
result = _aligned_realloc(ptr,new_size,16);
|
result = _aligned_realloc(ptr,new_size,16);
|
||||||
#else
|
#else
|
||||||
result = generic_aligned_realloc(ptr,new_size,old_size);
|
result = generic_aligned_realloc(ptr,new_size,old_size);
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER) && (!defined(_WIN32_WCE))
|
||||||
result = _aligned_realloc(ptr,new_size,16);
|
result = _aligned_realloc(ptr,new_size,16);
|
||||||
#else
|
#else
|
||||||
result = handmade_aligned_realloc(ptr,new_size,old_size);
|
result = handmade_aligned_realloc(ptr,new_size,old_size);
|
||||||
@@ -405,6 +417,8 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pt
|
|||||||
|
|
||||||
template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
|
template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
|
||||||
{
|
{
|
||||||
|
if(size==0)
|
||||||
|
return 0; // short-cut. Also fixes Bug 884
|
||||||
check_size_for_overflow<T>(size);
|
check_size_for_overflow<T>(size);
|
||||||
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||||
if(NumTraits<T>::RequireInitialization)
|
if(NumTraits<T>::RequireInitialization)
|
||||||
@@ -452,10 +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)
|
||||||
{
|
{
|
||||||
typedef typename packet_traits<Scalar>::type Packet;
|
static const Index PacketSize = packet_traits<Scalar>::size;
|
||||||
enum { PacketSize = packet_traits<Scalar>::size,
|
static const Index PacketAlignedMask = PacketSize-1;
|
||||||
PacketAlignedMask = PacketSize-1
|
|
||||||
};
|
|
||||||
|
|
||||||
if(PacketSize==1)
|
if(PacketSize==1)
|
||||||
{
|
{
|
||||||
@@ -511,7 +523,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
|
||||||
@@ -567,7 +579,7 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
*/
|
*/
|
||||||
#ifdef EIGEN_ALLOCA
|
#ifdef EIGEN_ALLOCA
|
||||||
|
|
||||||
#ifdef __arm__
|
#if defined(__arm__) || defined(_WIN32)
|
||||||
#define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
|
#define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
|
||||||
#else
|
#else
|
||||||
#define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
|
#define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
|
||||||
@@ -601,7 +613,6 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
void* operator new(size_t size, const std::nothrow_t&) throw() { \
|
void* operator new(size_t size, const std::nothrow_t&) throw() { \
|
||||||
try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
|
try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
|
||||||
catch (...) { return 0; } \
|
catch (...) { return 0; } \
|
||||||
return 0; \
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||||
@@ -623,7 +634,9 @@ template<typename T> class aligned_stack_memory_handler
|
|||||||
/* 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. */ \
|
||||||
static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
|
static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
|
||||||
|
static void *operator new[](size_t size, void* ptr) { return ::operator new[](size,ptr); } \
|
||||||
void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
|
void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
|
||||||
|
void operator delete[](void * memory, void *ptr) throw() { return ::operator delete[](memory,ptr); } \
|
||||||
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
|
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
|
||||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||||
void operator delete(void *ptr, const std::nothrow_t&) throw() { \
|
void operator delete(void *ptr, const std::nothrow_t&) throw() { \
|
||||||
@@ -718,15 +731,6 @@ public:
|
|||||||
::new( p ) T( value );
|
::new( p ) T( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for c++11
|
|
||||||
#if (__cplusplus >= 201103L)
|
|
||||||
template<typename... Args>
|
|
||||||
void construct(pointer p, Args&&... args)
|
|
||||||
{
|
|
||||||
::new(p) T(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void destroy( pointer p )
|
void destroy( pointer p )
|
||||||
{
|
{
|
||||||
p->~T();
|
p->~T();
|
||||||
@@ -751,11 +755,16 @@ public:
|
|||||||
# if defined(__PIC__) && defined(__i386__)
|
# if defined(__PIC__) && defined(__i386__)
|
||||||
// Case for x86 with PIC
|
// Case for x86 with PIC
|
||||||
# define EIGEN_CPUID(abcd,func,id) \
|
# define EIGEN_CPUID(abcd,func,id) \
|
||||||
__asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
|
__asm__ __volatile__ ("xchgl %%ebx, %k1;cpuid; xchgl %%ebx,%k1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
|
||||||
|
# elif defined(__PIC__) && defined(__x86_64__)
|
||||||
|
// Case for x64 with PIC. In theory this is only a problem with recent gcc and with medium or large code model, not with the default small code model.
|
||||||
|
// However, we cannot detect which code model is used, and the xchg overhead is negligible anyway.
|
||||||
|
# define EIGEN_CPUID(abcd,func,id) \
|
||||||
|
__asm__ __volatile__ ("xchg{q}\t{%%}rbx, %q1; cpuid; xchg{q}\t{%%}rbx, %q1": "=a" (abcd[0]), "=&r" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id));
|
||||||
# else
|
# else
|
||||||
// Case for x86_64 or x86 w/o PIC
|
// Case for x86_64 or x86 w/o PIC
|
||||||
# define EIGEN_CPUID(abcd,func,id) \
|
# define EIGEN_CPUID(abcd,func,id) \
|
||||||
__asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
|
__asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "0" (func), "2" (id) );
|
||||||
# endif
|
# endif
|
||||||
# elif defined(_MSC_VER)
|
# elif defined(_MSC_VER)
|
||||||
# if (_MSC_VER > 1500) && ( defined(_M_IX86) || defined(_M_X64) )
|
# if (_MSC_VER > 1500) && ( defined(_M_IX86) || defined(_M_X64) )
|
||||||
@@ -768,9 +777,9 @@ namespace internal {
|
|||||||
|
|
||||||
#ifdef EIGEN_CPUID
|
#ifdef EIGEN_CPUID
|
||||||
|
|
||||||
inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
|
inline bool cpuid_is_vendor(int abcd[4], const int vendor[3])
|
||||||
{
|
{
|
||||||
return abcd[1]==(reinterpret_cast<const int*>(vendor))[0] && abcd[3]==(reinterpret_cast<const int*>(vendor))[1] && abcd[2]==(reinterpret_cast<const int*>(vendor))[2];
|
return abcd[1]==vendor[0] && abcd[3]==vendor[1] && abcd[2]==vendor[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
|
inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
|
||||||
@@ -912,13 +921,16 @@ inline void queryCacheSizes(int& l1, int& l2, int& l3)
|
|||||||
{
|
{
|
||||||
#ifdef EIGEN_CPUID
|
#ifdef EIGEN_CPUID
|
||||||
int abcd[4];
|
int abcd[4];
|
||||||
|
const int GenuineIntel[] = {0x756e6547, 0x49656e69, 0x6c65746e};
|
||||||
|
const int AuthenticAMD[] = {0x68747541, 0x69746e65, 0x444d4163};
|
||||||
|
const int AMDisbetter_[] = {0x69444d41, 0x74656273, 0x21726574}; // "AMDisbetter!"
|
||||||
|
|
||||||
// identify the CPU vendor
|
// identify the CPU vendor
|
||||||
EIGEN_CPUID(abcd,0x0,0);
|
EIGEN_CPUID(abcd,0x0,0);
|
||||||
int max_std_funcs = abcd[1];
|
int max_std_funcs = abcd[1];
|
||||||
if(cpuid_is_vendor(abcd,"GenuineIntel"))
|
if(cpuid_is_vendor(abcd,GenuineIntel))
|
||||||
queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
|
queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
|
||||||
else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
|
else if(cpuid_is_vendor(abcd,AuthenticAMD) || cpuid_is_vendor(abcd,AMDisbetter_))
|
||||||
queryCacheSizes_amd(l1,l2,l3);
|
queryCacheSizes_amd(l1,l2,l3);
|
||||||
else
|
else
|
||||||
// by default let's use Intel's API
|
// by default let's use Intel's API
|
||||||
|
|||||||
@@ -186,23 +186,35 @@ template<int Y, int InfX, int SupX>
|
|||||||
class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
|
class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
|
||||||
|
|
||||||
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
|
/** \internal determines whether the product of two numeric types is allowed and what the return type is */
|
||||||
template<typename T, typename U> struct scalar_product_traits;
|
template<typename T, typename U> struct scalar_product_traits
|
||||||
|
{
|
||||||
|
enum { Defined = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T> struct scalar_product_traits<T,T>
|
template<typename T> struct scalar_product_traits<T,T>
|
||||||
{
|
{
|
||||||
//enum { Cost = NumTraits<T>::MulCost };
|
enum {
|
||||||
|
// Cost = NumTraits<T>::MulCost,
|
||||||
|
Defined = 1
|
||||||
|
};
|
||||||
typedef T ReturnType;
|
typedef T ReturnType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct scalar_product_traits<T,std::complex<T> >
|
template<typename T> struct scalar_product_traits<T,std::complex<T> >
|
||||||
{
|
{
|
||||||
//enum { Cost = 2*NumTraits<T>::MulCost };
|
enum {
|
||||||
|
// Cost = 2*NumTraits<T>::MulCost,
|
||||||
|
Defined = 1
|
||||||
|
};
|
||||||
typedef std::complex<T> ReturnType;
|
typedef std::complex<T> ReturnType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct scalar_product_traits<std::complex<T>, T>
|
template<typename T> struct scalar_product_traits<std::complex<T>, T>
|
||||||
{
|
{
|
||||||
//enum { Cost = 2*NumTraits<T>::MulCost };
|
enum {
|
||||||
|
// Cost = 2*NumTraits<T>::MulCost,
|
||||||
|
Defined = 1
|
||||||
|
};
|
||||||
typedef std::complex<T> ReturnType;
|
typedef std::complex<T> ReturnType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,9 @@
|
|||||||
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED,
|
YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED,
|
||||||
THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE,
|
THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE,
|
||||||
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
|
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
|
||||||
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
|
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG,
|
||||||
|
IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY,
|
||||||
|
STORAGE_LAYOUT_DOES_NOT_MATCH
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ template<typename T> struct functor_traits
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Cost = 10,
|
Cost = 10,
|
||||||
PacketAccess = false
|
PacketAccess = false,
|
||||||
|
IsRepeatable = false
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -340,7 +341,7 @@ template<typename T, int n=1, typename PlainObject = typename eval<T>::type> str
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* const_cast_ptr(const T* ptr)
|
inline T* const_cast_ptr(const T* ptr)
|
||||||
{
|
{
|
||||||
return const_cast<T*>(ptr);
|
return const_cast<T*>(ptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
|
|||||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||||
|
|
||||||
/** Default constructor initializing a null box. */
|
/** Default constructor initializing a null box. */
|
||||||
inline explicit AlignedBox()
|
inline AlignedBox()
|
||||||
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
||||||
|
|
||||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||||
|
|
||||||
/** Default constructor without initialization */
|
/** Default constructor without initialization */
|
||||||
inline explicit Hyperplane() {}
|
inline Hyperplane() {}
|
||||||
|
|
||||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||||
* of the ambient space */
|
* of the ambient space */
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||||
|
|
||||||
/** Default constructor without initialization */
|
/** Default constructor without initialization */
|
||||||
inline explicit ParametrizedLine() {}
|
inline ParametrizedLine() {}
|
||||||
|
|
||||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||||
* of the ambient space */
|
* of the ambient space */
|
||||||
|
|||||||
@@ -147,7 +147,6 @@ void fitHyperplane(int numPoints,
|
|||||||
|
|
||||||
// compute the covariance matrix
|
// compute the covariance matrix
|
||||||
CovMatrixType covMat = CovMatrixType::Zero(size, size);
|
CovMatrixType covMat = CovMatrixType::Zero(size, size);
|
||||||
VectorType remean = VectorType::Zero(size);
|
|
||||||
for(int i = 0; i < numPoints; ++i)
|
for(int i = 0; i < numPoints; ++i)
|
||||||
{
|
{
|
||||||
VectorType diff = (*(points[i]) - mean).conjugate();
|
VectorType diff = (*(points[i]) - mean).conjugate();
|
||||||
|
|||||||
@@ -12,18 +12,18 @@
|
|||||||
|
|
||||||
namespace Eigen {
|
namespace Eigen {
|
||||||
|
|
||||||
template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return internal::real(x); }
|
template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return numext::real(x); }
|
||||||
template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return internal::imag(x); }
|
template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return numext::imag(x); }
|
||||||
template<typename T> inline T ei_conj(const T& x) { return internal::conj(x); }
|
template<typename T> inline T ei_conj(const T& x) { return numext::conj(x); }
|
||||||
template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { using std::abs; return abs(x); }
|
template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { using std::abs; return abs(x); }
|
||||||
template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return internal::abs2(x); }
|
template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return numext::abs2(x); }
|
||||||
template<typename T> inline T ei_sqrt(const T& x) { using std::sqrt; return sqrt(x); }
|
template<typename T> inline T ei_sqrt(const T& x) { using std::sqrt; return sqrt(x); }
|
||||||
template<typename T> inline T ei_exp (const T& x) { using std::exp; return exp(x); }
|
template<typename T> inline T ei_exp (const T& x) { using std::exp; return exp(x); }
|
||||||
template<typename T> inline T ei_log (const T& x) { using std::log; return log(x); }
|
template<typename T> inline T ei_log (const T& x) { using std::log; return log(x); }
|
||||||
template<typename T> inline T ei_sin (const T& x) { using std::sin; return sin(x); }
|
template<typename T> inline T ei_sin (const T& x) { using std::sin; return sin(x); }
|
||||||
template<typename T> inline T ei_cos (const T& x) { using std::cos; return cos(x); }
|
template<typename T> inline T ei_cos (const T& x) { using std::cos; return cos(x); }
|
||||||
template<typename T> inline T ei_atan2(const T& x,const T& y) { using std::atan2; return atan2(x,y); }
|
template<typename T> inline T ei_atan2(const T& x,const T& y) { using std::atan2; return atan2(x,y); }
|
||||||
template<typename T> inline T ei_pow (const T& x,const T& y) { return internal::pow(x,y); }
|
template<typename T> inline T ei_pow (const T& x,const T& y) { return numext::pow(x,y); }
|
||||||
template<typename T> inline T ei_random () { return internal::random<T>(); }
|
template<typename T> inline T ei_random () { return internal::random<T>(); }
|
||||||
template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
|
template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
|
||||||
|
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
e[p-2] = 0.0;
|
e[p-2] = 0.0;
|
||||||
for (j = p-2; j >= k; --j)
|
for (j = p-2; j >= k; --j)
|
||||||
{
|
{
|
||||||
Scalar t(internal::hypot(m_sigma[j],f));
|
Scalar t(numext::hypot(m_sigma[j],f));
|
||||||
Scalar cs(m_sigma[j]/t);
|
Scalar cs(m_sigma[j]/t);
|
||||||
Scalar sn(f/t);
|
Scalar sn(f/t);
|
||||||
m_sigma[j] = t;
|
m_sigma[j] = t;
|
||||||
@@ -344,7 +344,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
e[k-1] = 0.0;
|
e[k-1] = 0.0;
|
||||||
for (j = k; j < p; ++j)
|
for (j = k; j < p; ++j)
|
||||||
{
|
{
|
||||||
Scalar t(internal::hypot(m_sigma[j],f));
|
Scalar t(numext::hypot(m_sigma[j],f));
|
||||||
Scalar cs( m_sigma[j]/t);
|
Scalar cs( m_sigma[j]/t);
|
||||||
Scalar sn(f/t);
|
Scalar sn(f/t);
|
||||||
m_sigma[j] = t;
|
m_sigma[j] = t;
|
||||||
@@ -392,7 +392,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
|
|
||||||
for (j = k; j < p-1; ++j)
|
for (j = k; j < p-1; ++j)
|
||||||
{
|
{
|
||||||
Scalar t = internal::hypot(f,g);
|
Scalar t = numext::hypot(f,g);
|
||||||
Scalar cs = f/t;
|
Scalar cs = f/t;
|
||||||
Scalar sn = g/t;
|
Scalar sn = g/t;
|
||||||
if (j != k)
|
if (j != k)
|
||||||
@@ -410,7 +410,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
m_matV(i,j) = t;
|
m_matV(i,j) = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t = internal::hypot(f,g);
|
t = numext::hypot(f,g);
|
||||||
cs = f/t;
|
cs = f/t;
|
||||||
sn = g/t;
|
sn = g/t;
|
||||||
m_sigma[j] = t;
|
m_sigma[j] = t;
|
||||||
@@ -512,8 +512,7 @@ template<typename MatrixType>
|
|||||||
template<typename OtherDerived, typename ResultType>
|
template<typename OtherDerived, typename ResultType>
|
||||||
bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
|
bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
|
||||||
{
|
{
|
||||||
const int rows = m_matU.rows();
|
ei_assert(b.rows() == m_matU.rows());
|
||||||
ei_assert(b.rows() == rows);
|
|
||||||
|
|
||||||
Scalar maxVal = m_sigma.cwise().abs().maxCoeff();
|
Scalar maxVal = m_sigma.cwise().abs().maxCoeff();
|
||||||
for (int j=0; j<b.cols(); ++j)
|
for (int j=0; j<b.cols(); ++j)
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
@@ -294,7 +302,7 @@ void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(const RealScalar& mat
|
|||||||
{
|
{
|
||||||
// If the i-th and k-th eigenvalue are equal, then z equals 0.
|
// If the i-th and k-th eigenvalue are equal, then z equals 0.
|
||||||
// Use a small value instead, to prevent division by zero.
|
// Use a small value instead, to prevent division by zero.
|
||||||
internal::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
|
numext::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
|
||||||
}
|
}
|
||||||
m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z;
|
m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,8 +263,8 @@ template<typename _MatrixType> class ComplexSchur
|
|||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
|
inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
|
||||||
{
|
{
|
||||||
RealScalar d = internal::norm1(m_matT.coeff(i,i)) + internal::norm1(m_matT.coeff(i+1,i+1));
|
RealScalar d = numext::norm1(m_matT.coeff(i,i)) + numext::norm1(m_matT.coeff(i+1,i+1));
|
||||||
RealScalar sd = internal::norm1(m_matT.coeff(i+1,i));
|
RealScalar sd = numext::norm1(m_matT.coeff(i+1,i));
|
||||||
if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon()))
|
if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon()))
|
||||||
{
|
{
|
||||||
m_matT.coeffRef(i+1,i) = ComplexScalar(0);
|
m_matT.coeffRef(i+1,i) = ComplexScalar(0);
|
||||||
@@ -282,7 +282,7 @@ typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::compu
|
|||||||
if (iter == 10 || iter == 20)
|
if (iter == 10 || iter == 20)
|
||||||
{
|
{
|
||||||
// exceptional shift, taken from http://www.netlib.org/eispack/comqr.f
|
// exceptional shift, taken from http://www.netlib.org/eispack/comqr.f
|
||||||
return abs(internal::real(m_matT.coeff(iu,iu-1))) + abs(internal::real(m_matT.coeff(iu-1,iu-2)));
|
return abs(numext::real(m_matT.coeff(iu,iu-1))) + abs(numext::real(m_matT.coeff(iu-1,iu-2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the shift as one of the eigenvalues of t, the 2x2
|
// compute the shift as one of the eigenvalues of t, the 2x2
|
||||||
@@ -299,13 +299,13 @@ typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::compu
|
|||||||
ComplexScalar eival1 = (trace + disc) / RealScalar(2);
|
ComplexScalar eival1 = (trace + disc) / RealScalar(2);
|
||||||
ComplexScalar eival2 = (trace - disc) / RealScalar(2);
|
ComplexScalar eival2 = (trace - disc) / RealScalar(2);
|
||||||
|
|
||||||
if(internal::norm1(eival1) > internal::norm1(eival2))
|
if(numext::norm1(eival1) > numext::norm1(eival2))
|
||||||
eival2 = det / eival1;
|
eival2 = det / eival1;
|
||||||
else
|
else
|
||||||
eival1 = det / eival2;
|
eival1 = det / eival2;
|
||||||
|
|
||||||
// choose the eigenvalue closest to the bottom entry of the diagonal
|
// choose the eigenvalue closest to the bottom entry of the diagonal
|
||||||
if(internal::norm1(eival1-t.coeff(1,1)) < internal::norm1(eival2-t.coeff(1,1)))
|
if(numext::norm1(eival1-t.coeff(1,1)) < numext::norm1(eival2-t.coeff(1,1)))
|
||||||
return normt * eival1;
|
return normt * eival1;
|
||||||
else
|
else
|
||||||
return normt * eival2;
|
return normt * eival2;
|
||||||
@@ -364,7 +364,6 @@ struct complex_schur_reduce_to_hessenberg<MatrixType, false>
|
|||||||
static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
|
static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
|
||||||
{
|
{
|
||||||
typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
|
typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
|
||||||
typedef typename ComplexSchur<MatrixType>::ComplexMatrixType ComplexMatrixType;
|
|
||||||
|
|
||||||
// Note: m_hess is over RealScalar; m_matT and m_matU is over ComplexScalar
|
// Note: m_hess is over RealScalar; m_matT and m_matU is over ComplexScalar
|
||||||
_this.m_hess.compute(matrix);
|
_this.m_hess.compute(matrix);
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -317,12 +324,12 @@ MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
|
|||||||
MatrixType matD = MatrixType::Zero(n,n);
|
MatrixType matD = MatrixType::Zero(n,n);
|
||||||
for (Index i=0; i<n; ++i)
|
for (Index i=0; i<n; ++i)
|
||||||
{
|
{
|
||||||
if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i))))
|
if (internal::isMuchSmallerThan(numext::imag(m_eivalues.coeff(i)), numext::real(m_eivalues.coeff(i))))
|
||||||
matD.coeffRef(i,i) = internal::real(m_eivalues.coeff(i));
|
matD.coeffRef(i,i) = numext::real(m_eivalues.coeff(i));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
matD.template block<2,2>(i,i) << internal::real(m_eivalues.coeff(i)), internal::imag(m_eivalues.coeff(i)),
|
matD.template block<2,2>(i,i) << numext::real(m_eivalues.coeff(i)), numext::imag(m_eivalues.coeff(i)),
|
||||||
-internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i));
|
-numext::imag(m_eivalues.coeff(i)), numext::real(m_eivalues.coeff(i));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +345,7 @@ typename EigenSolver<MatrixType>::EigenvectorsType EigenSolver<MatrixType>::eige
|
|||||||
EigenvectorsType matV(n,n);
|
EigenvectorsType matV(n,n);
|
||||||
for (Index j=0; j<n; ++j)
|
for (Index j=0; j<n; ++j)
|
||||||
{
|
{
|
||||||
if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(j)), internal::real(m_eivalues.coeff(j))) || j+1==n)
|
if (internal::isMuchSmallerThan(numext::imag(m_eivalues.coeff(j)), numext::real(m_eivalues.coeff(j))) || j+1==n)
|
||||||
{
|
{
|
||||||
// we have a real eigen value
|
// we have a real eigen value
|
||||||
matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
|
matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
|
||||||
@@ -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());
|
||||||
@@ -515,8 +524,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::complex<Scalar> cc = cdiv<Scalar>(0.0,-m_matT.coeff(n-1,n),m_matT.coeff(n-1,n-1)-p,q);
|
std::complex<Scalar> cc = cdiv<Scalar>(0.0,-m_matT.coeff(n-1,n),m_matT.coeff(n-1,n-1)-p,q);
|
||||||
m_matT.coeffRef(n-1,n-1) = internal::real(cc);
|
m_matT.coeffRef(n-1,n-1) = numext::real(cc);
|
||||||
m_matT.coeffRef(n-1,n) = internal::imag(cc);
|
m_matT.coeffRef(n-1,n) = numext::imag(cc);
|
||||||
}
|
}
|
||||||
m_matT.coeffRef(n,n-1) = 0.0;
|
m_matT.coeffRef(n,n-1) = 0.0;
|
||||||
m_matT.coeffRef(n,n) = 1.0;
|
m_matT.coeffRef(n,n) = 1.0;
|
||||||
@@ -538,8 +547,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
if (m_eivalues.coeff(i).imag() == RealScalar(0))
|
if (m_eivalues.coeff(i).imag() == RealScalar(0))
|
||||||
{
|
{
|
||||||
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
|
std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
|
||||||
m_matT.coeffRef(i,n-1) = internal::real(cc);
|
m_matT.coeffRef(i,n-1) = numext::real(cc);
|
||||||
m_matT.coeffRef(i,n) = internal::imag(cc);
|
m_matT.coeffRef(i,n) = numext::imag(cc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -552,8 +561,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
vr = eps * norm * (abs(w) + abs(q) + abs(x) + abs(y) + abs(lastw));
|
vr = eps * norm * (abs(w) + abs(q) + abs(x) + abs(y) + abs(lastw));
|
||||||
|
|
||||||
std::complex<Scalar> cc = cdiv(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra,vr,vi);
|
std::complex<Scalar> cc = cdiv(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra,vr,vi);
|
||||||
m_matT.coeffRef(i,n-1) = internal::real(cc);
|
m_matT.coeffRef(i,n-1) = numext::real(cc);
|
||||||
m_matT.coeffRef(i,n) = internal::imag(cc);
|
m_matT.coeffRef(i,n) = numext::imag(cc);
|
||||||
if (abs(x) > (abs(lastw) + abs(q)))
|
if (abs(x) > (abs(lastw) + abs(q)))
|
||||||
{
|
{
|
||||||
m_matT.coeffRef(i+1,n-1) = (-ra - w * m_matT.coeff(i,n-1) + q * m_matT.coeff(i,n)) / x;
|
m_matT.coeffRef(i+1,n-1) = (-ra - w * m_matT.coeff(i,n-1) + q * m_matT.coeff(i,n)) / x;
|
||||||
@@ -562,8 +571,8 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cc = cdiv(-lastra-y*m_matT.coeff(i,n-1),-lastsa-y*m_matT.coeff(i,n),lastw,q);
|
cc = cdiv(-lastra-y*m_matT.coeff(i,n-1),-lastsa-y*m_matT.coeff(i,n),lastw,q);
|
||||||
m_matT.coeffRef(i+1,n-1) = internal::real(cc);
|
m_matT.coeffRef(i+1,n-1) = numext::real(cc);
|
||||||
m_matT.coeffRef(i+1,n) = internal::imag(cc);
|
m_matT.coeffRef(i+1,n) = numext::imag(cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ template<typename _MatrixType> class HessenbergDecomposition
|
|||||||
typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
|
typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
|
||||||
|
|
||||||
/** \brief Return type of matrixQ() */
|
/** \brief Return type of matrixQ() */
|
||||||
typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
|
typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
|
||||||
|
|
||||||
typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;
|
typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVector
|
|||||||
|
|
||||||
// A = A H'
|
// A = A H'
|
||||||
matA.rightCols(remainingSize)
|
matA.rightCols(remainingSize)
|
||||||
.applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), internal::conj(h), &temp.coeffRef(0));
|
.applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), numext::conj(h), &temp.coeffRef(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,11 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
|||||||
#endif // EIGEN2_SUPPORT
|
#endif // EIGEN2_SUPPORT
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void check_template_parameters()
|
||||||
|
{
|
||||||
|
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||||
|
}
|
||||||
|
|
||||||
MatrixType m_eivec;
|
MatrixType m_eivec;
|
||||||
RealVectorType m_eivalues;
|
RealVectorType m_eivalues;
|
||||||
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
typename TridiagonalizationType::SubDiagonalType m_subdiag;
|
||||||
@@ -384,6 +389,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
|
||||||
@@ -395,7 +402,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
|
|||||||
|
|
||||||
if(n==1)
|
if(n==1)
|
||||||
{
|
{
|
||||||
m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0));
|
m_eivalues.coeffRef(0,0) = numext::real(matrix.coeff(0,0));
|
||||||
if(computeEigenvectors)
|
if(computeEigenvectors)
|
||||||
m_eivec.setOnes(n,n);
|
m_eivec.setOnes(n,n);
|
||||||
m_info = Success;
|
m_info = Success;
|
||||||
@@ -490,7 +497,12 @@ 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;
|
||||||
|
|
||||||
|
/** \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,39 +522,48 @@ 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
|
||||||
@@ -552,106 +573,72 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
|
|||||||
MatrixType& eivecs = solver.m_eivec;
|
MatrixType& 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();
|
|
||||||
safeNorm2 *= safeNorm2;
|
|
||||||
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 ? d1 : d0;
|
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);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm();
|
std::swap(k,l);
|
||||||
|
d0 = d1;
|
||||||
if(n>safeNorm2)
|
|
||||||
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 the eigenvector of index k
|
||||||
tmp.diagonal().array() -= eivals(1);
|
|
||||||
|
|
||||||
if(d0<=Eigen::NumTraits<Scalar>::epsilon())
|
|
||||||
eivecs.col(1) = eivecs.col(k).unitOrthogonal();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
n = (cross = eivecs.col(k).cross(tmp.row(0).normalized())).squaredNorm();
|
tmp.diagonal().array () -= eivals(k);
|
||||||
if(n>safeNorm2)
|
// By construction, 'tmp' is of rank 2, and its kernel corresponds to the respective eigenvector.
|
||||||
eivecs.col(1) = cross / sqrt(n);
|
extract_kernel(tmp, eivecs.col(k), eivecs.col(l));
|
||||||
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 ve very closed to each other
|
|
||||||
eivecs.col(1) = eivecs.col(k).unitOrthogonal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure that eivecs[1] is orthogonal to eivecs[2]
|
|
||||||
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();
|
// 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
|
||||||
|
{
|
||||||
|
tmp = scaledMat;
|
||||||
|
tmp.diagonal().array () -= eivals(l);
|
||||||
|
|
||||||
|
VectorType dummy;
|
||||||
|
extract_kernel(tmp, eivecs.col(l), dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute last eigenvector from the other two
|
||||||
|
eivecs.col(1) = eivecs.col(2).cross(eivecs.col(0)).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;
|
||||||
@@ -669,7 +656,7 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2
|
|||||||
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( 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;
|
||||||
@@ -678,6 +665,8 @@ 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
|
||||||
@@ -698,22 +687,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 = abs2(scaledMat(0,0));
|
|
||||||
Scalar c2 = abs2(scaledMat(1,1));
|
|
||||||
Scalar b2 = 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.
|
||||||
@@ -744,7 +740,7 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
|
|||||||
RealScalar e = subdiag[end-1];
|
RealScalar e = subdiag[end-1];
|
||||||
// Note that thanks to scaling, e^2 or td^2 cannot overflow, however they can still
|
// Note that thanks to scaling, e^2 or td^2 cannot overflow, however they can still
|
||||||
// underflow thus leading to inf/NaN values when using the following commented code:
|
// underflow thus leading to inf/NaN values when using the following commented code:
|
||||||
// RealScalar e2 = abs2(subdiag[end-1]);
|
// RealScalar e2 = numext::abs2(subdiag[end-1]);
|
||||||
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
|
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
|
||||||
// This explain the following, somewhat more complicated, version:
|
// This explain the following, somewhat more complicated, version:
|
||||||
RealScalar mu = diag[end];
|
RealScalar mu = diag[end];
|
||||||
@@ -752,8 +748,8 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
|
|||||||
mu -= abs(e);
|
mu -= abs(e);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar e2 = abs2(subdiag[end-1]);
|
RealScalar e2 = numext::abs2(subdiag[end-1]);
|
||||||
RealScalar h = hypot(td,e);
|
RealScalar h = numext::hypot(td,e);
|
||||||
if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
|
if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
|
||||||
else mu -= e2 / (td + (td>0 ? h : -h));
|
else mu -= e2 / (td + (td>0 ? h : -h));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ SelfAdjointEigenSolver<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW> >::compute(c
|
|||||||
\
|
\
|
||||||
if(n==1) \
|
if(n==1) \
|
||||||
{ \
|
{ \
|
||||||
m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0)); \
|
m_eivalues.coeffRef(0,0) = numext::real(matrix.coeff(0,0)); \
|
||||||
if(computeEigenvectors) m_eivec.setOnes(n,n); \
|
if(computeEigenvectors) m_eivec.setOnes(n,n); \
|
||||||
m_info = Success; \
|
m_info = Success; \
|
||||||
m_isInitialized = true; \
|
m_isInitialized = true; \
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ template<typename _MatrixType> class Tridiagonalization
|
|||||||
>::type SubDiagonalReturnType;
|
>::type SubDiagonalReturnType;
|
||||||
|
|
||||||
/** \brief Return type of matrixQ() */
|
/** \brief Return type of matrixQ() */
|
||||||
typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
|
typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
|
||||||
|
|
||||||
/** \brief Default constructor.
|
/** \brief Default constructor.
|
||||||
*
|
*
|
||||||
@@ -345,7 +345,7 @@ namespace internal {
|
|||||||
template<typename MatrixType, typename CoeffVectorType>
|
template<typename MatrixType, typename CoeffVectorType>
|
||||||
void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
|
void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
|
||||||
{
|
{
|
||||||
using internal::conj;
|
using numext::conj;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::RealScalar RealScalar;
|
typedef typename MatrixType::RealScalar RealScalar;
|
||||||
@@ -426,8 +426,6 @@ struct tridiagonalization_inplace_selector;
|
|||||||
template<typename MatrixType, typename DiagonalType, typename SubDiagonalType>
|
template<typename MatrixType, typename DiagonalType, typename SubDiagonalType>
|
||||||
void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
|
void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
|
||||||
{
|
{
|
||||||
typedef typename MatrixType::Index Index;
|
|
||||||
//Index n = mat.rows();
|
|
||||||
eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
|
eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
|
||||||
tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, extractQ);
|
tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, extractQ);
|
||||||
}
|
}
|
||||||
@@ -470,7 +468,7 @@ struct tridiagonalization_inplace_selector<MatrixType,3,false>
|
|||||||
{
|
{
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
diag[0] = mat(0,0);
|
diag[0] = mat(0,0);
|
||||||
RealScalar v1norm2 = abs2(mat(2,0));
|
RealScalar v1norm2 = numext::abs2(mat(2,0));
|
||||||
if(v1norm2 == RealScalar(0))
|
if(v1norm2 == RealScalar(0))
|
||||||
{
|
{
|
||||||
diag[1] = mat(1,1);
|
diag[1] = mat(1,1);
|
||||||
@@ -482,7 +480,7 @@ struct tridiagonalization_inplace_selector<MatrixType,3,false>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RealScalar beta = sqrt(abs2(mat(1,0)) + v1norm2);
|
RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2);
|
||||||
RealScalar invBeta = RealScalar(1)/beta;
|
RealScalar invBeta = RealScalar(1)/beta;
|
||||||
Scalar m01 = mat(1,0) * invBeta;
|
Scalar m01 = mat(1,0) * invBeta;
|
||||||
Scalar m02 = mat(2,0) * invBeta;
|
Scalar m02 = mat(2,0) * invBeta;
|
||||||
@@ -512,7 +510,7 @@ struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
|
|||||||
template<typename DiagonalType, typename SubDiagonalType>
|
template<typename DiagonalType, typename SubDiagonalType>
|
||||||
static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, bool extractQ)
|
static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, bool extractQ)
|
||||||
{
|
{
|
||||||
diag(0,0) = real(mat(0,0));
|
diag(0,0) = numext::real(mat(0,0));
|
||||||
if(extractQ)
|
if(extractQ)
|
||||||
mat(0,0) = Scalar(1);
|
mat(0,0) = Scalar(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,57 +42,59 @@ 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
|
||||||
|
/** @} */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Default constructor initializing a null box. */
|
/** Default constructor initializing a null box. */
|
||||||
inline explicit AlignedBox()
|
inline AlignedBox()
|
||||||
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
||||||
|
|
||||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||||
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() );
|
||||||
@@ -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))); }
|
||||||
|
|||||||
@@ -27,56 +27,75 @@ namespace Eigen {
|
|||||||
* * AngleAxisf(ea[1], Vector3f::UnitX())
|
* * AngleAxisf(ea[1], Vector3f::UnitX())
|
||||||
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
|
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
|
||||||
* This corresponds to the right-multiply conventions (with right hand side frames).
|
* This corresponds to the right-multiply conventions (with right hand side frames).
|
||||||
|
*
|
||||||
|
* The returned angles are in the ranges [0:pi]x[-pi:pi]x[-pi:pi].
|
||||||
|
*
|
||||||
|
* \sa class AngleAxis
|
||||||
*/
|
*/
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
||||||
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||||
{
|
{
|
||||||
using std::atan2;
|
using std::atan2;
|
||||||
|
using std::sin;
|
||||||
|
using std::cos;
|
||||||
/* Implemented from Graphics Gems IV */
|
/* Implemented from Graphics Gems IV */
|
||||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
||||||
|
|
||||||
Matrix<Scalar,3,1> res;
|
Matrix<Scalar,3,1> res;
|
||||||
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
|
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
|
||||||
const Scalar epsilon = NumTraits<Scalar>::dummy_precision();
|
|
||||||
|
|
||||||
const Index odd = ((a0+1)%3 == a1) ? 0 : 1;
|
const Index odd = ((a0+1)%3 == a1) ? 0 : 1;
|
||||||
const Index i = a0;
|
const Index i = a0;
|
||||||
const Index j = (a0 + 1 + odd)%3;
|
const Index j = (a0 + 1 + odd)%3;
|
||||||
const Index k = (a0 + 2 - odd)%3;
|
const Index k = (a0 + 2 - odd)%3;
|
||||||
|
|
||||||
if (a0==a2)
|
if (a0==a2)
|
||||||
{
|
{
|
||||||
Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
|
res[0] = atan2(coeff(j,i), coeff(k,i));
|
||||||
res[1] = atan2(s, coeff(i,i));
|
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0)))
|
||||||
if (s > epsilon)
|
|
||||||
{
|
{
|
||||||
res[0] = atan2(coeff(j,i), coeff(k,i));
|
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
|
||||||
res[2] = atan2(coeff(i,j),-coeff(i,k));
|
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||||
|
res[1] = -atan2(s2, coeff(i,i));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res[0] = Scalar(0);
|
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||||
res[2] = (coeff(i,i)>0?1:-1)*atan2(-coeff(k,j), coeff(j,j));
|
res[1] = atan2(s2, coeff(i,i));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first two angles,
|
||||||
|
// we can compute their respective rotation, and apply its inverse to M. Since the result must
|
||||||
|
// be a rotation around x, we have:
|
||||||
|
//
|
||||||
|
// c2 s1.s2 c1.s2 1 0 0
|
||||||
|
// 0 c1 -s1 * M = 0 c3 s3
|
||||||
|
// -s2 s1.c2 c1.c2 0 -s3 c3
|
||||||
|
//
|
||||||
|
// Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3
|
||||||
|
|
||||||
|
Scalar s1 = sin(res[0]);
|
||||||
|
Scalar c1 = cos(res[0]);
|
||||||
|
res[2] = atan2(c1*coeff(j,k)-s1*coeff(k,k), c1*coeff(j,j) - s1 * coeff(k,j));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Scalar c = Vector2(coeff(i,i) , coeff(i,j)).norm();
|
res[0] = atan2(coeff(j,k), coeff(k,k));
|
||||||
res[1] = atan2(-coeff(i,k), c);
|
Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
|
||||||
if (c > epsilon)
|
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0))) {
|
||||||
{
|
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
|
||||||
res[0] = atan2(coeff(j,k), coeff(k,k));
|
res[1] = atan2(-coeff(i,k), -c2);
|
||||||
res[2] = atan2(coeff(i,j), coeff(i,i));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
res[1] = atan2(-coeff(i,k), c2);
|
||||||
res[0] = Scalar(0);
|
Scalar s1 = sin(res[0]);
|
||||||
res[2] = (coeff(i,k)>0?1:-1)*atan2(-coeff(k,j), coeff(j,j));
|
Scalar c1 = cos(res[0]);
|
||||||
}
|
res[2] = atan2(s1*coeff(k,i)-c1*coeff(j,i), c1*coeff(j,j) - s1 * coeff(k,j));
|
||||||
}
|
}
|
||||||
if (!odd)
|
if (!odd)
|
||||||
res = -res;
|
res = -res;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user