Compare commits

..

107 Commits

Author SHA1 Message Date
Gael Guennebaud
38229a3d23 bump to 3.1.4 2013-08-01 11:35:43 +02:00
Gael Guennebaud
b18f9427a8 Fix bug in sparse documentation.
(transplanted from 4020d4286f
)
2013-07-04 06:49:24 +02:00
Gael Guennebaud
a6fbf2c202 CwiseUnaryView should not inherit no_assignment_operator!
(transplanted from 1330ca611b
)
2013-06-24 13:45:33 +02:00
Gael Guennebaud
2034af6db9 fix compilation of ArrayBase::transposeInPlace
(transplanted from c21a04bcf9
)
2013-06-24 13:35:13 +02:00
Gael Guennebaud
fbe1d5fb2c bug #620: fix robustness issue in JacobiSVD::solve (also fix a perf. issue)
(transplanted from 8bbde351e7
)
2013-06-24 13:08:09 +02:00
Jitse Niesen
560877016a Avoid phrase "static allocation" for local storage on stack (bug #615).
(transplanted from 4e6d746514
)
2013-06-18 14:35:12 +01:00
Gael Guennebaud
c7ba7f59d6 Fix compilation issue with some compilers (when doing using Base::foo;, foo must be visible in the direct base class)
(transplanted from 33788b97dd
)
2013-06-18 00:48:47 +02:00
Jeff Dean
5dca39eb8b Fix bug #613: psqrt was incorrect for small numbers
(transplanted from d5fa5001a7
)
2013-06-13 18:17:27 +02:00
Gael Guennebaud
21826e9e53 Add missing dependency in SparseSholesky header
(transplanted from f3af423c70
)
2013-06-11 21:13:30 +02:00
Gael Guennebaud
97c08b43b4 Fix bug #608: the sign computation in LDLT was broken
(transplanted from a69b4b092b
)
2013-06-09 23:19:32 +02:00
Gael Guennebaud
8f67e02ee2 Fix non const data() member in Array and Matrix wrappers.
(transplanted from b5e5b6aa57
)
2013-05-16 10:18:19 +02:00
Gael Guennebaud
93c329445c Add missing data member function in CwiseUnaryView
(transplanted from e21dc15386
)
2013-02-07 17:44:24 +01:00
Gael Guennebaud
575255bc1f fix a typo in commit 324ecf153b
(regarding MKL on windows)
(transplanted from 576d62db64
)
2012-08-27 13:17:45 +02:00
Gael Guennebaud
d29654fb4e Added tag 3.1.3 for changeset 2221cdbe62 2013-04-16 09:38:46 +02:00
Gael Guennebaud
2221cdbe62 bump to 3.1.3 2013-04-16 09:38:40 +02:00
Hauke Heibel
ba1e62f516 Prevent calling .norm() on integer matrices in the unit tests.
(transplanted from b5d8299ee7
)
2013-02-28 12:33:34 +01:00
Gael Guennebaud
ce2b0ac502 Fix two numerical issues in unit tests.
(transplanted from 455e6e38b6
)
2013-02-27 08:07:18 +01:00
Gael Guennebaud
1f7dfcff8a Add missing template keyword
(transplanted from 858ac9ffe0
)
2013-03-01 00:03:28 +01:00
Gael Guennebaud
2234043f99 Enable SSE with ICC even when it mimics a gcc version lower than 4.2
(transplanted from 6eaff5a098
)
2013-04-11 19:48:34 +02:00
Gael Guennebaud
69ff8afea7 Workaround gcc-4.7 bug #53900 (too aggressive optimization in our alignment check)
(transplanted from 19c78cf510
)
2013-01-22 22:59:09 +01:00
Gael Guennebaud
64a6d37729 Fix a serious bug in handmade_aligned_realloc: original data have to be moved if the alignment offset differs.
(transplanted from 7e04d7db02
)
2013-04-10 13:58:20 +02:00
Gael Guennebaud
4ac874ed03 Upload CDASH submissions for the 3.1 branch to a separate project 2013-04-10 10:06:36 +02:00
Gael Guennebaud
0029599c4a Fix bug #581: remove useless piece of code is blueNorm
(transplanted from 8f44205671
)
2013-04-09 09:23:40 +02:00
Claas H. Köhler
f78dffffda Forward compiler flags to Fortran workaround
(transplanted from d6d638c751
)
2013-03-17 14:17:44 +01:00
Gael Guennebaud
e304a92f41 fix sparse vector assignment from a sparse matrix
(transplanted from 98ce4455dd
)
2013-03-06 11:58:22 +01:00
Gael Guennebaud
2674a31421 Fix a compilation with CGAL::Gmpq by adding explicit internal:: namespace when calling abs(). 2013-02-26 16:46:10 +01:00
Gael Guennebaud
de25881056 Fix computation of outer-stride when calling .real() or .imag()
(transplanted from 63135a7350
)
2013-02-26 15:08:50 +01:00
Jitse Niesen
7df8b57770 Fix linear vectorized transversal in linspace (fixes bug #526).
(transplanted from b4f6aec195
)
2013-02-18 17:26:03 +00:00
Gael Guennebaud
ddba6054e0 Push cdash report of the 3.1 branch in its own cdash subproject 2013-02-15 15:30:27 +01:00
Gael Guennebaud
6adc13ea04 Fix SSE plog<float> to return -INF on 0
(transplanted from 8745da14d8
)
2013-02-14 23:34:05 +01:00
Gael Guennebaud
66cbfd4d39 Fix some implicit int64 to int conversion warnings. However, the real issue
is that PermutationMatrix mixes the type of the stored indices and the "Index"
type used for the sizes, coeff indices, etc., which should be DenseIndex.
2013-02-14 18:16:51 +01:00
Gael Guennebaud
394784c999 Fix bug in aligned_free with windows CE
(transplanted from 25bcbfb10c
)
2013-02-13 19:09:31 +01:00
Gael Guennebaud
fcc46f49ca Fix bug #551: compilation issue when using EIGEN_DEFAULT_DENSE_INDEX_TYPE 2013-02-09 09:43:17 +01:00
Gael Guennebaud
92983fc95a Fix traits of Map<Quaternion>, and respectively extend the unit tests
(transplanted from 392ffce3b9
)
2013-01-20 10:21:54 +01:00
Gael Guennebaud
d5702fb7e9 Some minor documentation fixes in Quaternion
(transplanted from fb89b66229
)
2013-01-20 10:20:39 +01:00
Christoph Hertzberg
8aaa570c6d Fix bug #507: Mark variable as unused in NDEBUG case 2012-12-20 11:21:47 +01:00
Christoph Hertzberg
8c65cacad8 Fix bug #531: Empty line in <table> made doxygen render it as paragraphs 2012-12-17 16:13:42 +01:00
Gael Guennebaud
2041114285 Fix bug #533: add some missing const qualifiers (was already fixed in devel branch) 2012-12-16 20:36:59 +01:00
Gael Guennebaud
ac406a7685 Fix bug #535: unused variable warnings
(transplanted from 925a5b7d07
)
2012-12-16 20:21:28 +01:00
Gael Guennebaud
45ccaacc54 fix geometry tutorial
(transplanted from 8719b1bf16
)
2012-11-29 22:48:13 +08:00
Gael Guennebaud
43e90e3575 Added tag 3.1.2 for changeset 63c58c8436 2012-11-05 22:23:03 +01:00
Gael Guennebaud
63c58c8436 bump to 3.1.2 2012-11-05 22:22:49 +01:00
Gael Guennebaud
caf24f1c9e Disable opengl demo if Qt4 or OpenGL cannot be found. 2012-10-31 11:36:45 +01:00
Gael Guennebaud
f7b959b5fb Fix unused variable warning 2012-10-30 10:10:29 +01:00
Gael Guennebaud
ad27746b5d fix bug #524: Pardiso's parameter array does not have to be aligned!
(transplanted from b3254c9af5
)
2012-10-24 10:31:04 +02:00
Gael Guennebaud
90912315ac fix bug #521: __cpuidex is not available on all architectures supported by MSVC
(transplanted from 138897cc06
)
2012-10-24 10:21:41 +02:00
Gael Guennebaud
26e9563baf Windows CE does not provide an aligned_malloc function.
(transplanted from 9b418afff6
)
2012-10-24 10:12:42 +02:00
Gael Guennebaud
85c40128e4 Fix bug #519: AlignedBox::dim() was wrong for dynamic dimensions
(transplanted from 0753463d70
)
2012-10-24 09:58:35 +02:00
Gael Guennebaud
7b13a7fd23 fix comma initializer when inserting empty matrices
(transplanted from a67eea05c1
)
2012-10-03 21:58:14 +02:00
Gael Guennebaud
2f0307cdb5 fix dense=sparse*diagonal (there was an issue in the values returned by the .outer() function of the related iterators)
(transplanted from fec6df1f7d
)
2012-10-03 09:06:19 +02:00
Gael Guennebaud
749317561c add an assertion when inserting an already existing element 2012-10-02 23:02:23 +02:00
Gael Guennebaud
dc5b335f9f add scalar multiple to diagonal matrices 2012-09-27 09:37:05 +02:00
Gael Guennebaud
74a2a0f224 fix SparseMatrix option bit flag in eval<> helper
(transplanted from 1b004d5794
)
2012-09-27 09:22:10 +02:00
Gael Guennebaud
b0862dcb2f fix bug #515: missing explicit scalar conversion 2012-09-27 00:23:19 +02:00
Gael Guennebaud
ba013de9da fix bug #511: pretty printers on windows
(transplanted from 44374788b5
)
2012-09-26 23:48:48 +02:00
Gael Guennebaud
4ea9113efc fix bug #509: warning with gcc 4.7
(transplanted from 7c4b55fda9
)
2012-09-26 23:32:22 +02:00
Gael Guennebaud
76a2db4c74 workaround weird compilation error with MSVC
(transplanted from 48c4d48aec
)
2012-09-14 09:54:56 +02:00
Gael Guennebaud
53a0142583 fix compilation with m.array().min/max(scalar)
(transplanted from 0c584dcf4d
)
2012-09-12 17:50:07 +02:00
Benoit Jacob
733fd6e7ba Replace COPYING.LGPL by a copy of the LGPL 2.1 (instead of LGPL 3).
Indeed, all the LGPL code we use, is licensed under LGPL 2.1 (with some files being "2.1 or later").
2012-09-10 13:27:44 -04:00
Gael Guennebaud
26282498dc fix bug #501: remove aggressive mat/scalar optimization (was replaced by mat*(1/scalar) for non integer types)
(transplanted from 721671cc4e
)
2012-09-08 11:52:03 +02:00
Gael Guennebaud
f4bdc66e83 remove stupid assert in blue norm.
(transplanted from 06d2fe453d
)
2012-09-07 23:19:24 +02:00
Gael Guennebaud
16deb21376 forward resize() function from Array/Matrix-Wrapper to the nested expression such that mat.array().resize(a,b) is now allowed.
(transplanted from 9da41cc527
)
2012-08-30 16:28:53 +02:00
Gael Guennebaud
221f54698c Fix out-of-range memory access in GEMV (the memory was not used for the computation, only to assemble unaligned packets from aligned packet loads) 2012-08-30 10:52:15 +02:00
Gael Guennebaud
2858b6d2d6 fix bug #499: the image was missing because of a dependency issue when building/executing the "special" examples
(transplanted from 75435079ca
)
2012-08-27 11:11:25 +02:00
Gael Guennebaud
e589e3f0b6 simplify eigen-doc.tgz file generation, and make it more future proof
(transplanted from aa1aa36d6d
)
2012-08-27 10:56:44 +02:00
Gael Guennebaud
66e7d02533 remove EXTRACT_ALL
(transplanted from 904c2e6cfb
)
2012-08-27 10:30:10 +02:00
Thomas Capricelli
5cde86fce8 add piwik code to documentation (web stats engine) 2012-08-21 22:39:47 +02:00
Thomas Capricelli
d0cb2b78d3 documentation script : the 3.1 branch is currently 'dox', not 'dox-devel' 2012-08-21 20:42:09 +02:00
jdh8
c0da31309d merge 2012-08-18 21:10:42 +08:00
Jitse Niesen
66c3343238 Undo incorrect fix in previous commit, and fix real mistake instead.
(transplanted from dee866a99a
)
2012-08-17 15:36:37 +01:00
Jitse Niesen
0c078ca80a Documentation fixes. Thanks to Rodney Sparapani for reporting these.
(transplanted from 5eefca637e
)
2012-08-17 14:49:18 +01:00
jdh8
87e4b10747 merge 2012-08-08 17:47:59 +08:00
Gael Guennebaud
e2886d34ef Fix precision regression when attempting to fix underflow issues.
(transplanted from af824091be
)
2012-08-05 09:57:31 +02:00
jdh8
246d12dcab Fix some typos in MatrixLogarithm to improve accuracy. 2012-08-03 23:39:15 +08:00
Desire NUENTSA
1914024965 bug #493 : multiple calls to FindUmfPack 2012-08-02 10:00:23 +02:00
Gael Guennebaud
a03c970c5c fix various regressions with MKL support
(transplanted from 8ab0e16e27
)
2012-07-28 16:32:43 +02:00
Gael Guennebaud
9f945b6028 SparseMatrix: add missing ctor for ReturnByValue
(transplanted from 7518201de8
)
2012-07-25 23:03:10 +02:00
Gael Guennebaud
4691a4e4b5 Fix aliasing issue in sparse matrix assignment.
(m=-m; or m=m.transpose(); with m sparse work again)
(transplanted from e75b1eb883
)
2012-07-25 09:33:50 +02:00
Jitse Niesen
e546ee315a Use EISPACK's strategy re max number of iters in Schur decomposition (bug #479). 2012-07-22 22:03:23 +01:00
Benoit Jacob
a63c4da68e Added tag 3.1.1 for changeset 22415b3dbb 2012-07-22 10:18:18 -04:00
Benoit Jacob
22415b3dbb bump version number 2012-07-22 10:17:54 -04:00
Desire NUENTSA
b4065b5598 bug #479 : Adjust max iterations count wrt matrix size 2012-07-16 11:31:59 +02:00
Benoit Jacob
7273feee92 add COPYING.MINPACK 2012-07-15 11:46:22 -04:00
Benoit Jacob
3a0c40de29 MINPACK license is OK for MPL2 after all 2012-07-15 10:30:57 -04:00
Benoit Jacob
d1765d98a9 add COPYING.README 2012-07-15 10:29:09 -04:00
Benoit Jacob
de23f2a27e add COPYING.MPL2 2012-07-15 10:20:59 -04:00
Benoit Jacob
48ea53288d remove outdated "Eigen itself is part of the KDE project" outside of eigen2 files 2012-07-15 10:17:45 -04:00
Gael Guennebaud
b2d857af3e document EIGEN_MPL2_ONLY
(transplanted from 54559094ec
)
2012-07-14 09:56:03 +02:00
Gael Guennebaud
98f16a6ee7 fix bug #485: conflict between a typedef and template type parameter
(transplanted from 46b1c7a0ce
)
2012-07-13 20:54:38 +02:00
Benoit Jacob
0de22418e1 Add a EIGEN_MPL2_ONLY build option to generate compiler errors when including non-MPL2 modules 2012-07-13 14:42:47 -04:00
Benoit Jacob
6072cac80e Manual MPL2 relicensing fixes 2012-07-13 14:42:47 -04:00
Benoit Jacob
132eb28e9c Automatic relicensing to MPL2 using Keirs script. Manual fixup follows. 2012-07-13 14:42:47 -04:00
Keir Mierle
0bec280dd1 Add preliminary script to relicense Eigen to MPL2. 2012-07-11 11:29:52 -07:00
Gael Guennebaud
bff29c0af9 fix computation of fixed size sub/super diagonal size
(transplanted from 3e6329a0d9
)
2012-07-10 22:39:05 +02:00
Gael Guennebaud
a1f7a87e1e Fix possible underflow issues in SelfAdjointEigenSolver
(transplanted from a2c3003be2
)
2012-07-10 09:51:26 +02:00
Gael Guennebaud
689d64156c fix compilation with MSVC 2012-07-05 21:58:01 +02:00
Gael Guennebaud
95e3e4f865 Fix bug #480: workaround the Android NDK defining isfinite as a macro
(transplanted from 5dbdde0420
)
2012-07-05 17:22:25 +02:00
Jitse Niesen
32e83f6000 doc: Typo in CustomizingEigen, introduced in previous commit.
Thanks to Christoph Hertzberg for noting this.
(transplanted from 60edf02f6f
)
2012-07-05 13:56:28 +01:00
Jitse Niesen
4a7609fa74 doc: Add constructor to example for inheritance.
See "Error in Inheriting Eigen::Vector3d" on forum.
(transplanted from b582b2ebdc
)
2012-07-05 13:36:02 +01:00
Gael Guennebaud
dee3325ef5 fix bug #486: template speacialization of member functions must be declared inline to avoid duplicate references
(transplanted from 0a7ce6ad69
)
2012-07-05 13:32:23 +02:00
Gael Guennebaud
2c88252599 fix bug #487: isometry * scaling was not compiling 2012-07-04 18:25:07 +02:00
Gael Guennebaud
7027b5a8f9 workaround compilation issue with MSVC 2005
(transplanted from eee34f2da4
)
2012-07-02 10:20:44 +02:00
Gael Guennebaud
2d45ad75ea fix implicit scalar conversion
(transplanted from 139c91bf30
)
2012-06-28 13:12:49 +02:00
Gael Guennebaud
4328afc1a5 remove dynamic allocation for fixed size object and triangular matrix-matrix products
(transplanted from 57b5804974
)
2012-06-26 17:45:01 +02:00
Gael Guennebaud
086e0aae51 Added tag 3.1.0 for changeset dd3cd5455e 2012-06-24 11:29:15 +02:00
Gael Guennebaud
dd3cd5455e fix GMRES
(transplanted from e46fc8c05c
)
2012-06-23 19:29:21 +02:00
Gael Guennebaud
9c2cc0b243 create 3.1 branch and bump to 3.1.0 2012-06-22 09:26:23 +02:00
777 changed files with 39263 additions and 59982 deletions

3
.hgeol
View File

@@ -1,9 +1,6 @@
[patterns] [patterns]
*.sh = LF
*.MINPACK = CRLF
scripts/*.in = LF scripts/*.in = LF
debug/msvc/*.dat = CRLF debug/msvc/*.dat = CRLF
debug/msvc/*.natvis = CRLF
unsupported/test/mpreal/*.* = CRLF unsupported/test/mpreal/*.* = CRLF
** = native ** = native

3
.krazy Normal file
View File

@@ -0,0 +1,3 @@
SKIP /disabled/
SKIP /bench/
SKIP /build/

View File

@@ -1,6 +1,6 @@
project(Eigen) project(Eigen)
cmake_minimum_required(VERSION 2.8.2) cmake_minimum_required(VERSION 2.6.2)
# guard against in-source builds # guard against in-source builds
@@ -105,71 +105,26 @@ if(EIGEN_DEFAULT_TO_ROW_MAJOR)
add_definitions("-DEIGEN_DEFAULT_TO_ROW_MAJOR") add_definitions("-DEIGEN_DEFAULT_TO_ROW_MAJOR")
endif() endif()
add_definitions("-DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS")
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")
macro(ei_add_cxx_compiler_flag FLAG) if(CMAKE_COMPILER_IS_GNUCXX)
string(REGEX REPLACE "-" "" SFLAG1 ${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 "\\+" "p" SFLAG ${SFLAG1})
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")
# clang outputs some warnings for unknwon flags that are not caught by check_cxx_compiler_flag check_cxx_compiler_flag("-Wno-variadic-macros" COMPILER_SUPPORT_WNOVARIADICMACRO)
# adding -Werror turns such warnings into errors if(COMPILER_SUPPORT_WNOVARIADICMACRO)
check_cxx_compiler_flag("-Werror" COMPILER_SUPPORT_WERROR) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros")
if(COMPILER_SUPPORT_WERROR)
set(CMAKE_REQUIRED_FLAGS "-Werror")
endif() endif()
ei_add_cxx_compiler_flag("-pedantic") check_cxx_compiler_flag("-Wextra" COMPILER_SUPPORT_WEXTRA)
ei_add_cxx_compiler_flag("-Wall") if(COMPILER_SUPPORT_WEXTRA)
ei_add_cxx_compiler_flag("-Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -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("-Wshorten-64-to-32")
ei_add_cxx_compiler_flag("-Wenum-conversion")
ei_add_cxx_compiler_flag("-Wc++11-extensions")
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()
set(CMAKE_REQUIRED_FLAGS "") 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)
@@ -201,18 +156,6 @@ if(NOT MSVC)
message(STATUS "Enabling SSE4.2 in tests/examples") message(STATUS "Enabling SSE4.2 in tests/examples")
endif() endif()
option(EIGEN_TEST_AVX "Enable/Disable AVX in tests/examples" OFF)
if(EIGEN_TEST_AVX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
message(STATUS "Enabling AVX in tests/examples")
endif()
option(EIGEN_TEST_FMA "Enable/Disable FMA in tests/examples" OFF)
if(EIGEN_TEST_FMA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma")
message(STATUS "Enabling FMA in tests/examples")
endif()
option(EIGEN_TEST_ALTIVEC "Enable/Disable AltiVec in tests/examples" OFF) option(EIGEN_TEST_ALTIVEC "Enable/Disable AltiVec in tests/examples" OFF)
if(EIGEN_TEST_ALTIVEC) if(EIGEN_TEST_ALTIVEC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maltivec -mabi=altivec") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maltivec -mabi=altivec")
@@ -234,8 +177,9 @@ if(NOT MSVC)
endif() endif()
endif() endif()
else(NOT MSVC) endif(CMAKE_COMPILER_IS_GNUCXX)
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
@@ -265,7 +209,7 @@ else(NOT 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(NOT MSVC) endif(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)
@@ -301,12 +245,6 @@ if(EIGEN_TEST_NO_EXPLICIT_ALIGNMENT)
message(STATUS "Disabling alignment in tests/examples") message(STATUS "Disabling alignment in tests/examples")
endif() endif()
option(EIGEN_TEST_NO_EXCEPTIONS "Disables C++ exceptions" OFF)
if(EIGEN_TEST_NO_EXCEPTIONS)
ei_add_cxx_compiler_flag("-fno-exceptions")
message(STATUS "Disabling exceptions in tests/examples")
endif()
option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF) option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
@@ -370,7 +308,6 @@ 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
@@ -405,8 +342,6 @@ 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 "")
@@ -441,31 +376,3 @@ else()
endif() endif()
message(STATUS "") message(STATUS "")
set ( EIGEN_CONFIG_CMAKE_PATH
lib${LIB_SUFFIX}/cmake/eigen3
CACHE PATH "The directory where the CMake files are installed"
)
if ( NOT IS_ABSOLUTE EIGEN_CONFIG_CMAKE_PATH )
set ( EIGEN_CONFIG_CMAKE_PATH ${CMAKE_INSTALL_PREFIX}/${EIGEN_CONFIG_CMAKE_PATH} )
endif ()
set ( EIGEN_USE_FILE ${EIGEN_CONFIG_CMAKE_PATH}/UseEigen3.cmake )
set ( EIGEN_VERSION_STRING ${EIGEN_VERSION_NUMBER} )
set ( EIGEN_VERSION_MAJOR ${EIGEN_WORLD_VERSION} )
set ( EIGEN_VERSION_MINOR ${EIGEN_MAJOR_VERSION} )
set ( EIGEN_VERSION_PATCH ${EIGEN_MINOR_VERSION} )
set ( EIGEN_DEFINITIONS "")
set ( EIGEN_INCLUDE_DIR ${INCLUDE_INSTALL_DIR} )
set ( EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR} )
set ( EIGEN_ROOT_DIR ${CMAKE_INSTALL_PREFIX} )
configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake
@ONLY ESCAPE_QUOTES
)
install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UseEigen3.cmake
${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake
DESTINATION ${EIGEN_CONFIG_CMAKE_PATH}
)

View File

@@ -4,14 +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.1")
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.1")
set(CTEST_DROP_SITE_CDASH TRUE) set(CTEST_DROP_SITE_CDASH TRUE)
set(CTEST_PROJECT_SUBPROJECTS
Official
Unsupported
)

View File

@@ -1,3 +1,4 @@
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "2000") ## A tribute to Dynamic!
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "2000") set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "33331")
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "33331")

11
Eigen/Array Normal file
View File

@@ -0,0 +1,11 @@
#ifndef EIGEN_ARRAY_MODULE_H
#define EIGEN_ARRAY_MODULE_H
// include Core first to handle Eigen2 support macros
#include "Core"
#ifndef EIGEN2_SUPPORT
#error The Eigen/Array header does no longer exist in Eigen3. All that functionality has moved to Eigen/Core.
#endif
#endif // EIGEN_ARRAY_MODULE_H

View File

@@ -10,11 +10,9 @@
* *
* *
* This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices. * This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
* Those decompositions are also accessible via the following methods: * Those decompositions are accessible via the following MatrixBase methods:
* - MatrixBase::llt() * - MatrixBase::llt(),
* - MatrixBase::ldlt() * - MatrixBase::ldlt()
* - SelfAdjointView::llt()
* - SelfAdjointView::ldlt()
* *
* \code * \code
* #include <Eigen/Cholesky> * #include <Eigen/Cholesky>

View File

@@ -14,53 +14,11 @@
// first thing Eigen does: stop the compiler from committing suicide // first thing Eigen does: stop the compiler from committing suicide
#include "src/Core/util/DisableStupidWarnings.h" #include "src/Core/util/DisableStupidWarnings.h"
// Handle NVCC/CUDA
#ifdef __CUDACC__
// Do not try asserts on CUDA!
#ifndef EIGEN_NO_DEBUG
#define EIGEN_NO_DEBUG
#endif
#ifdef EIGEN_INTERNAL_DEBUGGING
#undef EIGEN_INTERNAL_DEBUGGING
#endif
// Do not try to vectorize on CUDA!
#define EIGEN_DONT_VECTORIZE
// All functions callable from CUDA code must be qualified with __device__
#define EIGEN_DEVICE_FUNC __host__ __device__
#else
#define EIGEN_DEVICE_FUNC
#endif
#if defined(__CUDA_ARCH__)
#define EIGEN_USING_STD_MATH(FUNC) using ::FUNC;
#else
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
#endif
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) && !defined(EIGEN_EXCEPTIONS)
#define EIGEN_EXCEPTIONS
#endif
#ifdef EIGEN_EXCEPTIONS
#include <new>
#endif
// then include this file where all our macros are defined. It's really important to do it first because // then include this file where all our macros are defined. It's really important to do it first because
// it's where we do all the alignment settings (platform detection and honoring the user's will if he // it's where we do all the alignment settings (platform detection and honoring the user's will if he
// 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
@@ -118,16 +76,7 @@
#ifdef __SSE4_2__ #ifdef __SSE4_2__
#define EIGEN_VECTORIZE_SSE4_2 #define EIGEN_VECTORIZE_SSE4_2
#endif #endif
#ifdef __AVX__
#define EIGEN_VECTORIZE_AVX
#define EIGEN_VECTORIZE_SSE3
#define EIGEN_VECTORIZE_SSSE3
#define EIGEN_VECTORIZE_SSE4_1
#define EIGEN_VECTORIZE_SSE4_2
#endif
#ifdef __FMA__
#define EIGEN_VECTORIZE_FMA
#endif
// include files // include files
// This extern "C" works around a MINGW-w64 compilation issue // This extern "C" works around a MINGW-w64 compilation issue
@@ -138,11 +87,6 @@
// so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too. // so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too.
// notice that since these are C headers, the extern "C" is theoretically needed anyways. // notice that since these are C headers, the extern "C" is theoretically needed anyways.
extern "C" { extern "C" {
// 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:
#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1110
#include <immintrin.h>
#else
#include <emmintrin.h> #include <emmintrin.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#ifdef EIGEN_VECTORIZE_SSE3 #ifdef EIGEN_VECTORIZE_SSE3
@@ -157,10 +101,6 @@
#ifdef EIGEN_VECTORIZE_SSE4_2 #ifdef EIGEN_VECTORIZE_SSE4_2
#include <nmmintrin.h> #include <nmmintrin.h>
#endif #endif
#ifdef EIGEN_VECTORIZE_AVX
#include <immintrin.h>
#endif
#endif
} // end extern "C" } // end extern "C"
#elif defined __ALTIVEC__ #elif defined __ALTIVEC__
#define EIGEN_VECTORIZE #define EIGEN_VECTORIZE
@@ -213,17 +153,23 @@
#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)) && (!defined(_WIN32_WCE)) #if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64))
#include <intrin.h> #include <intrin.h>
#endif #endif
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS)
#define EIGEN_EXCEPTIONS
#endif
#ifdef EIGEN_EXCEPTIONS
#include <new>
#endif
/** \brief Namespace containing all symbols from the %Eigen library. */ /** \brief Namespace containing all symbols from the %Eigen library. */
namespace Eigen { namespace Eigen {
inline static const char *SimdInstructionSetsInUse(void) { inline static const char *SimdInstructionSetsInUse(void) {
#if defined(EIGEN_VECTORIZE_AVX) #if defined(EIGEN_VECTORIZE_SSE4_2)
return "AVX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
#elif defined(EIGEN_VECTORIZE_SSE4_2)
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2"; return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
#elif defined(EIGEN_VECTORIZE_SSE4_1) #elif defined(EIGEN_VECTORIZE_SSE4_1)
return "SSE, SSE2, SSE3, SSSE3, SSE4.1"; return "SSE, SSE2, SSE3, SSSE3, SSE4.1";
@@ -244,9 +190,34 @@ inline static const char *SimdInstructionSetsInUse(void) {
} // end namespace Eigen } // end namespace Eigen
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS || defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API || defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS || defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API || defined EIGEN2_SUPPORT #define STAGE10_FULL_EIGEN2_API 10
// This will generate an error message: #define STAGE20_RESOLVE_API_CONFLICTS 20
#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information #define STAGE30_FULL_EIGEN3_API 30
#define STAGE40_FULL_EIGEN3_STRICTNESS 40
#define STAGE99_NO_EIGEN2_SUPPORT 99
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS
#define EIGEN2_SUPPORT
#define EIGEN2_SUPPORT_STAGE STAGE40_FULL_EIGEN3_STRICTNESS
#elif defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
#define EIGEN2_SUPPORT
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
#elif defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS
#define EIGEN2_SUPPORT
#define EIGEN2_SUPPORT_STAGE STAGE20_RESOLVE_API_CONFLICTS
#elif defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API
#define EIGEN2_SUPPORT
#define EIGEN2_SUPPORT_STAGE STAGE10_FULL_EIGEN2_API
#elif defined EIGEN2_SUPPORT
// default to stage 3, that's what it's always meant
#define EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
#else
#define EIGEN2_SUPPORT_STAGE STAGE99_NO_EIGEN2_SUPPORT
#endif
#ifdef EIGEN2_SUPPORT
#undef minor
#endif #endif
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to // we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
@@ -265,24 +236,22 @@ using std::ptrdiff_t;
* \endcode * \endcode
*/ */
/** \defgroup Support_modules Support modules [category]
* Category of modules which add support for external libraries.
*/
#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/StaticAssert.h"
#include "src/Core/util/XprHelper.h" #include "src/Core/util/XprHelper.h"
#include "src/Core/util/StaticAssert.h"
#include "src/Core/util/Memory.h" #include "src/Core/util/Memory.h"
#include "src/Core/NumTraits.h" #include "src/Core/NumTraits.h"
#include "src/Core/MathFunctions.h" #include "src/Core/MathFunctions.h"
#include "src/Core/GenericPacketMath.h" #include "src/Core/GenericPacketMath.h"
#if defined EIGEN_VECTORIZE_AVX #if defined EIGEN_VECTORIZE_SSE
// Use AVX for floats and doubles, SSE for integers
#include "src/Core/arch/SSE/PacketMath.h"
#include "src/Core/arch/SSE/Complex.h"
#include "src/Core/arch/AVX/PacketMath.h"
#include "src/Core/arch/AVX/Complex.h"
#elif defined EIGEN_VECTORIZE_SSE
#include "src/Core/arch/SSE/PacketMath.h" #include "src/Core/arch/SSE/PacketMath.h"
#include "src/Core/arch/SSE/MathFunctions.h" #include "src/Core/arch/SSE/MathFunctions.h"
#include "src/Core/arch/SSE/Complex.h" #include "src/Core/arch/SSE/Complex.h"
@@ -296,30 +265,17 @@ using std::ptrdiff_t;
#include "src/Core/arch/Default/Settings.h" #include "src/Core/arch/Default/Settings.h"
#include "src/Core/functors/BinaryFunctors.h" #include "src/Core/Functors.h"
#include "src/Core/functors/UnaryFunctors.h"
#include "src/Core/functors/NullaryFunctors.h"
#include "src/Core/functors/StlFunctors.h"
#include "src/Core/DenseCoeffsBase.h" #include "src/Core/DenseCoeffsBase.h"
#include "src/Core/DenseBase.h" #include "src/Core/DenseBase.h"
#include "src/Core/MatrixBase.h" #include "src/Core/MatrixBase.h"
#include "src/Core/EigenBase.h" #include "src/Core/EigenBase.h"
#ifdef EIGEN_ENABLE_EVALUATORS
#include "src/Core/functors/AssignmentFunctors.h"
#include "src/Core/Product.h"
#include "src/Core/CoreEvaluators.h"
#include "src/Core/AssignEvaluator.h"
#include "src/Core/ProductEvaluators.h"
#endif
#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874 #ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
// at least confirmed with Doxygen 1.5.5 and 1.5.6 // at least confirmed with Doxygen 1.5.5 and 1.5.6
#include "src/Core/Assign.h" #include "src/Core/Assign.h"
#endif #endif
#include "src/Core/ArrayBase.h"
#include "src/Core/util/BlasUtil.h" #include "src/Core/util/BlasUtil.h"
#include "src/Core/DenseStorage.h" #include "src/Core/DenseStorage.h"
#include "src/Core/NestByValue.h" #include "src/Core/NestByValue.h"
@@ -341,7 +297,6 @@ using std::ptrdiff_t;
#include "src/Core/Map.h" #include "src/Core/Map.h"
#include "src/Core/Block.h" #include "src/Core/Block.h"
#include "src/Core/VectorBlock.h" #include "src/Core/VectorBlock.h"
#include "src/Core/Ref.h"
#include "src/Core/Transpose.h" #include "src/Core/Transpose.h"
#include "src/Core/DiagonalMatrix.h" #include "src/Core/DiagonalMatrix.h"
#include "src/Core/Diagonal.h" #include "src/Core/Diagonal.h"
@@ -375,7 +330,6 @@ using std::ptrdiff_t;
#include "src/Core/products/TriangularSolverMatrix.h" #include "src/Core/products/TriangularSolverMatrix.h"
#include "src/Core/products/TriangularSolverVector.h" #include "src/Core/products/TriangularSolverVector.h"
#include "src/Core/BandMatrix.h" #include "src/Core/BandMatrix.h"
#include "src/Core/CoreIterators.h"
#include "src/Core/BooleanRedux.h" #include "src/Core/BooleanRedux.h"
#include "src/Core/Select.h" #include "src/Core/Select.h"
@@ -383,6 +337,7 @@ using std::ptrdiff_t;
#include "src/Core/Random.h" #include "src/Core/Random.h"
#include "src/Core/Replicate.h" #include "src/Core/Replicate.h"
#include "src/Core/Reverse.h" #include "src/Core/Reverse.h"
#include "src/Core/ArrayBase.h"
#include "src/Core/ArrayWrapper.h" #include "src/Core/ArrayWrapper.h"
#ifdef EIGEN_USE_BLAS #ifdef EIGEN_USE_BLAS
@@ -404,4 +359,8 @@ using std::ptrdiff_t;
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"
#ifdef EIGEN2_SUPPORT
#include "Eigen2Support"
#endif
#endif // EIGEN_CORE_H #endif // EIGEN_CORE_H

View File

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

82
Eigen/Eigen2Support Normal file
View File

@@ -0,0 +1,82 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 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 EIGEN2SUPPORT_H
#define EIGEN2SUPPORT_H
#if (!defined(EIGEN2_SUPPORT)) || (!defined(EIGEN_CORE_H))
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
#endif
#include "src/Core/util/DisableStupidWarnings.h"
/** \ingroup Support_modules
* \defgroup Eigen2Support_Module Eigen2 support module
* This module provides a couple of deprecated functions improving the compatibility with Eigen2.
*
* To use it, define EIGEN2_SUPPORT before including any Eigen header
* \code
* #define EIGEN2_SUPPORT
* \endcode
*
*/
#include "src/Eigen2Support/Macros.h"
#include "src/Eigen2Support/Memory.h"
#include "src/Eigen2Support/Meta.h"
#include "src/Eigen2Support/Lazy.h"
#include "src/Eigen2Support/Cwise.h"
#include "src/Eigen2Support/CwiseOperators.h"
#include "src/Eigen2Support/TriangularSolver.h"
#include "src/Eigen2Support/Block.h"
#include "src/Eigen2Support/VectorBlock.h"
#include "src/Eigen2Support/Minor.h"
#include "src/Eigen2Support/MathFunctions.h"
#include "src/Core/util/ReenableStupidWarnings.h"
// Eigen2 used to include iostream
#include<iostream>
#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
using Eigen::Matrix##SizeSuffix##TypeSuffix; \
using Eigen::Vector##SizeSuffix##TypeSuffix; \
using Eigen::RowVector##SizeSuffix##TypeSuffix;
#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
#define EIGEN_USING_MATRIX_TYPEDEFS \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd)
#define USING_PART_OF_NAMESPACE_EIGEN \
EIGEN_USING_MATRIX_TYPEDEFS \
using Eigen::Matrix; \
using Eigen::MatrixBase; \
using Eigen::ei_random; \
using Eigen::ei_real; \
using Eigen::ei_imag; \
using Eigen::ei_conj; \
using Eigen::ei_abs; \
using Eigen::ei_abs2; \
using Eigen::ei_sqrt; \
using Eigen::ei_exp; \
using Eigen::ei_log; \
using Eigen::ei_sin; \
using Eigen::ei_cos;
#endif // EIGEN2SUPPORT_H

View File

@@ -33,8 +33,6 @@
#include "src/Eigenvalues/HessenbergDecomposition.h" #include "src/Eigenvalues/HessenbergDecomposition.h"
#include "src/Eigenvalues/ComplexSchur.h" #include "src/Eigenvalues/ComplexSchur.h"
#include "src/Eigenvalues/ComplexEigenSolver.h" #include "src/Eigenvalues/ComplexEigenSolver.h"
#include "src/Eigenvalues/RealQZ.h"
#include "src/Eigenvalues/GeneralizedEigenSolver.h"
#include "src/Eigenvalues/MatrixBaseEigenvalues.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h"
#ifdef EIGEN_USE_LAPACKE #ifdef EIGEN_USE_LAPACKE
#include "src/Eigenvalues/RealSchur_MKL.h" #include "src/Eigenvalues/RealSchur_MKL.h"

View File

@@ -33,6 +33,7 @@
#include "src/Geometry/OrthoMethods.h" #include "src/Geometry/OrthoMethods.h"
#include "src/Geometry/EulerAngles.h" #include "src/Geometry/EulerAngles.h"
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
#include "src/Geometry/Homogeneous.h" #include "src/Geometry/Homogeneous.h"
#include "src/Geometry/RotationBase.h" #include "src/Geometry/RotationBase.h"
#include "src/Geometry/Rotation2D.h" #include "src/Geometry/Rotation2D.h"
@@ -46,11 +47,14 @@
#include "src/Geometry/AlignedBox.h" #include "src/Geometry/AlignedBox.h"
#include "src/Geometry/Umeyama.h" #include "src/Geometry/Umeyama.h"
// Use the SSE optimized version whenever possible. At the moment the #if defined EIGEN_VECTORIZE_SSE
// SSE version doesn't compile when AVX is enabled
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
#include "src/Geometry/arch/Geometry_SSE.h" #include "src/Geometry/arch/Geometry_SSE.h"
#endif #endif
#endif
#ifdef EIGEN2_SUPPORT
#include "src/Eigen2Support/Geometry/All.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"

View File

@@ -6,7 +6,7 @@
#include "src/Core/util/DisableStupidWarnings.h" #include "src/Core/util/DisableStupidWarnings.h"
/** /** \ingroup Sparse_modules
* \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module * \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module
* *
* This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a squared matrix, usually very large and sparse. * This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a squared matrix, usually very large and sparse.

View File

@@ -27,12 +27,14 @@
#include "src/LU/Determinant.h" #include "src/LU/Determinant.h"
#include "src/LU/Inverse.h" #include "src/LU/Inverse.h"
// Use the SSE optimized version whenever possible. At the moment the #if defined EIGEN_VECTORIZE_SSE
// SSE version doesn't compile when AVX is enabled
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
#include "src/LU/arch/Inverse_SSE.h" #include "src/LU/arch/Inverse_SSE.h"
#endif #endif
#ifdef EIGEN2_SUPPORT
#include "src/Eigen2Support/LU.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_LU_MODULE_H #endif // EIGEN_LU_MODULE_H

32
Eigen/LeastSquares Normal file
View File

@@ -0,0 +1,32 @@
#ifndef EIGEN_REGRESSION_MODULE_H
#define EIGEN_REGRESSION_MODULE_H
#ifndef EIGEN2_SUPPORT
#error LeastSquares is only available in Eigen2 support mode (define EIGEN2_SUPPORT)
#endif
// exclude from normal eigen3-only documentation
#ifdef EIGEN2_SUPPORT
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
#include "Eigenvalues"
#include "Geometry"
/** \defgroup LeastSquares_Module LeastSquares module
* This module provides linear regression and related features.
*
* \code
* #include <Eigen/LeastSquares>
* \endcode
*/
#include "src/Eigen2Support/LeastSquares.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN2_SUPPORT
#endif // EIGEN_REGRESSION_MODULE_H

View File

@@ -1,28 +0,0 @@
#ifndef EIGEN_METISSUPPORT_MODULE_H
#define EIGEN_METISSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
extern "C" {
#include <metis.h>
}
/** \ingroup Support_modules
* \defgroup MetisSupport_Module MetisSupport module
*
* \code
* #include <Eigen/MetisSupport>
* \endcode
* This module defines an interface to the METIS reordering package (http://glaros.dtc.umn.edu/gkhome/views/metis).
* It can be used just as any other built-in method as explained in \link OrderingMethods_Module here. \endlink
*/
#include "src/MetisSupport/MetisSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_METISSUPPORT_MODULE_H

View File

@@ -5,62 +5,19 @@
#include "src/Core/util/DisableStupidWarnings.h" #include "src/Core/util/DisableStupidWarnings.h"
/** /** \ingroup Sparse_modules
* \defgroup OrderingMethods_Module OrderingMethods module * \defgroup OrderingMethods_Module OrderingMethods module
* *
* This module is currently for internal use only * This module is currently for internal use only.
*
* It defines various built-in and external ordering methods for sparse matrices.
* They are typically used to reduce the number of elements during
* the sparse matrix decomposition (LLT, LU, QR).
* Precisely, in a preprocessing step, a permutation matrix P is computed using
* those ordering methods and applied to the columns of the matrix.
* Using for instance the sparse Cholesky decomposition, it is expected that
* the nonzeros elements in LLT(A*P) will be much smaller than that in LLT(A).
* *
* *
* Usage :
* \code * \code
* #include <Eigen/OrderingMethods> * #include <Eigen/OrderingMethods>
* \endcode * \endcode
*
* A simple usage is as a template parameter in the sparse decomposition classes :
*
* \code
* SparseLU<MatrixType, COLAMDOrdering<int> > solver;
* \endcode
*
* \code
* SparseQR<MatrixType, COLAMDOrdering<int> > solver;
* \endcode
*
* It is possible as well to call directly a particular ordering method for your own purpose,
* \code
* AMDOrdering<int> ordering;
* PermutationMatrix<Dynamic, Dynamic, int> perm;
* SparseMatrix<double> A;
* //Fill the matrix ...
*
* ordering(A, perm); // Call AMD
* \endcode
*
* \note Some of these methods (like AMD or METIS), need the sparsity pattern
* of the input matrix to be symmetric. When the matrix is structurally unsymmetric,
* Eigen computes internally the pattern of \f$A^T*A\f$ before calling the method.
* If your matrix is already symmetric (at leat in structure), you can avoid that
* by calling the method with a SelfAdjointView type.
*
* \code
* // Call the ordering on the pattern of the lower triangular matrix A
* ordering(A.selfadjointView<Lower>(), perm);
* \endcode
*/ */
#ifndef EIGEN_MPL2_ONLY
#include "src/OrderingMethods/Amd.h" #include "src/OrderingMethods/Amd.h"
#endif
#include "src/OrderingMethods/Ordering.h"
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_ORDERINGMETHODS_MODULE_H #endif // EIGEN_ORDERINGMETHODS_MODULE_H

View File

@@ -15,9 +15,7 @@
* *
* This module provides various QR decompositions * This module provides various QR decompositions
* This module also provides some MatrixBase methods, including: * This module also provides some MatrixBase methods, including:
* - MatrixBase::householderQr() * - MatrixBase::qr(),
* - MatrixBase::colPivHouseholderQr()
* - MatrixBase::fullPivHouseholderQr()
* *
* \code * \code
* #include <Eigen/QR> * #include <Eigen/QR>
@@ -33,7 +31,15 @@
#include "src/QR/ColPivHouseholderQR_MKL.h" #include "src/QR/ColPivHouseholderQR_MKL.h"
#endif #endif
#ifdef EIGEN2_SUPPORT
#include "src/Eigen2Support/QR.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"
#ifdef EIGEN2_SUPPORT
#include "Eigenvalues"
#endif
#endif // EIGEN_QR_MODULE_H #endif // EIGEN_QR_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */ /* vim: set filetype=cpp et sw=2 ts=2 ai: */

View File

@@ -1,29 +0,0 @@
#ifndef EIGEN_SPQRSUPPORT_MODULE_H
#define EIGEN_SPQRSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
#include "SuiteSparseQR.hpp"
/** \ingroup Support_modules
* \defgroup SPQRSupport_Module SuiteSparseQR module
*
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.cise.ufl.edu/research/sparse/SuiteSparse/">suitesparse</a> package.
*
* \code
* #include <Eigen/SPQRSupport>
* \endcode
*
* In order to use this module, the SPQR headers must be accessible from the include paths, and your binary must be linked to the SPQR library and its dependencies (Cholmod, AMD, COLAMD,...).
* For a cmake based project, you can use our FindSPQR.cmake and FindCholmod.Cmake modules
*
*/
#include "src/misc/Solve.h"
#include "src/misc/SparseSolve.h"
#include "src/CholmodSupport/CholmodSupport.h"
#include "src/SPQRSupport/SuiteSparseQRSupport.h"
#endif

View File

@@ -21,13 +21,16 @@
*/ */
#include "src/misc/Solve.h" #include "src/misc/Solve.h"
#include "src/SVD/SVDBase.h"
#include "src/SVD/JacobiSVD.h" #include "src/SVD/JacobiSVD.h"
#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT) #if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT)
#include "src/SVD/JacobiSVD_MKL.h" #include "src/SVD/JacobiSVD_MKL.h"
#endif #endif
#include "src/SVD/UpperBidiagonalization.h" #include "src/SVD/UpperBidiagonalization.h"
#ifdef EIGEN2_SUPPORT
#include "src/Eigen2Support/SVD.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SVD_MODULE_H #endif // EIGEN_SVD_MODULE_H

View File

@@ -1,15 +1,13 @@
#ifndef EIGEN_SPARSE_MODULE_H #ifndef EIGEN_SPARSE_MODULE_H
#define EIGEN_SPARSE_MODULE_H #define EIGEN_SPARSE_MODULE_H
/** \defgroup Sparse_Module Sparse meta-module /** \defgroup Sparse_modules Sparse modules
* *
* Meta-module including all related modules: * Meta-module including all related modules:
* - \ref SparseCore_Module * - SparseCore
* - \ref OrderingMethods_Module * - OrderingMethods
* - \ref SparseCholesky_Module * - SparseCholesky
* - \ref SparseLU_Module * - IterativeLinearSolvers
* - \ref SparseQR_Module
* - \ref IterativeLinearSolvers_Module
* *
* \code * \code
* #include <Eigen/Sparse> * #include <Eigen/Sparse>
@@ -19,8 +17,6 @@
#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

View File

@@ -1,12 +1,3 @@
// 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
@@ -15,7 +6,7 @@
#include "src/Core/util/DisableStupidWarnings.h" #include "src/Core/util/DisableStupidWarnings.h"
/** /** \ingroup Sparse_modules
* \defgroup SparseCholesky_Module SparseCholesky module * \defgroup SparseCholesky_Module SparseCholesky module
* *
* This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) matrices. * This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) matrices.
@@ -30,17 +21,10 @@
* \endcode * \endcode
*/ */
#ifdef EIGEN_MPL2_ONLY
#error The SparseCholesky module has nothing to offer in MPL2 only mode
#endif
#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"
#ifndef EIGEN_MPL2_ONLY #include "src/SparseCholesky/SimplicialCholesky.h"
#include "src/SparseCholesky/SimplicialCholesky_impl.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h" #include "src/Core/util/ReenableStupidWarnings.h"

View File

@@ -11,7 +11,7 @@
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
/** /** \ingroup Sparse_modules
* \defgroup SparseCore_Module SparseCore module * \defgroup SparseCore_Module SparseCore module
* *
* This module provides a sparse matrix representation, and basic associatd matrix manipulations * This module provides a sparse matrix representation, and basic associatd matrix manipulations
@@ -40,12 +40,14 @@ struct Sparse {};
#include "src/SparseCore/SparseMatrix.h" #include "src/SparseCore/SparseMatrix.h"
#include "src/SparseCore/MappedSparseMatrix.h" #include "src/SparseCore/MappedSparseMatrix.h"
#include "src/SparseCore/SparseVector.h" #include "src/SparseCore/SparseVector.h"
#include "src/SparseCore/CoreIterators.h"
#include "src/SparseCore/SparseBlock.h" #include "src/SparseCore/SparseBlock.h"
#include "src/SparseCore/SparseTranspose.h" #include "src/SparseCore/SparseTranspose.h"
#include "src/SparseCore/SparseCwiseUnaryOp.h" #include "src/SparseCore/SparseCwiseUnaryOp.h"
#include "src/SparseCore/SparseCwiseBinaryOp.h" #include "src/SparseCore/SparseCwiseBinaryOp.h"
#include "src/SparseCore/SparseDot.h" #include "src/SparseCore/SparseDot.h"
#include "src/SparseCore/SparsePermutation.h" #include "src/SparseCore/SparsePermutation.h"
#include "src/SparseCore/SparseAssign.h"
#include "src/SparseCore/SparseRedux.h" #include "src/SparseCore/SparseRedux.h"
#include "src/SparseCore/SparseFuzzy.h" #include "src/SparseCore/SparseFuzzy.h"
#include "src/SparseCore/ConservativeSparseSparseProduct.h" #include "src/SparseCore/ConservativeSparseSparseProduct.h"

View File

@@ -1,49 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
// Copyright (C) 2012 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_SPARSELU_MODULE_H
#define EIGEN_SPARSELU_MODULE_H
#include "SparseCore"
/**
* \defgroup SparseLU_Module SparseLU module
* This module defines a supernodal factorization of general sparse matrices.
* The code is fully optimized for supernode-panel updates with specialized kernels.
* Please, see the documentation of the SparseLU class for more details.
*/
#include "src/misc/Solve.h"
#include "src/misc/SparseSolve.h"
// Ordering interface
#include "OrderingMethods"
#include "src/SparseLU/SparseLU_gemm_kernel.h"
#include "src/SparseLU/SparseLU_Structs.h"
#include "src/SparseLU/SparseLU_SupernodalMatrix.h"
#include "src/SparseLU/SparseLUImpl.h"
#include "src/SparseCore/SparseColEtree.h"
#include "src/SparseLU/SparseLU_Memory.h"
#include "src/SparseLU/SparseLU_heap_relax_snode.h"
#include "src/SparseLU/SparseLU_relax_snode.h"
#include "src/SparseLU/SparseLU_pivotL.h"
#include "src/SparseLU/SparseLU_panel_dfs.h"
#include "src/SparseLU/SparseLU_kernel_bmod.h"
#include "src/SparseLU/SparseLU_panel_bmod.h"
#include "src/SparseLU/SparseLU_column_dfs.h"
#include "src/SparseLU/SparseLU_column_bmod.h"
#include "src/SparseLU/SparseLU_copy_to_ucol.h"
#include "src/SparseLU/SparseLU_pruneL.h"
#include "src/SparseLU/SparseLU_Utils.h"
#include "src/SparseLU/SparseLU.h"
#endif // EIGEN_SPARSELU_MODULE_H

View File

@@ -1,33 +0,0 @@
#ifndef EIGEN_SPARSEQR_MODULE_H
#define EIGEN_SPARSEQR_MODULE_H
#include "SparseCore"
#include "OrderingMethods"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup SparseQR_Module SparseQR module
* \brief Provides QR decomposition for sparse matrices
*
* This module provides a simplicial version of the left-looking Sparse QR decomposition.
* The columns of the input matrix should be reordered to limit the fill-in during the
* decomposition. Built-in methods (COLAMD, AMD) or external methods (METIS) can be used to this end.
* See the \link OrderingMethods_Module OrderingMethods\endlink module for the list
* of built-in and external ordering methods.
*
* \code
* #include <Eigen/SparseQR>
* \endcode
*
*
*/
#include "src/misc/Solve.h"
#include "src/misc/SparseSolve.h"
#include "OrderingMethods"
#include "src/SparseCore/SparseColEtree.h"
#include "src/SparseQR/SparseQR.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif

View File

@@ -17,9 +17,6 @@ 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
@@ -43,7 +40,7 @@ namespace internal {
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky * Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
* decomposition to determine whether a system of equations has a solution. * decomposition to determine whether a system of equations has a solution.
* *
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt(), class LLT * \sa MatrixBase::ldlt(), class LLT
*/ */
template<typename _MatrixType, int _UpLo> class LDLT template<typename _MatrixType, int _UpLo> class LDLT
{ {
@@ -72,12 +69,7 @@ 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() LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {}
: m_matrix(),
m_transpositions(),
m_sign(internal::ZeroSign),
m_isInitialized(false)
{}
/** \brief Default Constructor with memory preallocation /** \brief Default Constructor with memory preallocation
* *
@@ -89,7 +81,6 @@ 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)
{} {}
@@ -102,7 +93,6 @@ 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);
@@ -149,14 +139,21 @@ 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 == internal::PositiveSemiDef || m_sign == internal::ZeroSign; return m_sign == 1;
} }
#ifdef EIGEN2_SUPPORT
inline bool isPositiveDefinite() const
{
return isPositive();
}
#endif
/** \returns true if the matrix is negative (semidefinite) */ /** \returns true if the matrix is negative (semidefinite) */
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 == internal::NegativeSemiDef || m_sign == internal::ZeroSign; return m_sign == -1;
} }
/** \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.
@@ -172,7 +169,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
* least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function * least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function
* computes the least-square solution of \f$ A x = b \f$ is \f$ A \f$ is singular. * computes the least-square solution of \f$ A x = b \f$ is \f$ A \f$ is singular.
* *
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt() * \sa MatrixBase::ldlt()
*/ */
template<typename Rhs> template<typename Rhs>
inline const internal::solve_retval<LDLT, Rhs> inline const internal::solve_retval<LDLT, Rhs>
@@ -184,13 +181,22 @@ template<typename _MatrixType, int _UpLo> class LDLT
return internal::solve_retval<LDLT, Rhs>(*this, b.derived()); return internal::solve_retval<LDLT, Rhs>(*this, b.derived());
} }
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived, typename ResultType>
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
{
*result = this->solve(b);
return true;
}
#endif
template<typename Derived> template<typename Derived>
bool solveInPlace(MatrixBase<Derived> &bAndX) const; bool solveInPlace(MatrixBase<Derived> &bAndX) const;
LDLT& compute(const MatrixType& matrix); LDLT& compute(const MatrixType& matrix);
template <typename Derived> template <typename Derived>
LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1); LDLT& rankUpdate(const MatrixBase<Derived>& w,RealScalar alpha=1);
/** \returns the internal LDLT decomposition matrix /** \returns the internal LDLT decomposition matrix
* *
@@ -229,7 +235,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;
internal::SignMatrix m_sign; int m_sign;
bool m_isInitialized; bool m_isInitialized;
}; };
@@ -240,33 +246,48 @@ 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, SignMatrix& sign) static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
{ {
using std::abs;
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;
typedef typename TranspositionType::StorageIndexType IndexType;
eigen_assert(mat.rows()==mat.cols()); eigen_assert(mat.rows()==mat.cols());
const Index size = mat.rows(); const Index size = mat.rows();
if (size <= 1) if (size <= 1)
{ {
transpositions.setIdentity(); transpositions.setIdentity();
if (numext::real(mat.coeff(0,0)) > 0) sign = PositiveSemiDef; if(sign)
else if (numext::real(mat.coeff(0,0)) < 0) sign = NegativeSemiDef; *sign = real(mat.coeff(0,0))>0 ? 1:-1;
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;
mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner); 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;
transpositions.coeffRef(k) = IndexType(index_of_biggest_in_corner); 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);
}
// 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;
if(sign) *sign = 0;
break;
}
transpositions.coeffRef(k) = index_of_biggest_in_corner;
if(k != index_of_biggest_in_corner) if(k != index_of_biggest_in_corner)
{ {
// apply the transposition while taking care to consider only // apply the transposition while taking care to consider only
@@ -275,14 +296,14 @@ template<> struct ldlt_inplace<Lower>
mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k)); mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s)); mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner)); std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
for(Index 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) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i)); mat.coeffRef(i,k) = conj(mat.coeffRef(index_of_biggest_in_corner,i));
mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp); mat.coeffRef(index_of_biggest_in_corner,i) = conj(tmp);
} }
if(NumTraits<Scalar>::IsComplex) if(NumTraits<Scalar>::IsComplex)
mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k)); mat.coeffRef(index_of_biggest_in_corner,k) = conj(mat.coeff(index_of_biggest_in_corner,k));
} }
// partition the matrix: // partition the matrix:
@@ -296,27 +317,22 @@ template<> struct ldlt_inplace<Lower>
if(k>0) if(k>0)
{ {
temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint(); temp.head(k) = mat.diagonal().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 if(sign)
// 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. // LDLT is not guaranteed to work for indefinite matrices, but let's try to get the sign right
// LAPACK also uses 0 as the cutoff value. int newSign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0;
RealScalar realAkk = numext::real(mat.coeffRef(k,k)); if(k == 0)
if((rs>0) && (abs(realAkk) > RealScalar(0))) *sign = newSign;
A21 /= realAkk; else if(*sign != newSign)
*sign = 0;
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;
} }
} }
@@ -331,9 +347,9 @@ template<> struct ldlt_inplace<Lower>
// Here only rank-1 updates are implemented, to reduce the // Here only rank-1 updates are implemented, to reduce the
// requirement for intermediate storage and improve accuracy // requirement for intermediate storage and improve accuracy
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, typename MatrixType::RealScalar sigma=1)
{ {
using numext::isfinite; using internal::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;
@@ -351,9 +367,9 @@ template<> struct ldlt_inplace<Lower>
break; break;
// Update the diagonal terms // Update the diagonal terms
RealScalar dj = numext::real(mat.coeff(j,j)); RealScalar dj = real(mat.coeff(j,j));
Scalar wj = w.coeff(j); Scalar wj = w.coeff(j);
RealScalar swj2 = sigma*numext::abs2(wj); RealScalar swj2 = sigma*abs2(wj);
RealScalar gamma = dj*alpha + swj2; RealScalar gamma = dj*alpha + swj2;
mat.coeffRef(j,j) += swj2/alpha; mat.coeffRef(j,j) += swj2/alpha;
@@ -364,13 +380,13 @@ 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*numext::conj(wj)/gamma)*w.tail(rs); mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs);
} }
return true; return true;
} }
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType> template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1) static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, typename MatrixType::RealScalar sigma=1)
{ {
// Apply the permutation to the input w // Apply the permutation to the input w
tmp = transpositions * w; tmp = transpositions * w;
@@ -382,14 +398,14 @@ 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, SignMatrix& sign) static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
{ {
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);
} }
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType> template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1) static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, typename MatrixType::RealScalar sigma=1)
{ {
Transpose<MatrixType> matt(mat); Transpose<MatrixType> matt(mat);
return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma); return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
@@ -428,7 +444,7 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
m_isInitialized = false; m_isInitialized = false;
m_temporary.resize(size); m_temporary.resize(size);
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;
@@ -441,9 +457,8 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
*/ */
template<typename MatrixType, int _UpLo> template<typename MatrixType, int _UpLo>
template<typename Derived> template<typename Derived>
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename NumTraits<typename MatrixType::Scalar>::Real& sigma) LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w,typename NumTraits<typename MatrixType::Scalar>::Real sigma)
{ {
typedef typename TranspositionType::StorageIndexType IndexType;
const Index size = w.rows(); const Index size = w.rows();
if (m_isInitialized) if (m_isInitialized)
{ {
@@ -455,9 +470,9 @@ LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Deri
m_matrix.setZero(); m_matrix.setZero();
m_transpositions.resize(size); m_transpositions.resize(size);
for (Index i = 0; i < size; i++) for (Index i = 0; i < size; i++)
m_transpositions.coeffRef(i) = IndexType(i); m_transpositions.coeffRef(i) = i;
m_temporary.resize(size); m_temporary.resize(size);
m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef; m_sign = sigma>=0 ? 1 : -1;
m_isInitialized = true; m_isInitialized = true;
} }
@@ -486,17 +501,13 @@ struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
// dst = D^-1 (L^-1 P b) // dst = D^-1 (L^-1 P b)
// more precisely, use pseudo-inverse of D (see bug 241) // more precisely, use pseudo-inverse of D (see bug 241)
using std::abs; using std::abs;
EIGEN_USING_STD_MATH(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 typename Diagonal<const MatrixType>::RealReturnType vectorD(dec().vectorD()); const Diagonal<const MatrixType> vectorD = dec().vectorD();
// In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(),
// as motivated by LAPACK's xGELSS: RealScalar(1) / NumTraits<RealScalar>::highest()); // 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);
@@ -554,7 +565,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().real().asDiagonal() * res; res = vectorD().asDiagonal() * res;
// L(DL^*P) // L(DL^*P)
res = matrixL() * res; res = matrixL() * res;
// P^T (LDL^*P) // P^T (LDL^*P)
@@ -563,10 +574,8 @@ MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
return res; return res;
} }
#ifndef __CUDACC__
/** \cholesky_module /** \cholesky_module
* \returns the Cholesky decomposition with full pivoting without square root of \c *this * \returns the Cholesky decomposition with full pivoting without square root of \c *this
* \sa MatrixBase::ldlt()
*/ */
template<typename MatrixType, unsigned int UpLo> template<typename MatrixType, unsigned int UpLo>
inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo> inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
@@ -577,7 +586,6 @@ SelfAdjointView<MatrixType, UpLo>::ldlt() const
/** \cholesky_module /** \cholesky_module
* \returns the Cholesky decomposition with full pivoting without square root of \c *this * \returns the Cholesky decomposition with full pivoting without square root of \c *this
* \sa SelfAdjointView::ldlt()
*/ */
template<typename Derived> template<typename Derived>
inline const LDLT<typename MatrixBase<Derived>::PlainObject> inline const LDLT<typename MatrixBase<Derived>::PlainObject>
@@ -585,7 +593,6 @@ MatrixBase<Derived>::ldlt() const
{ {
return LDLT<PlainObject>(derived()); return LDLT<PlainObject>(derived());
} }
#endif // __CUDACC__
} // end namespace Eigen } // end namespace Eigen

View File

@@ -41,7 +41,7 @@ template<typename MatrixType, int UpLo> struct LLT_Traits;
* Example: \include LLT_example.cpp * Example: \include LLT_example.cpp
* Output: \verbinclude LLT_example.out * Output: \verbinclude LLT_example.out
* *
* \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT * \sa MatrixBase::llt(), class LDLT
*/ */
/* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH)
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore, * Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
@@ -115,7 +115,7 @@ template<typename _MatrixType, int _UpLo> class LLT
* Example: \include LLT_solve.cpp * Example: \include LLT_solve.cpp
* Output: \verbinclude LLT_solve.out * Output: \verbinclude LLT_solve.out
* *
* \sa solveInPlace(), MatrixBase::llt(), SelfAdjointView::llt() * \sa solveInPlace(), MatrixBase::llt()
*/ */
template<typename Rhs> template<typename Rhs>
inline const internal::solve_retval<LLT, Rhs> inline const internal::solve_retval<LLT, Rhs>
@@ -127,6 +127,17 @@ template<typename _MatrixType, int _UpLo> class LLT
return internal::solve_retval<LLT, Rhs>(*this, b.derived()); return internal::solve_retval<LLT, Rhs>(*this, b.derived());
} }
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived, typename ResultType>
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
{
*result = this->solve(b);
return true;
}
bool isPositiveDefinite() const { return true; }
#endif
template<typename Derived> template<typename Derived>
void solveInPlace(MatrixBase<Derived> &bAndX) const; void solveInPlace(MatrixBase<Derived> &bAndX) const;
@@ -179,7 +190,6 @@ template<typename Scalar, int UpLo> struct llt_inplace;
template<typename MatrixType, typename VectorType> template<typename MatrixType, typename VectorType>
static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma)
{ {
using std::sqrt;
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;
@@ -189,7 +199,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;
Index n = mat.cols(); int n = mat.cols();
eigen_assert(mat.rows()==n && vec.size()==n); eigen_assert(mat.rows()==n && vec.size()==n);
TempVectorType temp; TempVectorType temp;
@@ -201,12 +211,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(Index i=0; i<n; ++i) for(int 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));
Index rs = n-i-1; int rs = n-i-1;
if(rs>0) if(rs>0)
{ {
ColXprSegment x(mat.col(i).tail(rs)); ColXprSegment x(mat.col(i).tail(rs));
@@ -219,12 +229,12 @@ static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const V
{ {
temp = vec; temp = vec;
RealScalar beta = 1; RealScalar beta = 1;
for(Index j=0; j<n; ++j) for(int j=0; j<n; ++j)
{ {
RealScalar Ljj = numext::real(mat.coeff(j,j)); RealScalar Ljj = real(mat.coeff(j,j));
RealScalar dj = numext::abs2(Ljj); RealScalar dj = abs2(Ljj);
Scalar wj = temp.coeff(j); Scalar wj = temp.coeff(j);
RealScalar swj2 = sigma*numext::abs2(wj); RealScalar swj2 = sigma*abs2(wj);
RealScalar gamma = dj*beta + swj2; RealScalar gamma = dj*beta + swj2;
RealScalar x = dj + swj2/beta; RealScalar x = dj + swj2/beta;
@@ -240,7 +250,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*numext::conj(wj)/gamma)*temp.tail(rs); mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*conj(wj)/gamma)*temp.tail(rs);
} }
} }
} }
@@ -253,7 +263,6 @@ template<typename Scalar> struct llt_inplace<Scalar, Lower>
template<typename MatrixType> template<typename MatrixType>
static typename MatrixType::Index unblocked(MatrixType& mat) static typename MatrixType::Index unblocked(MatrixType& mat)
{ {
using std::sqrt;
typedef typename MatrixType::Index Index; typedef typename MatrixType::Index Index;
eigen_assert(mat.rows()==mat.cols()); eigen_assert(mat.rows()==mat.cols());
@@ -266,7 +275,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 = numext::real(mat.coeff(k,k)); RealScalar x = 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;
@@ -454,10 +463,8 @@ MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const
return matrixL() * matrixL().adjoint().toDenseMatrix(); return matrixL() * matrixL().adjoint().toDenseMatrix();
} }
#ifndef __CUDACC__
/** \cholesky_module /** \cholesky_module
* \returns the LLT decomposition of \c *this * \returns the LLT decomposition of \c *this
* \sa SelfAdjointView::llt()
*/ */
template<typename Derived> template<typename Derived>
inline const LLT<typename MatrixBase<Derived>::PlainObject> inline const LLT<typename MatrixBase<Derived>::PlainObject>
@@ -468,7 +475,6 @@ MatrixBase<Derived>::llt() const
/** \cholesky_module /** \cholesky_module
* \returns the LLT decomposition of \c *this * \returns the LLT decomposition of \c *this
* \sa SelfAdjointView::llt()
*/ */
template<typename MatrixType, unsigned int UpLo> template<typename MatrixType, unsigned int UpLo>
inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo> inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
@@ -476,7 +482,6 @@ SelfAdjointView<MatrixType, UpLo>::llt() const
{ {
return LLT<PlainObject,UpLo>(m_matrix); return LLT<PlainObject,UpLo>(m_matrix);
} }
#endif // __CUDACC__
} // end namespace Eigen } // end namespace Eigen

View File

@@ -51,6 +51,7 @@ 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();;
@@ -58,12 +59,10 @@ 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
{ {
@@ -78,13 +77,9 @@ cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat)
{ {
res.itype = CHOLMOD_INT; res.itype = CHOLMOD_INT;
} }
else if (internal::is_same<_Index,UF_long>::value)
{
res.itype = CHOLMOD_LONG;
}
else else
{ {
eigen_assert(false && "Index type not supported yet"); eigen_assert(false && "Index type different than int is not supported yet");
} }
// setup res.xtype // setup res.xtype
@@ -128,7 +123,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 = (void*)(mat.derived().data()); res.x = mat.derived().data();
res.z = 0; res.z = 0;
internal::cholmod_configure_matrix<Scalar>(res); internal::cholmod_configure_matrix<Scalar>(res);
@@ -142,8 +137,8 @@ template<typename Scalar, int Flags, typename Index>
MappedSparseMatrix<Scalar,Flags,Index> viewAsEigen(cholmod_sparse& cm) MappedSparseMatrix<Scalar,Flags,Index> viewAsEigen(cholmod_sparse& cm)
{ {
return MappedSparseMatrix<Scalar,Flags,Index> return MappedSparseMatrix<Scalar,Flags,Index>
(cm.nrow, cm.ncol, static_cast<Index*>(cm.p)[cm.ncol], (cm.nrow, cm.ncol, reinterpret_cast<Index*>(cm.p)[cm.ncol],
static_cast<Index*>(cm.p), static_cast<Index*>(cm.i),static_cast<Scalar*>(cm.x) ); reinterpret_cast<Index*>(cm.p), reinterpret_cast<Index*>(cm.i),reinterpret_cast<Scalar*>(cm.x) );
} }
enum CholmodMode { enum CholmodMode {
@@ -172,14 +167,12 @@ 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);
} }
CholmodBase(const MatrixType& matrix) CholmodBase(const MatrixType& matrix)
: 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);
compute(matrix); compute(matrix);
} }
@@ -244,7 +237,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 sparsity pattern of \a matrix. /** Performs a symbolic decomposition on the sparcity 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.
* *
@@ -268,7 +261,7 @@ class CholmodBase : internal::noncopyable
/** Performs a numeric decomposition of \a matrix /** Performs a numeric decomposition of \a matrix
* *
* The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed. * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
* *
* \sa analyzePattern() * \sa analyzePattern()
*/ */
@@ -276,10 +269,9 @@ class CholmodBase : internal::noncopyable
{ {
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>()); cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod); cholmod_factorize(&A, m_cholmodFactor, &m_cholmod);
// If the factorization failed, minor is the column at which it did. On success minor == n. this->m_info = Success;
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
m_factorizationIsOk = true; m_factorizationIsOk = true;
} }
@@ -294,18 +286,16 @@ 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: cd stands for Cholmod Dense // note: cd stands for Cholmod Dense
Rhs& b_ref(b.const_cast_derived()); cholmod_dense b_cd = viewAsCholmod(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 careful with alignment, etc.) // TODO optimize this copy by swapping when possible (be carreful 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);
} }
@@ -316,7 +306,6 @@ 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
@@ -326,36 +315,19 @@ class CholmodBase : internal::noncopyable
{ {
this->m_info = NumericalIssue; this->m_info = NumericalIssue;
} }
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.) // TODO optimize this copy by swapping when possible (be carreful 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);
} }
#endif // EIGEN_PARSED_BY_DOXYGEN #endif // EIGEN_PARSED_BY_DOXYGEN
/** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization.
*
* During the numerical factorization, an offset term is added to the diagonal coefficients:\n
* \c d_ii = \a offset + \c d_ii
*
* The default is \a offset=0.
*
* \returns a reference to \c *this.
*/
Derived& setShift(const RealScalar& offset)
{
m_shiftOffset[0] = offset;
return derived();
}
template<typename Stream> template<typename Stream>
void dumpMemory(Stream& /*s*/) void dumpMemory(Stream& s)
{} {}
protected: protected:
mutable cholmod_common m_cholmod; mutable cholmod_common m_cholmod;
cholmod_factor* m_cholmodFactor; cholmod_factor* m_cholmodFactor;
RealScalar m_shiftOffset[2];
mutable ComputationInfo m_info; mutable ComputationInfo m_info;
bool m_isInitialized; bool m_isInitialized;
int m_factorizationIsOk; int m_factorizationIsOk;
@@ -368,8 +340,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. Therefore, it has little practical interest. * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Thefore, it has little practical interest.
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices * The sparse matrix A must be selfajoint 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<>
@@ -415,8 +387,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. Therefore, it has little practical interest. * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Thefore, it has little practical interest.
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices * The sparse matrix A must be selfajoint 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<>
@@ -461,7 +433,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 selfadjoint and positive definite. The vectors or matrices * The sparse matrix A must be selfajoint 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<>
@@ -504,7 +476,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 selfadjoint and positive definite. The vectors or matrices * using the Cholmod library. The sparse matrix A must be selfajoint 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.

View File

@@ -69,7 +69,6 @@ class Array
* the usage of 'using'. This should be done only for operator=. * the usage of 'using'. This should be done only for operator=.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE Array& operator=(const EigenBase<OtherDerived> &other)
{ {
return Base::operator=(other); return Base::operator=(other);
@@ -85,7 +84,6 @@ class Array
* remain row-vectors and vectors remain vectors. * remain row-vectors and vectors remain vectors.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const ArrayBase<OtherDerived>& other) EIGEN_STRONG_INLINE Array& operator=(const ArrayBase<OtherDerived>& other)
{ {
return Base::_set(other); return Base::_set(other);
@@ -94,7 +92,6 @@ class Array
/** This is a special case of the templated operator=. Its purpose is to /** This is a special case of the templated operator=. Its purpose is to
* prevent a default operator= from hiding the templated operator=. * prevent a default operator= from hiding the templated operator=.
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const Array& other) EIGEN_STRONG_INLINE Array& operator=(const Array& other)
{ {
return Base::_set(other); return Base::_set(other);
@@ -110,105 +107,81 @@ class Array
* *
* \sa resize(Index,Index) * \sa resize(Index,Index)
*/ */
EIGEN_DEVICE_FUNC 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_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
// FIXME is it still needed ?? // FIXME is it still needed ??
/** \internal */ /** \internal */
EIGEN_DEVICE_FUNC
Array(internal::constructor_without_unaligned_array_assert) Array(internal::constructor_without_unaligned_array_assert)
: Base(internal::constructor_without_unaligned_array_assert()) : Base(internal::constructor_without_unaligned_array_assert())
{ {
Base::_check_template_params(); Base::_check_template_params();
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
#endif #endif
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
Array(Array&& other)
: Base(std::move(other))
{
Base::_check_template_params();
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
Base::_set_noalias(other);
}
Array& operator=(Array&& other)
{
other.swap(*this);
return *this;
}
#endif
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE explicit Array(const T& x)
{
Base::_check_template_params();
Base::template _init1<T>(x);
}
template<typename T0, typename T1>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const T0& val0, const T1& val1)
{
Base::_check_template_params();
this->template _init2<T0,T1>(val0, val1);
}
#else
/** \brief Constructs a fixed-sized array initialized with coefficients starting at \a data */
EIGEN_DEVICE_FUNC explicit Array(const Scalar *data);
/** Constructs a vector or row-vector with given dimension. \only_for_vectors /** Constructs a vector or row-vector with given dimension. \only_for_vectors
* *
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors, * Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
* it is redundant to pass the dimension here, so it makes more sense to use the default * it is redundant to pass the dimension here, so it makes more sense to use the default
* constructor Array() instead. * constructor Matrix() instead.
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit Array(Index dim)
EIGEN_STRONG_INLINE explicit Array(Index dim); : Base(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
/** constructs an initialized 1x1 Array with the given coefficient */ {
Array(const Scalar& value); Base::_check_template_params();
/** constructs an uninitialized array with \a rows rows and \a cols columns. EIGEN_STATIC_ASSERT_VECTOR_ONLY(Array)
eigen_assert(dim >= 0);
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename T0, typename T1>
EIGEN_STRONG_INLINE Array(const T0& x, const T1& y)
{
Base::_check_template_params();
this->template _init2<T0,T1>(x, y);
}
#else
/** constructs an uninitialized matrix with \a rows rows and \a cols columns.
* *
* This is useful for dynamic-size arrays. For fixed-size arrays, * This is useful for dynamic-size matrices. For fixed-size matrices,
* it is redundant to pass these parameters, so one should use the default constructor * it is redundant to pass these parameters, so one should use the default constructor
* Array() instead. */ * Matrix() instead. */
Array(Index rows, Index cols); Array(Index rows, Index cols);
/** constructs an initialized 2D vector with given coefficients */ /** constructs an initialized 2D vector with given coefficients */
Array(const Scalar& val0, const Scalar& val1); Array(const Scalar& x, const Scalar& y);
#endif #endif
/** constructs an initialized 3D vector with given coefficients */ /** constructs an initialized 3D vector with given coefficients */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z)
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2)
{ {
Base::_check_template_params(); Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3) EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3)
m_storage.data()[0] = val0; m_storage.data()[0] = x;
m_storage.data()[1] = val1; m_storage.data()[1] = y;
m_storage.data()[2] = val2; m_storage.data()[2] = z;
} }
/** constructs an initialized 4D vector with given coefficients */ /** constructs an initialized 4D vector with given coefficients */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2, const Scalar& val3)
{ {
Base::_check_template_params(); Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4) EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4)
m_storage.data()[0] = val0; m_storage.data()[0] = x;
m_storage.data()[1] = val1; m_storage.data()[1] = y;
m_storage.data()[2] = val2; m_storage.data()[2] = z;
m_storage.data()[3] = val3; m_storage.data()[3] = w;
} }
explicit Array(const Scalar *data);
/** Constructor copying the value of the expression \a other */ /** Constructor copying the value of the expression \a other */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const ArrayBase<OtherDerived>& other) EIGEN_STRONG_INLINE Array(const ArrayBase<OtherDerived>& other)
: Base(other.rows() * other.cols(), other.rows(), other.cols()) : Base(other.rows() * other.cols(), other.rows(), other.cols())
{ {
@@ -216,7 +189,6 @@ class Array
Base::_set_noalias(other); Base::_set_noalias(other);
} }
/** Copy constructor */ /** Copy constructor */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const Array& other) EIGEN_STRONG_INLINE Array(const Array& other)
: Base(other.rows() * other.cols(), other.rows(), other.cols()) : Base(other.rows() * other.cols(), other.rows(), other.cols())
{ {
@@ -225,7 +197,6 @@ class Array
} }
/** Copy constructor with in-place evaluation */ /** Copy constructor with in-place evaluation */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const ReturnByValue<OtherDerived>& other) EIGEN_STRONG_INLINE Array(const ReturnByValue<OtherDerived>& other)
{ {
Base::_check_template_params(); Base::_check_template_params();
@@ -235,12 +206,11 @@ class Array
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */ /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other)
: 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_to_match(other); Base::resize(other.rows(), other.cols());
*this = other; *this = other;
} }
@@ -251,8 +221,8 @@ class Array
void swap(ArrayBase<OtherDerived> const & other) void swap(ArrayBase<OtherDerived> const & other)
{ this->_swap(other.derived()); } { this->_swap(other.derived()); }
EIGEN_DEVICE_FUNC inline Index innerStride() const { return 1; } inline Index innerStride() const { return 1; }
EIGEN_DEVICE_FUNC inline Index outerStride() const { return this->innerSize(); } inline Index outerStride() const { return this->innerSize(); }
#ifdef EIGEN_ARRAY_PLUGIN #ifdef EIGEN_ARRAY_PLUGIN
#include EIGEN_ARRAY_PLUGIN #include EIGEN_ARRAY_PLUGIN

View File

@@ -118,50 +118,40 @@ template<typename Derived> class ArrayBase
/** Special case of the template operator=, in order to prevent the compiler /** Special case of the template operator=, in order to prevent the compiler
* from generating a default operator= (issue hit with g++ 4.1) * from generating a default operator= (issue hit with g++ 4.1)
*/ */
EIGEN_DEVICE_FUNC
Derived& operator=(const ArrayBase& other) Derived& operator=(const ArrayBase& other)
{ {
return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
} }
EIGEN_DEVICE_FUNC Derived& operator+=(const Scalar& scalar)
Derived& operator+=(const Scalar& scalar); { return *this = derived() + scalar; }
EIGEN_DEVICE_FUNC Derived& operator-=(const Scalar& scalar)
Derived& operator-=(const Scalar& scalar); { return *this = derived() - scalar; }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator+=(const ArrayBase<OtherDerived>& other); Derived& operator+=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator-=(const ArrayBase<OtherDerived>& other); Derived& operator-=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator*=(const ArrayBase<OtherDerived>& other); Derived& operator*=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator/=(const ArrayBase<OtherDerived>& other); Derived& operator/=(const ArrayBase<OtherDerived>& other);
public: public:
EIGEN_DEVICE_FUNC
ArrayBase<Derived>& array() { return *this; } ArrayBase<Derived>& array() { return *this; }
EIGEN_DEVICE_FUNC
const ArrayBase<Derived>& array() const { return *this; } const ArrayBase<Derived>& array() const { return *this; }
/** \returns an \link Eigen::MatrixBase Matrix \endlink expression of this array /** \returns an \link MatrixBase Matrix \endlink expression of this array
* \sa MatrixBase::array() */ * \sa MatrixBase::array() */
EIGEN_DEVICE_FUNC
MatrixWrapper<Derived> matrix() { return derived(); } MatrixWrapper<Derived> matrix() { return derived(); }
EIGEN_DEVICE_FUNC
const MatrixWrapper<const Derived> matrix() const { return derived(); } const MatrixWrapper<const Derived> matrix() const { return derived(); }
// template<typename Dest> // template<typename Dest>
// inline void evalTo(Dest& dst) const { dst = matrix(); } // inline void evalTo(Dest& dst) const { dst = matrix(); }
protected: protected:
EIGEN_DEVICE_FUNC
ArrayBase() : Base() {} ArrayBase() : Base() {}
private: private:

View File

@@ -29,11 +29,6 @@ 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
};
}; };
} }
@@ -53,69 +48,56 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
typedef typename internal::nested<ExpressionType>::type NestedExpressionType; typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
EIGEN_DEVICE_FUNC inline ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); } inline Index rows() const { return m_expression.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_expression.cols(); } inline Index cols() const { return m_expression.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_expression.outerStride(); } inline Index outerStride() const { return m_expression.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_expression.innerStride(); } inline Index innerStride() const { return m_expression.innerStride(); }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); } inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return m_expression.data(); } inline const Scalar* data() const { return m_expression.data(); }
EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index row, Index col) const
inline CoeffReturnType coeff(Index rowId, Index colId) const
{ {
return m_expression.coeff(rowId, colId); return m_expression.coeff(row, col);
} }
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col)
inline Scalar& coeffRef(Index rowId, Index colId)
{ {
return m_expression.const_cast_derived().coeffRef(rowId, colId); return m_expression.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const
inline const Scalar& coeffRef(Index rowId, Index colId) const
{ {
return m_expression.const_cast_derived().coeffRef(rowId, colId); return m_expression.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
inline CoeffReturnType coeff(Index index) const inline CoeffReturnType coeff(Index index) const
{ {
return m_expression.coeff(index); return m_expression.coeff(index);
} }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) inline Scalar& coeffRef(Index index)
{ {
return m_expression.const_cast_derived().coeffRef(index); return m_expression.const_cast_derived().coeffRef(index);
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
return m_expression.const_cast_derived().coeffRef(index); return m_expression.const_cast_derived().coeffRef(index);
} }
template<int LoadMode> template<int LoadMode>
inline const PacketScalar packet(Index rowId, Index colId) const inline const PacketScalar packet(Index row, Index col) const
{ {
return m_expression.template packet<LoadMode>(rowId, colId); return m_expression.template packet<LoadMode>(row, col);
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index rowId, Index colId, const PacketScalar& val) inline void writePacket(Index row, Index col, const PacketScalar& x)
{ {
m_expression.const_cast_derived().template writePacket<LoadMode>(rowId, colId, val); m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
} }
template<int LoadMode> template<int LoadMode>
@@ -125,17 +107,15 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index index, const PacketScalar& val) inline void writePacket(Index index, const PacketScalar& x)
{ {
m_expression.const_cast_derived().template writePacket<LoadMode>(index, val); m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
} }
template<typename Dest> template<typename Dest>
EIGEN_DEVICE_FUNC
inline void evalTo(Dest& dst) const { dst = m_expression; } inline void evalTo(Dest& dst) const { dst = m_expression; }
const typename internal::remove_all<NestedExpressionType>::type& const typename internal::remove_all<NestedExpressionType>::type&
EIGEN_DEVICE_FUNC
nestedExpression() const nestedExpression() const
{ {
return m_expression; return m_expression;
@@ -143,11 +123,9 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
/** Forwards the resizing request to the nested expression /** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index) */ * \sa DenseBase::resize(Index) */
EIGEN_DEVICE_FUNC
void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); } void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); }
/** Forwards the resizing request to the nested expression /** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index,Index)*/ * \sa DenseBase::resize(Index,Index)*/
EIGEN_DEVICE_FUNC
void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); } void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); }
protected: protected:
@@ -171,11 +149,6 @@ 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
};
}; };
} }
@@ -195,69 +168,56 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
typedef typename internal::nested<ExpressionType>::type NestedExpressionType; typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
EIGEN_DEVICE_FUNC inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
inline MatrixWrapper(ExpressionType& a_matrix) : m_expression(a_matrix) {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); } inline Index rows() const { return m_expression.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_expression.cols(); } inline Index cols() const { return m_expression.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_expression.outerStride(); } inline Index outerStride() const { return m_expression.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_expression.innerStride(); } inline Index innerStride() const { return m_expression.innerStride(); }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); } inline ScalarWithConstIfNotLvalue* data() { return m_expression.const_cast_derived().data(); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return m_expression.data(); } inline const Scalar* data() const { return m_expression.data(); }
EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index row, Index col) const
inline CoeffReturnType coeff(Index rowId, Index colId) const
{ {
return m_expression.coeff(rowId, colId); return m_expression.coeff(row, col);
} }
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col)
inline Scalar& coeffRef(Index rowId, Index colId)
{ {
return m_expression.const_cast_derived().coeffRef(rowId, colId); return m_expression.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const
inline const Scalar& coeffRef(Index rowId, Index colId) const
{ {
return m_expression.derived().coeffRef(rowId, colId); return m_expression.derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
inline CoeffReturnType coeff(Index index) const inline CoeffReturnType coeff(Index index) const
{ {
return m_expression.coeff(index); return m_expression.coeff(index);
} }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) inline Scalar& coeffRef(Index index)
{ {
return m_expression.const_cast_derived().coeffRef(index); return m_expression.const_cast_derived().coeffRef(index);
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
return m_expression.const_cast_derived().coeffRef(index); return m_expression.const_cast_derived().coeffRef(index);
} }
template<int LoadMode> template<int LoadMode>
inline const PacketScalar packet(Index rowId, Index colId) const inline const PacketScalar packet(Index row, Index col) const
{ {
return m_expression.template packet<LoadMode>(rowId, colId); return m_expression.template packet<LoadMode>(row, col);
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index rowId, Index colId, const PacketScalar& val) inline void writePacket(Index row, Index col, const PacketScalar& x)
{ {
m_expression.const_cast_derived().template writePacket<LoadMode>(rowId, colId, val); m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
} }
template<int LoadMode> template<int LoadMode>
@@ -267,12 +227,11 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index index, const PacketScalar& val) inline void writePacket(Index index, const PacketScalar& x)
{ {
m_expression.const_cast_derived().template writePacket<LoadMode>(index, val); m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
} }
EIGEN_DEVICE_FUNC
const typename internal::remove_all<NestedExpressionType>::type& const typename internal::remove_all<NestedExpressionType>::type&
nestedExpression() const nestedExpression() const
{ {
@@ -281,11 +240,9 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
/** Forwards the resizing request to the nested expression /** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index) */ * \sa DenseBase::resize(Index) */
EIGEN_DEVICE_FUNC
void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); } void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); }
/** Forwards the resizing request to the nested expression /** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index,Index)*/ * \sa DenseBase::resize(Index,Index)*/
EIGEN_DEVICE_FUNC
void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); } void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); }
protected: protected:

View File

@@ -105,8 +105,6 @@ public:
EIGEN_DEBUG_VAR(DstIsAligned) EIGEN_DEBUG_VAR(DstIsAligned)
EIGEN_DEBUG_VAR(SrcIsAligned) EIGEN_DEBUG_VAR(SrcIsAligned)
EIGEN_DEBUG_VAR(JointAlignment) EIGEN_DEBUG_VAR(JointAlignment)
EIGEN_DEBUG_VAR(Derived::SizeAtCompileTime)
EIGEN_DEBUG_VAR(OtherDerived::CoeffReadCost)
EIGEN_DEBUG_VAR(InnerSize) EIGEN_DEBUG_VAR(InnerSize)
EIGEN_DEBUG_VAR(InnerMaxSize) EIGEN_DEBUG_VAR(InnerMaxSize)
EIGEN_DEBUG_VAR(PacketSize) EIGEN_DEBUG_VAR(PacketSize)
@@ -141,7 +139,6 @@ struct assign_DefaultTraversal_CompleteUnrolling
inner = Index % Derived1::InnerSizeAtCompileTime inner = Index % Derived1::InnerSizeAtCompileTime
}; };
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
{ {
dst.copyCoeffByOuterInner(outer, inner, src); dst.copyCoeffByOuterInner(outer, inner, src);
@@ -152,15 +149,13 @@ struct assign_DefaultTraversal_CompleteUnrolling
template<typename Derived1, typename Derived2, int Stop> template<typename Derived1, typename Derived2, int Stop>
struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop> struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {}
}; };
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
{ {
EIGEN_DEVICE_FUNC 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);
@@ -170,8 +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>
{ {
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, typename Derived1::Index) {}
}; };
/*********************** /***********************
@@ -181,7 +175,6 @@ struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
template<typename Derived1, typename Derived2, int Index, int Stop> template<typename Derived1, typename Derived2, int Index, int Stop>
struct assign_LinearTraversal_CompleteUnrolling struct assign_LinearTraversal_CompleteUnrolling
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
{ {
dst.copyCoeff(Index, src); dst.copyCoeff(Index, src);
@@ -192,7 +185,6 @@ struct assign_LinearTraversal_CompleteUnrolling
template<typename Derived1, typename Derived2, int Stop> template<typename Derived1, typename Derived2, int Stop>
struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop> struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {}
}; };
@@ -226,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, typename Derived1::Index outer) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int 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,
@@ -237,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 &, typename Derived1::Index) {} static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
}; };
/*************************************************************************** /***************************************************************************
@@ -257,7 +249,6 @@ struct assign_impl;
template<typename Derived1, typename Derived2, int Unrolling, int Version> template<typename Derived1, typename Derived2, int Unrolling, int Version>
struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling, Version> struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling, Version>
{ {
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &, const Derived2 &) { } static inline void run(Derived1 &, const Derived2 &) { }
}; };
@@ -265,7 +256,6 @@ template<typename Derived1, typename Derived2, int Version>
struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling, Version> struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling, Version>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
const Index innerSize = dst.innerSize(); const Index innerSize = dst.innerSize();
@@ -279,7 +269,6 @@ struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling, Version>
template<typename Derived1, typename Derived2, int Version> template<typename Derived1, typename Derived2, int Version>
struct assign_impl<Derived1, Derived2, DefaultTraversal, CompleteUnrolling, Version> struct assign_impl<Derived1, Derived2, DefaultTraversal, CompleteUnrolling, Version>
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
{ {
assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime> assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
@@ -291,7 +280,6 @@ template<typename Derived1, typename Derived2, int Version>
struct assign_impl<Derived1, Derived2, DefaultTraversal, InnerUnrolling, Version> struct assign_impl<Derived1, Derived2, DefaultTraversal, InnerUnrolling, Version>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
{ {
const Index outerSize = dst.outerSize(); const Index outerSize = dst.outerSize();
@@ -309,7 +297,6 @@ template<typename Derived1, typename Derived2, int Version>
struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling, Version> struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling, Version>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
const Index size = dst.size(); const Index size = dst.size();
@@ -321,7 +308,6 @@ struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling, Version>
template<typename Derived1, typename Derived2, int Version> template<typename Derived1, typename Derived2, int Version>
struct assign_impl<Derived1, Derived2, LinearTraversal, CompleteUnrolling, Version> struct assign_impl<Derived1, Derived2, LinearTraversal, CompleteUnrolling, Version>
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
{ {
assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime> assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
@@ -506,25 +492,12 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived) EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
#ifdef EIGEN_TEST_EVALUATORS
#ifdef EIGEN_DEBUG_ASSIGN
internal::copy_using_evaluator_traits<Derived, OtherDerived>::debug();
#endif
eigen_assert(rows() == other.rows() && cols() == other.cols());
internal::call_dense_assignment_loop(derived(),other.derived());
#else // EIGEN_TEST_EVALUATORS
#ifdef EIGEN_DEBUG_ASSIGN #ifdef EIGEN_DEBUG_ASSIGN
internal::assign_traits<Derived, OtherDerived>::debug(); internal::assign_traits<Derived, OtherDerived>::debug();
#endif #endif
eigen_assert(rows() == other.rows() && cols() == other.cols()); eigen_assert(rows() == other.rows() && cols() == other.cols());
internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal) internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal)
: int(InvalidTraversal)>::run(derived(),other.derived()); : int(InvalidTraversal)>::run(derived(),other.derived());
#endif // EIGEN_TEST_EVALUATORS
#ifndef EIGEN_NO_DEBUG #ifndef EIGEN_NO_DEBUG
checkTransposeAliasing(other.derived()); checkTransposeAliasing(other.derived());
#endif #endif
@@ -534,8 +507,10 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
namespace internal { namespace internal {
template<typename Derived, typename OtherDerived, template<typename Derived, typename OtherDerived,
bool EvalBeforeAssigning = (int(internal::traits<OtherDerived>::Flags) & EvalBeforeAssigningBit) != 0, bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
bool NeedToTranspose = ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1) bool NeedToTranspose = Derived::IsVectorAtCompileTime
&& OtherDerived::IsVectorAtCompileTime
&& ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
// revert to || as soon as not needed anymore. // revert to || as soon as not needed anymore.
(int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1)) (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
@@ -544,28 +519,18 @@ 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> {
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
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> {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
}; };
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct assign_selector<Derived,OtherDerived,false,true> { struct assign_selector<Derived,OtherDerived,false,true> {
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
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> {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); } static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
}; };
@@ -573,21 +538,18 @@ struct assign_selector<Derived,OtherDerived,true,true> {
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
{ {
return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
} }
template<typename Derived> template<typename Derived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other) EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other)
{ {
return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
} }
template<typename Derived> template<typename Derived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other)
{ {
return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
@@ -595,7 +557,6 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& ot
template<typename Derived> template<typename Derived>
template <typename OtherDerived> template <typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
{ {
return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
@@ -603,18 +564,18 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<Othe
template<typename Derived> template<typename Derived>
template <typename OtherDerived> template <typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
{ {
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived()); other.derived().evalTo(derived());
return derived();
} }
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
{ {
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived()); other.evalTo(derived());
return derived();
} }
} // end namespace Eigen } // end namespace Eigen

View File

@@ -1,842 +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-2013 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 Kernel, int Index, int Stop>
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
{
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
typedef typename DstEvaluatorType::XprType DstXprType;
enum {
outer = Index / DstXprType::InnerSizeAtCompileTime,
inner = Index % DstXprType::InnerSizeAtCompileTime
};
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
kernel.assignCoeffByOuterInner(outer, inner);
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop, Stop>
{
static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel, int outer)
{
kernel.assignCoeffByOuterInner(outer, Index);
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Index+1, Stop>::run(kernel, outer);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Stop, Stop>
{
static EIGEN_STRONG_INLINE void run(Kernel&, int) { }
};
/***********************
*** Linear traversal ***
***********************/
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling
{
static EIGEN_STRONG_INLINE void run(Kernel& kernel)
{
kernel.assignCoeff(Index);
copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Stop, Stop>
{
static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
/**************************
*** Inner vectorization ***
**************************/
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_innervec_CompleteUnrolling
{
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
typedef typename DstEvaluatorType::XprType DstXprType;
enum {
outer = Index / DstXprType::InnerSizeAtCompileTime,
inner = Index % DstXprType::InnerSizeAtCompileTime,
JointAlignment = Kernel::AssignmentTraits::JointAlignment
};
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
kernel.template assignPacketByOuterInner<Aligned, JointAlignment>(outer, inner);
enum { NextIndex = Index + packet_traits<typename DstXprType::Scalar>::size };
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, NextIndex, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_innervec_CompleteUnrolling<Kernel, Stop, Stop>
{
static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_innervec_InnerUnrolling
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel, int outer)
{
kernel.template assignPacketByOuterInner<Aligned, Aligned>(outer, Index);
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
enum { NextIndex = Index + packet_traits<typename DstXprType::Scalar>::size };
copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop>::run(kernel, outer);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop>
{
static EIGEN_STRONG_INLINE void run(Kernel &, int) { }
};
/***************************************************************************
* Part 3 : implementation of all cases
***************************************************************************/
// dense_assignment_loop is based on assign_impl
template<typename Kernel,
int Traversal = Kernel::AssignmentTraits::Traversal,
int Unrolling = Kernel::AssignmentTraits::Unrolling>
struct dense_assignment_loop;
/************************
*** Default traversal ***
************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, NoUnrolling>
{
static void run(Kernel &kernel)
{
typedef typename Kernel::Index Index;
for(Index outer = 0; outer < kernel.outerSize(); ++outer) {
for(Index inner = 0; inner < kernel.innerSize(); ++inner) {
kernel.assignCoeffByOuterInner(outer, inner);
}
}
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, CompleteUnrolling>
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, InnerUnrolling>
{
typedef typename Kernel::Index Index;
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
const Index outerSize = kernel.outerSize();
for(Index outer = 0; outer < outerSize; ++outer)
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime>::run(kernel, outer);
}
};
/***************************
*** Linear vectorization ***
***************************/
// The goal of unaligned_dense_assignment_loop is simply to factorize the handling
// of the non vectorizable beginning and ending parts
template <bool IsAligned = false>
struct unaligned_dense_assignment_loop
{
// if IsAligned = true, then do nothing
template <typename Kernel>
static EIGEN_STRONG_INLINE void run(Kernel&, typename Kernel::Index, typename Kernel::Index) {}
};
template <>
struct unaligned_dense_assignment_loop<false>
{
// MSVC must not inline this functions. If it does, it fails to optimize the
// packet access path.
// FIXME check which version exhibits this issue
#ifdef _MSC_VER
template <typename Kernel>
static EIGEN_DONT_INLINE void run(Kernel &kernel,
typename Kernel::Index start,
typename Kernel::Index end)
#else
template <typename Kernel>
static EIGEN_STRONG_INLINE void run(Kernel &kernel,
typename Kernel::Index start,
typename Kernel::Index end)
#endif
{
for (typename Kernel::Index index = start; index < end; ++index)
kernel.assignCoeff(index);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, NoUnrolling>
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::Index Index;
const Index size = kernel.size();
typedef packet_traits<typename Kernel::Scalar> PacketTraits;
enum {
packetSize = PacketTraits::size,
dstIsAligned = int(Kernel::AssignmentTraits::DstIsAligned),
dstAlignment = PacketTraits::AlignedOnScalar ? Aligned : dstIsAligned,
srcAlignment = Kernel::AssignmentTraits::JointAlignment
};
const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned(&kernel.dstEvaluator().coeffRef(0), size);
const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
unaligned_dense_assignment_loop<dstIsAligned!=0>::run(kernel, 0, alignedStart);
for(Index index = alignedStart; index < alignedEnd; index += packetSize)
kernel.template assignPacket<dstAlignment, srcAlignment>(index);
unaligned_dense_assignment_loop<>::run(kernel, alignedEnd, size);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrolling>
{
typedef typename Kernel::Index Index;
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
enum { size = DstXprType::SizeAtCompileTime,
packetSize = packet_traits<typename Kernel::Scalar>::size,
alignedSize = (size/packetSize)*packetSize };
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize, size>::run(kernel);
}
};
/**************************
*** Inner vectorization ***
**************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, NoUnrolling>
{
static inline void run(Kernel &kernel)
{
typedef typename Kernel::Index Index;
const Index innerSize = kernel.innerSize();
const Index outerSize = kernel.outerSize();
const Index packetSize = packet_traits<typename Kernel::Scalar>::size;
for(Index outer = 0; outer < outerSize; ++outer)
for(Index inner = 0; inner < innerSize; inner+=packetSize)
kernel.template assignPacketByOuterInner<Aligned, Aligned>(outer, inner);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, CompleteUnrolling>
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, InnerUnrolling>
{
typedef typename Kernel::Index Index;
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
const Index outerSize = kernel.outerSize();
for(Index outer = 0; outer < outerSize; ++outer)
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime>::run(kernel, outer);
}
};
/***********************
*** Linear traversal ***
***********************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearTraversal, NoUnrolling>
{
static inline void run(Kernel &kernel)
{
typedef typename Kernel::Index Index;
const Index size = kernel.size();
for(Index i = 0; i < size; ++i)
kernel.assignCoeff(i);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearTraversal, CompleteUnrolling>
{
static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
/**************************
*** Slice vectorization ***
***************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
{
static inline void run(Kernel &kernel)
{
typedef typename Kernel::Index Index;
typedef packet_traits<typename Kernel::Scalar> PacketTraits;
enum {
packetSize = PacketTraits::size,
alignable = PacketTraits::AlignedOnScalar,
dstAlignment = alignable ? Aligned : int(Kernel::AssignmentTraits::DstIsAligned)
};
const Index packetAlignedMask = packetSize - 1;
const Index innerSize = kernel.innerSize();
const Index outerSize = kernel.outerSize();
const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0;
Index alignedStart = ((!alignable) || Kernel::AssignmentTraits::DstIsAligned) ? 0
: internal::first_aligned(&kernel.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)
kernel.assignCoeffByOuterInner(outer, inner);
// do the vectorizable part of the assignment
for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
kernel.template assignPacketByOuterInner<dstAlignment, Unaligned>(outer, inner);
// do the non-vectorizable part of the assignment
for(Index inner = alignedEnd; inner<innerSize ; ++inner)
kernel.assignCoeffByOuterInner(outer, inner);
alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
}
}
};
/****************************
*** All-at-once traversal ***
****************************/
// TODO: this 'AllAtOnceTraversal' should be dropped or caught earlier (Gael)
// Indeed, what to do with the kernel's functor??
template<typename Kernel>
struct dense_assignment_loop<Kernel, AllAtOnceTraversal, NoUnrolling>
{
static inline void run(Kernel & kernel)
{
// Evaluate rhs in temporary to prevent aliasing problems in a = a * a;
// TODO: Do not pass the xpr object to evalTo() (Jitse)
kernel.srcEvaluator().evalTo(kernel.dstEvaluator(), kernel.dstExpression());
}
};
/***************************************************************************
* Part 4 : Generic Assignment routine
***************************************************************************/
// This class generalize the assignment of a coefficient (or packet) from one dense evaluator
// to another dense writable evaluator.
// It is parametrized by the two evaluators, and the actual assignment functor.
// This abstraction level permits to keep the evaluation loops as simple and as generic as possible.
// One can customize the assignment using this generic dense_assignment_kernel with different
// functors, or by completely overloading it, by-passing a functor.
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor>
class generic_dense_assignment_kernel
{
protected:
typedef typename DstEvaluatorTypeT::XprType DstXprType;
typedef typename SrcEvaluatorTypeT::XprType SrcXprType;
public:
typedef DstEvaluatorTypeT DstEvaluatorType;
typedef SrcEvaluatorTypeT SrcEvaluatorType;
typedef typename DstEvaluatorType::Scalar Scalar;
typedef typename DstEvaluatorType::Index Index;
typedef copy_using_evaluator_traits<DstXprType, SrcXprType> AssignmentTraits;
generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
: m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr)
{}
Index size() const { return m_dstExpr.size(); }
Index innerSize() const { return m_dstExpr.innerSize(); }
Index outerSize() const { return m_dstExpr.outerSize(); }
Index outerStride() const { return m_dstExpr.outerStride(); }
// TODO get rid of this one:
DstXprType& dstExpression() const { return m_dstExpr; }
DstEvaluatorType& dstEvaluator() { return m_dst; }
const SrcEvaluatorType& srcEvaluator() const { return m_src; }
void assignCoeff(Index row, Index col)
{
m_functor.assignCoeff(m_dst.coeffRef(row,col), m_src.coeff(row,col));
}
void assignCoeff(Index index)
{
m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index));
}
void assignCoeffByOuterInner(Index outer, Index inner)
{
Index row = rowIndexByOuterInner(outer, inner);
Index col = colIndexByOuterInner(outer, inner);
assignCoeff(row, col);
}
template<int StoreMode, int LoadMode>
void assignPacket(Index row, Index col)
{
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode>(row,col));
}
template<int StoreMode, int LoadMode>
void assignPacket(Index index)
{
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode>(index));
}
template<int StoreMode, int LoadMode>
void assignPacketByOuterInner(Index outer, Index inner)
{
Index row = rowIndexByOuterInner(outer, inner);
Index col = colIndexByOuterInner(outer, inner);
assignPacket<StoreMode,LoadMode>(row, col);
}
static Index rowIndexByOuterInner(Index outer, Index inner)
{
typedef typename DstEvaluatorType::ExpressionTraits Traits;
return int(Traits::RowsAtCompileTime) == 1 ? 0
: int(Traits::ColsAtCompileTime) == 1 ? inner
: int(Traits::Flags)&RowMajorBit ? outer
: inner;
}
static Index colIndexByOuterInner(Index outer, Index inner)
{
typedef typename DstEvaluatorType::ExpressionTraits Traits;
return int(Traits::ColsAtCompileTime) == 1 ? 0
: int(Traits::RowsAtCompileTime) == 1 ? inner
: int(Traits::Flags)&RowMajorBit ? inner
: outer;
}
protected:
DstEvaluatorType& m_dst;
const SrcEvaluatorType& m_src;
const Functor &m_functor;
// TODO find a way to avoid the needs of the original expression
DstXprType& m_dstExpr;
};
template<typename DstXprType, typename SrcXprType, typename Functor>
void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
{
#ifdef EIGEN_DEBUG_ASSIGN
// TODO these traits should be computed from information provided by the evaluators
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
#endif
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
DstEvaluatorType dstEvaluator(dst);
SrcEvaluatorType srcEvaluator(src);
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
dense_assignment_loop<Kernel>::run(kernel);
}
template<typename DstXprType, typename SrcXprType>
void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src)
{
call_dense_assignment_loop(dst, src, internal::assign_op<typename DstXprType::Scalar>());
}
/***************************************************************************
* Part 5 : Entry points
***************************************************************************/
// Based on DenseBase::LazyAssign()
// The following functions are just for testing and they are meant to be moved to operator= and the likes.
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(), internal::assign_op<typename DstXprType::Scalar>());
}
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, typename Functor>
EIGEN_STRONG_INLINE
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
{
return noalias_copy_using_evaluator(dst.const_cast_derived(),
AddEvalIfAssumingAliasing<SrcXprType>::run(src.derived()),
func
);
}
// this mimics operator=
template<typename DstXprType, typename SrcXprType>
EIGEN_STRONG_INLINE
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
{
return copy_using_evaluator(dst.const_cast_derived(), src.derived(), internal::assign_op<typename DstXprType::Scalar>());
}
template<typename DstXprType, typename SrcXprType, typename Functor>
EIGEN_STRONG_INLINE
const DstXprType& noalias_copy_using_evaluator(const PlainObjectBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
{
#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
call_dense_assignment_loop(dst.const_cast_derived(), src.derived(), func);
return dst.derived();
}
template<typename DstXprType, typename SrcXprType, typename Functor>
EIGEN_STRONG_INLINE
const DstXprType& noalias_copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src, const Functor &func)
{
call_dense_assignment_loop(dst.const_cast_derived(), src.derived(), func);
return dst.derived();
}
// Based on DenseBase::swap()
// TODO: Check whether we need to do something special for swapping two
// Arrays or Matrices. (Jitse)
// Overload default assignPacket behavior for swapping them
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT>
class swap_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> >
{
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, swap_assign_op<typename DstEvaluatorTypeT::Scalar> > Base;
typedef typename DstEvaluatorTypeT::PacketScalar PacketScalar;
using Base::m_dst;
using Base::m_src;
using Base::m_functor;
public:
typedef typename Base::Scalar Scalar;
typedef typename Base::Index Index;
typedef typename Base::DstXprType DstXprType;
swap_kernel(DstEvaluatorTypeT &dst, const SrcEvaluatorTypeT &src, DstXprType& dstExpr)
: Base(dst, src, swap_assign_op<Scalar>(), dstExpr)
{}
template<int StoreMode, int LoadMode>
void assignPacket(Index row, Index col)
{
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(row,col), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(row,col));
}
template<int StoreMode, int LoadMode>
void assignPacket(Index index)
{
m_functor.template swapPacket<StoreMode,LoadMode,PacketScalar>(&m_dst.coeffRef(index), &const_cast<SrcEvaluatorTypeT&>(m_src).coeffRef(index));
}
// TODO find a simple way not to have to copy/paste this function from generic_dense_assignment_kernel, by simple I mean no CRTP (Gael)
template<int StoreMode, int LoadMode>
void assignPacketByOuterInner(Index outer, Index inner)
{
Index row = Base::rowIndexByOuterInner(outer, inner);
Index col = Base::colIndexByOuterInner(outer, inner);
assignPacket<StoreMode,LoadMode>(row, col);
}
};
template<typename DstXprType, typename SrcXprType>
void swap_using_evaluator(const DstXprType& dst, const SrcXprType& src)
{
// TODO there is too much redundancy with call_dense_assignment_loop
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
typedef typename evaluator<SrcXprType>::type SrcEvaluatorType;
DstEvaluatorType dstEvaluator(dst);
SrcEvaluatorType srcEvaluator(src);
typedef swap_kernel<DstEvaluatorType,SrcEvaluatorType> Kernel;
Kernel kernel(dstEvaluator, srcEvaluator, dst.const_cast_derived());
dense_assignment_loop<Kernel>::run(kernel);
}
// 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;
copy_using_evaluator(dst.derived(), src.derived(), add_assign_op<Scalar>());
}
// 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;
copy_using_evaluator(dst.derived(), src.derived(), add_assign_op<Scalar>());
}
// TODO: Add add_assign_using_evaluator for EigenBase ? (Jitse)
template<typename DstXprType, typename SrcXprType>
void subtract_assign_using_evaluator(const MatrixBase<DstXprType>& dst, const MatrixBase<SrcXprType>& src)
{
typedef typename DstXprType::Scalar Scalar;
copy_using_evaluator(dst.derived(), src.derived(), sub_assign_op<Scalar>());
}
template<typename DstXprType, typename SrcXprType>
void subtract_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
{
typedef typename DstXprType::Scalar Scalar;
copy_using_evaluator(dst.derived(), src.derived(), sub_assign_op<Scalar>());
}
template<typename DstXprType, typename SrcXprType>
void multiply_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
{
typedef typename DstXprType::Scalar Scalar;
copy_using_evaluator(dst.derived(), src.derived(), mul_assign_op<Scalar>());
}
template<typename DstXprType, typename SrcXprType>
void divide_assign_using_evaluator(const ArrayBase<DstXprType>& dst, const ArrayBase<SrcXprType>& src)
{
typedef typename DstXprType::Scalar Scalar;
copy_using_evaluator(dst.derived(), src.derived(), div_assign_op<Scalar>());
}
} // namespace internal
} // end namespace Eigen
#endif // EIGEN_ASSIGN_EVALUATOR_H

View File

@@ -202,7 +202,6 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(asin, Asin)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cos, Cos) EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cos, Cos)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(acos, Acos) EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(acos, Acos)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tan, Tan) EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tan, Tan)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(atan, Atan)
//EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs) //EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(exp, Exp) EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(exp, Exp)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log, Ln) EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log, Ln)

View File

@@ -21,9 +21,7 @@ namespace Eigen {
* \param XprType the type of the expression in which we are taking a block * \param XprType the type of the expression in which we are taking a block
* \param BlockRows the number of rows of the block we are taking at compile time (optional) * \param BlockRows the number of rows of the block we are taking at compile time (optional)
* \param BlockCols the number of columns of the block we are taking at compile time (optional) * \param BlockCols the number of columns of the block we are taking at compile time (optional)
* \param InnerPanel is true, if the block maps to a set of rows of a row major matrix or * \param _DirectAccessStatus \internal used for partial specialization
* to set of columns of a column major matrix (optional). The parameter allows to determine
* at compile time whether aligned access is possible on the block expression.
* *
* This class represents an expression of either a fixed-size or dynamic-size block. It is the return * This class represents an expression of either a fixed-size or dynamic-size block. It is the return
* type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and
@@ -49,8 +47,8 @@ namespace Eigen {
*/ */
namespace internal { namespace internal {
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprType> struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType>
{ {
typedef typename traits<XprType>::Scalar Scalar; typedef typename traits<XprType>::Scalar Scalar;
typedef typename traits<XprType>::StorageKind StorageKind; typedef typename traits<XprType>::StorageKind StorageKind;
@@ -83,8 +81,8 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0) MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
&& (InnerStrideAtCompileTime == 1) && (InnerStrideAtCompileTime == 1)
? PacketAccessBit : 0, ? PacketAccessBit : 0,
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % EIGEN_ALIGN_BYTES) == 0)) ? AlignedBit : 0, MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (traits<XprType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0, FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? 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) |
@@ -94,97 +92,21 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
}; };
}; };
template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class BlockImpl_dense;
} // end namespace internal
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind> class BlockImpl;
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class Block
: public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind>
{
typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl;
public:
//typedef typename Impl::Base Base;
typedef Impl Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
/** Column or Row constructor
*/
EIGEN_DEVICE_FUNC
inline Block(XprType& xpr, Index i) : Impl(xpr,i)
{
eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
} }
/** Fixed-size constructor template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block
*/ : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type
EIGEN_DEVICE_FUNC
inline Block(XprType& xpr, Index a_startRow, Index a_startCol)
: Impl(xpr, a_startRow, a_startCol)
{ {
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
eigen_assert(a_startRow >= 0 && BlockRows >= 1 && a_startRow + BlockRows <= xpr.rows()
&& a_startCol >= 0 && BlockCols >= 1 && a_startCol + BlockCols <= xpr.cols());
}
/** Dynamic-size constructor
*/
EIGEN_DEVICE_FUNC
inline Block(XprType& xpr,
Index a_startRow, Index a_startCol,
Index blockRows, Index blockCols)
: Impl(xpr, a_startRow, a_startCol, blockRows, blockCols)
{
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
eigen_assert(a_startRow >= 0 && blockRows >= 0 && a_startRow <= xpr.rows() - blockRows
&& a_startCol >= 0 && blockCols >= 0 && a_startCol <= xpr.cols() - blockCols);
}
};
// The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense
// that must be specialized for direct and non-direct access...
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
: public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel>
{
typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl;
typedef typename XprType::Index Index;
public:
typedef Impl Base;
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
EIGEN_DEVICE_FUNC inline BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {}
EIGEN_DEVICE_FUNC inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol) : Impl(xpr, a_startRow, a_startCol) {}
EIGEN_DEVICE_FUNC
inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol, Index blockRows, Index blockCols)
: Impl(xpr, a_startRow, a_startCol, blockRows, blockCols) {}
};
namespace internal {
/** \internal Internal implementation of dense Blocks in the general case. */
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class BlockImpl_dense
: public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel> >::type
{
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
public: public:
typedef typename internal::dense_xpr_base<BlockType>::type Base; typedef typename internal::dense_xpr_base<Block>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) EIGEN_DENSE_PUBLIC_INTERFACE(Block)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
class InnerIterator; class InnerIterator;
/** Column or Row constructor /** Column or Row constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr, Index i)
inline BlockImpl_dense(XprType& xpr, Index i)
: m_xpr(xpr), : m_xpr(xpr),
// It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
// and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
@@ -194,51 +116,60 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
m_blockRows(BlockRows==1 ? 1 : xpr.rows()), m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
m_blockCols(BlockCols==1 ? 1 : xpr.cols()) m_blockCols(BlockCols==1 ? 1 : xpr.cols())
{} {
eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
}
/** Fixed-size constructor /** Fixed-size constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr, Index startRow, Index startCol)
inline BlockImpl_dense(XprType& xpr, Index a_startRow, Index a_startCol) : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
m_blockRows(BlockRows), m_blockCols(BlockCols) m_blockRows(BlockRows), m_blockCols(BlockCols)
{} {
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
}
/** Dynamic-size constructor /** Dynamic-size constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr,
inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol,
Index a_startRow, Index a_startCol,
Index blockRows, Index blockCols) Index blockRows, Index blockCols)
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol), : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
m_blockRows(blockRows), m_blockCols(blockCols) m_blockRows(blockRows), m_blockCols(blockCols)
{} {
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
&& startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
}
EIGEN_DEVICE_FUNC inline Index rows() const { return m_blockRows.value(); } EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
EIGEN_DEVICE_FUNC inline Index cols() const { return m_blockCols.value(); }
EIGEN_DEVICE_FUNC inline Index rows() const { return m_blockRows.value(); }
inline Scalar& coeffRef(Index rowId, Index colId) inline Index cols() const { return m_blockCols.value(); }
inline Scalar& coeffRef(Index row, Index col)
{ {
EIGEN_STATIC_ASSERT_LVALUE(XprType) EIGEN_STATIC_ASSERT_LVALUE(XprType)
return m_xpr.const_cast_derived() return m_xpr.const_cast_derived()
.coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); .coeffRef(row + m_startRow.value(), col + m_startCol.value());
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const
inline const Scalar& coeffRef(Index rowId, Index colId) const
{ {
return m_xpr.derived() return m_xpr.derived()
.coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); .coeffRef(row + m_startRow.value(), col + m_startCol.value());
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const
{ {
return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value()); return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value());
} }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) inline Scalar& coeffRef(Index index)
{ {
EIGEN_STATIC_ASSERT_LVALUE(XprType) EIGEN_STATIC_ASSERT_LVALUE(XprType)
@@ -247,7 +178,6 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
return m_xpr.const_cast_derived() return m_xpr.const_cast_derived()
@@ -255,7 +185,6 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
} }
EIGEN_DEVICE_FUNC
inline const CoeffReturnType coeff(Index index) const inline const CoeffReturnType coeff(Index index) const
{ {
return m_xpr return m_xpr
@@ -264,17 +193,17 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
} }
template<int LoadMode> template<int LoadMode>
inline PacketScalar packet(Index rowId, Index colId) const inline PacketScalar packet(Index row, Index col) const
{ {
return m_xpr.template packet<Unaligned> return m_xpr.template packet<Unaligned>
(rowId + m_startRow.value(), colId + m_startCol.value()); (row + m_startRow.value(), col + m_startCol.value());
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index rowId, Index colId, const PacketScalar& val) inline void writePacket(Index row, Index col, const PacketScalar& x)
{ {
m_xpr.const_cast_derived().template writePacket<Unaligned> m_xpr.const_cast_derived().template writePacket<Unaligned>
(rowId + m_startRow.value(), colId + m_startCol.value(), val); (row + m_startRow.value(), col + m_startCol.value(), x);
} }
template<int LoadMode> template<int LoadMode>
@@ -286,33 +215,30 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index index, const PacketScalar& val) inline void writePacket(Index index, const PacketScalar& x)
{ {
m_xpr.const_cast_derived().template writePacket<Unaligned> m_xpr.const_cast_derived().template writePacket<Unaligned>
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val); m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
} }
#ifdef EIGEN_PARSED_BY_DOXYGEN #ifdef EIGEN_PARSED_BY_DOXYGEN
/** \sa MapBase::data() */ /** \sa MapBase::data() */
EIGEN_DEVICE_FUNC inline const Scalar* data() const; inline const Scalar* data() const;
EIGEN_DEVICE_FUNC inline Index innerStride() const; inline Index innerStride() const;
EIGEN_DEVICE_FUNC inline Index outerStride() const; inline Index outerStride() const;
#endif #endif
EIGEN_DEVICE_FUNC
const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const
{ {
return m_xpr; return m_xpr;
} }
EIGEN_DEVICE_FUNC
Index startRow() const Index startRow() const
{ {
return m_startRow.value(); return m_startRow.value();
} }
EIGEN_DEVICE_FUNC
Index startCol() const Index startCol() const
{ {
return m_startCol.value(); return m_startCol.value();
@@ -327,22 +253,21 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
}; };
/** \internal Internal implementation of dense Blocks in the direct access case.*/ /** \internal */
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true> class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
: public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> > : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> >
{ {
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
public: public:
typedef MapBase<BlockType> Base; typedef MapBase<Block> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) EIGEN_DENSE_PUBLIC_INTERFACE(Block)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
/** Column or Row constructor /** Column or Row constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr, Index i)
inline BlockImpl_dense(XprType& xpr, Index i)
: Base(internal::const_cast_ptr(&xpr.coeffRef( : Base(internal::const_cast_ptr(&xpr.coeffRef(
(BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0, (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
(BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)), (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
@@ -350,47 +275,51 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
BlockCols==1 ? 1 : xpr.cols()), BlockCols==1 ? 1 : xpr.cols()),
m_xpr(xpr) m_xpr(xpr)
{ {
eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
init(); init();
} }
/** Fixed-size constructor /** Fixed-size constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr, Index startRow, Index startCol)
inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr) : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
{ {
eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
init(); init();
} }
/** Dynamic-size constructor /** Dynamic-size constructor
*/ */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr,
inline BlockImpl_dense(XprType& xpr,
Index startRow, Index startCol, Index startRow, Index startCol,
Index blockRows, Index blockCols) Index blockRows, Index blockCols)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols), : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
m_xpr(xpr) m_xpr(xpr)
{ {
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
&& startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
init(); init();
} }
EIGEN_DEVICE_FUNC
const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const
{ {
return m_xpr; return m_xpr;
} }
/** \sa MapBase::innerStride() */ /** \sa MapBase::innerStride() */
EIGEN_DEVICE_FUNC
inline Index innerStride() const inline Index innerStride() const
{ {
return internal::traits<BlockType>::HasSameStorageOrderAsXprType return internal::traits<Block>::HasSameStorageOrderAsXprType
? m_xpr.innerStride() ? m_xpr.innerStride()
: m_xpr.outerStride(); : m_xpr.outerStride();
} }
/** \sa MapBase::outerStride() */ /** \sa MapBase::outerStride() */
EIGEN_DEVICE_FUNC
inline Index outerStride() const inline Index outerStride() const
{ {
return m_outerStride; return m_outerStride;
@@ -404,8 +333,7 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal used by allowAligned() */ /** \internal used by allowAligned() */
EIGEN_DEVICE_FUNC inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
: Base(data, blockRows, blockCols), m_xpr(xpr) : Base(data, blockRows, blockCols), m_xpr(xpr)
{ {
init(); init();
@@ -413,10 +341,9 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
#endif #endif
protected: protected:
EIGEN_DEVICE_FUNC
void init() void init()
{ {
m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType
? m_xpr.outerStride() ? m_xpr.outerStride()
: m_xpr.innerStride(); : m_xpr.innerStride();
} }
@@ -425,8 +352,6 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
Index m_outerStride; Index m_outerStride;
}; };
} // end namespace internal
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_BLOCK_H #endif // EIGEN_BLOCK_H

View File

@@ -29,9 +29,9 @@ struct all_unroller
}; };
template<typename Derived> template<typename Derived>
struct all_unroller<Derived, 0> struct all_unroller<Derived, 1>
{ {
static inline bool run(const Derived &/*mat*/) { return true; } static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
}; };
template<typename Derived> template<typename Derived>
@@ -55,9 +55,9 @@ struct any_unroller
}; };
template<typename Derived> template<typename Derived>
struct any_unroller<Derived, 0> struct any_unroller<Derived, 1>
{ {
static inline bool run(const Derived & /*mat*/) { return false; } static inline bool run(const Derived &mat) { return mat.coeff(0, 0); }
}; };
template<typename Derived> template<typename Derived>
@@ -85,7 +85,9 @@ inline bool DenseBase<Derived>::all() const
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT && SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
}; };
if(unroll) if(unroll)
return internal::all_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived()); return internal::all_unroller<Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived());
else else
{ {
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
@@ -109,7 +111,9 @@ inline bool DenseBase<Derived>::any() const
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT && SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
}; };
if(unroll) if(unroll)
return internal::any_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived()); return internal::any_unroller<Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived());
else else
{ {
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
@@ -129,26 +133,6 @@ 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

View File

@@ -8,4 +8,3 @@ INSTALL(FILES
ADD_SUBDIRECTORY(products) ADD_SUBDIRECTORY(products)
ADD_SUBDIRECTORY(util) ADD_SUBDIRECTORY(util)
ADD_SUBDIRECTORY(arch) ADD_SUBDIRECTORY(arch)
ADD_SUBDIRECTORY(functors)

View File

@@ -30,7 +30,6 @@ struct CommaInitializer
typedef typename XprType::Scalar Scalar; typedef typename XprType::Scalar Scalar;
typedef typename XprType::Index Index; typedef typename XprType::Index Index;
EIGEN_DEVICE_FUNC
inline CommaInitializer(XprType& xpr, const Scalar& s) inline CommaInitializer(XprType& xpr, const Scalar& s)
: m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1)
{ {
@@ -38,27 +37,13 @@ struct CommaInitializer
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other) inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other)
: m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows()) : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows())
{ {
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
EIGEN_DEVICE_FUNC
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 */
EIGEN_DEVICE_FUNC
CommaInitializer& operator,(const Scalar& s) CommaInitializer& operator,(const Scalar& s)
{ {
if (m_col==m_xpr.cols()) if (m_col==m_xpr.cols())
@@ -78,7 +63,6 @@ struct CommaInitializer
/* inserts a matrix expression in the target matrix */ /* inserts a matrix expression in the target matrix */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
CommaInitializer& operator,(const DenseBase<OtherDerived>& other) CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
{ {
if(other.cols()==0 || other.rows()==0) if(other.cols()==0 || other.rows()==0)
@@ -104,7 +88,6 @@ struct CommaInitializer
return *this; return *this;
} }
EIGEN_DEVICE_FUNC
inline ~CommaInitializer() inline ~CommaInitializer()
{ {
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows() eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
@@ -119,7 +102,6 @@ struct CommaInitializer
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished()); * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
* \endcode * \endcode
*/ */
EIGEN_DEVICE_FUNC
inline XprType& finished() { return m_xpr; } inline XprType& finished() { return m_xpr; }
XprType& m_xpr; // target expression XprType& m_xpr; // target expression
@@ -137,8 +119,6 @@ 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
*/ */
template<typename Derived> template<typename Derived>

File diff suppressed because it is too large Load Diff

View File

@@ -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_is_product_like<BINOP>::ret \ EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
? int(internal::scalar_product_traits<LHS, RHS>::Defined) \ ? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
: 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)
@@ -122,17 +122,15 @@ class CwiseBinaryOp : internal::no_assignment_operator,
typedef typename internal::remove_reference<LhsNested>::type _LhsNested; typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
typedef typename internal::remove_reference<RhsNested>::type _RhsNested; typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp()) : m_lhs(lhs), m_rhs(rhs), m_functor(func)
: m_lhs(aLhs), m_rhs(aRhs), m_functor(func)
{ {
EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar); EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
// require the sizes to match // require the sizes to match
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()); eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rows() const { EIGEN_STRONG_INLINE Index rows() const {
// return the fixed size type if available to enable compile time optimizations // return the fixed size type if available to enable compile time optimizations
if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic) if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic)
@@ -140,7 +138,6 @@ class CwiseBinaryOp : internal::no_assignment_operator,
else else
return m_lhs.rows(); return m_lhs.rows();
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index cols() const { EIGEN_STRONG_INLINE Index cols() const {
// return the fixed size type if available to enable compile time optimizations // return the fixed size type if available to enable compile time optimizations
if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic) if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic)
@@ -150,13 +147,10 @@ class CwiseBinaryOp : internal::no_assignment_operator,
} }
/** \returns the left hand side nested expression */ /** \returns the left hand side nested expression */
EIGEN_DEVICE_FUNC
const _LhsNested& lhs() const { return m_lhs; } const _LhsNested& lhs() const { return m_lhs; }
/** \returns the right hand side nested expression */ /** \returns the right hand side nested expression */
EIGEN_DEVICE_FUNC
const _RhsNested& rhs() const { return m_rhs; } const _RhsNested& rhs() const { return m_rhs; }
/** \returns the functor representing the binary operation */ /** \returns the functor representing the binary operation */
EIGEN_DEVICE_FUNC
const BinaryOp& functor() const { return m_functor; } const BinaryOp& functor() const { return m_functor; }
protected: protected:
@@ -175,21 +169,19 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base; typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE( Derived ) EIGEN_DENSE_PUBLIC_INTERFACE( Derived )
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{ {
return derived().functor()(derived().lhs().coeff(rowId, colId), return derived().functor()(derived().lhs().coeff(row, col),
derived().rhs().coeff(rowId, colId)); derived().rhs().coeff(row, col));
} }
template<int LoadMode> template<int LoadMode>
EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
{ {
return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(rowId, colId), return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col),
derived().rhs().template packet<LoadMode>(rowId, colId)); derived().rhs().template packet<LoadMode>(row, col));
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
{ {
return derived().functor()(derived().lhs().coeff(index), return derived().functor()(derived().lhs().coeff(index),
@@ -235,4 +227,3 @@ MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_CWISE_BINARY_OP_H #endif // EIGEN_CWISE_BINARY_OP_H

View File

@@ -54,34 +54,29 @@ class CwiseNullaryOp : internal::no_assignment_operator,
typedef typename internal::dense_xpr_base<CwiseNullaryOp>::type Base; typedef typename internal::dense_xpr_base<CwiseNullaryOp>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp) EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp)
EIGEN_DEVICE_FUNC CwiseNullaryOp(Index rows, Index cols, const NullaryOp& func = NullaryOp())
CwiseNullaryOp(Index nbRows, Index nbCols, const NullaryOp& func = NullaryOp()) : m_rows(rows), m_cols(cols), m_functor(func)
: m_rows(nbRows), m_cols(nbCols), m_functor(func)
{ {
eigen_assert(nbRows >= 0 eigen_assert(rows >= 0
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == nbRows) && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& nbCols >= 0 && cols >= 0
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == nbCols)); && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); } EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); } EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index rows, Index cols) const
EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{ {
return m_functor(rowId, colId); return m_functor(rows, cols);
} }
template<int LoadMode> template<int LoadMode>
EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
{ {
return m_functor.packetOp(rowId, colId); return m_functor.packetOp(row, col);
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
{ {
return m_functor(index); return m_functor(index);
@@ -94,7 +89,6 @@ class CwiseNullaryOp : internal::no_assignment_operator,
} }
/** \returns the functor representing the nullary operation */ /** \returns the functor representing the nullary operation */
EIGEN_DEVICE_FUNC
const NullaryOp& functor() const { return m_functor; } const NullaryOp& functor() const { return m_functor; }
protected: protected:
@@ -138,9 +132,6 @@ DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& f
* *
* The template parameter \a CustomNullaryOp is the type of the functor. * The template parameter \a CustomNullaryOp is the type of the functor.
* *
* Here is an example with C++11 random generators: \include random_cpp11.cpp
* Output: \verbinclude random_cpp11.out
*
* \sa class CwiseNullaryOp * \sa class CwiseNullaryOp
*/ */
template<typename Derived> template<typename Derived>
@@ -172,11 +163,11 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
/** \returns an expression of a constant matrix of value \a value /** \returns an expression of a constant matrix of value \a value
* *
* The parameters \a nbRows and \a nbCols are the number of rows and of columns of * The parameters \a rows and \a cols are the number of rows and of columns of
* the returned matrix. Must be compatible with this DenseBase type. * the returned matrix. Must be compatible with this DenseBase type.
* *
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, * This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
* it is redundant to pass \a nbRows and \a nbCols as arguments, so Zero() should be used * it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used
* instead. * instead.
* *
* The template parameter \a CustomNullaryOp is the type of the functor. * The template parameter \a CustomNullaryOp is the type of the functor.
@@ -185,9 +176,9 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
DenseBase<Derived>::Constant(Index nbRows, Index nbCols, const Scalar& value) DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
{ {
return DenseBase<Derived>::NullaryExpr(nbRows, nbCols, internal::scalar_constant_op<Scalar>(value)); return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_constant_op<Scalar>(value));
} }
/** \returns an expression of a constant matrix of value \a value /** \returns an expression of a constant matrix of value \a value
@@ -301,14 +292,14 @@ DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,true>(low,high,Derived::SizeAtCompileTime)); return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,true>(low,high,Derived::SizeAtCompileTime));
} }
/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */ /** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<typename Derived> template<typename Derived>
bool DenseBase<Derived>::isApproxToConstant bool DenseBase<Derived>::isApproxToConstant
(const Scalar& val, const RealScalar& prec) const (const Scalar& value, RealScalar prec) const
{ {
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
for(Index i = 0; i < rows(); ++i) for(Index i = 0; i < rows(); ++i)
if(!internal::isApprox(this->coeff(i, j), val, prec)) if(!internal::isApprox(this->coeff(i, j), value, prec))
return false; return false;
return true; return true;
} }
@@ -318,19 +309,19 @@ bool DenseBase<Derived>::isApproxToConstant
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ * \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<typename Derived> template<typename Derived>
bool DenseBase<Derived>::isConstant bool DenseBase<Derived>::isConstant
(const Scalar& val, const RealScalar& prec) const (const Scalar& value, RealScalar prec) const
{ {
return isApproxToConstant(val, prec); return isApproxToConstant(value, prec);
} }
/** Alias for setConstant(): sets all coefficients in this expression to \a val. /** Alias for setConstant(): sets all coefficients in this expression to \a value.
* *
* \sa setConstant(), Constant(), class CwiseNullaryOp * \sa setConstant(), Constant(), class CwiseNullaryOp
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val) EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& value)
{ {
setConstant(val); setConstant(value);
} }
/** Sets all coefficients in this expression to \a value. /** Sets all coefficients in this expression to \a value.
@@ -338,9 +329,9 @@ EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val)
* \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes() * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val) EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value)
{ {
return derived() = Constant(rows(), cols(), val); return derived() = Constant(rows(), cols(), value);
} }
/** Resizes to the given \a size, and sets all coefficients in this expression to the given \a value. /** Resizes to the given \a size, and sets all coefficients in this expression to the given \a value.
@@ -354,17 +345,17 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setConstant(Index size, const Scalar& val) PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value)
{ {
resize(size); resize(size);
return setConstant(val); return setConstant(value);
} }
/** Resizes to the given size, and sets all coefficients in this expression to the given \a value. /** Resizes to the given size, and sets all coefficients in this expression to the given \a value.
* *
* \param nbRows the new number of rows * \param rows the new number of rows
* \param nbCols the new number of columns * \param cols the new number of columns
* \param val the value to which all coefficients are set * \param value the value to which all coefficients are set
* *
* Example: \include Matrix_setConstant_int_int.cpp * Example: \include Matrix_setConstant_int_int.cpp
* Output: \verbinclude Matrix_setConstant_int_int.out * Output: \verbinclude Matrix_setConstant_int_int.out
@@ -373,10 +364,10 @@ PlainObjectBase<Derived>::setConstant(Index size, const Scalar& val)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setConstant(Index nbRows, Index nbCols, const Scalar& val) PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& value)
{ {
resize(nbRows, nbCols); resize(rows, cols);
return setConstant(val); return setConstant(value);
} }
/** /**
@@ -393,10 +384,10 @@ PlainObjectBase<Derived>::setConstant(Index nbRows, Index nbCols, const Scalar&
* \sa CwiseNullaryOp * \sa CwiseNullaryOp
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index size, const Scalar& low, const Scalar& high)
{ {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,false>(low,high,newSize)); return derived() = Derived::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size));
} }
/** /**
@@ -434,9 +425,9 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low,
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
DenseBase<Derived>::Zero(Index nbRows, Index nbCols) DenseBase<Derived>::Zero(Index rows, Index cols)
{ {
return Constant(nbRows, nbCols, Scalar(0)); return Constant(rows, cols, Scalar(0));
} }
/** \returns an expression of a zero vector. /** \returns an expression of a zero vector.
@@ -488,7 +479,7 @@ DenseBase<Derived>::Zero()
* \sa class CwiseNullaryOp, Zero() * \sa class CwiseNullaryOp, Zero()
*/ */
template<typename Derived> template<typename Derived>
bool DenseBase<Derived>::isZero(const RealScalar& prec) const bool DenseBase<Derived>::isZero(RealScalar prec) const
{ {
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
for(Index i = 0; i < rows(); ++i) for(Index i = 0; i < rows(); ++i)
@@ -521,16 +512,16 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setZero(Index newSize) PlainObjectBase<Derived>::setZero(Index size)
{ {
resize(newSize); resize(size);
return setConstant(Scalar(0)); return setConstant(Scalar(0));
} }
/** Resizes to the given size, and sets all coefficients in this expression to zero. /** Resizes to the given size, and sets all coefficients in this expression to zero.
* *
* \param nbRows the new number of rows * \param rows the new number of rows
* \param nbCols the new number of columns * \param cols the new number of columns
* *
* Example: \include Matrix_setZero_int_int.cpp * Example: \include Matrix_setZero_int_int.cpp
* Output: \verbinclude Matrix_setZero_int_int.out * Output: \verbinclude Matrix_setZero_int_int.out
@@ -539,9 +530,9 @@ PlainObjectBase<Derived>::setZero(Index newSize)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setZero(Index nbRows, Index nbCols) PlainObjectBase<Derived>::setZero(Index rows, Index cols)
{ {
resize(nbRows, nbCols); resize(rows, cols);
return setConstant(Scalar(0)); return setConstant(Scalar(0));
} }
@@ -549,7 +540,7 @@ PlainObjectBase<Derived>::setZero(Index nbRows, Index nbCols)
/** \returns an expression of a matrix where all coefficients equal one. /** \returns an expression of a matrix where all coefficients equal one.
* *
* The parameters \a nbRows and \a nbCols are the number of rows and of columns of * The parameters \a rows and \a cols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type. * the returned matrix. Must be compatible with this MatrixBase type.
* *
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, * This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
@@ -563,14 +554,14 @@ PlainObjectBase<Derived>::setZero(Index nbRows, Index nbCols)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
DenseBase<Derived>::Ones(Index nbRows, Index nbCols) DenseBase<Derived>::Ones(Index rows, Index cols)
{ {
return Constant(nbRows, nbCols, Scalar(1)); return Constant(rows, cols, Scalar(1));
} }
/** \returns an expression of a vector where all coefficients equal one. /** \returns an expression of a vector where all coefficients equal one.
* *
* The parameter \a newSize is the size of the returned vector. * The parameter \a size is the size of the returned vector.
* Must be compatible with this MatrixBase type. * Must be compatible with this MatrixBase type.
* *
* \only_for_vectors * \only_for_vectors
@@ -586,9 +577,9 @@ DenseBase<Derived>::Ones(Index nbRows, Index nbCols)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
DenseBase<Derived>::Ones(Index newSize) DenseBase<Derived>::Ones(Index size)
{ {
return Constant(newSize, Scalar(1)); return Constant(size, Scalar(1));
} }
/** \returns an expression of a fixed-size matrix or vector where all coefficients equal one. /** \returns an expression of a fixed-size matrix or vector where all coefficients equal one.
@@ -618,7 +609,7 @@ DenseBase<Derived>::Ones()
*/ */
template<typename Derived> template<typename Derived>
bool DenseBase<Derived>::isOnes bool DenseBase<Derived>::isOnes
(const RealScalar& prec) const (RealScalar prec) const
{ {
return isApproxToConstant(Scalar(1), prec); return isApproxToConstant(Scalar(1), prec);
} }
@@ -636,7 +627,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
return setConstant(Scalar(1)); return setConstant(Scalar(1));
} }
/** Resizes to the given \a newSize, and sets all coefficients in this expression to one. /** Resizes to the given \a size, and sets all coefficients in this expression to one.
* *
* \only_for_vectors * \only_for_vectors
* *
@@ -647,16 +638,16 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setOnes(Index newSize) PlainObjectBase<Derived>::setOnes(Index size)
{ {
resize(newSize); resize(size);
return setConstant(Scalar(1)); return setConstant(Scalar(1));
} }
/** Resizes to the given size, and sets all coefficients in this expression to one. /** Resizes to the given size, and sets all coefficients in this expression to one.
* *
* \param nbRows the new number of rows * \param rows the new number of rows
* \param nbCols the new number of columns * \param cols the new number of columns
* *
* Example: \include Matrix_setOnes_int_int.cpp * Example: \include Matrix_setOnes_int_int.cpp
* Output: \verbinclude Matrix_setOnes_int_int.out * Output: \verbinclude Matrix_setOnes_int_int.out
@@ -665,9 +656,9 @@ PlainObjectBase<Derived>::setOnes(Index newSize)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setOnes(Index nbRows, Index nbCols) PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
{ {
resize(nbRows, nbCols); resize(rows, cols);
return setConstant(Scalar(1)); return setConstant(Scalar(1));
} }
@@ -675,7 +666,7 @@ PlainObjectBase<Derived>::setOnes(Index nbRows, Index nbCols)
/** \returns an expression of the identity matrix (not necessarily square). /** \returns an expression of the identity matrix (not necessarily square).
* *
* The parameters \a nbRows and \a nbCols are the number of rows and of columns of * The parameters \a rows and \a cols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type. * the returned matrix. Must be compatible with this MatrixBase type.
* *
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, * This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
@@ -689,9 +680,9 @@ PlainObjectBase<Derived>::setOnes(Index nbRows, Index nbCols)
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
MatrixBase<Derived>::Identity(Index nbRows, Index nbCols) MatrixBase<Derived>::Identity(Index rows, Index cols)
{ {
return DenseBase<Derived>::NullaryExpr(nbRows, nbCols, internal::scalar_identity_op<Scalar>()); return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_identity_op<Scalar>());
} }
/** \returns an expression of the identity matrix (not necessarily square). /** \returns an expression of the identity matrix (not necessarily square).
@@ -723,7 +714,7 @@ MatrixBase<Derived>::Identity()
*/ */
template<typename Derived> template<typename Derived>
bool MatrixBase<Derived>::isIdentity bool MatrixBase<Derived>::isIdentity
(const RealScalar& prec) const (RealScalar prec) const
{ {
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
{ {
@@ -749,7 +740,6 @@ namespace internal {
template<typename Derived, bool Big = (Derived::SizeAtCompileTime>=16)> template<typename Derived, bool Big = (Derived::SizeAtCompileTime>=16)>
struct setIdentity_impl struct setIdentity_impl
{ {
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Derived& run(Derived& m) static EIGEN_STRONG_INLINE Derived& run(Derived& m)
{ {
return m = Derived::Identity(m.rows(), m.cols()); return m = Derived::Identity(m.rows(), m.cols());
@@ -760,7 +750,6 @@ template<typename Derived>
struct setIdentity_impl<Derived, true> struct setIdentity_impl<Derived, true>
{ {
typedef typename Derived::Index Index; typedef typename Derived::Index Index;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Derived& run(Derived& m) static EIGEN_STRONG_INLINE Derived& run(Derived& m)
{ {
m.setZero(); m.setZero();
@@ -787,8 +776,8 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
/** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this. /** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this.
* *
* \param nbRows the new number of rows * \param rows the new number of rows
* \param nbCols the new number of columns * \param cols the new number of columns
* *
* Example: \include Matrix_setIdentity_int_int.cpp * Example: \include Matrix_setIdentity_int_int.cpp
* Output: \verbinclude Matrix_setIdentity_int_int.out * Output: \verbinclude Matrix_setIdentity_int_int.out
@@ -796,9 +785,9 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index nbRows, Index nbCols) EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols)
{ {
derived().resize(nbRows, nbCols); derived().resize(rows, cols);
return setIdentity(); return setIdentity();
} }
@@ -809,10 +798,10 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index nbRows, Inde
* \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index newSize, Index i) EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index size, Index i)
{ {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i); return BasisReturnType(SquareMatrixType::Identity(size,size), i);
} }
/** \returns an expression of the i-th unit (basis) vector. /** \returns an expression of the i-th unit (basis) vector.

View File

@@ -64,26 +64,20 @@ class CwiseUnaryOp : internal::no_assignment_operator,
typedef typename CwiseUnaryOpImpl<UnaryOp, XprType,typename internal::traits<XprType>::StorageKind>::Base Base; typedef typename CwiseUnaryOpImpl<UnaryOp, XprType,typename internal::traits<XprType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp) EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
EIGEN_DEVICE_FUNC
inline CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp()) inline CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp())
: m_xpr(xpr), m_functor(func) {} : m_xpr(xpr), m_functor(func) {}
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rows() const { return m_xpr.rows(); } EIGEN_STRONG_INLINE Index rows() const { return m_xpr.rows(); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index cols() const { return m_xpr.cols(); } EIGEN_STRONG_INLINE Index cols() const { return m_xpr.cols(); }
/** \returns the functor representing the unary operation */ /** \returns the functor representing the unary operation */
EIGEN_DEVICE_FUNC
const UnaryOp& functor() const { return m_functor; } const UnaryOp& functor() const { return m_functor; }
/** \returns the nested expression */ /** \returns the nested expression */
EIGEN_DEVICE_FUNC
const typename internal::remove_all<typename XprType::Nested>::type& const typename internal::remove_all<typename XprType::Nested>::type&
nestedExpression() const { return m_xpr; } nestedExpression() const { return m_xpr; }
/** \returns the nested expression */ /** \returns the nested expression */
EIGEN_DEVICE_FUNC
typename internal::remove_all<typename XprType::Nested>::type& typename internal::remove_all<typename XprType::Nested>::type&
nestedExpression() { return m_xpr.const_cast_derived(); } nestedExpression() { return m_xpr.const_cast_derived(); }
@@ -104,26 +98,23 @@ class CwiseUnaryOpImpl<UnaryOp,XprType,Dense>
typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base; typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived) EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{ {
return derived().functor()(derived().nestedExpression().coeff(rowId, colId)); return derived().functor()(derived().nestedExpression().coeff(row, col));
} }
template<int LoadMode> template<int LoadMode>
EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
{ {
return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(rowId, colId)); return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(row, col));
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
{ {
return derived().functor()(derived().nestedExpression().coeff(index)); return derived().functor()(derived().nestedExpression().coeff(index));
} }
template<int LoadMode> template<int LoadMode>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
{ {
return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(index)); return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(index));

View File

@@ -13,16 +13,6 @@
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
* *
@@ -182,7 +172,6 @@ template<typename Derived> class DenseBase
/** \returns the number of nonzero coefficients which is in practice the number /** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */ * of stored coefficients. */
EIGEN_DEVICE_FUNC
inline Index nonZeros() const { return size(); } inline Index nonZeros() const { return size(); }
/** \returns true if either the number of rows or the number of columns is equal to 1. /** \returns true if either the number of rows or the number of columns is equal to 1.
* In other words, this function returns * In other words, this function returns
@@ -194,7 +183,6 @@ template<typename Derived> class DenseBase
* \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension * \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a
* column-major matrix, and the number of rows for a row-major matrix. */ * column-major matrix, and the number of rows for a row-major matrix. */
EIGEN_DEVICE_FUNC
Index outerSize() const Index outerSize() const
{ {
return IsVectorAtCompileTime ? 1 return IsVectorAtCompileTime ? 1
@@ -206,7 +194,6 @@ template<typename Derived> class DenseBase
* \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension * \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a
* column-major matrix, and the number of columns for a row-major matrix. */ * column-major matrix, and the number of columns for a row-major matrix. */
EIGEN_DEVICE_FUNC
Index innerSize() const Index innerSize() const
{ {
return IsVectorAtCompileTime ? this->size() return IsVectorAtCompileTime ? this->size()
@@ -217,23 +204,21 @@ template<typename Derived> class DenseBase
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
* nothing else. * nothing else.
*/ */
EIGEN_DEVICE_FUNC void resize(Index size)
void resize(Index newSize)
{ {
EIGEN_ONLY_USED_FOR_DEBUG(newSize); EIGEN_ONLY_USED_FOR_DEBUG(size);
eigen_assert(newSize == this->size() eigen_assert(size == this->size()
&& "DenseBase::resize() does not actually allow to resize."); && "DenseBase::resize() does not actually allow to resize.");
} }
/** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
* nothing else. * nothing else.
*/ */
EIGEN_DEVICE_FUNC void resize(Index rows, Index cols)
void resize(Index nbRows, Index nbCols)
{ {
EIGEN_ONLY_USED_FOR_DEBUG(nbRows); EIGEN_ONLY_USED_FOR_DEBUG(rows);
EIGEN_ONLY_USED_FOR_DEBUG(nbCols); EIGEN_ONLY_USED_FOR_DEBUG(cols);
eigen_assert(nbRows == this->rows() && nbCols == this->cols() eigen_assert(rows == this->rows() && cols == this->cols()
&& "DenseBase::resize() does not actually allow to resize."); && "DenseBase::resize() does not actually allow to resize.");
} }
@@ -252,54 +237,42 @@ template<typename Derived> class DenseBase
/** Copies \a other into *this. \returns a reference to *this. */ /** Copies \a other into *this. \returns a reference to *this. */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const DenseBase<OtherDerived>& other); Derived& operator=(const DenseBase<OtherDerived>& other);
/** Special case of the template operator=, in order to prevent the compiler /** Special case of the template operator=, in order to prevent the compiler
* from generating a default operator= (issue hit with g++ 4.1) * from generating a default operator= (issue hit with g++ 4.1)
*/ */
EIGEN_DEVICE_FUNC
Derived& operator=(const DenseBase& other); Derived& operator=(const DenseBase& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const EigenBase<OtherDerived> &other); Derived& operator=(const EigenBase<OtherDerived> &other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator+=(const EigenBase<OtherDerived> &other); Derived& operator+=(const EigenBase<OtherDerived> &other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator-=(const EigenBase<OtherDerived> &other); Derived& operator-=(const EigenBase<OtherDerived> &other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const ReturnByValue<OtherDerived>& func); Derived& operator=(const ReturnByValue<OtherDerived>& func);
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
/** 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>
EIGEN_DEVICE_FUNC
Derived& lazyAssign(const DenseBase<OtherDerived>& other); Derived& lazyAssign(const DenseBase<OtherDerived>& other);
#endif // not EIGEN_PARSED_BY_DOXYGEN #endif // not EIGEN_PARSED_BY_DOXYGEN
EIGEN_DEVICE_FUNC
CommaInitializer<Derived> operator<< (const Scalar& s); CommaInitializer<Derived> operator<< (const Scalar& s);
template<unsigned int Added,unsigned int Removed> template<unsigned int Added,unsigned int Removed>
const Flagged<Derived, Added, Removed> flagged() const; const Flagged<Derived, Added, Removed> flagged() const;
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other); CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other);
EIGEN_DEVICE_FUNC
Eigen::Transpose<Derived> transpose(); Eigen::Transpose<Derived> transpose();
typedef typename internal::add_const<Transpose<const Derived> >::type ConstTransposeReturnType; typedef const Transpose<const Derived> ConstTransposeReturnType;
EIGEN_DEVICE_FUNC
ConstTransposeReturnType transpose() const; ConstTransposeReturnType transpose() const;
EIGEN_DEVICE_FUNC
void transposeInPlace(); void transposeInPlace();
#ifndef EIGEN_NO_DEBUG #ifndef EIGEN_NO_DEBUG
protected: protected:
@@ -308,69 +281,86 @@ template<typename Derived> class DenseBase
public: public:
#endif #endif
typedef VectorBlock<Derived> SegmentReturnType;
typedef const VectorBlock<const Derived> ConstSegmentReturnType;
template<int Size> struct FixedSegmentReturnType { typedef VectorBlock<Derived, Size> Type; };
template<int Size> struct ConstFixedSegmentReturnType { typedef const VectorBlock<const Derived, Size> Type; };
EIGEN_DEVICE_FUNC static const ConstantReturnType // Note: The "DenseBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
SegmentReturnType segment(Index start, Index size);
typename DenseBase::ConstSegmentReturnType segment(Index start, Index size) const;
SegmentReturnType head(Index size);
typename DenseBase::ConstSegmentReturnType head(Index size) const;
SegmentReturnType tail(Index size);
typename DenseBase::ConstSegmentReturnType tail(Index size) const;
template<int Size> typename FixedSegmentReturnType<Size>::Type head();
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type head() const;
template<int Size> typename FixedSegmentReturnType<Size>::Type tail();
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type tail() const;
template<int Size> typename FixedSegmentReturnType<Size>::Type segment(Index start);
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type segment(Index start) const;
static const ConstantReturnType
Constant(Index rows, Index cols, const Scalar& value); Constant(Index rows, Index cols, const Scalar& value);
EIGEN_DEVICE_FUNC static const ConstantReturnType static const ConstantReturnType
Constant(Index size, const Scalar& value); Constant(Index size, const Scalar& value);
EIGEN_DEVICE_FUNC static const ConstantReturnType static const ConstantReturnType
Constant(const Scalar& value); Constant(const Scalar& value);
EIGEN_DEVICE_FUNC static const SequentialLinSpacedReturnType static const SequentialLinSpacedReturnType
LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high); LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high);
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType static const RandomAccessLinSpacedReturnType
LinSpaced(Index size, const Scalar& low, const Scalar& high); LinSpaced(Index size, const Scalar& low, const Scalar& high);
EIGEN_DEVICE_FUNC static const SequentialLinSpacedReturnType static const SequentialLinSpacedReturnType
LinSpaced(Sequential_t, const Scalar& low, const Scalar& high); LinSpaced(Sequential_t, const Scalar& low, const Scalar& high);
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType static const RandomAccessLinSpacedReturnType
LinSpaced(const Scalar& low, const Scalar& high); LinSpaced(const Scalar& low, const Scalar& high);
template<typename CustomNullaryOp> EIGEN_DEVICE_FUNC template<typename CustomNullaryOp>
static const CwiseNullaryOp<CustomNullaryOp, Derived> static const CwiseNullaryOp<CustomNullaryOp, Derived>
NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func); NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func);
template<typename CustomNullaryOp> EIGEN_DEVICE_FUNC template<typename CustomNullaryOp>
static const CwiseNullaryOp<CustomNullaryOp, Derived> static const CwiseNullaryOp<CustomNullaryOp, Derived>
NullaryExpr(Index size, const CustomNullaryOp& func); NullaryExpr(Index size, const CustomNullaryOp& func);
template<typename CustomNullaryOp> EIGEN_DEVICE_FUNC template<typename CustomNullaryOp>
static const CwiseNullaryOp<CustomNullaryOp, Derived> static const CwiseNullaryOp<CustomNullaryOp, Derived>
NullaryExpr(const CustomNullaryOp& func); NullaryExpr(const CustomNullaryOp& func);
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero(Index rows, Index cols); static const ConstantReturnType Zero(Index rows, Index cols);
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero(Index size); static const ConstantReturnType Zero(Index size);
EIGEN_DEVICE_FUNC static const ConstantReturnType Zero(); static const ConstantReturnType Zero();
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index rows, Index cols); static const ConstantReturnType Ones(Index rows, Index cols);
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(Index size); static const ConstantReturnType Ones(Index size);
EIGEN_DEVICE_FUNC static const ConstantReturnType Ones(); static const ConstantReturnType Ones();
EIGEN_DEVICE_FUNC void fill(const Scalar& value); void fill(const Scalar& value);
EIGEN_DEVICE_FUNC Derived& setConstant(const Scalar& value); Derived& setConstant(const Scalar& value);
EIGEN_DEVICE_FUNC Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high); Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high);
EIGEN_DEVICE_FUNC Derived& setLinSpaced(const Scalar& low, const Scalar& high); Derived& setLinSpaced(const Scalar& low, const Scalar& high);
EIGEN_DEVICE_FUNC Derived& setZero(); Derived& setZero();
EIGEN_DEVICE_FUNC Derived& setOnes(); Derived& setOnes();
EIGEN_DEVICE_FUNC Derived& setRandom(); Derived& setRandom();
template<typename OtherDerived> EIGEN_DEVICE_FUNC template<typename OtherDerived>
bool isApprox(const DenseBase<OtherDerived>& other, bool isApprox(const DenseBase<OtherDerived>& other,
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC
bool isMuchSmallerThan(const RealScalar& other, bool isMuchSmallerThan(const RealScalar& other,
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
template<typename OtherDerived> EIGEN_DEVICE_FUNC template<typename OtherDerived>
bool isMuchSmallerThan(const DenseBase<OtherDerived>& other, bool isMuchSmallerThan(const DenseBase<OtherDerived>& other,
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC bool isApproxToConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC bool isZero(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isZero(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC bool isOnes(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isOnes(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
inline bool hasNaN() const;
inline bool allFinite() const;
EIGEN_DEVICE_FUNC
inline Derived& operator*=(const Scalar& other); inline Derived& operator*=(const Scalar& other);
EIGEN_DEVICE_FUNC
inline Derived& operator/=(const Scalar& other); inline Derived& operator/=(const Scalar& other);
typedef typename internal::add_const_on_value_type<typename internal::eval<Derived>::type>::type EvalReturnType; typedef typename internal::add_const_on_value_type<typename internal::eval<Derived>::type>::type EvalReturnType;
@@ -379,7 +369,6 @@ template<typename Derived> class DenseBase
* Notice that in the case of a plain matrix or vector (not an expression) this function just returns * Notice that in the case of a plain matrix or vector (not an expression) this function just returns
* a const reference, in order to avoid a useless copy. * a const reference, in order to avoid a useless copy.
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE EvalReturnType eval() const EIGEN_STRONG_INLINE EvalReturnType eval() const
{ {
// Even though MSVC does not honor strong inlining when the return type // Even though MSVC does not honor strong inlining when the return type
@@ -392,7 +381,6 @@ template<typename Derived> class DenseBase
* *
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void swap(const DenseBase<OtherDerived>& other, void swap(const DenseBase<OtherDerived>& other,
int = OtherDerived::ThisConstantIsPrivateInPlainObjectBase) int = OtherDerived::ThisConstantIsPrivateInPlainObjectBase)
{ {
@@ -403,52 +391,46 @@ template<typename Derived> class DenseBase
* *
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void swap(PlainObjectBase<OtherDerived>& other) void swap(PlainObjectBase<OtherDerived>& other)
{ {
SwapWrapper<Derived>(derived()).lazyAssign(other.derived()); SwapWrapper<Derived>(derived()).lazyAssign(other.derived());
} }
EIGEN_DEVICE_FUNC inline const NestByValue<Derived> nestByValue() const; inline const NestByValue<Derived> nestByValue() const;
EIGEN_DEVICE_FUNC inline const ForceAlignedAccess<Derived> forceAlignedAccess() const; inline const ForceAlignedAccess<Derived> forceAlignedAccess() const;
EIGEN_DEVICE_FUNC inline ForceAlignedAccess<Derived> forceAlignedAccess(); inline ForceAlignedAccess<Derived> forceAlignedAccess();
template<bool Enable> EIGEN_DEVICE_FUNC template<bool Enable> inline const typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf() const;
inline const typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf() const; template<bool Enable> inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf();
template<bool Enable> EIGEN_DEVICE_FUNC
inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf();
EIGEN_DEVICE_FUNC Scalar sum() const; Scalar sum() const;
EIGEN_DEVICE_FUNC Scalar mean() const; Scalar mean() const;
EIGEN_DEVICE_FUNC Scalar trace() const; Scalar trace() const;
EIGEN_DEVICE_FUNC Scalar prod() const; Scalar prod() const;
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar minCoeff() const; typename internal::traits<Derived>::Scalar minCoeff() const;
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar maxCoeff() const; typename internal::traits<Derived>::Scalar maxCoeff() const;
template<typename IndexType> EIGEN_DEVICE_FUNC template<typename IndexType>
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const; typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const;
template<typename IndexType> EIGEN_DEVICE_FUNC template<typename IndexType>
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const; typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const;
template<typename IndexType> EIGEN_DEVICE_FUNC template<typename IndexType>
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const; typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const;
template<typename IndexType> EIGEN_DEVICE_FUNC template<typename IndexType>
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const; typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const;
template<typename BinaryOp> template<typename BinaryOp>
EIGEN_DEVICE_FUNC
typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type
redux(const BinaryOp& func) const; redux(const BinaryOp& func) const;
template<typename Visitor> template<typename Visitor>
EIGEN_DEVICE_FUNC
void visit(Visitor& func) const; void visit(Visitor& func) const;
inline const WithFormat<Derived> format(const IOFormat& fmt) const; inline const WithFormat<Derived> format(const IOFormat& fmt) const;
/** \returns the unique coefficient of a 1x1 expression */ /** \returns the unique coefficient of a 1x1 expression */
EIGEN_DEVICE_FUNC
CoeffReturnType value() const CoeffReturnType value() const
{ {
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
@@ -456,8 +438,10 @@ template<typename Derived> class DenseBase
return derived().coeff(0,0); return derived().coeff(0,0);
} }
bool all() const; /////////// Array module ///////////
bool any() const;
bool all(void) const;
bool any(void) const;
Index count() const; Index count() const;
typedef VectorwiseOp<Derived, Horizontal> RowwiseReturnType; typedef VectorwiseOp<Derived, Horizontal> RowwiseReturnType;
@@ -481,11 +465,11 @@ 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, const typename ThenDerived::Scalar& elseScalar) const; select(const DenseBase<ThenDerived>& thenMatrix, 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(const typename ElseDerived::Scalar& thenScalar, const DenseBase<ElseDerived>& elseMatrix) const; select(typename ElseDerived::Scalar thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
template<int p> RealScalar lpNorm() const; template<int p> RealScalar lpNorm() const;
@@ -506,18 +490,27 @@ template<typename Derived> class DenseBase
# endif # endif
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS #undef EIGEN_CURRENT_STORAGE_BASE_CLASS
#ifdef EIGEN2_SUPPORT
Block<Derived> corner(CornerType type, Index cRows, Index cCols);
const Block<Derived> corner(CornerType type, Index cRows, Index cCols) const;
template<int CRows, int CCols>
Block<Derived, CRows, CCols> corner(CornerType type);
template<int CRows, int CCols>
const Block<Derived, CRows, CCols> corner(CornerType type) const;
#endif // EIGEN2_SUPPORT
// disable the use of evalTo for dense objects with a nice compilation error // disable the use of evalTo for dense objects with a nice compilation error
template<typename Dest> template<typename Dest> inline void evalTo(Dest& ) const
EIGEN_DEVICE_FUNC
inline void evalTo(Dest& ) const
{ {
EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS); EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS);
} }
protected: protected:
/** Default constructor. Do nothing. */ /** Default constructor. Do nothing. */
EIGEN_DEVICE_FUNC DenseBase() DenseBase()
{ {
/* Just checks for self-consistency of the flags. /* Just checks for self-consistency of the flags.
* Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down * Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down
@@ -530,9 +523,9 @@ template<typename Derived> class DenseBase
} }
private: private:
EIGEN_DEVICE_FUNC explicit DenseBase(int); explicit DenseBase(int);
EIGEN_DEVICE_FUNC DenseBase(int,int); DenseBase(int,int);
template<typename OtherDerived> EIGEN_DEVICE_FUNC explicit DenseBase(const DenseBase<OtherDerived>&); template<typename OtherDerived> explicit DenseBase(const DenseBase<OtherDerived>&);
}; };
} // end namespace Eigen } // end namespace Eigen

View File

@@ -61,7 +61,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
using Base::size; using Base::size;
using Base::derived; using Base::derived;
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const
{ {
return int(Derived::RowsAtCompileTime) == 1 ? 0 return int(Derived::RowsAtCompileTime) == 1 ? 0
@@ -70,7 +69,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
: inner; : inner;
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const
{ {
return int(Derived::ColsAtCompileTime) == 1 ? 0 return int(Derived::ColsAtCompileTime) == 1 ? 0
@@ -93,7 +91,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
* *
* \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const * \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
{ {
eigen_internal_assert(row >= 0 && row < rows() eigen_internal_assert(row >= 0 && row < rows()
@@ -101,7 +98,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
return derived().coeff(row, col); return derived().coeff(row, col);
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const
{ {
return coeff(rowIndexByOuterInner(outer, inner), return coeff(rowIndexByOuterInner(outer, inner),
@@ -112,7 +108,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
* *
* \sa operator()(Index,Index), operator[](Index) * \sa operator()(Index,Index), operator[](Index)
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
{ {
eigen_assert(row >= 0 && row < rows() eigen_assert(row >= 0 && row < rows()
@@ -135,7 +130,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
* \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const * \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
coeff(Index index) const coeff(Index index) const
{ {
@@ -152,12 +146,13 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
* z() const, w() const * z() const, w() const
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
operator[](Index index) const operator[](Index index) const
{ {
#ifndef EIGEN2_SUPPORT
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
#endif
eigen_assert(index >= 0 && index < size()); eigen_assert(index >= 0 && index < size());
return derived().coeff(index); return derived().coeff(index);
} }
@@ -172,7 +167,6 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
* z() const, w() const * z() const, w() const
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
operator()(Index index) const operator()(Index index) const
{ {
@@ -182,25 +176,21 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
/** equivalent to operator[](0). */ /** equivalent to operator[](0). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
x() const { return (*this)[0]; } x() const { return (*this)[0]; }
/** equivalent to operator[](1). */ /** equivalent to operator[](1). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
y() const { return (*this)[1]; } y() const { return (*this)[1]; }
/** equivalent to operator[](2). */ /** equivalent to operator[](2). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
z() const { return (*this)[2]; } z() const { return (*this)[2]; }
/** equivalent to operator[](3). */ /** equivalent to operator[](3). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType EIGEN_STRONG_INLINE CoeffReturnType
w() const { return (*this)[3]; } w() const { return (*this)[3]; }
@@ -321,7 +311,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* *
* \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index) * \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index)
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
{ {
eigen_internal_assert(row >= 0 && row < rows() eigen_internal_assert(row >= 0 && row < rows()
@@ -329,7 +318,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
return derived().coeffRef(row, col); return derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
coeffRefByOuterInner(Index outer, Index inner) coeffRefByOuterInner(Index outer, Index inner)
{ {
@@ -342,7 +330,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index) * \sa operator[](Index)
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
operator()(Index row, Index col) operator()(Index row, Index col)
{ {
@@ -367,7 +354,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index) * \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index)
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
coeffRef(Index index) coeffRef(Index index)
{ {
@@ -382,12 +368,13 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
operator[](Index index) operator[](Index index)
{ {
#ifndef EIGEN2_SUPPORT
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
#endif
eigen_assert(index >= 0 && index < size()); eigen_assert(index >= 0 && index < size());
return derived().coeffRef(index); return derived().coeffRef(index);
} }
@@ -401,7 +388,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
operator()(Index index) operator()(Index index)
{ {
@@ -411,25 +397,21 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
/** equivalent to operator[](0). */ /** equivalent to operator[](0). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
x() { return (*this)[0]; } x() { return (*this)[0]; }
/** equivalent to operator[](1). */ /** equivalent to operator[](1). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
y() { return (*this)[1]; } y() { return (*this)[1]; }
/** equivalent to operator[](2). */ /** equivalent to operator[](2). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
z() { return (*this)[2]; } z() { return (*this)[2]; }
/** equivalent to operator[](3). */ /** equivalent to operator[](3). */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& EIGEN_STRONG_INLINE Scalar&
w() { return (*this)[3]; } w() { return (*this)[3]; }
@@ -445,22 +427,22 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
template<int StoreMode> template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket EIGEN_STRONG_INLINE void writePacket
(Index row, Index col, const typename internal::packet_traits<Scalar>::type& val) (Index row, Index col, const typename internal::packet_traits<Scalar>::type& x)
{ {
eigen_internal_assert(row >= 0 && row < rows() eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols()); && col >= 0 && col < cols());
derived().template writePacket<StoreMode>(row,col,val); derived().template writePacket<StoreMode>(row,col,x);
} }
/** \internal */ /** \internal */
template<int StoreMode> template<int StoreMode>
EIGEN_STRONG_INLINE void writePacketByOuterInner EIGEN_STRONG_INLINE void writePacketByOuterInner
(Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& val) (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x)
{ {
writePacket<StoreMode>(rowIndexByOuterInner(outer, inner), writePacket<StoreMode>(rowIndexByOuterInner(outer, inner),
colIndexByOuterInner(outer, inner), colIndexByOuterInner(outer, inner),
val); x);
} }
/** \internal /** \internal
@@ -474,10 +456,10 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
*/ */
template<int StoreMode> template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket EIGEN_STRONG_INLINE void writePacket
(Index index, const typename internal::packet_traits<Scalar>::type& val) (Index index, const typename internal::packet_traits<Scalar>::type& x)
{ {
eigen_internal_assert(index >= 0 && index < size()); eigen_internal_assert(index >= 0 && index < size());
derived().template writePacket<StoreMode>(index,val); derived().template writePacket<StoreMode>(index,x);
} }
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -491,7 +473,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
{ {
eigen_internal_assert(row >= 0 && row < rows() eigen_internal_assert(row >= 0 && row < rows()
@@ -508,7 +489,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
{ {
eigen_internal_assert(index >= 0 && index < size()); eigen_internal_assert(index >= 0 && index < size());
@@ -517,7 +497,6 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
{ {
const Index row = rowIndexByOuterInner(outer,inner); const Index row = rowIndexByOuterInner(outer,inner);
@@ -602,7 +581,6 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
* *
* \sa outerStride(), rowStride(), colStride() * \sa outerStride(), rowStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index innerStride() const inline Index innerStride() const
{ {
return derived().innerStride(); return derived().innerStride();
@@ -613,7 +591,6 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
* *
* \sa innerStride(), rowStride(), colStride() * \sa innerStride(), rowStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index outerStride() const inline Index outerStride() const
{ {
return derived().outerStride(); return derived().outerStride();
@@ -629,7 +606,6 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
* *
* \sa innerStride(), outerStride(), colStride() * \sa innerStride(), outerStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index rowStride() const inline Index rowStride() const
{ {
return Derived::IsRowMajor ? outerStride() : innerStride(); return Derived::IsRowMajor ? outerStride() : innerStride();
@@ -639,7 +615,6 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
* *
* \sa innerStride(), outerStride(), rowStride() * \sa innerStride(), outerStride(), rowStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index colStride() const inline Index colStride() const
{ {
return Derived::IsRowMajor ? innerStride() : outerStride(); return Derived::IsRowMajor ? innerStride() : outerStride();
@@ -677,7 +652,6 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
* *
* \sa outerStride(), rowStride(), colStride() * \sa outerStride(), rowStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index innerStride() const inline Index innerStride() const
{ {
return derived().innerStride(); return derived().innerStride();
@@ -688,7 +662,6 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
* *
* \sa innerStride(), rowStride(), colStride() * \sa innerStride(), rowStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index outerStride() const inline Index outerStride() const
{ {
return derived().outerStride(); return derived().outerStride();
@@ -704,7 +677,6 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
* *
* \sa innerStride(), outerStride(), colStride() * \sa innerStride(), outerStride(), colStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index rowStride() const inline Index rowStride() const
{ {
return Derived::IsRowMajor ? outerStride() : innerStride(); return Derived::IsRowMajor ? outerStride() : innerStride();
@@ -714,7 +686,6 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
* *
* \sa innerStride(), outerStride(), rowStride() * \sa innerStride(), outerStride(), rowStride()
*/ */
EIGEN_DEVICE_FUNC
inline Index colStride() const inline Index colStride() const
{ {
return Derived::IsRowMajor ? innerStride() : outerStride(); return Derived::IsRowMajor ? innerStride() : outerStride();

View File

@@ -3,7 +3,7 @@
// //
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com> // Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2010-2013 Hauke Heibel <hauke.heibel@gmail.com> // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
// //
// This Source Code Form is subject to the terms of the Mozilla // 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 // Public License v. 2.0. If a copy of the MPL was not distributed
@@ -24,39 +24,19 @@ namespace internal {
struct constructor_without_unaligned_array_assert {}; struct constructor_without_unaligned_array_assert {};
template<typename T, int Size>
EIGEN_DEVICE_FUNC
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.
*/ */
template <typename T, int Size, int MatrixOrArrayOptions, template <typename T, int Size, int MatrixOrArrayOptions,
int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0 int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
: (((Size*sizeof(T))%EIGEN_ALIGN_BYTES)==0) ? EIGEN_ALIGN_BYTES : (((Size*sizeof(T))%16)==0) ? 16
: 0 > : 0 >
struct plain_array struct plain_array
{ {
T array[Size]; T array[Size];
plain_array() {}
EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {}
plain_array()
{
check_static_allocation_size<T,Size>();
}
EIGEN_DEVICE_FUNC
plain_array(constructor_without_unaligned_array_assert)
{
check_static_allocation_size<T,Size>();
}
}; };
#if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT) #if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
@@ -68,43 +48,32 @@ struct plain_array
template<typename PtrType> template<typename PtrType>
EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; } EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \ #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & (sizemask)) == 0 \ eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & sizemask) == 0 \
&& "this assertion is explained here: " \ && "this assertion is explained here: " \
"http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
" **** READ THIS WEB PAGE !!! ****"); " **** READ THIS WEB PAGE !!! ****");
#else #else
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \ #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
eigen_assert((reinterpret_cast<size_t>(array) & (sizemask)) == 0 \ eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
&& "this assertion is explained here: " \ && "this assertion is explained here: " \
"http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
" **** READ THIS WEB PAGE !!! ****"); " **** READ THIS WEB PAGE !!! ****");
#endif #endif
template <typename T, int Size, int MatrixOrArrayOptions> template <typename T, int Size, int MatrixOrArrayOptions>
struct plain_array<T, Size, MatrixOrArrayOptions, EIGEN_ALIGN_BYTES> struct plain_array<T, Size, MatrixOrArrayOptions, 16>
{ {
EIGEN_USER_ALIGN_DEFAULT T array[Size]; EIGEN_USER_ALIGN16 T array[Size];
plain_array() { EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf) }
EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {}
plain_array()
{
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(EIGEN_ALIGN_BYTES-1);
check_static_allocation_size<T,Size>();
}
EIGEN_DEVICE_FUNC
plain_array(constructor_without_unaligned_array_assert)
{
check_static_allocation_size<T,Size>();
}
}; };
template <typename T, int MatrixOrArrayOptions, int Alignment> template <typename T, int MatrixOrArrayOptions, int Alignment>
struct plain_array<T, 0, MatrixOrArrayOptions, Alignment> struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
{ {
EIGEN_USER_ALIGN_DEFAULT T array[1]; EIGEN_USER_ALIGN16 T array[1];
EIGEN_DEVICE_FUNC plain_array() {} plain_array() {}
EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {} plain_array(constructor_without_unaligned_array_assert) {}
}; };
} // end namespace internal } // end namespace internal
@@ -128,44 +97,33 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() {} inline explicit DenseStorage() {}
EIGEN_DEVICE_FUNC inline DenseStorage(internal::constructor_without_unaligned_array_assert)
DenseStorage(internal::constructor_without_unaligned_array_assert)
: m_data(internal::constructor_without_unaligned_array_assert()) {} : m_data(internal::constructor_without_unaligned_array_assert()) {}
EIGEN_DEVICE_FUNC inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {} inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
EIGEN_DEVICE_FUNC static inline DenseIndex rows(void) {return _Rows;}
DenseStorage& operator=(const DenseStorage& other) static inline DenseIndex cols(void) {return _Cols;}
{ inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
if (this != &other) m_data = other.m_data; inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
return *this; inline const T *data() const { return m_data.array; }
} inline T *data() { return m_data.array; }
EIGEN_DEVICE_FUNC DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
EIGEN_DEVICE_FUNC static DenseIndex rows(void) {return _Rows;}
EIGEN_DEVICE_FUNC static DenseIndex cols(void) {return _Cols;}
EIGEN_DEVICE_FUNC void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC void resize(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
}; };
// null matrix // null matrix
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options> template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
{ {
public: public:
EIGEN_DEVICE_FUNC DenseStorage() {} inline explicit DenseStorage() {}
EIGEN_DEVICE_FUNC DenseStorage(internal::constructor_without_unaligned_array_assert) {} inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage&) {} inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage&) { return *this; } inline void swap(DenseStorage& ) {}
EIGEN_DEVICE_FUNC DenseStorage(DenseIndex,DenseIndex,DenseIndex) {} static inline DenseIndex rows(void) {return _Rows;}
EIGEN_DEVICE_FUNC void swap(DenseStorage& ) {} static inline DenseIndex cols(void) {return _Cols;}
EIGEN_DEVICE_FUNC static DenseIndex rows(void) {return _Rows;} inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC static DenseIndex cols(void) {return _Cols;} inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
EIGEN_DEVICE_FUNC void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {} inline const T *data() const { return 0; }
EIGEN_DEVICE_FUNC void resize(DenseIndex,DenseIndex,DenseIndex) {} inline T *data() { return 0; }
EIGEN_DEVICE_FUNC const T *data() const { return 0; }
EIGEN_DEVICE_FUNC T *data() { return 0; }
}; };
// more specializations for null matrices; these are necessary to resolve ambiguities // more specializations for null matrices; these are necessary to resolve ambiguities
@@ -185,29 +143,18 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0), m_cols(0) {} inline explicit DenseStorage() : m_rows(0), m_cols(0) {}
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) {}
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {} inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex cols) : m_rows(rows), m_cols(cols) {}
DenseStorage& operator=(const DenseStorage& other) inline void swap(DenseStorage& other)
{
if (this != &other)
{
m_data = other.m_data;
m_rows = other.m_rows;
m_cols = other.m_cols;
}
return *this;
}
DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); } { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
EIGEN_DEVICE_FUNC DenseIndex rows() const {return m_rows;} inline DenseIndex rows(void) const {return m_rows;}
EIGEN_DEVICE_FUNC DenseIndex cols() const {return m_cols;} inline DenseIndex cols(void) const {return m_cols;}
void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; } inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; } inline void resize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; } inline const T *data() const { return m_data.array; }
EIGEN_DEVICE_FUNC T *data() { return m_data.array; } inline T *data() { return m_data.array; }
}; };
// dynamic-size matrix with fixed-size storage and fixed width // dynamic-size matrix with fixed-size storage and fixed width
@@ -216,27 +163,17 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0) {} inline explicit DenseStorage() : m_rows(0) {}
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) {}
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {} inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex) : m_rows(rows) {}
DenseStorage& operator=(const DenseStorage& other) inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
{ inline DenseIndex rows(void) const {return m_rows;}
if (this != &other) inline DenseIndex cols(void) const {return _Cols;}
{ inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
m_data = other.m_data; inline void resize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
m_rows = other.m_rows; inline const T *data() const { return m_data.array; }
} inline T *data() { return m_data.array; }
return *this;
}
DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
EIGEN_DEVICE_FUNC DenseIndex rows(void) const {return m_rows;}
EIGEN_DEVICE_FUNC DenseIndex cols(void) const {return _Cols;}
void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
}; };
// dynamic-size matrix with fixed-size storage and fixed height // dynamic-size matrix with fixed-size storage and fixed height
@@ -245,27 +182,17 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_cols(0) {} inline explicit DenseStorage() : m_cols(0) {}
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) {}
DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {} inline DenseStorage(DenseIndex, DenseIndex, DenseIndex cols) : m_cols(cols) {}
DenseStorage& operator=(const DenseStorage& other) inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
{ inline DenseIndex rows(void) const {return _Rows;}
if (this != &other) inline DenseIndex cols(void) const {return m_cols;}
{ inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
m_data = other.m_data; inline void resize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
m_cols = other.m_cols; inline const T *data() const { return m_data.array; }
} inline T *data() { return m_data.array; }
return *this;
}
DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
EIGEN_DEVICE_FUNC DenseIndex rows(void) const {return _Rows;}
EIGEN_DEVICE_FUNC DenseIndex cols(void) const {return m_cols;}
void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
}; };
// purely dynamic matrix. // purely dynamic matrix.
@@ -275,57 +202,24 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_rows(0), m_cols(0) {} inline explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
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) {}
DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols) inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex cols)
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
DenseStorage(const DenseStorage& other) inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(other.m_rows*other.m_cols)) inline void swap(DenseStorage& other)
, m_rows(other.m_rows)
, m_cols(other.m_cols)
{
internal::smart_copy(other.m_data, other.m_data+other.m_rows*other.m_cols, m_data);
}
DenseStorage& operator=(const DenseStorage& other)
{
if (this != &other)
{
DenseStorage tmp(other);
this->swap(tmp);
}
return *this;
}
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
DenseStorage(DenseStorage&& other)
: m_data(std::move(other.m_data))
, m_rows(std::move(other.m_rows))
, m_cols(std::move(other.m_cols))
{
other.m_data = nullptr;
}
DenseStorage& operator=(DenseStorage&& other)
{
using std::swap;
swap(m_data, other.m_data);
swap(m_rows, other.m_rows);
swap(m_cols, other.m_cols);
return *this;
}
#endif
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
void swap(DenseStorage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); } { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
EIGEN_DEVICE_FUNC DenseIndex rows(void) const {return m_rows;} inline DenseIndex rows(void) const {return m_rows;}
EIGEN_DEVICE_FUNC DenseIndex cols(void) const {return m_cols;} inline DenseIndex cols(void) const {return m_cols;}
void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols) inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex cols)
{ {
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols); m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
m_rows = nbRows; m_rows = rows;
m_cols = nbCols; m_cols = cols;
} }
void resize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols) void resize(DenseIndex size, DenseIndex rows, DenseIndex cols)
{ {
if(size != m_rows*m_cols) if(size != m_rows*m_cols)
{ {
@@ -336,11 +230,11 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
m_data = 0; m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
} }
m_rows = nbRows; m_rows = rows;
m_cols = nbCols; m_cols = cols;
} }
EIGEN_DEVICE_FUNC const T *data() const { return m_data; } inline const T *data() const { return m_data; }
EIGEN_DEVICE_FUNC T *data() { return m_data; } inline T *data() { return m_data; }
}; };
// matrix with dynamic width and fixed height (so that matrix has dynamic size). // matrix with dynamic width and fixed height (so that matrix has dynamic size).
@@ -349,50 +243,20 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_cols(0) {} inline explicit DenseStorage() : m_data(0), m_cols(0) {}
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) {}
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 cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
DenseStorage(const DenseStorage& other) inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(_Rows*other.m_cols)) inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
, m_cols(other.m_cols) static inline DenseIndex rows(void) {return _Rows;}
{ inline DenseIndex cols(void) const {return m_cols;}
internal::smart_copy(other.m_data, other.m_data+_Rows*m_cols, m_data); inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols)
}
DenseStorage& operator=(const DenseStorage& other)
{
if (this != &other)
{
DenseStorage tmp(other);
this->swap(tmp);
}
return *this;
}
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
DenseStorage(DenseStorage&& other)
: m_data(std::move(other.m_data))
, m_cols(std::move(other.m_cols))
{
other.m_data = nullptr;
}
DenseStorage& operator=(DenseStorage&& other)
{
using std::swap;
swap(m_data, other.m_data);
swap(m_cols, other.m_cols);
return *this;
}
#endif
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
EIGEN_DEVICE_FUNC static DenseIndex rows(void) {return _Rows;}
EIGEN_DEVICE_FUNC DenseIndex cols(void) const {return m_cols;}
void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
{ {
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols); m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
m_cols = nbCols; m_cols = cols;
} }
EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex nbCols) EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex cols)
{ {
if(size != _Rows*m_cols) if(size != _Rows*m_cols)
{ {
@@ -403,10 +267,10 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
m_data = 0; m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
} }
m_cols = nbCols; m_cols = cols;
} }
EIGEN_DEVICE_FUNC const T *data() const { return m_data; } inline const T *data() const { return m_data; }
EIGEN_DEVICE_FUNC T *data() { return m_data; } inline T *data() { return m_data; }
}; };
// matrix with dynamic height and fixed width (so that matrix has dynamic size). // matrix with dynamic height and fixed width (so that matrix has dynamic size).
@@ -415,50 +279,20 @@ 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:
EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_rows(0) {} inline explicit DenseStorage() : m_data(0), m_rows(0) {}
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) {}
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 rows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
DenseStorage(const DenseStorage& other) inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(other.m_rows*_Cols)) inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
, m_rows(other.m_rows) inline DenseIndex rows(void) const {return m_rows;}
{ static inline DenseIndex cols(void) {return _Cols;}
internal::smart_copy(other.m_data, other.m_data+other.m_rows*_Cols, m_data); inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex)
}
DenseStorage& operator=(const DenseStorage& other)
{
if (this != &other)
{
DenseStorage tmp(other);
this->swap(tmp);
}
return *this;
}
#ifdef EIGEN_HAVE_RVALUE_REFERENCES
DenseStorage(DenseStorage&& other)
: m_data(std::move(other.m_data))
, m_rows(std::move(other.m_rows))
{
other.m_data = nullptr;
}
DenseStorage& operator=(DenseStorage&& other)
{
using std::swap;
swap(m_data, other.m_data);
swap(m_rows, other.m_rows);
return *this;
}
#endif
~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
EIGEN_DEVICE_FUNC DenseIndex rows(void) const {return m_rows;}
EIGEN_DEVICE_FUNC static DenseIndex cols(void) {return _Cols;}
void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
{ {
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols); m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
m_rows = nbRows; m_rows = rows;
} }
EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex nbRows, DenseIndex) EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex rows, DenseIndex)
{ {
if(size != m_rows*_Cols) if(size != m_rows*_Cols)
{ {
@@ -469,10 +303,10 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
m_data = 0; m_data = 0;
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
} }
m_rows = nbRows; m_rows = rows;
} }
EIGEN_DEVICE_FUNC const T *data() const { return m_data; } inline const T *data() const { return m_data; }
EIGEN_DEVICE_FUNC T *data() { return m_data; } inline T *data() { return m_data; }
}; };
} // end namespace Eigen } // end namespace Eigen

View File

@@ -41,12 +41,12 @@ struct traits<Diagonal<MatrixType,DiagIndex> >
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
typedef typename MatrixType::StorageKind StorageKind; typedef typename MatrixType::StorageKind StorageKind;
enum { enum {
RowsAtCompileTime = (int(DiagIndex) == DynamicIndex || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic RowsAtCompileTime = (int(DiagIndex) == Dynamic || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic
: (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
ColsAtCompileTime = 1, ColsAtCompileTime = 1,
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
: DiagIndex == DynamicIndex ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, : DiagIndex == Dynamic ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime,
MatrixType::MaxColsAtCompileTime) MatrixType::MaxColsAtCompileTime)
: (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), : (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0),
MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))),
@@ -61,39 +61,28 @@ struct traits<Diagonal<MatrixType,DiagIndex> >
}; };
} }
template<typename MatrixType, int _DiagIndex> class Diagonal template<typename MatrixType, int DiagIndex> class Diagonal
: public internal::dense_xpr_base< Diagonal<MatrixType,_DiagIndex> >::type : public internal::dense_xpr_base< Diagonal<MatrixType,DiagIndex> >::type
{ {
public: public:
enum { DiagIndex = _DiagIndex };
typedef typename internal::dense_xpr_base<Diagonal>::type Base; typedef typename internal::dense_xpr_base<Diagonal>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal)
EIGEN_DEVICE_FUNC inline Diagonal(MatrixType& matrix, Index index = DiagIndex) : m_matrix(matrix), m_index(index) {}
inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
EIGEN_DEVICE_FUNC
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()); }
EIGEN_USING_STD_MATH(min);
return m_index.value()<0 ? (min)(Index(m_matrix.cols()),Index(m_matrix.rows()+m_index.value()))
: (min)(Index(m_matrix.rows()),Index(m_matrix.cols()-m_index.value()));
}
EIGEN_DEVICE_FUNC
inline Index cols() const { return 1; } inline Index cols() const { return 1; }
EIGEN_DEVICE_FUNC
inline Index innerStride() const inline Index innerStride() const
{ {
return m_matrix.outerStride() + 1; return m_matrix.outerStride() + 1;
} }
EIGEN_DEVICE_FUNC
inline Index outerStride() const inline Index outerStride() const
{ {
return 0; return 0;
@@ -105,57 +94,47 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
const Scalar const Scalar
>::type ScalarWithConstIfNotLvalue; >::type ScalarWithConstIfNotLvalue;
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } inline const Scalar* data() const { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index row, Index) inline Scalar& coeffRef(Index row, Index)
{ {
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset()); return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index row, Index) const inline const Scalar& coeffRef(Index row, Index) const
{ {
return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset()); return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
} }
EIGEN_DEVICE_FUNC
inline CoeffReturnType coeff(Index row, Index) const inline CoeffReturnType coeff(Index row, Index) const
{ {
return m_matrix.coeff(row+rowOffset(), row+colOffset()); return m_matrix.coeff(row+rowOffset(), row+colOffset());
} }
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index)
inline Scalar& coeffRef(Index idx)
{ {
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset()); return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index index) const
inline const Scalar& coeffRef(Index idx) const
{ {
return m_matrix.const_cast_derived().coeffRef(idx+rowOffset(), idx+colOffset()); return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
} }
EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index index) const
inline CoeffReturnType coeff(Index idx) const
{ {
return m_matrix.coeff(idx+rowOffset(), idx+colOffset()); return m_matrix.coeff(index+rowOffset(), index+colOffset());
} }
EIGEN_DEVICE_FUNC
const typename internal::remove_all<typename MatrixType::Nested>::type& const typename internal::remove_all<typename MatrixType::Nested>::type&
nestedExpression() const nestedExpression() const
{ {
return m_matrix; return m_matrix;
} }
EIGEN_DEVICE_FUNC
int index() const int index() const
{ {
return m_index.value(); return m_index.value();
@@ -163,15 +142,12 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
protected: protected:
typename MatrixType::Nested m_matrix; typename MatrixType::Nested m_matrix;
const internal::variable_if_dynamicindex<Index, DiagIndex> m_index; const internal::variable_if_dynamic<Index, DiagIndex> m_index;
private: private:
// some compilers may fail to optimize std::max etc in case of compile-time constants... // some compilers may fail to optimize std::max etc in case of compile-time constants...
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); } EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); } EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; } EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; }
// triger a compile time error is someone try to call packet // triger a compile time error is someone try to call packet
template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const; template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const;
@@ -195,7 +171,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 typename MatrixBase<Derived>::ConstDiagonalReturnType inline const typename MatrixBase<Derived>::ConstDiagonalReturnType
MatrixBase<Derived>::diagonal() const MatrixBase<Derived>::diagonal() const
{ {
return ConstDiagonalReturnType(derived()); return ConstDiagonalReturnType(derived());
@@ -213,18 +189,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>::template DiagonalIndexReturnType<Dynamic>::Type
MatrixBase<Derived>::diagonal(Index index) MatrixBase<Derived>::diagonal(Index index)
{ {
return typename DiagonalIndexReturnType<DynamicIndex>::Type(derived(), index); return typename DiagonalIndexReturnType<Dynamic>::Type(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>::template ConstDiagonalIndexReturnType<Dynamic>::Type
MatrixBase<Derived>::diagonal(Index index) const MatrixBase<Derived>::diagonal(Index index) const
{ {
return typename ConstDiagonalIndexReturnType<DynamicIndex>::Type(derived(), index); return typename ConstDiagonalIndexReturnType<Dynamic>::Type(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

View File

@@ -37,64 +37,58 @@ class DiagonalBase : public EigenBase<Derived>
typedef DenseMatrixType DenseType; typedef DenseMatrixType DenseType;
typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject; typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject;
EIGEN_DEVICE_FUNC
inline const Derived& derived() const { return *static_cast<const Derived*>(this); } inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
EIGEN_DEVICE_FUNC
inline Derived& derived() { return *static_cast<Derived*>(this); } inline Derived& derived() { return *static_cast<Derived*>(this); }
EIGEN_DEVICE_FUNC
DenseMatrixType toDenseMatrix() const { return derived(); } DenseMatrixType toDenseMatrix() const { return derived(); }
template<typename DenseDerived> template<typename DenseDerived>
EIGEN_DEVICE_FUNC
void evalTo(MatrixBase<DenseDerived> &other) const; void evalTo(MatrixBase<DenseDerived> &other) const;
template<typename DenseDerived> template<typename DenseDerived>
EIGEN_DEVICE_FUNC
void addTo(MatrixBase<DenseDerived> &other) const void addTo(MatrixBase<DenseDerived> &other) const
{ other.diagonal() += diagonal(); } { other.diagonal() += diagonal(); }
template<typename DenseDerived> template<typename DenseDerived>
EIGEN_DEVICE_FUNC
void subTo(MatrixBase<DenseDerived> &other) const void subTo(MatrixBase<DenseDerived> &other) const
{ other.diagonal() -= diagonal(); } { other.diagonal() -= diagonal(); }
EIGEN_DEVICE_FUNC
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); } inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
EIGEN_DEVICE_FUNC
inline DiagonalVectorType& diagonal() { return derived().diagonal(); } inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
EIGEN_DEVICE_FUNC
inline Index rows() const { return diagonal().size(); } inline Index rows() const { return diagonal().size(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return diagonal().size(); } inline Index cols() const { return diagonal().size(); }
/** \returns the diagonal matrix product of \c *this by the matrix \a matrix.
*/
template<typename MatrixDerived> template<typename MatrixDerived>
EIGEN_DEVICE_FUNC
const DiagonalProduct<MatrixDerived, Derived, OnTheLeft> const DiagonalProduct<MatrixDerived, Derived, OnTheLeft>
operator*(const MatrixBase<MatrixDerived> &matrix) const operator*(const MatrixBase<MatrixDerived> &matrix) const;
{
return DiagonalProduct<MatrixDerived, Derived, OnTheLeft>(matrix.derived(), derived());
}
EIGEN_DEVICE_FUNC
inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> > inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> >
inverse() const inverse() const
{ {
return diagonal().cwiseInverse(); return diagonal().cwiseInverse();
} }
EIGEN_DEVICE_FUNC
inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> > inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> >
operator*(const Scalar& scalar) const operator*(const Scalar& scalar) const
{ {
return diagonal() * scalar; return diagonal() * scalar;
} }
EIGEN_DEVICE_FUNC
friend inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> > friend inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> >
operator*(const Scalar& scalar, const DiagonalBase& other) operator*(const Scalar& scalar, const DiagonalBase& other)
{ {
return other.diagonal() * scalar; return other.diagonal() * scalar;
} }
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived>
bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
{
return diagonal().isApprox(other.diagonal(), precision);
}
template<typename OtherDerived>
bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
{
return toDenseMatrix().isApprox(other, precision);
}
#endif
}; };
template<typename Derived> template<typename Derived>
@@ -152,31 +146,24 @@ class DiagonalMatrix
public: public:
/** const version of diagonal(). */ /** const version of diagonal(). */
EIGEN_DEVICE_FUNC
inline const DiagonalVectorType& diagonal() const { return m_diagonal; } inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
/** \returns a reference to the stored vector of diagonal coefficients. */ /** \returns a reference to the stored vector of diagonal coefficients. */
EIGEN_DEVICE_FUNC
inline DiagonalVectorType& diagonal() { return m_diagonal; } inline DiagonalVectorType& diagonal() { return m_diagonal; }
/** Default constructor without initialization */ /** Default constructor without initialization */
EIGEN_DEVICE_FUNC
inline DiagonalMatrix() {} inline DiagonalMatrix() {}
/** Constructs a diagonal matrix with given dimension */ /** Constructs a diagonal matrix with given dimension */
EIGEN_DEVICE_FUNC
inline DiagonalMatrix(Index dim) : m_diagonal(dim) {} inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
/** 2D constructor. */ /** 2D constructor. */
EIGEN_DEVICE_FUNC
inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {} inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {}
/** 3D constructor. */ /** 3D constructor. */
EIGEN_DEVICE_FUNC
inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {} inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}
/** Copy constructor. */ /** Copy constructor. */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {} inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {}
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -186,13 +173,11 @@ class DiagonalMatrix
/** generic constructor from expression of the diagonal coefficients */ /** generic constructor from expression of the diagonal coefficients */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other) explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other)
{} {}
/** Copy operator. */ /** Copy operator. */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other) DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other)
{ {
m_diagonal = other.diagonal(); m_diagonal = other.diagonal();
@@ -203,7 +188,6 @@ class DiagonalMatrix
/** This is a special case of the templated operator=. Its purpose is to /** This is a special case of the templated operator=. Its purpose is to
* prevent a default operator= from hiding the templated operator=. * prevent a default operator= from hiding the templated operator=.
*/ */
EIGEN_DEVICE_FUNC
DiagonalMatrix& operator=(const DiagonalMatrix& other) DiagonalMatrix& operator=(const DiagonalMatrix& other)
{ {
m_diagonal = other.diagonal(); m_diagonal = other.diagonal();
@@ -212,19 +196,14 @@ class DiagonalMatrix
#endif #endif
/** Resizes to given size. */ /** Resizes to given size. */
EIGEN_DEVICE_FUNC
inline void resize(Index size) { m_diagonal.resize(size); } inline void resize(Index size) { m_diagonal.resize(size); }
/** Sets all coefficients to zero. */ /** Sets all coefficients to zero. */
EIGEN_DEVICE_FUNC
inline void setZero() { m_diagonal.setZero(); } inline void setZero() { m_diagonal.setZero(); }
/** Resizes and sets all coefficients to zero. */ /** Resizes and sets all coefficients to zero. */
EIGEN_DEVICE_FUNC
inline void setZero(Index size) { m_diagonal.setZero(size); } inline void setZero(Index size) { m_diagonal.setZero(size); }
/** Sets this matrix to be the identity matrix of the current size. */ /** Sets this matrix to be the identity matrix of the current size. */
EIGEN_DEVICE_FUNC
inline void setIdentity() { m_diagonal.setOnes(); } inline void setIdentity() { m_diagonal.setOnes(); }
/** Sets this matrix to be the identity matrix of the given size. */ /** Sets this matrix to be the identity matrix of the given size. */
EIGEN_DEVICE_FUNC
inline void setIdentity(Index size) { m_diagonal.setOnes(size); } inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
}; };
@@ -271,11 +250,9 @@ class DiagonalWrapper
#endif #endif
/** Constructor from expression of diagonal coefficients to wrap. */ /** Constructor from expression of diagonal coefficients to wrap. */
EIGEN_DEVICE_FUNC inline DiagonalWrapper(DiagonalVectorType& diagonal) : m_diagonal(diagonal) {}
inline DiagonalWrapper(DiagonalVectorType& a_diagonal) : m_diagonal(a_diagonal) {}
/** \returns a const reference to the wrapped expression of diagonal coefficients. */ /** \returns a const reference to the wrapped expression of diagonal coefficients. */
EIGEN_DEVICE_FUNC
const DiagonalVectorType& diagonal() const { return m_diagonal; } const DiagonalVectorType& diagonal() const { return m_diagonal; }
protected: protected:
@@ -307,14 +284,13 @@ MatrixBase<Derived>::asDiagonal() const
* \sa asDiagonal() * \sa asDiagonal()
*/ */
template<typename Derived> template<typename Derived>
bool MatrixBase<Derived>::isDiagonal(const RealScalar& prec) const bool MatrixBase<Derived>::isDiagonal(RealScalar prec) const
{ {
using std::abs;
if(cols() != rows()) return false; if(cols() != rows()) return false;
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1); RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
{ {
RealScalar absOnDiagonal = abs(coeff(j,j)); RealScalar absOnDiagonal = internal::abs(coeff(j,j));
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal; if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
} }
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)

View File

@@ -26,15 +26,14 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
_StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor, _StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
_ScalarAccessOnDiag = !((int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheLeft) _PacketOnDiag = !((int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
||(int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheRight)), ||(int(_StorageOrder) == ColMajor && 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::DiagonalVectorType::Flags)&PacketAccessBit))), //_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::Flags)&PacketAccessBit))),
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))), _Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && ((!_PacketOnDiag) || (bool(int(DiagonalType::Flags)&PacketAccessBit))),
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit), Flags = (HereditaryBits & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
}; };
}; };
@@ -55,22 +54,14 @@ 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()));
} }
EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); } inline Index rows() const { return m_matrix.rows(); }
EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); } inline Index cols() const { return m_matrix.cols(); }
EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const 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
{ {
@@ -78,20 +69,12 @@ 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>
EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::true_type) const EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::true_type) const
@@ -105,7 +88,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) || (int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit)==AlignedBit) ? Aligned : Unaligned) DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? 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));
@@ -120,9 +103,19 @@ class DiagonalProduct : internal::no_assignment_operator,
template<typename Derived> template<typename Derived>
template<typename DiagonalDerived> template<typename DiagonalDerived>
inline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight> inline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &a_diagonal) const MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &diagonal) const
{ {
return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), a_diagonal.derived()); return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), diagonal.derived());
}
/** \returns the diagonal matrix product of \c *this by the matrix \a matrix.
*/
template<typename DiagonalDerived>
template<typename MatrixDerived>
inline const DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>
DiagonalBase<DiagonalDerived>::operator*(const MatrixBase<MatrixDerived> &matrix) const
{
return DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>(matrix.derived(), derived());
} }
} // end namespace Eigen } // end namespace Eigen

View File

@@ -29,7 +29,6 @@ template<typename T, typename U,
struct dot_nocheck struct dot_nocheck
{ {
typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar; typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
EIGEN_DEVICE_FUNC
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b) static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
{ {
return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum(); return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
@@ -40,7 +39,6 @@ template<typename T, typename U>
struct dot_nocheck<T, U, true> struct dot_nocheck<T, U, true>
{ {
typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar; typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
EIGEN_DEVICE_FUNC
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b) static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
{ {
return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum(); return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
@@ -61,7 +59,6 @@ struct dot_nocheck<T, U, true>
*/ */
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
{ {
@@ -76,6 +73,34 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other); return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
} }
#ifdef EIGEN2_SUPPORT
/** \returns the dot product of *this with other, with the Eigen2 convention that the dot product is linear in the first variable
* (conjugating the second variable). Of course this only makes a difference in the complex case.
*
* This method is only available in EIGEN2_SUPPORT mode.
*
* \only_for_vectors
*
* \sa dot()
*/
template<typename Derived>
template<typename OtherDerived>
typename internal::traits<Derived>::Scalar
MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
eigen_assert(size() == other.size());
return internal::dot_nocheck<OtherDerived,Derived>::run(other,*this);
}
#endif
//---------- implementation of L2 norm and related functions ---------- //---------- implementation of L2 norm and related functions ----------
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm. /** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
@@ -87,7 +112,7 @@ MatrixBase<Derived>::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 numext::real((*this).cwiseAbs2().sum()); return internal::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.
@@ -99,8 +124,7 @@ EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scala
template<typename Derived> template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
{ {
using std::sqrt; return internal::sqrt(squaredNorm());
return sqrt(squaredNorm());
} }
/** \returns an expression of the quotient of *this by its own norm. /** \returns an expression of the quotient of *this by its own norm.
@@ -139,10 +163,8 @@ template<typename Derived, int p>
struct lpNorm_selector struct lpNorm_selector
{ {
typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar; typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
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);
} }
}; };
@@ -150,7 +172,6 @@ struct lpNorm_selector
template<typename Derived> template<typename Derived>
struct lpNorm_selector<Derived, 1> struct lpNorm_selector<Derived, 1>
{ {
EIGEN_DEVICE_FUNC
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
{ {
return m.cwiseAbs().sum(); return m.cwiseAbs().sum();
@@ -160,7 +181,6 @@ struct lpNorm_selector<Derived, 1>
template<typename Derived> template<typename Derived>
struct lpNorm_selector<Derived, 2> struct lpNorm_selector<Derived, 2>
{ {
EIGEN_DEVICE_FUNC
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
{ {
return m.norm(); return m.norm();
@@ -170,7 +190,6 @@ struct lpNorm_selector<Derived, 2>
template<typename Derived> template<typename Derived>
struct lpNorm_selector<Derived, Infinity> struct lpNorm_selector<Derived, Infinity>
{ {
EIGEN_DEVICE_FUNC
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
{ {
return m.cwiseAbs().maxCoeff(); return m.cwiseAbs().maxCoeff();
@@ -204,11 +223,11 @@ MatrixBase<Derived>::lpNorm() const
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
bool MatrixBase<Derived>::isOrthogonal bool MatrixBase<Derived>::isOrthogonal
(const MatrixBase<OtherDerived>& other, const RealScalar& prec) const (const MatrixBase<OtherDerived>& other, RealScalar prec) const
{ {
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 numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm(); return internal::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,
@@ -223,7 +242,7 @@ bool MatrixBase<Derived>::isOrthogonal
* Output: \verbinclude MatrixBase_isUnitary.out * Output: \verbinclude MatrixBase_isUnitary.out
*/ */
template<typename Derived> template<typename Derived>
bool MatrixBase<Derived>::isUnitary(const RealScalar& prec) const bool MatrixBase<Derived>::isUnitary(RealScalar prec) const
{ {
typename Derived::Nested nested(derived()); typename Derived::Nested nested(derived());
for(Index i = 0; i < cols(); ++i) for(Index i = 0; i < cols(); ++i)

View File

@@ -31,40 +31,29 @@ template<typename Derived> struct EigenBase
typedef typename internal::traits<Derived>::Index Index; typedef typename internal::traits<Derived>::Index Index;
/** \returns a reference to the derived object */ /** \returns a reference to the derived object */
EIGEN_DEVICE_FUNC
Derived& derived() { return *static_cast<Derived*>(this); } Derived& derived() { return *static_cast<Derived*>(this); }
/** \returns a const reference to the derived object */ /** \returns a const reference to the derived object */
EIGEN_DEVICE_FUNC
const Derived& derived() const { return *static_cast<const Derived*>(this); } const Derived& derived() const { return *static_cast<const Derived*>(this); }
EIGEN_DEVICE_FUNC
inline Derived& const_cast_derived() const inline Derived& const_cast_derived() const
{ return *static_cast<Derived*>(const_cast<EigenBase*>(this)); } { return *static_cast<Derived*>(const_cast<EigenBase*>(this)); }
EIGEN_DEVICE_FUNC
inline const Derived& const_derived() const inline const Derived& const_derived() const
{ return *static_cast<const Derived*>(this); } { return *static_cast<const Derived*>(this); }
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */ /** \returns the number of rows. \sa cols(), RowsAtCompileTime */
EIGEN_DEVICE_FUNC
inline Index rows() const { return derived().rows(); } inline Index rows() const { return derived().rows(); }
/** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
EIGEN_DEVICE_FUNC
inline Index cols() const { return derived().cols(); } inline Index cols() const { return derived().cols(); }
/** \returns the number of coefficients, which is rows()*cols(). /** \returns the number of coefficients, which is rows()*cols().
* \sa rows(), cols(), SizeAtCompileTime. */ * \sa rows(), cols(), SizeAtCompileTime. */
EIGEN_DEVICE_FUNC
inline Index size() const { return rows() * cols(); } inline Index size() const { return rows() * cols(); }
/** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */ /** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */
template<typename Dest> template<typename Dest> inline void evalTo(Dest& dst) const
EIGEN_DEVICE_FUNC
inline void evalTo(Dest& dst) const
{ derived().evalTo(dst); } { derived().evalTo(dst); }
/** \internal Don't use it, but do the equivalent: \code dst += *this; \endcode */ /** \internal Don't use it, but do the equivalent: \code dst += *this; \endcode */
template<typename Dest> template<typename Dest> inline void addTo(Dest& dst) const
EIGEN_DEVICE_FUNC
inline void addTo(Dest& dst) const
{ {
// This is the default implementation, // This is the default implementation,
// derived class can reimplement it in a more optimized way. // derived class can reimplement it in a more optimized way.
@@ -74,9 +63,7 @@ template<typename Derived> struct EigenBase
} }
/** \internal Don't use it, but do the equivalent: \code dst -= *this; \endcode */ /** \internal Don't use it, but do the equivalent: \code dst -= *this; \endcode */
template<typename Dest> template<typename Dest> inline void subTo(Dest& dst) const
EIGEN_DEVICE_FUNC
inline void subTo(Dest& dst) const
{ {
// This is the default implementation, // This is the default implementation,
// derived class can reimplement it in a more optimized way. // derived class can reimplement it in a more optimized way.
@@ -86,8 +73,7 @@ template<typename Derived> struct EigenBase
} }
/** \internal Don't use it, but do the equivalent: \code dst.applyOnTheRight(*this); \endcode */ /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheRight(*this); \endcode */
template<typename Dest> template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
EIGEN_DEVICE_FUNC inline void applyThisOnTheRight(Dest& dst) const
{ {
// This is the default implementation, // This is the default implementation,
// derived class can reimplement it in a more optimized way. // derived class can reimplement it in a more optimized way.
@@ -95,8 +81,7 @@ template<typename Derived> struct EigenBase
} }
/** \internal Don't use it, but do the equivalent: \code dst.applyOnTheLeft(*this); \endcode */ /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheLeft(*this); \endcode */
template<typename Dest> template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
EIGEN_DEVICE_FUNC inline void applyThisOnTheLeft(Dest& dst) const
{ {
// This is the default implementation, // This is the default implementation,
// derived class can reimplement it in a more optimized way. // derived class can reimplement it in a more optimized way.
@@ -141,6 +126,35 @@ 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

975
Eigen/src/Core/Functors.h Normal file
View File

@@ -0,0 +1,975 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 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_FUNCTORS_H
#define EIGEN_FUNCTORS_H
namespace Eigen {
namespace internal {
// associative functors:
/** \internal
* \brief Template functor to compute the sum of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, MatrixBase::sum()
*/
template<typename Scalar> struct scalar_sum_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::padd(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux(a); }
};
template<typename Scalar>
struct functor_traits<scalar_sum_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasAdd
};
};
/** \internal
* \brief Template functor to compute the product of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
*/
template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
enum {
// TODO vectorize mixed product
Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
};
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmul(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
{ return internal::predux_mul(a); }
};
template<typename LhsScalar,typename RhsScalar>
struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
enum {
Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
};
};
/** \internal
* \brief Template functor to compute the conjugate product of two scalars
*
* This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
*/
template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
enum {
Conj = NumTraits<LhsScalar>::IsComplex
};
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
{ return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
};
template<typename LhsScalar,typename RhsScalar>
struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
enum {
Cost = NumTraits<LhsScalar>::MulCost,
PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
};
};
/** \internal
* \brief Template functor to compute the min of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
*/
template<typename Scalar> struct scalar_min_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmin(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux_min(a); }
};
template<typename Scalar>
struct functor_traits<scalar_min_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasMin
};
};
/** \internal
* \brief Template functor to compute the max of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
*/
template<typename Scalar> struct scalar_max_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmax(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux_max(a); }
};
template<typename Scalar>
struct functor_traits<scalar_max_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasMax
};
};
/** \internal
* \brief Template functor to compute the hypot of two scalars
*
* \sa MatrixBase::stableNorm(), class Redux
*/
template<typename Scalar> struct scalar_hypot_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
// typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
{
using std::max;
using std::min;
Scalar p = (max)(_x, _y);
Scalar q = (min)(_x, _y);
Scalar qp = q/p;
return p * sqrt(Scalar(1) + qp*qp);
}
};
template<typename Scalar>
struct functor_traits<scalar_hypot_op<Scalar> > {
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
};
/** \internal
* \brief Template functor to compute the pow of two scalars
*/
template<typename Scalar, typename OtherScalar> struct 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); }
};
template<typename Scalar, typename OtherScalar>
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
};
// other binary functors:
/** \internal
* \brief Template functor to compute the difference of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator-
*/
template<typename Scalar> struct scalar_difference_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::psub(a,b); }
};
template<typename Scalar>
struct functor_traits<scalar_difference_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasSub
};
};
/** \internal
* \brief Template functor to compute the quotient of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator/()
*/
template<typename Scalar> struct scalar_quotient_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pdiv(a,b); }
};
template<typename Scalar>
struct functor_traits<scalar_quotient_op<Scalar> > {
enum {
Cost = 2 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasDiv
};
};
/** \internal
* \brief Template functor to compute the and of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator&&
*/
struct scalar_boolean_and_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
};
template<> struct functor_traits<scalar_boolean_and_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
};
/** \internal
* \brief Template functor to compute the or of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator||
*/
struct scalar_boolean_or_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
};
template<> struct functor_traits<scalar_boolean_or_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
};
// unary functors:
/** \internal
* \brief Template functor to compute the opposite of a scalar
*
* \sa class CwiseUnaryOp, MatrixBase::operator-
*/
template<typename Scalar> struct scalar_opposite_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pnegate(a); }
};
template<typename Scalar>
struct functor_traits<scalar_opposite_op<Scalar> >
{ enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasNegate };
};
/** \internal
* \brief Template functor to compute the absolute value of a scalar
*
* \sa class CwiseUnaryOp, Cwise::abs
*/
template<typename Scalar> struct scalar_abs_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pabs(a); }
};
template<typename Scalar>
struct functor_traits<scalar_abs_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasAbs
};
};
/** \internal
* \brief Template functor to compute the squared absolute value of a scalar
*
* \sa class CwiseUnaryOp, Cwise::abs2
*/
template<typename Scalar> struct scalar_abs2_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pmul(a,a); }
};
template<typename Scalar>
struct functor_traits<scalar_abs2_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; };
/** \internal
* \brief Template functor to compute the conjugate of a complex value
*
* \sa class CwiseUnaryOp, MatrixBase::conjugate()
*/
template<typename Scalar> struct scalar_conjugate_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
};
template<typename Scalar>
struct functor_traits<scalar_conjugate_op<Scalar> >
{
enum {
Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0,
PacketAccess = packet_traits<Scalar>::HasConj
};
};
/** \internal
* \brief Template functor to cast a scalar to another type
*
* \sa class CwiseUnaryOp, MatrixBase::cast()
*/
template<typename Scalar, typename NewType>
struct scalar_cast_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op)
typedef NewType result_type;
EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); }
};
template<typename Scalar, typename NewType>
struct functor_traits<scalar_cast_op<Scalar,NewType> >
{ enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
/** \internal
* \brief Template functor to extract the real part of a complex
*
* \sa class CwiseUnaryOp, MatrixBase::real()
*/
template<typename Scalar>
struct scalar_real_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); }
};
template<typename Scalar>
struct functor_traits<scalar_real_op<Scalar> >
{ enum { Cost = 0, PacketAccess = false }; };
/** \internal
* \brief Template functor to extract the imaginary part of a complex
*
* \sa class CwiseUnaryOp, MatrixBase::imag()
*/
template<typename Scalar>
struct scalar_imag_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); }
};
template<typename Scalar>
struct functor_traits<scalar_imag_op<Scalar> >
{ enum { Cost = 0, PacketAccess = false }; };
/** \internal
* \brief Template functor to extract the real part of a complex as a reference
*
* \sa class CwiseUnaryOp, MatrixBase::real()
*/
template<typename Scalar>
struct scalar_real_ref_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
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)); }
};
template<typename Scalar>
struct functor_traits<scalar_real_ref_op<Scalar> >
{ enum { Cost = 0, PacketAccess = false }; };
/** \internal
* \brief Template functor to extract the imaginary part of a complex as a reference
*
* \sa class CwiseUnaryOp, MatrixBase::imag()
*/
template<typename Scalar>
struct scalar_imag_ref_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
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)); }
};
template<typename Scalar>
struct functor_traits<scalar_imag_ref_op<Scalar> >
{ enum { Cost = 0, PacketAccess = false }; };
/** \internal
*
* \brief Template functor to compute the exponential of a scalar
*
* \sa class CwiseUnaryOp, Cwise::exp()
*/
template<typename Scalar> struct scalar_exp_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
};
template<typename Scalar>
struct functor_traits<scalar_exp_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasExp }; };
/** \internal
*
* \brief Template functor to compute the logarithm of a scalar
*
* \sa class CwiseUnaryOp, Cwise::log()
*/
template<typename Scalar> struct scalar_log_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
inline const Scalar operator() (const Scalar& a) const { return internal::log(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
};
template<typename Scalar>
struct functor_traits<scalar_log_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
/** \internal
* \brief Template functor to multiply a scalar by a fixed other one
*
* \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/
*/
/* NOTE why doing the pset1() in packetOp *is* an optimization ?
* indeed it seems better to declare m_other as a Packet and do the pset1() once
* in the constructor. However, in practice:
* - GCC does not like m_other as a Packet and generate a load every time it needs it
* - on the other hand GCC is able to moves the pset1() outside the loop :)
* - simpler code ;)
* (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
*/
template<typename Scalar>
struct scalar_multiple_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pmul(a, pset1<Packet>(m_other)); }
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
};
template<typename Scalar>
struct functor_traits<scalar_multiple_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
template<typename Scalar1, typename Scalar2>
struct scalar_multiple2_op {
typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
};
template<typename Scalar1,typename Scalar2>
struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
/** \internal
* \brief Template functor to divide a scalar by a fixed other one
*
* This functor is used to implement the quotient of a matrix by
* a scalar where the scalar type is not necessarily a floating point type.
*
* \sa class CwiseUnaryOp, MatrixBase::operator/
*/
template<typename Scalar>
struct scalar_quotient1_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { }
EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {}
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pdiv(a, pset1<Packet>(m_other)); }
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
};
template<typename Scalar>
struct functor_traits<scalar_quotient1_op<Scalar> >
{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
// nullary functors
template<typename Scalar>
struct scalar_constant_op {
typedef typename packet_traits<Scalar>::type Packet;
EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_constant_op<Scalar> >
// FIXME replace this packet test by a safe one
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; };
template<typename Scalar> struct scalar_identity_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
};
template<typename Scalar>
struct functor_traits<scalar_identity_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
// linear access for packet ops:
// 1) initialization
// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
// 2) each step (where size is 1 for coeff access or PacketSize for packet access)
// base += [size*step, ..., size*step]
//
// TODO: Perhaps it's better to initialize lazily (so not in the constructor but in packetOp)
// in order to avoid the padd() in operator() ?
template <typename Scalar>
struct linspaced_op_impl<Scalar,false>
{
typedef typename packet_traits<Scalar>::type Packet;
linspaced_op_impl(Scalar low, Scalar step) :
m_low(low), m_step(step),
m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
m_base(padd(pset1<Packet>(low), pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
{
m_base = padd(m_base, pset1<Packet>(m_step));
return m_low+i*m_step;
}
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
const Scalar m_low;
const Scalar m_step;
const Packet m_packetStep;
mutable Packet m_base;
};
// random access for packet ops:
// 1) each step
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
template <typename Scalar>
struct linspaced_op_impl<Scalar,true>
{
typedef typename packet_traits<Scalar>::type Packet;
linspaced_op_impl(Scalar low, Scalar step) :
m_low(low), m_step(step),
m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
const Scalar m_low;
const Scalar m_step;
const Packet m_lowPacket;
const Packet m_stepPacket;
const Packet m_interPacket;
};
// ----- Linspace functor ----------------------------------------------------------------
// Forward declaration (we default to random access which does not really give
// us a speed gain when using packet access but it allows to use the functor in
// nested expressions).
template <typename Scalar, bool RandomAccess = true> struct linspaced_op;
template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> >
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; };
template <typename Scalar, bool RandomAccess> struct linspaced_op
{
typedef typename packet_traits<Scalar>::type Packet;
linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {}
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
// there row==0 and col is used for the actual iteration.
template<typename Index>
EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const
{
eigen_assert(col==0 || row==0);
return impl(col + row);
}
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
// there row==0 and col is used for the actual iteration.
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
{
eigen_assert(col==0 || row==0);
return impl.packetOp(col + row);
}
// This proxy object handles the actual required temporaries, the different
// implementations (random vs. sequential access) as well as the
// correct piping to size 2/4 packet operations.
const linspaced_op_impl<Scalar,RandomAccess> impl;
};
// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
// to indicate whether a functor allows linear access, just always answering 'yes' except for
// scalar_identity_op.
// FIXME move this to functor_traits adding a functor_default
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 }; };
// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
// 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 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_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
/** \internal
* \brief Template functor to add a scalar to a fixed other one
* \sa class CwiseUnaryOp, Array::operator+
*/
/* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
template<typename Scalar>
struct scalar_add_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
inline scalar_add_op(const Scalar& other) : m_other(other) { }
inline Scalar operator() (const Scalar& a) const { return a + m_other; }
inline const Packet packetOp(const Packet& a) const
{ return internal::padd(a, pset1<Packet>(m_other)); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_add_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
/** \internal
* \brief Template functor to compute the square root of a scalar
* \sa class CwiseUnaryOp, Cwise::sqrt()
*/
template<typename Scalar> struct scalar_sqrt_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
};
template<typename Scalar>
struct functor_traits<scalar_sqrt_op<Scalar> >
{ enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasSqrt
};
};
/** \internal
* \brief Template functor to compute the cosine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::cos()
*/
template<typename Scalar> struct scalar_cos_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
inline Scalar operator() (const Scalar& a) const { return internal::cos(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
};
template<typename Scalar>
struct functor_traits<scalar_cos_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasCos
};
};
/** \internal
* \brief Template functor to compute the sine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::sin()
*/
template<typename Scalar> struct scalar_sin_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
};
template<typename Scalar>
struct functor_traits<scalar_sin_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasSin
};
};
/** \internal
* \brief Template functor to compute the tan of a scalar
* \sa class CwiseUnaryOp, ArrayBase::tan()
*/
template<typename Scalar> struct scalar_tan_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::ptan(a); }
};
template<typename Scalar>
struct functor_traits<scalar_tan_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasTan
};
};
/** \internal
* \brief Template functor to compute the arc cosine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::acos()
*/
template<typename Scalar> struct scalar_acos_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op)
inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
};
template<typename Scalar>
struct functor_traits<scalar_acos_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasACos
};
};
/** \internal
* \brief Template functor to compute the arc sine of a scalar
* \sa class CwiseUnaryOp, ArrayBase::asin()
*/
template<typename Scalar> struct scalar_asin_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); }
typedef typename packet_traits<Scalar>::type Packet;
inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
};
template<typename Scalar>
struct functor_traits<scalar_asin_op<Scalar> >
{
enum {
Cost = 5 * NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasASin
};
};
/** \internal
* \brief Template functor to raise a scalar to a power
* \sa class CwiseUnaryOp, Cwise::pow
*/
template<typename Scalar>
struct scalar_pow_op {
// 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& exponent) : m_exponent(exponent) {}
inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
const Scalar m_exponent;
};
template<typename Scalar>
struct functor_traits<scalar_pow_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
/** \internal
* \brief Template functor to compute the quotient between a scalar and array entries.
* \sa class CwiseUnaryOp, Cwise::inverse()
*/
template<typename Scalar>
struct scalar_inverse_mult_op {
scalar_inverse_mult_op(const Scalar& other) : m_other(other) {}
inline Scalar operator() (const Scalar& a) const { return m_other / a; }
template<typename Packet>
inline const Packet packetOp(const Packet& a) const
{ return internal::pdiv(pset1<Packet>(m_other),a); }
Scalar m_other;
};
/** \internal
* \brief Template functor to compute the inverse of a scalar
* \sa class CwiseUnaryOp, Cwise::inverse()
*/
template<typename Scalar>
struct scalar_inverse_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op)
inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
template<typename Packet>
inline const Packet packetOp(const Packet& a) const
{ return internal::pdiv(pset1<Packet>(Scalar(1)),a); }
};
template<typename Scalar>
struct functor_traits<scalar_inverse_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
/** \internal
* \brief Template functor to compute the square of a scalar
* \sa class CwiseUnaryOp, Cwise::square()
*/
template<typename Scalar>
struct scalar_square_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
inline Scalar operator() (const Scalar& a) const { return a*a; }
template<typename Packet>
inline const Packet packetOp(const Packet& a) const
{ return internal::pmul(a,a); }
};
template<typename Scalar>
struct functor_traits<scalar_square_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
/** \internal
* \brief Template functor to compute the cube of a scalar
* \sa class CwiseUnaryOp, Cwise::cube()
*/
template<typename Scalar>
struct scalar_cube_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
inline Scalar operator() (const Scalar& a) const { return a*a*a; }
template<typename Packet>
inline const Packet packetOp(const Packet& a) const
{ return internal::pmul(a,pmul(a,a)); }
};
template<typename Scalar>
struct functor_traits<scalar_cube_op<Scalar> >
{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
// default functor traits for STL functors:
template<typename T>
struct functor_traits<std::multiplies<T> >
{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::divides<T> >
{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::plus<T> >
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::minus<T> >
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::negate<T> >
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::logical_or<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::logical_and<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::logical_not<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::greater<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::less<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::greater_equal<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::less_equal<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::equal_to<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::not_equal_to<T> >
{ enum { Cost = 1, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::binder2nd<T> >
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::binder1st<T> >
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::unary_negate<T> >
{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
template<typename T>
struct functor_traits<std::binary_negate<T> >
{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
#ifdef EIGEN_STDEXT_SUPPORT
template<typename T0,typename T1>
struct functor_traits<std::project1st<T0,T1> >
{ enum { Cost = 0, PacketAccess = false }; };
template<typename T0,typename T1>
struct functor_traits<std::project2nd<T0,T1> >
{ enum { Cost = 0, PacketAccess = false }; };
template<typename T0,typename T1>
struct functor_traits<std::select2nd<std::pair<T0,T1> > >
{ enum { Cost = 0, PacketAccess = false }; };
template<typename T0,typename T1>
struct functor_traits<std::select1st<std::pair<T0,T1> > >
{ enum { Cost = 0, PacketAccess = false }; };
template<typename T0,typename T1>
struct functor_traits<std::unary_compose<T0,T1> >
{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost, PacketAccess = false }; };
template<typename T0,typename T1,typename T2>
struct functor_traits<std::binary_compose<T0,T1,T2> >
{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost + functor_traits<T2>::Cost, PacketAccess = false }; };
#endif // EIGEN_STDEXT_SUPPORT
// allow to add new functors and specializations of functor_traits from outside Eigen.
// this macro is really needed because functor_traits must be specialized after it is declared but before it is used...
#ifdef EIGEN_FUNCTORS_PLUGIN
#include EIGEN_FUNCTORS_PLUGIN
#endif
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_FUNCTORS_H

View File

@@ -19,10 +19,9 @@ namespace internal
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isApprox_selector struct isApprox_selector
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
{ {
EIGEN_USING_STD_MATH(min); using std::min;
typename internal::nested<Derived,2>::type nested(x); typename internal::nested<Derived,2>::type nested(x);
typename internal::nested<OtherDerived,2>::type otherNested(y); typename internal::nested<OtherDerived,2>::type otherNested(y);
return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum());
@@ -32,8 +31,7 @@ struct isApprox_selector
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct isApprox_selector<Derived, OtherDerived, true> struct isApprox_selector<Derived, OtherDerived, true>
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar)
static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar&)
{ {
return x.matrix() == y.matrix(); return x.matrix() == y.matrix();
} }
@@ -42,18 +40,16 @@ struct isApprox_selector<Derived, OtherDerived, true>
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isMuchSmallerThan_object_selector struct isMuchSmallerThan_object_selector
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
static bool run(const Derived& x, const OtherDerived& y, const typename Derived::RealScalar& prec)
{ {
return x.cwiseAbs2().sum() <= numext::abs2(prec) * y.cwiseAbs2().sum(); return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum();
} }
}; };
template<typename Derived, typename OtherDerived> template<typename Derived, typename OtherDerived>
struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true> struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true>
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar)
static bool run(const Derived& x, const OtherDerived&, const typename Derived::RealScalar&)
{ {
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
} }
@@ -62,18 +58,16 @@ struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true>
template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
struct isMuchSmallerThan_scalar_selector struct isMuchSmallerThan_scalar_selector
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec)
static bool run(const Derived& x, const typename Derived::RealScalar& y, const typename Derived::RealScalar& prec)
{ {
return x.cwiseAbs2().sum() <= numext::abs2(prec * y); return x.cwiseAbs2().sum() <= abs2(prec * y);
} }
}; };
template<typename Derived> template<typename Derived>
struct isMuchSmallerThan_scalar_selector<Derived, true> struct isMuchSmallerThan_scalar_selector<Derived, true>
{ {
EIGEN_DEVICE_FUNC static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar)
static bool run(const Derived& x, const typename Derived::RealScalar&, const typename Derived::RealScalar&)
{ {
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
} }
@@ -103,7 +97,7 @@ template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
bool DenseBase<Derived>::isApprox( bool DenseBase<Derived>::isApprox(
const DenseBase<OtherDerived>& other, const DenseBase<OtherDerived>& other,
const RealScalar& prec RealScalar prec
) const ) const
{ {
return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);
@@ -125,7 +119,7 @@ bool DenseBase<Derived>::isApprox(
template<typename Derived> template<typename Derived>
bool DenseBase<Derived>::isMuchSmallerThan( bool DenseBase<Derived>::isMuchSmallerThan(
const typename NumTraits<Scalar>::Real& other, const typename NumTraits<Scalar>::Real& other,
const RealScalar& prec RealScalar prec
) const ) const
{ {
return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec); return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec);
@@ -145,7 +139,7 @@ template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
bool DenseBase<Derived>::isMuchSmallerThan( bool DenseBase<Derived>::isMuchSmallerThan(
const DenseBase<OtherDerived>& other, const DenseBase<OtherDerived>& other,
const RealScalar& prec RealScalar prec
) const ) const
{ {
return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);

View File

@@ -66,7 +66,8 @@ template<typename Lhs, typename Rhs> struct product_type
MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime, MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime,
_Rhs::MaxRowsAtCompileTime), _Rhs::MaxRowsAtCompileTime),
Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime,
_Rhs::RowsAtCompileTime) _Rhs::RowsAtCompileTime),
LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
}; };
// the splitting into different lines of code here, introducing the _select enums and the typedef below, // the splitting into different lines of code here, introducing the _select enums and the typedef below,
@@ -221,29 +222,7 @@ class GeneralProduct<Lhs, Rhs, InnerProduct>
***********************************************************************/ ***********************************************************************/
namespace internal { namespace internal {
template<int StorageOrder> struct outer_product_selector;
// Column major
template<typename ProductType, typename Dest, typename Func>
EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest& dest, const Func& func, const false_type&)
{
typedef typename Dest::Index Index;
// FIXME make sure lhs is sequentially stored
// FIXME not very good if rhs is real and lhs complex while alpha is real too
const Index cols = dest.cols();
for (Index j=0; j<cols; ++j)
func(dest.col(j), prod.rhs().coeff(0,j) * prod.lhs());
}
// Row major
template<typename ProductType, typename Dest, typename Func>
EIGEN_DONT_INLINE void outer_product_selector_run(const ProductType& prod, Dest& dest, const Func& func, const true_type&) {
typedef typename Dest::Index Index;
// FIXME make sure rhs is sequentially stored
// FIXME not very good if lhs is real and rhs complex while alpha is real too
const Index rows = dest.rows();
for (Index i=0; i<rows; ++i)
func(dest.row(i), prod.lhs().coeff(i,0) * prod.rhs());
}
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> > struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
@@ -256,8 +235,6 @@ template<typename Lhs, typename Rhs>
class GeneralProduct<Lhs, Rhs, OuterProduct> class GeneralProduct<Lhs, Rhs, OuterProduct>
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> : public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
{ {
template<typename T> struct IsRowMajor : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
public: public:
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
@@ -267,38 +244,40 @@ class GeneralProduct<Lhs, Rhs, OuterProduct>
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)
} }
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } }; template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
struct add { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() += src; } };
struct sub { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() -= src; } };
struct adds {
Scalar m_scale;
adds(const Scalar& s) : m_scale(s) {}
template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const {
dst.const_cast_derived() += m_scale * src;
}
};
template<typename Dest>
inline void evalTo(Dest& dest) const {
internal::outer_product_selector_run(*this, dest, set(), IsRowMajor<Dest>());
}
template<typename Dest>
inline void addTo(Dest& dest) const {
internal::outer_product_selector_run(*this, dest, add(), IsRowMajor<Dest>());
}
template<typename Dest>
inline void subTo(Dest& dest) const {
internal::outer_product_selector_run(*this, dest, sub(), IsRowMajor<Dest>());
}
template<typename Dest> void scaleAndAddTo(Dest& dest, const Scalar& alpha) const
{ {
internal::outer_product_selector_run(*this, dest, adds(alpha), IsRowMajor<Dest>()); internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha);
} }
}; };
namespace internal {
template<> struct outer_product_selector<ColMajor> {
template<typename ProductType, typename Dest>
static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
typedef typename Dest::Index Index;
// FIXME make sure lhs is sequentially stored
// FIXME not very good if rhs is real and lhs complex while alpha is real too
const Index cols = dest.cols();
for (Index j=0; j<cols; ++j)
dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
}
};
template<> struct outer_product_selector<RowMajor> {
template<typename ProductType, typename Dest>
static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
typedef typename Dest::Index Index;
// FIXME make sure rhs is sequentially stored
// FIXME not very good if lhs is real and rhs complex while alpha is real too
const Index rows = dest.rows();
for (Index i=0; i<rows; ++i)
dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
}
};
} // end namespace internal
/*********************************************************************** /***********************************************************************
* Implementation of General Matrix Vector Product * Implementation of General Matrix Vector Product
***********************************************************************/ ***********************************************************************/
@@ -332,7 +311,7 @@ class GeneralProduct<Lhs, Rhs, GemvProduct>
typedef typename Lhs::Scalar LhsScalar; typedef typename Lhs::Scalar LhsScalar;
typedef typename Rhs::Scalar RhsScalar; typedef typename Rhs::Scalar RhsScalar;
GeneralProduct(const Lhs& a_lhs, const Rhs& a_rhs) : Base(a_lhs,a_rhs) GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
{ {
// EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value), // EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::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)
@@ -341,7 +320,7 @@ class GeneralProduct<Lhs, Rhs, GemvProduct>
enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight }; enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType; typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
template<typename Dest> void scaleAndAddTo(Dest& dst, const Scalar& alpha) const template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
{ {
eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols()); eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor, internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
@@ -356,7 +335,7 @@ template<int StorageOrder, bool BlasCompatible>
struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible> struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible>
{ {
template<typename ProductType, typename Dest> template<typename ProductType, typename Dest>
static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha) static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
{ {
Transpose<Dest> destT(dest); Transpose<Dest> destT(dest);
enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor }; enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor };
@@ -396,7 +375,7 @@ struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data; internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
EIGEN_STRONG_INLINE Scalar* data() { EIGEN_STRONG_INLINE Scalar* data() {
return ForceAlignment return ForceAlignment
? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(EIGEN_ALIGN_BYTES-1))) + EIGEN_ALIGN_BYTES) ? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
: m_data.array; : m_data.array;
} }
#endif #endif
@@ -405,7 +384,7 @@ struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
template<> struct gemv_selector<OnTheRight,ColMajor,true> template<> struct gemv_selector<OnTheRight,ColMajor,true>
{ {
template<typename ProductType, typename Dest> template<typename ProductType, typename Dest>
static inline void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha) static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
{ {
typedef typename ProductType::Index Index; typedef typename ProductType::Index Index;
typedef typename ProductType::LhsScalar LhsScalar; typedef typename ProductType::LhsScalar LhsScalar;
@@ -434,7 +413,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) || (numext::imag(actualAlpha)==RealScalar(0)); bool alphaIsCompatible = (!ComplexByReal) || (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);
@@ -445,7 +424,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
if(!evalToDest) if(!evalToDest)
{ {
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
Index size = dest.size(); int size = dest.size();
EIGEN_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN
#endif #endif
if(!alphaIsCompatible) if(!alphaIsCompatible)
@@ -478,7 +457,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,true>
template<> struct gemv_selector<OnTheRight,RowMajor,true> template<> struct gemv_selector<OnTheRight,RowMajor,true>
{ {
template<typename ProductType, typename Dest> template<typename ProductType, typename Dest>
static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha) static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
{ {
typedef typename ProductType::LhsScalar LhsScalar; typedef typename ProductType::LhsScalar LhsScalar;
typedef typename ProductType::RhsScalar RhsScalar; typedef typename ProductType::RhsScalar RhsScalar;
@@ -510,7 +489,7 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
if(!DirectlyUseRhs) if(!DirectlyUseRhs)
{ {
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
Index size = actualRhs.size(); int size = actualRhs.size();
EIGEN_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN
#endif #endif
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs; Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
@@ -529,7 +508,7 @@ template<> struct gemv_selector<OnTheRight,RowMajor,true>
template<> struct gemv_selector<OnTheRight,ColMajor,false> template<> struct gemv_selector<OnTheRight,ColMajor,false>
{ {
template<typename ProductType, typename Dest> template<typename ProductType, typename Dest>
static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha) static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
{ {
typedef typename Dest::Index Index; typedef typename Dest::Index Index;
// TODO makes sure dest is sequentially stored in memory, otherwise use a temp // TODO makes sure dest is sequentially stored in memory, otherwise use a temp
@@ -542,7 +521,7 @@ template<> struct gemv_selector<OnTheRight,ColMajor,false>
template<> struct gemv_selector<OnTheRight,RowMajor,false> template<> struct gemv_selector<OnTheRight,RowMajor,false>
{ {
template<typename ProductType, typename Dest> template<typename ProductType, typename Dest>
static void run(const ProductType& prod, Dest& dest, const typename ProductType::Scalar& alpha) static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
{ {
typedef typename Dest::Index Index; typedef typename Dest::Index Index;
// TODO makes sure rhs is sequentially stored in memory, otherwise use a temp // TODO makes sure rhs is sequentially stored in memory, otherwise use a temp
@@ -564,40 +543,6 @@ template<> struct gemv_selector<OnTheRight,RowMajor,false>
* *
* \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*()
*/ */
#ifndef __CUDACC__
#ifdef EIGEN_TEST_EVALUATORS
template<typename Derived>
template<typename OtherDerived>
inline const Product<Derived, OtherDerived>
MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
{
// A note regarding the function declaration: In MSVC, this function will sometimes
// not be inlined since DenseStorage is an unwindable object for dynamic
// matrices and product types are holding a member to store the result.
// Thus it does not help tagging this function with EIGEN_STRONG_INLINE.
enum {
ProductIsValid = Derived::ColsAtCompileTime==Dynamic
|| OtherDerived::RowsAtCompileTime==Dynamic
|| int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
};
// note to the lost user:
// * for a dot product use: v1.dot(v2)
// * for a coeff-wise product use: v1.cwiseProduct(v2)
EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
#ifdef EIGEN_DEBUG_PRODUCT
internal::product_type<Derived,OtherDerived>::debug();
#endif
return Product<Derived, OtherDerived>(derived(), other.derived());
}
#else
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
inline const typename ProductReturnType<Derived, OtherDerived>::Type inline const typename ProductReturnType<Derived, OtherDerived>::Type
@@ -627,9 +572,7 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
#endif #endif
return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived()); return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
} }
#endif
#endif
/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. /** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation.
* *
* The returned product will behave like any other expressions: the coefficients of the product will be * The returned product will behave like any other expressions: the coefficients of the product will be

View File

@@ -42,8 +42,6 @@ namespace internal {
struct default_packet_traits struct default_packet_traits
{ {
enum { enum {
HasHalfPacket = 0,
HasAdd = 1, HasAdd = 1,
HasSub = 1, HasSub = 1,
HasMul = 1, HasMul = 1,
@@ -73,12 +71,10 @@ struct default_packet_traits
template<typename T> struct packet_traits : default_packet_traits template<typename T> struct packet_traits : default_packet_traits
{ {
typedef T type; typedef T type;
typedef T half;
enum { enum {
Vectorizable = 0, Vectorizable = 0,
size = 1, size = 1,
AlignedOnScalar = 0, AlignedOnScalar = 0
HasHalfPacket = 0
}; };
enum { enum {
HasAdd = 0, HasAdd = 0,
@@ -95,150 +91,91 @@ template<typename T> struct packet_traits : default_packet_traits
}; };
/** \internal \returns a + b (coeff-wise) */ /** \internal \returns a + b (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
padd(const Packet& a, padd(const Packet& a,
const Packet& b) { return a+b; } const Packet& b) { return a+b; }
/** \internal \returns a - b (coeff-wise) */ /** \internal \returns a - b (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
psub(const Packet& a, psub(const Packet& a,
const Packet& b) { return a-b; } const Packet& b) { return a-b; }
/** \internal \returns -a (coeff-wise) */ /** \internal \returns -a (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pnegate(const Packet& a) { return -a; } 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> EIGEN_DEVICE_FUNC 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> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pmul(const Packet& a, pmul(const Packet& a,
const Packet& b) { return a*b; } const Packet& b) { return a*b; }
/** \internal \returns a / b (coeff-wise) */ /** \internal \returns a / b (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pdiv(const Packet& a, pdiv(const Packet& a,
const Packet& b) { return a/b; } const Packet& b) { return a/b; }
/** \internal \returns the min of \a a and \a b (coeff-wise) */ /** \internal \returns the min of \a a and \a b (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pmin(const Packet& a, pmin(const Packet& a,
const Packet& b) { EIGEN_USING_STD_MATH(min); return (min)(a, b); } const Packet& b) { using std::min; return (min)(a, b); }
/** \internal \returns the max of \a a and \a b (coeff-wise) */ /** \internal \returns the max of \a a and \a b (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pmax(const Packet& a, pmax(const Packet& a,
const Packet& b) { EIGEN_USING_STD_MATH(max); return (max)(a, b); } const Packet& b) { using std::max; return (max)(a, b); }
/** \internal \returns the absolute value of \a a */ /** \internal \returns the absolute value of \a a */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pabs(const Packet& a) { using std::abs; return abs(a); } pabs(const Packet& a) { return abs(a); }
/** \internal \returns the bitwise and of \a a and \a b */ /** \internal \returns the bitwise and of \a a and \a b */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pand(const Packet& a, const Packet& b) { return a & b; } pand(const Packet& a, const Packet& b) { return a & b; }
/** \internal \returns the bitwise or of \a a and \a b */ /** \internal \returns the bitwise or of \a a and \a b */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
por(const Packet& a, const Packet& b) { return a | b; } por(const Packet& a, const Packet& b) { return a | b; }
/** \internal \returns the bitwise xor of \a a and \a b */ /** \internal \returns the bitwise xor of \a a and \a b */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pxor(const Packet& a, const Packet& b) { return a ^ b; } pxor(const Packet& a, const Packet& b) { return a ^ b; }
/** \internal \returns the bitwise andnot of \a a and \a b */ /** \internal \returns the bitwise andnot of \a a and \a b */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pandnot(const Packet& a, const Packet& b) { return a & (!b); } pandnot(const Packet& a, const Packet& b) { return a & (!b); }
/** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */ /** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pload(const typename unpacket_traits<Packet>::type* from) { return *from; } pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
/** \internal \returns a packet version of \a *from, (un-aligned load) */ /** \internal \returns a packet version of \a *from, (un-aligned load) */
template<typename Packet> EIGEN_DEVICE_FUNC 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 constant coefficients \a a, e.g.: (a,a,a,a) */ /** \internal \returns a packet with elements of \a *from duplicated, e.g.: (from[0],from[0],from[1],from[1]) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
/** \internal \returns a packet with constant coefficients \a a[0], e.g.: (a[0],a[0],a[0],a[0]) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
pload1(const typename unpacket_traits<Packet>::type *a) { return pset1<Packet>(*a); }
/** \internal \returns a packet with elements of \a *from duplicated.
* For instance, for a packet of 8 elements, 4 scalars 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> EIGEN_DEVICE_FUNC inline Packet
ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; } ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
/** \internal \returns a packet with elements of \a *from quadrupled. /** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */
* For instance, for a packet of 8 elements, 2 scalars will be read from \a *from and template<typename Packet> inline Packet
* replicated to form: {from[0],from[0],from[0],from[0],from[1],from[1],from[1],from[1]} pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
* Currently, this function is only used in matrix products.
* For packet-size smaller or equal to 4, this function is equivalent to pload1
*/
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
ploadquad(const typename unpacket_traits<Packet>::type* from)
{ return pload1<Packet>(from); }
/** \internal equivalent to
* \code
* a0 = pload1(a+0);
* a1 = pload1(a+1);
* a2 = pload1(a+2);
* a3 = pload1(a+3);
* \endcode
* \sa pset1, pload1, ploaddup, pbroadcast2
*/
template<typename Packet> EIGEN_DEVICE_FUNC
inline void pbroadcast4(const typename unpacket_traits<Packet>::type *a,
Packet& a0, Packet& a1, Packet& a2, Packet& a3)
{
a0 = pload1<Packet>(a+0);
a1 = pload1<Packet>(a+1);
a2 = pload1<Packet>(a+2);
a3 = pload1<Packet>(a+3);
}
/** \internal equivalent to
* \code
* a0 = pload1(a+0);
* a1 = pload1(a+1);
* \endcode
* \sa pset1, pload1, ploaddup, pbroadcast4
*/
template<typename Packet> EIGEN_DEVICE_FUNC
inline void pbroadcast2(const typename unpacket_traits<Packet>::type *a,
Packet& a0, Packet& a1)
{
a0 = pload1<Packet>(a+0);
a1 = pload1<Packet>(a+1);
}
/** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */ /** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */
template<typename Scalar> inline typename packet_traits<Scalar>::type template<typename Scalar> inline typename packet_traits<Scalar>::type
plset(const Scalar& a) { return a; } plset(const Scalar& a) { return a; }
/** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */ /** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstore(Scalar* to, const Packet& from) template<typename Scalar, typename Packet> inline void pstore(Scalar* to, const Packet& from)
{ (*to) = from; } { (*to) = from; }
/** \internal copy the packet \a from to \a *to, (un-aligned store) */ /** \internal copy the packet \a from to \a *to, (un-aligned store) */
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstoreu(Scalar* to, const Packet& from) template<typename Scalar, typename Packet> inline void pstoreu(Scalar* to, const Packet& from)
{ (*to) = from; } { (*to) = from; }
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline Packet pgather(const Scalar* from, DenseIndex /*stride*/)
{ return ploadu<Packet>(from); }
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pscatter(Scalar* to, const Packet& from, DenseIndex /*stride*/)
{ pstore(to, from); }
/** \internal tries to do cache prefetching of \a addr */ /** \internal tries to do cache prefetching of \a addr */
template<typename Scalar> inline void prefetch(const Scalar* addr) template<typename Scalar> inline void prefetch(const Scalar* addr)
{ {
@@ -248,51 +185,37 @@ __builtin_prefetch(addr);
} }
/** \internal \returns the first element of a packet */ /** \internal \returns the first element of a packet */
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type pfirst(const Packet& a) template<typename Packet> inline typename unpacket_traits<Packet>::type pfirst(const Packet& a)
{ return a; } { return a; }
/** \internal \returns a packet where the element i contains the sum of the packet of \a vec[i] */ /** \internal \returns a packet where the element i contains the sum of the packet of \a vec[i] */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
preduxp(const Packet* vecs) { return vecs[0]; } preduxp(const Packet* vecs) { return vecs[0]; }
/** \internal \returns the sum of the elements of \a a*/ /** \internal \returns the sum of the elements of \a a*/
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux(const Packet& a) template<typename Packet> inline typename unpacket_traits<Packet>::type predux(const Packet& a)
{ return a; }
/** \internal \returns the sum of the elements of \a a by block of 4 elements.
* For a packet {a0, a1, a2, a3, a4, a5, a6, a7}, it returns a half packet {a0+a4, a1+a5, a2+a6, a3+a7}
* For packet-size smaller or equal to 4, this boils down to a noop.
*/
template<typename Packet> EIGEN_DEVICE_FUNC inline
typename conditional<(unpacket_traits<Packet>::size%8)==0,typename unpacket_traits<Packet>::half,Packet>::type
predux4(const Packet& a)
{ return a; } { return a; }
/** \internal \returns the product of the elements of \a a*/ /** \internal \returns the product of the elements of \a a*/
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_mul(const Packet& a) template<typename Packet> inline typename unpacket_traits<Packet>::type predux_mul(const Packet& a)
{ return a; } { return a; }
/** \internal \returns the min of the elements of \a a*/ /** \internal \returns the min of the elements of \a a*/
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(const Packet& a) template<typename Packet> inline typename unpacket_traits<Packet>::type predux_min(const Packet& a)
{ return a; } { return a; }
/** \internal \returns the max of the elements of \a a*/ /** \internal \returns the max of the elements of \a a*/
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(const Packet& a) template<typename Packet> inline typename unpacket_traits<Packet>::type predux_max(const Packet& a)
{ return a; } { return a; }
/** \internal \returns the reversed elements of \a a*/ /** \internal \returns the reversed elements of \a a*/
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& a) template<typename Packet> inline Packet preverse(const Packet& a)
{ return a; } { return a; }
/** \internal \returns \a a with real and imaginary part flipped (for complex type only) */ /** \internal \returns \a a with real and imaginary part flipped (for complex type only) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet& a) template<typename Packet> inline Packet pcplxflip(const Packet& a)
{ { return Packet(imag(a),real(a)); }
// FIXME: uncomment the following in case we drop the internal imag and real functions.
// using std::imag;
// using std::real;
return Packet(imag(a),real(a));
}
/************************** /**************************
* Special math functions * Special math functions
@@ -300,39 +223,35 @@ template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet
/** \internal \returns the sine of \a a (coeff-wise) */ /** \internal \returns the sine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet psin(const Packet& a) { using std::sin; return sin(a); } Packet psin(const Packet& a) { return sin(a); }
/** \internal \returns the cosine of \a a (coeff-wise) */ /** \internal \returns the cosine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pcos(const Packet& a) { using std::cos; return cos(a); } Packet pcos(const Packet& a) { return cos(a); }
/** \internal \returns the tan of \a a (coeff-wise) */ /** \internal \returns the tan of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet ptan(const Packet& a) { using std::tan; return tan(a); } Packet ptan(const Packet& a) { return tan(a); }
/** \internal \returns the arc sine of \a a (coeff-wise) */ /** \internal \returns the arc sine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pasin(const Packet& a) { using std::asin; return asin(a); } Packet pasin(const Packet& a) { return asin(a); }
/** \internal \returns the arc cosine of \a a (coeff-wise) */ /** \internal \returns the arc cosine of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pacos(const Packet& a) { using std::acos; return acos(a); } Packet pacos(const Packet& a) { return acos(a); }
/** \internal \returns the atan of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet patan(const Packet& a) { using std::atan; return atan(a); }
/** \internal \returns the exp of \a a (coeff-wise) */ /** \internal \returns the exp of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet pexp(const Packet& a) { using std::exp; return exp(a); } Packet pexp(const Packet& a) { return exp(a); }
/** \internal \returns the log of \a a (coeff-wise) */ /** \internal \returns the log of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet plog(const Packet& a) { using std::log; return log(a); } Packet plog(const Packet& a) { return log(a); }
/** \internal \returns the square-root of \a a (coeff-wise) */ /** \internal \returns the square-root of \a a (coeff-wise) */
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
Packet psqrt(const Packet& a) { using std::sqrt; return sqrt(a); } Packet psqrt(const Packet& a) { return sqrt(a); }
/*************************************************************************** /***************************************************************************
* The following functions might not have to be overwritten for vectorized types * The following functions might not have to be overwritten for vectorized types
@@ -347,7 +266,7 @@ inline void pstore1(typename unpacket_traits<Packet>::type* to, const typename u
} }
/** \internal \returns a * b + c (coeff-wise) */ /** \internal \returns a * b + c (coeff-wise) */
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet template<typename Packet> inline Packet
pmadd(const Packet& a, pmadd(const Packet& a,
const Packet& b, const Packet& b,
const Packet& c) const Packet& c)
@@ -383,21 +302,8 @@ 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 packet_size minus \a Offset last elements /** \internal update \a first using the concatenation of the \a Offset last elements
* of \a first and \a Offset first elements of \a second. * of \a first and packet_size minus \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)
{ {
@@ -408,33 +314,15 @@ inline void palign(PacketType& first, const PacketType& second)
* Fast complex products (GCC generates a function call which is very slow) * Fast complex products (GCC generates a function call which is very slow)
***************************************************************************/ ***************************************************************************/
// Eigen+CUDA does not support complexes.
#ifndef __CUDACC__
template<> inline std::complex<float> pmul(const std::complex<float>& a, const std::complex<float>& b) template<> inline std::complex<float> pmul(const std::complex<float>& a, const std::complex<float>& b)
{ return std::complex<float>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } { return std::complex<float>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
template<> inline std::complex<double> pmul(const std::complex<double>& a, const std::complex<double>& b) template<> inline std::complex<double> pmul(const std::complex<double>& a, const std::complex<double>& b)
{ return std::complex<double>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } { return std::complex<double>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
#endif
/***************************************************************************
* PacketBlock, that is a collection of N packets where the number of words
* in the packet is a multiple of N.
***************************************************************************/
template <typename Packet,int N=unpacket_traits<Packet>::size> struct PacketBlock {
Packet packet[N];
};
template<typename Packet> EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet,1>& /*kernel*/) {
// Nothing to do in the scalar case, i.e. a 1x1 matrix.
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_GENERIC_PACKET_MATH_H #endif // EIGEN_GENERIC_PACKET_MATH_H

View File

@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library // This file is part of Eigen, a lightweight C++ template library
// for linear algebra. // for linear algebra.
// //
// Copyright (C) 2010-2012 Gael Guennebaud <gael.guennebaud@inria.fr> // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com> // Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
// //
// This Source Code Form is subject to the terms of the Mozilla // This Source Code Form is subject to the terms of the Mozilla
@@ -11,7 +11,7 @@
#ifndef EIGEN_GLOBAL_FUNCTIONS_H #ifndef EIGEN_GLOBAL_FUNCTIONS_H
#define EIGEN_GLOBAL_FUNCTIONS_H #define EIGEN_GLOBAL_FUNCTIONS_H
#define EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(NAME,FUNCTOR) \ #define EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(NAME,FUNCTOR) \
template<typename Derived> \ template<typename Derived> \
inline const Eigen::CwiseUnaryOp<Eigen::internal::FUNCTOR<typename Derived::Scalar>, const Derived> \ inline const Eigen::CwiseUnaryOp<Eigen::internal::FUNCTOR<typename Derived::Scalar>, const Derived> \
NAME(const Eigen::ArrayBase<Derived>& x) { \ NAME(const Eigen::ArrayBase<Derived>& x) { \
@@ -35,21 +35,19 @@
}; };
namespace Eigen namespace std
{ {
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(real,scalar_real_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(real,scalar_real_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(imag,scalar_imag_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(imag,scalar_imag_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(conj,scalar_conjugate_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sin,scalar_sin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sin,scalar_sin_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(cos,scalar_cos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cos,scalar_cos_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(asin,scalar_asin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asin,scalar_asin_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(acos,scalar_acos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acos,scalar_acos_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(tan,scalar_tan_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tan,scalar_tan_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(exp,scalar_exp_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(atan,scalar_atan_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(log,scalar_log_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(abs,scalar_abs_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op) EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sqrt,scalar_sqrt_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs,scalar_abs_op)
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sqrt,scalar_sqrt_op)
template<typename Derived> template<typename Derived>
inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar>, const Derived> inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar>, const Derived>
@@ -66,13 +64,16 @@ namespace Eigen
exponents.derived() exponents.derived()
); );
} }
}
namespace Eigen
{
/** /**
* \brief Component-wise division of a scalar by array elements. * \brief Component-wise division of a scalar by array elements.
**/ **/
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/(const typename Derived::Scalar& s, const Eigen::ArrayBase<Derived>& a) operator/(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(),
@@ -84,10 +85,19 @@ namespace Eigen
{ {
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real,scalar_real_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real,scalar_real_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag,scalar_imag_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag,scalar_imag_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sin,scalar_sin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(cos,scalar_cos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(asin,scalar_asin_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(acos,scalar_acos_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(tan,scalar_tan_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(exp,scalar_exp_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(log,scalar_log_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs,scalar_abs_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs2,scalar_abs2_op) EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs2,scalar_abs2_op)
EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sqrt,scalar_sqrt_op)
} }
} }
// TODO: cleanly disable those functions that are not supported on Array (numext::real_ref, internal::random, internal::isApprox...) // TODO: cleanly disable those functions that are not supported on Array (internal::real_ref, internal::random, internal::isApprox...)
#endif // EIGEN_GLOBAL_FUNCTIONS_H #endif // EIGEN_GLOBAL_FUNCTIONS_H

View File

@@ -49,18 +49,15 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
*/ */
struct IOFormat struct IOFormat
{ {
/** Default constructor, see class IOFormat for the meaning of the parameters */ /** Default contructor, see class IOFormat for the meaning of the parameters */
IOFormat(int _precision = StreamPrecision, int _flags = 0, IOFormat(int _precision = StreamPrecision, int _flags = 0,
const std::string& _coeffSeparator = " ", const std::string& _coeffSeparator = " ",
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),
rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags) coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
{ {
// TODO check if rowPrefix, rowSuffix or rowSeparator contains a newline rowSpacer = "";
// don't add rowSpacer if columns are not to be aligned
if((flags & DontAlignCols))
return;
int i = int(matSuffix.length())-1; int i = int(matSuffix.length())-1;
while (i>=0 && matSuffix[i]!='\n') while (i>=0 && matSuffix[i]!='\n')
{ {
@@ -132,7 +129,6 @@ struct significant_decimals_default_impl
static inline int run() static inline int run()
{ {
using std::ceil; using std::ceil;
using std::log;
return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10)))); return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
} }
}; };
@@ -189,22 +185,21 @@ 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 = 0; j < m.cols(); ++j) for(Index j = 1; 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;
sstr.copyfmt(s); if(explicit_precision) sstr.precision(explicit_precision);
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)
{ {

View File

@@ -88,7 +88,7 @@ struct traits<Map<PlainObjectType, MapOptions, StrideType> >
&& ( bool(IsDynamicSize) && ( bool(IsDynamicSize)
|| HasNoOuterStride || HasNoOuterStride
|| ( OuterStrideAtCompileTime!=Dynamic || ( OuterStrideAtCompileTime!=Dynamic
&& ((static_cast<int>(sizeof(Scalar))*OuterStrideAtCompileTime)%EIGEN_ALIGN_BYTES)==0 ) ), && ((static_cast<int>(sizeof(Scalar))*OuterStrideAtCompileTime)%16)==0 ) ),
Flags0 = TraitsBase::Flags & (~NestByRefBit), Flags0 = TraitsBase::Flags & (~NestByRefBit),
Flags1 = IsAligned ? (int(Flags0) | AlignedBit) : (int(Flags0) & ~AlignedBit), Flags1 = IsAligned ? (int(Flags0) | AlignedBit) : (int(Flags0) & ~AlignedBit),
Flags2 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime)) Flags2 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime))
@@ -110,17 +110,19 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
EIGEN_DENSE_PUBLIC_INTERFACE(Map) EIGEN_DENSE_PUBLIC_INTERFACE(Map)
typedef typename Base::PointerType PointerType; typedef typename Base::PointerType PointerType;
#if EIGEN2_SUPPORT_STAGE <= STAGE30_FULL_EIGEN3_API
typedef const Scalar* PointerArgType;
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return const_cast<PointerType>(ptr); }
#else
typedef PointerType PointerArgType; typedef PointerType PointerArgType;
EIGEN_DEVICE_FUNC
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; } inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; }
#endif
EIGEN_DEVICE_FUNC
inline Index innerStride() const inline Index innerStride() const
{ {
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
} }
EIGEN_DEVICE_FUNC
inline Index outerStride() const inline Index outerStride() const
{ {
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
@@ -131,39 +133,36 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
/** Constructor in the fixed-size case. /** Constructor in the fixed-size case.
* *
* \param dataPtr pointer to the array to map * \param data pointer to the array to map
* \param a_stride optional Stride object, passing the strides. * \param stride optional Stride object, passing the strides.
*/ */
EIGEN_DEVICE_FUNC inline Map(PointerArgType data, const StrideType& stride = StrideType())
inline Map(PointerArgType dataPtr, const StrideType& a_stride = StrideType()) : Base(cast_to_pointer_type(data)), m_stride(stride)
: Base(cast_to_pointer_type(dataPtr)), m_stride(a_stride)
{ {
PlainObjectType::Base::_check_template_params(); PlainObjectType::Base::_check_template_params();
} }
/** Constructor in the dynamic-size vector case. /** Constructor in the dynamic-size vector case.
* *
* \param dataPtr pointer to the array to map * \param data pointer to the array to map
* \param a_size the size of the vector expression * \param size the size of the vector expression
* \param a_stride optional Stride object, passing the strides. * \param stride optional Stride object, passing the strides.
*/ */
EIGEN_DEVICE_FUNC inline Map(PointerArgType data, Index size, const StrideType& stride = StrideType())
inline Map(PointerArgType dataPtr, Index a_size, const StrideType& a_stride = StrideType()) : Base(cast_to_pointer_type(data), size), m_stride(stride)
: Base(cast_to_pointer_type(dataPtr), a_size), m_stride(a_stride)
{ {
PlainObjectType::Base::_check_template_params(); PlainObjectType::Base::_check_template_params();
} }
/** Constructor in the dynamic-size matrix case. /** Constructor in the dynamic-size matrix case.
* *
* \param dataPtr pointer to the array to map * \param data pointer to the array to map
* \param nbRows the number of rows of the matrix expression * \param rows the number of rows of the matrix expression
* \param nbCols the number of columns of the matrix expression * \param cols the number of columns of the matrix expression
* \param a_stride optional Stride object, passing the strides. * \param stride optional Stride object, passing the strides.
*/ */
EIGEN_DEVICE_FUNC inline Map(PointerArgType data, Index rows, Index cols, const StrideType& stride = StrideType())
inline Map(PointerArgType dataPtr, Index nbRows, Index nbCols, const StrideType& a_stride = StrideType()) : Base(cast_to_pointer_type(data), rows, cols), m_stride(stride)
: Base(cast_to_pointer_type(dataPtr), nbRows, nbCols), m_stride(a_stride)
{ {
PlainObjectType::Base::_check_template_params(); PlainObjectType::Base::_check_template_params();
} }
@@ -174,6 +173,19 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
StrideType m_stride; StrideType m_stride;
}; };
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
::Array(const Scalar *data)
{
this->_set_noalias(Eigen::Map<const Array>(data));
}
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
::Matrix(const Scalar *data)
{
this->_set_noalias(Eigen::Map<const Matrix>(data));
}
} // end namespace Eigen } // end namespace Eigen

View File

@@ -76,8 +76,8 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
typedef typename Base::CoeffReturnType CoeffReturnType; typedef typename Base::CoeffReturnType CoeffReturnType;
EIGEN_DEVICE_FUNC inline Index rows() const { return m_rows.value(); } inline Index rows() const { return m_rows.value(); }
EIGEN_DEVICE_FUNC inline Index cols() const { return m_cols.value(); } inline Index cols() const { return m_cols.value(); }
/** Returns a pointer to the first coefficient of the matrix or vector. /** Returns a pointer to the first coefficient of the matrix or vector.
* *
@@ -87,26 +87,22 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
*/ */
inline const Scalar* data() const { return m_data; } inline const Scalar* data() const { return m_data; }
EIGEN_DEVICE_FUNC inline const Scalar& coeff(Index row, Index col) const
inline const Scalar& coeff(Index rowId, Index colId) const
{ {
return m_data[colId * colStride() + rowId * rowStride()]; return m_data[col * colStride() + row * rowStride()];
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeff(Index index) const inline const Scalar& coeff(Index index) const
{ {
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
return m_data[index * innerStride()]; return m_data[index * innerStride()];
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const
inline const Scalar& coeffRef(Index rowId, Index colId) const
{ {
return this->m_data[colId * colStride() + rowId * rowStride()]; return this->m_data[col * colStride() + row * rowStride()];
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
@@ -114,10 +110,10 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
} }
template<int LoadMode> template<int LoadMode>
inline PacketScalar packet(Index rowId, Index colId) const inline PacketScalar packet(Index row, Index col) const
{ {
return internal::ploadt<PacketScalar, LoadMode> return internal::ploadt<PacketScalar, LoadMode>
(m_data + (colId * colStride() + rowId * rowStride())); (m_data + (col * colStride() + row * rowStride()));
} }
template<int LoadMode> template<int LoadMode>
@@ -127,44 +123,40 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride()); return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
} }
EIGEN_DEVICE_FUNC inline MapBase(PointerType data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
{ {
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
checkSanity(); checkSanity();
} }
EIGEN_DEVICE_FUNC inline MapBase(PointerType data, Index size)
inline MapBase(PointerType dataPtr, Index vecSize) : m_data(data),
: m_data(dataPtr), m_rows(RowsAtCompileTime == Dynamic ? size : Index(RowsAtCompileTime)),
m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)), m_cols(ColsAtCompileTime == Dynamic ? size : Index(ColsAtCompileTime))
m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime))
{ {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
eigen_assert(vecSize >= 0); eigen_assert(size >= 0);
eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize); eigen_assert(data == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
checkSanity(); checkSanity();
} }
EIGEN_DEVICE_FUNC inline MapBase(PointerType data, Index rows, Index cols)
inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols) : m_data(data), m_rows(rows), m_cols(cols)
: m_data(dataPtr), m_rows(nbRows), m_cols(nbCols)
{ {
eigen_assert( (dataPtr == 0) eigen_assert( (data == 0)
|| ( nbRows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == nbRows) || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& nbCols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == nbCols))); && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
checkSanity(); checkSanity();
} }
protected: protected:
EIGEN_DEVICE_FUNC
void checkSanity() const void checkSanity() const
{ {
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(internal::traits<Derived>::Flags&PacketAccessBit, EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(internal::traits<Derived>::Flags&PacketAccessBit,
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) % EIGEN_ALIGN_BYTES) == 0) eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0)
&& "data is not aligned"); && "data is not aligned");
} }
@@ -203,18 +195,14 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
const Scalar const Scalar
>::type ScalarWithConstIfNotLvalue; >::type ScalarWithConstIfNotLvalue;
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return this->m_data; } inline const Scalar* data() const { return this->m_data; }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col) inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
{ {
return this->m_data[col * colStride() + row * rowStride()]; return this->m_data[col * colStride() + row * rowStride()];
} }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue& coeffRef(Index index) inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
{ {
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
@@ -222,25 +210,24 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
} }
template<int StoreMode> template<int StoreMode>
inline void writePacket(Index row, Index col, const PacketScalar& val) inline void writePacket(Index row, Index col, const PacketScalar& x)
{ {
internal::pstoret<Scalar, PacketScalar, StoreMode> internal::pstoret<Scalar, PacketScalar, StoreMode>
(this->m_data + (col * colStride() + row * rowStride()), val); (this->m_data + (col * colStride() + row * rowStride()), x);
} }
template<int StoreMode> template<int StoreMode>
inline void writePacket(Index index, const PacketScalar& val) inline void writePacket(Index index, const PacketScalar& x)
{ {
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
internal::pstoret<Scalar, PacketScalar, StoreMode> internal::pstoret<Scalar, PacketScalar, StoreMode>
(this->m_data + index * innerStride(), val); (this->m_data + index * innerStride(), x);
} }
EIGEN_DEVICE_FUNC explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {} explicit inline MapBase(PointerType data) : Base(data) {}
EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {} inline MapBase(PointerType data, Index size) : Base(data, size) {}
EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols) : Base(dataPtr, nbRows, nbCols) {} inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {}
EIGEN_DEVICE_FUNC
Derived& operator=(const MapBase& other) Derived& operator=(const MapBase& other)
{ {
Base::Base::operator=(other); Base::Base::operator=(other);
@@ -250,8 +237,6 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
using Base::Base::operator=; using Base::Base::operator=;
}; };
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_MAPBASE_H #endif // EIGEN_MAPBASE_H

View File

@@ -12,15 +12,6 @@
namespace Eigen { namespace Eigen {
// On WINCE, std::abs is defined for int only, so let's defined our own overloads:
// This issue has been confirmed with MSVC 2008 only, but the issue might exist for more recent versions too.
#if defined(_WIN32_WCE) && defined(_MSC_VER) && _MSC_VER<=1500
long abs(long x) { return (labs(x)); }
double abs(double x) { return (fabs(x)); }
float abs(float x) { return (fabsf(x)); }
long double abs(long double x) { return (fabsl(x)); }
#endif
namespace internal { namespace internal {
/** \internal \struct global_math_functions_filtering_base /** \internal \struct global_math_functions_filtering_base
@@ -60,79 +51,82 @@ struct global_math_functions_filtering_base
typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
}; };
#define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type> #define EIGEN_MATHFUNC_IMPL(func, scalar) func##_impl<typename global_math_functions_filtering_base<scalar>::type>
#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type #define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type
/**************************************************************************** /****************************************************************************
* Implementation of real * * Implementation of real *
****************************************************************************/ ****************************************************************************/
template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> template<typename Scalar>
struct real_default_impl struct real_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar& x) static inline RealScalar run(const Scalar& x)
{ {
return x; return x;
} }
}; };
template<typename Scalar> template<typename RealScalar>
struct real_default_impl<Scalar,true> struct real_impl<std::complex<RealScalar> >
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; static inline RealScalar run(const std::complex<RealScalar>& x)
EIGEN_DEVICE_FUNC
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, bool IsComplex = NumTraits<Scalar>::IsComplex> template<typename Scalar>
struct imag_default_impl struct imag_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar&) static inline RealScalar run(const Scalar&)
{ {
return RealScalar(0); return RealScalar(0);
} }
}; };
template<typename Scalar> template<typename RealScalar>
struct imag_default_impl<Scalar,true> struct imag_impl<std::complex<RealScalar> >
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; static inline RealScalar run(const std::complex<RealScalar>& x)
EIGEN_DEVICE_FUNC
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 *
****************************************************************************/ ****************************************************************************/
@@ -141,12 +135,10 @@ template<typename Scalar>
struct real_ref_impl struct real_ref_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar& run(Scalar& x) static inline RealScalar& run(Scalar& x)
{ {
return reinterpret_cast<RealScalar*>(&x)[0]; return reinterpret_cast<RealScalar*>(&x)[0];
} }
EIGEN_DEVICE_FUNC
static inline const RealScalar& run(const Scalar& x) static inline const RealScalar& run(const Scalar& x)
{ {
return reinterpret_cast<const RealScalar*>(&x)[0]; return reinterpret_cast<const RealScalar*>(&x)[0];
@@ -159,6 +151,18 @@ 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 *
****************************************************************************/ ****************************************************************************/
@@ -167,12 +171,10 @@ template<typename Scalar, bool IsComplex>
struct imag_ref_default_impl struct imag_ref_default_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar& run(Scalar& x) static inline RealScalar& run(Scalar& x)
{ {
return reinterpret_cast<RealScalar*>(&x)[1]; return reinterpret_cast<RealScalar*>(&x)[1];
} }
EIGEN_DEVICE_FUNC
static inline const RealScalar& run(const Scalar& x) static inline const RealScalar& run(const Scalar& x)
{ {
return reinterpret_cast<RealScalar*>(&x)[1]; return reinterpret_cast<RealScalar*>(&x)[1];
@@ -182,12 +184,10 @@ struct imag_ref_default_impl
template<typename Scalar> template<typename Scalar>
struct imag_ref_default_impl<Scalar, false> struct imag_ref_default_impl<Scalar, false>
{ {
EIGEN_DEVICE_FUNC
static inline Scalar run(Scalar&) static inline Scalar run(Scalar&)
{ {
return Scalar(0); return Scalar(0);
} }
EIGEN_DEVICE_FUNC
static inline const Scalar run(const Scalar&) static inline const Scalar run(const Scalar&)
{ {
return Scalar(0); return Scalar(0);
@@ -203,25 +203,35 @@ 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, bool IsComplex = NumTraits<Scalar>::IsComplex> template<typename Scalar>
struct conj_impl struct conj_impl
{ {
EIGEN_DEVICE_FUNC
static inline Scalar run(const Scalar& x) static inline Scalar run(const Scalar& x)
{ {
return x; return x;
} }
}; };
template<typename Scalar> template<typename RealScalar>
struct conj_impl<Scalar,true> struct conj_impl<std::complex<RealScalar> >
{ {
EIGEN_DEVICE_FUNC 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);
@@ -234,6 +244,39 @@ 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 abs *
****************************************************************************/
template<typename Scalar>
struct abs_impl
{
typedef typename NumTraits<Scalar>::Real RealScalar;
static inline RealScalar run(const Scalar& x)
{
using std::abs;
return abs(x);
}
};
template<typename Scalar>
struct abs_retval
{
typedef typename NumTraits<Scalar>::Real type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(abs, Scalar) abs(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(abs, Scalar)::run(x);
}
/**************************************************************************** /****************************************************************************
* Implementation of abs2 * * Implementation of abs2 *
****************************************************************************/ ****************************************************************************/
@@ -242,7 +285,6 @@ template<typename Scalar>
struct abs2_impl struct abs2_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar& x) static inline RealScalar run(const Scalar& x)
{ {
return x*x; return x*x;
@@ -252,7 +294,6 @@ struct abs2_impl
template<typename RealScalar> template<typename RealScalar>
struct abs2_impl<std::complex<RealScalar> > struct abs2_impl<std::complex<RealScalar> >
{ {
EIGEN_DEVICE_FUNC
static inline RealScalar run(const std::complex<RealScalar>& x) static inline RealScalar run(const std::complex<RealScalar>& x)
{ {
return real(x)*real(x) + imag(x)*imag(x); return real(x)*real(x) + imag(x)*imag(x);
@@ -265,6 +306,12 @@ 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 *
****************************************************************************/ ****************************************************************************/
@@ -273,10 +320,8 @@ template<typename Scalar, bool IsComplex>
struct norm1_default_impl struct norm1_default_impl
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
EIGEN_DEVICE_FUNC
static inline RealScalar run(const Scalar& x) static inline RealScalar run(const Scalar& x)
{ {
using std::abs;
return abs(real(x)) + abs(imag(x)); return abs(real(x)) + abs(imag(x));
} }
}; };
@@ -284,10 +329,8 @@ struct norm1_default_impl
template<typename Scalar> template<typename Scalar>
struct norm1_default_impl<Scalar, false> struct norm1_default_impl<Scalar, false>
{ {
EIGEN_DEVICE_FUNC
static inline Scalar run(const Scalar& x) static inline Scalar run(const Scalar& x)
{ {
using std::abs;
return abs(x); return abs(x);
} }
}; };
@@ -301,6 +344,12 @@ 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 *
****************************************************************************/ ****************************************************************************/
@@ -311,23 +360,13 @@ struct hypot_impl
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
static inline RealScalar run(const Scalar& x, const Scalar& y) static inline RealScalar run(const Scalar& x, const Scalar& y)
{ {
EIGEN_USING_STD_MATH(max); using std::max;
EIGEN_USING_STD_MATH(min); using std::min;
using std::abs;
using std::sqrt;
RealScalar _x = abs(x); RealScalar _x = abs(x);
RealScalar _y = abs(y); RealScalar _y = abs(y);
Scalar p, qp; RealScalar p = (max)(_x, _y);
if(_x>_y) RealScalar q = (min)(_x, _y);
{ RealScalar qp = q/p;
p = _x;
qp = _y / p;
}
else
{
p = _y;
qp = _x / p;
}
return p * sqrt(RealScalar(1) + qp*qp); return p * sqrt(RealScalar(1) + qp*qp);
} }
}; };
@@ -338,6 +377,12 @@ 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 *
****************************************************************************/ ****************************************************************************/
@@ -360,54 +405,120 @@ inline NewType cast(const OldType& x)
} }
/**************************************************************************** /****************************************************************************
* Implementation of atanh2 * * Implementation of sqrt *
****************************************************************************/ ****************************************************************************/
template<typename Scalar, bool IsInteger>
struct sqrt_default_impl
{
static inline Scalar run(const Scalar& x)
{
using std::sqrt;
return sqrt(x);
}
};
template<typename Scalar> template<typename Scalar>
struct atanh2_impl struct sqrt_default_impl<Scalar, true>
{ {
static inline Scalar run(const Scalar& x, const Scalar& r) static inline Scalar run(const Scalar&)
{ {
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) #ifdef EIGEN2_SUPPORT
#if (__cplusplus >= 201103L) && !defined(__CYGWIN__) eigen_assert(!NumTraits<Scalar>::IsInteger);
using std::log1p;
return log1p(2 * x / (r - x)) / 2;
#else #else
using std::abs; EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
using std::log;
using std::sqrt;
Scalar z = x / r;
if (r == 0 || abs(z) > sqrt(NumTraits<Scalar>::epsilon()))
return log((r + x) / (r - x)) / 2;
else
return z + z*z*z / 3;
#endif #endif
} return Scalar(0);
};
template<typename RealScalar>
struct atanh2_impl<std::complex<RealScalar> >
{
typedef std::complex<RealScalar> Scalar;
static inline Scalar run(const Scalar& x, const Scalar& r)
{
using std::log;
using std::norm;
using std::sqrt;
Scalar z = x / r;
if (r == Scalar(0) || norm(z) > NumTraits<RealScalar>::epsilon())
return RealScalar(0.5) * log((r + x) / (r - x));
else
return z + z*z*z / RealScalar(3);
} }
}; };
template<typename Scalar> template<typename Scalar>
struct atanh2_retval struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct sqrt_retval
{ {
typedef Scalar type; typedef Scalar type;
}; };
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x);
}
/****************************************************************************
* Implementation of standard unary real functions (exp, log, sin, cos, ... *
****************************************************************************/
// This macro instanciate all the necessary template mechanism which is common to all unary real functions.
#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \
template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \
}; \
template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
static inline Scalar run(const Scalar&) { \
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \
return Scalar(0); \
} \
}; \
template<typename Scalar> struct NAME##_impl \
: NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \
{}; \
template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \
template<typename Scalar> \
inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \
return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \
}
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin)
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos)
/****************************************************************************
* Implementation of atan2 *
****************************************************************************/
template<typename Scalar, bool IsInteger>
struct atan2_default_impl
{
typedef Scalar retval;
static inline Scalar run(const Scalar& x, const Scalar& y)
{
using std::atan2;
return atan2(x, y);
}
};
template<typename Scalar>
struct atan2_default_impl<Scalar, true>
{
static inline Scalar run(const Scalar&, const Scalar&)
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
return Scalar(0);
}
};
template<typename Scalar>
struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar>
struct atan2_retval
{
typedef Scalar type;
};
template<typename Scalar>
inline EIGEN_MATHFUNC_RETVAL(atan2, Scalar) atan2(const Scalar& x, const Scalar& y)
{
return EIGEN_MATHFUNC_IMPL(atan2, Scalar)::run(x, y);
}
/**************************************************************************** /****************************************************************************
* Implementation of pow * * Implementation of pow *
****************************************************************************/ ****************************************************************************/
@@ -451,6 +562,12 @@ 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 *
****************************************************************************/ ****************************************************************************/
@@ -549,10 +666,11 @@ 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
}; };
return Scalar((std::rand() >> shift) - offset); Scalar x = Scalar(std::rand() >> shift);
Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0);
return x - offset;
#endif #endif
} }
}; };
@@ -584,120 +702,6 @@ 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>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
{
return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
}
template<typename Scalar>
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
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>
EIGEN_DEVICE_FUNC
bool (isfinite)(const T& x)
{
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
}
template<typename T>
EIGEN_DEVICE_FUNC
bool (isfinite)(const std::complex<T>& x)
{
using std::real;
using std::imag;
return isfinite(real(x)) && isfinite(imag(x));
}
} // end namespace numext
namespace internal {
/**************************************************************************** /****************************************************************************
* Implementation of fuzzy comparisons * * Implementation of fuzzy comparisons *
****************************************************************************/ ****************************************************************************/
@@ -711,20 +715,16 @@ template<typename Scalar>
struct scalar_fuzzy_default_impl<Scalar, false, false> struct scalar_fuzzy_default_impl<Scalar, false, false>
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
template<typename OtherScalar> EIGEN_DEVICE_FUNC 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)
{ {
using std::abs;
return abs(x) <= abs(y) * prec; return abs(x) <= abs(y) * prec;
} }
EIGEN_DEVICE_FUNC
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)
{ {
EIGEN_USING_STD_MATH(min); using std::min;
using std::abs;
return abs(x - y) <= (min)(abs(x), abs(y)) * prec; return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
} }
EIGEN_DEVICE_FUNC
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
{ {
return x <= y || isApprox(x, y, prec); return x <= y || isApprox(x, y, prec);
@@ -735,17 +735,15 @@ template<typename Scalar>
struct scalar_fuzzy_default_impl<Scalar, false, true> struct scalar_fuzzy_default_impl<Scalar, false, true>
{ {
typedef typename NumTraits<Scalar>::Real RealScalar; typedef typename NumTraits<Scalar>::Real RealScalar;
template<typename OtherScalar> EIGEN_DEVICE_FUNC template<typename OtherScalar>
static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&)
{ {
return x == Scalar(0); return x == Scalar(0);
} }
EIGEN_DEVICE_FUNC
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&)
{ {
return x == y; return x == y;
} }
EIGEN_DEVICE_FUNC
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&)
{ {
return x <= y; return x <= y;
@@ -759,33 +757,33 @@ 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 numext::abs2(x) <= numext::abs2(y) * prec * prec; return abs2(x) <= 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)
{ {
EIGEN_USING_STD_MATH(min); using std::min;
return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec; return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec;
} }
}; };
template<typename Scalar> template<typename Scalar>
struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
template<typename Scalar, typename OtherScalar> EIGEN_DEVICE_FUNC template<typename Scalar, typename OtherScalar>
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
{ {
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
} }
template<typename Scalar> EIGEN_DEVICE_FUNC template<typename Scalar>
inline bool isApprox(const Scalar& x, const Scalar& y, inline bool isApprox(const Scalar& x, const Scalar& y,
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
{ {
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
} }
template<typename Scalar> EIGEN_DEVICE_FUNC template<typename Scalar>
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
{ {
@@ -808,19 +806,17 @@ template<> struct scalar_fuzzy_impl<bool>
{ {
typedef bool RealScalar; typedef bool RealScalar;
template<typename OtherScalar> EIGEN_DEVICE_FUNC template<typename OtherScalar>
static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
{ {
return !x; return !x;
} }
EIGEN_DEVICE_FUNC
static inline bool isApprox(bool x, bool y, bool) static inline bool isApprox(bool x, bool y, bool)
{ {
return x == y; return x == y;
} }
EIGEN_DEVICE_FUNC
static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&)
{ {
return (!x) || y; return (!x) || y;
@@ -828,6 +824,16 @@ 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

View File

@@ -151,7 +151,6 @@ class Matrix
* *
* \callgraph * \callgraph
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other) EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
{ {
return Base::_set(other); return Base::_set(other);
@@ -168,7 +167,6 @@ class Matrix
* remain row-vectors and vectors remain vectors. * remain row-vectors and vectors remain vectors.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other) EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
{ {
return Base::_set(other); return Base::_set(other);
@@ -181,14 +179,12 @@ class Matrix
* \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other) * \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix& operator=(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE Matrix& operator=(const EigenBase<OtherDerived> &other)
{ {
return Base::operator=(other); return Base::operator=(other);
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix& operator=(const ReturnByValue<OtherDerived>& func) EIGEN_STRONG_INLINE Matrix& operator=(const ReturnByValue<OtherDerived>& func)
{ {
return Base::operator=(func); return Base::operator=(func);
@@ -204,93 +200,52 @@ class Matrix
* *
* \sa resize(Index,Index) * \sa resize(Index,Index)
*/ */
EIGEN_DEVICE_FUNC 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_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
// FIXME is it still needed // FIXME is it still needed
EIGEN_DEVICE_FUNC
Matrix(internal::constructor_without_unaligned_array_assert) Matrix(internal::constructor_without_unaligned_array_assert)
: Base(internal::constructor_without_unaligned_array_assert()) : Base(internal::constructor_without_unaligned_array_assert())
{ Base::_check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED } { Base::_check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED }
#ifdef EIGEN_HAVE_RVALUE_REFERENCES /** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
Matrix(Matrix&& other) *
: Base(std::move(other)) * Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
* it is redundant to pass the dimension here, so it makes more sense to use the default
* constructor Matrix() instead.
*/
EIGEN_STRONG_INLINE explicit Matrix(Index dim)
: Base(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
{ {
Base::_check_template_params(); Base::_check_template_params();
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic) EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
Base::_set_noalias(other); eigen_assert(dim >= 0);
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
Matrix& operator=(Matrix&& other)
{
other.swap(*this);
return *this;
}
#endif
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
// This constructor is for both 1x1 matrices and dynamic vectors
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE explicit Matrix(const T& x)
{
Base::_check_template_params();
Base::template _init1<T>(x);
}
template<typename T0, typename T1> template<typename T0, typename T1>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const T0& x, const T1& y) EIGEN_STRONG_INLINE Matrix(const T0& x, const T1& y)
{ {
Base::_check_template_params(); Base::_check_template_params();
Base::template _init2<T0,T1>(x, y); Base::template _init2<T0,T1>(x, y);
} }
#else #else
/** \brief Constructs a fixed-sized matrix initialized with coefficients starting at \a data */
EIGEN_DEVICE_FUNC
explicit Matrix(const Scalar *data);
/** \brief Constructs a vector or row-vector with given dimension. \only_for_vectors
*
* This is useful for dynamic-size vectors. For fixed-size vectors,
* it is redundant to pass these parameters, so one should use the default constructor
* Matrix() instead.
*
* \warning This constructor is disabled for fixed-size \c 1x1 matrices. For instance,
* calling Matrix<double,1,1>(1) will call the initialization constructor: Matrix(const Scalar&).
* For fixed-size \c 1x1 matrices it is thefore recommended to use the default
* constructor Matrix() instead, especilly when using one of the non standard
* \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives).
*/
EIGEN_STRONG_INLINE explicit Matrix(Index dim);
/** \brief Constructs an initialized 1x1 matrix with the given coefficient */
Matrix(const Scalar& x);
/** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns. /** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns.
* *
* This is useful for dynamic-size matrices. For fixed-size matrices, * This is useful for dynamic-size matrices. For fixed-size matrices,
* it is redundant to pass these parameters, so one should use the default constructor * it is redundant to pass these parameters, so one should use the default constructor
* Matrix() instead. * Matrix() instead. */
*
* \warning This constructor is disabled for fixed-size \c 1x2 and \c 2x1 vectors. For instance,
* calling Matrix2f(2,1) will call the initialization constructor: Matrix(const Scalar& x, const Scalar& y).
* For fixed-size \c 1x2 or \c 2x1 vectors it is thefore recommended to use the default
* constructor Matrix() instead, especilly when using one of the non standard
* \c EIGEN_INITIALIZE_MATRICES_BY_{ZERO,\c NAN} macros (see \ref TopicPreprocessorDirectives).
*/
EIGEN_DEVICE_FUNC
Matrix(Index rows, Index cols); Matrix(Index rows, Index cols);
/** \brief Constructs an initialized 2D vector with given coefficients */ /** \brief Constructs an initialized 2D vector with given coefficients */
Matrix(const Scalar& x, const Scalar& y); Matrix(const Scalar& x, const Scalar& y);
#endif #endif
/** \brief Constructs an initialized 3D vector with given coefficients */ /** \brief Constructs an initialized 3D vector with given coefficients */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z) EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
{ {
Base::_check_template_params(); Base::_check_template_params();
@@ -300,7 +255,6 @@ class Matrix
m_storage.data()[2] = z; m_storage.data()[2] = z;
} }
/** \brief Constructs an initialized 4D vector with given coefficients */ /** \brief Constructs an initialized 4D vector with given coefficients */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w) EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
{ {
Base::_check_template_params(); Base::_check_template_params();
@@ -311,10 +265,10 @@ class Matrix
m_storage.data()[3] = w; m_storage.data()[3] = w;
} }
explicit Matrix(const Scalar *data);
/** \brief Constructor copying the value of the expression \a other */ /** \brief Constructor copying the value of the expression \a other */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other) EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
: Base(other.rows() * other.cols(), other.rows(), other.cols()) : Base(other.rows() * other.cols(), other.rows(), other.cols())
{ {
@@ -327,7 +281,6 @@ class Matrix
Base::_set_noalias(other); Base::_set_noalias(other);
} }
/** \brief Copy constructor */ /** \brief Copy constructor */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const Matrix& other) EIGEN_STRONG_INLINE Matrix(const Matrix& other)
: Base(other.rows() * other.cols(), other.rows(), other.cols()) : Base(other.rows() * other.cols(), other.rows(), other.cols())
{ {
@@ -336,7 +289,6 @@ class Matrix
} }
/** \brief Copy constructor with in-place evaluation */ /** \brief Copy constructor with in-place evaluation */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const ReturnByValue<OtherDerived>& other) EIGEN_STRONG_INLINE Matrix(const ReturnByValue<OtherDerived>& other)
{ {
Base::_check_template_params(); Base::_check_template_params();
@@ -348,12 +300,11 @@ class Matrix
* \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) * \sa MatrixBase::operator=(const EigenBase<OtherDerived>&)
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived> &other)
: 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_to_match(other); Base::resize(other.rows(), other.cols());
// 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;
@@ -364,22 +315,26 @@ class Matrix
* of same type it is enough to swap the data pointers. * of same type it is enough to swap the data pointers.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void swap(MatrixBase<OtherDerived> const & other) void swap(MatrixBase<OtherDerived> const & other)
{ this->_swap(other.derived()); } { this->_swap(other.derived()); }
EIGEN_DEVICE_FUNC inline Index innerStride() const { return 1; } inline Index innerStride() const { return 1; }
EIGEN_DEVICE_FUNC inline Index outerStride() const { return this->innerSize(); } inline Index outerStride() const { return this->innerSize(); }
/////////// Geometry module /////////// /////////// Geometry module ///////////
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r); explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r); Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived>
explicit Matrix(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
template<typename OtherDerived>
Matrix& operator=(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
#endif
// allow to extend Matrix outside Eigen // allow to extend Matrix outside Eigen
#ifdef EIGEN_MATRIX_PLUGIN #ifdef EIGEN_MATRIX_PLUGIN
#include EIGEN_MATRIX_PLUGIN #include EIGEN_MATRIX_PLUGIN

View File

@@ -81,7 +81,6 @@ template<typename Derived> class MatrixBase
using Base::operator-=; using Base::operator-=;
using Base::operator*=; using Base::operator*=;
using Base::operator/=; using Base::operator/=;
using Base::operator*;
typedef typename Base::CoeffReturnType CoeffReturnType; typedef typename Base::CoeffReturnType CoeffReturnType;
typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType; typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType;
@@ -99,7 +98,6 @@ template<typename Derived> class MatrixBase
/** \returns the size of the main diagonal, which is min(rows(),cols()). /** \returns the size of the main diagonal, which is min(rows(),cols()).
* \sa rows(), cols(), SizeAtCompileTime. */ * \sa rows(), cols(), SizeAtCompileTime. */
EIGEN_DEVICE_FUNC
inline Index diagonalSize() const { return (std::min)(rows(),cols()); } inline Index diagonalSize() const { return (std::min)(rows(),cols()); }
/** \brief The plain matrix type corresponding to this expression. /** \brief The plain matrix type corresponding to this expression.
@@ -147,59 +145,35 @@ template<typename Derived> class MatrixBase
/** Special case of the template operator=, in order to prevent the compiler /** Special case of the template operator=, in order to prevent the compiler
* from generating a default operator= (issue hit with g++ 4.1) * from generating a default operator= (issue hit with g++ 4.1)
*/ */
EIGEN_DEVICE_FUNC
Derived& operator=(const MatrixBase& other); Derived& operator=(const MatrixBase& other);
// We cannot inherit here via Base::operator= since it is causing // We cannot inherit here via Base::operator= since it is causing
// trouble with MSVC. // trouble with MSVC.
template <typename OtherDerived> template <typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const DenseBase<OtherDerived>& other); Derived& operator=(const DenseBase<OtherDerived>& other);
template <typename OtherDerived> template <typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const EigenBase<OtherDerived>& other); Derived& operator=(const EigenBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator=(const ReturnByValue<OtherDerived>& other); Derived& operator=(const ReturnByValue<OtherDerived>& other);
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other); Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other);
#endif // not EIGEN_PARSED_BY_DOXYGEN #endif // not EIGEN_PARSED_BY_DOXYGEN
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator+=(const MatrixBase<OtherDerived>& other); Derived& operator+=(const MatrixBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& operator-=(const MatrixBase<OtherDerived>& other); Derived& operator-=(const MatrixBase<OtherDerived>& other);
#ifdef __CUDACC__
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
const typename LazyProductReturnType<Derived,OtherDerived>::Type
operator*(const MatrixBase<OtherDerived> &other) const
{ return this->lazyProduct(other); }
#else
#ifdef EIGEN_TEST_EVALUATORS
template<typename OtherDerived>
const Product<Derived,OtherDerived>
operator*(const MatrixBase<OtherDerived> &other) const;
#else
template<typename OtherDerived> template<typename OtherDerived>
const typename ProductReturnType<Derived,OtherDerived>::Type const typename ProductReturnType<Derived,OtherDerived>::Type
operator*(const MatrixBase<OtherDerived> &other) const; operator*(const MatrixBase<OtherDerived> &other) const;
#endif
#endif
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
const typename LazyProductReturnType<Derived,OtherDerived>::Type const typename LazyProductReturnType<Derived,OtherDerived>::Type
lazyProduct(const MatrixBase<OtherDerived> &other) const; lazyProduct(const MatrixBase<OtherDerived> &other) const;
@@ -213,108 +187,100 @@ template<typename Derived> class MatrixBase
void applyOnTheRight(const EigenBase<OtherDerived>& other); void applyOnTheRight(const EigenBase<OtherDerived>& other);
template<typename DiagonalDerived> template<typename DiagonalDerived>
EIGEN_DEVICE_FUNC
const DiagonalProduct<Derived, DiagonalDerived, OnTheRight> const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
operator*(const DiagonalBase<DiagonalDerived> &diagonal) const; operator*(const DiagonalBase<DiagonalDerived> &diagonal) const;
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
dot(const MatrixBase<OtherDerived>& other) const; dot(const MatrixBase<OtherDerived>& other) const;
EIGEN_DEVICE_FUNC RealScalar squaredNorm() const; #ifdef EIGEN2_SUPPORT
EIGEN_DEVICE_FUNC RealScalar norm() const; template<typename OtherDerived>
Scalar eigen2_dot(const MatrixBase<OtherDerived>& other) const;
#endif
RealScalar squaredNorm() const;
RealScalar norm() const;
RealScalar stableNorm() const; RealScalar stableNorm() const;
RealScalar blueNorm() const; RealScalar blueNorm() const;
RealScalar hypotNorm() const; RealScalar hypotNorm() const;
EIGEN_DEVICE_FUNC const PlainObject normalized() const; const PlainObject normalized() const;
EIGEN_DEVICE_FUNC void normalize(); void normalize();
EIGEN_DEVICE_FUNC const AdjointReturnType adjoint() const; const AdjointReturnType adjoint() const;
EIGEN_DEVICE_FUNC void adjointInPlace(); void adjointInPlace();
typedef Diagonal<Derived> DiagonalReturnType; typedef Diagonal<Derived> DiagonalReturnType;
EIGEN_DEVICE_FUNC
DiagonalReturnType diagonal(); DiagonalReturnType diagonal();
typedef const Diagonal<const Derived> ConstDiagonalReturnType;
typedef typename internal::add_const<Diagonal<const Derived> >::type ConstDiagonalReturnType; const ConstDiagonalReturnType diagonal() const;
EIGEN_DEVICE_FUNC
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> template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal();
EIGEN_DEVICE_FUNC template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
typename DiagonalIndexReturnType<Index>::Type diagonal();
template<int Index>
EIGEN_DEVICE_FUNC
typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
// Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations. // Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
// On the other hand they confuse MSVC8... // On the other hand they confuse MSVC8...
#if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later #if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later
typename MatrixBase::template DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index); typename MatrixBase::template DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index);
typename MatrixBase::template ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const; typename MatrixBase::template ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
#else #else
EIGEN_DEVICE_FUNC typename DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index);
typename DiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index); typename ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
EIGEN_DEVICE_FUNC
typename ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
#endif #endif
#ifdef EIGEN2_SUPPORT
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
template<unsigned int Mode> const typename internal::eigen2_part_return_type<Derived, Mode>::type part() const;
// huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead
// of an integer constant. Solution: overload the part() method template wrt template parameters list.
template<template<typename T, int N> class U>
const DiagonalWrapper<ConstDiagonalReturnType> part() const
{ return diagonal().asDiagonal(); }
#endif // EIGEN2_SUPPORT
template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; }; template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; };
template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; }; template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; };
template<unsigned int Mode> template<unsigned int Mode> typename TriangularViewReturnType<Mode>::Type triangularView();
EIGEN_DEVICE_FUNC template<unsigned int Mode> typename ConstTriangularViewReturnType<Mode>::Type triangularView() const;
typename TriangularViewReturnType<Mode>::Type triangularView();
template<unsigned int Mode>
EIGEN_DEVICE_FUNC
typename ConstTriangularViewReturnType<Mode>::Type triangularView() const;
template<unsigned int UpLo> struct SelfAdjointViewReturnType { typedef SelfAdjointView<Derived, UpLo> Type; }; template<unsigned int UpLo> struct SelfAdjointViewReturnType { typedef SelfAdjointView<Derived, UpLo> Type; };
template<unsigned int UpLo> struct ConstSelfAdjointViewReturnType { typedef const SelfAdjointView<const Derived, UpLo> Type; }; template<unsigned int UpLo> struct ConstSelfAdjointViewReturnType { typedef const SelfAdjointView<const Derived, UpLo> Type; };
template<unsigned int UpLo> template<unsigned int UpLo> typename SelfAdjointViewReturnType<UpLo>::Type selfadjointView();
EIGEN_DEVICE_FUNC template<unsigned int UpLo> typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const;
typename SelfAdjointViewReturnType<UpLo>::Type selfadjointView();
template<unsigned int UpLo>
EIGEN_DEVICE_FUNC
typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const;
const SparseView<Derived> sparseView(const Scalar& m_reference = Scalar(0), const SparseView<Derived> sparseView(const Scalar& m_reference = Scalar(0),
const typename NumTraits<Scalar>::Real& m_epsilon = NumTraits<Scalar>::dummy_precision()) const; typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) const;
EIGEN_DEVICE_FUNC static const IdentityReturnType Identity(); static const IdentityReturnType Identity();
EIGEN_DEVICE_FUNC static const IdentityReturnType Identity(Index rows, Index cols); static const IdentityReturnType Identity(Index rows, Index cols);
EIGEN_DEVICE_FUNC static const BasisReturnType Unit(Index size, Index i); static const BasisReturnType Unit(Index size, Index i);
EIGEN_DEVICE_FUNC static const BasisReturnType Unit(Index i); static const BasisReturnType Unit(Index i);
EIGEN_DEVICE_FUNC static const BasisReturnType UnitX(); static const BasisReturnType UnitX();
EIGEN_DEVICE_FUNC static const BasisReturnType UnitY(); static const BasisReturnType UnitY();
EIGEN_DEVICE_FUNC static const BasisReturnType UnitZ(); static const BasisReturnType UnitZ();
EIGEN_DEVICE_FUNC static const BasisReturnType UnitW(); static const BasisReturnType UnitW();
EIGEN_DEVICE_FUNC
const DiagonalWrapper<const Derived> asDiagonal() const; const DiagonalWrapper<const Derived> asDiagonal() const;
const PermutationWrapper<const Derived> asPermutation() const; const PermutationWrapper<const Derived> asPermutation() const;
EIGEN_DEVICE_FUNC
Derived& setIdentity(); Derived& setIdentity();
EIGEN_DEVICE_FUNC
Derived& setIdentity(Index rows, Index cols); Derived& setIdentity(Index rows, Index cols);
bool isIdentity(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isIdentity(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
bool isDiagonal(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isDiagonal(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
bool isUpperTriangular(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isUpperTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
bool isLowerTriangular(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isLowerTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
template<typename OtherDerived> template<typename OtherDerived>
bool isOrthogonal(const MatrixBase<OtherDerived>& other, bool isOrthogonal(const MatrixBase<OtherDerived>& other,
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
bool isUnitary(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const; bool isUnitary(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
/** \returns true if each coefficients of \c *this and \a other are all exactly equal. /** \returns true if each coefficients of \c *this and \a other are all exactly equal.
* \warning When using floating point scalar values you probably should rather use a * \warning When using floating point scalar values you probably should rather use a
@@ -341,26 +307,42 @@ template<typename Derived> class MatrixBase
Scalar trace() const; Scalar trace() const;
template<int p> EIGEN_DEVICE_FUNC RealScalar lpNorm() const; /////////// Array module ///////////
EIGEN_DEVICE_FUNC MatrixBase<Derived>& matrix() { return *this; } template<int p> RealScalar lpNorm() const;
EIGEN_DEVICE_FUNC const MatrixBase<Derived>& matrix() const { return *this; }
/** \returns an \link Eigen::ArrayBase Array \endlink expression of this matrix MatrixBase<Derived>& matrix() { return *this; }
const MatrixBase<Derived>& matrix() const { return *this; }
/** \returns an \link ArrayBase Array \endlink expression of this matrix
* \sa ArrayBase::matrix() */ * \sa ArrayBase::matrix() */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ArrayWrapper<Derived> array() { return derived(); } ArrayWrapper<Derived> array() { return derived(); }
/** \returns a const \link Eigen::ArrayBase Array \endlink expression of this matrix const ArrayWrapper<const Derived> array() const { return derived(); }
* \sa ArrayBase::matrix() */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArrayWrapper<const Derived> array() const { return derived(); }
/////////// LU module /////////// /////////// LU module ///////////
EIGEN_DEVICE_FUNC const FullPivLU<PlainObject> fullPivLu() const; const FullPivLU<PlainObject> fullPivLu() const;
EIGEN_DEVICE_FUNC const PartialPivLU<PlainObject> partialPivLu() const; const PartialPivLU<PlainObject> partialPivLu() const;
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
const LU<PlainObject> lu() const;
#endif
#ifdef EIGEN2_SUPPORT
const LU<PlainObject> eigen2_lu() const;
#endif
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
const PartialPivLU<PlainObject> lu() const; const PartialPivLU<PlainObject> lu() const;
#endif
#ifdef EIGEN2_SUPPORT
template<typename ResultType>
void computeInverse(MatrixBase<ResultType> *result) const {
*result = this->inverse();
}
#endif
EIGEN_DEVICE_FUNC
const internal::inverse_impl<Derived> inverse() const; const internal::inverse_impl<Derived> inverse() const;
template<typename ResultType> template<typename ResultType>
void computeInverseAndDetWithCheck( void computeInverseAndDetWithCheck(
@@ -388,6 +370,10 @@ template<typename Derived> class MatrixBase
const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const; const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const;
const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const; const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const;
#ifdef EIGEN2_SUPPORT
const QR<PlainObject> qr() const;
#endif
EigenvaluesReturnType eigenvalues() const; EigenvaluesReturnType eigenvalues() const;
RealScalar operatorNorm() const; RealScalar operatorNorm() const;
@@ -395,6 +381,10 @@ template<typename Derived> class MatrixBase
JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const; JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const;
#ifdef EIGEN2_SUPPORT
SVD<PlainObject> svd() const;
#endif
/////////// Geometry module /////////// /////////// Geometry module ///////////
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
@@ -405,24 +395,20 @@ template<typename Derived> class MatrixBase
}; };
#endif // EIGEN_PARSED_BY_DOXYGEN #endif // EIGEN_PARSED_BY_DOXYGEN
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
typename cross_product_return_type<OtherDerived>::type typename cross_product_return_type<OtherDerived>::type
cross(const MatrixBase<OtherDerived>& other) const; cross(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
PlainObject cross3(const MatrixBase<OtherDerived>& other) const; PlainObject cross3(const MatrixBase<OtherDerived>& other) const;
EIGEN_DEVICE_FUNC
PlainObject unitOrthogonal(void) const; PlainObject unitOrthogonal(void) const;
Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const; Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const;
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
ScalarMultipleReturnType operator*(const UniformScaling<Scalar>& s) const; ScalarMultipleReturnType operator*(const UniformScaling<Scalar>& s) const;
// put this as separate enum value to work around possible GCC 4.3 bug (?) // put this as separate enum value to work around possible GCC 4.3 bug (?)
enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1?Vertical:Horizontal }; enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1?Vertical:Horizontal };
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType; typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
HomogeneousReturnType homogeneous() const; HomogeneousReturnType homogeneous() const;
#endif
enum { enum {
SizeMinusOne = SizeAtCompileTime==Dynamic ? Dynamic : SizeAtCompileTime-1 SizeMinusOne = SizeAtCompileTime==Dynamic ? Dynamic : SizeAtCompileTime-1
@@ -468,16 +454,49 @@ 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(const RealScalar& p) const;
const MatrixComplexPowerReturnValue<Derived> pow(const std::complex<RealScalar>& p) const; #ifdef EIGEN2_SUPPORT
template<typename ProductDerived, typename Lhs, typename Rhs>
Derived& operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
EvalBeforeAssigningBit>& other);
template<typename ProductDerived, typename Lhs, typename Rhs>
Derived& operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
EvalBeforeAssigningBit>& other);
/** \deprecated because .lazy() is deprecated
* Overloaded for cache friendly product evaluation */
template<typename OtherDerived>
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeAssigningBit>& other)
{ return lazyAssign(other._expression()); }
template<unsigned int Added>
const Flagged<Derived, Added, 0> marked() const;
const Flagged<Derived, 0, EvalBeforeAssigningBit> lazy() const;
inline const Cwise<Derived> cwise() const;
inline Cwise<Derived> cwise();
VectorBlock<Derived> start(Index size);
const VectorBlock<const Derived> start(Index size) const;
VectorBlock<Derived> end(Index size);
const VectorBlock<const Derived> end(Index size) const;
template<int Size> VectorBlock<Derived,Size> start();
template<int Size> const VectorBlock<const Derived,Size> start() const;
template<int Size> VectorBlock<Derived,Size> end();
template<int Size> const VectorBlock<const Derived,Size> end() const;
Minor<Derived> minor(Index row, Index col);
const Minor<Derived> minor(Index row, Index col) const;
#endif
protected: protected:
EIGEN_DEVICE_FUNC MatrixBase() : Base() {} MatrixBase() : Base() {}
private: private:
EIGEN_DEVICE_FUNC explicit MatrixBase(int); explicit MatrixBase(int);
EIGEN_DEVICE_FUNC MatrixBase(int,int); MatrixBase(int,int);
template<typename OtherDerived> EIGEN_DEVICE_FUNC explicit MatrixBase(const MatrixBase<OtherDerived>&); template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&);
protected: protected:
// mixing arrays and matrices is not legal // mixing arrays and matrices is not legal
template<typename OtherDerived> Derived& operator+=(const ArrayBase<OtherDerived>& ) template<typename OtherDerived> Derived& operator+=(const ArrayBase<OtherDerived>& )
@@ -487,51 +506,6 @@ 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

View File

@@ -37,13 +37,11 @@ class NoAlias
/** Behaves like MatrixBase::lazyAssign(other) /** Behaves like MatrixBase::lazyAssign(other)
* \sa MatrixBase::lazyAssign() */ * \sa MatrixBase::lazyAssign() */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other) EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other)
{ return internal::assign_selector<ExpressionType,OtherDerived,false>::run(m_expression,other.derived()); } { return internal::assign_selector<ExpressionType,OtherDerived,false>::run(m_expression,other.derived()); }
/** \sa MatrixBase::operator+= */ /** \sa MatrixBase::operator+= */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other) EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other)
{ {
typedef SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, ExpressionType, OtherDerived> SelfAdder; typedef SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
@@ -56,7 +54,6 @@ class NoAlias
/** \sa MatrixBase::operator-= */ /** \sa MatrixBase::operator-= */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other) EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other)
{ {
typedef SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, ExpressionType, OtherDerived> SelfAdder; typedef SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
@@ -69,12 +66,10 @@ class NoAlias
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other) EIGEN_STRONG_INLINE ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{ other.derived().addTo(m_expression); return m_expression; } { other.derived().addTo(m_expression); return m_expression; }
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other) EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{ other.derived().subTo(m_expression); return m_expression; } { other.derived().subTo(m_expression); return m_expression; }
@@ -83,21 +78,10 @@ class NoAlias
{ 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 Lhs, typename Rhs, int NestingFlags> template<typename Lhs, typename Rhs, int NestingFlags>
EIGEN_DEVICE_FUNC
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
EIGEN_DEVICE_FUNC
ExpressionType& expression() const
{
return m_expression;
}
protected: protected:
ExpressionType& m_expression; ExpressionType& m_expression;
}; };

View File

@@ -68,16 +68,7 @@ template<typename T> struct GenericNumTraits
>::type NonInteger; >::type NonInteger;
typedef T Nested; typedef T Nested;
EIGEN_DEVICE_FUNC static inline Real epsilon() { return std::numeric_limits<T>::epsilon(); }
static inline Real epsilon()
{
#if defined(__CUDA_ARCH__)
return internal::device::numeric_limits<T>::epsilon();
#else
return std::numeric_limits<T>::epsilon();
#endif
}
EIGEN_DEVICE_FUNC
static inline Real dummy_precision() static inline Real dummy_precision()
{ {
// make sure to override this for floating-point types // make sure to override this for floating-point types
@@ -85,6 +76,13 @@ template<typename T> struct GenericNumTraits
} }
static inline T highest() { return (std::numeric_limits<T>::max)(); } static inline T highest() { return (std::numeric_limits<T>::max)(); }
static inline T lowest() { return IsInteger ? (std::numeric_limits<T>::min)() : (-(std::numeric_limits<T>::max)()); } static inline T lowest() { return IsInteger ? (std::numeric_limits<T>::min)() : (-(std::numeric_limits<T>::max)()); }
#ifdef EIGEN2_SUPPORT
enum {
HasFloatingPoint = !IsInteger
};
typedef NonInteger FloatingPoint;
#endif
}; };
template<typename T> struct NumTraits : GenericNumTraits<T> template<typename T> struct NumTraits : GenericNumTraits<T>
@@ -93,13 +91,11 @@ template<typename T> struct NumTraits : GenericNumTraits<T>
template<> struct NumTraits<float> template<> struct NumTraits<float>
: GenericNumTraits<float> : GenericNumTraits<float>
{ {
EIGEN_DEVICE_FUNC
static inline float dummy_precision() { return 1e-5f; } static inline float dummy_precision() { return 1e-5f; }
}; };
template<> struct NumTraits<double> : GenericNumTraits<double> template<> struct NumTraits<double> : GenericNumTraits<double>
{ {
EIGEN_DEVICE_FUNC
static inline double dummy_precision() { return 1e-12; } static inline double dummy_precision() { return 1e-12; }
}; };
@@ -144,9 +140,6 @@ 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

View File

@@ -66,11 +66,11 @@ class PermutationBase : public EigenBase<Derived>
MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime,
MaxColsAtCompileTime = Traits::MaxColsAtCompileTime MaxColsAtCompileTime = Traits::MaxColsAtCompileTime
}; };
typedef typename Traits::StorageIndexType StorageIndexType; typedef typename Traits::Scalar Scalar;
typedef typename Traits::Index Index; typedef typename Traits::Index Index;
typedef Matrix<StorageIndexType,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime> typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime>
DenseMatrixType; DenseMatrixType;
typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,StorageIndexType> typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,Index>
PlainPermutationType; PlainPermutationType;
using Base::derived; using Base::derived;
#endif #endif
@@ -139,23 +139,23 @@ class PermutationBase : public EigenBase<Derived>
/** Resizes to given size. /** Resizes to given size.
*/ */
inline void resize(Index newSize) inline void resize(Index size)
{ {
indices().resize(newSize); indices().resize(size);
} }
/** Sets *this to be the identity permutation matrix */ /** Sets *this to be the identity permutation matrix */
void setIdentity() void setIdentity()
{ {
for(StorageIndexType i = 0; i < size(); ++i) for(Index i = 0; i < size(); ++i)
indices().coeffRef(i) = i; indices().coeffRef(i) = i;
} }
/** Sets *this to be the identity permutation matrix of given size. /** Sets *this to be the identity permutation matrix of given size.
*/ */
void setIdentity(Index newSize) void setIdentity(Index size)
{ {
resize(newSize); resize(size);
setIdentity(); setIdentity();
} }
@@ -173,8 +173,8 @@ class PermutationBase : public EigenBase<Derived>
eigen_assert(i>=0 && j>=0 && i<size() && j<size()); eigen_assert(i>=0 && j>=0 && i<size() && j<size());
for(Index k = 0; k < size(); ++k) for(Index k = 0; k < size(); ++k)
{ {
if(indices().coeff(k) == i) indices().coeffRef(k) = StorageIndexType(j); if(indices().coeff(k) == i) indices().coeffRef(k) = j;
else if(indices().coeff(k) == j) indices().coeffRef(k) = StorageIndexType(i); else if(indices().coeff(k) == j) indices().coeffRef(k) = i;
} }
return derived(); return derived();
} }
@@ -262,7 +262,7 @@ class PermutationBase : public EigenBase<Derived>
* *
* \param SizeAtCompileTime the number of rows/cols, or Dynamic * \param SizeAtCompileTime the number of rows/cols, or Dynamic
* \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it. * \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it.
* \param StorageIndexType the integer type of the indices * \param IndexType the interger type of the indices
* *
* This class represents a permutation matrix, internally stored as a vector of integers. * This class represents a permutation matrix, internally stored as a vector of integers.
* *
@@ -270,18 +270,17 @@ class PermutationBase : public EigenBase<Derived>
*/ */
namespace internal { namespace internal {
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndexType> > struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> >
: traits<Matrix<_StorageIndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
{ {
typedef Matrix<_StorageIndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType; typedef IndexType Index;
typedef typename IndicesType::Index Index; typedef Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
typedef _StorageIndexType StorageIndexType;
}; };
} }
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndexType> > class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> >
{ {
typedef PermutationBase<PermutationMatrix> Base; typedef PermutationBase<PermutationMatrix> Base;
typedef internal::traits<PermutationMatrix> Traits; typedef internal::traits<PermutationMatrix> Traits;
@@ -289,8 +288,6 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename Traits::StorageIndexType StorageIndexType;
typedef typename Traits::Index Index;
#endif #endif
inline PermutationMatrix() inline PermutationMatrix()
@@ -298,7 +295,7 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
/** Constructs an uninitialized permutation matrix of given size. /** Constructs an uninitialized permutation matrix of given size.
*/ */
inline PermutationMatrix(Index size) : m_indices(size) inline PermutationMatrix(int size) : m_indices(size)
{} {}
/** Copy constructor. */ /** Copy constructor. */
@@ -320,7 +317,7 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
* array's size. * array's size.
*/ */
template<typename Other> template<typename Other>
explicit inline PermutationMatrix(const MatrixBase<Other>& a_indices) : m_indices(a_indices) explicit inline PermutationMatrix(const MatrixBase<Other>& indices) : m_indices(indices)
{} {}
/** Convert the Transpositions \a tr to a permutation matrix */ /** Convert the Transpositions \a tr to a permutation matrix */
@@ -387,19 +384,18 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
namespace internal { namespace internal {
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType, int _PacketAccess> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndexType>,_PacketAccess> > struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> >
: traits<Matrix<_StorageIndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
{ {
typedef Map<const Matrix<_StorageIndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType; typedef IndexType Index;
typedef typename IndicesType::Index Index; typedef Map<const Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType;
typedef _StorageIndexType StorageIndexType;
}; };
} }
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType, int _PacketAccess> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndexType>,_PacketAccess> class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess>
: public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageIndexType>,_PacketAccess> > : public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> >
{ {
typedef PermutationBase<Map> Base; typedef PermutationBase<Map> Base;
typedef internal::traits<Map> Traits; typedef internal::traits<Map> Traits;
@@ -407,16 +403,15 @@ class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, _StorageInd
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar StorageIndexType; typedef typename IndicesType::Scalar Index;
typedef typename IndicesType::Index Index;
#endif #endif
inline Map(const StorageIndexType* indicesPtr) inline Map(const Index* indices)
: m_indices(indicesPtr) : m_indices(indices)
{} {}
inline Map(const StorageIndexType* indicesPtr, Index size) inline Map(const Index* indices, Index size)
: m_indices(indicesPtr,size) : m_indices(indices,size)
{} {}
/** Copies the other permutation into *this */ /** Copies the other permutation into *this */
@@ -471,8 +466,7 @@ struct traits<PermutationWrapper<_IndicesType> >
{ {
typedef PermutationStorage StorageKind; typedef PermutationStorage StorageKind;
typedef typename _IndicesType::Scalar Scalar; typedef typename _IndicesType::Scalar Scalar;
typedef typename _IndicesType::Scalar StorageIndexType; typedef typename _IndicesType::Scalar Index;
typedef typename _IndicesType::Index Index;
typedef _IndicesType IndicesType; typedef _IndicesType IndicesType;
enum { enum {
RowsAtCompileTime = _IndicesType::SizeAtCompileTime, RowsAtCompileTime = _IndicesType::SizeAtCompileTime,
@@ -496,8 +490,8 @@ class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesTyp
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
#endif #endif
inline PermutationWrapper(const IndicesType& a_indices) inline PermutationWrapper(const IndicesType& indices)
: m_indices(a_indices) : m_indices(indices)
{} {}
/** const version of indices(). */ /** const version of indices(). */
@@ -547,26 +541,24 @@ 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 Index rows() const { return m_matrix.rows(); } inline int rows() const { return m_matrix.rows(); }
inline Index cols() const { return m_matrix.cols(); } inline int 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 Index n = Side==OnTheLeft ? rows() : cols(); const int n = Side==OnTheLeft ? rows() : cols();
// FIXME we need an is_same for expression that is not sensitive to constness. For instance
// is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true.
if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)) if(is_same<MatrixTypeNestedCleaned,Dest>::value && 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);
Index r = 0; int r = 0;
while(r < m_permutation.size()) while(r < m_permutation.size())
{ {
// search for the next seed // search for the next seed
@@ -574,10 +566,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
Index k0 = r++; int k0 = r++;
Index kPrev = k0; int kPrev = k0;
mask.coeffRef(k0) = true; mask.coeffRef(k0) = true;
for(Index k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k)) for(int 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>

View File

@@ -11,48 +11,30 @@
#ifndef EIGEN_DENSESTORAGEBASE_H #ifndef EIGEN_DENSESTORAGEBASE_H
#define EIGEN_DENSESTORAGEBASE_H #define EIGEN_DENSESTORAGEBASE_H
#if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO) #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
# define EIGEN_INITIALIZE_COEFFS # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
#elif defined(EIGEN_INITIALIZE_MATRICES_BY_NAN)
# define EIGEN_INITIALIZE_COEFFS
# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=std::numeric_limits<Scalar>::quiet_NaN();
#else #else
# undef EIGEN_INITIALIZE_COEFFS # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
#endif #endif
namespace Eigen { namespace Eigen {
namespace internal { namespace internal {
template<int MaxSizeAtCompileTime> struct check_rows_cols_for_overflow {
template<typename Index> template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols)
static EIGEN_ALWAYS_INLINE void run(Index, Index)
{
}
};
template<> struct check_rows_cols_for_overflow<Dynamic> {
template<typename Index>
EIGEN_DEVICE_FUNC
static EIGEN_ALWAYS_INLINE void run(Index rows, Index cols)
{ {
// http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
// we assume Index is signed // we assume Index is signed
Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
bool error = (rows == 0 || cols == 0) ? false bool error = (rows < 0 || cols < 0) ? true
: (rows == 0 || cols == 0) ? false
: (rows > max_index / cols); : (rows > max_index / cols);
if (error) if (error)
throw_std_bad_alloc(); throw_std_bad_alloc();
} }
};
template <typename Derived, template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
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;
@@ -131,56 +113,46 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 }; enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 };
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
EIGEN_DEVICE_FUNC
Base& base() { return *static_cast<Base*>(this); } Base& base() { return *static_cast<Base*>(this); }
EIGEN_DEVICE_FUNC
const Base& base() const { return *static_cast<const Base*>(this); } const Base& base() const { return *static_cast<const Base*>(this); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); } EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); } EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
EIGEN_STRONG_INLINE const Scalar& coeff(Index rowId, Index colId) const
{ {
if(Flags & RowMajorBit) if(Flags & RowMajorBit)
return m_storage.data()[colId + rowId * m_storage.cols()]; return m_storage.data()[col + row * m_storage.cols()];
else // column-major else // column-major
return m_storage.data()[rowId + colId * m_storage.rows()]; return m_storage.data()[row + col * m_storage.rows()];
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
{ {
return m_storage.data()[index]; return m_storage.data()[index];
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
EIGEN_STRONG_INLINE Scalar& coeffRef(Index rowId, Index colId)
{ {
if(Flags & RowMajorBit) if(Flags & RowMajorBit)
return m_storage.data()[colId + rowId * m_storage.cols()]; return m_storage.data()[col + row * m_storage.cols()];
else // column-major else // column-major
return m_storage.data()[rowId + colId * m_storage.rows()]; return m_storage.data()[row + col * m_storage.rows()];
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
{ {
return m_storage.data()[index]; return m_storage.data()[index];
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
EIGEN_STRONG_INLINE const Scalar& coeffRef(Index rowId, Index colId) const
{ {
if(Flags & RowMajorBit) if(Flags & RowMajorBit)
return m_storage.data()[colId + rowId * m_storage.cols()]; return m_storage.data()[col + row * m_storage.cols()];
else // column-major else // column-major
return m_storage.data()[rowId + colId * m_storage.rows()]; return m_storage.data()[row + col * m_storage.rows()];
} }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
{ {
return m_storage.data()[index]; return m_storage.data()[index];
@@ -188,12 +160,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \internal */ /** \internal */
template<int LoadMode> template<int LoadMode>
EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
{ {
return internal::ploadt<PacketScalar, LoadMode> return internal::ploadt<PacketScalar, LoadMode>
(m_storage.data() + (Flags & RowMajorBit (m_storage.data() + (Flags & RowMajorBit
? colId + rowId * m_storage.cols() ? col + row * m_storage.cols()
: rowId + colId * m_storage.rows())); : row + col * m_storage.rows()));
} }
/** \internal */ /** \internal */
@@ -205,19 +177,19 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \internal */ /** \internal */
template<int StoreMode> template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket(Index rowId, Index colId, const PacketScalar& val) EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
{ {
internal::pstoret<Scalar, PacketScalar, StoreMode> internal::pstoret<Scalar, PacketScalar, StoreMode>
(m_storage.data() + (Flags & RowMajorBit (m_storage.data() + (Flags & RowMajorBit
? colId + rowId * m_storage.cols() ? col + row * m_storage.cols()
: rowId + colId * m_storage.rows()), val); : row + col * m_storage.rows()), x);
} }
/** \internal */ /** \internal */
template<int StoreMode> template<int StoreMode>
EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& val) EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
{ {
internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, val); internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
} }
/** \returns a const pointer to the data array of this matrix */ /** \returns a const pointer to the data array of this matrix */
@@ -244,23 +216,17 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t) * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t)
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
EIGEN_STRONG_INLINE void resize(Index nbRows, Index nbCols)
{ {
eigen_assert( EIGEN_IMPLIES(RowsAtCompileTime!=Dynamic,nbRows==RowsAtCompileTime) #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
&& EIGEN_IMPLIES(ColsAtCompileTime!=Dynamic,nbCols==ColsAtCompileTime) internal::check_rows_cols_for_overflow(rows, cols);
&& EIGEN_IMPLIES(RowsAtCompileTime==Dynamic && MaxRowsAtCompileTime!=Dynamic,nbRows<=MaxRowsAtCompileTime) Index size = rows*cols;
&& EIGEN_IMPLIES(ColsAtCompileTime==Dynamic && MaxColsAtCompileTime!=Dynamic,nbCols<=MaxColsAtCompileTime)
&& nbRows>=0 && nbCols>=0 && "Invalid sizes when resizing a matrix or array.");
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(nbRows, nbCols);
#ifdef EIGEN_INITIALIZE_COEFFS
Index size = nbRows*nbCols;
bool size_changed = size != this->size(); bool size_changed = size != this->size();
m_storage.resize(size, nbRows, nbCols); m_storage.resize(size, rows, cols);
if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#else #else
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(nbRows, nbCols); internal::check_rows_cols_for_overflow(rows, cols);
m_storage.resize(nbRows*nbCols, nbRows, nbCols); m_storage.resize(rows*cols, rows, cols);
#endif #endif
} }
@@ -275,20 +241,19 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t) * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t)
*/ */
EIGEN_DEVICE_FUNC
inline void resize(Index size) inline void resize(Index size)
{ {
EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase) EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0); eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
#ifdef EIGEN_INITIALIZE_COEFFS #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
bool size_changed = size != this->size(); bool size_changed = size != this->size();
#endif #endif
if(RowsAtCompileTime == 1) if(RowsAtCompileTime == 1)
m_storage.resize(size, 1, size); m_storage.resize(size, 1, size);
else else
m_storage.resize(size, size, 1); m_storage.resize(size, size, 1);
#ifdef EIGEN_INITIALIZE_COEFFS #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#endif #endif
} }
@@ -300,10 +265,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* \sa resize(Index,Index) * \sa resize(Index,Index)
*/ */
EIGEN_DEVICE_FUNC inline void resize(NoChange_t, Index cols)
inline void resize(NoChange_t, Index nbCols)
{ {
resize(rows(), nbCols); resize(rows(), cols);
} }
/** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange
@@ -314,10 +278,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* \sa resize(Index,Index) * \sa resize(Index,Index)
*/ */
EIGEN_DEVICE_FUNC inline void resize(Index rows, NoChange_t)
inline void resize(Index nbRows, NoChange_t)
{ {
resize(nbRows, cols()); resize(rows, cols());
} }
/** Resizes \c *this to have the same dimensions as \a other. /** Resizes \c *this to have the same dimensions as \a other.
@@ -328,11 +291,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* remain row-vectors and vectors remain vectors. * remain row-vectors and vectors remain vectors.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other) EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
{ {
const OtherDerived& other = _other.derived(); const OtherDerived& other = _other.derived();
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.rows(), other.cols()); internal::check_rows_cols_for_overflow(other.rows(), other.cols());
const Index othersize = other.rows()*other.cols(); const Index othersize = other.rows()*other.cols();
if(RowsAtCompileTime == 1) if(RowsAtCompileTime == 1)
{ {
@@ -356,10 +318,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* Matrices are resized relative to the top-left element. In case values need to be * Matrices are resized relative to the top-left element. In case values need to be
* appended to the matrix they will be uninitialized. * appended to the matrix they will be uninitialized.
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
EIGEN_STRONG_INLINE void conservativeResize(Index nbRows, Index nbCols)
{ {
internal::conservative_resize_like_impl<Derived>::run(*this, nbRows, nbCols); internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
} }
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched. /** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
@@ -369,11 +330,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* In case the matrix is growing, new rows will be uninitialized. * In case the matrix is growing, new rows will be uninitialized.
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
EIGEN_STRONG_INLINE void conservativeResize(Index nbRows, NoChange_t)
{ {
// Note: see the comment in conservativeResize(Index,Index) // Note: see the comment in conservativeResize(Index,Index)
conservativeResize(nbRows, cols()); conservativeResize(rows, cols());
} }
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched. /** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
@@ -383,11 +343,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* In case the matrix is growing, new columns will be uninitialized. * In case the matrix is growing, new columns will be uninitialized.
*/ */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index nbCols)
{ {
// Note: see the comment in conservativeResize(Index,Index) // Note: see the comment in conservativeResize(Index,Index)
conservativeResize(rows(), nbCols); conservativeResize(rows(), cols);
} }
/** Resizes the vector to \a size while retaining old values. /** Resizes the vector to \a size while retaining old values.
@@ -398,7 +357,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* *
* When values are appended, they will be uninitialized. * When values are appended, they will be uninitialized.
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void conservativeResize(Index size) EIGEN_STRONG_INLINE void conservativeResize(Index size)
{ {
internal::conservative_resize_like_impl<Derived>::run(*this, size); internal::conservative_resize_like_impl<Derived>::run(*this, size);
@@ -414,7 +372,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* appended to the matrix they will copied from \c other. * appended to the matrix they will copied from \c other.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other)
{ {
internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other); internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
@@ -423,7 +380,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** This is a special case of the templated operator=. Its purpose is to /** This is a special case of the templated operator=. Its purpose is to
* prevent a default operator= from hiding the templated operator=. * prevent a default operator= from hiding the templated operator=.
*/ */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other) EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other)
{ {
return _set(other); return _set(other);
@@ -431,7 +387,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \sa MatrixBase::lazyAssign() */ /** \sa MatrixBase::lazyAssign() */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other)
{ {
_resize_to_match(other); _resize_to_match(other);
@@ -439,59 +394,38 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func) EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func)
{ {
resize(func.rows(), func.cols()); resize(func.rows(), func.cols());
return Base::operator=(func); return Base::operator=(func);
} }
EIGEN_DEVICE_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_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
// FIXME is it still needed ? // FIXME is it still needed ?
/** \internal */ /** \internal */
EIGEN_DEVICE_FUNC
PlainObjectBase(internal::constructor_without_unaligned_array_assert) PlainObjectBase(internal::constructor_without_unaligned_array_assert)
: m_storage(internal::constructor_without_unaligned_array_assert()) : m_storage(internal::constructor_without_unaligned_array_assert())
{ {
// _check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED // _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
#endif #endif
#ifdef EIGEN_HAVE_RVALUE_REFERENCES EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
EIGEN_DEVICE_FUNC : m_storage(size, rows, cols)
PlainObjectBase(PlainObjectBase&& other)
: m_storage( std::move(other.m_storage) )
{
}
EIGEN_DEVICE_FUNC
PlainObjectBase& operator=(PlainObjectBase&& other)
{
using std::swap;
swap(m_storage, other.m_storage);
return *this;
}
#endif
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE PlainObjectBase(Index a_size, Index nbRows, Index nbCols)
: m_storage(a_size, nbRows, nbCols)
{ {
// _check_template_params(); // _check_template_params();
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
/** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&) /** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&)
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
{ {
_resize_to_match(other); _resize_to_match(other);
@@ -501,12 +435,11 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */ /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other) EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols()) : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
{ {
_check_template_params(); _check_template_params();
internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.derived().rows(), other.derived().cols()); internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols());
Base::operator=(other.derived()); Base::operator=(other.derived());
} }
@@ -584,16 +517,16 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
//@} //@}
using Base::setConstant; using Base::setConstant;
EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& value); Derived& setConstant(Index size, const Scalar& value);
EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& value); Derived& setConstant(Index rows, Index cols, const Scalar& value);
using Base::setZero; using Base::setZero;
EIGEN_DEVICE_FUNC Derived& setZero(Index size); Derived& setZero(Index size);
EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols); Derived& setZero(Index rows, Index cols);
using Base::setOnes; using Base::setOnes;
EIGEN_DEVICE_FUNC Derived& setOnes(Index size); Derived& setOnes(Index size);
EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols); Derived& setOnes(Index rows, Index cols);
using Base::setRandom; using Base::setRandom;
Derived& setRandom(Index size); Derived& setRandom(Index size);
@@ -612,7 +545,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* remain row-vectors and vectors remain vectors. * remain row-vectors and vectors remain vectors.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
{ {
#ifdef EIGEN_NO_AUTOMATIC_RESIZING #ifdef EIGEN_NO_AUTOMATIC_RESIZING
@@ -640,7 +572,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* \internal * \internal
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
{ {
_set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type()); _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
@@ -648,11 +579,9 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); } EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); } EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
@@ -661,7 +590,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* \sa operator=(const MatrixBase<OtherDerived>&), _set() * \sa operator=(const MatrixBase<OtherDerived>&), _set()
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other) EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other)
{ {
// I don't think we need this resize call since the lazyAssign will anyways resize // I don't think we need this resize call since the lazyAssign will anyways resize
@@ -673,98 +601,23 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
} }
template<typename T0, typename T1> template<typename T0, typename T1>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
EIGEN_STRONG_INLINE void _init2(Index nbRows, Index nbCols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
{ {
EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) && EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
bool(NumTraits<T1>::IsInteger), bool(NumTraits<T1>::IsInteger),
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
resize(nbRows,nbCols); eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
internal::check_rows_cols_for_overflow(rows, cols);
m_storage.resize(rows*cols,rows,cols);
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
} }
template<typename T0, typename T1> template<typename T0, typename T1>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
EIGEN_STRONG_INLINE void _init2(const Scalar& val0, const Scalar& val1, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
{ {
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
m_storage.data()[0] = val0; m_storage.data()[0] = x;
m_storage.data()[1] = val1; m_storage.data()[1] = y;
}
template<typename T0, typename T1>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init2(const Index& val0, const Index& val1,
typename internal::enable_if< (!internal::is_same<Index,Scalar>::value)
&& (internal::is_same<T0,Index>::value)
&& (internal::is_same<T1,Index>::value)
&& Base::SizeAtCompileTime==2,T1>::type* = 0)
{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
m_storage.data()[0] = Scalar(val0);
m_storage.data()[1] = Scalar(val1);
}
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if<Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value,T>::type* = 0)
{
// NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument.
const bool is_integer = NumTraits<T>::IsInteger;
EIGEN_STATIC_ASSERT(is_integer,
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
resize(size);
}
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0)
{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1)
m_storage.data()[0] = val0;
}
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Index& val0,
typename internal::enable_if< (!internal::is_same<Index,Scalar>::value)
&& (internal::is_same<Index,T>::value)
&& Base::SizeAtCompileTime==1
&& internal::is_convertible<T, Scalar>::value,T*>::type* = 0)
{
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1)
m_storage.data()[0] = Scalar(val0);
}
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const Scalar* data){
this->_set_noalias(ConstMapType(data));
}
template<typename T, typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other){
this->_set_noalias(other);
}
template<typename T, typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other){
this->derived() = other;
}
template<typename T, typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const ReturnByValue<OtherDerived>& other)
{
resize(other.rows(), other.cols());
other.evalTo(this->derived());
}
template<typename T, typename OtherDerived, int ColsAtCompileTime>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void _init1(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
{
this->derived() = r;
} }
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
@@ -774,7 +627,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
* data pointers. * data pointers.
*/ */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void _swap(DenseBase<OtherDerived> const & other) void _swap(DenseBase<OtherDerived> const & other)
{ {
enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic }; enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
@@ -783,7 +635,6 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
public: public:
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void _check_template_params() static EIGEN_STRONG_INLINE void _check_template_params()
{ {
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
@@ -803,10 +654,8 @@ private:
enum { ThisConstantIsPrivateInPlainObjectBase }; enum { ThisConstantIsPrivateInPlainObjectBase };
}; };
namespace internal {
template <typename Derived, typename OtherDerived, bool IsVector> template <typename Derived, typename OtherDerived, bool IsVector>
struct conservative_resize_like_impl struct internal::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)
@@ -817,7 +666,7 @@ struct conservative_resize_like_impl
if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
(!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns
{ {
internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime>::run(rows, cols); internal::check_rows_cols_for_overflow(rows, cols);
_this.derived().m_storage.conservativeResize(rows*cols,rows,cols); _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
} }
else else
@@ -866,14 +715,11 @@ struct conservative_resize_like_impl
} }
}; };
// Here, the specialization for vectors inherits from the general matrix case namespace internal {
// 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)
{ {
@@ -900,7 +746,6 @@ struct conservative_resize_like_impl<Derived,OtherDerived,true>
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
struct matrix_swap_impl struct matrix_swap_impl
{ {
EIGEN_DEVICE_FUNC
static inline void run(MatrixTypeA& a, MatrixTypeB& b) static inline void run(MatrixTypeA& a, MatrixTypeB& b)
{ {
a.base().swap(b); a.base().swap(b);
@@ -910,7 +755,6 @@ struct matrix_swap_impl
template<typename MatrixTypeA, typename MatrixTypeB> template<typename MatrixTypeA, typename MatrixTypeB>
struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
{ {
EIGEN_DEVICE_FUNC
static inline void run(MatrixTypeA& a, MatrixTypeB& b) static inline void run(MatrixTypeA& a, MatrixTypeB& b)
{ {
static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage); static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);

View File

@@ -3,15 +3,13 @@
// //
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr> // Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
// //
// This Source Code Form is subject to the terms of the Mozilla // This Source Code Form is subject to the terms of the Mozilla Public
// Public License v. 2.0. If a copy of the MPL was not distributed // License, v. 2.0. If a copy of the MPL was not distributed with this
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_PRODUCT_H #ifndef EIGEN_PRODUCT_H
#define EIGEN_PRODUCT_H #define EIGEN_PRODUCT_H
namespace Eigen {
template<typename Lhs, typename Rhs> class Product; template<typename Lhs, typename Rhs> class Product;
template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl; template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl;
@@ -27,16 +25,25 @@ template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl;
* *
*/ */
// Use ProductReturnType to get correct traits, in particular vectorization flags
namespace internal { namespace internal {
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct traits<Product<Lhs, 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> typedef MatrixXpr XprKind;
// TODO: This flag should eventually go in a separate evaluator traits class typedef typename remove_all<Lhs>::type LhsCleaned;
typedef typename remove_all<Rhs>::type RhsCleaned;
typedef typename scalar_product_traits<typename traits<LhsCleaned>::Scalar, typename traits<RhsCleaned>::Scalar>::ReturnType Scalar;
typedef typename promote_storage_type<typename traits<LhsCleaned>::StorageKind,
typename traits<RhsCleaned>::StorageKind>::ret StorageKind;
typedef typename promote_index_type<typename traits<LhsCleaned>::Index,
typename traits<RhsCleaned>::Index>::type Index;
enum { enum {
Flags = traits<typename ProductReturnType<Lhs, Rhs>::Type>::Flags & ~(EvalBeforeNestingBit | DirectAccessBit) RowsAtCompileTime = LhsCleaned::RowsAtCompileTime,
ColsAtCompileTime = RhsCleaned::ColsAtCompileTime,
MaxRowsAtCompileTime = LhsCleaned::MaxRowsAtCompileTime,
MaxColsAtCompileTime = RhsCleaned::MaxColsAtCompileTime,
Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0), // TODO should be no storage order
CoeffReadCost = 0 // TODO CoeffReadCost should not be part of the expression traits
}; };
}; };
} // end namespace internal } // end namespace internal
@@ -74,8 +81,8 @@ class Product : public ProductImpl<Lhs,Rhs,typename internal::promote_storage_ty
protected: protected:
LhsNested m_lhs; const LhsNested m_lhs;
RhsNested m_rhs; const RhsNested m_rhs;
}; };
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
@@ -88,20 +95,4 @@ class ProductImpl<Lhs,Rhs,Dense> : public internal::dense_xpr_base<Product<Lhs,R
EIGEN_DENSE_PUBLIC_INTERFACE(Derived) 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 #endif // EIGEN_PRODUCT_H

View File

@@ -87,10 +87,10 @@ class ProductBase : public MatrixBase<Derived>
typedef typename Base::PlainObject PlainObject; typedef typename Base::PlainObject PlainObject;
ProductBase(const Lhs& a_lhs, const Rhs& a_rhs) ProductBase(const Lhs& lhs, const Rhs& rhs)
: m_lhs(a_lhs), m_rhs(a_rhs) : m_lhs(lhs), m_rhs(rhs)
{ {
eigen_assert(a_lhs.cols() == a_rhs.rows() eigen_assert(lhs.cols() == rhs.rows()
&& "invalid matrix product" && "invalid matrix product"
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions"); && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
} }
@@ -108,7 +108,7 @@ class ProductBase : public MatrixBase<Derived>
inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); } inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); }
template<typename Dest> template<typename Dest>
inline void scaleAndAddTo(Dest& dst, const Scalar& alpha) const { derived().scaleAndAddTo(dst,alpha); } inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); }
const _LhsNested& lhs() const { return m_lhs; } const _LhsNested& lhs() const { return m_lhs; }
const _RhsNested& rhs() const { return m_rhs; } const _RhsNested& rhs() const { return m_rhs; }
@@ -131,13 +131,17 @@ class ProductBase : public MatrixBase<Derived>
const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); } { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
// restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isn't an Lvalue expression // restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression
typename Base::CoeffReturnType coeff(Index row, Index col) const typename Base::CoeffReturnType coeff(Index row, Index col) const
{ {
#ifdef EIGEN2_SUPPORT
return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum();
#else
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
eigen_assert(this->rows() == 1 && this->cols() == 1); eigen_assert(this->rows() == 1 && this->cols() == 1);
Matrix<Scalar,1,1> result = *this; Matrix<Scalar,1,1> result = *this;
return result.coeff(row,col); return result.coeff(row,col);
#endif
} }
typename Base::CoeffReturnType coeff(Index i) const typename Base::CoeffReturnType coeff(Index i) const
@@ -191,25 +195,25 @@ 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, const typename Derived::Scalar& x) operator*(const ProductBase<Derived,Lhs,Rhs>& prod, 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>
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value, typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
const ScaledProduct<Derived> >::type const ScaledProduct<Derived> >::type
operator*(const ProductBase<Derived,Lhs,Rhs>& prod, const typename Derived::RealScalar& x) operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::RealScalar 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>
const ScaledProduct<Derived> const ScaledProduct<Derived>
operator*(const typename Derived::Scalar& x,const ProductBase<Derived,Lhs,Rhs>& prod) operator*(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>
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value, typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
const ScaledProduct<Derived> >::type const ScaledProduct<Derived> >::type
operator*(const typename Derived::RealScalar& x,const ProductBase<Derived,Lhs,Rhs>& prod) operator*(typename Derived::RealScalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
{ return ScaledProduct<Derived>(prod.derived(), x); } { return ScaledProduct<Derived>(prod.derived(), x); }
namespace internal { namespace internal {
@@ -237,7 +241,7 @@ class ScaledProduct
typedef typename Base::PlainObject PlainObject; typedef typename Base::PlainObject PlainObject;
// EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct) // EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct)
ScaledProduct(const NestedProduct& prod, const Scalar& x) ScaledProduct(const NestedProduct& prod, Scalar x)
: Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {} : Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {}
template<typename Dest> template<typename Dest>
@@ -250,7 +254,7 @@ class ScaledProduct
inline void subTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(-1)); } inline void subTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(-1)); }
template<typename Dest> template<typename Dest>
inline void scaleAndAddTo(Dest& dst, const Scalar& a_alpha) const { m_prod.derived().scaleAndAddTo(dst,a_alpha * m_alpha); } inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { m_prod.derived().scaleAndAddTo(dst,alpha * m_alpha); }
const Scalar& alpha() const { return m_alpha; } const Scalar& alpha() const { return m_alpha; }

View File

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

View File

@@ -27,20 +27,14 @@ struct functor_traits<scalar_random_op<Scalar> >
} // end namespace internal } // end namespace internal
/** \returns a random matrix expression /** \returns a random matrix expression
*
* Numbers are uniformly spread through their whole definition range for integer types,
* and in the [-1:1] range for floating point scalar types.
* *
* The parameters \a rows and \a cols are the number of rows and of columns of * The parameters \a rows and \a cols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type. * the returned matrix. Must be compatible with this MatrixBase type.
* *
* \not_reentrant
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, * This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
* it is redundant to pass \a rows and \a cols as arguments, so Random() should be used * it is redundant to pass \a rows and \a cols as arguments, so Random() should be used
* instead. * instead.
* *
*
* Example: \include MatrixBase_random_int_int.cpp * Example: \include MatrixBase_random_int_int.cpp
* Output: \verbinclude MatrixBase_random_int_int.out * Output: \verbinclude MatrixBase_random_int_int.out
* *
@@ -48,9 +42,7 @@ struct functor_traits<scalar_random_op<Scalar> >
* a temporary matrix whenever it is nested in a larger expression. This prevents unexpected * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected
* behavior with expressions involving random matrices. * behavior with expressions involving random matrices.
* *
* See DenseBase::NullaryExpr(Index, const CustomNullaryOp&) for an example using C++11 random generators. * \sa MatrixBase::setRandom(), MatrixBase::Random(Index), MatrixBase::Random()
*
* \sa DenseBase::setRandom(), DenseBase::Random(Index), DenseBase::Random()
*/ */
template<typename Derived> template<typename Derived>
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
@@ -60,15 +52,11 @@ DenseBase<Derived>::Random(Index rows, Index cols)
} }
/** \returns a random vector expression /** \returns a random vector expression
*
* Numbers are uniformly spread through their whole definition range for integer types,
* and in the [-1:1] range for floating point scalar types.
* *
* The parameter \a size is the size of the returned vector. * The parameter \a size is the size of the returned vector.
* Must be compatible with this MatrixBase type. * Must be compatible with this MatrixBase type.
* *
* \only_for_vectors * \only_for_vectors
* \not_reentrant
* *
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, * This variant is meant to be used for dynamic-size vector types. For fixed-size types,
* it is redundant to pass \a size as argument, so Random() should be used * it is redundant to pass \a size as argument, so Random() should be used
@@ -81,7 +69,7 @@ DenseBase<Derived>::Random(Index rows, Index cols)
* a temporary vector whenever it is nested in a larger expression. This prevents unexpected * a temporary vector whenever it is nested in a larger expression. This prevents unexpected
* behavior with expressions involving random matrices. * behavior with expressions involving random matrices.
* *
* \sa DenseBase::setRandom(), DenseBase::Random(Index,Index), DenseBase::Random() * \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random()
*/ */
template<typename Derived> template<typename Derived>
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
@@ -91,9 +79,6 @@ DenseBase<Derived>::Random(Index size)
} }
/** \returns a fixed-size random matrix or vector expression /** \returns a fixed-size random matrix or vector expression
*
* Numbers are uniformly spread through their whole definition range for integer types,
* and in the [-1:1] range for floating point scalar types.
* *
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you
* need to use the variants taking size arguments. * need to use the variants taking size arguments.
@@ -105,9 +90,7 @@ DenseBase<Derived>::Random(Index size)
* a temporary matrix whenever it is nested in a larger expression. This prevents unexpected * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected
* behavior with expressions involving random matrices. * behavior with expressions involving random matrices.
* *
* \not_reentrant * \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random(Index)
*
* \sa DenseBase::setRandom(), DenseBase::Random(Index,Index), DenseBase::Random(Index)
*/ */
template<typename Derived> template<typename Derived>
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
@@ -117,11 +100,6 @@ DenseBase<Derived>::Random()
} }
/** Sets all coefficients in this expression to random values. /** Sets all coefficients in this expression to random values.
*
* Numbers are uniformly spread through their whole definition range for integer types,
* and in the [-1:1] range for floating point scalar types.
*
* \not_reentrant
* *
* Example: \include MatrixBase_setRandom.cpp * Example: \include MatrixBase_setRandom.cpp
* Output: \verbinclude MatrixBase_setRandom.out * Output: \verbinclude MatrixBase_setRandom.out
@@ -134,47 +112,38 @@ inline Derived& DenseBase<Derived>::setRandom()
return *this = Random(rows(), cols()); return *this = Random(rows(), cols());
} }
/** Resizes to the given \a newSize, and sets all coefficients in this expression to random values. /** Resizes to the given \a size, and sets all coefficients in this expression to random values.
*
* Numbers are uniformly spread through their whole definition range for integer types,
* and in the [-1:1] range for floating point scalar types.
* *
* \only_for_vectors * \only_for_vectors
* \not_reentrant
* *
* Example: \include Matrix_setRandom_int.cpp * Example: \include Matrix_setRandom_int.cpp
* Output: \verbinclude Matrix_setRandom_int.out * Output: \verbinclude Matrix_setRandom_int.out
* *
* \sa DenseBase::setRandom(), setRandom(Index,Index), class CwiseNullaryOp, DenseBase::Random() * \sa MatrixBase::setRandom(), setRandom(Index,Index), class CwiseNullaryOp, MatrixBase::Random()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setRandom(Index newSize) PlainObjectBase<Derived>::setRandom(Index size)
{ {
resize(newSize); resize(size);
return setRandom(); return setRandom();
} }
/** Resizes to the given size, and sets all coefficients in this expression to random values. /** Resizes to the given size, and sets all coefficients in this expression to random values.
* *
* Numbers are uniformly spread through their whole definition range for integer types, * \param rows the new number of rows
* and in the [-1:1] range for floating point scalar types. * \param cols the new number of columns
*
* \not_reentrant
*
* \param nbRows the new number of rows
* \param nbCols the new number of columns
* *
* Example: \include Matrix_setRandom_int_int.cpp * Example: \include Matrix_setRandom_int_int.cpp
* Output: \verbinclude Matrix_setRandom_int_int.out * Output: \verbinclude Matrix_setRandom_int_int.out
* *
* \sa DenseBase::setRandom(), setRandom(Index), class CwiseNullaryOp, DenseBase::Random() * \sa MatrixBase::setRandom(), setRandom(Index), class CwiseNullaryOp, MatrixBase::Random()
*/ */
template<typename Derived> template<typename Derived>
EIGEN_STRONG_INLINE Derived& EIGEN_STRONG_INLINE Derived&
PlainObjectBase<Derived>::setRandom(Index nbRows, Index nbCols) PlainObjectBase<Derived>::setRandom(Index rows, Index cols)
{ {
resize(nbRows, nbCols); resize(rows, cols);
return setRandom(); return setRandom();
} }

View File

@@ -82,7 +82,6 @@ struct redux_novec_unroller
typedef typename Derived::Scalar Scalar; typedef typename Derived::Scalar Scalar;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func) static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func)
{ {
return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func), return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
@@ -100,7 +99,6 @@ struct redux_novec_unroller<Func, Derived, Start, 1>
typedef typename Derived::Scalar Scalar; typedef typename Derived::Scalar Scalar;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func&) static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func&)
{ {
return mat.coeffByOuterInner(outer, inner); return mat.coeffByOuterInner(outer, inner);
@@ -114,7 +112,6 @@ template<typename Func, typename Derived, int Start>
struct redux_novec_unroller<Func, Derived, Start, 0> struct redux_novec_unroller<Func, Derived, Start, 0>
{ {
typedef typename Derived::Scalar Scalar; typedef typename Derived::Scalar Scalar;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(const Derived&, const Func&) { return Scalar(); } static EIGEN_STRONG_INLINE Scalar run(const Derived&, const Func&) { return Scalar(); }
}; };
@@ -173,7 +170,6 @@ struct redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>
{ {
typedef typename Derived::Scalar Scalar; typedef typename Derived::Scalar Scalar;
typedef typename Derived::Index Index; typedef typename Derived::Index Index;
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func)
{ {
eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
@@ -207,7 +203,7 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
const Index packetSize = packet_traits<Scalar>::size; const Index packetSize = packet_traits<Scalar>::size;
const Index alignedStart = internal::first_aligned(mat); const Index alignedStart = internal::first_aligned(mat);
enum { enum {
alignment = (bool(Derived::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::AlignedOnScalar)) || bool(Derived::Flags & AlignedBit) alignment = bool(Derived::Flags & DirectAccessBit) || bool(Derived::Flags & AlignedBit)
? Aligned : Unaligned ? Aligned : Unaligned
}; };
const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize); const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize);
@@ -303,16 +299,11 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, CompleteUnrolling>
static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func)
{ {
eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
if (VectorizedSize > 0) {
Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func)); Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func));
if (VectorizedSize != Size) if (VectorizedSize != Size)
res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func)); res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
return res; return res;
} }
else {
return redux_novec_unroller<Func, Derived, 0, Size>::run(mat,func);
}
}
}; };
} // end namespace internal } // end namespace internal
@@ -339,8 +330,7 @@ DenseBase<Derived>::redux(const Func& func) const
::run(derived(), func); ::run(derived(), func);
} }
/** \returns the minimum of all coefficients of \c *this. /** \returns the minimum of all coefficients of *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
@@ -349,8 +339,7 @@ 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 \c *this. /** \returns the maximum of all coefficients of *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

View File

@@ -1,260 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 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_REF_H
#define EIGEN_REF_H
namespace Eigen {
template<typename Derived> class RefBase;
template<typename PlainObjectType, int Options = 0,
typename StrideType = typename internal::conditional<PlainObjectType::IsVectorAtCompileTime,InnerStride<1>,OuterStride<> >::type > class Ref;
/** \class Ref
* \ingroup Core_Module
*
* \brief A matrix or vector expression mapping an existing expression
*
* \tparam PlainObjectType the equivalent matrix type of the mapped data
* \tparam Options specifies whether the pointer is \c #Aligned, or \c #Unaligned.
* The default is \c #Unaligned.
* \tparam StrideType optionally specifies strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1),
* but accepts a variable outer stride (leading dimension).
* This can be overridden by specifying strides.
* The type passed here must be a specialization of the Stride template, see examples below.
*
* This class provides a way to write non-template functions taking Eigen objects as parameters while limiting the number of copies.
* A Ref<> object can represent either a const expression or a l-value:
* \code
* // in-out argument:
* void foo1(Ref<VectorXf> x);
*
* // read-only const argument:
* void foo2(const Ref<const VectorXf>& x);
* \endcode
*
* In the in-out case, the input argument must satisfy the constraints of the actual Ref<> type, otherwise a compilation issue will be triggered.
* By default, a Ref<VectorXf> can reference any dense vector expression of float having a contiguous memory layout.
* Likewise, a Ref<MatrixXf> can reference any column-major dense matrix expression of float whose column's elements are contiguously stored with
* the possibility to have a constant space in-between each column, i.e. the inner stride must be equal to 1, but the outer stride (or leading dimension)
* can be greater than the number of rows.
*
* In the const case, if the input expression does not match the above requirement, then it is evaluated into a temporary before being passed to the function.
* Here are some examples:
* \code
* MatrixXf A;
* VectorXf a;
* foo1(a.head()); // OK
* foo1(A.col()); // OK
* foo1(A.row()); // compilation error because here innerstride!=1
* foo2(A.row()); // The row is copied into a contiguous temporary
* foo2(2*a); // The expression is evaluated into a temporary
* foo2(A.col().segment(2,4)); // No temporary
* \endcode
*
* The range of inputs that can be referenced without temporary can be enlarged using the last two template parameters.
* Here is an example accepting an innerstride!=1:
* \code
* // in-out argument:
* void foo3(Ref<VectorXf,0,InnerStride<> > x);
* foo3(A.row()); // OK
* \endcode
* The downside here is that the function foo3 might be significantly slower than foo1 because it won't be able to exploit vectorization, and will involve more
* expensive address computations even if the input is contiguously stored in memory. To overcome this issue, one might propose to overload internally calling a
* template function, e.g.:
* \code
* // in the .h:
* void foo(const Ref<MatrixXf>& A);
* void foo(const Ref<MatrixXf,0,Stride<> >& A);
*
* // in the .cpp:
* template<typename TypeOfA> void foo_impl(const TypeOfA& A) {
* ... // crazy code goes here
* }
* void foo(const Ref<MatrixXf>& A) { foo_impl(A); }
* void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); }
* \endcode
*
*
* \sa PlainObjectBase::Map(), \ref TopicStorageOrders
*/
namespace internal {
template<typename _PlainObjectType, int _Options, typename _StrideType>
struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
: public traits<Map<_PlainObjectType, _Options, _StrideType> >
{
typedef _PlainObjectType PlainObjectType;
typedef _StrideType StrideType;
enum {
Options = _Options,
Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit
};
template<typename Derived> struct match {
enum {
HasDirectAccess = internal::has_direct_access<Derived>::ret,
StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
|| int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
OuterStrideMatch = Derived::IsVectorAtCompileTime
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
AlignmentMatch = (_Options!=Aligned) || ((PlainObjectType::Flags&AlignedBit)==0) || ((traits<Derived>::Flags&AlignedBit)==AlignedBit),
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch
};
typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
};
};
template<typename Derived>
struct traits<RefBase<Derived> > : public traits<Derived> {};
}
template<typename Derived> class RefBase
: public MapBase<Derived>
{
typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType;
typedef typename internal::traits<Derived>::StrideType StrideType;
public:
typedef MapBase<Derived> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
inline Index innerStride() const
{
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
}
inline Index outerStride() const
{
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
: IsVectorAtCompileTime ? this->size()
: int(Flags)&RowMajorBit ? this->cols()
: this->rows();
}
RefBase()
: Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime),
// Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values:
m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime,
StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime)
{}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase)
protected:
typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase;
template<typename Expression>
void construct(Expression& expr)
{
if(PlainObjectType::RowsAtCompileTime==1)
{
eigen_assert(expr.rows()==1 || expr.cols()==1);
::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size());
}
else if(PlainObjectType::ColsAtCompileTime==1)
{
eigen_assert(expr.rows()==1 || expr.cols()==1);
::new (static_cast<Base*>(this)) Base(expr.data(), expr.size(), 1);
}
else
::new (static_cast<Base*>(this)) Base(expr.data(), expr.rows(), expr.cols());
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;
};
template<typename PlainObjectType, int Options, typename StrideType> class Ref
: public RefBase<Ref<PlainObjectType, Options, StrideType> >
{
typedef internal::traits<Ref> Traits;
public:
typedef RefBase<Ref> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename Derived>
inline Ref(PlainObjectBase<Derived>& expr,
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
{
Base::construct(expr);
}
template<typename Derived>
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,
int = Derived::ThisConstantIsPrivateInPlainObjectBase)
#else
template<typename Derived>
inline Ref(DenseBase<Derived>& expr)
#endif
{
Base::construct(expr.const_cast_derived());
}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
};
// this is the const ref version
template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType>
: public RefBase<Ref<const TPlainObjectType, Options, StrideType> >
{
typedef internal::traits<Ref> Traits;
public:
typedef RefBase<Ref> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
template<typename Derived>
inline Ref(const DenseBase<Derived>& expr)
{
// 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::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
construct(expr.derived(), typename Traits::template match<Derived>::type());
}
protected:
template<typename Expression>
void construct(const Expression& expr,internal::true_type)
{
Base::construct(expr);
}
template<typename Expression>
void construct(const Expression& expr, internal::false_type)
{
m_object.lazyAssign(expr);
Base::construct(m_object);
}
protected:
TPlainObjectType m_object;
};
} // end namespace Eigen
#endif // EIGEN_REF_H

View File

@@ -70,8 +70,8 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
EIGEN_DENSE_PUBLIC_INTERFACE(Replicate) EIGEN_DENSE_PUBLIC_INTERFACE(Replicate)
template<typename OriginalMatrixType> template<typename OriginalMatrixType>
inline explicit Replicate(const OriginalMatrixType& a_matrix) inline explicit Replicate(const OriginalMatrixType& matrix)
: m_matrix(a_matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor) : m_matrix(matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor)
{ {
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value), EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
@@ -79,8 +79,8 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
} }
template<typename OriginalMatrixType> template<typename OriginalMatrixType>
inline Replicate(const OriginalMatrixType& a_matrix, Index rowFactor, Index colFactor) inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor)
: m_matrix(a_matrix), m_rowFactor(rowFactor), m_colFactor(colFactor) : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor)
{ {
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value), EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
@@ -89,27 +89,27 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); } inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); } inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
inline Scalar coeff(Index rowId, Index colId) const inline Scalar coeff(Index row, Index col) const
{ {
// try to avoid using modulo; this is a pure optimization strategy // try to avoid using modulo; this is a pure optimization strategy
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0 const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
: RowFactor==1 ? rowId : RowFactor==1 ? row
: rowId%m_matrix.rows(); : row%m_matrix.rows();
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0 const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
: ColFactor==1 ? colId : ColFactor==1 ? col
: colId%m_matrix.cols(); : col%m_matrix.cols();
return m_matrix.coeff(actual_row, actual_col); return m_matrix.coeff(actual_row, actual_col);
} }
template<int LoadMode> template<int LoadMode>
inline PacketScalar packet(Index rowId, Index colId) const inline PacketScalar packet(Index row, Index col) const
{ {
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0 const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
: RowFactor==1 ? rowId : RowFactor==1 ? row
: rowId%m_matrix.rows(); : row%m_matrix.rows();
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0 const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
: ColFactor==1 ? colId : ColFactor==1 ? col
: colId%m_matrix.cols(); : col%m_matrix.cols();
return m_matrix.template packet<LoadMode>(actual_row, actual_col); return m_matrix.template packet<LoadMode>(actual_row, actual_col);
} }

View File

@@ -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
: internal::no_assignment_operator, public internal::dense_xpr_base< ReturnByValue<Derived> >::type : public internal::dense_xpr_base< ReturnByValue<Derived> >::type
{ {
public: public:
typedef typename internal::traits<Derived>::ReturnType ReturnType; typedef typename internal::traits<Derived>::ReturnType ReturnType;
@@ -57,11 +57,10 @@ template<typename Derived> class ReturnByValue
EIGEN_DENSE_PUBLIC_INTERFACE(ReturnByValue) EIGEN_DENSE_PUBLIC_INTERFACE(ReturnByValue)
template<typename Dest> template<typename Dest>
EIGEN_DEVICE_FUNC
inline void evalTo(Dest& dst) const inline void evalTo(Dest& dst) const
{ static_cast<const Derived*>(this)->evalTo(dst); } { static_cast<const Derived*>(this)->evalTo(dst); }
EIGEN_DEVICE_FUNC inline Index rows() const { return static_cast<const Derived*>(this)->rows(); } inline Index rows() const { return static_cast<const Derived*>(this)->rows(); }
EIGEN_DEVICE_FUNC inline Index cols() const { return static_cast<const Derived*>(this)->cols(); } inline Index cols() const { return static_cast<const Derived*>(this)->cols(); }
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
#define Unusable YOU_ARE_TRYING_TO_ACCESS_A_SINGLE_COEFFICIENT_IN_A_SPECIAL_EXPRESSION_WHERE_THAT_IS_NOT_ALLOWED_BECAUSE_THAT_WOULD_BE_INEFFICIENT #define Unusable YOU_ARE_TRYING_TO_ACCESS_A_SINGLE_COEFFICIENT_IN_A_SPECIAL_EXPRESSION_WHERE_THAT_IS_NOT_ALLOWED_BECAUSE_THAT_WOULD_BE_INEFFICIENT

View File

@@ -60,10 +60,10 @@ class Select : internal::no_assignment_operator,
typedef typename internal::dense_xpr_base<Select>::type Base; typedef typename internal::dense_xpr_base<Select>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Select) EIGEN_DENSE_PUBLIC_INTERFACE(Select)
Select(const ConditionMatrixType& a_conditionMatrix, Select(const ConditionMatrixType& conditionMatrix,
const ThenMatrixType& a_thenMatrix, const ThenMatrixType& thenMatrix,
const ElseMatrixType& a_elseMatrix) const ElseMatrixType& elseMatrix)
: m_condition(a_conditionMatrix), m_then(a_thenMatrix), m_else(a_elseMatrix) : m_condition(conditionMatrix), m_then(thenMatrix), m_else(elseMatrix)
{ {
eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows()); eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols()); eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
@@ -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,
const typename ThenDerived::Scalar& elseScalar) 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,7 +150,7 @@ 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(const typename ElseDerived::Scalar& thenScalar, DenseBase<Derived>::select(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>(

View File

@@ -69,23 +69,17 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
}; };
typedef typename MatrixType::PlainObject PlainObject; typedef typename MatrixType::PlainObject PlainObject;
EIGEN_DEVICE_FUNC
inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix)
{} {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_matrix.rows(); } inline Index rows() const { return m_matrix.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_matrix.cols(); } inline Index cols() const { return m_matrix.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_matrix.outerStride(); } inline Index outerStride() const { return m_matrix.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_matrix.innerStride(); } inline Index innerStride() const { return m_matrix.innerStride(); }
/** \sa MatrixBase::coeff() /** \sa MatrixBase::coeff()
* \warning the coordinates must fit into the referenced triangular part * \warning the coordinates must fit into the referenced triangular part
*/ */
EIGEN_DEVICE_FUNC
inline Scalar coeff(Index row, Index col) const inline Scalar coeff(Index row, Index col) const
{ {
Base::check_coordinates_internal(row, col); Base::check_coordinates_internal(row, col);
@@ -95,7 +89,6 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
/** \sa MatrixBase::coeffRef() /** \sa MatrixBase::coeffRef()
* \warning the coordinates must fit into the referenced triangular part * \warning the coordinates must fit into the referenced triangular part
*/ */
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index row, Index col) inline Scalar& coeffRef(Index row, Index col)
{ {
Base::check_coordinates_internal(row, col); Base::check_coordinates_internal(row, col);
@@ -103,17 +96,13 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
} }
/** \internal */ /** \internal */
EIGEN_DEVICE_FUNC
const MatrixTypeNestedCleaned& _expression() const { return m_matrix; } const MatrixTypeNestedCleaned& _expression() const { return m_matrix; }
EIGEN_DEVICE_FUNC
const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; }
EIGEN_DEVICE_FUNC
MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); } MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); }
/** Efficient self-adjoint matrix times vector/matrix product */ /** Efficient self-adjoint matrix times vector/matrix product */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
SelfadjointProductMatrix<MatrixType,Mode,false,OtherDerived,0,OtherDerived::IsVectorAtCompileTime> SelfadjointProductMatrix<MatrixType,Mode,false,OtherDerived,0,OtherDerived::IsVectorAtCompileTime>
operator*(const MatrixBase<OtherDerived>& rhs) const operator*(const MatrixBase<OtherDerived>& rhs) const
{ {
@@ -124,7 +113,6 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
/** Efficient vector/matrix times self-adjoint matrix product */ /** Efficient vector/matrix times self-adjoint matrix product */
template<typename OtherDerived> friend template<typename OtherDerived> friend
EIGEN_DEVICE_FUNC
SelfadjointProductMatrix<OtherDerived,0,OtherDerived::IsVectorAtCompileTime,MatrixType,Mode,false> SelfadjointProductMatrix<OtherDerived,0,OtherDerived::IsVectorAtCompileTime,MatrixType,Mode,false>
operator*(const MatrixBase<OtherDerived>& lhs, const SelfAdjointView& rhs) operator*(const MatrixBase<OtherDerived>& lhs, const SelfAdjointView& rhs)
{ {
@@ -144,8 +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>
EIGEN_DEVICE_FUNC 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.
@@ -158,8 +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>
EIGEN_DEVICE_FUNC 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 ///////////
@@ -173,11 +159,32 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
/** Return type of eigenvalues() */ /** Return type of eigenvalues() */
typedef Matrix<RealScalar, internal::traits<MatrixType>::ColsAtCompileTime, 1> EigenvaluesReturnType; typedef Matrix<RealScalar, internal::traits<MatrixType>::ColsAtCompileTime, 1> EigenvaluesReturnType;
EIGEN_DEVICE_FUNC
EigenvaluesReturnType eigenvalues() const; EigenvaluesReturnType eigenvalues() const;
EIGEN_DEVICE_FUNC
RealScalar operatorNorm() const; RealScalar operatorNorm() const;
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived>
SelfAdjointView& operator=(const MatrixBase<OtherDerived>& other)
{
enum {
OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
};
m_matrix.const_cast_derived().template triangularView<UpLo>() = other;
m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.adjoint();
return *this;
}
template<typename OtherMatrixType, unsigned int OtherMode>
SelfAdjointView& operator=(const TriangularView<OtherMatrixType, OtherMode>& other)
{
enum {
OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
};
m_matrix.const_cast_derived().template triangularView<UpLo>() = other.toDenseMatrix();
m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.toDenseMatrix().adjoint();
return *this;
}
#endif
protected: protected:
MatrixTypeNested m_matrix; MatrixTypeNested m_matrix;
}; };
@@ -202,22 +209,20 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), U
row = (UnrollCount-1) % Derived1::RowsAtCompileTime row = (UnrollCount-1) % Derived1::RowsAtCompileTime
}; };
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
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) = numext::real(src.coeff(row, col)); dst.coeffRef(row, col) = real(src.coeff(row, col));
else if(row < col) else if(row < col)
dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col)); dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
} }
}; };
template<typename Derived1, typename Derived2, bool ClearOpposite> template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, 0, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, 0, ClearOpposite>
{ {
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &, const Derived2 &) {} static inline void run(Derived1 &, const Derived2 &) {}
}; };
@@ -229,22 +234,20 @@ struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), U
row = (UnrollCount-1) % Derived1::RowsAtCompileTime row = (UnrollCount-1) % Derived1::RowsAtCompileTime
}; };
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
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) = numext::real(src.coeff(row, col)); dst.coeffRef(row, col) = real(src.coeff(row, col));
else if(row > col) else if(row > col)
dst.coeffRef(col, row) = numext::conj(dst.coeffRef(row, col) = src.coeff(row, col)); dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
} }
}; };
template<typename Derived1, typename Derived2, bool ClearOpposite> template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, 0, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, 0, ClearOpposite>
{ {
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &, const Derived2 &) {} static inline void run(Derived1 &, const Derived2 &) {}
}; };
@@ -252,7 +255,6 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dynamic, ClearOpposite>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -260,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) = numext::conj(dst.coeff(i,j)); dst.coeffRef(j,i) = conj(dst.coeff(i,j));
} }
dst.copyCoeff(j, j, src); dst.copyCoeff(j, j, src);
} }
@@ -270,7 +272,6 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dyn
template<typename Derived1, typename Derived2, bool ClearOpposite> template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dynamic, ClearOpposite>
{ {
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
@@ -279,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) = numext::conj(dst.coeff(i,j)); dst.coeffRef(j,i) = conj(dst.coeff(i,j));
} }
dst.copyCoeff(i, i, src); dst.copyCoeff(i, i, src);
} }

View File

@@ -35,7 +35,7 @@ struct traits<SelfCwiseBinaryOp<BinaryOp,Lhs,Rhs> >
enum { enum {
// Note that it is still a good idea to preserve the DirectAccessBit // Note that it is still a good idea to preserve the DirectAccessBit
// so that assign can correctly align the data. // so that assign can correctly align the data.
Flags = traits<CwiseBinaryOp<BinaryOp,Lhs,Rhs> >::Flags | (Lhs::Flags&AlignedBit) | (Lhs::Flags&DirectAccessBit) | (Lhs::Flags&LvalueBit), Flags = traits<CwiseBinaryOp<BinaryOp,Lhs,Rhs> >::Flags | (Lhs::Flags&DirectAccessBit) | (Lhs::Flags&LvalueBit),
OuterStrideAtCompileTime = Lhs::OuterStrideAtCompileTime, OuterStrideAtCompileTime = Lhs::OuterStrideAtCompileTime,
InnerStrideAtCompileTime = Lhs::InnerStrideAtCompileTime InnerStrideAtCompileTime = Lhs::InnerStrideAtCompileTime
}; };
@@ -52,24 +52,21 @@ template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
typedef typename internal::packet_traits<Scalar>::type Packet; typedef typename internal::packet_traits<Scalar>::type Packet;
EIGEN_DEVICE_FUNC
inline SelfCwiseBinaryOp(Lhs& xpr, const BinaryOp& func = BinaryOp()) : m_matrix(xpr), m_functor(func) {} inline SelfCwiseBinaryOp(Lhs& xpr, const BinaryOp& func = BinaryOp()) : m_matrix(xpr), m_functor(func) {}
EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows(); } inline Index rows() const { return m_matrix.rows(); }
EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.cols(); } inline Index cols() const { return m_matrix.cols(); }
EIGEN_DEVICE_FUNC inline Index outerStride() const { return m_matrix.outerStride(); } inline Index outerStride() const { return m_matrix.outerStride(); }
EIGEN_DEVICE_FUNC inline Index innerStride() const { return m_matrix.innerStride(); } inline Index innerStride() const { return m_matrix.innerStride(); }
EIGEN_DEVICE_FUNC inline const Scalar* data() const { return m_matrix.data(); } inline const Scalar* data() const { return m_matrix.data(); }
// note that this function is needed by assign to correctly align loads/stores // note that this function is needed by assign to correctly align loads/stores
// TODO make Assign use .data() // TODO make Assign use .data()
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index row, Index col) inline Scalar& coeffRef(Index row, Index col)
{ {
EIGEN_STATIC_ASSERT_LVALUE(Lhs) EIGEN_STATIC_ASSERT_LVALUE(Lhs)
return m_matrix.const_cast_derived().coeffRef(row, col); return m_matrix.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index row, Index col) const inline const Scalar& coeffRef(Index row, Index col) const
{ {
return m_matrix.coeffRef(row, col); return m_matrix.coeffRef(row, col);
@@ -77,20 +74,17 @@ template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
// note that this function is needed by assign to correctly align loads/stores // note that this function is needed by assign to correctly align loads/stores
// TODO make Assign use .data() // TODO make Assign use .data()
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) inline Scalar& coeffRef(Index index)
{ {
EIGEN_STATIC_ASSERT_LVALUE(Lhs) EIGEN_STATIC_ASSERT_LVALUE(Lhs)
return m_matrix.const_cast_derived().coeffRef(index); return m_matrix.const_cast_derived().coeffRef(index);
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
return m_matrix.const_cast_derived().coeffRef(index); return m_matrix.const_cast_derived().coeffRef(index);
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other) void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
{ {
OtherDerived& _other = other.const_cast_derived(); OtherDerived& _other = other.const_cast_derived();
@@ -101,7 +95,6 @@ template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void copyCoeff(Index index, const DenseBase<OtherDerived>& other) void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
{ {
OtherDerived& _other = other.const_cast_derived(); OtherDerived& _other = other.const_cast_derived();
@@ -132,7 +125,6 @@ template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
// reimplement lazyAssign to handle complex *= real // reimplement lazyAssign to handle complex *= real
// see CwiseBinaryOp ctor for details // see CwiseBinaryOp ctor for details
template<typename RhsDerived> template<typename RhsDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE SelfCwiseBinaryOp& lazyAssign(const DenseBase<RhsDerived>& rhs) EIGEN_STRONG_INLINE SelfCwiseBinaryOp& lazyAssign(const DenseBase<RhsDerived>& rhs)
{ {
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs,RhsDerived) EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs,RhsDerived)
@@ -152,20 +144,17 @@ template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
// overloaded to honor evaluation of special matrices // overloaded to honor evaluation of special matrices
// maybe another solution would be to not use SelfCwiseBinaryOp // maybe another solution would be to not use SelfCwiseBinaryOp
// at first... // at first...
EIGEN_DEVICE_FUNC
SelfCwiseBinaryOp& operator=(const Rhs& _rhs) SelfCwiseBinaryOp& operator=(const Rhs& _rhs)
{ {
typename internal::nested<Rhs>::type rhs(_rhs); typename internal::nested<Rhs>::type rhs(_rhs);
return Base::operator=(rhs); return Base::operator=(rhs);
} }
EIGEN_DEVICE_FUNC
Lhs& expression() const Lhs& expression() const
{ {
return m_matrix; return m_matrix;
} }
EIGEN_DEVICE_FUNC
const BinaryOp& functor() const const BinaryOp& functor() const
{ {
return m_functor; return m_functor;
@@ -188,30 +177,15 @@ inline Derived& DenseBase<Derived>::operator*=(const Scalar& other)
return derived(); return derived();
} }
template<typename Derived>
inline Derived& ArrayBase<Derived>::operator+=(const Scalar& other)
{
typedef typename Derived::PlainObject PlainObject;
SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
tmp = PlainObject::Constant(rows(),cols(),other);
return derived();
}
template<typename Derived>
inline Derived& ArrayBase<Derived>::operator-=(const Scalar& other)
{
typedef typename Derived::PlainObject PlainObject;
SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
tmp = PlainObject::Constant(rows(),cols(),other);
return derived();
}
template<typename Derived> template<typename Derived>
inline Derived& DenseBase<Derived>::operator/=(const Scalar& other) inline Derived& DenseBase<Derived>::operator/=(const Scalar& other)
{ {
typedef typename internal::conditional<NumTraits<Scalar>::IsInteger,
internal::scalar_quotient_op<Scalar>,
internal::scalar_product_op<Scalar> >::type BinOp;
typedef typename Derived::PlainObject PlainObject; typedef typename Derived::PlainObject PlainObject;
SelfCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived()); SelfCwiseBinaryOp<BinOp, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
tmp = PlainObject::Constant(rows(),cols(), other); tmp = PlainObject::Constant(rows(),cols(), NumTraits<Scalar>::IsInteger ? other : Scalar(1)/other);
return derived(); return derived();
} }

View File

@@ -17,62 +17,76 @@ 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)
{ {
using std::max; Scalar max = bl.cwiseAbs().maxCoeff();
Scalar maxCoeff = bl.cwiseAbs().maxCoeff(); if (max>scale)
if(maxCoeff>scale)
{ {
ssq = ssq * numext::abs2(scale/maxCoeff); ssq = ssq * abs2(scale/max);
Scalar tmp = Scalar(1)/maxCoeff; scale = max;
if(tmp > NumTraits<Scalar>::highest()) invScale = Scalar(1)/scale;
{
invScale = NumTraits<Scalar>::highest();
scale = Scalar(1)/invScale;
} }
else if(maxCoeff>NumTraits<Scalar>::highest()) // we got a INF // TODO if the max is much much smaller than the current scale,
{
invScale = Scalar(1);
scale = maxCoeff;
}
else
{
scale = maxCoeff;
invScale = tmp;
}
}
else if(maxCoeff!=maxCoeff) // we got a NaN
{
scale = maxCoeff;
}
// 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
if(scale>Scalar(0)) // if scale==0, then bl is 0
ssq += (bl*invScale).squaredNorm(); ssq += (bl*invScale).squaredNorm();
} }
}
/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
* This version use a blockwise two passes algorithm:
* 1 - find the absolute largest coefficient \c s
* 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way
*
* For architecture/scalar types supporting vectorization, this version
* is faster than blueNorm(). Otherwise the blueNorm() is much faster.
*
* \sa norm(), blueNorm(), hypotNorm()
*/
template<typename Derived> template<typename Derived>
inline typename NumTraits<typename traits<Derived>::Scalar>::Real inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
blueNorm_impl(const EigenBase<Derived>& _vec) MatrixBase<Derived>::stableNorm() const
{
using std::min;
const Index blockSize = 4096;
RealScalar scale(0);
RealScalar invScale(1);
RealScalar ssq(0); // sum of square
enum {
Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
};
Index n = size();
Index bi = internal::first_aligned(derived());
if (bi>0)
internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
for (; bi<n; bi+=blockSize)
internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
return scale * internal::sqrt(ssq);
}
/** \returns the \em l2 norm of \c *this using the Blue's algorithm.
* A Portable Fortran Program to Find the Euclidean Norm of a Vector,
* ACM TOMS, Vol 4, Issue 1, 1978.
*
* For architecture/scalar types without vectorization, this version
* is much faster than stableNorm(). Otherwise the stableNorm() is faster.
*
* \sa norm(), stableNorm(), hypotNorm()
*/
template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
MatrixBase<Derived>::blueNorm() const
{ {
typedef typename Derived::RealScalar RealScalar;
typedef typename Derived::Index Index;
using std::pow; using std::pow;
EIGEN_USING_STD_MATH(min); using std::min;
EIGEN_USING_STD_MATH(max); using std::max;
using std::sqrt;
using std::abs;
const Derived& vec(_vec.derived());
static bool initialized = false; static bool initialized = false;
static RealScalar b1, b2, s1m, s2m, rbig, relerr; static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
if(!initialized) if(!initialized)
{ {
int ibeta, it, iemin, iemax, iexp; int ibeta, it, iemin, iemax, iexp;
RealScalar eps; RealScalar abig, eps;
// This program calculates the machine-dependent constants // This program calculates the machine-dependent constants
// bl, b2, slm, s2m, relerr overfl // bl, b2, slm, s2m, relerr overfl
// from the "basic" machine-dependent numbers // from the "basic" machine-dependent numbers
// nbig, ibeta, it, iemin, iemax, rbig. // 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
@@ -93,33 +107,35 @@ blueNorm_impl(const EigenBase<Derived>& _vec)
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
eps = RealScalar(pow(double(ibeta), 1-it)); eps = RealScalar(pow(double(ibeta), 1-it));
relerr = sqrt(eps); // tolerance for neglecting asml relerr = internal::sqrt(eps); // tolerance for neglecting asml
abig = RealScalar(1.0/eps - 1.0);
initialized = true; initialized = true;
} }
Index n = vec.size(); Index n = size();
RealScalar ab2 = b2 / RealScalar(n); RealScalar ab2 = b2 / RealScalar(n);
RealScalar asml = RealScalar(0); RealScalar asml = RealScalar(0);
RealScalar amed = RealScalar(0); RealScalar amed = RealScalar(0);
RealScalar abig = RealScalar(0); RealScalar abig = RealScalar(0);
for(typename Derived::InnerIterator it(vec, 0); it; ++it) for(Index j=0; j<n; ++j)
{ {
RealScalar ax = abs(it.value()); RealScalar ax = internal::abs(coeff(j));
if(ax > ab2) abig += numext::abs2(ax*s2m); if(ax > ab2) abig += internal::abs2(ax*s2m);
else if(ax < b1) asml += numext::abs2(ax*s1m); else if(ax < b1) asml += internal::abs2(ax*s1m);
else amed += numext::abs2(ax); else amed += internal::abs2(ax);
} }
if(amed!=amed)
return amed; // we got a NaN
if(abig > RealScalar(0)) if(abig > RealScalar(0))
{ {
abig = sqrt(abig); abig = internal::sqrt(abig);
if(abig > rbig) // overflow, or *this contains INF values if(abig > overfl)
return abig; // return INF {
return rbig;
}
if(amed > RealScalar(0)) if(amed > RealScalar(0))
{ {
abig = abig/s2m; abig = abig/s2m;
amed = sqrt(amed); amed = internal::sqrt(amed);
} }
else else
return abig/s2m; return abig/s2m;
@@ -128,70 +144,20 @@ blueNorm_impl(const EigenBase<Derived>& _vec)
{ {
if (amed > RealScalar(0)) if (amed > RealScalar(0))
{ {
abig = sqrt(amed); abig = internal::sqrt(amed);
amed = sqrt(asml) / s1m; amed = internal::sqrt(asml) / s1m;
} }
else else
return sqrt(asml)/s1m; return internal::sqrt(asml)/s1m;
} }
else else
return sqrt(amed); return internal::sqrt(amed);
asml = (min)(abig, amed); asml = (min)(abig, amed);
abig = (max)(abig, amed); abig = (max)(abig, amed);
if(asml <= abig*relerr) if(asml <= abig*relerr)
return abig; return abig;
else else
return abig * sqrt(RealScalar(1) + numext::abs2(asml/abig)); return abig * internal::sqrt(RealScalar(1) + internal::abs2(asml/abig));
}
} // end namespace internal
/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
* This version use a blockwise two passes algorithm:
* 1 - find the absolute largest coefficient \c s
* 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way
*
* For architecture/scalar types supporting vectorization, this version
* is faster than blueNorm(). Otherwise the blueNorm() is much faster.
*
* \sa norm(), blueNorm(), hypotNorm()
*/
template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
MatrixBase<Derived>::stableNorm() const
{
EIGEN_USING_STD_MATH(min);
using std::sqrt;
const Index blockSize = 4096;
RealScalar scale(0);
RealScalar invScale(1);
RealScalar ssq(0); // sum of square
enum {
Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
};
Index n = size();
Index bi = internal::first_aligned(derived());
if (bi>0)
internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
for (; bi<n; bi+=blockSize)
internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
return scale * sqrt(ssq);
}
/** \returns the \em l2 norm of \c *this using the Blue's algorithm.
* A Portable Fortran Program to Find the Euclidean Norm of a Vector,
* ACM TOMS, Vol 4, Issue 1, 1978.
*
* For architecture/scalar types without vectorization, this version
* is much faster than stableNorm(). Otherwise the stableNorm() is faster.
*
* \sa norm(), stableNorm(), hypotNorm()
*/
template<typename Derived>
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
MatrixBase<Derived>::blueNorm() const
{
return internal::blueNorm_impl(*this);
} }
/** \returns the \em l2 norm of \c *this avoiding undeflow and overflow. /** \returns the \em l2 norm of \c *this avoiding undeflow and overflow.

View File

@@ -51,7 +51,6 @@ class Stride
}; };
/** Default constructor, for use when strides are fixed at compile time */ /** Default constructor, for use when strides are fixed at compile time */
EIGEN_DEVICE_FUNC
Stride() Stride()
: m_outer(OuterStrideAtCompileTime), m_inner(InnerStrideAtCompileTime) : m_outer(OuterStrideAtCompileTime), m_inner(InnerStrideAtCompileTime)
{ {
@@ -59,7 +58,6 @@ class Stride
} }
/** Constructor allowing to pass the strides at runtime */ /** Constructor allowing to pass the strides at runtime */
EIGEN_DEVICE_FUNC
Stride(Index outerStride, Index innerStride) Stride(Index outerStride, Index innerStride)
: m_outer(outerStride), m_inner(innerStride) : m_outer(outerStride), m_inner(innerStride)
{ {
@@ -67,16 +65,13 @@ class Stride
} }
/** Copy constructor */ /** Copy constructor */
EIGEN_DEVICE_FUNC
Stride(const Stride& other) Stride(const Stride& other)
: m_outer(other.outer()), m_inner(other.inner()) : m_outer(other.outer()), m_inner(other.inner())
{} {}
/** \returns the outer stride */ /** \returns the outer stride */
EIGEN_DEVICE_FUNC
inline Index outer() const { return m_outer.value(); } inline Index outer() const { return m_outer.value(); }
/** \returns the inner stride */ /** \returns the inner stride */
EIGEN_DEVICE_FUNC
inline Index inner() const { return m_inner.value(); } inline Index inner() const { return m_inner.value(); }
protected: protected:
@@ -92,8 +87,8 @@ class InnerStride : public Stride<0, Value>
typedef Stride<0, Value> Base; typedef Stride<0, Value> Base;
public: public:
typedef DenseIndex Index; typedef DenseIndex Index;
EIGEN_DEVICE_FUNC InnerStride() : Base() {} InnerStride() : Base() {}
EIGEN_DEVICE_FUNC InnerStride(Index v) : Base(0, v) {} InnerStride(Index v) : Base(0, v) {}
}; };
/** \brief Convenience specialization of Stride to specify only an outer stride /** \brief Convenience specialization of Stride to specify only an outer stride
@@ -104,8 +99,8 @@ class OuterStride : public Stride<Value, 0>
typedef Stride<Value, 0> Base; typedef Stride<Value, 0> Base;
public: public:
typedef DenseIndex Index; typedef DenseIndex Index;
EIGEN_DEVICE_FUNC OuterStride() : Base() {} OuterStride() : Base() {}
EIGEN_DEVICE_FUNC OuterStride(Index v) : Base(v,0) {} OuterStride(Index v) : Base(v,0) {}
}; };
} // end namespace Eigen } // end namespace Eigen

View File

@@ -33,16 +33,11 @@ template<typename ExpressionType> class SwapWrapper
EIGEN_DENSE_PUBLIC_INTERFACE(SwapWrapper) EIGEN_DENSE_PUBLIC_INTERFACE(SwapWrapper)
typedef typename internal::packet_traits<Scalar>::type Packet; typedef typename internal::packet_traits<Scalar>::type Packet;
EIGEN_DEVICE_FUNC
inline SwapWrapper(ExpressionType& xpr) : m_expression(xpr) {} inline SwapWrapper(ExpressionType& xpr) : m_expression(xpr) {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); } inline Index rows() const { return m_expression.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_expression.cols(); } inline Index cols() const { return m_expression.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_expression.outerStride(); } inline Index outerStride() const { return m_expression.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_expression.innerStride(); } inline Index innerStride() const { return m_expression.innerStride(); }
typedef typename internal::conditional< typedef typename internal::conditional<
@@ -51,49 +46,41 @@ template<typename ExpressionType> class SwapWrapper
const Scalar const Scalar
>::type ScalarWithConstIfNotLvalue; >::type ScalarWithConstIfNotLvalue;
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return m_expression.data(); } inline const Scalar* data() const { return m_expression.data(); }
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col)
inline Scalar& coeffRef(Index rowId, Index colId)
{ {
return m_expression.const_cast_derived().coeffRef(rowId, colId); return m_expression.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) inline Scalar& coeffRef(Index index)
{ {
return m_expression.const_cast_derived().coeffRef(index); return m_expression.const_cast_derived().coeffRef(index);
} }
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col) const
inline Scalar& coeffRef(Index rowId, Index colId) const
{ {
return m_expression.coeffRef(rowId, colId); return m_expression.coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index index) const inline Scalar& coeffRef(Index index) const
{ {
return m_expression.coeffRef(index); return m_expression.coeffRef(index);
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
void copyCoeff(Index rowId, Index colId, const DenseBase<OtherDerived>& other)
{ {
OtherDerived& _other = other.const_cast_derived(); OtherDerived& _other = other.const_cast_derived();
eigen_internal_assert(rowId >= 0 && rowId < rows() eigen_internal_assert(row >= 0 && row < rows()
&& colId >= 0 && colId < cols()); && col >= 0 && col < cols());
Scalar tmp = m_expression.coeff(rowId, colId); Scalar tmp = m_expression.coeff(row, col);
m_expression.coeffRef(rowId, colId) = _other.coeff(rowId, colId); m_expression.coeffRef(row, col) = _other.coeff(row, col);
_other.coeffRef(rowId, colId) = tmp; _other.coeffRef(row, col) = tmp;
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void copyCoeff(Index index, const DenseBase<OtherDerived>& other) void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
{ {
OtherDerived& _other = other.const_cast_derived(); OtherDerived& _other = other.const_cast_derived();
@@ -104,16 +91,16 @@ template<typename ExpressionType> class SwapWrapper
} }
template<typename OtherDerived, int StoreMode, int LoadMode> template<typename OtherDerived, int StoreMode, int LoadMode>
void copyPacket(Index rowId, Index colId, const DenseBase<OtherDerived>& other) void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
{ {
OtherDerived& _other = other.const_cast_derived(); OtherDerived& _other = other.const_cast_derived();
eigen_internal_assert(rowId >= 0 && rowId < rows() eigen_internal_assert(row >= 0 && row < rows()
&& colId >= 0 && colId < cols()); && col >= 0 && col < cols());
Packet tmp = m_expression.template packet<StoreMode>(rowId, colId); Packet tmp = m_expression.template packet<StoreMode>(row, col);
m_expression.template writePacket<StoreMode>(rowId, colId, m_expression.template writePacket<StoreMode>(row, col,
_other.template packet<LoadMode>(rowId, colId) _other.template packet<LoadMode>(row, col)
); );
_other.template writePacket<LoadMode>(rowId, colId, tmp); _other.template writePacket<LoadMode>(row, col, tmp);
} }
template<typename OtherDerived, int StoreMode, int LoadMode> template<typename OtherDerived, int StoreMode, int LoadMode>
@@ -128,7 +115,6 @@ template<typename ExpressionType> class SwapWrapper
_other.template writePacket<LoadMode>(index, tmp); _other.template writePacket<LoadMode>(index, tmp);
} }
EIGEN_DEVICE_FUNC
ExpressionType& expression() const { return m_expression; } ExpressionType& expression() const { return m_expression; }
protected: protected:

View File

@@ -62,21 +62,18 @@ template<typename MatrixType> class Transpose
typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base; typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose) EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
EIGEN_DEVICE_FUNC inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
inline Transpose(MatrixType& a_matrix) : m_matrix(a_matrix) {}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose) EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.cols(); } inline Index rows() const { return m_matrix.cols(); }
EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.rows(); }
/** \returns the nested expression */ /** \returns the nested expression */
EIGEN_DEVICE_FUNC
const typename internal::remove_all<typename MatrixType::Nested>::type& const typename internal::remove_all<typename MatrixType::Nested>::type&
nestedExpression() const { return m_matrix; } nestedExpression() const { return m_matrix; }
/** \returns the nested expression */ /** \returns the nested expression */
EIGEN_DEVICE_FUNC
typename internal::remove_all<typename MatrixType::Nested>::type& typename internal::remove_all<typename MatrixType::Nested>::type&
nestedExpression() { return m_matrix.const_cast_derived(); } nestedExpression() { return m_matrix.const_cast_derived(); }
@@ -109,8 +106,8 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>) EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl) EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); } inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); } inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
typedef typename internal::conditional< typedef typename internal::conditional<
internal::is_lvalue<MatrixType>::value, internal::is_lvalue<MatrixType>::value,
@@ -121,54 +118,48 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); } inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
inline const Scalar* data() const { return derived().nestedExpression().data(); } inline const Scalar* data() const { return derived().nestedExpression().data(); }
EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
inline ScalarWithConstIfNotLvalue& coeffRef(Index rowId, Index colId)
{ {
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
return derived().nestedExpression().const_cast_derived().coeffRef(colId, rowId); return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
} }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue& coeffRef(Index index) inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
{ {
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
return derived().nestedExpression().const_cast_derived().coeffRef(index); return derived().nestedExpression().const_cast_derived().coeffRef(index);
} }
EIGEN_DEVICE_FUNC inline const Scalar& coeffRef(Index row, Index col) const
inline const Scalar& coeffRef(Index rowId, Index colId) const
{ {
return derived().nestedExpression().coeffRef(colId, rowId); return derived().nestedExpression().coeffRef(col, row);
} }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const inline const Scalar& coeffRef(Index index) const
{ {
return derived().nestedExpression().coeffRef(index); return derived().nestedExpression().coeffRef(index);
} }
EIGEN_DEVICE_FUNC inline CoeffReturnType coeff(Index row, Index col) const
inline CoeffReturnType coeff(Index rowId, Index colId) const
{ {
return derived().nestedExpression().coeff(colId, rowId); return derived().nestedExpression().coeff(col, row);
} }
EIGEN_DEVICE_FUNC
inline CoeffReturnType coeff(Index index) const inline CoeffReturnType coeff(Index index) const
{ {
return derived().nestedExpression().coeff(index); return derived().nestedExpression().coeff(index);
} }
template<int LoadMode> template<int LoadMode>
inline const PacketScalar packet(Index rowId, Index colId) const inline const PacketScalar packet(Index row, Index col) const
{ {
return derived().nestedExpression().template packet<LoadMode>(colId, rowId); return derived().nestedExpression().template packet<LoadMode>(col, row);
} }
template<int LoadMode> template<int LoadMode>
inline void writePacket(Index rowId, Index colId, const PacketScalar& x) inline void writePacket(Index row, Index col, const PacketScalar& x)
{ {
derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(colId, rowId, x); derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
} }
template<int LoadMode> template<int LoadMode>
@@ -216,7 +207,7 @@ DenseBase<Derived>::transpose()
* *
* \sa transposeInPlace(), adjoint() */ * \sa transposeInPlace(), adjoint() */
template<typename Derived> template<typename Derived>
inline typename DenseBase<Derived>::ConstTransposeReturnType inline const typename DenseBase<Derived>::ConstTransposeReturnType
DenseBase<Derived>::transpose() const DenseBase<Derived>::transpose() const
{ {
return ConstTransposeReturnType(derived()); return ConstTransposeReturnType(derived());
@@ -288,20 +279,17 @@ struct inplace_transpose_selector<MatrixType,false> { // non square matrix
* m = m.transpose().eval(); * m = m.transpose().eval();
* \endcode * \endcode
* and is faster and also safer because in the latter line of code, forgetting the eval() results * and is faster and also safer because in the latter line of code, forgetting the eval() results
* in a bug caused by \ref TopicAliasing "aliasing". * in a bug caused by aliasing.
* *
* 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>
inline void DenseBase<Derived>::transposeInPlace() inline void DenseBase<Derived>::transposeInPlace()
{ {
eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic))
&& "transposeInPlace() called on a non-square non-resizable matrix");
internal::inplace_transpose_selector<Derived>::run(derived()); internal::inplace_transpose_selector<Derived>::run(derived());
} }
@@ -325,7 +313,6 @@ 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>
@@ -399,7 +386,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 transposition, use transposeInPlace() " && "aliasing detected during tranposition, use transposeInPlace() "
"or evaluate the rhs into a temporary using .eval()"); "or evaluate the rhs into a temporary using .eval()");
} }

View File

@@ -53,8 +53,7 @@ class TranspositionsBase
public: public:
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar StorageIndexType; typedef typename IndicesType::Scalar Index;
typedef typename IndicesType::Index Index;
Derived& derived() { return *static_cast<Derived*>(this); } Derived& derived() { return *static_cast<Derived*>(this); }
const Derived& derived() const { return *static_cast<const Derived*>(this); } const Derived& derived() const { return *static_cast<const Derived*>(this); }
@@ -82,17 +81,17 @@ class TranspositionsBase
inline Index size() const { return indices().size(); } inline Index size() const { return indices().size(); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline const StorageIndexType& coeff(Index i) const { return indices().coeff(i); } inline const Index& coeff(Index i) const { return indices().coeff(i); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline StorageIndexType& coeffRef(Index i) { return indices().coeffRef(i); } inline Index& coeffRef(Index i) { return indices().coeffRef(i); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline const StorageIndexType& operator()(Index i) const { return indices()(i); } inline const Index& operator()(Index i) const { return indices()(i); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline StorageIndexType& operator()(Index i) { return indices()(i); } inline Index& operator()(Index i) { return indices()(i); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline const StorageIndexType& operator[](Index i) const { return indices()(i); } inline const Index& operator[](Index i) const { return indices()(i); }
/** Direct access to the underlying index vector */ /** Direct access to the underlying index vector */
inline StorageIndexType& operator[](Index i) { return indices()(i); } inline Index& operator[](Index i) { return indices()(i); }
/** const version of indices(). */ /** const version of indices(). */
const IndicesType& indices() const { return derived().indices(); } const IndicesType& indices() const { return derived().indices(); }
@@ -100,15 +99,15 @@ class TranspositionsBase
IndicesType& indices() { return derived().indices(); } IndicesType& indices() { return derived().indices(); }
/** Resizes to given size. */ /** Resizes to given size. */
inline void resize(Index newSize) inline void resize(int size)
{ {
indices().resize(newSize); indices().resize(size);
} }
/** Sets \c *this to represents an identity transformation */ /** Sets \c *this to represents an identity transformation */
void setIdentity() void setIdentity()
{ {
for(StorageIndexType i = 0; i < indices().size(); ++i) for(int i = 0; i < indices().size(); ++i)
coeffRef(i) = i; coeffRef(i) = i;
} }
@@ -145,26 +144,23 @@ class TranspositionsBase
}; };
namespace internal { namespace internal {
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
struct traits<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,_StorageIndexType> > struct traits<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
{ {
typedef Matrix<_StorageIndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType; typedef IndexType Index;
typedef typename IndicesType::Index Index; typedef Matrix<Index, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
typedef _StorageIndexType StorageIndexType;
}; };
} }
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,_StorageIndexType> > class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
{ {
typedef internal::traits<Transpositions> Traits; typedef internal::traits<Transpositions> Traits;
public: public:
typedef TranspositionsBase<Transpositions> Base; typedef TranspositionsBase<Transpositions> Base;
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar StorageIndexType; typedef typename IndicesType::Scalar Index;
typedef typename IndicesType::Index Index;
inline Transpositions() {} inline Transpositions() {}
@@ -181,7 +177,7 @@ class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTim
/** Generic constructor from expression of the transposition indices. */ /** Generic constructor from expression of the transposition indices. */
template<typename Other> template<typename Other>
explicit inline Transpositions(const MatrixBase<Other>& a_indices) : m_indices(a_indices) explicit inline Transpositions(const MatrixBase<Other>& indices) : m_indices(indices)
{} {}
/** Copies the \a other transpositions into \c *this */ /** Copies the \a other transpositions into \c *this */
@@ -219,33 +215,31 @@ class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTim
namespace internal { namespace internal {
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType, int _PacketAccess> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
struct traits<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,_StorageIndexType>,_PacketAccess> > struct traits<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,_PacketAccess> >
{ {
typedef Map<const Matrix<_StorageIndexType,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1>, _PacketAccess> IndicesType; typedef IndexType Index;
typedef typename IndicesType::Index Index; typedef Map<const Matrix<Index,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1>, _PacketAccess> IndicesType;
typedef _StorageIndexType StorageIndexType;
}; };
} }
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename _StorageIndexType, int PacketAccess> template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int PacketAccess>
class Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,_StorageIndexType>,PacketAccess> class Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess>
: public TranspositionsBase<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,_StorageIndexType>,PacketAccess> > : public TranspositionsBase<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess> >
{ {
typedef internal::traits<Map> Traits; typedef internal::traits<Map> Traits;
public: public:
typedef TranspositionsBase<Map> Base; typedef TranspositionsBase<Map> Base;
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar StorageIndexType; typedef typename IndicesType::Scalar Index;
typedef typename IndicesType::Index Index;
inline Map(const StorageIndexType* indicesPtr) inline Map(const Index* indices)
: m_indices(indicesPtr) : m_indices(indices)
{} {}
inline Map(const StorageIndexType* indicesPtr, Index size) inline Map(const Index* indices, Index size)
: m_indices(indicesPtr,size) : m_indices(indices,size)
{} {}
/** Copies the \a other transpositions into \c *this */ /** Copies the \a other transpositions into \c *this */
@@ -281,8 +275,7 @@ namespace internal {
template<typename _IndicesType> template<typename _IndicesType>
struct traits<TranspositionsWrapper<_IndicesType> > struct traits<TranspositionsWrapper<_IndicesType> >
{ {
typedef typename _IndicesType::Scalar StorageIndexType; typedef typename _IndicesType::Scalar Index;
typedef typename _IndicesType::Index Index;
typedef _IndicesType IndicesType; typedef _IndicesType IndicesType;
}; };
} }
@@ -296,11 +289,10 @@ class TranspositionsWrapper
typedef TranspositionsBase<TranspositionsWrapper> Base; typedef TranspositionsBase<TranspositionsWrapper> Base;
typedef typename Traits::IndicesType IndicesType; typedef typename Traits::IndicesType IndicesType;
typedef typename IndicesType::Scalar StorageIndexType; typedef typename IndicesType::Scalar Index;
typedef typename IndicesType::Index Index;
inline TranspositionsWrapper(IndicesType& a_indices) inline TranspositionsWrapper(IndicesType& indices)
: m_indices(a_indices) : m_indices(indices)
{} {}
/** Copies the \a other transpositions into \c *this */ /** Copies the \a other transpositions into \c *this */
@@ -371,25 +363,24 @@ struct transposition_matrix_product_retval
{ {
typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned; typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
typedef typename TranspositionType::Index Index; typedef typename TranspositionType::Index Index;
typedef typename TranspositionType::StorageIndexType StorageIndexType;
transposition_matrix_product_retval(const TranspositionType& tr, const MatrixType& matrix) transposition_matrix_product_retval(const TranspositionType& tr, const MatrixType& matrix)
: m_transpositions(tr), m_matrix(matrix) : m_transpositions(tr), m_matrix(matrix)
{} {}
inline Index rows() const { return m_matrix.rows(); } inline int rows() const { return m_matrix.rows(); }
inline Index cols() const { return m_matrix.cols(); } inline int 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 Index size = m_transpositions.size(); const int size = m_transpositions.size();
StorageIndexType j = 0; Index j = 0;
if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix))) if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
dst = m_matrix; dst = m_matrix;
for(Index k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k) for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
if(Index(j=m_transpositions.coeff(k))!=k) if((j=m_transpositions.coeff(k))!=k)
{ {
if(Side==OnTheLeft) if(Side==OnTheLeft)
dst.row(k).swap(dst.row(j)); dst.row(k).swap(dst.row(j));

View File

@@ -44,39 +44,29 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
typedef typename internal::traits<Derived>::DenseMatrixType DenseMatrixType; typedef typename internal::traits<Derived>::DenseMatrixType DenseMatrixType;
typedef DenseMatrixType DenseType; typedef DenseMatrixType DenseType;
EIGEN_DEVICE_FUNC
inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); } inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); }
EIGEN_DEVICE_FUNC
inline Index rows() const { return derived().rows(); } inline Index rows() const { return derived().rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return derived().cols(); } inline Index cols() const { return derived().cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return derived().outerStride(); } inline Index outerStride() const { return derived().outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return derived().innerStride(); } inline Index innerStride() const { return derived().innerStride(); }
EIGEN_DEVICE_FUNC
inline Scalar coeff(Index row, Index col) const { return derived().coeff(row,col); } inline Scalar coeff(Index row, Index col) const { return derived().coeff(row,col); }
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row,col); } inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row,col); }
/** \see MatrixBase::copyCoeff(row,col) /** \see MatrixBase::copyCoeff(row,col)
*/ */
template<typename Other> template<typename Other>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other) EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other)
{ {
derived().coeffRef(row, col) = other.coeff(row, col); derived().coeffRef(row, col) = other.coeff(row, col);
} }
EIGEN_DEVICE_FUNC
inline Scalar operator()(Index row, Index col) const inline Scalar operator()(Index row, Index col) const
{ {
check_coordinates(row, col); check_coordinates(row, col);
return coeff(row,col); return coeff(row,col);
} }
EIGEN_DEVICE_FUNC
inline Scalar& operator()(Index row, Index col) inline Scalar& operator()(Index row, Index col)
{ {
check_coordinates(row, col); check_coordinates(row, col);
@@ -84,20 +74,15 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
} }
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
EIGEN_DEVICE_FUNC
inline const Derived& derived() const { return *static_cast<const Derived*>(this); } inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
EIGEN_DEVICE_FUNC
inline Derived& derived() { return *static_cast<Derived*>(this); } inline Derived& derived() { return *static_cast<Derived*>(this); }
#endif // not EIGEN_PARSED_BY_DOXYGEN #endif // not EIGEN_PARSED_BY_DOXYGEN
template<typename DenseDerived> template<typename DenseDerived>
EIGEN_DEVICE_FUNC
void evalTo(MatrixBase<DenseDerived> &other) const; void evalTo(MatrixBase<DenseDerived> &other) const;
template<typename DenseDerived> template<typename DenseDerived>
EIGEN_DEVICE_FUNC
void evalToLazy(MatrixBase<DenseDerived> &other) const; void evalToLazy(MatrixBase<DenseDerived> &other) const;
EIGEN_DEVICE_FUNC
DenseMatrixType toDenseMatrix() const DenseMatrixType toDenseMatrix() const
{ {
DenseMatrixType res(rows(), cols()); DenseMatrixType res(rows(), cols());
@@ -204,52 +189,36 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
| (Mode & (ZeroDiag)) | (Mode & (ZeroDiag))
}; };
EIGEN_DEVICE_FUNC
inline TriangularView(const MatrixType& matrix) : m_matrix(matrix) inline TriangularView(const MatrixType& matrix) : m_matrix(matrix)
{} {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_matrix.rows(); } inline Index rows() const { return m_matrix.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_matrix.cols(); } inline Index cols() const { return m_matrix.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_matrix.outerStride(); } inline Index outerStride() const { return m_matrix.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_matrix.innerStride(); } inline Index innerStride() const { return m_matrix.innerStride(); }
/** \sa MatrixBase::operator+=() */ /** \sa MatrixBase::operator+=() */
template<typename Other> template<typename Other> TriangularView& operator+=(const DenseBase<Other>& other) { return *this = m_matrix + other.derived(); }
EIGEN_DEVICE_FUNC
TriangularView& operator+=(const DenseBase<Other>& other) { return *this = m_matrix + other.derived(); }
/** \sa MatrixBase::operator-=() */ /** \sa MatrixBase::operator-=() */
template<typename Other> template<typename Other> TriangularView& operator-=(const DenseBase<Other>& other) { return *this = m_matrix - other.derived(); }
EIGEN_DEVICE_FUNC
TriangularView& operator-=(const DenseBase<Other>& other) { return *this = m_matrix - other.derived(); }
/** \sa MatrixBase::operator*=() */ /** \sa MatrixBase::operator*=() */
EIGEN_DEVICE_FUNC
TriangularView& operator*=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix * other; } TriangularView& operator*=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix * other; }
/** \sa MatrixBase::operator/=() */ /** \sa MatrixBase::operator/=() */
EIGEN_DEVICE_FUNC
TriangularView& operator/=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix / other; } TriangularView& operator/=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix / other; }
/** \sa MatrixBase::fill() */ /** \sa MatrixBase::fill() */
EIGEN_DEVICE_FUNC
void fill(const Scalar& value) { setConstant(value); } void fill(const Scalar& value) { setConstant(value); }
/** \sa MatrixBase::setConstant() */ /** \sa MatrixBase::setConstant() */
EIGEN_DEVICE_FUNC
TriangularView& setConstant(const Scalar& value) TriangularView& setConstant(const Scalar& value)
{ return *this = MatrixType::Constant(rows(), cols(), value); } { return *this = MatrixType::Constant(rows(), cols(), value); }
/** \sa MatrixBase::setZero() */ /** \sa MatrixBase::setZero() */
EIGEN_DEVICE_FUNC
TriangularView& setZero() { return setConstant(Scalar(0)); } TriangularView& setZero() { return setConstant(Scalar(0)); }
/** \sa MatrixBase::setOnes() */ /** \sa MatrixBase::setOnes() */
EIGEN_DEVICE_FUNC
TriangularView& setOnes() { return setConstant(Scalar(1)); } TriangularView& setOnes() { return setConstant(Scalar(1)); }
/** \sa MatrixBase::coeff() /** \sa MatrixBase::coeff()
* \warning the coordinates must fit into the referenced triangular part * \warning the coordinates must fit into the referenced triangular part
*/ */
EIGEN_DEVICE_FUNC
inline Scalar coeff(Index row, Index col) const inline Scalar coeff(Index row, Index col) const
{ {
Base::check_coordinates_internal(row, col); Base::check_coordinates_internal(row, col);
@@ -259,62 +228,49 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
/** \sa MatrixBase::coeffRef() /** \sa MatrixBase::coeffRef()
* \warning the coordinates must fit into the referenced triangular part * \warning the coordinates must fit into the referenced triangular part
*/ */
EIGEN_DEVICE_FUNC
inline Scalar& coeffRef(Index row, Index col) inline Scalar& coeffRef(Index row, Index col)
{ {
Base::check_coordinates_internal(row, col); Base::check_coordinates_internal(row, col);
return m_matrix.const_cast_derived().coeffRef(row, col); return m_matrix.const_cast_derived().coeffRef(row, col);
} }
EIGEN_DEVICE_FUNC
const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; }
EIGEN_DEVICE_FUNC
MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); } MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); }
/** Assigns a triangular matrix to a triangular part of a dense matrix */ /** Assigns a triangular matrix to a triangular part of a dense matrix */
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
TriangularView& operator=(const TriangularBase<OtherDerived>& other); TriangularView& operator=(const TriangularBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
TriangularView& operator=(const MatrixBase<OtherDerived>& other); TriangularView& operator=(const MatrixBase<OtherDerived>& other);
EIGEN_DEVICE_FUNC
TriangularView& operator=(const TriangularView& other) TriangularView& operator=(const TriangularView& other)
{ return *this = other.nestedExpression(); } { return *this = other.nestedExpression(); }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void lazyAssign(const TriangularBase<OtherDerived>& other); void lazyAssign(const TriangularBase<OtherDerived>& other);
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void lazyAssign(const MatrixBase<OtherDerived>& other); void lazyAssign(const MatrixBase<OtherDerived>& other);
/** \sa MatrixBase::conjugate() */ /** \sa MatrixBase::conjugate() */
EIGEN_DEVICE_FUNC
inline TriangularView<MatrixConjugateReturnType,Mode> conjugate() inline TriangularView<MatrixConjugateReturnType,Mode> conjugate()
{ return m_matrix.conjugate(); } { return m_matrix.conjugate(); }
/** \sa MatrixBase::conjugate() const */ /** \sa MatrixBase::conjugate() const */
EIGEN_DEVICE_FUNC
inline const TriangularView<MatrixConjugateReturnType,Mode> conjugate() const inline const TriangularView<MatrixConjugateReturnType,Mode> conjugate() const
{ return m_matrix.conjugate(); } { return m_matrix.conjugate(); }
/** \sa MatrixBase::adjoint() const */ /** \sa MatrixBase::adjoint() const */
EIGEN_DEVICE_FUNC
inline const TriangularView<const typename MatrixType::AdjointReturnType,TransposeMode> adjoint() const inline const TriangularView<const typename MatrixType::AdjointReturnType,TransposeMode> adjoint() const
{ return m_matrix.adjoint(); } { return m_matrix.adjoint(); }
/** \sa MatrixBase::transpose() */ /** \sa MatrixBase::transpose() */
EIGEN_DEVICE_FUNC
inline TriangularView<Transpose<MatrixType>,TransposeMode> transpose() inline TriangularView<Transpose<MatrixType>,TransposeMode> transpose()
{ {
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
return m_matrix.const_cast_derived().transpose(); return m_matrix.const_cast_derived().transpose();
} }
/** \sa MatrixBase::transpose() const */ /** \sa MatrixBase::transpose() const */
EIGEN_DEVICE_FUNC
inline const TriangularView<Transpose<MatrixType>,TransposeMode> transpose() const inline const TriangularView<Transpose<MatrixType>,TransposeMode> transpose() const
{ {
return m_matrix.transpose(); return m_matrix.transpose();
@@ -322,53 +278,74 @@ 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>
EIGEN_DEVICE_FUNC 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::ColsAtCompileTime==1> <Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
(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
EIGEN_DEVICE_FUNC 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::RowsAtCompileTime==1, MatrixType, false> <Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
(lhs.derived(),rhs.m_matrix); (lhs.derived(),rhs.m_matrix);
} }
#ifdef EIGEN2_SUPPORT
template<typename OtherDerived>
struct eigen2_product_return_type
{
typedef typename TriangularView<MatrixType,Mode>::DenseMatrixType DenseMatrixType;
typedef typename OtherDerived::PlainObject::DenseType OtherPlainObject;
typedef typename ProductReturnType<DenseMatrixType, OtherPlainObject>::Type ProdRetType;
typedef typename ProdRetType::PlainObject type;
};
template<typename OtherDerived>
const typename eigen2_product_return_type<OtherDerived>::type
operator*(const EigenBase<OtherDerived>& rhs) const
{
typename OtherDerived::PlainObject::DenseType rhsPlainObject;
rhs.evalTo(rhsPlainObject);
return this->toDenseMatrix() * rhsPlainObject;
}
template<typename OtherMatrixType>
bool isApprox(const TriangularView<OtherMatrixType, Mode>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
{
return this->toDenseMatrix().isApprox(other.toDenseMatrix(), precision);
}
template<typename OtherDerived>
bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
{
return this->toDenseMatrix().isApprox(other, precision);
}
#endif // EIGEN2_SUPPORT
template<int Side, typename Other> template<int Side, typename Other>
EIGEN_DEVICE_FUNC
inline const internal::triangular_solve_retval<Side,TriangularView, Other> inline const internal::triangular_solve_retval<Side,TriangularView, Other>
solve(const MatrixBase<Other>& other) const; solve(const MatrixBase<Other>& other) const;
template<int Side, typename OtherDerived> template<int Side, typename OtherDerived>
EIGEN_DEVICE_FUNC
void solveInPlace(const MatrixBase<OtherDerived>& other) const; void solveInPlace(const MatrixBase<OtherDerived>& other) const;
template<typename Other> template<typename Other>
EIGEN_DEVICE_FUNC
inline const internal::triangular_solve_retval<OnTheLeft,TriangularView, Other> inline const internal::triangular_solve_retval<OnTheLeft,TriangularView, Other>
solve(const MatrixBase<Other>& other) const solve(const MatrixBase<Other>& other) const
{ return solve<OnTheLeft>(other); } { return solve<OnTheLeft>(other); }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void solveInPlace(const MatrixBase<OtherDerived>& other) const void solveInPlace(const MatrixBase<OtherDerived>& other) const
{ return solveInPlace<OnTheLeft>(other); } { return solveInPlace<OnTheLeft>(other); }
EIGEN_DEVICE_FUNC
const SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() const const SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() const
{ {
EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR); EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR);
return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix); return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix);
} }
EIGEN_DEVICE_FUNC
SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView()
{ {
EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR); EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR);
@@ -376,21 +353,18 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void swap(TriangularBase<OtherDerived> const & other) void swap(TriangularBase<OtherDerived> const & other)
{ {
TriangularView<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived()); TriangularView<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
} }
template<typename OtherDerived> template<typename OtherDerived>
EIGEN_DEVICE_FUNC
void swap(MatrixBase<OtherDerived> const & other) void swap(MatrixBase<OtherDerived> const & other)
{ {
SwapWrapper<MatrixType> swaper(const_cast<MatrixType&>(m_matrix)); SwapWrapper<MatrixType> swaper(const_cast<MatrixType&>(m_matrix));
TriangularView<SwapWrapper<MatrixType>,Mode>(swaper).lazyAssign(other.derived()); TriangularView<SwapWrapper<MatrixType>,Mode>(swaper).lazyAssign(other.derived());
} }
EIGEN_DEVICE_FUNC
Scalar determinant() const Scalar determinant() const
{ {
if (Mode & UnitDiag) if (Mode & UnitDiag)
@@ -403,7 +377,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
// TODO simplify the following: // TODO simplify the following:
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other) EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
{ {
setZero(); setZero();
@@ -411,14 +384,12 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
} }
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
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,1);
} }
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
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,-1);
@@ -426,7 +397,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
template<typename ProductDerived> template<typename ProductDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other) EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other)
{ {
setZero(); setZero();
@@ -434,14 +404,12 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
} }
template<typename ProductDerived> template<typename ProductDerived>
EIGEN_DEVICE_FUNC
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,other.alpha());
} }
template<typename ProductDerived> template<typename ProductDerived>
EIGEN_DEVICE_FUNC
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,-other.alpha());
@@ -450,7 +418,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
protected: protected:
template<typename ProductDerived, typename Lhs, typename Rhs> template<typename ProductDerived, typename Lhs, typename Rhs>
EIGEN_DEVICE_FUNC
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);
MatrixTypeNested m_matrix; MatrixTypeNested m_matrix;
@@ -472,7 +439,6 @@ struct triangular_assignment_selector
typedef typename Derived1::Scalar Scalar; typedef typename Derived1::Scalar Scalar;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
triangular_assignment_selector<Derived1, Derived2, Mode, UnrollCount-1, ClearOpposite>::run(dst, src); triangular_assignment_selector<Derived1, Derived2, Mode, UnrollCount-1, ClearOpposite>::run(dst, src);
@@ -501,7 +467,6 @@ struct triangular_assignment_selector
template<typename Derived1, typename Derived2, unsigned int Mode, bool ClearOpposite> template<typename Derived1, typename Derived2, unsigned int Mode, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, Mode, 0, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, Mode, 0, ClearOpposite>
{ {
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &, const Derived2 &) {} static inline void run(Derived1 &, const Derived2 &) {}
}; };
@@ -510,7 +475,6 @@ struct triangular_assignment_selector<Derived1, Derived2, Upper, Dynamic, ClearO
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
typedef typename Derived1::Scalar Scalar; typedef typename Derived1::Scalar Scalar;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -529,7 +493,6 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, Lower, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, Lower, Dynamic, ClearOpposite>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -549,7 +512,6 @@ struct triangular_assignment_selector<Derived1, Derived2, StrictlyUpper, Dynamic
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
typedef typename Derived1::Scalar Scalar; typedef typename Derived1::Scalar Scalar;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -568,7 +530,6 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, StrictlyLower, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, StrictlyLower, Dynamic, ClearOpposite>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -587,7 +548,6 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, UnitUpper, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, UnitUpper, Dynamic, ClearOpposite>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -608,7 +568,6 @@ template<typename Derived1, typename Derived2, bool ClearOpposite>
struct triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic, ClearOpposite> struct triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic, ClearOpposite>
{ {
typedef typename Derived1::Index Index; typedef typename Derived1::Index Index;
EIGEN_DEVICE_FUNC
static inline void run(Derived1 &dst, const Derived2 &src) static inline void run(Derived1 &dst, const Derived2 &src)
{ {
for(Index j = 0; j < dst.cols(); ++j) for(Index j = 0; j < dst.cols(); ++j)
@@ -751,6 +710,41 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
* Implementation of MatrixBase methods * Implementation of MatrixBase methods
***************************************************************************/ ***************************************************************************/
#ifdef EIGEN2_SUPPORT
// implementation of part<>(), including the SelfAdjoint case.
namespace internal {
template<typename MatrixType, unsigned int Mode>
struct eigen2_part_return_type
{
typedef TriangularView<MatrixType, Mode> type;
};
template<typename MatrixType>
struct eigen2_part_return_type<MatrixType, SelfAdjoint>
{
typedef SelfAdjointView<MatrixType, Upper> type;
};
}
/** \deprecated use MatrixBase::triangularView() */
template<typename Derived>
template<unsigned int Mode>
const typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part() const
{
return derived();
}
/** \deprecated use MatrixBase::triangularView() */
template<typename Derived>
template<unsigned int Mode>
typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part()
{
return derived();
}
#endif
/** /**
* \returns an expression of a triangular view extracted from the current matrix * \returns an expression of a triangular view extracted from the current matrix
* *
@@ -785,23 +779,22 @@ MatrixBase<Derived>::triangularView() const
* \sa isLowerTriangular() * \sa isLowerTriangular()
*/ */
template<typename Derived> template<typename Derived>
bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
{ {
using std::abs;
RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1); RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
{ {
Index maxi = (std::min)(j, rows()-1); Index maxi = (std::min)(j, rows()-1);
for(Index i = 0; i <= maxi; ++i) for(Index i = 0; i <= maxi; ++i)
{ {
RealScalar absValue = abs(coeff(i,j)); RealScalar absValue = internal::abs(coeff(i,j));
if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue; if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
} }
} }
RealScalar threshold = maxAbsOnUpperPart * prec; RealScalar threshold = maxAbsOnUpperPart * prec;
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
for(Index i = j+1; i < rows(); ++i) for(Index i = j+1; i < rows(); ++i)
if(abs(coeff(i, j)) > threshold) return false; if(internal::abs(coeff(i, j)) > threshold) return false;
return true; return true;
} }
@@ -811,14 +804,13 @@ bool MatrixBase<Derived>::isUpperTriangular(const RealScalar& prec) const
* \sa isUpperTriangular() * \sa isUpperTriangular()
*/ */
template<typename Derived> template<typename Derived>
bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
{ {
using std::abs;
RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1); RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
for(Index j = 0; j < cols(); ++j) for(Index j = 0; j < cols(); ++j)
for(Index i = j; i < rows(); ++i) for(Index i = j; i < rows(); ++i)
{ {
RealScalar absValue = abs(coeff(i,j)); RealScalar absValue = internal::abs(coeff(i,j));
if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue; if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
} }
RealScalar threshold = maxAbsOnLowerPart * prec; RealScalar threshold = maxAbsOnLowerPart * prec;
@@ -826,7 +818,7 @@ bool MatrixBase<Derived>::isLowerTriangular(const RealScalar& prec) const
{ {
Index maxi = (std::min)(j, rows()-1); Index maxi = (std::min)(j, rows()-1);
for(Index i = 0; i < maxi; ++i) for(Index i = 0; i < maxi; ++i)
if(abs(coeff(i, j)) > threshold) return false; if(internal::abs(coeff(i, j)) > threshold) return false;
} }
return true; return true;
} }

View File

@@ -72,7 +72,6 @@ template<typename VectorType, int Size> class VectorBlock
/** Dynamic-size constructor /** Dynamic-size constructor
*/ */
EIGEN_DEVICE_FUNC
inline VectorBlock(VectorType& vector, Index start, Index size) inline VectorBlock(VectorType& vector, Index start, Index size)
: Base(vector, : Base(vector,
IsColVector ? start : 0, IsColVector ? 0 : start, IsColVector ? start : 0, IsColVector ? 0 : start,
@@ -83,7 +82,6 @@ template<typename VectorType, int Size> class VectorBlock
/** Fixed-size constructor /** Fixed-size constructor
*/ */
EIGEN_DEVICE_FUNC
inline VectorBlock(VectorType& vector, Index start) inline VectorBlock(VectorType& vector, Index start)
: Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start) : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start)
{ {
@@ -92,6 +90,195 @@ template<typename VectorType, int Size> class VectorBlock
}; };
/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
*
* \only_for_vectors
*
* \param start the first coefficient in the segment
* \param size the number of coefficients in the segment
*
* Example: \include MatrixBase_segment_int_int.cpp
* Output: \verbinclude MatrixBase_segment_int_int.out
*
* \note Even though the returned expression has dynamic size, in the case
* when it is applied to a fixed-size vector, it inherits a fixed maximal size,
* which means that evaluating it does not cause a dynamic memory allocation.
*
* \sa class Block, segment(Index)
*/
template<typename Derived>
inline typename DenseBase<Derived>::SegmentReturnType
DenseBase<Derived>::segment(Index start, Index size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return SegmentReturnType(derived(), start, size);
}
/** This is the const version of segment(Index,Index).*/
template<typename Derived>
inline typename DenseBase<Derived>::ConstSegmentReturnType
DenseBase<Derived>::segment(Index start, Index size) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return ConstSegmentReturnType(derived(), start, size);
}
/** \returns a dynamic-size expression of the first coefficients of *this.
*
* \only_for_vectors
*
* \param size the number of coefficients in the block
*
* Example: \include MatrixBase_start_int.cpp
* Output: \verbinclude MatrixBase_start_int.out
*
* \note Even though the returned expression has dynamic size, in the case
* when it is applied to a fixed-size vector, it inherits a fixed maximal size,
* which means that evaluating it does not cause a dynamic memory allocation.
*
* \sa class Block, block(Index,Index)
*/
template<typename Derived>
inline typename DenseBase<Derived>::SegmentReturnType
DenseBase<Derived>::head(Index size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return SegmentReturnType(derived(), 0, size);
}
/** This is the const version of head(Index).*/
template<typename Derived>
inline typename DenseBase<Derived>::ConstSegmentReturnType
DenseBase<Derived>::head(Index size) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return ConstSegmentReturnType(derived(), 0, size);
}
/** \returns a dynamic-size expression of the last coefficients of *this.
*
* \only_for_vectors
*
* \param size the number of coefficients in the block
*
* Example: \include MatrixBase_end_int.cpp
* Output: \verbinclude MatrixBase_end_int.out
*
* \note Even though the returned expression has dynamic size, in the case
* when it is applied to a fixed-size vector, it inherits a fixed maximal size,
* which means that evaluating it does not cause a dynamic memory allocation.
*
* \sa class Block, block(Index,Index)
*/
template<typename Derived>
inline typename DenseBase<Derived>::SegmentReturnType
DenseBase<Derived>::tail(Index size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return SegmentReturnType(derived(), this->size() - size, size);
}
/** This is the const version of tail(Index).*/
template<typename Derived>
inline typename DenseBase<Derived>::ConstSegmentReturnType
DenseBase<Derived>::tail(Index size) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return ConstSegmentReturnType(derived(), this->size() - size, size);
}
/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
*
* \only_for_vectors
*
* The template parameter \a Size is the number of coefficients in the block
*
* \param start the index of the first element of the sub-vector
*
* Example: \include MatrixBase_template_int_segment.cpp
* Output: \verbinclude MatrixBase_template_int_segment.out
*
* \sa class Block
*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
DenseBase<Derived>::segment(Index start)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename FixedSegmentReturnType<Size>::Type(derived(), start);
}
/** This is the const version of segment<int>(Index).*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
DenseBase<Derived>::segment(Index start) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename ConstFixedSegmentReturnType<Size>::Type(derived(), start);
}
/** \returns a fixed-size expression of the first coefficients of *this.
*
* \only_for_vectors
*
* The template parameter \a Size is the number of coefficients in the block
*
* Example: \include MatrixBase_template_int_start.cpp
* Output: \verbinclude MatrixBase_template_int_start.out
*
* \sa class Block
*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
DenseBase<Derived>::head()
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename FixedSegmentReturnType<Size>::Type(derived(), 0);
}
/** This is the const version of head<int>().*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
DenseBase<Derived>::head() const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename ConstFixedSegmentReturnType<Size>::Type(derived(), 0);
}
/** \returns a fixed-size expression of the last coefficients of *this.
*
* \only_for_vectors
*
* The template parameter \a Size is the number of coefficients in the block
*
* Example: \include MatrixBase_template_int_end.cpp
* Output: \verbinclude MatrixBase_template_int_end.out
*
* \sa class Block
*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
DenseBase<Derived>::tail()
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename FixedSegmentReturnType<Size>::Type(derived(), size() - Size);
}
/** This is the const version of tail<int>.*/
template<typename Derived>
template<int Size>
inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
DenseBase<Derived>::tail() const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return typename ConstFixedSegmentReturnType<Size>::Type(derived(), size() - Size);
}
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_VECTORBLOCK_H #endif // EIGEN_VECTORBLOCK_H

View File

@@ -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 ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime TraversalSize = Direction==Vertical ? RowsAtCompileTime : 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,8 +58,7 @@ 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==Dynamic ? Dynamic CoeffReadCost = TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
: TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
}; };
}; };
} }
@@ -235,28 +234,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
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:
inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {} inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {}
@@ -279,8 +256,6 @@ 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
* *
@@ -291,8 +266,6 @@ 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
* *
@@ -302,7 +275,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the squared norm /** \returns a row (or column) vector expression of the squared norm
* of each column (or row) of the referenced expression. * of each column (or row) of the referenced expression.
* This is a vector with real entries, even if the original matrix has complex entries.
* *
* Example: \include PartialRedux_squaredNorm.cpp * Example: \include PartialRedux_squaredNorm.cpp
* Output: \verbinclude PartialRedux_squaredNorm.out * Output: \verbinclude PartialRedux_squaredNorm.out
@@ -313,7 +285,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the norm /** \returns a row (or column) vector expression of the norm
* of each column (or row) of the referenced expression. * of each column (or row) of the referenced expression.
* This is a vector with real entries, even if the original matrix has complex entries.
* *
* Example: \include PartialRedux_norm.cpp * Example: \include PartialRedux_norm.cpp
* Output: \verbinclude PartialRedux_norm.out * Output: \verbinclude PartialRedux_norm.out
@@ -325,8 +296,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the norm /** \returns a row (or column) vector expression of the norm
* of each column (or row) of the referenced expression, using * of each column (or row) of the referenced expression, using
* Blue's algorithm. * blue's algorithm.
* This is a vector with real entries, even if the original matrix has complex entries.
* *
* \sa DenseBase::blueNorm() */ * \sa DenseBase::blueNorm() */
const typename ReturnType<internal::member_blueNorm,RealScalar>::Type blueNorm() const const typename ReturnType<internal::member_blueNorm,RealScalar>::Type blueNorm() const
@@ -336,7 +306,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the norm /** \returns a row (or column) vector expression of the norm
* of each column (or row) of the referenced expression, avoiding * of each column (or row) of the referenced expression, avoiding
* underflow and overflow. * underflow and overflow.
* This is a vector with real entries, even if the original matrix has complex entries.
* *
* \sa DenseBase::stableNorm() */ * \sa DenseBase::stableNorm() */
const typename ReturnType<internal::member_stableNorm,RealScalar>::Type stableNorm() const const typename ReturnType<internal::member_stableNorm,RealScalar>::Type stableNorm() const
@@ -346,7 +315,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression of the norm /** \returns a row (or column) vector expression of the norm
* of each column (or row) of the referenced expression, avoiding * of each column (or row) of the referenced expression, avoiding
* underflow and overflow using a concatenation of hypot() calls. * underflow and overflow using a concatenation of hypot() calls.
* This is a vector with real entries, even if the original matrix has complex entries.
* *
* \sa DenseBase::hypotNorm() */ * \sa DenseBase::hypotNorm() */
const typename ReturnType<internal::member_hypotNorm,RealScalar>::Type hypotNorm() const const typename ReturnType<internal::member_hypotNorm,RealScalar>::Type hypotNorm() const
@@ -371,7 +339,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression representing /** \returns a row (or column) vector expression representing
* whether \b all coefficients of each respective column (or row) are \c true. * whether \b all coefficients of each respective column (or row) are \c true.
* This expression can be assigned to a vector with entries of type \c bool.
* *
* \sa DenseBase::all() */ * \sa DenseBase::all() */
const typename ReturnType<internal::member_all>::Type all() const const typename ReturnType<internal::member_all>::Type all() const
@@ -379,7 +346,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression representing /** \returns a row (or column) vector expression representing
* whether \b at \b least one coefficient of each respective column (or row) is \c true. * whether \b at \b least one coefficient of each respective column (or row) is \c true.
* This expression can be assigned to a vector with entries of type \c bool.
* *
* \sa DenseBase::any() */ * \sa DenseBase::any() */
const typename ReturnType<internal::member_any>::Type any() const const typename ReturnType<internal::member_any>::Type any() const
@@ -387,8 +353,6 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
/** \returns a row (or column) vector expression representing /** \returns a row (or column) vector expression representing
* the number of \c true coefficients of each respective column (or row). * the number of \c true coefficients of each respective column (or row).
* This expression can be assigned to a vector whose entries have the same type as is used to
* index entries of the original matrix; for dense matrices, this is \c std::ptrdiff_t .
* *
* Example: \include PartialRedux_count.cpp * Example: \include PartialRedux_count.cpp
* Output: \verbinclude PartialRedux_count.out * Output: \verbinclude PartialRedux_count.out
@@ -541,26 +505,11 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
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 ///////////
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
Homogeneous<ExpressionType,Direction> homogeneous() const; Homogeneous<ExpressionType,Direction> homogeneous() const;
#endif
typedef typename ExpressionType::PlainObject CrossReturnType; typedef typename ExpressionType::PlainObject CrossReturnType;
template<typename OtherDerived> template<typename OtherDerived>

View File

@@ -164,25 +164,25 @@ struct functor_traits<max_coeff_visitor<Scalar> > {
} // end namespace internal } // end namespace internal
/** \returns the minimum of all coefficients of *this and puts in *row and *col its location. /** \returns the minimum of all coefficients of *this
* \warning the result is undefined if \c *this contains NaN. * and puts in *row and *col its location.
* *
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff() * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
*/ */
template<typename Derived> template<typename Derived>
template<typename IndexType> template<typename IndexType>
typename internal::traits<Derived>::Scalar typename internal::traits<Derived>::Scalar
DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
{ {
internal::min_coeff_visitor<Derived> minVisitor; internal::min_coeff_visitor<Derived> minVisitor;
this->visit(minVisitor); this->visit(minVisitor);
*rowId = minVisitor.row; *row = minVisitor.row;
if (colId) *colId = minVisitor.col; if (col) *col = minVisitor.col;
return minVisitor.res; return minVisitor.res;
} }
/** \returns the minimum of all coefficients of *this and puts in *index its location. /** \returns the minimum of all coefficients of *this
* \warning the result is undefined if \c *this contains NaN. * and puts in *index its location.
* *
* \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()
*/ */
@@ -194,29 +194,29 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
internal::min_coeff_visitor<Derived> minVisitor; internal::min_coeff_visitor<Derived> minVisitor;
this->visit(minVisitor); this->visit(minVisitor);
*index = IndexType((RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row); *index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
return minVisitor.res; return minVisitor.res;
} }
/** \returns the maximum of all coefficients of *this and puts in *row and *col its location. /** \returns the maximum of all coefficients of *this
* \warning the result is undefined if \c *this contains NaN. * and puts in *row and *col its location.
* *
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff() * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
*/ */
template<typename Derived> template<typename Derived>
template<typename IndexType> template<typename IndexType>
typename internal::traits<Derived>::Scalar typename internal::traits<Derived>::Scalar
DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
{ {
internal::max_coeff_visitor<Derived> maxVisitor; internal::max_coeff_visitor<Derived> maxVisitor;
this->visit(maxVisitor); this->visit(maxVisitor);
*rowPtr = maxVisitor.row; *row = maxVisitor.row;
if (colPtr) *colPtr = maxVisitor.col; if (col) *col = maxVisitor.col;
return maxVisitor.res; return maxVisitor.res;
} }
/** \returns the maximum of all coefficients of *this and puts in *index its location. /** \returns the maximum of all coefficients of *this
* \warning the result is undefined if \c *this contains NaN. * and puts in *index its location.
* *
* \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()
*/ */

View File

@@ -1,6 +0,0 @@
FILE(GLOB Eigen_Core_arch_AVX_SRCS "*.h")
INSTALL(FILES
${Eigen_Core_arch_AVX_SRCS}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/arch/AVX COMPONENT Devel
)

View File

@@ -1,463 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner (benoit.steiner.goog@gmail.com)
//
// 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_COMPLEX_AVX_H
#define EIGEN_COMPLEX_AVX_H
namespace Eigen {
namespace internal {
//---------- float ----------
struct Packet4cf
{
EIGEN_STRONG_INLINE Packet4cf() {}
EIGEN_STRONG_INLINE explicit Packet4cf(const __m256& a) : v(a) {}
__m256 v;
};
template<> struct packet_traits<std::complex<float> > : default_packet_traits
{
typedef Packet4cf type;
typedef Packet2cf half;
enum {
Vectorizable = 1,
AlignedOnScalar = 1,
size = 4,
HasHalfPacket = 1,
HasAdd = 1,
HasSub = 1,
HasMul = 1,
HasDiv = 1,
HasNegate = 1,
HasAbs = 0,
HasAbs2 = 0,
HasMin = 0,
HasMax = 0,
HasSetLinear = 0
};
};
template<> struct unpacket_traits<Packet4cf> { typedef std::complex<float> type; enum {size=4}; typedef Packet2cf half; };
template<> EIGEN_STRONG_INLINE Packet4cf padd<Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_add_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf psub<Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_sub_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf pnegate(const Packet4cf& a)
{
return Packet4cf(pnegate(a.v));
}
template<> EIGEN_STRONG_INLINE Packet4cf pconj(const Packet4cf& a)
{
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000,0x00000000,0x80000000,0x00000000,0x80000000));
return Packet4cf(_mm256_xor_ps(a.v,mask));
}
template<> EIGEN_STRONG_INLINE Packet4cf pmul<Packet4cf>(const Packet4cf& a, const Packet4cf& b)
{
__m256 tmp1 = _mm256_mul_ps(_mm256_moveldup_ps(a.v), b.v);
__m256 tmp2 = _mm256_mul_ps(_mm256_movehdup_ps(a.v), _mm256_permute_ps(b.v, _MM_SHUFFLE(2,3,0,1)));
__m256 result = _mm256_addsub_ps(tmp1, tmp2);
return Packet4cf(result);
}
template<> EIGEN_STRONG_INLINE Packet4cf pand <Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_and_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf por <Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_or_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf pxor <Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_xor_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf pandnot<Packet4cf>(const Packet4cf& a, const Packet4cf& b) { return Packet4cf(_mm256_andnot_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet4cf pload <Packet4cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet4cf(pload<Packet8f>(&numext::real_ref(*from))); }
template<> EIGEN_STRONG_INLINE Packet4cf ploadu<Packet4cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet4cf(ploadu<Packet8f>(&numext::real_ref(*from))); }
template<> EIGEN_STRONG_INLINE Packet4cf pset1<Packet4cf>(const std::complex<float>& from)
{
return Packet4cf(_mm256_castpd_ps(_mm256_broadcast_sd((const double*)(const void*)&from)));
}
template<> EIGEN_STRONG_INLINE Packet4cf ploaddup<Packet4cf>(const std::complex<float>* from)
{
// FIXME The following might be optimized using _mm256_movedup_pd
Packet2cf a = ploaddup<Packet2cf>(from);
Packet2cf b = ploaddup<Packet2cf>(from+1);
return Packet4cf(_mm256_insertf128_ps(_mm256_castps128_ps256(a.v), b.v, 1));
}
template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float>* to, const Packet4cf& 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 Packet4cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), from.v); }
template<> EIGEN_DEVICE_FUNC inline Packet4cf pgather<std::complex<float>, Packet4cf>(const std::complex<float>* from, DenseIndex stride)
{
return Packet4cf(_mm256_set_ps(std::imag(from[3*stride]), std::real(from[3*stride]),
std::imag(from[2*stride]), std::real(from[2*stride]),
std::imag(from[1*stride]), std::real(from[1*stride]),
std::imag(from[0*stride]), std::real(from[0*stride])));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet4cf>(std::complex<float>* to, const Packet4cf& from, DenseIndex stride)
{
__m128 low = _mm256_extractf128_ps(from.v, 0);
to[stride*0] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 0)),
_mm_cvtss_f32(_mm_shuffle_ps(low, low, 1)));
to[stride*1] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 2)),
_mm_cvtss_f32(_mm_shuffle_ps(low, low, 3)));
__m128 high = _mm256_extractf128_ps(from.v, 1);
to[stride*2] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 0)),
_mm_cvtss_f32(_mm_shuffle_ps(high, high, 1)));
to[stride*3] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 2)),
_mm_cvtss_f32(_mm_shuffle_ps(high, high, 3)));
}
template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet4cf>(const Packet4cf& a)
{
return pfirst(Packet2cf(_mm256_castps256_ps128(a.v)));
}
template<> EIGEN_STRONG_INLINE Packet4cf preverse(const Packet4cf& a) {
__m128 low = _mm256_extractf128_ps(a.v, 0);
__m128 high = _mm256_extractf128_ps(a.v, 1);
__m128d lowd = _mm_castps_pd(low);
__m128d highd = _mm_castps_pd(high);
low = _mm_castpd_ps(_mm_shuffle_pd(lowd,lowd,0x1));
high = _mm_castpd_ps(_mm_shuffle_pd(highd,highd,0x1));
__m256 result = _mm256_setzero_ps();
result = _mm256_insertf128_ps(result, low, 1);
result = _mm256_insertf128_ps(result, high, 0);
return Packet4cf(result);
}
template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet4cf>(const Packet4cf& a)
{
return predux(padd(Packet2cf(_mm256_extractf128_ps(a.v,0)),
Packet2cf(_mm256_extractf128_ps(a.v,1))));
}
template<> EIGEN_STRONG_INLINE Packet4cf preduxp<Packet4cf>(const Packet4cf* vecs)
{
Packet8f t0 = _mm256_shuffle_ps(vecs[0].v, vecs[0].v, _MM_SHUFFLE(3, 1, 2 ,0));
Packet8f t1 = _mm256_shuffle_ps(vecs[1].v, vecs[1].v, _MM_SHUFFLE(3, 1, 2 ,0));
t0 = _mm256_hadd_ps(t0,t1);
Packet8f t2 = _mm256_shuffle_ps(vecs[2].v, vecs[2].v, _MM_SHUFFLE(3, 1, 2 ,0));
Packet8f t3 = _mm256_shuffle_ps(vecs[3].v, vecs[3].v, _MM_SHUFFLE(3, 1, 2 ,0));
t2 = _mm256_hadd_ps(t2,t3);
t1 = _mm256_permute2f128_ps(t0,t2, 0 + (2<<4));
t3 = _mm256_permute2f128_ps(t0,t2, 1 + (3<<4));
return Packet4cf(_mm256_add_ps(t1,t3));
}
template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet4cf>(const Packet4cf& a)
{
return predux_mul(pmul(Packet2cf(_mm256_extractf128_ps(a.v, 0)),
Packet2cf(_mm256_extractf128_ps(a.v, 1))));
}
template<int Offset>
struct palign_impl<Offset,Packet4cf>
{
static EIGEN_STRONG_INLINE void run(Packet4cf& first, const Packet4cf& second)
{
if (Offset==0) return;
palign_impl<Offset*2,Packet8f>::run(first.v, second.v);
}
};
template<> struct conj_helper<Packet4cf, Packet4cf, false,true>
{
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
{
return internal::pmul(a, pconj(b));
}
};
template<> struct conj_helper<Packet4cf, Packet4cf, true,false>
{
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
{
return internal::pmul(pconj(a), b);
}
};
template<> struct conj_helper<Packet4cf, Packet4cf, true,true>
{
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet4cf& y, const Packet4cf& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& a, const Packet4cf& b) const
{
return pconj(internal::pmul(a, b));
}
};
template<> struct conj_helper<Packet8f, Packet4cf, false,false>
{
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet8f& x, const Packet4cf& y, const Packet4cf& c) const
{ return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet8f& x, const Packet4cf& y) const
{ return Packet4cf(Eigen::internal::pmul(x, y.v)); }
};
template<> struct conj_helper<Packet4cf, Packet8f, false,false>
{
EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet8f& y, const Packet4cf& c) const
{ return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& x, const Packet8f& y) const
{ return Packet4cf(Eigen::internal::pmul(x.v, y)); }
};
template<> EIGEN_STRONG_INLINE Packet4cf pdiv<Packet4cf>(const Packet4cf& a, const Packet4cf& b)
{
Packet4cf num = pmul(a, pconj(b));
__m256 tmp = _mm256_mul_ps(b.v, b.v);
__m256 tmp2 = _mm256_shuffle_ps(tmp,tmp,0xB1);
__m256 denom = _mm256_add_ps(tmp, tmp2);
return Packet4cf(_mm256_div_ps(num.v, denom));
}
template<> EIGEN_STRONG_INLINE Packet4cf pcplxflip<Packet4cf>(const Packet4cf& x)
{
return Packet4cf(_mm256_shuffle_ps(x.v, x.v, _MM_SHUFFLE(2, 3, 0 ,1)));
}
//---------- double ----------
struct Packet2cd
{
EIGEN_STRONG_INLINE Packet2cd() {}
EIGEN_STRONG_INLINE explicit Packet2cd(const __m256d& a) : v(a) {}
__m256d v;
};
template<> struct packet_traits<std::complex<double> > : default_packet_traits
{
typedef Packet2cd type;
typedef Packet1cd half;
enum {
Vectorizable = 1,
AlignedOnScalar = 0,
size = 2,
HasHalfPacket = 1,
HasAdd = 1,
HasSub = 1,
HasMul = 1,
HasDiv = 1,
HasNegate = 1,
HasAbs = 0,
HasAbs2 = 0,
HasMin = 0,
HasMax = 0,
HasSetLinear = 0
};
};
template<> struct unpacket_traits<Packet2cd> { typedef std::complex<double> type; enum {size=2}; typedef Packet1cd half; };
template<> EIGEN_STRONG_INLINE Packet2cd padd<Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_add_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd psub<Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_sub_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd pnegate(const Packet2cd& a) { return Packet2cd(pnegate(a.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd pconj(const Packet2cd& a)
{
const __m256d mask = _mm256_castsi256_pd(_mm256_set_epi32(0x80000000,0x0,0x0,0x0,0x80000000,0x0,0x0,0x0));
return Packet2cd(_mm256_xor_pd(a.v,mask));
}
template<> EIGEN_STRONG_INLINE Packet2cd pmul<Packet2cd>(const Packet2cd& a, const Packet2cd& b)
{
__m256d tmp1 = _mm256_shuffle_pd(a.v,a.v,0x0);
__m256d even = _mm256_mul_pd(tmp1, b.v);
__m256d tmp2 = _mm256_shuffle_pd(a.v,a.v,0xF);
__m256d tmp3 = _mm256_shuffle_pd(b.v,b.v,0x5);
__m256d odd = _mm256_mul_pd(tmp2, tmp3);
return Packet2cd(_mm256_addsub_pd(even, odd));
}
template<> EIGEN_STRONG_INLINE Packet2cd pand <Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_and_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd por <Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_or_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd pxor <Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_xor_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd pandnot<Packet2cd>(const Packet2cd& a, const Packet2cd& b) { return Packet2cd(_mm256_andnot_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cd pload <Packet2cd>(const std::complex<double>* from)
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet2cd(pload<Packet4d>((const double*)from)); }
template<> EIGEN_STRONG_INLINE Packet2cd ploadu<Packet2cd>(const std::complex<double>* from)
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cd(ploadu<Packet4d>((const double*)from)); }
template<> EIGEN_STRONG_INLINE Packet2cd pset1<Packet2cd>(const std::complex<double>& from)
{
// in case casting to a __m128d* is really not safe, then we can still fallback to this version: (much slower though)
// return Packet2cd(_mm256_loadu2_m128d((const double*)&from,(const double*)&from));
return Packet2cd(_mm256_broadcast_pd((const __m128d*)(const void*)&from));
}
template<> EIGEN_STRONG_INLINE Packet2cd ploaddup<Packet2cd>(const std::complex<double>* from) { return pset1<Packet2cd>(*from); }
template<> EIGEN_STRONG_INLINE void pstore <std::complex<double> >(std::complex<double> * to, const Packet2cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); }
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double> * to, const Packet2cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); }
template<> EIGEN_DEVICE_FUNC inline Packet2cd pgather<std::complex<double>, Packet2cd>(const std::complex<double>* from, DenseIndex stride)
{
return Packet2cd(_mm256_set_pd(std::imag(from[1*stride]), std::real(from[1*stride]),
std::imag(from[0*stride]), std::real(from[0*stride])));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<double>, Packet2cd>(std::complex<double>* to, const Packet2cd& from, DenseIndex stride)
{
__m128d low = _mm256_extractf128_pd(from.v, 0);
to[stride*0] = std::complex<double>(_mm_cvtsd_f64(low), _mm_cvtsd_f64(_mm_shuffle_pd(low, low, 1)));
__m128d high = _mm256_extractf128_pd(from.v, 1);
to[stride*1] = std::complex<double>(_mm_cvtsd_f64(high), _mm_cvtsd_f64(_mm_shuffle_pd(high, high, 1)));
}
template<> EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet2cd>(const Packet2cd& a)
{
__m128d low = _mm256_extractf128_pd(a.v, 0);
EIGEN_ALIGN16 double res[2];
_mm_store_pd(res, low);
return std::complex<double>(res[0],res[1]);
}
template<> EIGEN_STRONG_INLINE Packet2cd preverse(const Packet2cd& a) {
__m256d result = _mm256_permute2f128_pd(a.v, a.v, 1);
return Packet2cd(result);
}
template<> EIGEN_STRONG_INLINE std::complex<double> predux<Packet2cd>(const Packet2cd& a)
{
return predux(padd(Packet1cd(_mm256_extractf128_pd(a.v,0)),
Packet1cd(_mm256_extractf128_pd(a.v,1))));
}
template<> EIGEN_STRONG_INLINE Packet2cd preduxp<Packet2cd>(const Packet2cd* vecs)
{
Packet4d t0 = _mm256_permute2f128_pd(vecs[0].v,vecs[1].v, 0 + (2<<4));
Packet4d t1 = _mm256_permute2f128_pd(vecs[0].v,vecs[1].v, 1 + (3<<4));
return Packet2cd(_mm256_add_pd(t0,t1));
}
template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet2cd>(const Packet2cd& a)
{
return predux(pmul(Packet1cd(_mm256_extractf128_pd(a.v,0)),
Packet1cd(_mm256_extractf128_pd(a.v,1))));
}
template<int Offset>
struct palign_impl<Offset,Packet2cd>
{
static EIGEN_STRONG_INLINE void run(Packet2cd& first, const Packet2cd& second)
{
if (Offset==0) return;
palign_impl<Offset*2,Packet4d>::run(first.v, second.v);
}
};
template<> struct conj_helper<Packet2cd, Packet2cd, false,true>
{
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
{
return internal::pmul(a, pconj(b));
}
};
template<> struct conj_helper<Packet2cd, Packet2cd, true,false>
{
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
{
return internal::pmul(pconj(a), b);
}
};
template<> struct conj_helper<Packet2cd, Packet2cd, true,true>
{
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet2cd& y, const Packet2cd& c) const
{ return padd(pmul(x,y),c); }
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& a, const Packet2cd& b) const
{
return pconj(internal::pmul(a, b));
}
};
template<> struct conj_helper<Packet4d, Packet2cd, false,false>
{
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet4d& x, const Packet2cd& y, const Packet2cd& c) const
{ return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet4d& x, const Packet2cd& y) const
{ return Packet2cd(Eigen::internal::pmul(x, y.v)); }
};
template<> struct conj_helper<Packet2cd, Packet4d, false,false>
{
EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet4d& y, const Packet2cd& c) const
{ return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& x, const Packet4d& y) const
{ return Packet2cd(Eigen::internal::pmul(x.v, y)); }
};
template<> EIGEN_STRONG_INLINE Packet2cd pdiv<Packet2cd>(const Packet2cd& a, const Packet2cd& b)
{
Packet2cd num = pmul(a, pconj(b));
__m256d tmp = _mm256_mul_pd(b.v, b.v);
__m256d denom = _mm256_hadd_pd(tmp, tmp);
return Packet2cd(_mm256_div_pd(num.v, denom));
}
template<> EIGEN_STRONG_INLINE Packet2cd pcplxflip<Packet2cd>(const Packet2cd& x)
{
return Packet2cd(_mm256_shuffle_pd(x.v, x.v, 0x5));
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4cf,4>& kernel) {
__m256d P0 = _mm256_castps_pd(kernel.packet[0].v);
__m256d P1 = _mm256_castps_pd(kernel.packet[1].v);
__m256d P2 = _mm256_castps_pd(kernel.packet[2].v);
__m256d P3 = _mm256_castps_pd(kernel.packet[3].v);
__m256d T0 = _mm256_shuffle_pd(P0, P1, 15);
__m256d T1 = _mm256_shuffle_pd(P0, P1, 0);
__m256d T2 = _mm256_shuffle_pd(P2, P3, 15);
__m256d T3 = _mm256_shuffle_pd(P2, P3, 0);
kernel.packet[1].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 32));
kernel.packet[3].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 49));
kernel.packet[0].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 32));
kernel.packet[2].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 49));
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet2cd,2>& kernel) {
__m256d tmp = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 0+(2<<4));
kernel.packet[1].v = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 1+(3<<4));
kernel.packet[0].v = tmp;
}
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_COMPLEX_AVX_H

View File

@@ -1,564 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner (benoit.steiner.goog@gmail.com)
//
// 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_PACKET_MATH_AVX_H
#define EIGEN_PACKET_MATH_AVX_H
namespace Eigen {
namespace internal {
#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 8
#endif
#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*))
#endif
#ifdef EIGEN_VECTORIZE_FMA
#ifndef EIGEN_HAS_FUSED_MADD
#define EIGEN_HAS_FUSED_MADD 1
#endif
#endif
typedef __m256 Packet8f;
typedef __m256i Packet8i;
typedef __m256d Packet4d;
template<> struct is_arithmetic<__m256> { enum { value = true }; };
template<> struct is_arithmetic<__m256i> { enum { value = true }; };
template<> struct is_arithmetic<__m256d> { enum { value = true }; };
#define _EIGEN_DECLARE_CONST_Packet8f(NAME,X) \
const Packet8f p8f_##NAME = pset1<Packet8f>(X)
#define _EIGEN_DECLARE_CONST_Packet4d(NAME,X) \
const Packet4d p4d_##NAME = pset1<Packet4d>(X)
template<> struct packet_traits<float> : default_packet_traits
{
typedef Packet8f type;
typedef Packet4f half;
enum {
Vectorizable = 1,
AlignedOnScalar = 1,
size=8,
HasHalfPacket = 1,
HasDiv = 1,
HasSin = 0,
HasCos = 0,
HasLog = 0,
HasExp = 0,
HasSqrt = 0
};
};
template<> struct packet_traits<double> : default_packet_traits
{
typedef Packet4d type;
typedef Packet2d half;
enum {
Vectorizable = 1,
AlignedOnScalar = 1,
size=4,
HasHalfPacket = 1,
HasDiv = 1,
HasExp = 0
};
};
/* Proper support for integers is only provided by AVX2. In the meantime, we'll
use SSE instructions and packets to deal with integers.
template<> struct packet_traits<int> : default_packet_traits
{
typedef Packet8i type;
enum {
Vectorizable = 1,
AlignedOnScalar = 1,
size=8
};
};
*/
template<> struct unpacket_traits<Packet8f> { typedef float type; typedef Packet4f half; enum {size=8}; };
template<> struct unpacket_traits<Packet4d> { typedef double type; typedef Packet2d half; enum {size=4}; };
template<> struct unpacket_traits<Packet8i> { typedef int type; typedef Packet4i half; enum {size=8}; };
template<> EIGEN_STRONG_INLINE Packet8f pset1<Packet8f>(const float& from) { return _mm256_set1_ps(from); }
template<> EIGEN_STRONG_INLINE Packet4d pset1<Packet4d>(const double& from) { return _mm256_set1_pd(from); }
template<> EIGEN_STRONG_INLINE Packet8i pset1<Packet8i>(const int& from) { return _mm256_set1_epi32(from); }
template<> EIGEN_STRONG_INLINE Packet8f pload1<Packet8f>(const float* from) { return _mm256_broadcast_ss(from); }
template<> EIGEN_STRONG_INLINE Packet4d pload1<Packet4d>(const double* from) { return _mm256_broadcast_sd(from); }
template<> EIGEN_STRONG_INLINE Packet8f plset<float>(const float& a) { return _mm256_add_ps(_mm256_set1_ps(a), _mm256_set_ps(7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0)); }
template<> EIGEN_STRONG_INLINE Packet4d plset<double>(const double& a) { return _mm256_add_pd(_mm256_set1_pd(a), _mm256_set_pd(3.0,2.0,1.0,0.0)); }
template<> EIGEN_STRONG_INLINE Packet8f padd<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_add_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d padd<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_add_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f psub<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_sub_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d psub<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_sub_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pnegate(const Packet8f& a)
{
return _mm256_sub_ps(_mm256_set1_ps(0.0),a);
}
template<> EIGEN_STRONG_INLINE Packet4d pnegate(const Packet4d& a)
{
return _mm256_sub_pd(_mm256_set1_pd(0.0),a);
}
template<> EIGEN_STRONG_INLINE Packet8f pconj(const Packet8f& a) { return a; }
template<> EIGEN_STRONG_INLINE Packet4d pconj(const Packet4d& a) { return a; }
template<> EIGEN_STRONG_INLINE Packet8i pconj(const Packet8i& a) { return a; }
template<> EIGEN_STRONG_INLINE Packet8f pmul<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_mul_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pmul<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_mul_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pdiv<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_div_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pdiv<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_div_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8i pdiv<Packet8i>(const Packet8i& /*a*/, const Packet8i& /*b*/)
{ eigen_assert(false && "packet integer division are not supported by AVX");
return pset1<Packet8i>(0);
}
#ifdef EIGEN_VECTORIZE_FMA
template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& b, const Packet8f& c) {
#if defined(__clang__) || defined(__GNUC__)
// clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers,
// and gcc stupidly generates a vfmadd132ps instruction,
// so let's enforce it to generate a vfmadd231ps instruction since the most common use case is to accumulate
// the result of the product.
Packet8f res = c;
__asm__("vfmadd231ps %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b));
return res;
#else
return _mm256_fmadd_ps(a,b,c);
#endif
}
template<> EIGEN_STRONG_INLINE Packet4d pmadd(const Packet4d& a, const Packet4d& b, const Packet4d& c) {
#if defined(__clang__) || defined(__GNUC__)
// see above
Packet4d res = c;
__asm__("vfmadd231pd %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b));
return res;
#else
return _mm256_fmadd_pd(a,b,c);
#endif
}
#endif
template<> EIGEN_STRONG_INLINE Packet8f pmin<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_min_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pmin<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_min_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pmax<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_max_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pmax<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_max_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pand<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_and_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pand<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_and_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f por<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_or_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d por<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_or_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pxor<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_xor_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pxor<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_xor_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pandnot<Packet8f>(const Packet8f& a, const Packet8f& b) { return _mm256_andnot_ps(a,b); }
template<> EIGEN_STRONG_INLINE Packet4d pandnot<Packet4d>(const Packet4d& a, const Packet4d& b) { return _mm256_andnot_pd(a,b); }
template<> EIGEN_STRONG_INLINE Packet8f pload<Packet8f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm256_load_ps(from); }
template<> EIGEN_STRONG_INLINE Packet4d pload<Packet4d>(const double* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm256_load_pd(from); }
template<> EIGEN_STRONG_INLINE Packet8i pload<Packet8i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm256_load_si256(reinterpret_cast<const __m256i*>(from)); }
template<> EIGEN_STRONG_INLINE Packet8f ploadu<Packet8f>(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm256_loadu_ps(from); }
template<> EIGEN_STRONG_INLINE Packet4d ploadu<Packet4d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm256_loadu_pd(from); }
template<> EIGEN_STRONG_INLINE Packet8i ploadu<Packet8i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(from)); }
// Loads 4 floats from memory a returns the packet {a0, a0 a1, a1, a2, a2, a3, a3}
template<> EIGEN_STRONG_INLINE Packet8f ploaddup<Packet8f>(const float* from)
{
// TODO try to find a way to avoid the need of a temporary register
// Packet8f tmp = _mm256_castps128_ps256(_mm_loadu_ps(from));
// tmp = _mm256_insertf128_ps(tmp, _mm_movehl_ps(_mm256_castps256_ps128(tmp),_mm256_castps256_ps128(tmp)), 1);
// return _mm256_unpacklo_ps(tmp,tmp);
// _mm256_insertf128_ps is very slow on Haswell, thus:
Packet8f tmp = _mm256_broadcast_ps((const __m128*)(const void*)from);
// mimic an "inplace" permutation of the lower 128bits using a blend
tmp = _mm256_blend_ps(tmp,_mm256_castps128_ps256(_mm_permute_ps( _mm256_castps256_ps128(tmp), _MM_SHUFFLE(1,0,1,0))), 15);
// then we can perform a consistent permutation on the global register to get everything in shape:
return _mm256_permute_ps(tmp, _MM_SHUFFLE(3,3,2,2));
}
// Loads 2 doubles from memory a returns the packet {a0, a0 a1, a1}
template<> EIGEN_STRONG_INLINE Packet4d ploaddup<Packet4d>(const double* from)
{
Packet4d tmp = _mm256_broadcast_pd((const __m128d*)(const void*)from);
return _mm256_permute_pd(tmp, 3<<2);
}
// Loads 2 floats from memory a returns the packet {a0, a0 a0, a0, a1, a1, a1, a1}
template<> EIGEN_STRONG_INLINE Packet8f ploadquad<Packet8f>(const float* from)
{
Packet8f tmp = _mm256_castps128_ps256(_mm_broadcast_ss(from));
return _mm256_insertf128_ps(tmp, _mm_broadcast_ss(from+1), 1);
}
template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet8f& from) { EIGEN_DEBUG_ALIGNED_STORE _mm256_store_ps(to, from); }
template<> EIGEN_STRONG_INLINE void pstore<double>(double* to, const Packet4d& from) { EIGEN_DEBUG_ALIGNED_STORE _mm256_store_pd(to, from); }
template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet8i& from) { EIGEN_DEBUG_ALIGNED_STORE _mm256_storeu_si256(reinterpret_cast<__m256i*>(to), from); }
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet8f& from) { EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_ps(to, from); }
template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet4d& from) { EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_pd(to, from); }
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet8i& from) { EIGEN_DEBUG_UNALIGNED_STORE _mm256_storeu_si256(reinterpret_cast<__m256i*>(to), from); }
// NOTE: leverage _mm256_i32gather_ps and _mm256_i32gather_pd if AVX2 instructions are available
// NOTE: for the record the following seems to be slower: return _mm256_i32gather_ps(from, _mm256_set1_epi32(stride), 4);
template<> EIGEN_DEVICE_FUNC inline Packet8f pgather<float, Packet8f>(const float* from, DenseIndex stride)
{
return _mm256_set_ps(from[7*stride], from[6*stride], from[5*stride], from[4*stride],
from[3*stride], from[2*stride], from[1*stride], from[0*stride]);
}
template<> EIGEN_DEVICE_FUNC inline Packet4d pgather<double, Packet4d>(const double* from, DenseIndex stride)
{
return _mm256_set_pd(from[3*stride], from[2*stride], from[1*stride], from[0*stride]);
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet8f>(float* to, const Packet8f& from, DenseIndex stride)
{
__m128 low = _mm256_extractf128_ps(from, 0);
to[stride*0] = _mm_cvtss_f32(low);
to[stride*1] = _mm_cvtss_f32(_mm_shuffle_ps(low, low, 1));
to[stride*2] = _mm_cvtss_f32(_mm_shuffle_ps(low, low, 2));
to[stride*3] = _mm_cvtss_f32(_mm_shuffle_ps(low, low, 3));
__m128 high = _mm256_extractf128_ps(from, 1);
to[stride*4] = _mm_cvtss_f32(high);
to[stride*5] = _mm_cvtss_f32(_mm_shuffle_ps(high, high, 1));
to[stride*6] = _mm_cvtss_f32(_mm_shuffle_ps(high, high, 2));
to[stride*7] = _mm_cvtss_f32(_mm_shuffle_ps(high, high, 3));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<double, Packet4d>(double* to, const Packet4d& from, DenseIndex stride)
{
__m128d low = _mm256_extractf128_pd(from, 0);
to[stride*0] = _mm_cvtsd_f64(low);
to[stride*1] = _mm_cvtsd_f64(_mm_shuffle_pd(low, low, 1));
__m128d high = _mm256_extractf128_pd(from, 1);
to[stride*2] = _mm_cvtsd_f64(high);
to[stride*3] = _mm_cvtsd_f64(_mm_shuffle_pd(high, high, 1));
}
template<> EIGEN_STRONG_INLINE void pstore1<Packet8f>(float* to, const float& a)
{
Packet8f pa = pset1<Packet8f>(a);
pstore(to, pa);
}
template<> EIGEN_STRONG_INLINE void pstore1<Packet4d>(double* to, const double& a)
{
Packet4d pa = pset1<Packet4d>(a);
pstore(to, pa);
}
template<> EIGEN_STRONG_INLINE void pstore1<Packet8i>(int* to, const int& a)
{
Packet8i pa = pset1<Packet8i>(a);
pstore(to, pa);
}
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE float pfirst<Packet8f>(const Packet8f& a) {
return _mm_cvtss_f32(_mm256_castps256_ps128(a));
}
template<> EIGEN_STRONG_INLINE double pfirst<Packet4d>(const Packet4d& a) {
return _mm_cvtsd_f64(_mm256_castpd256_pd128(a));
}
template<> EIGEN_STRONG_INLINE int pfirst<Packet8i>(const Packet8i& a) {
return _mm_cvtsi128_si32(_mm256_castsi256_si128(a));
}
template<> EIGEN_STRONG_INLINE Packet8f preverse(const Packet8f& a)
{
__m256 tmp = _mm256_shuffle_ps(a,a,0x1b);
return _mm256_permute2f128_ps(tmp, tmp, 1);
}
template<> EIGEN_STRONG_INLINE Packet4d preverse(const Packet4d& a)
{
__m256d tmp = _mm256_shuffle_pd(a,a,5);
return _mm256_permute2f128_pd(tmp, tmp, 1);
__m256d swap_halves = _mm256_permute2f128_pd(a,a,1);
return _mm256_permute_pd(swap_halves,5);
}
// pabs should be ok
template<> EIGEN_STRONG_INLINE Packet8f pabs(const Packet8f& a)
{
const Packet8f mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF));
return _mm256_and_ps(a,mask);
}
template<> EIGEN_STRONG_INLINE Packet4d pabs(const Packet4d& a)
{
const Packet4d mask = _mm256_castsi256_pd(_mm256_setr_epi32(0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0x7FFFFFFF));
return _mm256_and_pd(a,mask);
}
// preduxp should be ok
// FIXME: why is this ok? why isn't the simply implementation working as expected?
template<> EIGEN_STRONG_INLINE Packet8f preduxp<Packet8f>(const Packet8f* vecs)
{
__m256 hsum1 = _mm256_hadd_ps(vecs[0], vecs[1]);
__m256 hsum2 = _mm256_hadd_ps(vecs[2], vecs[3]);
__m256 hsum3 = _mm256_hadd_ps(vecs[4], vecs[5]);
__m256 hsum4 = _mm256_hadd_ps(vecs[6], vecs[7]);
__m256 hsum5 = _mm256_hadd_ps(hsum1, hsum1);
__m256 hsum6 = _mm256_hadd_ps(hsum2, hsum2);
__m256 hsum7 = _mm256_hadd_ps(hsum3, hsum3);
__m256 hsum8 = _mm256_hadd_ps(hsum4, hsum4);
__m256 perm1 = _mm256_permute2f128_ps(hsum5, hsum5, 0x23);
__m256 perm2 = _mm256_permute2f128_ps(hsum6, hsum6, 0x23);
__m256 perm3 = _mm256_permute2f128_ps(hsum7, hsum7, 0x23);
__m256 perm4 = _mm256_permute2f128_ps(hsum8, hsum8, 0x23);
__m256 sum1 = _mm256_add_ps(perm1, hsum5);
__m256 sum2 = _mm256_add_ps(perm2, hsum6);
__m256 sum3 = _mm256_add_ps(perm3, hsum7);
__m256 sum4 = _mm256_add_ps(perm4, hsum8);
__m256 blend1 = _mm256_blend_ps(sum1, sum2, 0xcc);
__m256 blend2 = _mm256_blend_ps(sum3, sum4, 0xcc);
__m256 final = _mm256_blend_ps(blend1, blend2, 0xf0);
return final;
}
template<> EIGEN_STRONG_INLINE Packet4d preduxp<Packet4d>(const Packet4d* vecs)
{
Packet4d tmp0, tmp1;
tmp0 = _mm256_hadd_pd(vecs[0], vecs[1]);
tmp0 = _mm256_add_pd(tmp0, _mm256_permute2f128_pd(tmp0, tmp0, 1));
tmp1 = _mm256_hadd_pd(vecs[2], vecs[3]);
tmp1 = _mm256_add_pd(tmp1, _mm256_permute2f128_pd(tmp1, tmp1, 1));
return _mm256_blend_pd(tmp0, tmp1, 0xC);
}
template<> EIGEN_STRONG_INLINE float predux<Packet8f>(const Packet8f& a)
{
Packet8f tmp0 = _mm256_hadd_ps(a,_mm256_permute2f128_ps(a,a,1));
tmp0 = _mm256_hadd_ps(tmp0,tmp0);
return pfirst(_mm256_hadd_ps(tmp0, tmp0));
}
template<> EIGEN_STRONG_INLINE double predux<Packet4d>(const Packet4d& a)
{
Packet4d tmp0 = _mm256_hadd_pd(a,_mm256_permute2f128_pd(a,a,1));
return pfirst(_mm256_hadd_pd(tmp0,tmp0));
}
template<> EIGEN_STRONG_INLINE Packet4f predux4<Packet8f>(const Packet8f& a)
{
return _mm_add_ps(_mm256_castps256_ps128(a),_mm256_extractf128_ps(a,1));
}
template<> EIGEN_STRONG_INLINE float predux_mul<Packet8f>(const Packet8f& a)
{
Packet8f tmp;
tmp = _mm256_mul_ps(a, _mm256_permute2f128_ps(a,a,1));
tmp = _mm256_mul_ps(tmp, _mm256_shuffle_ps(tmp,tmp,_MM_SHUFFLE(1,0,3,2)));
return pfirst(_mm256_mul_ps(tmp, _mm256_shuffle_ps(tmp,tmp,1)));
}
template<> EIGEN_STRONG_INLINE double predux_mul<Packet4d>(const Packet4d& a)
{
Packet4d tmp;
tmp = _mm256_mul_pd(a, _mm256_permute2f128_pd(a,a,1));
return pfirst(_mm256_mul_pd(tmp, _mm256_shuffle_pd(tmp,tmp,1)));
}
template<> EIGEN_STRONG_INLINE float predux_min<Packet8f>(const Packet8f& a)
{
Packet8f tmp = _mm256_min_ps(a, _mm256_permute2f128_ps(a,a,1));
tmp = _mm256_min_ps(tmp, _mm256_shuffle_ps(tmp,tmp,_MM_SHUFFLE(1,0,3,2)));
return pfirst(_mm256_min_ps(tmp, _mm256_shuffle_ps(tmp,tmp,1)));
}
template<> EIGEN_STRONG_INLINE double predux_min<Packet4d>(const Packet4d& a)
{
Packet4d tmp = _mm256_min_pd(a, _mm256_permute2f128_pd(a,a,1));
return pfirst(_mm256_min_pd(tmp, _mm256_shuffle_pd(tmp, tmp, 1)));
}
template<> EIGEN_STRONG_INLINE float predux_max<Packet8f>(const Packet8f& a)
{
Packet8f tmp = _mm256_max_ps(a, _mm256_permute2f128_ps(a,a,1));
tmp = _mm256_max_ps(tmp, _mm256_shuffle_ps(tmp,tmp,_MM_SHUFFLE(1,0,3,2)));
return pfirst(_mm256_max_ps(tmp, _mm256_shuffle_ps(tmp,tmp,1)));
}
template<> EIGEN_STRONG_INLINE double predux_max<Packet4d>(const Packet4d& a)
{
Packet4d tmp = _mm256_max_pd(a, _mm256_permute2f128_pd(a,a,1));
return pfirst(_mm256_max_pd(tmp, _mm256_shuffle_pd(tmp, tmp, 1)));
}
template<int Offset>
struct palign_impl<Offset,Packet8f>
{
static EIGEN_STRONG_INLINE void run(Packet8f& first, const Packet8f& second)
{
if (Offset==1)
{
first = _mm256_blend_ps(first, second, 1);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(0,3,2,1));
first = _mm256_blend_ps(tmp, _mm256_permute2f128_ps (tmp, tmp, 1), 0x88);
}
else if (Offset==2)
{
first = _mm256_blend_ps(first, second, 3);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(1,0,3,2));
first = _mm256_blend_ps(tmp, _mm256_permute2f128_ps (tmp, tmp, 1), 0xcc);
}
else if (Offset==3)
{
first = _mm256_blend_ps(first, second, 7);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(2,1,0,3));
first = _mm256_blend_ps(tmp, _mm256_permute2f128_ps (tmp, tmp, 1), 0xee);
}
else if (Offset==4)
{
first = _mm256_blend_ps(first, second, 15);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(3,2,1,0));
first = _mm256_permute_ps(_mm256_permute2f128_ps (tmp, tmp, 1), _MM_SHUFFLE(3,2,1,0));
}
else if (Offset==5)
{
first = _mm256_blend_ps(first, second, 31);
first = _mm256_permute2f128_ps(first, first, 1);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(0,3,2,1));
first = _mm256_permute2f128_ps(tmp, tmp, 1);
first = _mm256_blend_ps(tmp, first, 0x88);
}
else if (Offset==6)
{
first = _mm256_blend_ps(first, second, 63);
first = _mm256_permute2f128_ps(first, first, 1);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(1,0,3,2));
first = _mm256_permute2f128_ps(tmp, tmp, 1);
first = _mm256_blend_ps(tmp, first, 0xcc);
}
else if (Offset==7)
{
first = _mm256_blend_ps(first, second, 127);
first = _mm256_permute2f128_ps(first, first, 1);
Packet8f tmp = _mm256_permute_ps (first, _MM_SHUFFLE(2,1,0,3));
first = _mm256_permute2f128_ps(tmp, tmp, 1);
first = _mm256_blend_ps(tmp, first, 0xee);
}
}
};
template<int Offset>
struct palign_impl<Offset,Packet4d>
{
static EIGEN_STRONG_INLINE void run(Packet4d& first, const Packet4d& second)
{
if (Offset==1)
{
first = _mm256_blend_pd(first, second, 1);
__m256d tmp = _mm256_permute_pd(first, 5);
first = _mm256_permute2f128_pd(tmp, tmp, 1);
first = _mm256_blend_pd(tmp, first, 0xA);
}
else if (Offset==2)
{
first = _mm256_blend_pd(first, second, 3);
first = _mm256_permute2f128_pd(first, first, 1);
}
else if (Offset==3)
{
first = _mm256_blend_pd(first, second, 7);
__m256d tmp = _mm256_permute_pd(first, 5);
first = _mm256_permute2f128_pd(tmp, tmp, 1);
first = _mm256_blend_pd(tmp, first, 5);
}
}
};
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet8f,8>& kernel) {
__m256 T0 = _mm256_unpacklo_ps(kernel.packet[0], kernel.packet[1]);
__m256 T1 = _mm256_unpackhi_ps(kernel.packet[0], kernel.packet[1]);
__m256 T2 = _mm256_unpacklo_ps(kernel.packet[2], kernel.packet[3]);
__m256 T3 = _mm256_unpackhi_ps(kernel.packet[2], kernel.packet[3]);
__m256 T4 = _mm256_unpacklo_ps(kernel.packet[4], kernel.packet[5]);
__m256 T5 = _mm256_unpackhi_ps(kernel.packet[4], kernel.packet[5]);
__m256 T6 = _mm256_unpacklo_ps(kernel.packet[6], kernel.packet[7]);
__m256 T7 = _mm256_unpackhi_ps(kernel.packet[6], kernel.packet[7]);
__m256 S0 = _mm256_shuffle_ps(T0,T2,_MM_SHUFFLE(1,0,1,0));
__m256 S1 = _mm256_shuffle_ps(T0,T2,_MM_SHUFFLE(3,2,3,2));
__m256 S2 = _mm256_shuffle_ps(T1,T3,_MM_SHUFFLE(1,0,1,0));
__m256 S3 = _mm256_shuffle_ps(T1,T3,_MM_SHUFFLE(3,2,3,2));
__m256 S4 = _mm256_shuffle_ps(T4,T6,_MM_SHUFFLE(1,0,1,0));
__m256 S5 = _mm256_shuffle_ps(T4,T6,_MM_SHUFFLE(3,2,3,2));
__m256 S6 = _mm256_shuffle_ps(T5,T7,_MM_SHUFFLE(1,0,1,0));
__m256 S7 = _mm256_shuffle_ps(T5,T7,_MM_SHUFFLE(3,2,3,2));
kernel.packet[0] = _mm256_permute2f128_ps(S0, S4, 0x20);
kernel.packet[1] = _mm256_permute2f128_ps(S1, S5, 0x20);
kernel.packet[2] = _mm256_permute2f128_ps(S2, S6, 0x20);
kernel.packet[3] = _mm256_permute2f128_ps(S3, S7, 0x20);
kernel.packet[4] = _mm256_permute2f128_ps(S0, S4, 0x31);
kernel.packet[5] = _mm256_permute2f128_ps(S1, S5, 0x31);
kernel.packet[6] = _mm256_permute2f128_ps(S2, S6, 0x31);
kernel.packet[7] = _mm256_permute2f128_ps(S3, S7, 0x31);
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet8f,4>& kernel) {
__m256 T0 = _mm256_unpacklo_ps(kernel.packet[0], kernel.packet[1]);
__m256 T1 = _mm256_unpackhi_ps(kernel.packet[0], kernel.packet[1]);
__m256 T2 = _mm256_unpacklo_ps(kernel.packet[2], kernel.packet[3]);
__m256 T3 = _mm256_unpackhi_ps(kernel.packet[2], kernel.packet[3]);
__m256 S0 = _mm256_shuffle_ps(T0,T2,_MM_SHUFFLE(1,0,1,0));
__m256 S1 = _mm256_shuffle_ps(T0,T2,_MM_SHUFFLE(3,2,3,2));
__m256 S2 = _mm256_shuffle_ps(T1,T3,_MM_SHUFFLE(1,0,1,0));
__m256 S3 = _mm256_shuffle_ps(T1,T3,_MM_SHUFFLE(3,2,3,2));
kernel.packet[0] = _mm256_permute2f128_ps(S0, S1, 0x20);
kernel.packet[1] = _mm256_permute2f128_ps(S2, S3, 0x20);
kernel.packet[2] = _mm256_permute2f128_ps(S0, S1, 0x31);
kernel.packet[3] = _mm256_permute2f128_ps(S2, S3, 0x31);
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4d,4>& kernel) {
__m256d T0 = _mm256_shuffle_pd(kernel.packet[0], kernel.packet[1], 15);
__m256d T1 = _mm256_shuffle_pd(kernel.packet[0], kernel.packet[1], 0);
__m256d T2 = _mm256_shuffle_pd(kernel.packet[2], kernel.packet[3], 15);
__m256d T3 = _mm256_shuffle_pd(kernel.packet[2], kernel.packet[3], 0);
kernel.packet[1] = _mm256_permute2f128_pd(T0, T2, 32);
kernel.packet[3] = _mm256_permute2f128_pd(T0, T2, 49);
kernel.packet[0] = _mm256_permute2f128_pd(T1, T3, 32);
kernel.packet[2] = _mm256_permute2f128_pd(T1, T3, 49);
}
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_PACKET_MATH_AVX_H

View File

@@ -16,14 +16,11 @@ namespace internal {
static Packet4ui p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_ZERO_);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 }; static Packet4ui p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_ZERO_);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
static Packet16uc p16uc_COMPLEX_RE = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 }; static Packet16uc p16uc_COMPLEX_RE = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 };
static Packet16uc p16uc_COMPLEX_IM = vec_sld(p16uc_DUPLICATE, (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; static Packet16uc p16uc_COMPLEX_IM = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 1), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 };
static Packet16uc p16uc_COMPLEX_REV = vec_sld(p16uc_REVERSE, p16uc_REVERSE, 8);//{ 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11 }; static Packet16uc p16uc_COMPLEX_REV = vec_sld(p16uc_REVERSE, p16uc_REVERSE, 8);//{ 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11 };
static Packet16uc p16uc_COMPLEX_REV2 = vec_sld(p16uc_FORWARD, p16uc_FORWARD, 8);//{ 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 }; static Packet16uc p16uc_COMPLEX_REV2 = vec_sld(p16uc_FORWARD, p16uc_FORWARD, 8);//{ 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
static Packet16uc p16uc_PSET_HI = (Packet16uc) vec_mergeh((Packet4ui)p16uc_COMPLEX_RE, (Packet4ui)p16uc_COMPLEX_IM);//{ 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 }; static Packet16uc p16uc_PSET_HI = (Packet16uc) vec_mergeh((Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 1));//{ 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 };
static Packet16uc p16uc_PSET_LO = (Packet16uc) vec_mergel((Packet4ui)p16uc_COMPLEX_RE, (Packet4ui)p16uc_COMPLEX_IM);//{ 8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15 }; static Packet16uc p16uc_PSET_LO = (Packet16uc) vec_mergeh((Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 2), (Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 3));//{ 8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15 };
static Packet16uc p16uc_COMPLEX_MASK16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8);//{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16};
static Packet16uc p16uc_COMPLEX_TRANSPOSE_0 = vec_add(p16uc_PSET_HI, p16uc_COMPLEX_MASK16);//{ 0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23};
static Packet16uc p16uc_COMPLEX_TRANSPOSE_1 = vec_add(p16uc_PSET_LO, p16uc_COMPLEX_MASK16);//{ 8,9,10,11, 12,13,14,15, 24,25,26,27, 28,29,30,31};
//---------- float ---------- //---------- float ----------
struct Packet2cf struct Packet2cf
@@ -36,7 +33,6 @@ struct Packet2cf
template<> struct packet_traits<std::complex<float> > : default_packet_traits template<> struct packet_traits<std::complex<float> > : default_packet_traits
{ {
typedef Packet2cf type; typedef Packet2cf type;
typedef Packet2cf half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
@@ -55,7 +51,7 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
}; };
}; };
template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; typedef Packet2cf half; }; template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
{ {
@@ -69,22 +65,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<flo
return res; return res;
} }
template<> EIGEN_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from, DenseIndex stride)
{
std::complex<float> EIGEN_ALIGN16 af[2];
af[0] = from[0*stride];
af[1] = from[1*stride];
return Packet2cf(vec_ld(0, (const float*)af));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, DenseIndex stride)
{
std::complex<float> EIGEN_ALIGN16 af[2];
vec_st(from.v, 0, (float*)af);
to[0*stride] = af[0];
to[1*stride] = af[1];
}
template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_add(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_add(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_sub(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_sub(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate(a.v)); } template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate(a.v)); }
@@ -230,13 +210,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x
return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX_REV)); return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX_REV));
} }
EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf,2>& kernel)
{
Packet4f tmp = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_COMPLEX_TRANSPOSE_0);
kernel.packet[1].v = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_COMPLEX_TRANSPOSE_1);
kernel.packet[0].v = tmp;
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

127
Eigen/src/Core/arch/AltiVec/PacketMath.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library // This file is part of Eigen, a lightweight C++ template library
// for linear algebra. // for linear algebra.
// //
// Copyright (C) 2008-2014 Konstantinos Margaritis <markos@freevec.org> // Copyright (C) 2008 Konstantinos Margaritis <markos@codex.gr>
// //
// This Source Code Form is subject to the terms of the Mozilla // 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 // Public License v. 2.0. If a copy of the MPL was not distributed
@@ -18,10 +18,6 @@ namespace internal {
#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4 #define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4
#endif #endif
#ifndef EIGEN_HAS_FUSED_MADD
#define EIGEN_HAS_FUSED_MADD 1
#endif
#ifndef EIGEN_HAS_FUSE_CJMADD #ifndef EIGEN_HAS_FUSE_CJMADD
#define EIGEN_HAS_FUSE_CJMADD 1 #define EIGEN_HAS_FUSE_CJMADD 1
#endif #endif
@@ -60,32 +56,29 @@ typedef __vector unsigned char Packet16uc;
#define DST_CTRL(size, count, stride) (((size) << 24) | ((count) << 16) | (stride)) #define DST_CTRL(size, count, stride) (((size) << 24) | ((count) << 16) | (stride))
// Define global static constants: // Define global static constants:
static Packet4f p4f_COUNTDOWN = { 0.0, 1.0, 2.0, 3.0 }; static Packet4f p4f_COUNTDOWN = { 3.0, 2.0, 1.0, 0.0 };
static Packet4i p4i_COUNTDOWN = { 0, 1, 2, 3 }; static Packet4i p4i_COUNTDOWN = { 3, 2, 1, 0 };
static Packet16uc p16uc_REVERSE = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; static Packet16uc p16uc_REVERSE = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3};
static Packet16uc p16uc_FORWARD = vec_lvsl(0, (float*)0); //{ 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15} static Packet16uc p16uc_FORWARD = vec_lvsl(0, (float*)0);
static Packet16uc p16uc_DUPLICATE = {0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7}; static Packet16uc p16uc_DUPLICATE = {0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7};
static _EIGEN_DECLARE_CONST_FAST_Packet4f(ZERO, 0); //{ 0.0, 0.0, 0.0, 0.0} static _EIGEN_DECLARE_CONST_FAST_Packet4f(ZERO, 0);
static _EIGEN_DECLARE_CONST_FAST_Packet4i(ZERO, 0); //{ 0, 0, 0, 0,} static _EIGEN_DECLARE_CONST_FAST_Packet4i(ZERO, 0);
static _EIGEN_DECLARE_CONST_FAST_Packet4i(ONE,1); //{ 1, 1, 1, 1} static _EIGEN_DECLARE_CONST_FAST_Packet4i(ONE,1);
static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS16,-16); //{ -16, -16, -16, -16} static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS16,-16);
static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS1,-1); //{ -1, -1, -1, -1} static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS1,-1);
static Packet4f p4f_ONE = vec_ctf(p4i_ONE, 0); //{ 1.0, 1.0, 1.0, 1.0} static Packet4f p4f_ONE = vec_ctf(p4i_ONE, 0);
static Packet4f p4f_ZERO_ = (Packet4f) vec_sl((Packet4ui)p4i_MINUS1, (Packet4ui)p4i_MINUS1); //{ 0x80000000, 0x80000000, 0x80000000, 0x80000000} static Packet4f p4f_ZERO_ = (Packet4f) vec_sl((Packet4ui)p4i_MINUS1, (Packet4ui)p4i_MINUS1);
template<> struct packet_traits<float> : default_packet_traits template<> struct packet_traits<float> : default_packet_traits
{ {
typedef Packet4f type; typedef Packet4f type;
typedef Packet4f half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
size=4, size=4,
HasHalfPacket=0,
// FIXME check the Has* // FIXME check the Has*
HasDiv = 1,
HasSin = 0, HasSin = 0,
HasCos = 0, HasCos = 0,
HasLog = 0, HasLog = 0,
@@ -96,7 +89,6 @@ template<> struct packet_traits<float> : default_packet_traits
template<> struct packet_traits<int> : default_packet_traits template<> struct packet_traits<int> : default_packet_traits
{ {
typedef Packet4i type; typedef Packet4i type;
typedef Packet4i half;
enum { enum {
// FIXME check the Has* // FIXME check the Has*
Vectorizable = 1, Vectorizable = 1,
@@ -105,8 +97,8 @@ template<> struct packet_traits<int> : default_packet_traits
}; };
}; };
template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; typedef Packet4f half; }; template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; typedef Packet4i half; }; template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
/* /*
inline std::ostream & operator <<(std::ostream & s, const Packet4f & v) inline std::ostream & operator <<(std::ostream & s, const Packet4f & v)
{ {
@@ -152,7 +144,6 @@ inline std::ostream & operator <<(std::ostream & s, const Packetbi & v)
return s; return s;
} }
*/ */
template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) {
// Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
float EIGEN_ALIGN16 af[4]; float EIGEN_ALIGN16 af[4];
@@ -170,65 +161,6 @@ template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) {
return vc; return vc;
} }
template<> EIGEN_STRONG_INLINE void
pbroadcast4<Packet4f>(const float *a,
Packet4f& a0, Packet4f& a1, Packet4f& a2, Packet4f& a3)
{
a3 = vec_ld(0,a);
a0 = vec_splat(a3, 0);
a1 = vec_splat(a3, 1);
a2 = vec_splat(a3, 2);
a3 = vec_splat(a3, 3);
}
template<> EIGEN_STRONG_INLINE void
pbroadcast4<Packet4i>(const int *a,
Packet4i& a0, Packet4i& a1, Packet4i& a2, Packet4i& a3)
{
a3 = vec_ld(0,a);
a0 = vec_splat(a3, 0);
a1 = vec_splat(a3, 1);
a2 = vec_splat(a3, 2);
a3 = vec_splat(a3, 3);
}
template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, DenseIndex stride)
{
float EIGEN_ALIGN16 af[4];
af[0] = from[0*stride];
af[1] = from[1*stride];
af[2] = from[2*stride];
af[3] = from[3*stride];
return vec_ld(0, af);
}
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, DenseIndex stride)
{
int EIGEN_ALIGN16 ai[4];
ai[0] = from[0*stride];
ai[1] = from[1*stride];
ai[2] = from[2*stride];
ai[3] = from[3*stride];
return vec_ld(0, ai);
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, DenseIndex stride)
{
float EIGEN_ALIGN16 af[4];
vec_st(from, 0, af);
to[0*stride] = af[0];
to[1*stride] = af[1];
to[2*stride] = af[2];
to[3*stride] = af[3];
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, DenseIndex stride)
{
int EIGEN_ALIGN16 ai[4];
vec_st(from, 0, ai);
to[0*stride] = ai[0];
to[1*stride] = ai[1];
to[2*stride] = ai[2];
to[3*stride] = ai[3];
}
template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return vec_add(pset1<Packet4f>(a), p4f_COUNTDOWN); } template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return vec_add(pset1<Packet4f>(a), p4f_COUNTDOWN); }
template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return vec_add(pset1<Packet4i>(a), p4i_COUNTDOWN); } template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return vec_add(pset1<Packet4i>(a), p4i_COUNTDOWN); }
@@ -241,9 +173,6 @@ 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
* *
@@ -354,14 +283,14 @@ template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from) template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
{ {
Packet4f p; Packet4f p;
if((ptrdiff_t(from) % 16) == 0) p = pload<Packet4f>(from); if((ptrdiff_t(&from) % 16) == 0) p = pload<Packet4f>(from);
else p = ploadu<Packet4f>(from); else p = ploadu<Packet4f>(from);
return vec_perm(p, p, p16uc_DUPLICATE); return vec_perm(p, p, p16uc_DUPLICATE);
} }
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from) template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
{ {
Packet4i p; Packet4i p;
if((ptrdiff_t(from) % 16) == 0) p = pload<Packet4i>(from); if((ptrdiff_t(&from) % 16) == 0) p = pload<Packet4i>(from);
else p = ploadu<Packet4i>(from); else p = ploadu<Packet4i>(from);
return vec_perm(p, p, p16uc_DUPLICATE); return vec_perm(p, p, p16uc_DUPLICATE);
} }
@@ -562,32 +491,6 @@ struct palign_impl<Offset,Packet4i>
} }
}; };
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4f,4>& kernel) {
Packet4f t0, t1, t2, t3;
t0 = vec_mergeh(kernel.packet[0], kernel.packet[2]);
t1 = vec_mergel(kernel.packet[0], kernel.packet[2]);
t2 = vec_mergeh(kernel.packet[1], kernel.packet[3]);
t3 = vec_mergel(kernel.packet[1], kernel.packet[3]);
kernel.packet[0] = vec_mergeh(t0, t2);
kernel.packet[1] = vec_mergel(t0, t2);
kernel.packet[2] = vec_mergeh(t1, t3);
kernel.packet[3] = vec_mergel(t1, t3);
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4i,4>& kernel) {
Packet4i t0, t1, t2, t3;
t0 = vec_mergeh(kernel.packet[0], kernel.packet[2]);
t1 = vec_mergel(kernel.packet[0], kernel.packet[2]);
t2 = vec_mergeh(kernel.packet[1], kernel.packet[3]);
t3 = vec_mergel(kernel.packet[1], kernel.packet[3]);
kernel.packet[0] = vec_mergeh(t0, t2);
kernel.packet[1] = vec_mergel(t0, t2);
kernel.packet[2] = vec_mergeh(t1, t3);
kernel.packet[3] = vec_mergel(t1, t3);
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

View File

@@ -1,5 +1,4 @@
ADD_SUBDIRECTORY(SSE) ADD_SUBDIRECTORY(SSE)
ADD_SUBDIRECTORY(AltiVec) ADD_SUBDIRECTORY(AltiVec)
ADD_SUBDIRECTORY(NEON) ADD_SUBDIRECTORY(NEON)
ADD_SUBDIRECTORY(AVX)
ADD_SUBDIRECTORY(Default) ADD_SUBDIRECTORY(Default)

View File

@@ -28,7 +28,6 @@ struct Packet2cf
template<> struct packet_traits<std::complex<float> > : default_packet_traits template<> struct packet_traits<std::complex<float> > : default_packet_traits
{ {
typedef Packet2cf type; typedef Packet2cf type;
typedef Packet2cf half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
@@ -47,7 +46,7 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
}; };
}; };
template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; typedef Packet2cf half; }; template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
{ {
@@ -69,6 +68,7 @@ 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,7 +81,9 @@ 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.
v2 = vrev64q_f32(v2); a_lo = vrev64_f32(vget_low_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));
} }
@@ -111,23 +113,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_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from, DenseIndex stride) template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { __pld((float *)addr); }
{
Packet4f res;
res = vsetq_lane_f32(std::real(from[0*stride]), res, 0);
res = vsetq_lane_f32(std::imag(from[0*stride]), res, 1);
res = vsetq_lane_f32(std::real(from[1*stride]), res, 2);
res = vsetq_lane_f32(std::imag(from[1*stride]), res, 3);
return Packet2cf(res);
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, DenseIndex stride)
{
to[stride*0] = std::complex<float>(vgetq_lane_f32(from.v, 0), vgetq_lane_f32(from.v, 1));
to[stride*1] = std::complex<float>(vgetq_lane_f32(from.v, 2), vgetq_lane_f32(from.v, 3));
}
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)
{ {
@@ -255,22 +241,17 @@ 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);
rev_s = vrev64q_f32(s); a_lo = vrev64_f32(vget_low_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)));
} }
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet2cf,2>& kernel) {
float32x4_t tmp = vcombine_f32(vget_high_f32(kernel.packet[0].v), vget_high_f32(kernel.packet[1].v));
kernel.packet[0].v = vcombine_f32(vget_low_f32(kernel.packet[0].v), vget_low_f32(kernel.packet[1].v));
kernel.packet[1].v = tmp;
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

View File

@@ -49,24 +49,13 @@ typedef uint32x4_t Packet4ui;
#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
{ {
typedef Packet4f type; typedef Packet4f type;
typedef Packet4f half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
@@ -84,7 +73,6 @@ template<> struct packet_traits<float> : default_packet_traits
template<> struct packet_traits<int> : default_packet_traits template<> struct packet_traits<int> : default_packet_traits
{ {
typedef Packet4i type; typedef Packet4i type;
typedef Packet4i half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
@@ -97,13 +85,12 @@ template<> struct packet_traits<int> : default_packet_traits
// workaround gcc 4.2, 4.3 and 4.4 compilatin issue // workaround gcc 4.2, 4.3 and 4.4 compilatin issue
EIGEN_STRONG_INLINE float32x4_t vld1q_f32(const float* x) { return ::vld1q_f32((const float32_t*)x); } EIGEN_STRONG_INLINE float32x4_t vld1q_f32(const float* x) { return ::vld1q_f32((const float32_t*)x); }
EIGEN_STRONG_INLINE float32x2_t vld1_f32 (const float* x) { return ::vld1_f32 ((const float32_t*)x); } EIGEN_STRONG_INLINE float32x2_t vld1_f32 (const float* x) { return ::vld1_f32 ((const float32_t*)x); }
EIGEN_STRONG_INLINE float32x2_t vld1_dup_f32 (const float* x) { return ::vld1_dup_f32 ((const float32_t*)x); }
EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q_f32((float32_t*)to,from); } EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q_f32((float32_t*)to,from); }
EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); } EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); }
#endif #endif
template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; typedef Packet4f half; }; template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; typedef Packet4i half; }; template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return vdupq_n_f32(from); } template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return vdupq_n_f32(from); }
template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return vdupq_n_s32(from); } template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return vdupq_n_s32(from); }
@@ -128,9 +115,6 @@ 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); }
@@ -204,15 +188,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 = vld1_dup_f32(from); lo = vdup_n_f32(*from);
hi = vld1_dup_f32(from+1); hi = vdup_n_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 = vld1_dup_s32(from); lo = vdup_n_s32(*from);
hi = vld1_dup_s32(from+1); hi = vdup_n_s32(*(from+1));
return vcombine_s32(lo, hi); return vcombine_s32(lo, hi);
} }
@@ -222,42 +206,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_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, DenseIndex stride) template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { __pld(addr); }
{ template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { __pld(addr); }
Packet4f res;
res = vsetq_lane_f32(from[0*stride], res, 0);
res = vsetq_lane_f32(from[1*stride], res, 1);
res = vsetq_lane_f32(from[2*stride], res, 2);
res = vsetq_lane_f32(from[3*stride], res, 3);
return res;
}
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, DenseIndex stride)
{
Packet4i res;
res = vsetq_lane_s32(from[0*stride], res, 0);
res = vsetq_lane_s32(from[1*stride], res, 1);
res = vsetq_lane_s32(from[2*stride], res, 2);
res = vsetq_lane_s32(from[3*stride], res, 3);
return res;
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, DenseIndex stride)
{
to[stride*0] = vgetq_lane_f32(from, 0);
to[stride*1] = vgetq_lane_f32(from, 1);
to[stride*2] = vgetq_lane_f32(from, 2);
to[stride*3] = vgetq_lane_f32(from, 3);
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, DenseIndex stride)
{
to[stride*0] = vgetq_lane_s32(from, 0);
to[stride*1] = vgetq_lane_s32(from, 1);
to[stride*2] = vgetq_lane_s32(from, 2);
to[stride*3] = vgetq_lane_s32(from, 3);
}
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { EIGEN_ARM_PREFETCH(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]; }
@@ -287,12 +237,15 @@ template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) { return vabsq_s
template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
{ {
float32x2_t a_lo, a_hi, sum; float32x2_t a_lo, a_hi, sum;
float s[2];
a_lo = vget_low_f32(a); a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a); a_hi = vget_high_f32(a);
sum = vpadd_f32(a_lo, a_hi); sum = vpadd_f32(a_lo, a_hi);
sum = vpadd_f32(sum, sum); sum = vpadd_f32(sum, sum);
return vget_lane_f32(sum, 0); vst1_f32(s, sum);
return s[0];
} }
template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs) template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
@@ -318,12 +271,15 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
{ {
int32x2_t a_lo, a_hi, sum; int32x2_t a_lo, a_hi, sum;
int32_t s[2];
a_lo = vget_low_s32(a); a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a); a_hi = vget_high_s32(a);
sum = vpadd_s32(a_lo, a_hi); sum = vpadd_s32(a_lo, a_hi);
sum = vpadd_s32(sum, sum); sum = vpadd_s32(sum, sum);
return vget_lane_s32(sum, 0); vst1_s32(s, sum);
return s[0];
} }
template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs) template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
@@ -351,6 +307,7 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
{ {
float32x2_t a_lo, a_hi, prod; float32x2_t a_lo, a_hi, prod;
float s[2];
// Get a_lo = |a1|a2| and a_hi = |a3|a4| // Get a_lo = |a1|a2| and a_hi = |a3|a4|
a_lo = vget_low_f32(a); a_lo = vget_low_f32(a);
@@ -359,12 +316,14 @@ template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
prod = vmul_f32(a_lo, a_hi); prod = vmul_f32(a_lo, a_hi);
// Multiply prod with its swapped value |a2*a4|a1*a3| // Multiply prod with its swapped value |a2*a4|a1*a3|
prod = vmul_f32(prod, vrev64_f32(prod)); prod = vmul_f32(prod, vrev64_f32(prod));
vst1_f32(s, prod);
return vget_lane_f32(prod, 0); return s[0];
} }
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
{ {
int32x2_t a_lo, a_hi, prod; int32x2_t a_lo, a_hi, prod;
int32_t s[2];
// Get a_lo = |a1|a2| and a_hi = |a3|a4| // Get a_lo = |a1|a2| and a_hi = |a3|a4|
a_lo = vget_low_s32(a); a_lo = vget_low_s32(a);
@@ -373,58 +332,65 @@ template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
prod = vmul_s32(a_lo, a_hi); prod = vmul_s32(a_lo, a_hi);
// Multiply prod with its swapped value |a2*a4|a1*a3| // Multiply prod with its swapped value |a2*a4|a1*a3|
prod = vmul_s32(prod, vrev64_s32(prod)); prod = vmul_s32(prod, vrev64_s32(prod));
vst1_s32(s, prod);
return vget_lane_s32(prod, 0); return s[0];
} }
// min // min
template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
{ {
float32x2_t a_lo, a_hi, min; float32x2_t a_lo, a_hi, min;
float s[2];
a_lo = vget_low_f32(a); a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a); a_hi = vget_high_f32(a);
min = vpmin_f32(a_lo, a_hi); min = vpmin_f32(a_lo, a_hi);
min = vpmin_f32(min, min); min = vpmin_f32(min, min);
vst1_f32(s, min);
return vget_lane_f32(min, 0); return s[0];
} }
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
{ {
int32x2_t a_lo, a_hi, min; int32x2_t a_lo, a_hi, min;
int32_t s[2];
a_lo = vget_low_s32(a); a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a); a_hi = vget_high_s32(a);
min = vpmin_s32(a_lo, a_hi); min = vpmin_s32(a_lo, a_hi);
min = vpmin_s32(min, min); min = vpmin_s32(min, min);
vst1_s32(s, min);
return vget_lane_s32(min, 0); return s[0];
} }
// max // max
template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
{ {
float32x2_t a_lo, a_hi, max; float32x2_t a_lo, a_hi, max;
float s[2];
a_lo = vget_low_f32(a); a_lo = vget_low_f32(a);
a_hi = vget_high_f32(a); a_hi = vget_high_f32(a);
max = vpmax_f32(a_lo, a_hi); max = vpmax_f32(a_lo, a_hi);
max = vpmax_f32(max, max); max = vpmax_f32(max, max);
vst1_f32(s, max);
return vget_lane_f32(max, 0); return s[0];
} }
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
{ {
int32x2_t a_lo, a_hi, max; int32x2_t a_lo, a_hi, max;
int32_t s[2];
a_lo = vget_low_s32(a); a_lo = vget_low_s32(a);
a_hi = vget_high_s32(a); a_hi = vget_high_s32(a);
max = vpmax_s32(a_lo, a_hi); max = vpmax_s32(a_lo, a_hi);
max = vpmax_s32(max, max); max = vpmax_s32(max, max);
vst1_s32(s, max);
return vget_lane_s32(max, 0); return s[0];
} }
// this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors, // this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors,
@@ -451,27 +417,6 @@ PALIGN_NEON(3,Packet4i,vextq_s32)
#undef PALIGN_NEON #undef PALIGN_NEON
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4f,4>& kernel) {
float32x4x2_t tmp1 = vzipq_f32(kernel.packet[0], kernel.packet[1]);
float32x4x2_t tmp2 = vzipq_f32(kernel.packet[2], kernel.packet[3]);
kernel.packet[0] = vcombine_f32(vget_low_f32(tmp1.val[0]), vget_low_f32(tmp2.val[0]));
kernel.packet[1] = vcombine_f32(vget_high_f32(tmp1.val[0]), vget_high_f32(tmp2.val[0]));
kernel.packet[2] = vcombine_f32(vget_low_f32(tmp1.val[1]), vget_low_f32(tmp2.val[1]));
kernel.packet[3] = vcombine_f32(vget_high_f32(tmp1.val[1]), vget_high_f32(tmp2.val[1]));
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4i,4>& kernel) {
int32x4x2_t tmp1 = vzipq_s32(kernel.packet[0], kernel.packet[1]);
int32x4x2_t tmp2 = vzipq_s32(kernel.packet[2], kernel.packet[3]);
kernel.packet[0] = vcombine_s32(vget_low_s32(tmp1.val[0]), vget_low_s32(tmp2.val[0]));
kernel.packet[1] = vcombine_s32(vget_high_s32(tmp1.val[0]), vget_high_s32(tmp2.val[0]));
kernel.packet[2] = vcombine_s32(vget_low_s32(tmp1.val[1]), vget_low_s32(tmp2.val[1]));
kernel.packet[3] = vcombine_s32(vget_high_s32(tmp1.val[1]), vget_high_s32(tmp2.val[1]));
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

View File

@@ -22,18 +22,13 @@ struct Packet2cf
__m128 v; __m128 v;
}; };
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going
// to leverage AVX instructions.
#ifndef EIGEN_VECTORIZE_AVX
template<> struct packet_traits<std::complex<float> > : default_packet_traits template<> struct packet_traits<std::complex<float> > : default_packet_traits
{ {
typedef Packet2cf type; typedef Packet2cf type;
typedef Packet2cf half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
size = 2, size = 2,
HasHalfPacket = 0,
HasAdd = 1, HasAdd = 1,
HasSub = 1, HasSub = 1,
@@ -47,9 +42,8 @@ template<> struct packet_traits<std::complex<float> > : default_packet_traits
HasSetLinear = 0 HasSetLinear = 0
}; };
}; };
#endif
template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; typedef Packet2cf half; }; template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_add_ps(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_add_ps(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_sub_ps(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_sub_ps(a.v,b.v)); }
@@ -87,21 +81,15 @@ 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>(&numext::real_ref(*from))); } 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 ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<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 pset1<Packet2cf>(const std::complex<float>& from) template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
{ {
Packet2cf res; Packet2cf res;
#if EIGEN_GNUC_AT_MOST(4,2) #if EIGEN_GNUC_AT_MOST(4,2)
// Workaround annoying "may be used uninitialized in this function" warning with gcc 4.2 // workaround annoying "may be used uninitialized in this function" warning with gcc 4.2
res.v = _mm_loadl_pi(_mm_set1_ps(0.0f), reinterpret_cast<const __m64*>(&from)); res.v = _mm_loadl_pi(_mm_set1_ps(0.0f), reinterpret_cast<const __m64*>(&from));
#elif EIGEN_GNUC_AT_LEAST(4,6)
// Suppress annoying "may be used uninitialized in this function" warning with gcc >= 4.6
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
res.v = _mm_loadl_pi(res.v, (const __m64*)&from);
#pragma GCC diagnostic pop
#else #else
res.v = _mm_loadl_pi(res.v, (const __m64*)&from); res.v = _mm_loadl_pi(res.v, (const __m64*)&from);
#endif #endif
@@ -110,23 +98,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(&numext::real_ref(*to), Packet4f(from.v)); } 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 pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), Packet4f(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_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from, DenseIndex stride)
{
return Packet2cf(_mm_set_ps(std::imag(from[1*stride]), std::real(from[1*stride]),
std::imag(from[0*stride]), std::real(from[0*stride])));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, DenseIndex stride)
{
to[stride*0] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 0)),
_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 1)));
to[stride*1] = std::complex<float>(_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 2)),
_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 3)));
}
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); }
@@ -145,7 +118,7 @@ template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Pack
#endif #endif
} }
template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) { return Packet2cf(_mm_castpd_ps(preverse(Packet2d(_mm_castps_pd(a.v))))); } template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) { return Packet2cf(_mm_castpd_ps(preverse(_mm_castps_pd(a.v)))); }
template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a) template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a)
{ {
@@ -235,7 +208,7 @@ template<> struct conj_helper<Packet4f, Packet2cf, false,false>
{ return padd(c, pmul(x,y)); } { return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const
{ return Packet2cf(Eigen::internal::pmul<Packet4f>(x, y.v)); } { return Packet2cf(Eigen::internal::pmul(x, y.v)); }
}; };
template<> struct conj_helper<Packet2cf, Packet4f, false,false> template<> struct conj_helper<Packet2cf, Packet4f, false,false>
@@ -244,7 +217,7 @@ template<> struct conj_helper<Packet2cf, Packet4f, false,false>
{ return padd(c, pmul(x,y)); } { return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const
{ return Packet2cf(Eigen::internal::pmul<Packet4f>(x.v, y)); } { return Packet2cf(Eigen::internal::pmul(x.v, y)); }
}; };
template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
@@ -269,18 +242,13 @@ struct Packet1cd
__m128d v; __m128d v;
}; };
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going
// to leverage AVX instructions.
#ifndef EIGEN_VECTORIZE_AVX
template<> struct packet_traits<std::complex<double> > : default_packet_traits template<> struct packet_traits<std::complex<double> > : default_packet_traits
{ {
typedef Packet1cd type; typedef Packet1cd type;
typedef Packet1cd half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 0, AlignedOnScalar = 0,
size = 1, size = 1,
HasHalfPacket = 0,
HasAdd = 1, HasAdd = 1,
HasSub = 1, HasSub = 1,
@@ -294,13 +262,12 @@ template<> struct packet_traits<std::complex<double> > : default_packet_traits
HasSetLinear = 0 HasSetLinear = 0
}; };
}; };
#endif
template<> struct unpacket_traits<Packet1cd> { typedef std::complex<double> type; enum {size=1}; typedef Packet1cd half; }; template<> struct unpacket_traits<Packet1cd> { typedef std::complex<double> type; enum {size=1}; };
template<> EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_add_pd(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_add_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_sub_pd(a.v,b.v)); } template<> EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_sub_pd(a.v,b.v)); }
template<> EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { return Packet1cd(pnegate(Packet2d(a.v))); } template<> EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { return Packet1cd(pnegate(a.v)); }
template<> EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) template<> EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a)
{ {
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0)); const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
@@ -338,8 +305,8 @@ template<> EIGEN_STRONG_INLINE Packet1cd pset1<Packet1cd>(const std::complex<dou
template<> EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) { return pset1<Packet1cd>(*from); } template<> EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) { return pset1<Packet1cd>(*from); }
// FIXME force unaligned store, this is a temporary fix // FIXME force unaligned store, this is a temporary fix
template<> EIGEN_STRONG_INLINE void pstore <std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, Packet2d(from.v)); } template<> EIGEN_STRONG_INLINE void pstore <std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); }
template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, Packet2d(from.v)); } template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); }
template<> EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
@@ -437,7 +404,7 @@ template<> struct conj_helper<Packet2d, Packet1cd, false,false>
{ return padd(c, pmul(x,y)); } { return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const
{ return Packet1cd(Eigen::internal::pmul<Packet2d>(x, y.v)); } { return Packet1cd(Eigen::internal::pmul(x, y.v)); }
}; };
template<> struct conj_helper<Packet1cd, Packet2d, false,false> template<> struct conj_helper<Packet1cd, Packet2d, false,false>
@@ -446,7 +413,7 @@ template<> struct conj_helper<Packet1cd, Packet2d, false,false>
{ return padd(c, pmul(x,y)); } { return padd(c, pmul(x,y)); }
EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const
{ return Packet1cd(Eigen::internal::pmul<Packet2d>(x.v, y)); } { return Packet1cd(Eigen::internal::pmul(x.v, y)); }
}; };
template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
@@ -459,17 +426,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, con
EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x) EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
{ {
return Packet1cd(preverse(Packet2d(x.v))); return Packet1cd(preverse(x.v));
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet2cf,2>& kernel) {
__m128d w1 = _mm_castps_pd(kernel.packet[0].v);
__m128d w2 = _mm_castps_pd(kernel.packet[1].v);
__m128 tmp = _mm_castpd_ps(_mm_unpackhi_pd(w1, w2));
kernel.packet[0].v = _mm_castpd_ps(_mm_unpacklo_pd(w1, w2));
kernel.packet[1].v = tmp;
} }
} // end namespace internal } // end namespace internal

View File

@@ -63,7 +63,7 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
x = _mm_or_ps(x, p4f_half); x = _mm_or_ps(x, p4f_half);
emm0 = _mm_sub_epi32(emm0, p4i_0x7f); emm0 = _mm_sub_epi32(emm0, p4i_0x7f);
Packet4f e = padd(Packet4f(_mm_cvtepi32_ps(emm0)), p4f_1); Packet4f e = padd(_mm_cvtepi32_ps(emm0), p4f_1);
/* part2: /* part2:
if( x < SQRTHF ) { if( x < SQRTHF ) {
@@ -72,9 +72,9 @@ Packet4f plog<Packet4f>(const Packet4f& _x)
} else { x = x - 1.0; } } else { x = x - 1.0; }
*/ */
Packet4f mask = _mm_cmplt_ps(x, p4f_cephes_SQRTHF); Packet4f mask = _mm_cmplt_ps(x, p4f_cephes_SQRTHF);
Packet4f tmp = pand(x, mask); Packet4f tmp = _mm_and_ps(x, mask);
x = psub(x, p4f_1); x = psub(x, p4f_1);
e = psub(e, pand(p4f_1, mask)); e = psub(e, _mm_and_ps(p4f_1, mask));
x = padd(x, tmp); x = padd(x, tmp);
Packet4f x2 = pmul(x,x); Packet4f x2 = pmul(x,x);
@@ -126,7 +126,7 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f); _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p4, 1.6666665459E-1f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f); _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p5, 5.0000001201E-1f);
Packet4f tmp, fx; Packet4f tmp = _mm_setzero_ps(), fx;
Packet4i emm0; Packet4i emm0;
// clamp x // clamp x
@@ -135,17 +135,13 @@ Packet4f pexp<Packet4f>(const Packet4f& _x)
/* express exp(x) as exp(g + n*log(2)) */ /* express exp(x) as exp(g + n*log(2)) */
fx = pmadd(x, p4f_cephes_LOG2EF, p4f_half); fx = pmadd(x, p4f_cephes_LOG2EF, p4f_half);
#ifdef EIGEN_VECTORIZE_SSE4_1 /* how to perform a floorf with SSE: just below */
fx = _mm_floor_ps(fx);
#else
tmp = _mm_setzero_ps();
emm0 = _mm_cvttps_epi32(fx); emm0 = _mm_cvttps_epi32(fx);
tmp = _mm_cvtepi32_ps(emm0); tmp = _mm_cvtepi32_ps(emm0);
/* if greater, substract 1 */ /* if greater, substract 1 */
Packet4f mask = _mm_cmpgt_ps(tmp, fx); Packet4f mask = _mm_cmpgt_ps(tmp, fx);
mask = _mm_and_ps(mask, p4f_1); mask = _mm_and_ps(mask, p4f_1);
fx = psub(tmp, mask); fx = psub(tmp, mask);
#endif
tmp = pmul(fx, p4f_cephes_exp_C1); tmp = pmul(fx, p4f_cephes_exp_C1);
Packet4f z = pmul(fx, p4f_cephes_exp_C2); Packet4f z = pmul(fx, p4f_cephes_exp_C2);
@@ -167,81 +163,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, Packet4f(_mm_castsi128_ps(emm0))); return pmul(y, _mm_castsi128_ps(emm0));
}
template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
Packet2d pexp<Packet2d>(const Packet2d& _x)
{
Packet2d x = _x;
_EIGEN_DECLARE_CONST_Packet2d(1 , 1.0);
_EIGEN_DECLARE_CONST_Packet2d(2 , 2.0);
_EIGEN_DECLARE_CONST_Packet2d(half, 0.5);
_EIGEN_DECLARE_CONST_Packet2d(exp_hi, 709.437);
_EIGEN_DECLARE_CONST_Packet2d(exp_lo, -709.436139303);
_EIGEN_DECLARE_CONST_Packet2d(cephes_LOG2EF, 1.4426950408889634073599);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p0, 1.26177193074810590878e-4);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p1, 3.02994407707441961300e-2);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_p2, 9.99999999999999999910e-1);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q0, 3.00198505138664455042e-6);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q1, 2.52448340349684104192e-3);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q2, 2.27265548208155028766e-1);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_q3, 2.00000000000000000009e0);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C1, 0.693145751953125);
_EIGEN_DECLARE_CONST_Packet2d(cephes_exp_C2, 1.42860682030941723212e-6);
static const __m128i p4i_1023_0 = _mm_setr_epi32(1023, 1023, 0, 0);
Packet2d tmp, fx;
Packet4i emm0;
// clamp x
x = pmax(pmin(x, p2d_exp_hi), p2d_exp_lo);
/* express exp(x) as exp(g + n*log(2)) */
fx = pmadd(p2d_cephes_LOG2EF, x, p2d_half);
#ifdef EIGEN_VECTORIZE_SSE4_1
fx = _mm_floor_pd(fx);
#else
tmp = _mm_setzero_pd();
emm0 = _mm_cvttpd_epi32(fx);
tmp = _mm_cvtepi32_pd(emm0);
/* if greater, substract 1 */
Packet2d mask = _mm_cmpgt_pd(tmp, fx);
mask = _mm_and_pd(mask, p2d_1);
fx = psub(tmp, mask);
#endif
tmp = pmul(fx, p2d_cephes_exp_C1);
Packet2d z = pmul(fx, p2d_cephes_exp_C2);
x = psub(x, tmp);
x = psub(x, z);
Packet2d x2 = pmul(x,x);
Packet2d px = p2d_cephes_exp_p0;
px = pmadd(px, x2, p2d_cephes_exp_p1);
px = pmadd(px, x2, p2d_cephes_exp_p2);
px = pmul (px, x);
Packet2d qx = p2d_cephes_exp_q0;
qx = pmadd(qx, x2, p2d_cephes_exp_q1);
qx = pmadd(qx, x2, p2d_cephes_exp_q2);
qx = pmadd(qx, x2, p2d_cephes_exp_q3);
x = pdiv(px,psub(qx,px));
x = pmadd(p2d_2,x,p2d_1);
// build 2^n
emm0 = _mm_cvttpd_epi32(fx);
emm0 = _mm_add_epi32(emm0, p4i_1023_0);
emm0 = _mm_slli_epi32(emm0, 20);
emm0 = _mm_shuffle_epi32(emm0, _MM_SHUFFLE(1,2,0,3));
return pmul(x, Packet2d(_mm_castsi128_pd(emm0)));
} }
/* evaluation of 4 sines at onces, using SSE2 intrinsics. /* evaluation of 4 sines at onces, using SSE2 intrinsics.
@@ -281,7 +203,7 @@ Packet4f psin<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f); _EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI _EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
Packet4f xmm1, xmm2, xmm3, sign_bit, y; Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y;
Packet4i emm0, emm2; Packet4i emm0, emm2;
sign_bit = x; sign_bit = x;
@@ -380,7 +302,7 @@ Packet4f pcos<Packet4f>(const Packet4f& _x)
_EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f); _EIGEN_DECLARE_CONST_Packet4f(coscof_p2, 4.166664568298827E-002f);
_EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI _EIGEN_DECLARE_CONST_Packet4f(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
Packet4f xmm1, xmm2, xmm3, y; Packet4f xmm1, xmm2 = _mm_setzero_ps(), xmm3, y;
Packet4i emm0, emm2; Packet4i emm0, emm2;
x = pabs(x); x = pabs(x);
@@ -444,32 +366,21 @@ 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_cmpge_ps(_x, pset1<Packet4f>((std::numeric_limits<float>::min)())); Packet4f non_zero_mask = _mm_cmpgt_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

242
Eigen/src/Core/arch/SSE/PacketMath.h Executable file → Normal file
View File

@@ -22,41 +22,9 @@ namespace internal {
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*)) #define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*))
#endif #endif
#ifdef EIGEN_VECTORIZE_FMA
#ifndef EIGEN_HAS_FUSED_MADD
#define EIGEN_HAS_FUSED_MADD 1
#endif
#endif
#if defined EIGEN_VECTORIZE_AVX && defined __GNUC__ && !(defined __clang__ || defined __INTEL_COMPILER)
// With GCC's default ABI version, a __m128 or __m256 are the same types and therefore we cannot
// have overloads for both types without linking error.
// One solution is to increase ABI version using -fabi-version=4 (or greater).
// To workaround this inconvenince, we rather wrap 128bit types into the following helper
// structure:
// TODO disable this wrapper if abi-versio>=4, but to detect that without asking the user to define a macro?
template<typename T>
struct eigen_packet_wrapper
{
EIGEN_ALWAYS_INLINE operator T&() { return m_val; }
EIGEN_ALWAYS_INLINE operator const T&() const { return m_val; }
EIGEN_ALWAYS_INLINE eigen_packet_wrapper() {}
EIGEN_ALWAYS_INLINE eigen_packet_wrapper(const T &v) : m_val(v) {}
EIGEN_ALWAYS_INLINE eigen_packet_wrapper& operator=(const T &v) {
m_val = v;
return *this;
}
T m_val;
};
typedef eigen_packet_wrapper<__m128> Packet4f;
typedef eigen_packet_wrapper<__m128i> Packet4i;
typedef eigen_packet_wrapper<__m128d> Packet2d;
#else
typedef __m128 Packet4f; typedef __m128 Packet4f;
typedef __m128i Packet4i; typedef __m128i Packet4i;
typedef __m128d Packet2d; typedef __m128d Packet2d;
#endif
template<> struct is_arithmetic<__m128> { enum { value = true }; }; template<> struct is_arithmetic<__m128> { enum { value = true }; };
template<> struct is_arithmetic<__m128i> { enum { value = true }; }; template<> struct is_arithmetic<__m128i> { enum { value = true }; };
@@ -80,9 +48,6 @@ template<> struct is_arithmetic<__m128d> { enum { value = true }; };
#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \ #define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \
const Packet4f p4f_##NAME = pset1<Packet4f>(X) const Packet4f p4f_##NAME = pset1<Packet4f>(X)
#define _EIGEN_DECLARE_CONST_Packet2d(NAME,X) \
const Packet2d p2d_##NAME = pset1<Packet2d>(X)
#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \ #define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
const Packet4f p4f_##NAME = _mm_castsi128_ps(pset1<Packet4i>(X)) const Packet4f p4f_##NAME = _mm_castsi128_ps(pset1<Packet4i>(X))
@@ -90,18 +55,13 @@ template<> struct is_arithmetic<__m128d> { enum { value = true }; };
const Packet4i p4i_##NAME = pset1<Packet4i>(X) const Packet4i p4i_##NAME = pset1<Packet4i>(X)
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going
// to leverage AVX instructions.
#ifndef EIGEN_VECTORIZE_AVX
template<> struct packet_traits<float> : default_packet_traits template<> struct packet_traits<float> : default_packet_traits
{ {
typedef Packet4f type; typedef Packet4f type;
typedef Packet4f half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
size=4, size=4,
HasHalfPacket = 0,
HasDiv = 1, HasDiv = 1,
HasSin = EIGEN_FAST_MATH, HasSin = EIGEN_FAST_MATH,
@@ -114,23 +74,17 @@ template<> struct packet_traits<float> : default_packet_traits
template<> struct packet_traits<double> : default_packet_traits template<> struct packet_traits<double> : default_packet_traits
{ {
typedef Packet2d type; typedef Packet2d type;
typedef Packet2d half;
enum { enum {
Vectorizable = 1, Vectorizable = 1,
AlignedOnScalar = 1, AlignedOnScalar = 1,
size=2, size=2,
HasHalfPacket = 0,
HasDiv = 1, HasDiv = 1
HasExp = 1,
HasSqrt = 1
}; };
}; };
#endif
template<> struct packet_traits<int> : default_packet_traits template<> struct packet_traits<int> : default_packet_traits
{ {
typedef Packet4i type; typedef Packet4i type;
typedef Packet4i half;
enum { enum {
// FIXME check the Has* // FIXME check the Has*
Vectorizable = 1, Vectorizable = 1,
@@ -139,9 +93,9 @@ template<> struct packet_traits<int> : default_packet_traits
}; };
}; };
template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; typedef Packet4f half; }; template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
template<> struct unpacket_traits<Packet2d> { typedef double type; enum {size=2}; typedef Packet2d half; }; template<> struct unpacket_traits<Packet2d> { typedef double type; enum {size=2}; };
template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; typedef Packet4i half; }; template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
#if defined(_MSC_VER) && (_MSC_VER==1500) #if defined(_MSC_VER) && (_MSC_VER==1500)
// Workaround MSVC 9 internal compiler error. // Workaround MSVC 9 internal compiler error.
@@ -151,26 +105,13 @@ template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { re
template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) { return _mm_set_pd(from,from); } template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) { return _mm_set_pd(from,from); }
template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return _mm_set_epi32(from,from,from,from); } template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return _mm_set_epi32(from,from,from,from); }
#else #else
template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return _mm_set_ps1(from); } template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return _mm_set1_ps(from); }
template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) { return _mm_set1_pd(from); } template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) { return _mm_set1_pd(from); }
template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return _mm_set1_epi32(from); } template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return _mm_set1_epi32(from); }
#endif #endif
// GCC generates a shufps instruction for _mm_set1_ps/_mm_load1_ps instead of the more efficient pshufd instruction.
// However, using inrinsics for pset1 makes gcc to generate crappy code in some cases (see bug 203)
// Using inline assembly is also not an option because then gcc fails to reorder properly the instructions.
// Therefore, we introduced the pload1 functions to be used in product kernels for which bug 203 does not apply.
// Also note that with AVX, we want it to generate a vbroadcastss.
#if (defined __GNUC__) && (!defined __INTEL_COMPILER) && (!defined __clang__) && (!defined __AVX__)
template<> EIGEN_STRONG_INLINE Packet4f pload1<Packet4f>(const float *from) {
return vec4f_swizzle1(_mm_load_ss(from),0,0,0,0);
}
#endif
#ifndef EIGEN_VECTORIZE_AVX
template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return _mm_add_ps(pset1<Packet4f>(a), _mm_set_ps(3,2,1,0)); } template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return _mm_add_ps(pset1<Packet4f>(a), _mm_set_ps(3,2,1,0)); }
template<> EIGEN_STRONG_INLINE Packet2d plset<double>(const double& a) { return _mm_add_pd(pset1<Packet2d>(a),_mm_set_pd(1,0)); } template<> EIGEN_STRONG_INLINE Packet2d plset<double>(const double& a) { return _mm_add_pd(pset1<Packet2d>(a),_mm_set_pd(1,0)); }
#endif
template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return _mm_add_epi32(pset1<Packet4i>(a),_mm_set_epi32(3,2,1,0)); } template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return _mm_add_epi32(pset1<Packet4i>(a),_mm_set_epi32(3,2,1,0)); }
template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_add_ps(a,b); } template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_add_ps(a,b); }
@@ -193,13 +134,9 @@ template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a)
} }
template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a)
{ {
return psub(Packet4i(_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)
@@ -227,35 +164,23 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv<Packet4i>(const Packet4i& /*a*/, co
// for some weird raisons, it has to be overloaded for packet of integers // for some weird raisons, it has to be overloaded for packet of integers
template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); } template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); }
#ifdef EIGEN_VECTORIZE_FMA
template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return _mm_fmadd_ps(a,b,c); }
template<> EIGEN_STRONG_INLINE Packet2d pmadd(const Packet2d& a, const Packet2d& b, const Packet2d& c) { return _mm_fmadd_pd(a,b,c); }
#endif
template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_min_ps(a,b); } template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_min_ps(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 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); }
@@ -276,7 +201,7 @@ template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, con
template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_ps(from); } template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_ps(from); }
template<> EIGEN_STRONG_INLINE Packet2d pload<Packet2d>(const double* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_pd(from); } template<> EIGEN_STRONG_INLINE Packet2d pload<Packet2d>(const double* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_pd(from); }
template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_si128(reinterpret_cast<const __m128i*>(from)); } template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_si128(reinterpret_cast<const Packet4i*>(from)); }
#if defined(_MSC_VER) #if defined(_MSC_VER)
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) { template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) {
@@ -294,7 +219,7 @@ template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { E
#endif #endif
} }
template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); } template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); }
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); } template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from)); }
#else #else
// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would // Fast unaligned loads. Note that here we cannot directly use intrinsics: this would
// require pointer casting to incompatible pointer types and leads to invalid code // require pointer casting to incompatible pointer types and leads to invalid code
@@ -303,17 +228,14 @@ template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { E
// TODO: do the same for MSVC (ICC is compatible) // TODO: do the same for MSVC (ICC is compatible)
// NOTE: with the code below, MSVC's compiler crashes! // NOTE: with the code below, MSVC's compiler crashes!
#if defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64) && EIGEN_GNUC_AT_LEAST(4, 8))) #if defined(__GNUC__) && defined(__i386__)
// bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd // bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
#define EIGEN_AVOID_CUSTOM_UNALIGNED_STORES 1
#elif defined(__clang__) #elif defined(__clang__)
// bug 201: Segfaults in __mm_loadh_pd with clang 2.8 // bug 201: Segfaults in __mm_loadh_pd with clang 2.8
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1 #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
#define EIGEN_AVOID_CUSTOM_UNALIGNED_STORES 0
#else #else
#define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0 #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0
#define EIGEN_AVOID_CUSTOM_UNALIGNED_STORES 0
#endif #endif
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
@@ -344,7 +266,7 @@ template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
{ {
EIGEN_DEBUG_UNALIGNED_LOAD EIGEN_DEBUG_UNALIGNED_LOAD
#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS #if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from));
#else #else
__m128d res; __m128d res;
res = _mm_load_sd((const double*)(from)) ; res = _mm_load_sd((const double*)(from)) ;
@@ -363,77 +285,38 @@ template<> EIGEN_STRONG_INLINE Packet2d ploaddup<Packet2d>(const double* from)
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from) template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
{ {
Packet4i tmp; Packet4i tmp;
tmp = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(from)); tmp = _mm_loadl_epi64(reinterpret_cast<const Packet4i*>(from));
return vec4i_swizzle1(tmp, 0, 0, 1, 1); return vec4i_swizzle1(tmp, 0, 0, 1, 1);
} }
template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_ps(to, from); } template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_ps(to, from); }
template<> EIGEN_STRONG_INLINE void pstore<double>(double* to, const Packet2d& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_pd(to, from); } template<> EIGEN_STRONG_INLINE void pstore<double>(double* to, const Packet2d& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_pd(to, from); }
template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_si128(reinterpret_cast<__m128i*>(to), from); } template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_si128(reinterpret_cast<Packet4i*>(to), from); }
template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet2d& from) { template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet2d& from) {
EIGEN_DEBUG_UNALIGNED_STORE EIGEN_DEBUG_UNALIGNED_STORE
#if EIGEN_AVOID_CUSTOM_UNALIGNED_STORES
_mm_storeu_pd(to, from);
#else
_mm_storel_pd((to), from); _mm_storel_pd((to), from);
_mm_storeh_pd((to+1), from); _mm_storeh_pd((to+1), from);
#endif
}
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast<double*>(to), Packet2d(_mm_castps_pd(from))); }
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast<double*>(to), Packet2d(_mm_castsi128_pd(from))); }
template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, DenseIndex stride)
{
return _mm_set_ps(from[3*stride], from[2*stride], from[1*stride], from[0*stride]);
}
template<> EIGEN_DEVICE_FUNC inline Packet2d pgather<double, Packet2d>(const double* from, DenseIndex stride)
{
return _mm_set_pd(from[1*stride], from[0*stride]);
}
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, DenseIndex stride)
{
return _mm_set_epi32(from[3*stride], from[2*stride], from[1*stride], from[0*stride]);
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, DenseIndex stride)
{
to[stride*0] = _mm_cvtss_f32(from);
to[stride*1] = _mm_cvtss_f32(_mm_shuffle_ps(from, from, 1));
to[stride*2] = _mm_cvtss_f32(_mm_shuffle_ps(from, from, 2));
to[stride*3] = _mm_cvtss_f32(_mm_shuffle_ps(from, from, 3));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<double, Packet2d>(double* to, const Packet2d& from, DenseIndex stride)
{
to[stride*0] = _mm_cvtsd_f64(from);
to[stride*1] = _mm_cvtsd_f64(_mm_shuffle_pd(from, from, 1));
}
template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, DenseIndex stride)
{
to[stride*0] = _mm_cvtsi128_si32(from);
to[stride*1] = _mm_cvtsi128_si32(_mm_shuffle_epi32(from, 1));
to[stride*2] = _mm_cvtsi128_si32(_mm_shuffle_epi32(from, 2));
to[stride*3] = _mm_cvtsi128_si32(_mm_shuffle_epi32(from, 3));
} }
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast<double*>(to), _mm_castps_pd(from)); }
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast<double*>(to), _mm_castsi128_pd(from)); }
// some compilers might be tempted to perform multiple moves instead of using a vector path. // some compilers might be tempted to perform multiple moves instead of using a vector path.
template<> EIGEN_STRONG_INLINE void pstore1<Packet4f>(float* to, const float& a) template<> EIGEN_STRONG_INLINE void pstore1<Packet4f>(float* to, const float& a)
{ {
Packet4f pa = _mm_set_ss(a); Packet4f pa = _mm_set_ss(a);
pstore(to, Packet4f(vec4f_swizzle1(pa,0,0,0,0))); pstore(to, vec4f_swizzle1(pa,0,0,0,0));
} }
// some compilers might be tempted to perform multiple moves instead of using a vector path. // some compilers might be tempted to perform multiple moves instead of using a vector path.
template<> EIGEN_STRONG_INLINE void pstore1<Packet2d>(double* to, const double& a) template<> EIGEN_STRONG_INLINE void pstore1<Packet2d>(double* to, const double& a)
{ {
Packet2d pa = _mm_set_sd(a); Packet2d pa = _mm_set_sd(a);
pstore(to, Packet2d(vec2d_swizzle1(pa,0,0))); pstore(to, vec2d_swizzle1(pa,0,0));
} }
#ifndef EIGEN_VECTORIZE_AVX
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
#endif
#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010 // The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
@@ -480,38 +363,6 @@ template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a)
#endif #endif
} }
// with AVX, the default implementations based on pload1 are faster
#ifndef __AVX__
template<> EIGEN_STRONG_INLINE void
pbroadcast4<Packet4f>(const float *a,
Packet4f& a0, Packet4f& a1, Packet4f& a2, Packet4f& a3)
{
a3 = pload<Packet4f>(a);
a0 = vec4f_swizzle1(a3, 0,0,0,0);
a1 = vec4f_swizzle1(a3, 1,1,1,1);
a2 = vec4f_swizzle1(a3, 2,2,2,2);
a3 = vec4f_swizzle1(a3, 3,3,3,3);
}
template<> EIGEN_STRONG_INLINE void
pbroadcast4<Packet2d>(const double *a,
Packet2d& a0, Packet2d& a1, Packet2d& a2, Packet2d& a3)
{
#ifdef EIGEN_VECTORIZE_SSE3
a0 = _mm_loaddup_pd(a+0);
a1 = _mm_loaddup_pd(a+1);
a2 = _mm_loaddup_pd(a+2);
a3 = _mm_loaddup_pd(a+3);
#else
a1 = pload<Packet2d>(a);
a0 = vec2d_swizzle1(a1, 0,0);
a1 = vec2d_swizzle1(a1, 1,1);
a3 = pload<Packet2d>(a+2);
a2 = vec2d_swizzle1(a3, 0,0);
a3 = vec2d_swizzle1(a3, 1,1);
#endif
}
#endif
EIGEN_STRONG_INLINE void punpackp(Packet4f* vecs) EIGEN_STRONG_INLINE void punpackp(Packet4f* vecs)
{ {
vecs[1] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x55)); vecs[1] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x55));
@@ -539,10 +390,10 @@ template<> EIGEN_STRONG_INLINE Packet2d preduxp<Packet2d>(const Packet2d* vecs)
template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
{ {
Packet4f tmp0 = _mm_hadd_ps(a,a); Packet4f tmp0 = _mm_hadd_ps(a,a);
return pfirst<Packet4f>(_mm_hadd_ps(tmp0, tmp0)); return pfirst(_mm_hadd_ps(tmp0, tmp0));
} }
template<> EIGEN_STRONG_INLINE double predux<Packet2d>(const Packet2d& a) { return pfirst<Packet2d>(_mm_hadd_pd(a, a)); } template<> EIGEN_STRONG_INLINE double predux<Packet2d>(const Packet2d& a) { return pfirst(_mm_hadd_pd(a, a)); }
// SSSE3 version: // SSSE3 version:
// EIGEN_STRONG_INLINE float predux(const Packet4i& a) // EIGEN_STRONG_INLINE float predux(const Packet4i& a)
@@ -585,7 +436,7 @@ template<> EIGEN_STRONG_INLINE Packet2d preduxp<Packet2d>(const Packet2d* vecs)
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
{ {
Packet4i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a)); Packet4i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a));
return pfirst(tmp) + pfirst<Packet4i>(_mm_shuffle_epi32(tmp, 1)); return pfirst(tmp) + pfirst(_mm_shuffle_epi32(tmp, 1));
} }
template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs) template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
@@ -608,11 +459,11 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
{ {
Packet4f tmp = _mm_mul_ps(a, _mm_movehl_ps(a,a)); Packet4f tmp = _mm_mul_ps(a, _mm_movehl_ps(a,a));
return pfirst<Packet4f>(_mm_mul_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); return pfirst(_mm_mul_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
} }
template<> EIGEN_STRONG_INLINE double predux_mul<Packet2d>(const Packet2d& a) template<> EIGEN_STRONG_INLINE double predux_mul<Packet2d>(const Packet2d& a)
{ {
return pfirst<Packet2d>(_mm_mul_sd(a, _mm_unpackhi_pd(a,a))); return pfirst(_mm_mul_sd(a, _mm_unpackhi_pd(a,a)));
} }
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
{ {
@@ -628,52 +479,42 @@ template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
{ {
Packet4f tmp = _mm_min_ps(a, _mm_movehl_ps(a,a)); Packet4f tmp = _mm_min_ps(a, _mm_movehl_ps(a,a));
return pfirst<Packet4f>(_mm_min_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); return pfirst(_mm_min_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
} }
template<> EIGEN_STRONG_INLINE double predux_min<Packet2d>(const Packet2d& a) template<> EIGEN_STRONG_INLINE double predux_min<Packet2d>(const Packet2d& a)
{ {
return pfirst<Packet2d>(_mm_min_sd(a, _mm_unpackhi_pd(a,a))); return pfirst(_mm_min_sd(a, _mm_unpackhi_pd(a,a)));
} }
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
{ {
#ifdef EIGEN_VECTORIZE_SSE4_1
Packet4i tmp = _mm_min_epi32(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0,0,3,2)));
return pfirst<Packet4i>(_mm_min_epi32(tmp,_mm_shuffle_epi32(tmp, 1)));
#else
// after some experiments, it is seems this is the fastest way to implement it // after some experiments, it is seems this is the fastest way to implement it
// 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);
int aux0 = aux[0]<aux[1] ? aux[0] : aux[1]; register int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
int aux2 = aux[2]<aux[3] ? aux[2] : aux[3]; register int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
return aux0<aux2 ? aux0 : aux2; return aux0<aux2 ? aux0 : aux2;
#endif // EIGEN_VECTORIZE_SSE4_1
} }
// max // max
template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a) template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
{ {
Packet4f tmp = _mm_max_ps(a, _mm_movehl_ps(a,a)); Packet4f tmp = _mm_max_ps(a, _mm_movehl_ps(a,a));
return pfirst<Packet4f>(_mm_max_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1))); return pfirst(_mm_max_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
} }
template<> EIGEN_STRONG_INLINE double predux_max<Packet2d>(const Packet2d& a) template<> EIGEN_STRONG_INLINE double predux_max<Packet2d>(const Packet2d& a)
{ {
return pfirst<Packet2d>(_mm_max_sd(a, _mm_unpackhi_pd(a,a))); return pfirst(_mm_max_sd(a, _mm_unpackhi_pd(a,a)));
} }
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a) template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
{ {
#ifdef EIGEN_VECTORIZE_SSE4_1
Packet4i tmp = _mm_max_epi32(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0,0,3,2)));
return pfirst<Packet4i>(_mm_max_epi32(tmp,_mm_shuffle_epi32(tmp, 1)));
#else
// after some experiments, it is seems this is the fastest way to implement it // after some experiments, it is seems this is the fastest way to implement it
// 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);
int aux0 = aux[0]>aux[1] ? aux[0] : aux[1]; register int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
int aux2 = aux[2]>aux[3] ? aux[2] : aux[3]; register int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
return aux0>aux2 ? aux0 : aux2; return aux0>aux2 ? aux0 : aux2;
#endif // EIGEN_VECTORIZE_SSE4_1
} }
#if (defined __GNUC__) #if (defined __GNUC__)
@@ -784,31 +625,6 @@ struct palign_impl<Offset,Packet2d>
}; };
#endif #endif
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4f,4>& kernel) {
_MM_TRANSPOSE4_PS(kernel.packet[0], kernel.packet[1], kernel.packet[2], kernel.packet[3]);
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet2d,2>& kernel) {
__m128d tmp = _mm_unpackhi_pd(kernel.packet[0], kernel.packet[1]);
kernel.packet[0] = _mm_unpacklo_pd(kernel.packet[0], kernel.packet[1]);
kernel.packet[1] = tmp;
}
EIGEN_DEVICE_FUNC inline void
ptranspose(PacketBlock<Packet4i,4>& kernel) {
__m128i T0 = _mm_unpacklo_epi32(kernel.packet[0], kernel.packet[1]);
__m128i T1 = _mm_unpacklo_epi32(kernel.packet[2], kernel.packet[3]);
__m128i T2 = _mm_unpackhi_epi32(kernel.packet[0], kernel.packet[1]);
__m128i T3 = _mm_unpackhi_epi32(kernel.packet[2], kernel.packet[3]);
kernel.packet[0] = _mm_unpacklo_epi64(T0, T1);
kernel.packet[1] = _mm_unpackhi_epi64(T0, T1);
kernel.packet[2] = _mm_unpacklo_epi64(T2, T3);
kernel.packet[3] = _mm_unpackhi_epi64(T2, T3);
}
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

View File

@@ -1,167 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 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_ASSIGNMENT_FUNCTORS_H
#define EIGEN_ASSIGNMENT_FUNCTORS_H
namespace Eigen {
namespace internal {
/** \internal
* \brief Template functor for scalar/packet assignment
*
*/
template<typename Scalar> struct assign_op {
EIGEN_EMPTY_STRUCT_CTOR(assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const { a = b; }
template<int Alignment, typename Packet>
EIGEN_STRONG_INLINE void assignPacket(Scalar* a, const Packet& b) const
{ internal::pstoret<Scalar,Packet,Alignment>(a,b); }
};
template<typename Scalar>
struct functor_traits<assign_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::ReadCost,
PacketAccess = packet_traits<Scalar>::IsVectorized
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with addition
*
*/
template<typename Scalar> struct add_assign_op {
EIGEN_EMPTY_STRUCT_CTOR(add_assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const { a += b; }
template<int Alignment, typename Packet>
EIGEN_STRONG_INLINE void assignPacket(Scalar* a, const Packet& b) const
{ internal::pstoret<Scalar,Packet,Alignment>(a,internal::padd(internal::ploadt<Packet,Alignment>(a),b)); }
};
template<typename Scalar>
struct functor_traits<add_assign_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::ReadCost + NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasAdd
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with subtraction
*
*/
template<typename Scalar> struct sub_assign_op {
EIGEN_EMPTY_STRUCT_CTOR(sub_assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const { a -= b; }
template<int Alignment, typename Packet>
EIGEN_STRONG_INLINE void assignPacket(Scalar* a, const Packet& b) const
{ internal::pstoret<Scalar,Packet,Alignment>(a,internal::psub(internal::ploadt<Packet,Alignment>(a),b)); }
};
template<typename Scalar>
struct functor_traits<sub_assign_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::ReadCost + NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasAdd
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with multiplication
*
*/
template<typename Scalar> struct mul_assign_op {
EIGEN_EMPTY_STRUCT_CTOR(mul_assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const { a *= b; }
template<int Alignment, typename Packet>
EIGEN_STRONG_INLINE void assignPacket(Scalar* a, const Packet& b) const
{ internal::pstoret<Scalar,Packet,Alignment>(a,internal::pmul(internal::ploadt<Packet,Alignment>(a),b)); }
};
template<typename Scalar>
struct functor_traits<mul_assign_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::ReadCost + NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasMul
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with diviving
*
*/
template<typename Scalar> struct div_assign_op {
EIGEN_EMPTY_STRUCT_CTOR(div_assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const { a /= b; }
template<int Alignment, typename Packet>
EIGEN_STRONG_INLINE void assignPacket(Scalar* a, const Packet& b) const
{ internal::pstoret<Scalar,Packet,Alignment>(a,internal::pdiv(internal::ploadt<Packet,Alignment>(a),b)); }
};
template<typename Scalar>
struct functor_traits<div_assign_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::ReadCost + NumTraits<Scalar>::MulCost,
PacketAccess = packet_traits<Scalar>::HasMul
};
};
/** \internal
* \brief Template functor for scalar/packet assignment with swaping
*
* It works as follow. For a non-vectorized evaluation loop, we have:
* for(i) func(A.coeffRef(i), B.coeff(i));
* where B is a SwapWrapper expression. The trick is to make SwapWrapper::coeff behaves like a non-const coeffRef.
* Actually, SwapWrapper might not even be needed since even if B is a plain expression, since it has to be writable
* B.coeff already returns a const reference to the underlying scalar value.
*
* The case of a vectorized loop is more tricky:
* for(i,j) func.assignPacket<A_Align>(&A.coeffRef(i,j), B.packet<B_Align>(i,j));
* Here, B must be a SwapWrapper whose packet function actually returns a proxy object holding a Scalar*,
* the actual alignment and Packet type.
*
*/
template<typename Scalar> struct swap_assign_op {
EIGEN_EMPTY_STRUCT_CTOR(swap_assign_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Scalar& a, const Scalar& b) const
{
using std::swap;
swap(a,const_cast<Scalar&>(b));
}
template<int LhsAlignment, int RhsAlignment, typename Packet>
EIGEN_STRONG_INLINE void swapPacket(Scalar* a, Scalar* b) const
{
Packet tmp = internal::ploadt<Packet,RhsAlignment>(b);
internal::pstoret<Scalar,Packet,RhsAlignment>(b, internal::ploadt<Packet,LhsAlignment>(a));
internal::pstoret<Scalar,Packet,LhsAlignment>(a, tmp);
}
};
template<typename Scalar>
struct functor_traits<swap_assign_op<Scalar> > {
enum {
Cost = 3 * NumTraits<Scalar>::ReadCost,
PacketAccess = packet_traits<Scalar>::IsVectorized
};
};
} // namespace internal
} // namespace Eigen
#endif // EIGEN_ASSIGNMENT_FUNCTORS_H

View File

@@ -1,456 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 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_BINARY_FUNCTORS_H
#define EIGEN_BINARY_FUNCTORS_H
namespace Eigen {
namespace internal {
//---------- associative binary functors ----------
/** \internal
* \brief Template functor to compute the sum of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, DenseBase::sum()
*/
template<typename Scalar> struct scalar_sum_op {
// typedef Scalar result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::padd(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux(a); }
};
template<typename Scalar>
struct functor_traits<scalar_sum_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasAdd
};
};
/** \internal
* \brief Template specialization to deprecate the summation of boolean expressions.
* This is required to solve Bug 426.
* \sa DenseBase::count(), DenseBase::any(), ArrayBase::cast(), MatrixBase::cast()
*/
template<> struct scalar_sum_op<bool> : scalar_sum_op<int> {
EIGEN_DEPRECATED
scalar_sum_op() {}
};
/** \internal
* \brief Template functor to compute the product of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
*/
template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
enum {
// TODO vectorize mixed product
Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
};
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmul(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
{ return internal::predux_mul(a); }
};
template<typename LhsScalar,typename RhsScalar>
struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
enum {
Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
};
};
/** \internal
* \brief Template functor to compute the conjugate product of two scalars
*
* This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
*/
template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
enum {
Conj = NumTraits<LhsScalar>::IsComplex
};
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
{ return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
};
template<typename LhsScalar,typename RhsScalar>
struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
enum {
Cost = NumTraits<LhsScalar>::MulCost,
PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
};
};
/** \internal
* \brief Template functor to compute the min of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
*/
template<typename Scalar> struct scalar_min_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { EIGEN_USING_STD_MATH(min); return (min)(a, b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmin(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux_min(a); }
};
template<typename Scalar>
struct functor_traits<scalar_min_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasMin
};
};
/** \internal
* \brief Template functor to compute the max of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
*/
template<typename Scalar> struct scalar_max_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { EIGEN_USING_STD_MATH(max); return (max)(a, b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pmax(a,b); }
template<typename Packet>
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
{ return internal::predux_max(a); }
};
template<typename Scalar>
struct functor_traits<scalar_max_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasMax
};
};
/** \internal
* \brief Template functor to compute the hypot of two scalars
*
* \sa MatrixBase::stableNorm(), class Redux
*/
template<typename Scalar> struct scalar_hypot_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
// typedef typename NumTraits<Scalar>::Real result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
{
EIGEN_USING_STD_MATH(max);
EIGEN_USING_STD_MATH(min);
using std::sqrt;
Scalar p, qp;
if(_x>_y)
{
p = _x;
qp = _y / p;
}
else
{
p = _y;
qp = _x / p;
}
return p * sqrt(Scalar(1) + qp*qp);
}
};
template<typename Scalar>
struct functor_traits<scalar_hypot_op<Scalar> > {
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
};
/** \internal
* \brief Template functor to compute the pow of two scalars
*/
template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
EIGEN_DEVICE_FUNC
inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
};
template<typename Scalar, typename OtherScalar>
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
};
//---------- non associative binary functors ----------
/** \internal
* \brief Template functor to compute the difference of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator-
*/
template<typename Scalar> struct scalar_difference_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::psub(a,b); }
};
template<typename Scalar>
struct functor_traits<scalar_difference_op<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost,
PacketAccess = packet_traits<Scalar>::HasSub
};
};
/** \internal
* \brief Template functor to compute the quotient of two scalars
*
* \sa class CwiseBinaryOp, Cwise::operator/()
*/
template<typename LhsScalar,typename RhsScalar> struct scalar_quotient_op {
enum {
// TODO vectorize mixed product
Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv
};
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
template<typename Packet>
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pdiv(a,b); }
};
template<typename LhsScalar,typename RhsScalar>
struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
enum {
Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost), // rough estimate!
PacketAccess = scalar_quotient_op<LhsScalar,RhsScalar>::Vectorizable
};
};
/** \internal
* \brief Template functor to compute the and of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator&&
*/
struct scalar_boolean_and_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
};
template<> struct functor_traits<scalar_boolean_and_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
};
/** \internal
* \brief Template functor to compute the or of two booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator||
*/
struct scalar_boolean_or_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
};
template<> struct functor_traits<scalar_boolean_or_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
};
//---------- binary functors bound to a constant, thus appearing as a unary functor ----------
/** \internal
* \brief Template functor to multiply a scalar by a fixed other one
*
* \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/
*/
/* NOTE why doing the pset1() in packetOp *is* an optimization ?
* indeed it seems better to declare m_other as a Packet and do the pset1() once
* in the constructor. However, in practice:
* - GCC does not like m_other as a Packet and generate a load every time it needs it
* - on the other hand GCC is able to moves the pset1() outside the loop :)
* - simpler code ;)
* (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
*/
template<typename Scalar>
struct scalar_multiple_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pmul(a, pset1<Packet>(m_other)); }
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
};
template<typename Scalar>
struct functor_traits<scalar_multiple_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
template<typename Scalar1, typename Scalar2>
struct scalar_multiple2_op {
typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
};
template<typename Scalar1,typename Scalar2>
struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
/** \internal
* \brief Template functor to divide a scalar by a fixed other one
*
* This functor is used to implement the quotient of a matrix by
* a scalar where the scalar type is not necessarily a floating point type.
*
* \sa class CwiseUnaryOp, MatrixBase::operator/
*/
template<typename Scalar>
struct scalar_quotient1_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
{ return internal::pdiv(a, pset1<Packet>(m_other)); }
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
};
template<typename Scalar>
struct functor_traits<scalar_quotient1_op<Scalar> >
{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
// In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication
// 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
template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
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_is_product_like<scalar_conj_product_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
* \brief Template functor to add a scalar to a fixed other one
* \sa class CwiseUnaryOp, Array::operator+
*/
/* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
template<typename Scalar>
struct scalar_add_op {
typedef typename packet_traits<Scalar>::type Packet;
// FIXME default copy constructors seems bugged with std::complex<>
EIGEN_DEVICE_FUNC inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
EIGEN_DEVICE_FUNC inline scalar_add_op(const Scalar& other) : m_other(other) { }
EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a + m_other; }
inline const Packet packetOp(const Packet& a) const
{ return internal::padd(a, pset1<Packet>(m_other)); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_add_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
/** \internal
* \brief Template functor to subtract a fixed scalar to another one
* \sa class CwiseUnaryOp, Array::operator-, struct scalar_add_op, struct scalar_rsub_op
*/
template<typename Scalar>
struct scalar_sub_op {
typedef typename packet_traits<Scalar>::type Packet;
inline scalar_sub_op(const scalar_sub_op& other) : m_other(other.m_other) { }
inline scalar_sub_op(const Scalar& other) : m_other(other) { }
inline Scalar operator() (const Scalar& a) const { return a - m_other; }
inline const Packet packetOp(const Packet& a) const
{ return internal::psub(a, pset1<Packet>(m_other)); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_sub_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
/** \internal
* \brief Template functor to subtract a scalar to fixed another one
* \sa class CwiseUnaryOp, Array::operator-, struct scalar_add_op, struct scalar_sub_op
*/
template<typename Scalar>
struct scalar_rsub_op {
typedef typename packet_traits<Scalar>::type Packet;
inline scalar_rsub_op(const scalar_rsub_op& other) : m_other(other.m_other) { }
inline scalar_rsub_op(const Scalar& other) : m_other(other) { }
inline Scalar operator() (const Scalar& a) const { return m_other - a; }
inline const Packet packetOp(const Packet& a) const
{ return internal::psub(pset1<Packet>(m_other), a); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_rsub_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
/** \internal
* \brief Template functor to raise a scalar to a power
* \sa class CwiseUnaryOp, Cwise::pow
*/
template<typename Scalar>
struct scalar_pow_op {
// 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& exponent) : m_exponent(exponent) {}
EIGEN_DEVICE_FUNC
inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
const Scalar m_exponent;
};
template<typename Scalar>
struct functor_traits<scalar_pow_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
/** \internal
* \brief Template functor to compute the quotient between a scalar and array entries.
* \sa class CwiseUnaryOp, Cwise::inverse()
*/
template<typename Scalar>
struct scalar_inverse_mult_op {
scalar_inverse_mult_op(const Scalar& other) : m_other(other) {}
EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return m_other / a; }
template<typename Packet>
inline const Packet packetOp(const Packet& a) const
{ return internal::pdiv(pset1<Packet>(m_other),a); }
Scalar m_other;
};
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_BINARY_FUNCTORS_H

View File

@@ -1,6 +0,0 @@
FILE(GLOB Eigen_Core_Functor_SRCS "*.h")
INSTALL(FILES
${Eigen_Core_Functor_SRCS}
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Core/functors COMPONENT Devel
)

View File

@@ -1,158 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 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_NULLARY_FUNCTORS_H
#define EIGEN_NULLARY_FUNCTORS_H
namespace Eigen {
namespace internal {
template<typename Scalar>
struct scalar_constant_op {
typedef typename packet_traits<Scalar>::type Packet;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); }
const Scalar m_other;
};
template<typename Scalar>
struct functor_traits<scalar_constant_op<Scalar> >
// FIXME replace this packet test by a safe one
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; };
template<typename Scalar> struct scalar_identity_op {
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
};
template<typename Scalar>
struct functor_traits<scalar_identity_op<Scalar> >
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
// linear access for packet ops:
// 1) initialization
// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
// 2) each step (where size is 1 for coeff access or PacketSize for packet access)
// base += [size*step, ..., size*step]
//
// TODO: Perhaps it's better to initialize lazily (so not in the constructor but in packetOp)
// in order to avoid the padd() in operator() ?
template <typename Scalar>
struct linspaced_op_impl<Scalar,false>
{
typedef typename packet_traits<Scalar>::type Packet;
linspaced_op_impl(const Scalar& low, const Scalar& step) :
m_low(low), m_step(step),
m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
m_base(padd(pset1<Packet>(low), pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const
{
m_base = padd(m_base, pset1<Packet>(m_step));
return m_low+Scalar(i)*m_step;
}
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
const Scalar m_low;
const Scalar m_step;
const Packet m_packetStep;
mutable Packet m_base;
};
// random access for packet ops:
// 1) each step
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
template <typename Scalar>
struct linspaced_op_impl<Scalar,true>
{
typedef typename packet_traits<Scalar>::type Packet;
linspaced_op_impl(const Scalar& low, const Scalar& step) :
m_low(low), m_step(step),
m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(Scalar(i)),m_interPacket))); }
const Scalar m_low;
const Scalar m_step;
const Packet m_lowPacket;
const Packet m_stepPacket;
const Packet m_interPacket;
};
// ----- Linspace functor ----------------------------------------------------------------
// Forward declaration (we default to random access which does not really give
// us a speed gain when using packet access but it allows to use the functor in
// nested expressions).
template <typename Scalar, bool RandomAccess = true> struct linspaced_op;
template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> >
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; };
template <typename Scalar, bool RandomAccess> struct linspaced_op
{
typedef typename packet_traits<Scalar>::type Packet;
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>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
// there row==0 and col is used for the actual iteration.
template<typename Index>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const
{
eigen_assert(col==0 || row==0);
return impl(col + row);
}
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
// there row==0 and col is used for the actual iteration.
template<typename Index>
EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
{
eigen_assert(col==0 || row==0);
return impl.packetOp(col + row);
}
// This proxy object handles the actual required temporaries, the different
// implementations (random vs. sequential access) as well as the
// correct piping to size 2/4 packet operations.
const linspaced_op_impl<Scalar,RandomAccess> impl;
};
// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
// to indicate whether a functor allows linear access, just always answering 'yes' except for
// scalar_identity_op.
// FIXME move this to functor_traits adding a functor_default
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 }; };
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_NULLARY_FUNCTORS_H

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