mirror of
https://github.com/hyblocker/OpenVR-SpaceCalibrator.git
synced 2026-10-07 01:00:26 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80e9e378e7 | ||
|
|
f88ac95a71 | ||
|
|
0667a955c2 | ||
|
|
2ba9f41be0 | ||
|
|
d4dfa26567 | ||
|
|
6b51b6ea97 | ||
|
|
23a73c2888 | ||
|
|
57a032558b | ||
|
|
8b2624cfdf | ||
|
|
08369b3ffb | ||
|
|
a71cfc3a8f | ||
|
|
d3adf9840e | ||
|
|
39e0beec3a | ||
|
|
4722698b77 | ||
|
|
d7d25b2f77 | ||
|
|
04270aa75b | ||
|
|
be38b018a9 | ||
|
|
cf5812a622 | ||
|
|
0eacd6d80f | ||
|
|
fe53a2bdc2 | ||
|
|
76cc3406f1 | ||
|
|
6e5c86245d | ||
|
|
fd6e6366c8 | ||
|
|
409ac63d02 | ||
|
|
21fdfaad75 | ||
|
|
7cde734718 | ||
|
|
68b6332fdd | ||
|
|
d4a5594300 | ||
|
|
0eca815a24 | ||
|
|
1bee2ea850 | ||
|
|
485f5b927a | ||
|
|
1398dd7ac7 | ||
|
|
cc6629ab10 | ||
|
|
8be1066339 | ||
|
|
cf8d6a4fc1 | ||
|
|
91eb9e8b15 | ||
|
|
2079a4339c | ||
|
|
5364db4c51 | ||
|
|
025ac300d6 | ||
|
|
6da5f0dd11 | ||
|
|
a1084cc48e | ||
|
|
ad6a689dad | ||
|
|
9bb647cdda | ||
|
|
5a6cd936ea | ||
|
|
3e7eaa5d58 | ||
|
|
5f5faa0ce4 | ||
|
|
f0517179fe | ||
|
|
1e8f47207b | ||
|
|
1cca795622 | ||
|
|
4ca48114e4 | ||
|
|
178293b92e | ||
|
|
a0d19f3beb | ||
|
|
5c649640d2 | ||
|
|
3f9742046d | ||
|
|
4fed033c0b | ||
|
|
d20717fe88 | ||
|
|
d2b05caa2d | ||
|
|
eefa827546 | ||
|
|
7046326c77 | ||
|
|
17a20e86c8 | ||
|
|
196fc36338 | ||
|
|
5b88a3447d | ||
|
|
8100d776b8 | ||
|
|
137d8916af | ||
|
|
ceeab0e6e2 | ||
|
|
797f65ad0d | ||
|
|
3460437924 | ||
|
|
67f7c820f5 | ||
|
|
3ac6dfc208 | ||
|
|
8b86898417 | ||
|
|
d9fb08560b | ||
|
|
0ac3ab3ad8 | ||
|
|
b0fe076845 | ||
|
|
5fba766d4d | ||
|
|
9da1c41927 | ||
|
|
31fb1d15f9 | ||
|
|
16625138e1 | ||
|
|
d0159852e1 | ||
|
|
d22b2d1c69 | ||
|
|
308641ebf2 | ||
|
|
19ed75c378 | ||
|
|
4dd9ccfc79 | ||
|
|
f578999f0e | ||
|
|
7a4dc9007d | ||
|
|
02f4aa22dc | ||
|
|
89d231472a | ||
|
|
1515312e76 | ||
|
|
7349f510ef | ||
|
|
71b82d0641 | ||
|
|
68476caafc | ||
|
|
011158cd2c | ||
|
|
a8c48136c0 | ||
|
|
dc9ada1a60 | ||
|
|
3acdbe5654 | ||
|
|
de0d3425fa | ||
|
|
3b8ea60c8a | ||
|
|
56531e0432 | ||
|
|
1c18cd5445 | ||
|
|
e371b1d13f | ||
|
|
cc4ffa774d | ||
|
|
9a0204466a | ||
|
|
71e9683dc4 | ||
|
|
f21de937f0 | ||
|
|
aecc9612e2 | ||
|
|
0e8ab54400 | ||
|
|
c5c63da491 | ||
|
|
f779d68dff | ||
|
|
20a1054111 | ||
|
|
3e3d7750f1 | ||
|
|
37a951a4cc | ||
|
|
492743e4d0 | ||
|
|
d9af36f290 | ||
|
|
98760540e6 | ||
|
|
be51eeeda1 | ||
|
|
1e8191bcf1 | ||
|
|
889cdf9828 | ||
|
|
650d86dcc3 | ||
|
|
996373e07d | ||
|
|
50ecc1af1c | ||
|
|
50991f17a8 | ||
|
|
52c166e643 | ||
|
|
9b9e2119d4 | ||
|
|
af409fbed3 | ||
|
|
51372d9f0b | ||
|
|
a732606507 | ||
|
|
ea13a5b9f7 | ||
|
|
a3dabf06bf | ||
|
|
faa0462d72 | ||
|
|
e052c85dd5 | ||
|
|
1ca0537e83 | ||
|
|
040b98a513 | ||
|
|
c4379bb84d | ||
|
|
843b01486a | ||
|
|
8969600007 | ||
|
|
bebeb0c1cd | ||
|
|
3d546f2fd2 | ||
|
|
3f170b9ff1 | ||
|
|
6969cb8c5a | ||
|
|
6f1c83dd9f | ||
|
|
fcb6f13c5f | ||
|
|
81c55df127 |
No files matched your search
+3
-4
@@ -4,7 +4,6 @@ ipch
|
||||
*.opendb
|
||||
*.aps
|
||||
*.user
|
||||
/OpenVR-SpaceCalibrator/x64/
|
||||
/OpenVR-SpaceCalibratorDriver/x64/
|
||||
/x64/
|
||||
/lib/boost*
|
||||
.code
|
||||
/install/*.exe
|
||||
[bB]in
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
[submodule "lib/minhook"]
|
||||
path = lib/minhook
|
||||
url = https://github.com/bdunderscore/minhook.git
|
||||
[submodule "lib/openvr"]
|
||||
path = lib/openvr
|
||||
url = https://github.com/ValveSoftware/openvr
|
||||
[submodule "lib/imgui"]
|
||||
path = lib/imgui
|
||||
url = https://github.com/ocornut/imgui
|
||||
[submodule "lib/implot"]
|
||||
path = lib/implot
|
||||
url = https://github.com/epezent/implot.git
|
||||
[submodule "lib/glfw"]
|
||||
path = lib/glfw
|
||||
url = https://github.com/glfw/glfw
|
||||
@@ -0,0 +1,60 @@
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Build directory
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts)
|
||||
|
||||
# Function because lazy
|
||||
function(adjust_bin_paths lib)
|
||||
set_target_properties(${lib}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts
|
||||
)
|
||||
endfunction()
|
||||
|
||||
project("SpaceCalibrator")
|
||||
|
||||
# Include project
|
||||
add_subdirectory ("src")
|
||||
|
||||
# Libs
|
||||
add_subdirectory ("lib")
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER}" MATCHES "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
# add_compile_options(-Werror=return-type -Wall -Wextra -Wpedantic /MP)
|
||||
add_compile_options(-Werror=return-type /MP)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
# add_compile_options(-Werror=return-type -Wall -Wextra -Wpedantic)
|
||||
add_compile_options(-Werror=return-type)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
|
||||
# add_compile_options(-Werror=return-type -Wall -Wextra -Wpedantic)
|
||||
add_compile_options(/Qdiag-error-return)
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
add_compile_options(
|
||||
# treat warnings as errors
|
||||
/we4715 # not all control paths return a value
|
||||
/we4828 # disallow invalid characters
|
||||
# prinf-like functions: format mismatch
|
||||
/we4473 # : not enough arguments passed for format string
|
||||
/we4474 # : too many arguments passed for format string
|
||||
/we4475 # : length modifier cannot be used with type field character in format specifier
|
||||
/we4476 # : unknown type field character in format specifier
|
||||
/we4477 # : format string requires an argument of type , but variadic argument has type
|
||||
/we4478 # : positional and non-positional placeholders cannot be mixed in the same format string
|
||||
/we4775 # nonstandard extension used in format string of function
|
||||
/we4776 # % is not allowed in the format string of function
|
||||
/we4777 # : format string requires an argument of type , but variadic argument has type
|
||||
/we4778 # : unterminated format string
|
||||
# macro arg mismatch
|
||||
/we4002 # too many actual parameters for macro 'identifier'
|
||||
/we4003 # not enough actual parameters for macro 'identifier'
|
||||
/Zc:threadSafeInit- # https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics
|
||||
/MP # multiprocessor compilation
|
||||
/utf-8 # utf-8 source & exec
|
||||
/GF) # eliminate duplicate strings
|
||||
endif()
|
||||
@@ -0,0 +1,2 @@
|
||||
@ECHO OFF
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -B bin -S .
|
||||
@@ -1,6 +1,9 @@
|
||||
== Space Calibrator ==
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Justin Li
|
||||
Copyright (c) 2023-2024 Hyblocker and other contributors
|
||||
Copyright (c) 2020-2022 Justin Li and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -19,3 +22,568 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
This software also includes components licensed as follows:
|
||||
|
||||
== MinHook ==
|
||||
|
||||
MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
================================================================================
|
||||
Hacker Disassembler Engine 32 C
|
||||
Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Hacker Disassembler Engine 64 C
|
||||
Copyright (c) 2008-2009, Vyacheslav Patkov.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
== ImGui ==
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2022 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
== ImPlot ==
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Evan Pezent
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
== glfw ==
|
||||
|
||||
Copyright (c) 2002-2006 Marcus Geelnard
|
||||
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
== gl3w ==
|
||||
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
== Eigen ==
|
||||
|
||||
Portions copyrighted by many parties; see source code for names.
|
||||
(The upstream distribution does not provide any single listing)
|
||||
|
||||
This application uses only the MPL-2.0 licensed components of Eigen.
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
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/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
@@ -0,0 +1 @@
|
||||
You may find the source code of this program at https://github.com/hyblocker/OpenVR-SpaceCalibrator . You should also have a LICENSE file alongside this one.
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenVR-SpaceCalibrator", "OpenVR-SpaceCalibrator\OpenVR-SpaceCalibrator.vcxproj", "{63BAE169-D595-4464-8E7E-50D6FD379348}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenVR-SpaceCalibratorDriver", "OpenVR-SpaceCalibratorDriver\OpenVR-SpaceCalibratorDriver.vcxproj", "{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{63BAE169-D595-4464-8E7E-50D6FD379348}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{63BAE169-D595-4464-8E7E-50D6FD379348}.Debug|x64.Build.0 = Debug|x64
|
||||
{63BAE169-D595-4464-8E7E-50D6FD379348}.Release|x64.ActiveCfg = Release|x64
|
||||
{63BAE169-D595-4464-8E7E-50D6FD379348}.Release|x64.Build.0 = Release|x64
|
||||
{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}.Debug|x64.Build.0 = Debug|x64
|
||||
{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}.Release|x64.ActiveCfg = Release|x64
|
||||
{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,519 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "Calibration.h"
|
||||
#include "Configuration.h"
|
||||
#include "IPCClient.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
|
||||
static IPCClient Driver;
|
||||
CalibrationContext CalCtx;
|
||||
|
||||
void InitCalibrator()
|
||||
{
|
||||
Driver.Connect();
|
||||
}
|
||||
|
||||
struct Pose
|
||||
{
|
||||
Eigen::Matrix3d rot;
|
||||
Eigen::Vector3d trans;
|
||||
|
||||
Pose() { }
|
||||
Pose(vr::HmdMatrix34_t hmdMatrix)
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
rot(i,j) = hmdMatrix.m[i][j];
|
||||
}
|
||||
}
|
||||
trans = Eigen::Vector3d(hmdMatrix.m[0][3], hmdMatrix.m[1][3], hmdMatrix.m[2][3]);
|
||||
}
|
||||
Pose(double x, double y, double z) : trans(Eigen::Vector3d(x,y,z)) { }
|
||||
};
|
||||
|
||||
struct Sample
|
||||
{
|
||||
Pose ref, target;
|
||||
bool valid;
|
||||
Sample() : valid(false) { }
|
||||
Sample(Pose ref, Pose target) : valid(true), ref(ref), target(target) { }
|
||||
};
|
||||
|
||||
struct DSample
|
||||
{
|
||||
bool valid;
|
||||
Eigen::Vector3d ref, target;
|
||||
};
|
||||
|
||||
bool StartsWith(const std::string &str, const std::string &prefix)
|
||||
{
|
||||
if (str.length() < prefix.length())
|
||||
return false;
|
||||
|
||||
return str.compare(0, prefix.length(), prefix) == 0;
|
||||
}
|
||||
|
||||
bool EndsWith(const std::string &str, const std::string &suffix)
|
||||
{
|
||||
if (str.length() < suffix.length())
|
||||
return false;
|
||||
|
||||
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
|
||||
}
|
||||
|
||||
Eigen::Vector3d AxisFromRotationMatrix3(Eigen::Matrix3d rot)
|
||||
{
|
||||
return Eigen::Vector3d(rot(2,1) - rot(1,2), rot(0,2) - rot(2,0), rot(1,0) - rot(0,1));
|
||||
}
|
||||
|
||||
double AngleFromRotationMatrix3(Eigen::Matrix3d rot)
|
||||
{
|
||||
return acos((rot(0,0) + rot(1,1) + rot(2,2) - 1.0) / 2.0);
|
||||
}
|
||||
|
||||
DSample DeltaRotationSamples(Sample s1, Sample s2)
|
||||
{
|
||||
// Difference in rotation between samples.
|
||||
auto dref = s1.ref.rot * s2.ref.rot.transpose();
|
||||
auto dtarget = s1.target.rot * s2.target.rot.transpose();
|
||||
|
||||
// When stuck together, the two tracked objects rotate as a pair,
|
||||
// therefore their axes of rotation must be equal between any given pair of samples.
|
||||
DSample ds;
|
||||
ds.ref = AxisFromRotationMatrix3(dref);
|
||||
ds.target = AxisFromRotationMatrix3(dtarget);
|
||||
|
||||
// Reject samples that were too close to each other.
|
||||
auto refA = AngleFromRotationMatrix3(dref);
|
||||
auto targetA = AngleFromRotationMatrix3(dtarget);
|
||||
ds.valid = refA > 0.4 && targetA > 0.4 && ds.ref.norm() > 0.01 && ds.target.norm() > 0.01;
|
||||
|
||||
ds.ref.normalize();
|
||||
ds.target.normalize();
|
||||
return ds;
|
||||
}
|
||||
|
||||
Eigen::Vector3d CalibrateRotation(const std::vector<Sample> &samples)
|
||||
{
|
||||
std::vector<DSample> deltas;
|
||||
|
||||
for (size_t i = 0; i < samples.size(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < i; j++)
|
||||
{
|
||||
auto delta = DeltaRotationSamples(samples[i], samples[j]);
|
||||
if (delta.valid)
|
||||
deltas.push_back(delta);
|
||||
}
|
||||
}
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof buf, "Got %zd samples with %zd delta samples\n", samples.size(), deltas.size());
|
||||
CalCtx.Log(buf);
|
||||
|
||||
// Kabsch algorithm
|
||||
|
||||
Eigen::MatrixXd refPoints(deltas.size(), 3), targetPoints(deltas.size(), 3);
|
||||
Eigen::Vector3d refCentroid(0,0,0), targetCentroid(0,0,0);
|
||||
|
||||
for (size_t i = 0; i < deltas.size(); i++)
|
||||
{
|
||||
refPoints.row(i) = deltas[i].ref;
|
||||
refCentroid += deltas[i].ref;
|
||||
|
||||
targetPoints.row(i) = deltas[i].target;
|
||||
targetCentroid += deltas[i].target;
|
||||
}
|
||||
|
||||
refCentroid /= (double) deltas.size();
|
||||
targetCentroid /= (double) deltas.size();
|
||||
|
||||
for (size_t i = 0; i < deltas.size(); i++)
|
||||
{
|
||||
refPoints.row(i) -= refCentroid;
|
||||
targetPoints.row(i) -= targetCentroid;
|
||||
}
|
||||
|
||||
auto crossCV = refPoints.transpose() * targetPoints;
|
||||
|
||||
Eigen::BDCSVD<Eigen::MatrixXd> bdcsvd;
|
||||
auto svd = bdcsvd.compute(crossCV, Eigen::ComputeThinU | Eigen::ComputeThinV);
|
||||
|
||||
Eigen::Matrix3d i = Eigen::Matrix3d::Identity();
|
||||
if ((svd.matrixU() * svd.matrixV().transpose()).determinant() < 0)
|
||||
{
|
||||
i(2,2) = -1;
|
||||
}
|
||||
|
||||
Eigen::Matrix3d rot = svd.matrixV() * i * svd.matrixU().transpose();
|
||||
rot.transposeInPlace();
|
||||
|
||||
Eigen::Vector3d euler = rot.eulerAngles(2, 1, 0) * 180.0 / EIGEN_PI;
|
||||
|
||||
snprintf(buf, sizeof buf, "Calibrated rotation: yaw=%.2f pitch=%.2f roll=%.2f\n", euler[1], euler[2], euler[0]);
|
||||
CalCtx.Log(buf);
|
||||
return euler;
|
||||
}
|
||||
|
||||
Eigen::Vector3d CalibrateTranslation(const std::vector<Sample> &samples)
|
||||
{
|
||||
std::vector<std::pair<Eigen::Vector3d, Eigen::Matrix3d>> deltas;
|
||||
|
||||
for (size_t i = 0; i < samples.size(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < i; j++)
|
||||
{
|
||||
auto QAi = samples[i].ref.rot.transpose();
|
||||
auto QAj = samples[j].ref.rot.transpose();
|
||||
auto dQA = QAj - QAi;
|
||||
auto CA = QAj * (samples[j].ref.trans - samples[j].target.trans) - QAi * (samples[i].ref.trans - samples[i].target.trans);
|
||||
deltas.push_back(std::make_pair(CA, dQA));
|
||||
|
||||
auto QBi = samples[i].target.rot.transpose();
|
||||
auto QBj = samples[j].target.rot.transpose();
|
||||
auto dQB = QBj - QBi;
|
||||
auto CB = QBj * (samples[j].ref.trans - samples[j].target.trans) - QBi * (samples[i].ref.trans - samples[i].target.trans);
|
||||
deltas.push_back(std::make_pair(CB, dQB));
|
||||
}
|
||||
}
|
||||
|
||||
Eigen::VectorXd constants(deltas.size() * 3);
|
||||
Eigen::MatrixXd coefficients(deltas.size() * 3, 3);
|
||||
|
||||
for (size_t i = 0; i < deltas.size(); i++)
|
||||
{
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
constants(i * 3 + axis) = deltas[i].first(axis);
|
||||
coefficients.row(i * 3 + axis) = deltas[i].second.row(axis);
|
||||
}
|
||||
}
|
||||
|
||||
Eigen::Vector3d trans = coefficients.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(constants);
|
||||
auto transcm = trans * 100.0;
|
||||
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof buf, "Calibrated translation x=%.2f y=%.2f z=%.2f\n", transcm[0], transcm[1], transcm[2]);
|
||||
CalCtx.Log(buf);
|
||||
return transcm;
|
||||
}
|
||||
|
||||
Sample CollectSample(const CalibrationContext &ctx)
|
||||
{
|
||||
vr::TrackedDevicePose_t reference, target;
|
||||
reference.bPoseIsValid = false;
|
||||
target.bPoseIsValid = false;
|
||||
|
||||
reference = ctx.devicePoses[ctx.referenceID];
|
||||
target = ctx.devicePoses[ctx.targetID];
|
||||
|
||||
bool ok = true;
|
||||
if (!reference.bPoseIsValid)
|
||||
{
|
||||
CalCtx.Log("Reference device is not tracking\n"); ok = false;
|
||||
}
|
||||
if (!target.bPoseIsValid)
|
||||
{
|
||||
CalCtx.Log("Target device is not tracking\n"); ok = false;
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
CalCtx.Log("Aborting calibration!\n");
|
||||
CalCtx.state = CalibrationState::None;
|
||||
return Sample();
|
||||
}
|
||||
|
||||
return Sample(
|
||||
Pose(reference.mDeviceToAbsoluteTracking),
|
||||
Pose(target.mDeviceToAbsoluteTracking)
|
||||
);
|
||||
}
|
||||
|
||||
vr::HmdQuaternion_t VRRotationQuat(Eigen::Vector3d eulerdeg)
|
||||
{
|
||||
auto euler = eulerdeg * EIGEN_PI / 180.0;
|
||||
|
||||
Eigen::Quaterniond rotQuat =
|
||||
Eigen::AngleAxisd(euler(0), Eigen::Vector3d::UnitZ()) *
|
||||
Eigen::AngleAxisd(euler(1), Eigen::Vector3d::UnitY()) *
|
||||
Eigen::AngleAxisd(euler(2), Eigen::Vector3d::UnitX());
|
||||
|
||||
vr::HmdQuaternion_t vrRotQuat;
|
||||
vrRotQuat.x = rotQuat.coeffs()[0];
|
||||
vrRotQuat.y = rotQuat.coeffs()[1];
|
||||
vrRotQuat.z = rotQuat.coeffs()[2];
|
||||
vrRotQuat.w = rotQuat.coeffs()[3];
|
||||
return vrRotQuat;
|
||||
}
|
||||
|
||||
vr::HmdVector3d_t VRTranslationVec(Eigen::Vector3d transcm)
|
||||
{
|
||||
auto trans = transcm * 0.01;
|
||||
vr::HmdVector3d_t vrTrans;
|
||||
vrTrans.v[0] = trans[0];
|
||||
vrTrans.v[1] = trans[1];
|
||||
vrTrans.v[2] = trans[2];
|
||||
return vrTrans;
|
||||
}
|
||||
|
||||
void ResetAndDisableOffsets(uint32_t id)
|
||||
{
|
||||
vr::HmdVector3d_t zeroV;
|
||||
zeroV.v[0] = zeroV.v[1] = zeroV.v[2] = 0;
|
||||
|
||||
vr::HmdQuaternion_t zeroQ;
|
||||
zeroQ.x = 0; zeroQ.y = 0; zeroQ.z = 0; zeroQ.w = 1;
|
||||
|
||||
protocol::Request req(protocol::RequestSetDeviceTransform);
|
||||
req.setDeviceTransform = { id, false, zeroV, zeroQ, 1.0 };
|
||||
Driver.SendBlocking(req);
|
||||
}
|
||||
|
||||
static_assert(vr::k_unTrackedDeviceIndex_Hmd == 0, "HMD index expected to be 0");
|
||||
|
||||
void ScanAndApplyProfile(CalibrationContext &ctx)
|
||||
{
|
||||
char buffer[vr::k_unMaxPropertyStringSize];
|
||||
ctx.enabled = ctx.validProfile;
|
||||
|
||||
for (uint32_t id = 0; id < vr::k_unMaxTrackedDeviceCount; ++id)
|
||||
{
|
||||
auto deviceClass = vr::VRSystem()->GetTrackedDeviceClass(id);
|
||||
if (deviceClass == vr::TrackedDeviceClass_Invalid)
|
||||
continue;
|
||||
|
||||
/*if (deviceClass == vr::TrackedDeviceClass_HMD) // for debugging unexpected universe switches
|
||||
{
|
||||
vr::ETrackedPropertyError err = vr::TrackedProp_Success;
|
||||
auto universeId = vr::VRSystem()->GetUint64TrackedDeviceProperty(id, vr::Prop_CurrentUniverseId_Uint64, &err);
|
||||
printf("uid %d err %d\n", universeId, err);
|
||||
ResetAndDisableOffsets(id);
|
||||
continue;
|
||||
}*/
|
||||
|
||||
if (!ctx.enabled)
|
||||
{
|
||||
ResetAndDisableOffsets(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
vr::ETrackedPropertyError err = vr::TrackedProp_Success;
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(id, vr::Prop_TrackingSystemName_String, buffer, vr::k_unMaxPropertyStringSize, &err);
|
||||
|
||||
if (err != vr::TrackedProp_Success)
|
||||
{
|
||||
ResetAndDisableOffsets(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string trackingSystem(buffer);
|
||||
|
||||
if (id == vr::k_unTrackedDeviceIndex_Hmd)
|
||||
{
|
||||
//auto p = ctx.devicePoses[id].mDeviceToAbsoluteTracking.m;
|
||||
//printf("HMD %d: %f %f %f\n", id, p[0][3], p[1][3], p[2][3]);
|
||||
|
||||
if (trackingSystem != ctx.referenceTrackingSystem)
|
||||
{
|
||||
// Currently using an HMD with a different tracking system than the calibration.
|
||||
ctx.enabled = false;
|
||||
}
|
||||
|
||||
ResetAndDisableOffsets(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trackingSystem != ctx.targetTrackingSystem)
|
||||
{
|
||||
ResetAndDisableOffsets(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
protocol::Request req(protocol::RequestSetDeviceTransform);
|
||||
req.setDeviceTransform = {
|
||||
id,
|
||||
true,
|
||||
VRTranslationVec(ctx.calibratedTranslation),
|
||||
VRRotationQuat(ctx.calibratedRotation),
|
||||
ctx.calibratedScale
|
||||
};
|
||||
Driver.SendBlocking(req);
|
||||
}
|
||||
|
||||
if (ctx.enabled && ctx.chaperone.valid && ctx.chaperone.autoApply)
|
||||
{
|
||||
uint32_t quadCount = 0;
|
||||
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &quadCount);
|
||||
|
||||
// Heuristic: when SteamVR resets to a blank-ish chaperone, it uses empty geometry,
|
||||
// but manual adjustments (e.g. via a play space mover) will not touch geometry.
|
||||
if (quadCount != ctx.chaperone.geometry.size())
|
||||
{
|
||||
ApplyChaperoneBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartCalibration()
|
||||
{
|
||||
CalCtx.state = CalibrationState::Begin;
|
||||
CalCtx.wantedUpdateInterval = 0.0;
|
||||
CalCtx.messages.clear();
|
||||
}
|
||||
|
||||
void CalibrationTick(double time)
|
||||
{
|
||||
if (!vr::VRSystem())
|
||||
return;
|
||||
|
||||
auto &ctx = CalCtx;
|
||||
if ((time - ctx.timeLastTick) < 0.05)
|
||||
return;
|
||||
|
||||
ctx.timeLastTick = time;
|
||||
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseRawAndUncalibrated, 0.0f, ctx.devicePoses, vr::k_unMaxTrackedDeviceCount);
|
||||
|
||||
if (ctx.state == CalibrationState::None)
|
||||
{
|
||||
ctx.wantedUpdateInterval = 1.0;
|
||||
|
||||
if ((time - ctx.timeLastScan) >= 1.0)
|
||||
{
|
||||
ScanAndApplyProfile(ctx);
|
||||
ctx.timeLastScan = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.state == CalibrationState::Editing)
|
||||
{
|
||||
ctx.wantedUpdateInterval = 0.1;
|
||||
|
||||
if ((time - ctx.timeLastScan) >= 0.1)
|
||||
{
|
||||
ScanAndApplyProfile(ctx);
|
||||
ctx.timeLastScan = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.state == CalibrationState::Begin)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
char referenceSerial[256], targetSerial[256];
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(ctx.referenceID, vr::Prop_SerialNumber_String, referenceSerial, 256);
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(ctx.targetID, vr::Prop_SerialNumber_String, targetSerial, 256);
|
||||
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof buf, "Reference device ID: %d, serial: %s\n", ctx.referenceID, referenceSerial);
|
||||
CalCtx.Log(buf);
|
||||
snprintf(buf, sizeof buf, "Target device ID: %d, serial %s\n", ctx.targetID, targetSerial);
|
||||
CalCtx.Log(buf);
|
||||
|
||||
if (ctx.referenceID == -1)
|
||||
{
|
||||
CalCtx.Log("Missing reference device\n"); ok = false;
|
||||
}
|
||||
else if (!ctx.devicePoses[ctx.referenceID].bPoseIsValid)
|
||||
{
|
||||
CalCtx.Log("Reference device is not tracking\n"); ok = false;
|
||||
}
|
||||
|
||||
if (ctx.targetID == -1)
|
||||
{
|
||||
CalCtx.Log("Missing target device\n"); ok = false;
|
||||
}
|
||||
else if (!ctx.devicePoses[ctx.targetID].bPoseIsValid)
|
||||
{
|
||||
CalCtx.Log("Target device is not tracking\n"); ok = false;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
ctx.state = CalibrationState::None;
|
||||
CalCtx.Log("Aborting calibration!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ResetAndDisableOffsets(ctx.targetID);
|
||||
ctx.state = CalibrationState::Rotation;
|
||||
ctx.wantedUpdateInterval = 0.0;
|
||||
|
||||
CalCtx.Log("Starting calibration...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
auto sample = CollectSample(ctx);
|
||||
if (!sample.valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static std::vector<Sample> samples;
|
||||
samples.push_back(sample);
|
||||
|
||||
CalCtx.Progress(samples.size(), CalCtx.SampleCount());
|
||||
|
||||
if (samples.size() == CalCtx.SampleCount())
|
||||
{
|
||||
CalCtx.Log("\n");
|
||||
if (ctx.state == CalibrationState::Rotation)
|
||||
{
|
||||
ctx.calibratedRotation = CalibrateRotation(samples);
|
||||
|
||||
auto vrRotQuat = VRRotationQuat(ctx.calibratedRotation);
|
||||
|
||||
protocol::Request req(protocol::RequestSetDeviceTransform);
|
||||
req.setDeviceTransform = { ctx.targetID, true, vrRotQuat };
|
||||
Driver.SendBlocking(req);
|
||||
|
||||
ctx.state = CalibrationState::Translation;
|
||||
}
|
||||
else if (ctx.state == CalibrationState::Translation)
|
||||
{
|
||||
ctx.calibratedTranslation = CalibrateTranslation(samples);
|
||||
|
||||
auto vrTrans = VRTranslationVec(ctx.calibratedTranslation);
|
||||
|
||||
protocol::Request req(protocol::RequestSetDeviceTransform);
|
||||
req.setDeviceTransform = { ctx.targetID, true, vrTrans };
|
||||
Driver.SendBlocking(req);
|
||||
|
||||
ctx.validProfile = true;
|
||||
SaveProfile(ctx);
|
||||
CalCtx.Log("Finished calibration, profile saved\n");
|
||||
|
||||
ctx.state = CalibrationState::None;
|
||||
}
|
||||
|
||||
samples.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void LoadChaperoneBounds()
|
||||
{
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
|
||||
uint32_t quadCount = 0;
|
||||
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &quadCount);
|
||||
|
||||
CalCtx.chaperone.geometry.resize(quadCount);
|
||||
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(&CalCtx.chaperone.geometry[0], &quadCount);
|
||||
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&CalCtx.chaperone.standingCenter);
|
||||
vr::VRChaperoneSetup()->GetWorkingPlayAreaSize(&CalCtx.chaperone.playSpaceSize.v[0], &CalCtx.chaperone.playSpaceSize.v[1]);
|
||||
CalCtx.chaperone.valid = true;
|
||||
}
|
||||
|
||||
void ApplyChaperoneBounds()
|
||||
{
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(&CalCtx.chaperone.geometry[0], CalCtx.chaperone.geometry.size());
|
||||
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&CalCtx.chaperone.standingCenter);
|
||||
vr::VRChaperoneSetup()->SetWorkingPlayAreaSize(CalCtx.chaperone.playSpaceSize.v[0], CalCtx.chaperone.playSpaceSize.v[1]);
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <openvr.h>
|
||||
#include <vector>
|
||||
|
||||
enum class CalibrationState
|
||||
{
|
||||
None,
|
||||
Begin,
|
||||
Rotation,
|
||||
Translation,
|
||||
Editing,
|
||||
};
|
||||
|
||||
struct CalibrationContext
|
||||
{
|
||||
CalibrationState state = CalibrationState::None;
|
||||
uint32_t referenceID, targetID;
|
||||
|
||||
Eigen::Vector3d calibratedRotation;
|
||||
Eigen::Vector3d calibratedTranslation;
|
||||
double calibratedScale;
|
||||
|
||||
std::string referenceTrackingSystem;
|
||||
std::string targetTrackingSystem;
|
||||
|
||||
bool enabled = false;
|
||||
bool validProfile = false;
|
||||
double timeLastTick = 0, timeLastScan = 0;
|
||||
double wantedUpdateInterval = 1.0;
|
||||
|
||||
enum Speed
|
||||
{
|
||||
FAST = 0,
|
||||
SLOW = 1,
|
||||
VERY_SLOW = 2
|
||||
};
|
||||
Speed calibrationSpeed = FAST;
|
||||
|
||||
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
|
||||
|
||||
struct Chaperone
|
||||
{
|
||||
bool valid = false;
|
||||
bool autoApply = true;
|
||||
std::vector<vr::HmdQuad_t> geometry;
|
||||
vr::HmdMatrix34_t standingCenter;
|
||||
vr::HmdVector2_t playSpaceSize;
|
||||
} chaperone;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
chaperone.geometry.clear();
|
||||
chaperone.standingCenter = vr::HmdMatrix34_t();
|
||||
chaperone.playSpaceSize = vr::HmdVector2_t();
|
||||
chaperone.valid = false;
|
||||
|
||||
calibratedRotation = Eigen::Vector3d();
|
||||
calibratedTranslation = Eigen::Vector3d();
|
||||
calibratedScale = 1.0;
|
||||
referenceTrackingSystem = "";
|
||||
targetTrackingSystem = "";
|
||||
enabled = false;
|
||||
validProfile = false;
|
||||
}
|
||||
|
||||
size_t SampleCount()
|
||||
{
|
||||
switch (calibrationSpeed)
|
||||
{
|
||||
case FAST:
|
||||
return 100;
|
||||
case SLOW:
|
||||
return 250;
|
||||
case VERY_SLOW:
|
||||
return 500;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
struct Message
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
String,
|
||||
Progress
|
||||
} type = String;
|
||||
|
||||
Message(Type type) : type(type) { }
|
||||
|
||||
std::string str;
|
||||
int progress, target;
|
||||
};
|
||||
|
||||
std::vector<Message> messages;
|
||||
|
||||
void Log(const std::string &msg)
|
||||
{
|
||||
if (messages.empty() || messages.back().type == Message::Progress)
|
||||
messages.push_back(Message(Message::String));
|
||||
|
||||
messages.back().str += msg;
|
||||
std::cerr << msg;
|
||||
}
|
||||
|
||||
void Progress(int current, int target)
|
||||
{
|
||||
if (messages.empty() || messages.back().type == Message::String)
|
||||
messages.push_back(Message(Message::Progress));
|
||||
|
||||
messages.back().progress = current;
|
||||
messages.back().target = target;
|
||||
}
|
||||
};
|
||||
|
||||
extern CalibrationContext CalCtx;
|
||||
|
||||
void InitCalibrator();
|
||||
void CalibrationTick(double time);
|
||||
void StartCalibration();
|
||||
void LoadChaperoneBounds();
|
||||
void ApplyChaperoneBounds();
|
||||
@@ -1,228 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
#include <picojson.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
static picojson::array FloatArray(const float *buf, int numFloats)
|
||||
{
|
||||
picojson::array arr;
|
||||
|
||||
for (int i = 0; i < numFloats; i++)
|
||||
arr.push_back(picojson::value(double(buf[i])));
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
static void LoadFloatArray(const picojson::value &obj, float *buf, int numFloats)
|
||||
{
|
||||
if (!obj.is<picojson::array>())
|
||||
throw std::runtime_error("expected array, got " + obj.to_str());
|
||||
|
||||
auto &arr = obj.get<picojson::array>();
|
||||
if (arr.size() != numFloats)
|
||||
throw std::runtime_error("wrong buffer size");
|
||||
|
||||
for (int i = 0; i < numFloats; i++)
|
||||
buf[i] = (float) arr[i].get<double>();
|
||||
}
|
||||
|
||||
static void ParseProfile(CalibrationContext &ctx, std::istream &stream)
|
||||
{
|
||||
picojson::value v;
|
||||
std::string err = picojson::parse(v, stream);
|
||||
if (!err.empty())
|
||||
throw std::runtime_error(err);
|
||||
|
||||
auto arr = v.get<picojson::array>();
|
||||
if (arr.size() < 1)
|
||||
throw std::runtime_error("no profiles in file");
|
||||
|
||||
auto obj = arr[0].get<picojson::object>();
|
||||
|
||||
ctx.referenceTrackingSystem = obj["reference_tracking_system"].get<std::string>();
|
||||
ctx.targetTrackingSystem = obj["target_tracking_system"].get<std::string>();
|
||||
ctx.calibratedRotation(0) = obj["roll"].get<double>();
|
||||
ctx.calibratedRotation(1) = obj["yaw"].get<double>();
|
||||
ctx.calibratedRotation(2) = obj["pitch"].get<double>();
|
||||
ctx.calibratedTranslation(0) = obj["x"].get<double>();
|
||||
ctx.calibratedTranslation(1) = obj["y"].get<double>();
|
||||
ctx.calibratedTranslation(2) = obj["z"].get<double>();
|
||||
|
||||
if (obj["scale"].is<double>())
|
||||
ctx.calibratedScale = obj["scale"].get<double>();
|
||||
else
|
||||
ctx.calibratedScale = 1.0;
|
||||
|
||||
if (obj["calibration_speed"].is<double>())
|
||||
ctx.calibrationSpeed = (CalibrationContext::Speed)(int) obj["calibration_speed"].get<double>();
|
||||
|
||||
if (obj["chaperone"].is<picojson::object>())
|
||||
{
|
||||
auto chaperone = obj["chaperone"].get<picojson::object>();
|
||||
ctx.chaperone.autoApply = chaperone["auto_apply"].get<bool>();
|
||||
|
||||
LoadFloatArray(chaperone["play_space_size"], ctx.chaperone.playSpaceSize.v, 2);
|
||||
|
||||
LoadFloatArray(
|
||||
chaperone["standing_center"],
|
||||
(float *) ctx.chaperone.standingCenter.m,
|
||||
sizeof(ctx.chaperone.standingCenter.m) / sizeof(float)
|
||||
);
|
||||
|
||||
if (!chaperone["geometry"].is<picojson::array>())
|
||||
throw std::runtime_error("chaperone geometry is not an array");
|
||||
|
||||
auto &geometry = chaperone["geometry"].get<picojson::array>();
|
||||
|
||||
if (geometry.size() > 0)
|
||||
{
|
||||
ctx.chaperone.geometry.resize(geometry.size() * sizeof(float) / sizeof(ctx.chaperone.geometry[0]));
|
||||
LoadFloatArray(chaperone["geometry"], (float *) ctx.chaperone.geometry.data(), geometry.size());
|
||||
|
||||
ctx.chaperone.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.validProfile = true;
|
||||
}
|
||||
|
||||
static void WriteProfile(CalibrationContext &ctx, std::ostream &out)
|
||||
{
|
||||
if (!ctx.validProfile)
|
||||
return;
|
||||
|
||||
picojson::object profile;
|
||||
profile["reference_tracking_system"].set<std::string>(ctx.referenceTrackingSystem);
|
||||
profile["target_tracking_system"].set<std::string>(ctx.targetTrackingSystem);
|
||||
profile["roll"].set<double>(ctx.calibratedRotation(0));
|
||||
profile["yaw"].set<double>(ctx.calibratedRotation(1));
|
||||
profile["pitch"].set<double>(ctx.calibratedRotation(2));
|
||||
profile["x"].set<double>(ctx.calibratedTranslation(0));
|
||||
profile["y"].set<double>(ctx.calibratedTranslation(1));
|
||||
profile["z"].set<double>(ctx.calibratedTranslation(2));
|
||||
profile["scale"].set<double>(ctx.calibratedScale);
|
||||
|
||||
double speed = (int) ctx.calibrationSpeed;
|
||||
profile["calibration_speed"].set<double>(speed);
|
||||
|
||||
if (ctx.chaperone.valid)
|
||||
{
|
||||
picojson::object chaperone;
|
||||
chaperone["auto_apply"].set<bool>(ctx.chaperone.autoApply);
|
||||
chaperone["play_space_size"].set<picojson::array>(FloatArray(ctx.chaperone.playSpaceSize.v, 2));
|
||||
|
||||
chaperone["standing_center"].set<picojson::array>(FloatArray(
|
||||
(float *) ctx.chaperone.standingCenter.m,
|
||||
sizeof(ctx.chaperone.standingCenter.m) / sizeof(float)
|
||||
));
|
||||
|
||||
chaperone["geometry"].set<picojson::array>(FloatArray(
|
||||
(float *) ctx.chaperone.geometry.data(),
|
||||
sizeof(ctx.chaperone.geometry[0]) / sizeof(float) * ctx.chaperone.geometry.size()
|
||||
));
|
||||
|
||||
profile["chaperone"].set<picojson::object>(chaperone);
|
||||
}
|
||||
|
||||
picojson::value profileV;
|
||||
profileV.set<picojson::object>(profile);
|
||||
|
||||
picojson::array profiles;
|
||||
profiles.push_back(profileV);
|
||||
|
||||
picojson::value profilesV;
|
||||
profilesV.set<picojson::array>(profiles);
|
||||
|
||||
out << profilesV.serialize(true);
|
||||
}
|
||||
|
||||
static void LogRegistryResult(LSTATUS result)
|
||||
{
|
||||
char *message;
|
||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, result, LANG_USER_DEFAULT, (LPSTR)&message, 0, NULL);
|
||||
std::cerr << "Opening registry key: " << message << std::endl;
|
||||
}
|
||||
|
||||
static const char *RegistryKey = "Software\\OpenVR-SpaceCalibrator";
|
||||
|
||||
static std::string ReadRegistryKey()
|
||||
{
|
||||
DWORD size = 0;
|
||||
auto result = RegGetValueA(HKEY_CURRENT_USER_LOCAL_SETTINGS, RegistryKey, "Config", RRF_RT_REG_SZ, 0, 0, &size);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
LogRegistryResult(result);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string str;
|
||||
str.resize(size);
|
||||
|
||||
result = RegGetValueA(HKEY_CURRENT_USER_LOCAL_SETTINGS, RegistryKey, "Config", RRF_RT_REG_SZ, 0, &str[0], &size);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
LogRegistryResult(result);
|
||||
return "";
|
||||
}
|
||||
|
||||
str.resize(size - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
static void WriteRegistryKey(std::string str)
|
||||
{
|
||||
HKEY hkey;
|
||||
auto result = RegCreateKeyExA(HKEY_CURRENT_USER_LOCAL_SETTINGS, RegistryKey, 0, REG_NONE, 0, KEY_ALL_ACCESS, 0, &hkey, 0);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
LogRegistryResult(result);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD size = str.size() + 1;
|
||||
|
||||
result = RegSetValueExA(hkey, "Config", 0, REG_SZ, reinterpret_cast<const BYTE*>(str.c_str()), size);
|
||||
if (result != ERROR_SUCCESS)
|
||||
LogRegistryResult(result);
|
||||
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
void LoadProfile(CalibrationContext &ctx)
|
||||
{
|
||||
ctx.validProfile = false;
|
||||
|
||||
auto str = ReadRegistryKey();
|
||||
if (str == "")
|
||||
{
|
||||
std::cout << "Profile is empty" << std::endl;
|
||||
ctx.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream io(str);
|
||||
ParseProfile(ctx, io);
|
||||
std::cout << "Loaded profile" << std::endl;
|
||||
}
|
||||
catch (const std::runtime_error &e)
|
||||
{
|
||||
std::cerr << "Error loading profile: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveProfile(CalibrationContext &ctx)
|
||||
{
|
||||
std::cout << "Saving profile to registry" << std::endl;
|
||||
|
||||
std::stringstream io;
|
||||
WriteProfile(ctx, io);
|
||||
WriteRegistryKey(io.str());
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{63BAE169-D595-4464-8E7E-50D6FD379348}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>OpenVRSpaceCalibrator</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\lib\gl3w\include;..\lib\glfw\include;..\lib\openvr;..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\lib\glfw\lib-vc2015;..\lib\openvr\lib\win64</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>openvr_api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\lib\gl3w\include;..\lib\glfw\include;..\lib\openvr;..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\lib\glfw\lib-vc2015;..\lib\openvr\lib\win64</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opengl32.lib;glfw3.lib;openvr_api.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Version.h" />
|
||||
<ClInclude Include="Calibration.h" />
|
||||
<ClInclude Include="Configuration.h" />
|
||||
<ClInclude Include="EmbeddedFiles.h" />
|
||||
<ClInclude Include="IPCClient.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="UserInterface.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\lib\gl3w\src\gl3w.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_demo.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_draw.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_impl_glfw.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_impl_opengl3.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Calibration.cpp" />
|
||||
<ClCompile Include="Configuration.cpp" />
|
||||
<ClCompile Include="EmbeddedFiles.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IPCClient.cpp" />
|
||||
<ClCompile Include="OpenVR-SpaceCalibrator.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="OpenVR-SpaceCalibrator.ico" />
|
||||
<Image Include="small.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OpenVR-SpaceCalibrator.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\ImGui">
|
||||
<UniqueIdentifier>{948e4c13-6f2b-44e3-a8b7-1a12c79aeeb7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\GL">
|
||||
<UniqueIdentifier>{d156ae5c-9fe6-41f0-a34e-333dc7a6b2f8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Calibration.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EmbeddedFiles.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UserInterface.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Configuration.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IPCClient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Calibration.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui.cpp">
|
||||
<Filter>Source Files\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_demo.cpp">
|
||||
<Filter>Source Files\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_impl_glfw.cpp">
|
||||
<Filter>Source Files\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_impl_opengl3.cpp">
|
||||
<Filter>Source Files\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\gl3w\src\gl3w.c">
|
||||
<Filter>Source Files\GL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\imgui\imgui_draw.cpp">
|
||||
<Filter>Source Files\ImGui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EmbeddedFiles.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Configuration.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IPCClient.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="OpenVR-SpaceCalibrator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="small.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="OpenVR-SpaceCalibrator.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OpenVR-SpaceCalibrator.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,503 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "UserInterface.h"
|
||||
#include "Calibration.h"
|
||||
#include "Configuration.h"
|
||||
#include "../Version.h"
|
||||
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
struct VRDevice
|
||||
{
|
||||
int id = -1;
|
||||
vr::TrackedDeviceClass deviceClass;
|
||||
std::string model = "";
|
||||
std::string serial = "";
|
||||
std::string trackingSystem = "";
|
||||
vr::ETrackedControllerRole controllerRole = vr::TrackedControllerRole_Invalid;
|
||||
};
|
||||
|
||||
struct VRState
|
||||
{
|
||||
std::vector<std::string> trackingSystems;
|
||||
std::vector<VRDevice> devices;
|
||||
};
|
||||
|
||||
void TextWithWidth(const char *label, const char *text, float width);
|
||||
|
||||
VRState LoadVRState();
|
||||
void BuildSystemSelection(const VRState &state);
|
||||
void BuildDeviceSelections(const VRState &state);
|
||||
void BuildProfileEditor();
|
||||
void BuildMenu(bool runningInOverlay);
|
||||
|
||||
static const ImGuiWindowFlags bareWindowFlags =
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove;
|
||||
|
||||
void BuildMainWindow(bool runningInOverlay)
|
||||
{
|
||||
auto &io = ImGui::GetIO();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiSetCond_Always);
|
||||
ImGui::SetNextWindowSize(io.DisplaySize, ImGuiSetCond_Always);
|
||||
|
||||
if (!ImGui::Begin("MainWindow", nullptr, bareWindowFlags))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImGui::GetStyleColorVec4(ImGuiCol_Button));
|
||||
|
||||
auto state = LoadVRState();
|
||||
BuildSystemSelection(state);
|
||||
BuildDeviceSelections(state);
|
||||
BuildMenu(runningInOverlay);
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void BuildMenu(bool runningInOverlay)
|
||||
{
|
||||
auto &io = ImGui::GetIO();
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
ImGui::Text("");
|
||||
|
||||
if (CalCtx.state == CalibrationState::None)
|
||||
{
|
||||
if (CalCtx.validProfile && !CalCtx.enabled)
|
||||
{
|
||||
ImGui::TextColored(ImColor(0.8f, 0.2f, 0.2f), "Reference (%s) HMD not detected, profile disabled", CalCtx.referenceTrackingSystem.c_str());
|
||||
ImGui::Text("");
|
||||
}
|
||||
|
||||
float width = ImGui::GetWindowContentRegionWidth(), scale = 1.0f;
|
||||
if (CalCtx.validProfile)
|
||||
{
|
||||
width -= style.FramePadding.x * 4.0f;
|
||||
scale = 1.0f / 3.0f;
|
||||
}
|
||||
|
||||
if (ImGui::Button("Start Calibration", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
ImGui::OpenPopup("Calibration Progress");
|
||||
StartCalibration();
|
||||
}
|
||||
|
||||
if (CalCtx.validProfile)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Edit Calibration", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
CalCtx.state = CalibrationState::Editing;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Clear Calibration", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
CalCtx.Clear();
|
||||
SaveProfile(CalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
width = ImGui::GetWindowContentRegionWidth();
|
||||
scale = 1.0f;
|
||||
if (CalCtx.chaperone.valid)
|
||||
{
|
||||
width -= style.FramePadding.x * 2.0f;
|
||||
scale = 0.5;
|
||||
}
|
||||
|
||||
ImGui::Text("");
|
||||
if (ImGui::Button("Copy Chaperone Bounds to profile", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
LoadChaperoneBounds();
|
||||
SaveProfile(CalCtx);
|
||||
}
|
||||
|
||||
if (CalCtx.chaperone.valid)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Paste Chaperone Bounds", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
ApplyChaperoneBounds();
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(" Paste Chaperone Bounds automatically when geometry resets", &CalCtx.chaperone.autoApply))
|
||||
{
|
||||
SaveProfile(CalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("");
|
||||
auto speed = CalCtx.calibrationSpeed;
|
||||
|
||||
ImGui::Columns(4, NULL, false);
|
||||
ImGui::Text("Calibration Speed");
|
||||
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(" Fast ", speed == CalibrationContext::FAST))
|
||||
CalCtx.calibrationSpeed = CalibrationContext::FAST;
|
||||
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(" Slow ", speed == CalibrationContext::SLOW))
|
||||
CalCtx.calibrationSpeed = CalibrationContext::SLOW;
|
||||
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(" Very Slow ", speed == CalibrationContext::VERY_SLOW))
|
||||
CalCtx.calibrationSpeed = CalibrationContext::VERY_SLOW;
|
||||
|
||||
ImGui::Columns(1);
|
||||
}
|
||||
else if (CalCtx.state == CalibrationState::Editing)
|
||||
{
|
||||
BuildProfileEditor();
|
||||
|
||||
if (ImGui::Button("Save Profile", ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetTextLineHeight() * 2)))
|
||||
{
|
||||
SaveProfile(CalCtx);
|
||||
CalCtx.state = CalibrationState::None;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Button("Calibration in progress...", ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetTextLineHeight() * 2));
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(10.0f, ImGui::GetWindowHeight() - ImGui::GetItemsLineHeightWithSpacing()));
|
||||
ImGui::BeginChild("bottom line", ImVec2(ImGui::GetWindowWidth() - 20.0f, ImGui::GetItemsLineHeightWithSpacing() * 2), false);
|
||||
ImGui::Text("OpenVR Space Calibrator v" SPACECAL_VERSION_STRING " - by tach/pushrax");
|
||||
if (runningInOverlay)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("- close VR overlay to use mouse");
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiSetCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x - 40.0f, io.DisplaySize.y - 40.0f), ImGuiSetCond_Always);
|
||||
if (ImGui::BeginPopupModal("Calibration Progress", nullptr, bareWindowFlags))
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor(0, 0, 0));
|
||||
for (auto &message : CalCtx.messages)
|
||||
{
|
||||
switch (message.type)
|
||||
{
|
||||
case CalibrationContext::Message::String:
|
||||
ImGui::TextWrapped(message.str.c_str());
|
||||
break;
|
||||
case CalibrationContext::Message::Progress:
|
||||
float fraction = (float)message.progress / (float)message.target;
|
||||
ImGui::Text("");
|
||||
ImGui::ProgressBar(fraction, ImVec2(-1.0f, 0.0f), "");
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetFontSize() - style.FramePadding.y * 2);
|
||||
ImGui::Text(" %d%%", (int)(fraction * 100));
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (CalCtx.state == CalibrationState::None)
|
||||
{
|
||||
ImGui::Text("");
|
||||
if (ImGui::Button("Close", ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetTextLineHeight() * 2)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSystemSelection(const VRState &state)
|
||||
{
|
||||
if (state.trackingSystems.empty())
|
||||
{
|
||||
ImGui::Text("No tracked devices are present");
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
float paneWidth = ImGui::GetWindowContentRegionWidth() / 2 - style.FramePadding.x;
|
||||
|
||||
TextWithWidth("ReferenceSystemLabel", "Reference Space", paneWidth);
|
||||
ImGui::SameLine();
|
||||
TextWithWidth("TargetSystemLabel", "Target Space", paneWidth);
|
||||
|
||||
int currentReferenceSystem = -1;
|
||||
int currentTargetSystem = -1;
|
||||
int firstReferenceSystemNotTargetSystem = -1;
|
||||
|
||||
std::vector<const char *> referenceSystems;
|
||||
for (auto &str : state.trackingSystems)
|
||||
{
|
||||
if (str == CalCtx.referenceTrackingSystem)
|
||||
{
|
||||
currentReferenceSystem = (int) referenceSystems.size();
|
||||
}
|
||||
else if (firstReferenceSystemNotTargetSystem == -1 && str != CalCtx.targetTrackingSystem)
|
||||
{
|
||||
firstReferenceSystemNotTargetSystem = (int) referenceSystems.size();
|
||||
}
|
||||
referenceSystems.push_back(str.c_str());
|
||||
}
|
||||
|
||||
if (currentReferenceSystem == -1 && CalCtx.referenceTrackingSystem == "")
|
||||
{
|
||||
currentReferenceSystem = firstReferenceSystemNotTargetSystem;
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(paneWidth);
|
||||
ImGui::Combo("##ReferenceTrackingSystem", ¤tReferenceSystem, &referenceSystems[0], (int) referenceSystems.size());
|
||||
|
||||
if (currentReferenceSystem != -1 && currentReferenceSystem < (int) referenceSystems.size())
|
||||
{
|
||||
CalCtx.referenceTrackingSystem = std::string(referenceSystems[currentReferenceSystem]);
|
||||
if (CalCtx.referenceTrackingSystem == CalCtx.targetTrackingSystem)
|
||||
CalCtx.targetTrackingSystem = "";
|
||||
}
|
||||
|
||||
if (CalCtx.targetTrackingSystem == "")
|
||||
currentTargetSystem = 0;
|
||||
|
||||
std::vector<const char *> targetSystems;
|
||||
for (auto &str : state.trackingSystems)
|
||||
{
|
||||
if (str != CalCtx.referenceTrackingSystem)
|
||||
{
|
||||
if (str != "" && str == CalCtx.targetTrackingSystem)
|
||||
currentTargetSystem = (int) targetSystems.size();
|
||||
targetSystems.push_back(str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##TargetTrackingSystem", ¤tTargetSystem, &targetSystems[0], (int) targetSystems.size());
|
||||
|
||||
if (currentTargetSystem != -1 && currentTargetSystem < targetSystems.size())
|
||||
{
|
||||
CalCtx.targetTrackingSystem = std::string(targetSystems[currentTargetSystem]);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void AppendSeparated(std::string &buffer, const std::string &suffix)
|
||||
{
|
||||
if (!buffer.empty())
|
||||
buffer += " | ";
|
||||
buffer += suffix;
|
||||
}
|
||||
|
||||
std::string LabelString(const VRDevice &device)
|
||||
{
|
||||
std::string label;
|
||||
|
||||
/*if (device.controllerRole == vr::TrackedControllerRole_LeftHand)
|
||||
label = "Left Controller";
|
||||
else if (device.controllerRole == vr::TrackedControllerRole_RightHand)
|
||||
label = "Right Controller";
|
||||
else if (device.deviceClass == vr::TrackedDeviceClass_Controller)
|
||||
label = "Controller";
|
||||
else if (device.deviceClass == vr::TrackedDeviceClass_HMD)
|
||||
label = "HMD";
|
||||
else if (device.deviceClass == vr::TrackedDeviceClass_GenericTracker)
|
||||
label = "Tracker";*/
|
||||
|
||||
AppendSeparated(label, device.model);
|
||||
AppendSeparated(label, device.serial);
|
||||
return label;
|
||||
}
|
||||
|
||||
void BuildDeviceSelection(const VRState &state, int &selected, const std::string &system)
|
||||
{
|
||||
ImGui::TextColored(ImColor(0.5f, 0.5f, 0.5f), "Devices from: %s", system.c_str());
|
||||
|
||||
if (selected != -1)
|
||||
{
|
||||
bool matched = false;
|
||||
for (auto &device : state.devices)
|
||||
{
|
||||
if (device.trackingSystem != system)
|
||||
continue;
|
||||
|
||||
if (selected == device.id)
|
||||
{
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
{
|
||||
// Device is no longer present.
|
||||
selected = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected == -1)
|
||||
{
|
||||
for (auto &device : state.devices)
|
||||
{
|
||||
if (device.trackingSystem != system)
|
||||
continue;
|
||||
|
||||
if (device.controllerRole == vr::TrackedControllerRole_LeftHand)
|
||||
{
|
||||
selected = device.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &device : state.devices)
|
||||
{
|
||||
if (device.trackingSystem != system)
|
||||
continue;
|
||||
|
||||
if (selected == -1)
|
||||
selected = device.id;
|
||||
|
||||
auto label = LabelString(device);
|
||||
if (ImGui::Selectable(label.c_str(), selected == device.id))
|
||||
selected = device.id;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildDeviceSelections(const VRState &state)
|
||||
{
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
ImVec2 paneSize(ImGui::GetWindowContentRegionWidth() / 2 - style.FramePadding.x, ImGui::GetTextLineHeightWithSpacing() * 5 + style.ItemSpacing.y * 4);
|
||||
|
||||
ImGui::BeginChild("left device pane", paneSize, true);
|
||||
static int selectedRefDevice = -1;
|
||||
BuildDeviceSelection(state, selectedRefDevice, CalCtx.referenceTrackingSystem);
|
||||
CalCtx.referenceID = selectedRefDevice;
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginChild("right device pane", paneSize, true);
|
||||
static int selectedCalDevice = -1;
|
||||
BuildDeviceSelection(state, selectedCalDevice, CalCtx.targetTrackingSystem);
|
||||
CalCtx.targetID = selectedCalDevice;
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button("Identify selected devices (blinks LED or vibrates)", ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetTextLineHeightWithSpacing() + 4.0f)))
|
||||
{
|
||||
for (unsigned i = 0; i < 100; ++i)
|
||||
{
|
||||
vr::VRSystem()->TriggerHapticPulse(CalCtx.targetID, 0, 2000);
|
||||
vr::VRSystem()->TriggerHapticPulse(CalCtx.referenceID, 0, 2000);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VRState LoadVRState()
|
||||
{
|
||||
VRState state;
|
||||
auto &trackingSystems = state.trackingSystems;
|
||||
|
||||
char buffer[vr::k_unMaxPropertyStringSize];
|
||||
|
||||
for (uint32_t id = 0; id < vr::k_unMaxTrackedDeviceCount; ++id)
|
||||
{
|
||||
vr::ETrackedPropertyError err = vr::TrackedProp_Success;
|
||||
auto deviceClass = vr::VRSystem()->GetTrackedDeviceClass(id);
|
||||
if (deviceClass == vr::TrackedDeviceClass_Invalid)
|
||||
continue;
|
||||
|
||||
if (deviceClass != vr::TrackedDeviceClass_TrackingReference)
|
||||
{
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(id, vr::Prop_TrackingSystemName_String, buffer, vr::k_unMaxPropertyStringSize, &err);
|
||||
|
||||
if (err == vr::TrackedProp_Success)
|
||||
{
|
||||
std::string system(buffer);
|
||||
auto existing = std::find(trackingSystems.begin(), trackingSystems.end(), system);
|
||||
if (existing != trackingSystems.end())
|
||||
{
|
||||
if (deviceClass == vr::TrackedDeviceClass_HMD)
|
||||
{
|
||||
trackingSystems.erase(existing);
|
||||
trackingSystems.insert(trackingSystems.begin(), system);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trackingSystems.push_back(system);
|
||||
}
|
||||
|
||||
VRDevice device;
|
||||
device.id = id;
|
||||
device.deviceClass = deviceClass;
|
||||
device.trackingSystem = system;
|
||||
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(id, vr::Prop_ModelNumber_String, buffer, vr::k_unMaxPropertyStringSize, &err);
|
||||
device.model = std::string(buffer);
|
||||
|
||||
vr::VRSystem()->GetStringTrackedDeviceProperty(id, vr::Prop_SerialNumber_String, buffer, vr::k_unMaxPropertyStringSize, &err);
|
||||
device.serial = std::string(buffer);
|
||||
|
||||
device.controllerRole = (vr::ETrackedControllerRole) vr::VRSystem()->GetInt32TrackedDeviceProperty(id, vr::Prop_ControllerRoleHint_Int32, &err);
|
||||
state.devices.push_back(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("failed to get tracking system name for id %d\n", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void BuildProfileEditor()
|
||||
{
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
float width = ImGui::GetWindowContentRegionWidth() / 3.0f - style.FramePadding.x;
|
||||
float widthF = width - style.FramePadding.x;
|
||||
|
||||
TextWithWidth("YawLabel", "Yaw", width);
|
||||
ImGui::SameLine();
|
||||
TextWithWidth("PitchLabel", "Pitch", width);
|
||||
ImGui::SameLine();
|
||||
TextWithWidth("RollLabel", "Roll", width);
|
||||
|
||||
ImGui::PushItemWidth(widthF);
|
||||
ImGui::InputDouble("##Yaw", &CalCtx.calibratedRotation(1), 0.1, 1.0, "%.8f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputDouble("##Pitch", &CalCtx.calibratedRotation(2), 0.1, 1.0, "%.8f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputDouble("##Roll", &CalCtx.calibratedRotation(0), 0.1, 1.0, "%.8f");
|
||||
|
||||
TextWithWidth("XLabel", "X", width);
|
||||
ImGui::SameLine();
|
||||
TextWithWidth("YLabel", "Y", width);
|
||||
ImGui::SameLine();
|
||||
TextWithWidth("ZLabel", "Z", width);
|
||||
|
||||
ImGui::InputDouble("##X", &CalCtx.calibratedTranslation(0), 1.0, 10.0, "%.8f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputDouble("##Y", &CalCtx.calibratedTranslation(1), 1.0, 10.0, "%.8f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputDouble("##Z", &CalCtx.calibratedTranslation(2), 1.0, 10.0, "%.8f");
|
||||
|
||||
TextWithWidth("ScaleLabel", "Scale", width);
|
||||
|
||||
ImGui::InputDouble("##Scale", &CalCtx.calibratedScale, 0.0001, 0.01, "%.8f");
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void TextWithWidth(const char *label, const char *text, float width)
|
||||
{
|
||||
ImGui::BeginChild(label, ImVec2(width, ImGui::GetTextLineHeightWithSpacing()));
|
||||
ImGui::Text(text);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
void BuildMainWindow(bool runningInOverlay);
|
||||
Binary file not shown.
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A61324AD-CE32-46D1-A95E-7E28A6D8CCA7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>OpenVRSpaceCalibratorDriver</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>driver_01spacecalibrator</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>driver_01spacecalibrator</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;OPENVRSPACECALIBRATORDRIVER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\lib\openvr;..\lib\MinHook\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\lib\MinHook\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libMinHook-x64-v140-mdd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;OPENVRSPACECALIBRATORDRIVER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\lib\openvr;..\lib\MinHook\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\lib\MinHook\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libMinHook-x64-v141-md.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Protocol.h" />
|
||||
<ClInclude Include="Hooking.h" />
|
||||
<ClInclude Include="InterfaceHookInjector.h" />
|
||||
<ClInclude Include="IPCServer.h" />
|
||||
<ClInclude Include="Logging.h" />
|
||||
<ClInclude Include="OpenVR-SpaceCalibratorDriver.h" />
|
||||
<ClInclude Include="ServerTrackedDeviceProvider.h" />
|
||||
<ClInclude Include="VRWatchdogProvider.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Hooking.cpp" />
|
||||
<ClCompile Include="InterfaceHookInjector.cpp" />
|
||||
<ClCompile Include="IPCServer.cpp" />
|
||||
<ClCompile Include="Logging.cpp" />
|
||||
<ClCompile Include="OpenVR-SpaceCalibratorDriver.cpp" />
|
||||
<ClCompile Include="ServerTrackedDeviceProvider.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="OpenVR-SpaceCalibratorDriver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Logging.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ServerTrackedDeviceProvider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VRWatchdogProvider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IPCServer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Protocol.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Hooking.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InterfaceHookInjector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="OpenVR-SpaceCalibratorDriver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Logging.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ServerTrackedDeviceProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IPCServer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Hooking.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InterfaceHookInjector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,75 +0,0 @@
|
||||
#include "ServerTrackedDeviceProvider.h"
|
||||
#include "Logging.h"
|
||||
#include "InterfaceHookInjector.h"
|
||||
|
||||
vr::EVRInitError ServerTrackedDeviceProvider::Init(vr::IVRDriverContext *pDriverContext)
|
||||
{
|
||||
TRACE("ServerTrackedDeviceProvider::Init()");
|
||||
VR_INIT_SERVER_DRIVER_CONTEXT(pDriverContext);
|
||||
|
||||
memset(transforms, 0, vr::k_unMaxTrackedDeviceCount * sizeof DeviceTransform);
|
||||
|
||||
InjectHooks(this, pDriverContext);
|
||||
server.Run();
|
||||
|
||||
return vr::VRInitError_None;
|
||||
}
|
||||
|
||||
void ServerTrackedDeviceProvider::Cleanup()
|
||||
{
|
||||
TRACE("ServerTrackedDeviceProvider::Cleanup()");
|
||||
server.Stop();
|
||||
DisableHooks();
|
||||
VR_CLEANUP_SERVER_DRIVER_CONTEXT();
|
||||
}
|
||||
|
||||
inline vr::HmdQuaternion_t operator*(const vr::HmdQuaternion_t &lhs, const vr::HmdQuaternion_t &rhs) {
|
||||
return {
|
||||
(lhs.w * rhs.w) - (lhs.x * rhs.x) - (lhs.y * rhs.y) - (lhs.z * rhs.z),
|
||||
(lhs.w * rhs.x) + (lhs.x * rhs.w) + (lhs.y * rhs.z) - (lhs.z * rhs.y),
|
||||
(lhs.w * rhs.y) + (lhs.y * rhs.w) + (lhs.z * rhs.x) - (lhs.x * rhs.z),
|
||||
(lhs.w * rhs.z) + (lhs.z * rhs.w) + (lhs.x * rhs.y) - (lhs.y * rhs.x)
|
||||
};
|
||||
}
|
||||
|
||||
inline vr::HmdVector3d_t quaternionRotateVector(const vr::HmdQuaternion_t& quat, const double(&vector)[3]) {
|
||||
vr::HmdQuaternion_t vectorQuat = { 0.0, vector[0], vector[1] , vector[2] };
|
||||
vr::HmdQuaternion_t conjugate = { quat.w, -quat.x, -quat.y, -quat.z };
|
||||
auto rotatedVectorQuat = quat * vectorQuat * conjugate;
|
||||
return { rotatedVectorQuat.x, rotatedVectorQuat.y, rotatedVectorQuat.z };
|
||||
}
|
||||
|
||||
void ServerTrackedDeviceProvider::SetDeviceTransform(const protocol::SetDeviceTransform &newTransform)
|
||||
{
|
||||
auto &tf = transforms[newTransform.openVRID];
|
||||
tf.enabled = newTransform.enabled;
|
||||
|
||||
if (newTransform.updateTranslation)
|
||||
tf.translation = newTransform.translation;
|
||||
|
||||
if (newTransform.updateRotation)
|
||||
tf.rotation = newTransform.rotation;
|
||||
|
||||
if (newTransform.updateScale)
|
||||
tf.scale = newTransform.scale;
|
||||
}
|
||||
|
||||
bool ServerTrackedDeviceProvider::HandleDevicePoseUpdated(uint32_t openVRID, vr::DriverPose_t &pose)
|
||||
{
|
||||
auto &tf = transforms[openVRID];
|
||||
if (tf.enabled)
|
||||
{
|
||||
pose.qWorldFromDriverRotation = tf.rotation * pose.qWorldFromDriverRotation;
|
||||
|
||||
pose.vecPosition[0] *= tf.scale;
|
||||
pose.vecPosition[1] *= tf.scale;
|
||||
pose.vecPosition[2] *= tf.scale;
|
||||
|
||||
vr::HmdVector3d_t rotatedTranslation = quaternionRotateVector(tf.rotation, pose.vecWorldFromDriverTranslation);
|
||||
pose.vecWorldFromDriverTranslation[0] = rotatedTranslation.v[0] + tf.translation.v[0];
|
||||
pose.vecWorldFromDriverTranslation[1] = rotatedTranslation.v[1] + tf.translation.v[1];
|
||||
pose.vecWorldFromDriverTranslation[2] = rotatedTranslation.v[2] + tf.translation.v[2];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef _OPENVR_API
|
||||
#include <openvr_driver.h>
|
||||
#endif
|
||||
|
||||
#define OPENVR_SPACECALIBRATOR_PIPE_NAME "\\\\.\\pipe\\OpenVRSpaceCalibratorDriver"
|
||||
|
||||
namespace protocol
|
||||
{
|
||||
const uint32_t Version = 2;
|
||||
|
||||
enum RequestType
|
||||
{
|
||||
RequestInvalid,
|
||||
RequestHandshake,
|
||||
RequestSetDeviceTransform,
|
||||
};
|
||||
|
||||
enum ResponseType
|
||||
{
|
||||
ResponseInvalid,
|
||||
ResponseHandshake,
|
||||
ResponseSuccess,
|
||||
};
|
||||
|
||||
struct Protocol
|
||||
{
|
||||
uint32_t version = Version;
|
||||
};
|
||||
|
||||
struct SetDeviceTransform
|
||||
{
|
||||
uint32_t openVRID;
|
||||
bool enabled;
|
||||
bool updateTranslation;
|
||||
bool updateRotation;
|
||||
bool updateScale;
|
||||
vr::HmdVector3d_t translation;
|
||||
vr::HmdQuaternion_t rotation;
|
||||
double scale;
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(false), updateScale(false) { }
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(false), updateScale(false), translation(translation) { }
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled, vr::HmdQuaternion_t rotation) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(true), updateScale(false), rotation(rotation) { }
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled, double scale) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(false), updateScale(true), scale(scale) { }
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation, vr::HmdQuaternion_t rotation) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(true), updateScale(false), translation(translation), rotation(rotation) { }
|
||||
|
||||
SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation, vr::HmdQuaternion_t rotation, double scale) :
|
||||
openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(true), updateScale(true), translation(translation), rotation(rotation), scale(scale) { }
|
||||
};
|
||||
|
||||
struct Request
|
||||
{
|
||||
RequestType type;
|
||||
|
||||
union {
|
||||
SetDeviceTransform setDeviceTransform;
|
||||
};
|
||||
|
||||
Request() : type(RequestInvalid) { }
|
||||
Request(RequestType type) : type(type) { }
|
||||
};
|
||||
|
||||
struct Response
|
||||
{
|
||||
ResponseType type;
|
||||
|
||||
union {
|
||||
Protocol protocol;
|
||||
};
|
||||
|
||||
Response() : type(ResponseInvalid) { }
|
||||
Response(ResponseType type) : type(type) { }
|
||||
};
|
||||
}
|
||||
@@ -1,52 +1,51 @@
|
||||
# OpenVR Space Calibrator
|
||||
# Space Calibrator
|
||||
|
||||
This helps you use tracked VR devices from one company with any other. It aligns multiple tracking systems with a quick calibration step. It may not work for your setup, but there are many cases that work to a degree, and some work very well.
|
||||
This program is designed to allow you to synchronise multiple playspaces with one another in SteamVR. This fork of Space Calibrator (spacecal) also supports [continuous calibration](#continous-calibration).
|
||||
|
||||
- Rift CV1 x Vive devices: works very well with the v2 (blue logo) trackers, v1 trackers (grey logo, not in production) have major interference issues in the IR spectrum, controller wands (both gen) and Index controllers work very well.
|
||||
- Rift S, Quest, Windows MR, other SLAM inside-out tracked HMDs x Vive devices: works very well when you aren't moving around the room far (e.g. Beat Saber) but a lot of walking around causes a nontrivial amount of drift between systems. Your results may vary depending on your space. It's possible some of this can be fixed in software with a better calibration algorithm.
|
||||
- Quest wireless streaming is particularly bad right now and requires frequent recalibration, but it does work for a short time until one of many factors causes it to drift. With wireless devices, moving slowly when calibrating and using the Slow or Very Slow calibration modes is effective at reducing the initial error.
|
||||
- Any non-Rift HMD x Touch controllers: does not work, the Oculus driver requires the HMD is a Rift. It's theoretically possible to work around this in software but as far as I know it hasn't been done as it would require a fair amount of reverse engineering effort.
|
||||
Continuous calibration is a tracking mode which automatically aligns playspaces together, using a tracker on the headset.
|
||||
|
||||
There is a community of a few thousand on [**Discord**](https://discord.gg/m7g2Wyj) and a newer community on [**Reddit**](https://www.reddit.com/r/MixedVR/). You may find the answer to your question in [the **wiki**](https://github.com/pushrax/OpenVR-SpaceCalibrator/wiki).
|
||||
## Installing
|
||||
|
||||
A quick video of how this works using an old version (~v0.3) is available at https://www.youtube.com/watch?v=W3TnQd9JMl4. The user interface has been upgraded since then; the calibration is now done via a SteamVR dashboard menu, and there's much more configurability.
|
||||
### Steam
|
||||
|
||||
### Install
|
||||
> [!NOTE]
|
||||
> **Space Calibrator is coming to Steam. When it is available you may choose to install it via Steam instead of the installer.**
|
||||
|
||||
Before following the directions below, download and run the installer for the [latest release](https://github.com/pushrax/OpenVR-SpaceCalibrator/releases). This will automatically set up SteamVR for use with multiple tracking systems (`activateMultipleDrivers: true`). There are many guides that say you need to edit the SteamVR config manually. You do not.
|
||||
You may find [Space Calibrator on Steam here](https://s.team/a/3368750).
|
||||
|
||||
### Usage
|
||||
### From GitHub
|
||||
|
||||
Once Space Calibrator has a calibration, it works in the background to keep your devices configured correctly. Since v0.8, everything aside from creating the calibration is automated.
|
||||
To install Space Calibrator, please get the latest installer from the downloads page, and install it. Make sure that you have:
|
||||
- Installed [Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe).
|
||||
- Installed SteamVR and run it at least once with a VR headset connected.
|
||||
- SteamVR is not running before you run the installer. If SteamVR is running the installer will not be able to install Space Calibrator correctly.
|
||||
|
||||
### Calibration
|
||||
## Calibration
|
||||
|
||||
As part of first time setup, or when you make a change to your space (e.g. move a sensor), and occasionally as the calibration drifts over time (consumer VR tracking isn't perfectly stable), you'll need to run a calibration:
|
||||
If you do not wish to use continuous calibration, you will have to use regular calibration. This means that every so often you will have to sync your headset's playspace with your tracker's playspace.
|
||||
|
||||
1. Copy the chaperone/guardian bounds from your HMD's play space. This doesn't need to be run if your HMD's play space hasn't changed since last time you copied it. __Example:__ if you're using the Rift with Vive trackers and you bump a Vive lighthouse, or if the calibration has just drifted a little, you likely don't need to run this step, but if you bump an Oculus sensor you will (after running Oculus guardian setup again).
|
||||
1. Run SteamVR, with only devices from your HMD's tracking system powered on. __Example:__ for Rift with Vive trackers, don't turn on the trackers yet.
|
||||
2. Confirm your chaperone/guardian is set up with the walls in the right place. If you change it later, you need to run step again.
|
||||
3. Open SPACE CAL in the SteamVR dashboard overlay.
|
||||
4. Click `Copy Chaperone Bounds to profile`
|
||||
To calibrate:
|
||||
1. Copy the chaperone/guardian bounds from your HMD's play space
|
||||
> You will only have to do this once. Connect your VR headset and start SteamVR. Then go to space calibrator's window (it will be minimised), and click the "Copy Chaperone" button.
|
||||
|
||||
2. Calibrate devices.
|
||||
1. Open SteamVR if you haven't already. Turn on some or all your devices.
|
||||
2. Open SPACE CAL in the SteamVR dashboard overlay.
|
||||
3. Select one device from the reference space on the left and one device from the target space on the right. If you turned on multiple devices from one space and can't tell which one is selected, click "Identify selected devices" to blink an LED or vibrate it. __Example:__ for Rift with Vive trackers, you'll see the Touch controllers on the left, and Vive trackers on the right. __Pro tip:__ if you turn on just one Vive tracker, you don't have to figure out which one is selected.
|
||||
4. Hold these two devices in one hand, like they're glued together. If they slip, calibration won't work as well.
|
||||
5. Click `Start Calibration`
|
||||
6. Move and rotate your hand around slowly a few times, like you're calibrating the compass on your phone. You want to sample as many orientations as possible.
|
||||
7. Done! A profile will be saved automatically. If you haven't already, turn on all your devices. Space Calibrator will automatically apply the calibration to devices as they turn on.
|
||||
2. Open the SteamVR dashboard. At the bottom, click on the Space Calibrator icon.
|
||||
3. In the Space Calibrator overlay, you'll see two lists at the top. On the left `Reference Space` column, select the controller you'll be calibrating along (e.g. Quest controller, Pico controller). On the right `Target Space`, select your SteamVR tracker (e.g. Vive Ultimate Tracker, Vive Tracker 3.0, Vive Ultimate Tracker). You can use the Identify button to make the controllers blink and tracker LEDs flash to see if you've selected the correct ones.
|
||||
4. Click the "Start calibration" button, and start calibrating.
|
||||
|
||||
### Calibration outside VR
|
||||
## Continuous Calibration
|
||||
|
||||
You can calibrate without using the dashboard overlay by unminimizing Space Calibrator after opening SteamVR (it starts minimized). This is required if you're calibrating for a lone HMD without any devices in its tracking system.
|
||||
> [!IMPORTANT]
|
||||
> **A tracker attached on your headset is required for this.**
|
||||
|
||||
### Compiling your own build
|
||||
To enable continuous calibration mode, first select your headset on the left column, then the tracker on your headset on the right column. Once you've done so, click `Start Calibration`, and click cancel. Then click `Continuous Calibration` to enable continuous calibration.
|
||||
|
||||
Open `OpenVR-SpaceCalibrator.sln` in Visual Studio 2017 and build. There are no external dependencies.
|
||||
1. Start SteamVR with the VR headset you wish to use.
|
||||
2. Turn on **ONLY** the tracker which is attached on the VR headset.
|
||||
3. Select the VR headset and tracker and calibrate.
|
||||
4. Turn on your other devices.
|
||||
5. You should see them line up with you as you after moving around your playspace for a bit for an initial calibration.
|
||||
|
||||
### The math
|
||||
|
||||
See [math.pdf](https://github.com/pushrax/OpenVR-SpaceCalibrator/blob/master/math.pdf) for details.
|
||||
If you have some ideas for how to improve the calibration process, let me know!
|
||||
## Help
|
||||
|
||||
If you need help with setting up this program, please check the [wiki](https://github.com/pushrax/OpenVR-SpaceCalibrator/wiki), or join the [Discord server](https://discord.gg/ja3WgNjC3z).
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+43
-28
@@ -7,14 +7,25 @@
|
||||
;General
|
||||
|
||||
!define OVERLAY_BASEDIR "..\client_overlay\bin\win64"
|
||||
!define DRIVER_RESDIR "..\OpenVR-SpaceCalibratorDriver\01spacecalibrator"
|
||||
!define ARTIFACTS_BASEDIR "..\bin\artifacts\Release"
|
||||
!define DRIVER_RESDIR "..\bin\driver_01spacecalibrator"
|
||||
|
||||
Name "OpenVR-SpaceCalibrator"
|
||||
OutFile "OpenVR-SpaceCalibrator.exe"
|
||||
InstallDir "$PROGRAMFILES64\OpenVR-SpaceCalibrator"
|
||||
InstallDirRegKey HKLM "Software\OpenVR-SpaceCalibrator\Main" ""
|
||||
Name "Space Calibrator"
|
||||
OutFile "SpaceCalibrator.exe"
|
||||
InstallDir "$PROGRAMFILES64\SpaceCalibrator"
|
||||
InstallDirRegKey HKLM "Software\SpaceCalibrator\Main" ""
|
||||
RequestExecutionLevel admin
|
||||
ShowInstDetails show
|
||||
|
||||
; Define the version number
|
||||
!define VERSION "1.5.1.0"
|
||||
; Set version information
|
||||
VIProductVersion "${VERSION}"
|
||||
VIAddVersionKey /LANG=1033 "ProductName" "Space Calibrator"
|
||||
VIAddVersionKey /LANG=1033 "FileDescription" "Space Calibrator Installer"
|
||||
VIAddVersionKey /LANG=1033 "LegalCopyright" "Open source at https://github.com/hyblocker/OpenVR-SpaceCalibrator"
|
||||
VIAddVersionKey /LANG=1033 "FileVersion" "${VERSION}"
|
||||
VIAddVersionKey /LANG=1033 "ProductVersion" "${VERSION}"
|
||||
|
||||
;--------------------------------
|
||||
;Variables
|
||||
@@ -69,7 +80,7 @@ Function .onInit
|
||||
|
||||
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||
"OpenVR-SpaceCalibrator is already installed. $\n$\nClick `OK` to upgrade the \
|
||||
"Space Calibrator is already installed. $\n$\nClick `OK` to upgrade the \
|
||||
existing installation or `Cancel` to cancel this upgrade." \
|
||||
IDOK upgrade
|
||||
Abort
|
||||
@@ -95,17 +106,19 @@ Section "Install" SecInstall
|
||||
afterupgrade:
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
File "..\LICENSE"
|
||||
File "..\x64\Release\OpenVR-SpaceCalibrator.exe"
|
||||
File "..\lib\openvr\lib\win64\openvr_api.dll"
|
||||
File "..\OpenVR-SpaceCalibrator\manifest.vrmanifest"
|
||||
File "..\OpenVR-SpaceCalibrator\icon.png"
|
||||
|
||||
File "${ARTIFACTS_BASEDIR}\LICENSE"
|
||||
File "${ARTIFACTS_BASEDIR}\README"
|
||||
File "${ARTIFACTS_BASEDIR}\SpaceCalibrator.exe"
|
||||
File "${ARTIFACTS_BASEDIR}\openvr_api.dll"
|
||||
File "${ARTIFACTS_BASEDIR}\manifest.vrmanifest"
|
||||
File "${ARTIFACTS_BASEDIR}\icon.png"
|
||||
File "${ARTIFACTS_BASEDIR}\taskbar_icon.png"
|
||||
|
||||
ExecWait '"$INSTDIR\vcredist_x64.exe" /install /quiet'
|
||||
|
||||
Var /GLOBAL vrRuntimePath
|
||||
nsExec::ExecToStack '"$INSTDIR\OpenVR-SpaceCalibrator.exe" -openvrpath'
|
||||
nsExec::ExecToStack '"$INSTDIR\SpaceCalibrator.exe" -openvrpath'
|
||||
Pop $0
|
||||
Pop $vrRuntimePath
|
||||
DetailPrint "VR runtime path: $vrRuntimePath"
|
||||
@@ -131,20 +144,20 @@ Section "Install" SecInstall
|
||||
SetOutPath "$vrRuntimePath\drivers\01spacecalibrator\resources\settings"
|
||||
File "${DRIVER_RESDIR}\resources\settings\default.vrsettings"
|
||||
SetOutPath "$vrRuntimePath\drivers\01spacecalibrator\bin\win64"
|
||||
File "..\x64\Release\driver_01spacecalibrator.dll"
|
||||
File "${DRIVER_RESDIR}\bin\win64\driver_01spacecalibrator.dll"
|
||||
|
||||
WriteRegStr HKLM "Software\OpenVR-SpaceCalibrator\Main" "" $INSTDIR
|
||||
WriteRegStr HKLM "Software\OpenVR-SpaceCalibrator\Driver" "" $vrRuntimePath
|
||||
WriteRegStr HKLM "Software\SpaceCalibrator\Main" "" $INSTDIR
|
||||
WriteRegStr HKLM "Software\SpaceCalibrator\Driver" "" $vrRuntimePath
|
||||
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRSpaceCalibrator" "DisplayName" "OpenVR-SpaceCalibrator"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRSpaceCalibrator" "DisplayName" "Space Calibrator"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRSpaceCalibrator" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||
|
||||
CreateShortCut "$SMPROGRAMS\OpenVR-SpaceCalibrator.lnk" "$INSTDIR\OpenVR-SpaceCalibrator.exe"
|
||||
CreateShortCut "$SMPROGRAMS\Space Calibrator.lnk" "$INSTDIR\SpaceCalibrator.exe"
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
nsExec::ExecToLog '"$INSTDIR\OpenVR-SpaceCalibrator.exe" -installmanifest'
|
||||
nsExec::ExecToLog '"$INSTDIR\OpenVR-SpaceCalibrator.exe" -activatemultipledrivers'
|
||||
nsExec::ExecToLog '"$INSTDIR\SpaceCalibrator.exe" -installmanifest'
|
||||
nsExec::ExecToLog '"$INSTDIR\SpaceCalibrator.exe" -activatemultipledrivers'
|
||||
|
||||
SectionEnd
|
||||
|
||||
@@ -160,10 +173,10 @@ Section "Uninstall"
|
||||
Abort
|
||||
|
||||
SetOutPath "$INSTDIR"
|
||||
nsExec::ExecToLog '"$INSTDIR\OpenVR-SpaceCalibrator.exe" -removemanifest'
|
||||
nsExec::ExecToLog '"$INSTDIR\SpaceCalibrator.exe" -removemanifest'
|
||||
|
||||
Var /GLOBAL vrRuntimePath2
|
||||
ReadRegStr $vrRuntimePath2 HKLM "Software\OpenVR-SpaceCalibrator\Driver" ""
|
||||
ReadRegStr $vrRuntimePath2 HKLM "Software\SpaceCalibrator\Driver" ""
|
||||
DetailPrint "VR runtime path: $vrRuntimePath2"
|
||||
Delete "$vrRuntimePath2\drivers\01spacecalibrator\driver.vrdrivermanifest"
|
||||
Delete "$vrRuntimePath2\drivers\01spacecalibrator\resources\driver.vrresources"
|
||||
@@ -175,18 +188,20 @@ Section "Uninstall"
|
||||
RMdir "$vrRuntimePath2\drivers\01spacecalibrator\bin\win64\"
|
||||
RMdir "$vrRuntimePath2\drivers\01spacecalibrator\bin\"
|
||||
RMdir "$vrRuntimePath2\drivers\01spacecalibrator\"
|
||||
|
||||
|
||||
Delete "$INSTDIR\LICENSE"
|
||||
Delete "$INSTDIR\OpenVR-SpaceCalibrator.exe"
|
||||
Delete "$INSTDIR\README"
|
||||
Delete "$INSTDIR\SpaceCalibrator.exe"
|
||||
Delete "$INSTDIR\openvr_api.dll"
|
||||
Delete "$INSTDIR\manifest.vrmanifest"
|
||||
Delete "$INSTDIR\icon.png"
|
||||
Delete "$INSTDIR\taskbar_icon.png"
|
||||
|
||||
DeleteRegKey HKLM "Software\OpenVR-SpaceCalibrator\Main"
|
||||
DeleteRegKey HKLM "Software\OpenVR-SpaceCalibrator\Driver"
|
||||
DeleteRegKey HKLM "Software\OpenVR-SpaceCalibrator"
|
||||
DeleteRegKey HKLM "Software\SpaceCalibrator\Main"
|
||||
DeleteRegKey HKLM "Software\SpaceCalibrator\Driver"
|
||||
DeleteRegKey HKLM "Software\SpaceCalibrator"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRSpaceCalibrator"
|
||||
|
||||
Delete "$SMPROGRAMS\OpenVR-SpaceCalibrator.lnk"
|
||||
Delete "$SMPROGRAMS\Space Calibrator.lnk"
|
||||
SectionEnd
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
cmake_minimum_required (VERSION 3.24)
|
||||
|
||||
project("lib")
|
||||
|
||||
# Includes all 3rd party libraries here
|
||||
|
||||
# Minhook library
|
||||
message("Adding minhook...")
|
||||
add_subdirectory ("minhook")
|
||||
|
||||
# GLFW
|
||||
message("Adding GLFW...")
|
||||
set(GLFW_BUILD_TESTS OFF)
|
||||
set(GLFW_BUILD_EXAMPLES OFF)
|
||||
set(GLFW_BUILD_DOCS OFF)
|
||||
set(GLFW_INSTALL OFF)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
add_subdirectory(glfw)
|
||||
|
||||
# Dear ImGui
|
||||
message("Adding ImGui...")
|
||||
add_library(imgui STATIC
|
||||
${CMAKE_SOURCE_DIR}/lib/imgui/imgui.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/imgui/imgui_demo.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/imgui/imgui_draw.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/imgui/imgui_tables.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/imgui/imgui_widgets.cpp)
|
||||
target_include_directories(imgui PUBLIC ${CMAKE_SOURCE_DIR}/lib/imgui)
|
||||
target_compile_definitions(imgui PRIVATE IMGUI_DEFINE_MATH_OPERATORS)
|
||||
|
||||
# ImPlot
|
||||
message("Adding ImPlot...")
|
||||
message("Adding ImGui...")
|
||||
add_library(implot STATIC
|
||||
${CMAKE_SOURCE_DIR}/lib/implot/implot.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/implot/implot_demo.cpp
|
||||
${CMAKE_SOURCE_DIR}/lib/implot/implot_items.cpp)
|
||||
target_include_directories(implot PUBLIC ${CMAKE_SOURCE_DIR}/lib/implot)
|
||||
target_compile_definitions(implot PRIVATE IMGUI_DEFINE_MATH_OPERATORS)
|
||||
target_link_libraries(implot PRIVATE imgui)
|
||||
|
||||
# gl3w
|
||||
message("Adding gl3w...")
|
||||
add_library(gl3w STATIC ${CMAKE_SOURCE_DIR}/lib/gl3w/src/gl3w.c)
|
||||
target_include_directories(gl3w PUBLIC ${CMAKE_SOURCE_DIR}/lib/gl3w/include)
|
||||
|
||||
# Assign solution dirs
|
||||
set_property(TARGET minhook PROPERTY FOLDER "lib")
|
||||
|
||||
set_property(TARGET glfw PROPERTY FOLDER "lib/glfw")
|
||||
set_property(TARGET update_mappings PROPERTY FOLDER "lib/glfw")
|
||||
|
||||
set_property(TARGET imgui PROPERTY FOLDER "lib")
|
||||
set_property(TARGET implot PROPERTY FOLDER "lib")
|
||||
set_property(TARGET gl3w PROPERTY FOLDER "lib")
|
||||
+5
-1
@@ -9,6 +9,7 @@
|
||||
#define EIGEN_CHOLESKY_MODULE_H
|
||||
|
||||
#include "Core"
|
||||
#include "Jacobi"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
@@ -31,11 +32,14 @@
|
||||
#include "src/Cholesky/LLT.h"
|
||||
#include "src/Cholesky/LDLT.h"
|
||||
#ifdef EIGEN_USE_LAPACKE
|
||||
#ifdef EIGEN_USE_MKL
|
||||
#include "mkl_lapacke.h"
|
||||
#else
|
||||
#include "src/misc/lapacke.h"
|
||||
#endif
|
||||
#include "src/Cholesky/LLT_LAPACKE.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_CHOLESKY_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
+114
-246
@@ -11,232 +11,55 @@
|
||||
#ifndef EIGEN_CORE_H
|
||||
#define EIGEN_CORE_H
|
||||
|
||||
// first thing Eigen does: stop the compiler from committing suicide
|
||||
// first thing Eigen does: stop the compiler from reporting useless warnings.
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
// Handle NVCC/CUDA/SYCL
|
||||
#if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__)
|
||||
// Do not try asserts on CUDA and SYCL!
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
#define EIGEN_NO_DEBUG
|
||||
#endif
|
||||
// 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 compiler/OS/arch detections and define most defaults.
|
||||
#include "src/Core/util/Macros.h"
|
||||
|
||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||
#undef EIGEN_INTERNAL_DEBUGGING
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#undef EIGEN_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
// All functions callable from CUDA code must be qualified with __device__
|
||||
#ifdef __CUDACC__
|
||||
// Do not try to vectorize on CUDA and SYCL!
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#define EIGEN_DONT_VECTORIZE
|
||||
#endif
|
||||
|
||||
#define EIGEN_DEVICE_FUNC __host__ __device__
|
||||
// We need math_functions.hpp to ensure that that EIGEN_USING_STD_MATH macro
|
||||
// works properly on the device side
|
||||
#include <math_functions.hpp>
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
// This detects SSE/AVX/NEON/etc. and configure alignment settings
|
||||
#include "src/Core/util/ConfigureVectorization.h"
|
||||
|
||||
// We need cuda_runtime.h/hip_runtime.h to ensure that
|
||||
// the EIGEN_USING_STD macro works properly on the device side
|
||||
#if defined(EIGEN_CUDACC)
|
||||
#include <cuda_runtime.h>
|
||||
#elif defined(EIGEN_HIPCC)
|
||||
#include <hip/hip_runtime.h>
|
||||
#endif
|
||||
|
||||
// When compiling CUDA device code with NVCC, pull in math functions from the
|
||||
// global namespace. In host mode, and when device doee with clang, use the
|
||||
// std versions.
|
||||
#if defined(__CUDA_ARCH__) && defined(__NVCC__)
|
||||
#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) && !defined(EIGEN_USE_SYCL)
|
||||
#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
|
||||
// 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.
|
||||
#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 EIGEN_COMP_MINGW && EIGEN_GNUC_AT_LEAST(4,6)
|
||||
#if EIGEN_COMP_MINGW && EIGEN_GNUC_AT_LEAST(4,6) && EIGEN_GNUC_AT_MOST(5,5)
|
||||
#pragma GCC optimize ("-fno-ipa-cp-clone")
|
||||
#endif
|
||||
|
||||
// Prevent ICC from specializing std::complex operators that silently fail
|
||||
// on device. This allows us to use our own device-compatible specializations
|
||||
// instead.
|
||||
#if defined(EIGEN_COMP_ICC) && defined(EIGEN_GPU_COMPILE_PHASE) \
|
||||
&& !defined(_OVERRIDE_COMPLEX_SPECIALIZATION_)
|
||||
#define _OVERRIDE_COMPLEX_SPECIALIZATION_ 1
|
||||
#endif
|
||||
#include <complex>
|
||||
|
||||
// this include file manages BLAS and MKL related macros
|
||||
// and inclusion of their respective header files
|
||||
#include "src/Core/util/MKL_support.h"
|
||||
|
||||
// if alignment is disabled, then disable vectorization. Note: EIGEN_MAX_ALIGN_BYTES is the proper check, it takes into
|
||||
// account both the user's will (EIGEN_MAX_ALIGN_BYTES,EIGEN_DONT_ALIGN) and our own platform checks
|
||||
#if EIGEN_MAX_ALIGN_BYTES==0
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#define EIGEN_DONT_VECTORIZE
|
||||
#endif
|
||||
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)
|
||||
#define EIGEN_HAS_GPU_FP16
|
||||
#endif
|
||||
|
||||
#if EIGEN_COMP_MSVC
|
||||
#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
|
||||
#if (EIGEN_COMP_MSVC >= 1500) // 2008 or later
|
||||
// Remember that usage of defined() in a #define is undefined by the standard.
|
||||
// a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
|
||||
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || EIGEN_ARCH_x86_64
|
||||
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
// Remember that usage of defined() in a #define is undefined by the standard
|
||||
#if (defined __SSE2__) && ( (!EIGEN_COMP_GNUC) || EIGEN_COMP_ICC || EIGEN_GNUC_AT_LEAST(4,2) )
|
||||
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
|
||||
#if defined (EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
|
||||
|
||||
// Defines symbols for compile-time detection of which instructions are
|
||||
// used.
|
||||
// EIGEN_VECTORIZE_YY is defined if and only if the instruction set YY is used
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_SSE
|
||||
#define EIGEN_VECTORIZE_SSE2
|
||||
|
||||
// Detect sse3/ssse3/sse4:
|
||||
// gcc and icc defines __SSE3__, ...
|
||||
// there is no way to know about this on msvc. You can define EIGEN_VECTORIZE_SSE* if you
|
||||
// want to force the use of those instructions with msvc.
|
||||
#ifdef __SSE3__
|
||||
#define EIGEN_VECTORIZE_SSE3
|
||||
#endif
|
||||
#ifdef __SSSE3__
|
||||
#define EIGEN_VECTORIZE_SSSE3
|
||||
#endif
|
||||
#ifdef __SSE4_1__
|
||||
#define EIGEN_VECTORIZE_SSE4_1
|
||||
#endif
|
||||
#ifdef __SSE4_2__
|
||||
#define EIGEN_VECTORIZE_SSE4_2
|
||||
#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 __AVX2__
|
||||
#define EIGEN_VECTORIZE_AVX2
|
||||
#endif
|
||||
#ifdef __FMA__
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#endif
|
||||
#if defined(__AVX512F__) && defined(EIGEN_ENABLE_AVX512)
|
||||
#define EIGEN_VECTORIZE_AVX512
|
||||
#define EIGEN_VECTORIZE_AVX2
|
||||
#define EIGEN_VECTORIZE_AVX
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#ifdef __AVX512DQ__
|
||||
#define EIGEN_VECTORIZE_AVX512DQ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// include files
|
||||
|
||||
// This extern "C" works around a MINGW-w64 compilation issue
|
||||
// https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354
|
||||
// In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do).
|
||||
// However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations
|
||||
// with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know;
|
||||
// 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.
|
||||
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 EIGEN_COMP_ICC >= 1110
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#include <mmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#ifdef EIGEN_VECTORIZE_SSSE3
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_1
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
#ifdef EIGEN_VECTORIZE_SSE4_2
|
||||
#include <nmmintrin.h>
|
||||
#endif
|
||||
#if defined(EIGEN_VECTORIZE_AVX) || defined(EIGEN_VECTORIZE_AVX512)
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
} // end extern "C"
|
||||
#elif defined __VSX__
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_VSX
|
||||
#include <altivec.h>
|
||||
// We need to #undef all these ugly tokens defined in <altivec.h>
|
||||
// => use __vector instead of vector
|
||||
#undef bool
|
||||
#undef vector
|
||||
#undef pixel
|
||||
#elif defined __ALTIVEC__
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_ALTIVEC
|
||||
#include <altivec.h>
|
||||
// We need to #undef all these ugly tokens defined in <altivec.h>
|
||||
// => use __vector instead of vector
|
||||
#undef bool
|
||||
#undef vector
|
||||
#undef pixel
|
||||
#elif (defined __ARM_NEON) || (defined __ARM_NEON__)
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_NEON
|
||||
#include <arm_neon.h>
|
||||
#elif (defined __s390x__ && defined __VEC__)
|
||||
#define EIGEN_VECTORIZE
|
||||
#define EIGEN_VECTORIZE_ZVECTOR
|
||||
#include <vecintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__F16C__) && !defined(EIGEN_COMP_CLANG)
|
||||
// We can use the optimized fp16 to float and float to fp16 conversion routines
|
||||
#define EIGEN_HAS_FP16_C
|
||||
#endif
|
||||
|
||||
#if defined __CUDACC__
|
||||
#define EIGEN_VECTORIZE_CUDA
|
||||
#include <vector_types.h>
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 70500
|
||||
#define EIGEN_HAS_CUDA_FP16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined EIGEN_HAS_CUDA_FP16
|
||||
#include <host_defines.h>
|
||||
#include <cuda_fp16.h>
|
||||
#if defined(EIGEN_HAS_CUDA_BF16) || defined(EIGEN_HAS_HIP_BF16)
|
||||
#define EIGEN_HAS_GPU_BF16
|
||||
#endif
|
||||
|
||||
#if (defined _OPENMP) && (!defined EIGEN_DONT_PARALLELIZE)
|
||||
@@ -260,7 +83,10 @@
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <sstream>
|
||||
#ifndef EIGEN_NO_IO
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
@@ -268,6 +94,10 @@
|
||||
// for min/max:
|
||||
#include <algorithm>
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
// for std::is_nothrow_move_assignable
|
||||
#ifdef EIGEN_INCLUDE_TYPE_TRAITS
|
||||
#include <type_traits>
|
||||
@@ -283,38 +113,25 @@
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
/** \brief Namespace containing all symbols from the %Eigen library. */
|
||||
namespace Eigen {
|
||||
|
||||
inline static const char *SimdInstructionSetsInUse(void) {
|
||||
#if defined(EIGEN_VECTORIZE_AVX512)
|
||||
return "AVX512, FMA, AVX2, AVX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
|
||||
#elif defined(EIGEN_VECTORIZE_AVX)
|
||||
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";
|
||||
#elif defined(EIGEN_VECTORIZE_SSE4_1)
|
||||
return "SSE, SSE2, SSE3, SSSE3, SSE4.1";
|
||||
#elif defined(EIGEN_VECTORIZE_SSSE3)
|
||||
return "SSE, SSE2, SSE3, SSSE3";
|
||||
#elif defined(EIGEN_VECTORIZE_SSE3)
|
||||
return "SSE, SSE2, SSE3";
|
||||
#elif defined(EIGEN_VECTORIZE_SSE2)
|
||||
return "SSE, SSE2";
|
||||
#elif defined(EIGEN_VECTORIZE_ALTIVEC)
|
||||
return "AltiVec";
|
||||
#elif defined(EIGEN_VECTORIZE_VSX)
|
||||
return "VSX";
|
||||
#elif defined(EIGEN_VECTORIZE_NEON)
|
||||
return "ARM NEON";
|
||||
#elif defined(EIGEN_VECTORIZE_ZVECTOR)
|
||||
return "S390X ZVECTOR";
|
||||
#else
|
||||
return "None";
|
||||
#if defined(EIGEN_USE_SYCL)
|
||||
#undef min
|
||||
#undef max
|
||||
#undef isnan
|
||||
#undef isinf
|
||||
#undef isfinite
|
||||
#include <CL/sycl.hpp>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <thread>
|
||||
#ifndef EIGEN_SYCL_LOCAL_THREAD_DIM0
|
||||
#define EIGEN_SYCL_LOCAL_THREAD_DIM0 16
|
||||
#endif
|
||||
#ifndef EIGEN_SYCL_LOCAL_THREAD_DIM1
|
||||
#define EIGEN_SYCL_LOCAL_THREAD_DIM1 16
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
} // 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
|
||||
// This will generate an error message:
|
||||
@@ -323,7 +140,7 @@ inline static const char *SimdInstructionSetsInUse(void) {
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// 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:: every time just to
|
||||
// ensure QNX/QCC support
|
||||
using std::size_t;
|
||||
// gcc 4.6.0 wants std:: for ptrdiff_t
|
||||
@@ -347,56 +164,90 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/util/StaticAssert.h"
|
||||
#include "src/Core/util/XprHelper.h"
|
||||
#include "src/Core/util/Memory.h"
|
||||
#include "src/Core/util/IntegralConstant.h"
|
||||
#include "src/Core/util/SymbolicIndex.h"
|
||||
|
||||
#include "src/Core/NumTraits.h"
|
||||
#include "src/Core/MathFunctions.h"
|
||||
#include "src/Core/GenericPacketMath.h"
|
||||
#include "src/Core/MathFunctionsImpl.h"
|
||||
#include "src/Core/arch/Default/ConjHelper.h"
|
||||
// Generic half float support
|
||||
#include "src/Core/arch/Default/Half.h"
|
||||
#include "src/Core/arch/Default/BFloat16.h"
|
||||
#include "src/Core/arch/Default/TypeCasting.h"
|
||||
#include "src/Core/arch/Default/GenericPacketMathFunctionsFwd.h"
|
||||
|
||||
#if defined EIGEN_VECTORIZE_AVX512
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/TypeCasting.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/AVX512/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/TypeCasting.h"
|
||||
#include "src/Core/arch/AVX512/Complex.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX512/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_AVX
|
||||
// Use AVX for floats and doubles, SSE for integers
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/AVX/TypeCasting.h"
|
||||
#include "src/Core/arch/AVX/Complex.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_SSE
|
||||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/SSE/Complex.h"
|
||||
#include "src/Core/arch/SSE/TypeCasting.h"
|
||||
#elif defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
|
||||
#include "src/Core/arch/AltiVec/PacketMath.h"
|
||||
#include "src/Core/arch/AltiVec/MathFunctions.h"
|
||||
#include "src/Core/arch/AltiVec/Complex.h"
|
||||
#elif defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/Core/arch/NEON/PacketMath.h"
|
||||
#include "src/Core/arch/NEON/TypeCasting.h"
|
||||
#include "src/Core/arch/NEON/MathFunctions.h"
|
||||
#include "src/Core/arch/NEON/Complex.h"
|
||||
#elif defined EIGEN_VECTORIZE_SVE
|
||||
#include "src/Core/arch/SVE/PacketMath.h"
|
||||
#include "src/Core/arch/SVE/TypeCasting.h"
|
||||
#include "src/Core/arch/SVE/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_ZVECTOR
|
||||
#include "src/Core/arch/ZVector/PacketMath.h"
|
||||
#include "src/Core/arch/ZVector/MathFunctions.h"
|
||||
#include "src/Core/arch/ZVector/Complex.h"
|
||||
#elif defined EIGEN_VECTORIZE_MSA
|
||||
#include "src/Core/arch/MSA/PacketMath.h"
|
||||
#include "src/Core/arch/MSA/MathFunctions.h"
|
||||
#include "src/Core/arch/MSA/Complex.h"
|
||||
#endif
|
||||
|
||||
// Half float support
|
||||
#include "src/Core/arch/CUDA/Half.h"
|
||||
#include "src/Core/arch/CUDA/PacketMathHalf.h"
|
||||
#include "src/Core/arch/CUDA/TypeCasting.h"
|
||||
#if defined EIGEN_VECTORIZE_GPU
|
||||
#include "src/Core/arch/GPU/PacketMath.h"
|
||||
#include "src/Core/arch/GPU/MathFunctions.h"
|
||||
#include "src/Core/arch/GPU/TypeCasting.h"
|
||||
#endif
|
||||
|
||||
#if defined EIGEN_VECTORIZE_CUDA
|
||||
#include "src/Core/arch/CUDA/PacketMath.h"
|
||||
#include "src/Core/arch/CUDA/MathFunctions.h"
|
||||
#if defined(EIGEN_USE_SYCL)
|
||||
#include "src/Core/arch/SYCL/SyclMemoryModel.h"
|
||||
#include "src/Core/arch/SYCL/InteropHeaders.h"
|
||||
#if !defined(EIGEN_DONT_VECTORIZE_SYCL)
|
||||
#include "src/Core/arch/SYCL/PacketMath.h"
|
||||
#include "src/Core/arch/SYCL/MathFunctions.h"
|
||||
#include "src/Core/arch/SYCL/TypeCasting.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "src/Core/arch/Default/Settings.h"
|
||||
// This file provides generic implementations valid for scalar as well
|
||||
#include "src/Core/arch/Default/GenericPacketMathFunctions.h"
|
||||
|
||||
#include "src/Core/functors/TernaryFunctors.h"
|
||||
#include "src/Core/functors/BinaryFunctors.h"
|
||||
@@ -407,9 +258,16 @@ using std::ptrdiff_t;
|
||||
|
||||
// Specialized functors to enable the processing of complex numbers
|
||||
// on CUDA devices
|
||||
#ifdef EIGEN_CUDACC
|
||||
#include "src/Core/arch/CUDA/Complex.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/IO.h"
|
||||
#include "src/Core/util/IndexedViewHelper.h"
|
||||
#include "src/Core/util/ReshapedHelper.h"
|
||||
#include "src/Core/ArithmeticSequence.h"
|
||||
#ifndef EIGEN_NO_IO
|
||||
#include "src/Core/IO.h"
|
||||
#endif
|
||||
#include "src/Core/DenseCoeffsBase.h"
|
||||
#include "src/Core/DenseBase.h"
|
||||
#include "src/Core/MatrixBase.h"
|
||||
@@ -450,6 +308,8 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/Ref.h"
|
||||
#include "src/Core/Block.h"
|
||||
#include "src/Core/VectorBlock.h"
|
||||
#include "src/Core/IndexedView.h"
|
||||
#include "src/Core/Reshaped.h"
|
||||
#include "src/Core/Transpose.h"
|
||||
#include "src/Core/DiagonalMatrix.h"
|
||||
#include "src/Core/Diagonal.h"
|
||||
@@ -486,13 +346,21 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/CoreIterators.h"
|
||||
#include "src/Core/ConditionEstimator.h"
|
||||
|
||||
#if defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
|
||||
#include "src/Core/arch/AltiVec/MatrixProduct.h"
|
||||
#elif defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/Core/arch/NEON/GeneralBlockPanelKernel.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/BooleanRedux.h"
|
||||
#include "src/Core/Select.h"
|
||||
#include "src/Core/VectorwiseOp.h"
|
||||
#include "src/Core/PartialReduxEvaluator.h"
|
||||
#include "src/Core/Random.h"
|
||||
#include "src/Core/Replicate.h"
|
||||
#include "src/Core/Reverse.h"
|
||||
#include "src/Core/ArrayWrapper.h"
|
||||
#include "src/Core/StlIterators.h"
|
||||
|
||||
#ifdef EIGEN_USE_BLAS
|
||||
#include "src/Core/products/GeneralMatrixMatrix_BLAS.h"
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "Cholesky"
|
||||
#include "Jacobi"
|
||||
#include "Householder"
|
||||
#include "LU"
|
||||
#include "Geometry"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
/** \defgroup Eigenvalues_Module Eigenvalues module
|
||||
*
|
||||
*
|
||||
@@ -45,7 +45,11 @@
|
||||
#include "src/Eigenvalues/GeneralizedEigenSolver.h"
|
||||
#include "src/Eigenvalues/MatrixBaseEigenvalues.h"
|
||||
#ifdef EIGEN_USE_LAPACKE
|
||||
#ifdef EIGEN_USE_MKL
|
||||
#include "mkl_lapacke.h"
|
||||
#else
|
||||
#include "src/misc/lapacke.h"
|
||||
#endif
|
||||
#include "src/Eigenvalues/RealSchur_LAPACKE.h"
|
||||
#include "src/Eigenvalues/ComplexSchur_LAPACKE.h"
|
||||
#include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h"
|
||||
@@ -54,4 +58,3 @@
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_EIGENVALUES_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
+5
-8
@@ -10,12 +10,12 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "SVD"
|
||||
#include "LU"
|
||||
#include <limits>
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
/** \defgroup Geometry_Module Geometry module
|
||||
*
|
||||
* This module provides support for:
|
||||
@@ -49,14 +49,11 @@
|
||||
#include "src/Geometry/AlignedBox.h"
|
||||
#include "src/Geometry/Umeyama.h"
|
||||
|
||||
// Use the SSE optimized version whenever possible. At the moment the
|
||||
// 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"
|
||||
// Use the SSE optimized version whenever possible.
|
||||
#if (defined EIGEN_VECTORIZE_SSE) || (defined EIGEN_VECTORIZE_NEON)
|
||||
#include "src/Geometry/arch/Geometry_SIMD.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_GEOMETRY_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
|
||||
@@ -27,4 +27,3 @@
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_HOUSEHOLDER_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
@@ -29,5 +29,4 @@
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_JACOBI_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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_KLUSUPPORT_MODULE_H
|
||||
#define EIGEN_KLUSUPPORT_MODULE_H
|
||||
|
||||
#include <Eigen/SparseCore>
|
||||
|
||||
#include <Eigen/src/Core/util/DisableStupidWarnings.h>
|
||||
|
||||
extern "C" {
|
||||
#include <btf.h>
|
||||
#include <klu.h>
|
||||
}
|
||||
|
||||
/** \ingroup Support_modules
|
||||
* \defgroup KLUSupport_Module KLUSupport module
|
||||
*
|
||||
* This module provides an interface to the KLU library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
|
||||
* It provides the following factorization class:
|
||||
* - class KLU: a sparse LU factorization, well-suited for circuit simulation.
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/KLUSupport>
|
||||
* \endcode
|
||||
*
|
||||
* In order to use this module, the klu and btf headers must be accessible from the include paths, and your binary must be linked to the klu library and its dependencies.
|
||||
* The dependencies depend on how umfpack has been compiled.
|
||||
* For a cmake based project, you can use our FindKLU.cmake module to help you in this task.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/KLUSupport/KLUSupport.h"
|
||||
|
||||
#include <Eigen/src/Core/util/ReenableStupidWarnings.h>
|
||||
|
||||
#endif // EIGEN_KLUSUPPORT_MODULE_H
|
||||
+6
-5
@@ -28,19 +28,20 @@
|
||||
#include "src/LU/FullPivLU.h"
|
||||
#include "src/LU/PartialPivLU.h"
|
||||
#ifdef EIGEN_USE_LAPACKE
|
||||
#ifdef EIGEN_USE_MKL
|
||||
#include "mkl_lapacke.h"
|
||||
#else
|
||||
#include "src/misc/lapacke.h"
|
||||
#endif
|
||||
#include "src/LU/PartialPivLU_LAPACKE.h"
|
||||
#endif
|
||||
#include "src/LU/Determinant.h"
|
||||
#include "src/LU/InverseImpl.h"
|
||||
|
||||
// Use the SSE optimized version whenever possible. At the moment the
|
||||
// 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"
|
||||
#if defined EIGEN_VECTORIZE_SSE || defined EIGEN_VECTORIZE_NEON
|
||||
#include "src/LU/arch/InverseSize4.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_LU_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
@@ -63,10 +63,7 @@
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#include "src/OrderingMethods/Amd.h"
|
||||
#endif
|
||||
|
||||
#include "src/OrderingMethods/Ordering.h"
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ extern "C" {
|
||||
* \endcode
|
||||
*
|
||||
* In order to use this module, the PaSTiX headers must be accessible from the include paths, and your binary must be linked to the PaSTiX library and its dependencies.
|
||||
* This wrapper resuires PaStiX version 5.x compiled without MPI support.
|
||||
* The dependencies depend on how PaSTiX has been compiled.
|
||||
* For a cmake based project, you can use our FindPaSTiX.cmake module to help you in this task.
|
||||
*
|
||||
|
||||
+6
-3
@@ -10,12 +10,12 @@
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "Cholesky"
|
||||
#include "Jacobi"
|
||||
#include "Householder"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
/** \defgroup QR_Module QR module
|
||||
*
|
||||
*
|
||||
@@ -36,7 +36,11 @@
|
||||
#include "src/QR/ColPivHouseholderQR.h"
|
||||
#include "src/QR/CompleteOrthogonalDecomposition.h"
|
||||
#ifdef EIGEN_USE_LAPACKE
|
||||
#ifdef EIGEN_USE_MKL
|
||||
#include "mkl_lapacke.h"
|
||||
#else
|
||||
#include "src/misc/lapacke.h"
|
||||
#endif
|
||||
#include "src/QR/HouseholderQR_LAPACKE.h"
|
||||
#include "src/QR/ColPivHouseholderQR_LAPACKE.h"
|
||||
#endif
|
||||
@@ -44,4 +48,3 @@
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_QR_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
@@ -27,7 +27,7 @@ void qFree(void *ptr)
|
||||
void *qRealloc(void *ptr, std::size_t size)
|
||||
{
|
||||
void* newPtr = Eigen::internal::aligned_malloc(size);
|
||||
memcpy(newPtr, ptr, size);
|
||||
std::memcpy(newPtr, ptr, size);
|
||||
Eigen::internal::aligned_free(ptr);
|
||||
return newPtr;
|
||||
}
|
||||
@@ -37,4 +37,3 @@ void *qRealloc(void *ptr, std::size_t size)
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_QTMALLOC_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
+4
-1
@@ -37,11 +37,14 @@
|
||||
#include "src/SVD/JacobiSVD.h"
|
||||
#include "src/SVD/BDCSVD.h"
|
||||
#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT)
|
||||
#ifdef EIGEN_USE_MKL
|
||||
#include "mkl_lapacke.h"
|
||||
#else
|
||||
#include "src/misc/lapacke.h"
|
||||
#endif
|
||||
#include "src/SVD/JacobiSVD_LAPACKE.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_SVD_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
@@ -25,9 +25,7 @@
|
||||
|
||||
#include "SparseCore"
|
||||
#include "OrderingMethods"
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#include "SparseCholesky"
|
||||
#endif
|
||||
#include "SparseLU"
|
||||
#include "SparseQR"
|
||||
#include "IterativeLinearSolvers"
|
||||
|
||||
@@ -30,16 +30,8 @@
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#ifdef EIGEN_MPL2_ONLY
|
||||
#error The SparseCholesky module has nothing to offer in MPL2 only mode
|
||||
#endif
|
||||
|
||||
#include "src/SparseCholesky/SimplicialCholesky.h"
|
||||
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#include "src/SparseCholesky/SimplicialCholesky_impl.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_SPARSECHOLESKY_MODULE_H
|
||||
@@ -23,6 +23,8 @@
|
||||
// Ordering interface
|
||||
#include "OrderingMethods"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "src/SparseLU/SparseLU_gemm_kernel.h"
|
||||
|
||||
#include "src/SparseLU/SparseLU_Structs.h"
|
||||
@@ -43,4 +45,6 @@
|
||||
#include "src/SparseLU/SparseLU_Utils.h"
|
||||
#include "src/SparseLU/SparseLU.h"
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_SPARSELU_MODULE_H
|
||||
@@ -28,7 +28,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "OrderingMethods"
|
||||
#include "src/SparseCore/SparseColEtree.h"
|
||||
#include "src/SparseQR/SparseQR.h"
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename _MatrixType, int _UpLo> struct traits<LDLT<_MatrixType, _UpLo> >
|
||||
: traits<_MatrixType>
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
template<typename MatrixType, int UpLo> struct LDLT_Traits;
|
||||
|
||||
// PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
|
||||
@@ -36,7 +45,7 @@ namespace internal {
|
||||
* matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L
|
||||
* is lower triangular with a unit diagonal and D is a diagonal matrix.
|
||||
*
|
||||
* The decomposition uses pivoting to ensure stability, so that L will have
|
||||
* The decomposition uses pivoting to ensure stability, so that D will have
|
||||
* zeros in the bottom right rank(A) - n submatrix. Avoiding the square root
|
||||
* on D also stabilizes the computation.
|
||||
*
|
||||
@@ -44,24 +53,23 @@ namespace internal {
|
||||
* decomposition to determine whether a system of equations has a solution.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
*
|
||||
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt(), class LLT
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo> class LDLT
|
||||
: public SolverBase<LDLT<_MatrixType, _UpLo> >
|
||||
{
|
||||
public:
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<LDLT> Base;
|
||||
friend class SolverBase<LDLT>;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(LDLT)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
|
||||
UpLo = _UpLo
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
typedef Matrix<Scalar, RowsAtCompileTime, 1, 0, MaxRowsAtCompileTime, 1> TmpMatrixType;
|
||||
|
||||
typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
|
||||
@@ -180,6 +188,7 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
*
|
||||
* This function also supports in-place solves using the syntax <tt>x = decompositionObject.solve(x)</tt> .
|
||||
@@ -191,19 +200,14 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
* \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then
|
||||
* \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the
|
||||
* 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$ if \f$ A \f$ is singular.
|
||||
*
|
||||
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt()
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<LDLT, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
eigen_assert(m_matrix.rows()==b.rows()
|
||||
&& "LDLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return Solve<LDLT, Rhs>(*this, b.derived());
|
||||
}
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
@@ -242,13 +246,13 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
*/
|
||||
const LDLT& adjoint() const { return *this; };
|
||||
|
||||
inline Index rows() const { return m_matrix.rows(); }
|
||||
inline Index cols() const { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
* \returns \c Success if computation was succesful,
|
||||
* \c NumericalIssue if the matrix.appears to be negative.
|
||||
* \returns \c Success if computation was successful,
|
||||
* \c NumericalIssue if the factorization failed because of a zero pivot.
|
||||
*/
|
||||
ComputationInfo info() const
|
||||
{
|
||||
@@ -258,8 +262,10 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -305,7 +311,8 @@ template<> struct ldlt_inplace<Lower>
|
||||
if (size <= 1)
|
||||
{
|
||||
transpositions.setIdentity();
|
||||
if (numext::real(mat.coeff(0,0)) > static_cast<RealScalar>(0) ) sign = PositiveSemiDef;
|
||||
if(size==0) sign = ZeroSign;
|
||||
else if (numext::real(mat.coeff(0,0)) > static_cast<RealScalar>(0) ) sign = PositiveSemiDef;
|
||||
else if (numext::real(mat.coeff(0,0)) < static_cast<RealScalar>(0)) sign = NegativeSemiDef;
|
||||
else sign = ZeroSign;
|
||||
return true;
|
||||
@@ -376,6 +383,8 @@ template<> struct ldlt_inplace<Lower>
|
||||
|
||||
if((rs>0) && pivot_is_valid)
|
||||
A21 /= realAkk;
|
||||
else if(rs>0)
|
||||
ret = ret && (A21.array()==Scalar(0)).all();
|
||||
|
||||
if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed
|
||||
else if(!pivot_is_valid) found_zero_pivot = true;
|
||||
@@ -557,25 +566,33 @@ template<typename _MatrixType, int _UpLo>
|
||||
template<typename RhsType, typename DstType>
|
||||
void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
eigen_assert(rhs.rows() == rows());
|
||||
_solve_impl_transposed<true>(rhs, dst);
|
||||
}
|
||||
|
||||
template<typename _MatrixType,int _UpLo>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void LDLT<_MatrixType,_UpLo>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
// dst = P b
|
||||
dst = m_transpositions * rhs;
|
||||
|
||||
// dst = L^-1 (P b)
|
||||
matrixL().solveInPlace(dst);
|
||||
// dst = L^-*T (P b)
|
||||
matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst);
|
||||
|
||||
// dst = D^-1 (L^-1 P b)
|
||||
// dst = D^-* (L^-1 P b)
|
||||
// dst = D^-1 (L^-*T P b)
|
||||
// more precisely, use pseudo-inverse of D (see bug 241)
|
||||
using std::abs;
|
||||
const typename Diagonal<const MatrixType>::RealReturnType vecD(vectorD());
|
||||
// In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon
|
||||
// as motivated by LAPACK's xGELSS:
|
||||
// In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min())
|
||||
// and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS:
|
||||
// RealScalar tolerance = numext::maxi(vecD.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 leads to numerical issues in some cases.
|
||||
// Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
|
||||
RealScalar tolerance = RealScalar(1) / NumTraits<RealScalar>::highest();
|
||||
|
||||
// Using numeric_limits::min() gives us more robustness to denormals.
|
||||
RealScalar tolerance = (std::numeric_limits<RealScalar>::min)();
|
||||
for (Index i = 0; i < vecD.size(); ++i)
|
||||
{
|
||||
if(abs(vecD(i)) > tolerance)
|
||||
@@ -584,10 +601,12 @@ void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) cons
|
||||
dst.row(i).setZero();
|
||||
}
|
||||
|
||||
// dst = L^-T (D^-1 L^-1 P b)
|
||||
matrixU().solveInPlace(dst);
|
||||
// dst = L^-* (D^-* L^-1 P b)
|
||||
// dst = L^-T (D^-1 L^-*T P b)
|
||||
matrixL().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
|
||||
|
||||
// dst = P^-1 (L^-T D^-1 L^-1 P b) = A^-1 b
|
||||
// dst = P^T (L^-* D^-* L^-1 P b) = A^-1 b
|
||||
// dst = P^-T (L^-T D^-1 L^-*T P b) = A^-1 b
|
||||
dst = m_transpositions.transpose() * dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal{
|
||||
|
||||
template<typename _MatrixType, int _UpLo> struct traits<LLT<_MatrixType, _UpLo> >
|
||||
: traits<_MatrixType>
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
template<typename MatrixType, int UpLo> struct LLT_Traits;
|
||||
}
|
||||
|
||||
@@ -24,7 +34,7 @@ template<typename MatrixType, int UpLo> struct LLT_Traits;
|
||||
*
|
||||
* \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition
|
||||
* \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper.
|
||||
* The other triangular part won't be read.
|
||||
* The other triangular part won't be read.
|
||||
*
|
||||
* This class performs a LL^T Cholesky decomposition of a symmetric, positive definite
|
||||
* matrix A such that A = LL^* = U^*U, where L is lower triangular.
|
||||
@@ -41,27 +51,30 @@ template<typename MatrixType, int UpLo> struct LLT_Traits;
|
||||
* Example: \include LLT_example.cpp
|
||||
* Output: \verbinclude LLT_example.out
|
||||
*
|
||||
* \b Performance: for best performance, it is recommended to use a column-major storage format
|
||||
* with the Lower triangular part (the default), or, equivalently, a row-major storage format
|
||||
* with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization
|
||||
* step, and rank-updates can be up to 3 times slower.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered.
|
||||
* Therefore, the strict lower part does not have to store correct values.
|
||||
*
|
||||
* \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT
|
||||
*/
|
||||
/* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH)
|
||||
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
|
||||
* the strict lower part does not have to store correct values.
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo> class LLT
|
||||
: public SolverBase<LLT<_MatrixType, _UpLo> >
|
||||
{
|
||||
public:
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<LLT> Base;
|
||||
friend class SolverBase<LLT>;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(LLT)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
|
||||
enum {
|
||||
PacketSize = internal::packet_traits<Scalar>::size,
|
||||
@@ -96,7 +109,7 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
compute(matrix.derived());
|
||||
}
|
||||
|
||||
/** \brief Constructs a LDLT factorization from a given matrix
|
||||
/** \brief Constructs a LLT factorization from a given matrix
|
||||
*
|
||||
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when
|
||||
* \c MatrixType is a Eigen::Ref.
|
||||
@@ -125,6 +138,7 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
return Traits::getL(m_matrix);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
|
||||
*
|
||||
* Since this LLT class assumes anyway that the matrix A is invertible, the solution
|
||||
@@ -137,16 +151,11 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<LLT, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "LLT is not initialized.");
|
||||
eigen_assert(m_matrix.rows()==b.rows()
|
||||
&& "LLT::solve(): invalid number of rows of the right hand side matrix b");
|
||||
return Solve<LLT, Rhs>(*this, b.derived());
|
||||
}
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
template<typename Derived>
|
||||
void solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
void solveInPlace(const MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
template<typename InputType>
|
||||
LLT& compute(const EigenBase<InputType>& matrix);
|
||||
@@ -176,8 +185,8 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
* \returns \c Success if computation was succesful,
|
||||
* \c NumericalIssue if the matrix.appears to be negative.
|
||||
* \returns \c Success if computation was successful,
|
||||
* \c NumericalIssue if the matrix.appears not to be positive definite.
|
||||
*/
|
||||
ComputationInfo info() const
|
||||
{
|
||||
@@ -190,18 +199,20 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
* This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as:
|
||||
* \code x = decomposition.adjoint().solve(b) \endcode
|
||||
*/
|
||||
const LLT& adjoint() const { return *this; };
|
||||
const LLT& adjoint() const EIGEN_NOEXCEPT { return *this; };
|
||||
|
||||
inline Index rows() const { return m_matrix.rows(); }
|
||||
inline Index cols() const { return m_matrix.cols(); }
|
||||
inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
|
||||
template<typename VectorType>
|
||||
LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
|
||||
LLT & rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -425,7 +436,8 @@ LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>
|
||||
eigen_assert(a.rows()==a.cols());
|
||||
const Index size = a.rows();
|
||||
m_matrix.resize(size, size);
|
||||
m_matrix = a.derived();
|
||||
if (!internal::is_same_dense(m_matrix, a.derived()))
|
||||
m_matrix = a.derived();
|
||||
|
||||
// Compute matrix L1 norm = max abs column sum.
|
||||
m_l1_norm = RealScalar(0);
|
||||
@@ -454,7 +466,7 @@ LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>
|
||||
*/
|
||||
template<typename _MatrixType, int _UpLo>
|
||||
template<typename VectorType>
|
||||
LLT<_MatrixType,_UpLo> LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma)
|
||||
LLT<_MatrixType,_UpLo> & LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType);
|
||||
eigen_assert(v.size()==m_matrix.cols());
|
||||
@@ -472,8 +484,17 @@ template<typename _MatrixType,int _UpLo>
|
||||
template<typename RhsType, typename DstType>
|
||||
void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
dst = rhs;
|
||||
solveInPlace(dst);
|
||||
_solve_impl_transposed<true>(rhs, dst);
|
||||
}
|
||||
|
||||
template<typename _MatrixType,int _UpLo>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void LLT<_MatrixType,_UpLo>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
dst = rhs;
|
||||
|
||||
matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst);
|
||||
matrixU().template conjugateIf<!Conjugate>().solveInPlace(dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -485,11 +506,14 @@ void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
*
|
||||
* This version avoids a copy when the right hand side matrix b is not needed anymore.
|
||||
*
|
||||
* \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
|
||||
* This function will const_cast it, so constness isn't honored here.
|
||||
*
|
||||
* \sa LLT::solve(), MatrixBase::llt()
|
||||
*/
|
||||
template<typename MatrixType, int _UpLo>
|
||||
template<typename Derived>
|
||||
void LLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
|
||||
void LLT<MatrixType,_UpLo>::solveInPlace(const MatrixBase<Derived> &bAndX) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "LLT is not initialized.");
|
||||
eigen_assert(m_matrix.rows()==bAndX.rows());
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_CHOLMODSUPPORT_H
|
||||
#define EIGEN_CHOLMODSUPPORT_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -32,7 +32,7 @@ template<> struct cholmod_configure_matrix<std::complex<double> > {
|
||||
}
|
||||
};
|
||||
|
||||
// Other scalar types are not yet suppotred by Cholmod
|
||||
// Other scalar types are not yet supported by Cholmod
|
||||
// template<> struct cholmod_configure_matrix<float> {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
@@ -79,12 +79,12 @@ cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> >
|
||||
|
||||
res.dtype = 0;
|
||||
res.stype = -1;
|
||||
|
||||
|
||||
if (internal::is_same<_StorageIndex,int>::value)
|
||||
{
|
||||
res.itype = CHOLMOD_INT;
|
||||
}
|
||||
else if (internal::is_same<_StorageIndex,long>::value)
|
||||
else if (internal::is_same<_StorageIndex,SuiteSparse_long>::value)
|
||||
{
|
||||
res.itype = CHOLMOD_LONG;
|
||||
}
|
||||
@@ -95,9 +95,9 @@ cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> >
|
||||
|
||||
// setup res.xtype
|
||||
internal::cholmod_configure_matrix<_Scalar>::run(res);
|
||||
|
||||
|
||||
res.stype = 0;
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -121,9 +121,12 @@ template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
|
||||
cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
|
||||
{
|
||||
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
|
||||
|
||||
|
||||
if(UpLo==Upper) res.stype = 1;
|
||||
if(UpLo==Lower) res.stype = -1;
|
||||
// swap stype for rowmajor matrices (only works for real matrices)
|
||||
EIGEN_STATIC_ASSERT((_Options & RowMajorBit) == 0 || NumTraits<_Scalar>::IsComplex == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
if(_Options & RowMajorBit) res.stype *=-1;
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -159,6 +162,44 @@ MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
|
||||
static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
// template specializations for int and long that call the correct cholmod method
|
||||
|
||||
#define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
|
||||
template<typename _StorageIndex> inline ret cm_ ## name (cholmod_common &Common) { return cholmod_ ## name (&Common); } \
|
||||
template<> inline ret cm_ ## name<SuiteSparse_long> (cholmod_common &Common) { return cholmod_l_ ## name (&Common); }
|
||||
|
||||
#define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
|
||||
template<typename _StorageIndex> inline ret cm_ ## name (t1& a1, cholmod_common &Common) { return cholmod_ ## name (&a1, &Common); } \
|
||||
template<> inline ret cm_ ## name<SuiteSparse_long> (t1& a1, cholmod_common &Common) { return cholmod_l_ ## name (&a1, &Common); }
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE0(int, start)
|
||||
EIGEN_CHOLMOD_SPECIALIZE0(int, finish)
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L)
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense, cholmod_dense*, X)
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A)
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
|
||||
|
||||
template<typename _StorageIndex> inline cholmod_dense* cm_solve (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_solve (sys, &L, &B, &Common); }
|
||||
template<> inline cholmod_dense* cm_solve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_l_solve (sys, &L, &B, &Common); }
|
||||
|
||||
template<typename _StorageIndex> inline cholmod_sparse* cm_spsolve (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_spsolve (sys, &L, &B, &Common); }
|
||||
template<> inline cholmod_sparse* cm_spsolve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_l_spsolve (sys, &L, &B, &Common); }
|
||||
|
||||
template<typename _StorageIndex>
|
||||
inline int cm_factorize_p (cholmod_sparse* A, double beta[2], _StorageIndex* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_factorize_p (A, beta, fset, fsize, L, &Common); }
|
||||
template<>
|
||||
inline int cm_factorize_p<SuiteSparse_long> (cholmod_sparse* A, double beta[2], SuiteSparse_long* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_l_factorize_p (A, beta, fset, fsize, L, &Common); }
|
||||
|
||||
#undef EIGEN_CHOLMOD_SPECIALIZE0
|
||||
#undef EIGEN_CHOLMOD_SPECIALIZE1
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
enum CholmodMode {
|
||||
CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
|
||||
};
|
||||
@@ -195,7 +236,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
internal::cm_start<StorageIndex>(m_cholmod);
|
||||
}
|
||||
|
||||
explicit CholmodBase(const MatrixType& matrix)
|
||||
@@ -203,23 +244,23 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
cholmod_start(&m_cholmod);
|
||||
internal::cm_start<StorageIndex>(m_cholmod);
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
~CholmodBase()
|
||||
{
|
||||
if(m_cholmodFactor)
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
cholmod_finish(&m_cholmod);
|
||||
internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
|
||||
internal::cm_finish<StorageIndex>(m_cholmod);
|
||||
}
|
||||
|
||||
|
||||
inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
|
||||
inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
|
||||
|
||||
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
* \returns \c Success if computation was succesful,
|
||||
* \returns \c Success if computation was successful,
|
||||
* \c NumericalIssue if the matrix.appears to be negative.
|
||||
*/
|
||||
ComputationInfo info() const
|
||||
@@ -235,29 +276,29 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
factorize(matrix);
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
/** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
*
|
||||
* \sa factorize()
|
||||
*/
|
||||
void analyzePattern(const MatrixType& matrix)
|
||||
{
|
||||
if(m_cholmodFactor)
|
||||
{
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
|
||||
m_cholmodFactor = 0;
|
||||
}
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
|
||||
|
||||
m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
|
||||
|
||||
this->m_isInitialized = true;
|
||||
this->m_info = Success;
|
||||
m_analysisIsOk = true;
|
||||
m_factorizationIsOk = false;
|
||||
}
|
||||
|
||||
|
||||
/** 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.
|
||||
@@ -268,17 +309,17 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
{
|
||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
|
||||
internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
|
||||
|
||||
// If the factorization failed, minor is the column at which it did. On success minor == n.
|
||||
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
|
||||
m_factorizationIsOk = true;
|
||||
}
|
||||
|
||||
|
||||
/** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations.
|
||||
* See the Cholmod user guide for details. */
|
||||
cholmod_common& cholmod() { return m_cholmod; }
|
||||
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal */
|
||||
template<typename Rhs,typename Dest>
|
||||
@@ -288,22 +329,23 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
const Index size = m_cholmodFactor->n;
|
||||
EIGEN_UNUSED_VARIABLE(size);
|
||||
eigen_assert(size==b.rows());
|
||||
|
||||
// Cholmod needs column-major stoarge without inner-stride, which corresponds to the default behavior of Ref.
|
||||
|
||||
// Cholmod needs column-major storage without inner-stride, which corresponds to the default behavior of Ref.
|
||||
Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.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 = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
|
||||
if(!x_cd)
|
||||
{
|
||||
this->m_info = NumericalIssue;
|
||||
return;
|
||||
}
|
||||
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||
// NOTE Actually, the copy can be avoided by calling cholmod_solve2 instead of cholmod_solve
|
||||
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);
|
||||
internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
|
||||
}
|
||||
|
||||
|
||||
/** \internal */
|
||||
template<typename RhsDerived, typename DestDerived>
|
||||
void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
|
||||
@@ -316,19 +358,20 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
// note: cs stands for Cholmod Sparse
|
||||
Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
|
||||
cholmod_sparse b_cs = viewAsCholmod(b_ref);
|
||||
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
|
||||
cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
|
||||
if(!x_cs)
|
||||
{
|
||||
this->m_info = NumericalIssue;
|
||||
return;
|
||||
}
|
||||
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||
// NOTE cholmod_spsolve in fact just calls the dense solver for blocks of 4 columns at a time (similar to Eigen's sparse solver)
|
||||
dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
|
||||
cholmod_free_sparse(&x_cs, &m_cholmod);
|
||||
internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
|
||||
}
|
||||
#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
|
||||
@@ -343,7 +386,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
m_shiftOffset[0] = double(offset);
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
/** \returns the determinant of the underlying matrix from the current factorization */
|
||||
Scalar determinant() const
|
||||
{
|
||||
@@ -398,7 +441,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
||||
template<typename Stream>
|
||||
void dumpMemory(Stream& /*s*/)
|
||||
{}
|
||||
|
||||
|
||||
protected:
|
||||
mutable cholmod_common m_cholmod;
|
||||
cholmod_factor* m_cholmodFactor;
|
||||
@@ -435,11 +478,11 @@ class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimpl
|
||||
{
|
||||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base;
|
||||
using Base::m_cholmod;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
|
||||
|
||||
CholmodSimplicialLLT() : Base() { init(); }
|
||||
|
||||
CholmodSimplicialLLT(const MatrixType& matrix) : Base()
|
||||
@@ -486,11 +529,11 @@ class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimp
|
||||
{
|
||||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base;
|
||||
using Base::m_cholmod;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
|
||||
|
||||
CholmodSimplicialLDLT() : Base() { init(); }
|
||||
|
||||
CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
|
||||
@@ -535,11 +578,11 @@ class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSuper
|
||||
{
|
||||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base;
|
||||
using Base::m_cholmod;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
|
||||
|
||||
CholmodSupernodalLLT() : Base() { init(); }
|
||||
|
||||
CholmodSupernodalLLT(const MatrixType& matrix) : Base()
|
||||
@@ -586,11 +629,11 @@ class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecom
|
||||
{
|
||||
typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base;
|
||||
using Base::m_cholmod;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
|
||||
|
||||
CholmodDecomposition() : Base() { init(); }
|
||||
|
||||
CholmodDecomposition(const MatrixType& matrix) : Base()
|
||||
@@ -600,7 +643,7 @@ class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecom
|
||||
}
|
||||
|
||||
~CholmodDecomposition() {}
|
||||
|
||||
|
||||
void setMode(CholmodMode mode)
|
||||
{
|
||||
switch(mode)
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2017 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_ARITHMETIC_SEQUENCE_H
|
||||
#define EIGEN_ARITHMETIC_SEQUENCE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
#if (!EIGEN_HAS_CXX11) || !((!EIGEN_COMP_GNUC) || EIGEN_COMP_GNUC>=48)
|
||||
template<typename T> struct aseq_negate {};
|
||||
|
||||
template<> struct aseq_negate<Index> {
|
||||
typedef Index type;
|
||||
};
|
||||
|
||||
template<int N> struct aseq_negate<FixedInt<N> > {
|
||||
typedef FixedInt<-N> type;
|
||||
};
|
||||
|
||||
// Compilation error in the following case:
|
||||
template<> struct aseq_negate<FixedInt<DynamicIndex> > {};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType,
|
||||
bool FirstIsSymbolic=symbolic::is_symbolic<FirstType>::value,
|
||||
bool SizeIsSymbolic =symbolic::is_symbolic<SizeType>::value>
|
||||
struct aseq_reverse_first_type {
|
||||
typedef Index type;
|
||||
};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,true> {
|
||||
typedef symbolic::AddExpr<FirstType,
|
||||
symbolic::ProductExpr<symbolic::AddExpr<SizeType,symbolic::ValueExpr<FixedInt<-1> > >,
|
||||
symbolic::ValueExpr<IncrType> >
|
||||
> type;
|
||||
};
|
||||
|
||||
template<typename SizeType,typename IncrType,typename EnableIf = void>
|
||||
struct aseq_reverse_first_type_aux {
|
||||
typedef Index type;
|
||||
};
|
||||
|
||||
template<typename SizeType,typename IncrType>
|
||||
struct aseq_reverse_first_type_aux<SizeType,IncrType,typename internal::enable_if<bool((SizeType::value+IncrType::value)|0x1)>::type> {
|
||||
typedef FixedInt<(SizeType::value-1)*IncrType::value> type;
|
||||
};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,true,false> {
|
||||
typedef typename aseq_reverse_first_type_aux<SizeType,IncrType>::type Aux;
|
||||
typedef symbolic::AddExpr<FirstType,symbolic::ValueExpr<Aux> > type;
|
||||
};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
struct aseq_reverse_first_type<FirstType,SizeType,IncrType,false,true> {
|
||||
typedef symbolic::AddExpr<symbolic::ProductExpr<symbolic::AddExpr<SizeType,symbolic::ValueExpr<FixedInt<-1> > >,
|
||||
symbolic::ValueExpr<IncrType> >,
|
||||
symbolic::ValueExpr<> > type;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Helper to cleanup the type of the increment:
|
||||
template<typename T> struct cleanup_seq_incr {
|
||||
typedef typename cleanup_index_type<T,DynamicIndex>::type type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// seq(first,last,incr) and seqN(first,size,incr)
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
template<typename FirstType=Index,typename SizeType=Index,typename IncrType=internal::FixedInt<1> >
|
||||
class ArithmeticSequence;
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
|
||||
typename internal::cleanup_index_type<SizeType>::type,
|
||||
typename internal::cleanup_seq_incr<IncrType>::type >
|
||||
seqN(FirstType first, SizeType size, IncrType incr);
|
||||
|
||||
/** \class ArithmeticSequence
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* This class represents an arithmetic progression \f$ a_0, a_1, a_2, ..., a_{n-1}\f$ defined by
|
||||
* its \em first value \f$ a_0 \f$, its \em size (aka length) \em n, and the \em increment (aka stride)
|
||||
* that is equal to \f$ a_{i+1}-a_{i}\f$ for any \em i.
|
||||
*
|
||||
* It is internally used as the return type of the Eigen::seq and Eigen::seqN functions, and as the input arguments
|
||||
* of DenseBase::operator()(const RowIndices&, const ColIndices&), and most of the time this is the
|
||||
* only way it is used.
|
||||
*
|
||||
* \tparam FirstType type of the first element, usually an Index,
|
||||
* but internally it can be a symbolic expression
|
||||
* \tparam SizeType type representing the size of the sequence, usually an Index
|
||||
* or a compile time integral constant. Internally, it can also be a symbolic expression
|
||||
* \tparam IncrType type of the increment, can be a runtime Index, or a compile time integral constant (default is compile-time 1)
|
||||
*
|
||||
* \sa Eigen::seq, Eigen::seqN, DenseBase::operator()(const RowIndices&, const ColIndices&), class IndexedView
|
||||
*/
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
class ArithmeticSequence
|
||||
{
|
||||
public:
|
||||
ArithmeticSequence(FirstType first, SizeType size) : m_first(first), m_size(size) {}
|
||||
ArithmeticSequence(FirstType first, SizeType size, IncrType incr) : m_first(first), m_size(size), m_incr(incr) {}
|
||||
|
||||
enum {
|
||||
SizeAtCompileTime = internal::get_fixed_value<SizeType>::value,
|
||||
IncrAtCompileTime = internal::get_fixed_value<IncrType,DynamicIndex>::value
|
||||
};
|
||||
|
||||
/** \returns the size, i.e., number of elements, of the sequence */
|
||||
Index size() const { return m_size; }
|
||||
|
||||
/** \returns the first element \f$ a_0 \f$ in the sequence */
|
||||
Index first() const { return m_first; }
|
||||
|
||||
/** \returns the value \f$ a_i \f$ at index \a i in the sequence. */
|
||||
Index operator[](Index i) const { return m_first + i * m_incr; }
|
||||
|
||||
const FirstType& firstObject() const { return m_first; }
|
||||
const SizeType& sizeObject() const { return m_size; }
|
||||
const IncrType& incrObject() const { return m_incr; }
|
||||
|
||||
protected:
|
||||
FirstType m_first;
|
||||
SizeType m_size;
|
||||
IncrType m_incr;
|
||||
|
||||
public:
|
||||
|
||||
#if EIGEN_HAS_CXX11 && ((!EIGEN_COMP_GNUC) || EIGEN_COMP_GNUC>=48)
|
||||
auto reverse() const -> decltype(Eigen::seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr)) {
|
||||
return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr);
|
||||
}
|
||||
#else
|
||||
protected:
|
||||
typedef typename internal::aseq_negate<IncrType>::type ReverseIncrType;
|
||||
typedef typename internal::aseq_reverse_first_type<FirstType,SizeType,IncrType>::type ReverseFirstType;
|
||||
public:
|
||||
ArithmeticSequence<ReverseFirstType,SizeType,ReverseIncrType>
|
||||
reverse() const {
|
||||
return seqN(m_first+(m_size+fix<-1>())*m_incr,m_size,-m_incr);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a first, of length \a size, and increment \a incr
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type,typename internal::cleanup_seq_incr<IncrType>::type >
|
||||
seqN(FirstType first, SizeType size, IncrType incr) {
|
||||
return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type,typename internal::cleanup_seq_incr<IncrType>::type>(first,size,incr);
|
||||
}
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a first, of length \a size, and unit increment
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType) */
|
||||
template<typename FirstType,typename SizeType>
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type >
|
||||
seqN(FirstType first, SizeType size) {
|
||||
return ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,typename internal::cleanup_index_type<SizeType>::type>(first,size);
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and with positive (or negative) increment \a incr
|
||||
*
|
||||
* It is essentially an alias to:
|
||||
* \code
|
||||
* seqN(f, (l-f+incr)/incr, incr);
|
||||
* \endcode
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType,IncrType), seq(FirstType,LastType)
|
||||
*/
|
||||
template<typename FirstType,typename LastType, typename IncrType>
|
||||
auto seq(FirstType f, LastType l, IncrType incr);
|
||||
|
||||
/** \returns an ArithmeticSequence starting at \a f, up (or down) to \a l, and unit increment
|
||||
*
|
||||
* It is essentially an alias to:
|
||||
* \code
|
||||
* seqN(f,l-f+1);
|
||||
* \endcode
|
||||
*
|
||||
* \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType)
|
||||
*/
|
||||
template<typename FirstType,typename LastType>
|
||||
auto seq(FirstType f, LastType l);
|
||||
|
||||
#else // EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
template<typename FirstType,typename LastType>
|
||||
auto seq(FirstType f, LastType l) -> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
( typename internal::cleanup_index_type<LastType>::type(l)
|
||||
- typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())))
|
||||
{
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
(typename internal::cleanup_index_type<LastType>::type(l)
|
||||
-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()));
|
||||
}
|
||||
|
||||
template<typename FirstType,typename LastType, typename IncrType>
|
||||
auto seq(FirstType f, LastType l, IncrType incr)
|
||||
-> decltype(seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
( typename internal::cleanup_index_type<LastType>::type(l)
|
||||
- typename internal::cleanup_index_type<FirstType>::type(f)+typename internal::cleanup_seq_incr<IncrType>::type(incr)
|
||||
) / typename internal::cleanup_seq_incr<IncrType>::type(incr),
|
||||
typename internal::cleanup_seq_incr<IncrType>::type(incr)))
|
||||
{
|
||||
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
( typename internal::cleanup_index_type<LastType>::type(l)
|
||||
-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr)) / CleanedIncrType(incr),
|
||||
CleanedIncrType(incr));
|
||||
}
|
||||
|
||||
#else // EIGEN_HAS_CXX11
|
||||
|
||||
template<typename FirstType,typename LastType>
|
||||
typename internal::enable_if<!(symbolic::is_symbolic<FirstType>::value || symbolic::is_symbolic<LastType>::value),
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index> >::type
|
||||
seq(FirstType f, LastType l)
|
||||
{
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>())));
|
||||
}
|
||||
|
||||
template<typename FirstTypeDerived,typename LastType>
|
||||
typename internal::enable_if<!symbolic::is_symbolic<LastType>::value,
|
||||
ArithmeticSequence<FirstTypeDerived, symbolic::AddExpr<symbolic::AddExpr<symbolic::NegateExpr<FirstTypeDerived>,symbolic::ValueExpr<> >,
|
||||
symbolic::ValueExpr<internal::FixedInt<1> > > > >::type
|
||||
seq(const symbolic::BaseExpr<FirstTypeDerived> &f, LastType l)
|
||||
{
|
||||
return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+fix<1>()));
|
||||
}
|
||||
|
||||
template<typename FirstType,typename LastTypeDerived>
|
||||
typename internal::enable_if<!symbolic::is_symbolic<FirstType>::value,
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
|
||||
symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::ValueExpr<> >,
|
||||
symbolic::ValueExpr<internal::FixedInt<1> > > > >::type
|
||||
seq(FirstType f, const symbolic::BaseExpr<LastTypeDerived> &l)
|
||||
{
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),(l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+fix<1>()));
|
||||
}
|
||||
|
||||
template<typename FirstTypeDerived,typename LastTypeDerived>
|
||||
ArithmeticSequence<FirstTypeDerived,
|
||||
symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::NegateExpr<FirstTypeDerived> >,symbolic::ValueExpr<internal::FixedInt<1> > > >
|
||||
seq(const symbolic::BaseExpr<FirstTypeDerived> &f, const symbolic::BaseExpr<LastTypeDerived> &l)
|
||||
{
|
||||
return seqN(f.derived(),(l.derived()-f.derived()+fix<1>()));
|
||||
}
|
||||
|
||||
|
||||
template<typename FirstType,typename LastType, typename IncrType>
|
||||
typename internal::enable_if<!(symbolic::is_symbolic<FirstType>::value || symbolic::is_symbolic<LastType>::value),
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,Index,typename internal::cleanup_seq_incr<IncrType>::type> >::type
|
||||
seq(FirstType f, LastType l, IncrType incr)
|
||||
{
|
||||
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
Index((typename internal::cleanup_index_type<LastType>::type(l)-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr)), incr);
|
||||
}
|
||||
|
||||
template<typename FirstTypeDerived,typename LastType, typename IncrType>
|
||||
typename internal::enable_if<!symbolic::is_symbolic<LastType>::value,
|
||||
ArithmeticSequence<FirstTypeDerived,
|
||||
symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<symbolic::NegateExpr<FirstTypeDerived>,
|
||||
symbolic::ValueExpr<> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
typename internal::cleanup_seq_incr<IncrType>::type> >::type
|
||||
seq(const symbolic::BaseExpr<FirstTypeDerived> &f, LastType l, IncrType incr)
|
||||
{
|
||||
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
|
||||
return seqN(f.derived(),(typename internal::cleanup_index_type<LastType>::type(l)-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
|
||||
}
|
||||
|
||||
template<typename FirstType,typename LastTypeDerived, typename IncrType>
|
||||
typename internal::enable_if<!symbolic::is_symbolic<FirstType>::value,
|
||||
ArithmeticSequence<typename internal::cleanup_index_type<FirstType>::type,
|
||||
symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,symbolic::ValueExpr<> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
typename internal::cleanup_seq_incr<IncrType>::type> >::type
|
||||
seq(FirstType f, const symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
|
||||
{
|
||||
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
|
||||
return seqN(typename internal::cleanup_index_type<FirstType>::type(f),
|
||||
(l.derived()-typename internal::cleanup_index_type<FirstType>::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
|
||||
}
|
||||
|
||||
template<typename FirstTypeDerived,typename LastTypeDerived, typename IncrType>
|
||||
ArithmeticSequence<FirstTypeDerived,
|
||||
symbolic::QuotientExpr<symbolic::AddExpr<symbolic::AddExpr<LastTypeDerived,
|
||||
symbolic::NegateExpr<FirstTypeDerived> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
symbolic::ValueExpr<typename internal::cleanup_seq_incr<IncrType>::type> >,
|
||||
typename internal::cleanup_seq_incr<IncrType>::type>
|
||||
seq(const symbolic::BaseExpr<FirstTypeDerived> &f, const symbolic::BaseExpr<LastTypeDerived> &l, IncrType incr)
|
||||
{
|
||||
typedef typename internal::cleanup_seq_incr<IncrType>::type CleanedIncrType;
|
||||
return seqN(f.derived(),(l.derived()-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr);
|
||||
}
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
#endif // EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
|
||||
#if EIGEN_HAS_CXX11 || defined(EIGEN_PARSED_BY_DOXYGEN)
|
||||
/** \cpp11
|
||||
* \returns a symbolic ArithmeticSequence representing the last \a size elements with increment \a incr.
|
||||
*
|
||||
* It is a shortcut for: \code seqN(last-(size-fix<1>)*incr, size, incr) \endcode
|
||||
*
|
||||
* \sa lastN(SizeType), seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */
|
||||
template<typename SizeType,typename IncrType>
|
||||
auto lastN(SizeType size, IncrType incr)
|
||||
-> decltype(seqN(Eigen::last-(size-fix<1>())*incr, size, incr))
|
||||
{
|
||||
return seqN(Eigen::last-(size-fix<1>())*incr, size, incr);
|
||||
}
|
||||
|
||||
/** \cpp11
|
||||
* \returns a symbolic ArithmeticSequence representing the last \a size elements with a unit increment.
|
||||
*
|
||||
* It is a shortcut for: \code seq(last+fix<1>-size, last) \endcode
|
||||
*
|
||||
* \sa lastN(SizeType,IncrType, seqN(FirstType,SizeType), seq(FirstType,LastType) */
|
||||
template<typename SizeType>
|
||||
auto lastN(SizeType size)
|
||||
-> decltype(seqN(Eigen::last+fix<1>()-size, size))
|
||||
{
|
||||
return seqN(Eigen::last+fix<1>()-size, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Convert a symbolic span into a usable one (i.e., remove last/end "keywords")
|
||||
template<typename T>
|
||||
struct make_size_type {
|
||||
typedef typename internal::conditional<symbolic::is_symbolic<T>::value, Index, T>::type type;
|
||||
};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType,int XprSize>
|
||||
struct IndexedViewCompatibleType<ArithmeticSequence<FirstType,SizeType,IncrType>, XprSize> {
|
||||
typedef ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType> type;
|
||||
};
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>
|
||||
makeIndexedViewCompatible(const ArithmeticSequence<FirstType,SizeType,IncrType>& ids, Index size,SpecializedType) {
|
||||
return ArithmeticSequence<Index,typename make_size_type<SizeType>::type,IncrType>(
|
||||
eval_expr_given_size(ids.firstObject(),size),eval_expr_given_size(ids.sizeObject(),size),ids.incrObject());
|
||||
}
|
||||
|
||||
template<typename FirstType,typename SizeType,typename IncrType>
|
||||
struct get_compile_time_incr<ArithmeticSequence<FirstType,SizeType,IncrType> > {
|
||||
enum { value = get_fixed_value<IncrType,DynamicIndex>::value };
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \namespace Eigen::indexing
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* The sole purpose of this namespace is to be able to import all functions
|
||||
* and symbols that are expected to be used within operator() for indexing
|
||||
* and slicing. If you already imported the whole Eigen namespace:
|
||||
* \code using namespace Eigen; \endcode
|
||||
* then you are already all set. Otherwise, if you don't want/cannot import
|
||||
* the whole Eigen namespace, the following line:
|
||||
* \code using namespace Eigen::indexing; \endcode
|
||||
* is equivalent to:
|
||||
* \code
|
||||
using Eigen::all;
|
||||
using Eigen::seq;
|
||||
using Eigen::seqN;
|
||||
using Eigen::lastN; // c++11 only
|
||||
using Eigen::last;
|
||||
using Eigen::lastp1;
|
||||
using Eigen::fix;
|
||||
\endcode
|
||||
*/
|
||||
namespace indexing {
|
||||
using Eigen::all;
|
||||
using Eigen::seq;
|
||||
using Eigen::seqN;
|
||||
#if EIGEN_HAS_CXX11
|
||||
using Eigen::lastN;
|
||||
#endif
|
||||
using Eigen::last;
|
||||
using Eigen::lastp1;
|
||||
using Eigen::fix;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ARITHMETIC_SEQUENCE_H
|
||||
+99
-13
@@ -117,7 +117,7 @@ class Array
|
||||
{
|
||||
return Base::_set(other);
|
||||
}
|
||||
|
||||
|
||||
/** Default constructor.
|
||||
*
|
||||
* For fixed-size matrices, does nothing.
|
||||
@@ -153,17 +153,54 @@ class Array
|
||||
: Base(std::move(other))
|
||||
{
|
||||
Base::_check_template_params();
|
||||
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
|
||||
Base::_set_noalias(other);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
Array& operator=(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value)
|
||||
{
|
||||
other.swap(*this);
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \copydoc PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
*
|
||||
* Example: \include Array_variadic_ctor_cxx11.cpp
|
||||
* Output: \verbinclude Array_variadic_ctor_cxx11.out
|
||||
*
|
||||
* \sa Array(const std::initializer_list<std::initializer_list<Scalar>>&)
|
||||
* \sa Array(const Scalar&), Array(const Scalar&,const Scalar&)
|
||||
*/
|
||||
template <typename... ArgTypes>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
: Base(a0, a1, a2, a3, args...) {}
|
||||
|
||||
/** \brief Constructs an array and initializes it from the coefficients given as initializer-lists grouped by row. \cpp11
|
||||
*
|
||||
* In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients:
|
||||
*
|
||||
* Example: \include Array_initializer_list_23_cxx11.cpp
|
||||
* Output: \verbinclude Array_initializer_list_23_cxx11.out
|
||||
*
|
||||
* Each of the inner initializer lists must contain the exact same number of elements, otherwise an assertion is triggered.
|
||||
*
|
||||
* In the case of a compile-time column 1D array, implicit transposition from a single row is allowed.
|
||||
* Therefore <code> Array<int,Dynamic,1>{{1,2,3,4,5}}</code> is legal and the more verbose syntax
|
||||
* <code>Array<int,Dynamic,1>{{1},{2},{3},{4},{5}}</code> can be avoided:
|
||||
*
|
||||
* Example: \include Array_initializer_list_vector_cxx11.cpp
|
||||
* Output: \verbinclude Array_initializer_list_vector_cxx11.out
|
||||
*
|
||||
* In the case of fixed-sized arrays, the initializer list sizes must exactly match the array sizes,
|
||||
* and implicit transposition is allowed for compile-time 1D arrays only.
|
||||
*
|
||||
* \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Array(const std::initializer_list<std::initializer_list<Scalar>>& list) : Base(list) {}
|
||||
#endif // end EIGEN_HAS_CXX11
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -180,6 +217,7 @@ class Array
|
||||
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);
|
||||
@@ -191,7 +229,8 @@ class Array
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE explicit Array(Index dim);
|
||||
/** constructs an initialized 1x1 Array with the given coefficient */
|
||||
/** constructs an initialized 1x1 Array with the given coefficient
|
||||
* \sa const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args */
|
||||
Array(const Scalar& value);
|
||||
/** constructs an uninitialized array with \a rows rows and \a cols columns.
|
||||
*
|
||||
@@ -199,11 +238,14 @@ class Array
|
||||
* it is redundant to pass these parameters, so one should use the default constructor
|
||||
* Array() instead. */
|
||||
Array(Index rows, Index cols);
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
/** constructs an initialized 2D vector with given coefficients
|
||||
* \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args) */
|
||||
Array(const Scalar& val0, const Scalar& val1);
|
||||
#endif
|
||||
#endif // end EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** constructs an initialized 3D vector with given coefficients */
|
||||
/** constructs an initialized 3D vector with given coefficients
|
||||
* \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2)
|
||||
{
|
||||
@@ -213,7 +255,9 @@ class Array
|
||||
m_storage.data()[1] = val1;
|
||||
m_storage.data()[2] = val2;
|
||||
}
|
||||
/** constructs an initialized 4D vector with given coefficients */
|
||||
/** constructs an initialized 4D vector with given coefficients
|
||||
* \sa Array(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2, const Scalar& val3)
|
||||
{
|
||||
@@ -244,8 +288,10 @@ class Array
|
||||
: Base(other.derived())
|
||||
{ }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const { return 1; }
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const { return this->innerSize(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT{ return 1; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return this->innerSize(); }
|
||||
|
||||
#ifdef EIGEN_ARRAY_PLUGIN
|
||||
#include EIGEN_ARRAY_PLUGIN
|
||||
@@ -260,7 +306,7 @@ class Array
|
||||
/** \defgroup arraytypedefs Global array typedefs
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* Eigen defines several typedef shortcuts for most common 1D and 2D array types.
|
||||
* %Eigen defines several typedef shortcuts for most common 1D and 2D array types.
|
||||
*
|
||||
* The general patterns are the following:
|
||||
*
|
||||
@@ -273,6 +319,12 @@ class Array
|
||||
* There are also \c ArraySizeType which are self-explanatory. For example, \c Array4cf is
|
||||
* a fixed-size 1D array of 4 complex floats.
|
||||
*
|
||||
* With \cpp11, template alias are also defined for common sizes.
|
||||
* They follow the same pattern as above except that the scalar type suffix is replaced by a
|
||||
* template parameter, i.e.:
|
||||
* - `ArrayRowsCols<Type>` where `Rows` and `Cols` can be \c 2,\c 3,\c 4, or \c X for fixed or dynamic size.
|
||||
* - `ArraySize<Type>` where `Size` can be \c 2,\c 3,\c 4 or \c X for fixed or dynamic size 1D arrays.
|
||||
*
|
||||
* \sa class Array
|
||||
*/
|
||||
|
||||
@@ -305,8 +357,42 @@ EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
|
||||
|
||||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES
|
||||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS
|
||||
#undef EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS
|
||||
|
||||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_LARGE
|
||||
#if EIGEN_HAS_CXX11
|
||||
|
||||
#define EIGEN_MAKE_ARRAY_TYPEDEFS(Size, SizeSuffix) \
|
||||
/** \ingroup arraytypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Array##SizeSuffix##SizeSuffix = Array<Type, Size, Size>; \
|
||||
/** \ingroup arraytypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Array##SizeSuffix = Array<Type, Size, 1>;
|
||||
|
||||
#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Size) \
|
||||
/** \ingroup arraytypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Array##Size##X = Array<Type, Size, Dynamic>; \
|
||||
/** \ingroup arraytypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Array##X##Size = Array<Type, Dynamic, Size>;
|
||||
|
||||
EIGEN_MAKE_ARRAY_TYPEDEFS(2, 2)
|
||||
EIGEN_MAKE_ARRAY_TYPEDEFS(3, 3)
|
||||
EIGEN_MAKE_ARRAY_TYPEDEFS(4, 4)
|
||||
EIGEN_MAKE_ARRAY_TYPEDEFS(Dynamic, X)
|
||||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(2)
|
||||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(3)
|
||||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(4)
|
||||
|
||||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS
|
||||
#undef EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS
|
||||
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
|
||||
using Eigen::Matrix##SizeSuffix##TypeSuffix; \
|
||||
|
||||
@@ -69,6 +69,7 @@ template<typename Derived> class ArrayBase
|
||||
using Base::coeff;
|
||||
using Base::coeffRef;
|
||||
using Base::lazyAssign;
|
||||
using Base::operator-;
|
||||
using Base::operator=;
|
||||
using Base::operator+=;
|
||||
using Base::operator-=;
|
||||
@@ -88,7 +89,6 @@ template<typename Derived> class ArrayBase
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
|
||||
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||
# include "../plugins/ArrayCwiseUnaryOps.h"
|
||||
# include "../plugins/CommonCwiseBinaryOps.h"
|
||||
@@ -153,8 +153,8 @@ template<typename Derived> class ArrayBase
|
||||
// inline void evalTo(Dest& dst) const { dst = matrix(); }
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC
|
||||
ArrayBase() : Base() {}
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(ArrayBase)
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(ArrayBase)
|
||||
|
||||
private:
|
||||
explicit ArrayBase(Index);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_ARRAYWRAPPER_H
|
||||
#define EIGEN_ARRAYWRAPPER_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
/** \class ArrayWrapper
|
||||
* \ingroup Core_Module
|
||||
@@ -60,14 +60,14 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index rows() const { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index cols() const { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||
@@ -90,9 +90,9 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void evalTo(Dest& dst) const { dst = m_expression; }
|
||||
|
||||
const typename internal::remove_all<NestedExpressionType>::type&
|
||||
EIGEN_DEVICE_FUNC
|
||||
nestedExpression() const
|
||||
const typename internal::remove_all<NestedExpressionType>::type&
|
||||
nestedExpression() const
|
||||
{
|
||||
return m_expression;
|
||||
}
|
||||
@@ -158,14 +158,14 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index rows() const { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index cols() const { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index outerStride() const { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const { return m_expression.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
|
||||
@@ -185,8 +185,8 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename internal::remove_all<NestedExpressionType>::type&
|
||||
nestedExpression() const
|
||||
const typename internal::remove_all<NestedExpressionType>::type&
|
||||
nestedExpression() const
|
||||
{
|
||||
return m_expression;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Eigen {
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
|
||||
::lazyAssign(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
enum{
|
||||
|
||||
@@ -17,29 +17,29 @@ 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 DstEvaluator, typename SrcEvaluator, typename AssignFunc>
|
||||
template <typename DstEvaluator, typename SrcEvaluator, typename AssignFunc, int MaxPacketSize = -1>
|
||||
struct copy_using_evaluator_traits
|
||||
{
|
||||
typedef typename DstEvaluator::XprType Dst;
|
||||
typedef typename Dst::Scalar DstScalar;
|
||||
|
||||
|
||||
enum {
|
||||
DstFlags = DstEvaluator::Flags,
|
||||
SrcFlags = SrcEvaluator::Flags
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
enum {
|
||||
DstAlignment = DstEvaluator::Alignment,
|
||||
SrcAlignment = SrcEvaluator::Alignment,
|
||||
DstHasDirectAccess = DstFlags & DirectAccessBit,
|
||||
DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit,
|
||||
JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment,SrcAlignment)
|
||||
};
|
||||
|
||||
@@ -51,13 +51,15 @@ private:
|
||||
InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
|
||||
: int(DstFlags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
|
||||
: int(Dst::MaxRowsAtCompileTime),
|
||||
RestrictedInnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(InnerSize,MaxPacketSize),
|
||||
RestrictedLinearSize = EIGEN_SIZE_MIN_PREFER_FIXED(Dst::SizeAtCompileTime,MaxPacketSize),
|
||||
OuterStride = int(outer_stride_at_compile_time<Dst>::ret),
|
||||
MaxSizeAtCompileTime = Dst::SizeAtCompileTime
|
||||
};
|
||||
|
||||
// TODO distinguish between linear traversal and inner-traversals
|
||||
typedef typename find_best_packet<DstScalar,Dst::SizeAtCompileTime>::type LinearPacketType;
|
||||
typedef typename find_best_packet<DstScalar,InnerSize>::type InnerPacketType;
|
||||
typedef typename find_best_packet<DstScalar,RestrictedLinearSize>::type LinearPacketType;
|
||||
typedef typename find_best_packet<DstScalar,RestrictedInnerSize>::type InnerPacketType;
|
||||
|
||||
enum {
|
||||
LinearPacketSize = unpacket_traits<LinearPacketType>::size,
|
||||
@@ -83,7 +85,7 @@ private:
|
||||
&& int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0
|
||||
&& (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)),
|
||||
MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit),
|
||||
MayLinearVectorize = bool(MightVectorize) && MayLinearize && DstHasDirectAccess
|
||||
MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess)
|
||||
&& (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || 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. */
|
||||
@@ -97,7 +99,8 @@ private:
|
||||
|
||||
public:
|
||||
enum {
|
||||
Traversal = int(MayLinearVectorize) && (LinearPacketSize>InnerPacketSize) ? int(LinearVectorizedTraversal)
|
||||
Traversal = int(Dst::SizeAtCompileTime) == 0 ? int(AllAtOnceTraversal) // If compile-size is zero, traversing will fail at compile-time.
|
||||
: (int(MayLinearVectorize) && (LinearPacketSize>InnerPacketSize)) ? int(LinearVectorizedTraversal)
|
||||
: int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
|
||||
: int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
|
||||
: int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
|
||||
@@ -135,7 +138,7 @@ public:
|
||||
? int(CompleteUnrolling)
|
||||
: int(NoUnrolling) )
|
||||
: int(Traversal) == int(LinearTraversal)
|
||||
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
||||
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
|
||||
: int(NoUnrolling) )
|
||||
#if EIGEN_UNALIGNED_VECTORIZE
|
||||
: int(Traversal) == int(SliceVectorizedTraversal)
|
||||
@@ -172,6 +175,8 @@ public:
|
||||
EIGEN_DEBUG_VAR(MaySliceVectorize)
|
||||
std::cerr << "Traversal" << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl;
|
||||
EIGEN_DEBUG_VAR(SrcEvaluator::CoeffReadCost)
|
||||
EIGEN_DEBUG_VAR(DstEvaluator::CoeffReadCost)
|
||||
EIGEN_DEBUG_VAR(Dst::SizeAtCompileTime)
|
||||
EIGEN_DEBUG_VAR(UnrollingLimit)
|
||||
EIGEN_DEBUG_VAR(MayUnrollCompletely)
|
||||
EIGEN_DEBUG_VAR(MayUnrollInner)
|
||||
@@ -195,7 +200,7 @@ struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
|
||||
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
|
||||
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
||||
|
||||
|
||||
enum {
|
||||
outer = Index / DstXprType::InnerSizeAtCompileTime,
|
||||
inner = Index % DstXprType::InnerSizeAtCompileTime
|
||||
@@ -261,7 +266,7 @@ struct copy_using_evaluator_innervec_CompleteUnrolling
|
||||
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
|
||||
typedef typename DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
||||
|
||||
enum {
|
||||
outer = Index / DstXprType::InnerSizeAtCompileTime,
|
||||
inner = Index % DstXprType::InnerSizeAtCompileTime,
|
||||
@@ -312,6 +317,22 @@ template<typename Kernel,
|
||||
int Unrolling = Kernel::AssignmentTraits::Unrolling>
|
||||
struct dense_assignment_loop;
|
||||
|
||||
/************************
|
||||
***** Special Cases *****
|
||||
************************/
|
||||
|
||||
// Zero-sized assignment is a no-op.
|
||||
template<typename Kernel, int Unrolling>
|
||||
struct dense_assignment_loop<Kernel, AllAtOnceTraversal, Unrolling>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE run(Kernel& /*kernel*/)
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
EIGEN_STATIC_ASSERT(int(DstXprType::SizeAtCompileTime) == 0,
|
||||
EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT)
|
||||
}
|
||||
};
|
||||
|
||||
/************************
|
||||
*** Default traversal ***
|
||||
************************/
|
||||
@@ -426,10 +447,10 @@ struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrollin
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
||||
|
||||
enum { size = DstXprType::SizeAtCompileTime,
|
||||
packetSize =unpacket_traits<PacketType>::size,
|
||||
alignedSize = (size/packetSize)*packetSize };
|
||||
alignedSize = (int(size)/packetSize)*packetSize };
|
||||
|
||||
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
|
||||
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize, size>::run(kernel);
|
||||
@@ -530,7 +551,7 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
|
||||
const Scalar *dst_ptr = kernel.dstDataPtr();
|
||||
if((!bool(dstIsAligned)) && (UIntPtr(dst_ptr) % sizeof(Scalar))>0)
|
||||
{
|
||||
// the pointer is not aligend-on scalar, so alignment is not possible
|
||||
// the pointer is not aligned-on scalar, so alignment is not possible
|
||||
return dense_assignment_loop<Kernel,DefaultTraversal,NoUnrolling>::run(kernel);
|
||||
}
|
||||
const Index packetAlignedMask = packetSize - 1;
|
||||
@@ -568,14 +589,15 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
||||
enum { size = DstXprType::InnerSizeAtCompileTime,
|
||||
enum { innerSize = DstXprType::InnerSizeAtCompileTime,
|
||||
packetSize =unpacket_traits<PacketType>::size,
|
||||
vectorizableSize = (size/packetSize)*packetSize };
|
||||
vectorizableSize = (int(innerSize) / int(packetSize)) * int(packetSize),
|
||||
size = DstXprType::SizeAtCompileTime };
|
||||
|
||||
for(Index outer = 0; outer < kernel.outerSize(); ++outer)
|
||||
{
|
||||
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, vectorizableSize, 0, 0>::run(kernel, outer);
|
||||
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, vectorizableSize, size>::run(kernel, outer);
|
||||
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, vectorizableSize, innerSize>::run(kernel, outer);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -599,73 +621,74 @@ protected:
|
||||
typedef typename DstEvaluatorTypeT::XprType DstXprType;
|
||||
typedef typename SrcEvaluatorTypeT::XprType SrcXprType;
|
||||
public:
|
||||
|
||||
|
||||
typedef DstEvaluatorTypeT DstEvaluatorType;
|
||||
typedef SrcEvaluatorTypeT SrcEvaluatorType;
|
||||
typedef typename DstEvaluatorType::Scalar Scalar;
|
||||
typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor> AssignmentTraits;
|
||||
typedef typename AssignmentTraits::PacketType PacketType;
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
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)
|
||||
{
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
AssignmentTraits::debug();
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC Index size() const { return m_dstExpr.size(); }
|
||||
EIGEN_DEVICE_FUNC Index innerSize() const { return m_dstExpr.innerSize(); }
|
||||
EIGEN_DEVICE_FUNC Index outerSize() const { return m_dstExpr.outerSize(); }
|
||||
EIGEN_DEVICE_FUNC Index rows() const { return m_dstExpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC Index cols() const { return m_dstExpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC Index outerStride() const { return m_dstExpr.outerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC DstEvaluatorType& dstEvaluator() { return m_dst; }
|
||||
EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const { return m_src; }
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_dstExpr.size(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index innerSize() const EIGEN_NOEXCEPT { return m_dstExpr.innerSize(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerSize() const EIGEN_NOEXCEPT { return m_dstExpr.outerSize(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_dstExpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_dstExpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerStride() const EIGEN_NOEXCEPT { return m_dstExpr.outerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC DstEvaluatorType& dstEvaluator() EIGEN_NOEXCEPT { return m_dst; }
|
||||
EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const EIGEN_NOEXCEPT { return m_src; }
|
||||
|
||||
/// Assign src(row,col) to dst(row,col) through the assignment functor.
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col)
|
||||
{
|
||||
m_functor.assignCoeff(m_dst.coeffRef(row,col), m_src.coeff(row,col));
|
||||
}
|
||||
|
||||
|
||||
/// \sa assignCoeff(Index,Index)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index index)
|
||||
{
|
||||
m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index));
|
||||
}
|
||||
|
||||
|
||||
/// \sa assignCoeff(Index,Index)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner)
|
||||
{
|
||||
Index row = rowIndexByOuterInner(outer, inner);
|
||||
Index col = colIndexByOuterInner(outer, inner);
|
||||
Index row = rowIndexByOuterInner(outer, inner);
|
||||
Index col = colIndexByOuterInner(outer, inner);
|
||||
assignCoeff(row, col);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index row, Index col)
|
||||
{
|
||||
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode,PacketType>(row,col));
|
||||
}
|
||||
|
||||
|
||||
template<int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index index)
|
||||
{
|
||||
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode,PacketType>(index));
|
||||
}
|
||||
|
||||
|
||||
template<int StoreMode, int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner)
|
||||
{
|
||||
Index row = rowIndexByOuterInner(outer, inner);
|
||||
Index row = rowIndexByOuterInner(outer, inner);
|
||||
Index col = colIndexByOuterInner(outer, inner);
|
||||
assignPacket<StoreMode,LoadMode,PacketType>(row, col);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner)
|
||||
{
|
||||
typedef typename DstEvaluatorType::ExpressionTraits Traits;
|
||||
@@ -688,7 +711,7 @@ public:
|
||||
{
|
||||
return m_dstExpr.data();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
DstEvaluatorType& m_dst;
|
||||
const SrcEvaluatorType& m_src;
|
||||
@@ -697,6 +720,27 @@ protected:
|
||||
DstXprType& m_dstExpr;
|
||||
};
|
||||
|
||||
// Special kernel used when computing small products whose operands have dynamic dimensions. It ensures that the
|
||||
// PacketSize used is no larger than 4, thereby increasing the chance that vectorized instructions will be used
|
||||
// when computing the product.
|
||||
|
||||
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor>
|
||||
class restricted_packet_dense_assignment_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, BuiltIn>
|
||||
{
|
||||
protected:
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, BuiltIn> Base;
|
||||
public:
|
||||
typedef typename Base::Scalar Scalar;
|
||||
typedef typename Base::DstXprType DstXprType;
|
||||
typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, 4> AssignmentTraits;
|
||||
typedef typename AssignmentTraits::PacketType PacketType;
|
||||
|
||||
EIGEN_DEVICE_FUNC restricted_packet_dense_assignment_kernel(DstEvaluatorTypeT &dst, const SrcEvaluatorTypeT &src, const Functor &func, DstXprType& dstExpr)
|
||||
: Base(dst, src, func, dstExpr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Part 5 : Entry point for dense rectangular assignment
|
||||
***************************************************************************/
|
||||
@@ -734,13 +778,23 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType
|
||||
resize_if_allowed(dst, src, func);
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
|
||||
|
||||
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
|
||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||
|
||||
dense_assignment_loop<Kernel>::run(kernel);
|
||||
}
|
||||
|
||||
// Specialization for filling the destination with a constant value.
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
template<typename DstXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<typename DstXprType::Scalar>, DstXprType>& src, const internal::assign_op<typename DstXprType::Scalar,typename DstXprType::Scalar>& func)
|
||||
{
|
||||
resize_if_allowed(dst, src, func);
|
||||
std::fill_n(dst.data(), dst.size(), src.functor()());
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename DstXprType, typename SrcXprType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src)
|
||||
{
|
||||
@@ -756,13 +810,13 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType
|
||||
// AssignmentKind must define a Kind typedef.
|
||||
template<typename DstShape, typename SrcShape> struct AssignmentKind;
|
||||
|
||||
// Assignement kind defined in this file:
|
||||
// Assignment kind defined in this file:
|
||||
struct Dense2Dense {};
|
||||
struct EigenBase2EigenBase {};
|
||||
|
||||
template<typename,typename> struct AssignmentKind { typedef EigenBase2EigenBase Kind; };
|
||||
template<> struct AssignmentKind<DenseShape,DenseShape> { typedef Dense2Dense Kind; };
|
||||
|
||||
|
||||
// This is the main assignment class
|
||||
template< typename DstXprType, typename SrcXprType, typename Functor,
|
||||
typename Kind = typename AssignmentKind< typename evaluator_traits<DstXprType>::Shape , typename evaluator_traits<SrcXprType>::Shape >::Kind,
|
||||
@@ -787,7 +841,7 @@ void call_assignment(const Dst& dst, const Src& src)
|
||||
{
|
||||
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
|
||||
}
|
||||
|
||||
|
||||
// Deal with "assume-aliasing"
|
||||
template<typename Dst, typename Src, typename Func>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
@@ -827,14 +881,35 @@ void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
|
||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst>::type ActualDstTypeCleaned;
|
||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
|
||||
ActualDstType actualDst(dst);
|
||||
|
||||
|
||||
// TODO check whether this is the right place to perform these checks:
|
||||
EIGEN_STATIC_ASSERT_LVALUE(Dst)
|
||||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned,Src)
|
||||
EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename ActualDstTypeCleaned::Scalar,typename Src::Scalar);
|
||||
|
||||
|
||||
Assignment<ActualDstTypeCleaned,Src,Func>::run(actualDst, src, func);
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src, typename Func>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void call_restricted_packet_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
|
||||
{
|
||||
typedef evaluator<Dst> DstEvaluatorType;
|
||||
typedef evaluator<Src> SrcEvaluatorType;
|
||||
typedef restricted_packet_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Func> Kernel;
|
||||
|
||||
EIGEN_STATIC_ASSERT_LVALUE(Dst)
|
||||
EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename Dst::Scalar,typename Src::Scalar);
|
||||
|
||||
SrcEvaluatorType srcEvaluator(src);
|
||||
resize_if_allowed(dst, src, func);
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
|
||||
|
||||
dense_assignment_loop<Kernel>::run(kernel);
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void call_assignment_no_alias(Dst& dst, const Src& src)
|
||||
@@ -875,7 +950,7 @@ struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Weak>
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
internal::check_for_aliasing(dst, src);
|
||||
#endif
|
||||
|
||||
|
||||
call_dense_assignment_loop(dst, src, func);
|
||||
}
|
||||
};
|
||||
@@ -899,7 +974,7 @@ struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
|
||||
src.evalTo(dst);
|
||||
}
|
||||
|
||||
// NOTE The following two functions are templated to avoid their instanciation if not needed
|
||||
// NOTE The following two functions are templated to avoid their instantiation if not needed
|
||||
// This is needed because some expressions supports evalTo only and/or have 'void' as scalar type.
|
||||
template<typename SrcScalarType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
||||
@@ -68,27 +68,28 @@ class vml_assign_traits
|
||||
|
||||
#define EIGEN_PP_EXPAND(ARG) ARG
|
||||
#if !defined (EIGEN_FAST_MATH) || (EIGEN_FAST_MATH != 1)
|
||||
#define EIGEN_VMLMODE_EXPAND_LA , VML_HA
|
||||
#define EIGEN_VMLMODE_EXPAND_xLA , VML_HA
|
||||
#else
|
||||
#define EIGEN_VMLMODE_EXPAND_LA , VML_LA
|
||||
#define EIGEN_VMLMODE_EXPAND_xLA , VML_LA
|
||||
#endif
|
||||
|
||||
#define EIGEN_VMLMODE_EXPAND__
|
||||
#define EIGEN_VMLMODE_EXPAND_x_
|
||||
|
||||
#define EIGEN_VMLMODE_PREFIX_LA vm
|
||||
#define EIGEN_VMLMODE_PREFIX__ v
|
||||
#define EIGEN_VMLMODE_PREFIX(VMLMODE) EIGEN_CAT(EIGEN_VMLMODE_PREFIX_,VMLMODE)
|
||||
#define EIGEN_VMLMODE_PREFIX_xLA vm
|
||||
#define EIGEN_VMLMODE_PREFIX_x_ v
|
||||
#define EIGEN_VMLMODE_PREFIX(VMLMODE) EIGEN_CAT(EIGEN_VMLMODE_PREFIX_x,VMLMODE)
|
||||
|
||||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE, VMLMODE) \
|
||||
template< typename DstXprType, typename SrcXprNested> \
|
||||
struct Assignment<DstXprType, CwiseUnaryOp<scalar_##EIGENOP##_op<EIGENTYPE>, SrcXprNested>, assign_op<EIGENTYPE,EIGENTYPE>, \
|
||||
Dense2Dense, typename enable_if<vml_assign_traits<DstXprType,SrcXprNested>::EnableVml>::type> { \
|
||||
typedef CwiseUnaryOp<scalar_##EIGENOP##_op<EIGENTYPE>, SrcXprNested> SrcXprType; \
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &/*func*/) { \
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &func) { \
|
||||
resize_if_allowed(dst, src, func); \
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \
|
||||
if(vml_assign_traits<DstXprType,SrcXprNested>::Traversal==LinearTraversal) { \
|
||||
VMLOP(dst.size(), (const VMLTYPE*)src.nestedExpression().data(), \
|
||||
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE) ); \
|
||||
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE) ); \
|
||||
} else { \
|
||||
const Index outerSize = dst.outerSize(); \
|
||||
for(Index outer = 0; outer < outerSize; ++outer) { \
|
||||
@@ -96,7 +97,7 @@ class vml_assign_traits
|
||||
&(src.nestedExpression().coeffRef(0, outer)); \
|
||||
EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); \
|
||||
VMLOP( dst.innerSize(), (const VMLTYPE*)src_ptr, \
|
||||
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE)); \
|
||||
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -144,13 +145,14 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _)
|
||||
Dense2Dense, typename enable_if<vml_assign_traits<DstXprType,SrcXprNested>::EnableVml>::type> { \
|
||||
typedef CwiseBinaryOp<scalar_##EIGENOP##_op<EIGENTYPE,EIGENTYPE>, SrcXprNested, \
|
||||
const CwiseNullaryOp<internal::scalar_constant_op<EIGENTYPE>,Plain> > SrcXprType; \
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &/*func*/) { \
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &func) { \
|
||||
resize_if_allowed(dst, src, func); \
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \
|
||||
VMLTYPE exponent = reinterpret_cast<const VMLTYPE&>(src.rhs().functor().m_other); \
|
||||
if(vml_assign_traits<DstXprType,SrcXprNested>::Traversal==LinearTraversal) \
|
||||
{ \
|
||||
VMLOP( dst.size(), (const VMLTYPE*)src.lhs().data(), exponent, \
|
||||
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE) ); \
|
||||
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE) ); \
|
||||
} else { \
|
||||
const Index outerSize = dst.outerSize(); \
|
||||
for(Index outer = 0; outer < outerSize; ++outer) { \
|
||||
@@ -158,7 +160,7 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _)
|
||||
&(src.lhs().coeffRef(0, outer)); \
|
||||
EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); \
|
||||
VMLOP( dst.innerSize(), (const VMLTYPE*)src_ptr, exponent, \
|
||||
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE)); \
|
||||
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_x##VMLMODE)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_BANDMATRIX_H
|
||||
#define EIGEN_BANDMATRIX_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -45,7 +45,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
|
||||
using Base::derived;
|
||||
using Base::rows;
|
||||
using Base::cols;
|
||||
@@ -55,10 +55,10 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
|
||||
/** \returns the number of sub diagonals */
|
||||
inline Index subs() const { return derived().subs(); }
|
||||
|
||||
|
||||
/** \returns an expression of the underlying coefficient matrix */
|
||||
inline const CoefficientsType& coeffs() const { return derived().coeffs(); }
|
||||
|
||||
|
||||
/** \returns an expression of the underlying coefficient matrix */
|
||||
inline CoefficientsType& coeffs() { return derived().coeffs(); }
|
||||
|
||||
@@ -67,7 +67,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
* \warning the internal storage must be column major. */
|
||||
inline Block<CoefficientsType,Dynamic,1> col(Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((Options&RowMajor)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
EIGEN_STATIC_ASSERT((int(Options) & int(RowMajor)) == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
Index start = 0;
|
||||
Index len = coeffs().rows();
|
||||
if (i<=supers())
|
||||
@@ -90,7 +90,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
|
||||
template<int Index> struct DiagonalIntReturnType {
|
||||
enum {
|
||||
ReturnOpposite = (Options&SelfAdjoint) && (((Index)>0 && Supers==0) || ((Index)<0 && Subs==0)),
|
||||
ReturnOpposite = (int(Options) & int(SelfAdjoint)) && (((Index) > 0 && Supers == 0) || ((Index) < 0 && Subs == 0)),
|
||||
Conjugate = ReturnOpposite && NumTraits<Scalar>::IsComplex,
|
||||
ActualIndex = ReturnOpposite ? -Index : Index,
|
||||
DiagonalSize = (RowsAtCompileTime==Dynamic || ColsAtCompileTime==Dynamic)
|
||||
@@ -130,7 +130,7 @@ class BandMatrixBase : public EigenBase<Derived>
|
||||
eigen_assert((i<0 && -i<=subs()) || (i>=0 && i<=supers()));
|
||||
return Block<const CoefficientsType,1,Dynamic>(coeffs(), supers()-i, std::max<Index>(0,i), 1, diagonalLength(i));
|
||||
}
|
||||
|
||||
|
||||
template<typename Dest> inline void evalTo(Dest& dst) const
|
||||
{
|
||||
dst.resize(rows(),cols());
|
||||
@@ -192,7 +192,7 @@ struct traits<BandMatrix<_Scalar,_Rows,_Cols,_Supers,_Subs,_Options> >
|
||||
Options = _Options,
|
||||
DataRowsAtCompileTime = ((Supers!=Dynamic) && (Subs!=Dynamic)) ? 1 + Supers + Subs : Dynamic
|
||||
};
|
||||
typedef Matrix<Scalar,DataRowsAtCompileTime,ColsAtCompileTime,Options&RowMajor?RowMajor:ColMajor> CoefficientsType;
|
||||
typedef Matrix<Scalar, DataRowsAtCompileTime, ColsAtCompileTime, int(Options) & int(RowMajor) ? RowMajor : ColMajor> CoefficientsType;
|
||||
};
|
||||
|
||||
template<typename _Scalar, int Rows, int Cols, int Supers, int Subs, int Options>
|
||||
@@ -211,16 +211,16 @@ class BandMatrix : public BandMatrixBase<BandMatrix<_Scalar,Rows,Cols,Supers,Sub
|
||||
}
|
||||
|
||||
/** \returns the number of columns */
|
||||
inline Index rows() const { return m_rows.value(); }
|
||||
inline EIGEN_CONSTEXPR Index rows() const { return m_rows.value(); }
|
||||
|
||||
/** \returns the number of rows */
|
||||
inline Index cols() const { return m_coeffs.cols(); }
|
||||
inline EIGEN_CONSTEXPR Index cols() const { return m_coeffs.cols(); }
|
||||
|
||||
/** \returns the number of super diagonals */
|
||||
inline Index supers() const { return m_supers.value(); }
|
||||
inline EIGEN_CONSTEXPR Index supers() const { return m_supers.value(); }
|
||||
|
||||
/** \returns the number of sub diagonals */
|
||||
inline Index subs() const { return m_subs.value(); }
|
||||
inline EIGEN_CONSTEXPR Index subs() const { return m_subs.value(); }
|
||||
|
||||
inline const CoefficientsType& coeffs() const { return m_coeffs; }
|
||||
inline CoefficientsType& coeffs() { return m_coeffs; }
|
||||
@@ -275,16 +275,16 @@ class BandMatrixWrapper : public BandMatrixBase<BandMatrixWrapper<_CoefficientsT
|
||||
}
|
||||
|
||||
/** \returns the number of columns */
|
||||
inline Index rows() const { return m_rows.value(); }
|
||||
inline EIGEN_CONSTEXPR Index rows() const { return m_rows.value(); }
|
||||
|
||||
/** \returns the number of rows */
|
||||
inline Index cols() const { return m_coeffs.cols(); }
|
||||
inline EIGEN_CONSTEXPR Index cols() const { return m_coeffs.cols(); }
|
||||
|
||||
/** \returns the number of super diagonals */
|
||||
inline Index supers() const { return m_supers.value(); }
|
||||
inline EIGEN_CONSTEXPR Index supers() const { return m_supers.value(); }
|
||||
|
||||
/** \returns the number of sub diagonals */
|
||||
inline Index subs() const { return m_subs.value(); }
|
||||
inline EIGEN_CONSTEXPR Index subs() const { return m_subs.value(); }
|
||||
|
||||
inline const CoefficientsType& coeffs() const { return m_coeffs; }
|
||||
|
||||
|
||||
+56
-60
@@ -11,7 +11,7 @@
|
||||
#ifndef EIGEN_BLOCK_H
|
||||
#define EIGEN_BLOCK_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
|
||||
@@ -52,7 +52,7 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
||||
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
|
||||
Flags = (traits<XprType>::Flags & (DirectAccessBit | (InnerPanel?CompressedAccessBit:0))) | FlagsLvalueBit | FlagsRowMajorBit,
|
||||
// FIXME DirectAccessBit should not be handled by expressions
|
||||
//
|
||||
//
|
||||
// Alignment is needed by MapBase's assertions
|
||||
// We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the respective evaluator
|
||||
Alignment = 0
|
||||
@@ -61,7 +61,7 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprTyp
|
||||
|
||||
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;
|
||||
@@ -109,13 +109,13 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class
|
||||
typedef Impl Base;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
|
||||
|
||||
|
||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||
|
||||
|
||||
/** Column or Row constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Block(XprType& xpr, Index i) : Impl(xpr,i)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Block(XprType& xpr, Index i) : Impl(xpr,i)
|
||||
{
|
||||
eigen_assert( (i>=0) && (
|
||||
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
|
||||
@@ -124,8 +124,8 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class
|
||||
|
||||
/** Fixed-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Block(XprType& xpr, Index startRow, Index startCol)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Block(XprType& xpr, Index startRow, Index startCol)
|
||||
: Impl(xpr, startRow, startCol)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
|
||||
@@ -135,8 +135,8 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class
|
||||
|
||||
/** Dynamic-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Block(XprType& xpr,
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Block(XprType& xpr,
|
||||
Index startRow, Index startCol,
|
||||
Index blockRows, Index blockCols)
|
||||
: Impl(xpr, startRow, startCol, blockRows, blockCols)
|
||||
@@ -147,7 +147,7 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class
|
||||
&& startCol >= 0 && blockCols >= 0 && 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>
|
||||
@@ -159,10 +159,10 @@ class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
|
||||
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 startRow, Index startCol) : Impl(xpr, startRow, startCol) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol) : Impl(xpr, startRow, startCol) {}
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
|
||||
EIGEN_STRONG_INLINE BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols)
|
||||
: Impl(xpr, startRow, startCol, blockRows, blockCols) {}
|
||||
};
|
||||
|
||||
@@ -294,25 +294,25 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const;
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const
|
||||
{
|
||||
return m_xpr;
|
||||
{
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
StorageIndex startRow() const
|
||||
{
|
||||
return m_startRow.value();
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
StorageIndex startRow() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return m_startRow.value();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
StorageIndex startCol() const
|
||||
{
|
||||
return m_startCol.value();
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
StorageIndex startCol() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return m_startCol.value();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -342,9 +342,9 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
|
||||
/** Column or Row constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline BlockImpl_dense(XprType& xpr, Index i)
|
||||
: Base(xpr.data() + i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor))
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr, Index i)
|
||||
: Base(xpr.data() + i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor))
|
||||
|| ((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && ( XprTypeIsRowMajor)) ? xpr.innerStride() : xpr.outerStride()),
|
||||
BlockRows==1 ? 1 : xpr.rows(),
|
||||
BlockCols==1 ? 1 : xpr.cols()),
|
||||
@@ -357,8 +357,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
|
||||
/** Fixed-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
|
||||
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol)),
|
||||
m_xpr(xpr), m_startRow(startRow), m_startCol(startCol)
|
||||
{
|
||||
@@ -367,8 +367,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
|
||||
/** Dynamic-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline BlockImpl_dense(XprType& xpr,
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr,
|
||||
Index startRow, Index startCol,
|
||||
Index blockRows, Index blockCols)
|
||||
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol), blockRows, blockCols),
|
||||
@@ -377,18 +377,18 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
init();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const
|
||||
{
|
||||
return m_xpr;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
|
||||
/** \sa MapBase::innerStride() */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index innerStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return internal::traits<BlockType>::HasSameStorageOrderAsXprType
|
||||
? m_xpr.innerStride()
|
||||
@@ -396,23 +396,19 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
}
|
||||
|
||||
/** \sa MapBase::outerStride() */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index outerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index outerStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return m_outerStride;
|
||||
return internal::traits<BlockType>::HasSameStorageOrderAsXprType
|
||||
? m_xpr.outerStride()
|
||||
: m_xpr.innerStride();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
StorageIndex startRow() const
|
||||
{
|
||||
return m_startRow.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
StorageIndex startRow() const EIGEN_NOEXCEPT { return m_startRow.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
StorageIndex startCol() const
|
||||
{
|
||||
return m_startCol.value();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
StorageIndex startCol() const EIGEN_NOEXCEPT { return m_startCol.value(); }
|
||||
|
||||
#ifndef __SUNPRO_CC
|
||||
// FIXME sunstudio is not friendly with the above friend...
|
||||
@@ -422,8 +418,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal used by allowAligned() */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
|
||||
: Base(data, blockRows, blockCols), m_xpr(xpr)
|
||||
{
|
||||
init();
|
||||
@@ -431,7 +427,7 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
|
||||
#endif
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void init()
|
||||
{
|
||||
m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType
|
||||
|
||||
@@ -14,58 +14,56 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Derived, int UnrollCount>
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
struct all_unroller
|
||||
{
|
||||
typedef typename Derived::ExpressionTraits Traits;
|
||||
enum {
|
||||
col = (UnrollCount-1) / Traits::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % Traits::RowsAtCompileTime
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
};
|
||||
|
||||
static inline bool run(const Derived &mat)
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
|
||||
{
|
||||
return all_unroller<Derived, UnrollCount-1>::run(mat) && mat.coeff(row, col);
|
||||
return all_unroller<Derived, UnrollCount-1, Rows>::run(mat) && mat.coeff(row, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct all_unroller<Derived, 0>
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, 0, Rows>
|
||||
{
|
||||
static inline bool run(const Derived &/*mat*/) { return true; }
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &/*mat*/) { return true; }
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct all_unroller<Derived, Dynamic>
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, Dynamic, Rows>
|
||||
{
|
||||
static inline bool run(const Derived &) { return false; }
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived, int UnrollCount>
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
struct any_unroller
|
||||
{
|
||||
typedef typename Derived::ExpressionTraits Traits;
|
||||
enum {
|
||||
col = (UnrollCount-1) / Traits::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % Traits::RowsAtCompileTime
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
};
|
||||
|
||||
static inline bool run(const Derived &mat)
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
|
||||
{
|
||||
return any_unroller<Derived, UnrollCount-1>::run(mat) || mat.coeff(row, col);
|
||||
return any_unroller<Derived, UnrollCount-1, Rows>::run(mat) || mat.coeff(row, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct any_unroller<Derived, 0>
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, 0, Rows>
|
||||
{
|
||||
static inline bool run(const Derived & /*mat*/) { return false; }
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived & /*mat*/) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct any_unroller<Derived, Dynamic>
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, Dynamic, Rows>
|
||||
{
|
||||
static inline bool run(const Derived &) { return false; }
|
||||
EIGEN_DEVICE_FUNC static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
@@ -78,16 +76,16 @@ struct any_unroller<Derived, Dynamic>
|
||||
* \sa any(), Cwise::operator<()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool DenseBase<Derived>::all() const
|
||||
EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::all() const
|
||||
{
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
&& SizeAtCompileTime * (int(Evaluator::CoeffReadCost) + int(NumTraits<Scalar>::AddCost)) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
@@ -102,16 +100,16 @@ inline bool DenseBase<Derived>::all() const
|
||||
* \sa all()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline bool DenseBase<Derived>::any() const
|
||||
EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::any() const
|
||||
{
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
&& SizeAtCompileTime * (int(Evaluator::CoeffReadCost) + int(NumTraits<Scalar>::AddCost)) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
@@ -126,7 +124,7 @@ inline bool DenseBase<Derived>::any() const
|
||||
* \sa all(), any()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Eigen::Index DenseBase<Derived>::count() const
|
||||
EIGEN_DEVICE_FUNC inline Eigen::Index DenseBase<Derived>::count() const
|
||||
{
|
||||
return derived().template cast<bool>().template cast<Index>().sum();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ struct CommaInitializer
|
||||
inline CommaInitializer(XprType& xpr, const Scalar& s)
|
||||
: m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1)
|
||||
{
|
||||
eigen_assert(m_xpr.rows() > 0 && m_xpr.cols() > 0
|
||||
&& "Cannot comma-initialize a 0x0 matrix (operator<<)");
|
||||
m_xpr.coeffRef(0,0) = s;
|
||||
}
|
||||
|
||||
@@ -41,6 +43,8 @@ struct CommaInitializer
|
||||
inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other)
|
||||
: m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows())
|
||||
{
|
||||
eigen_assert(m_xpr.rows() >= other.rows() && m_xpr.cols() >= other.cols()
|
||||
&& "Cannot comma-initialize a 0x0 matrix (operator<<)");
|
||||
m_xpr.block(0, 0, other.rows(), other.cols()) = other;
|
||||
}
|
||||
|
||||
@@ -103,7 +107,7 @@ struct CommaInitializer
|
||||
EIGEN_EXCEPTION_SPEC(Eigen::eigen_assert_exception)
|
||||
#endif
|
||||
{
|
||||
finished();
|
||||
finished();
|
||||
}
|
||||
|
||||
/** \returns the built matrix once all its coefficients have been set.
|
||||
@@ -141,7 +145,7 @@ struct CommaInitializer
|
||||
* \sa CommaInitializer::finished(), class CommaInitializer
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s)
|
||||
EIGEN_DEVICE_FUNC inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s)
|
||||
{
|
||||
return CommaInitializer<Derived>(*static_cast<Derived*>(this), s);
|
||||
}
|
||||
@@ -149,7 +153,7 @@ inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s
|
||||
/** \sa operator<<(const Scalar&) */
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline CommaInitializer<Derived>
|
||||
EIGEN_DEVICE_FUNC inline CommaInitializer<Derived>
|
||||
DenseBase<Derived>::operator<<(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
return CommaInitializer<Derived>(*static_cast<Derived *>(this), other);
|
||||
|
||||
@@ -160,7 +160,7 @@ rcond_estimate_helper(typename Decomposition::RealScalar matrix_norm, const Deco
|
||||
{
|
||||
typedef typename Decomposition::RealScalar RealScalar;
|
||||
eigen_assert(dec.rows() == dec.cols());
|
||||
if (dec.rows() == 0) return RealScalar(1);
|
||||
if (dec.rows() == 0) return NumTraits<RealScalar>::infinity();
|
||||
if (matrix_norm == RealScalar(0)) return RealScalar(0);
|
||||
if (dec.rows() == 1) return RealScalar(1);
|
||||
const RealScalar inverse_matrix_norm = rcond_invmatrix_L1_norm_estimate(dec);
|
||||
|
||||
+345
-275
File diff suppressed because it is too large.
Load diff
@@ -48,6 +48,11 @@ public:
|
||||
* Explicit zeros are not skipped over. To skip explicit zeros, see class SparseView
|
||||
*/
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator++() { m_iter.operator++(); return *this; }
|
||||
EIGEN_STRONG_INLINE InnerIterator& operator+=(Index i) { m_iter.operator+=(i); return *this; }
|
||||
EIGEN_STRONG_INLINE InnerIterator operator+(Index i)
|
||||
{ InnerIterator result(*this); result+=i; return result; }
|
||||
|
||||
|
||||
/// \returns the column or row index of the current coefficient.
|
||||
EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); }
|
||||
/// \returns the row index of the current coefficient.
|
||||
|
||||
@@ -74,7 +74,7 @@ class CwiseBinaryOpImpl;
|
||||
* \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp
|
||||
*/
|
||||
template<typename BinaryOp, typename LhsType, typename RhsType>
|
||||
class CwiseBinaryOp :
|
||||
class CwiseBinaryOp :
|
||||
public CwiseBinaryOpImpl<
|
||||
BinaryOp, LhsType, RhsType,
|
||||
typename internal::cwise_promote_storage_type<typename internal::traits<LhsType>::StorageKind,
|
||||
@@ -83,7 +83,7 @@ class CwiseBinaryOp :
|
||||
internal::no_assignment_operator
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
typedef typename internal::remove_all<BinaryOp>::type Functor;
|
||||
typedef typename internal::remove_all<LhsType>::type Lhs;
|
||||
typedef typename internal::remove_all<RhsType>::type Rhs;
|
||||
@@ -100,8 +100,14 @@ class CwiseBinaryOp :
|
||||
typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
|
||||
typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp())
|
||||
#if EIGEN_COMP_MSVC && EIGEN_HAS_CXX11
|
||||
//Required for Visual Studio or the Copy constructor will probably not get inlined!
|
||||
EIGEN_STRONG_INLINE
|
||||
CwiseBinaryOp(const CwiseBinaryOp<BinaryOp,LhsType,RhsType>&) = default;
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CwiseBinaryOp(const Lhs& aLhs, const Rhs& aRhs, const BinaryOp& func = BinaryOp())
|
||||
: m_lhs(aLhs), m_rhs(aRhs), m_functor(func)
|
||||
{
|
||||
EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
|
||||
@@ -110,31 +116,25 @@ class CwiseBinaryOp :
|
||||
eigen_assert(aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index rows() const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const EIGEN_NOEXCEPT {
|
||||
// return the fixed size type if available to enable compile time optimizations
|
||||
if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic)
|
||||
return m_rhs.rows();
|
||||
else
|
||||
return m_lhs.rows();
|
||||
return internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic ? m_rhs.rows() : m_lhs.rows();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index cols() const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const EIGEN_NOEXCEPT {
|
||||
// return the fixed size type if available to enable compile time optimizations
|
||||
if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic)
|
||||
return m_rhs.cols();
|
||||
else
|
||||
return m_lhs.cols();
|
||||
return internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic ? m_rhs.cols() : m_lhs.cols();
|
||||
}
|
||||
|
||||
/** \returns the left hand side nested expression */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const _LhsNested& lhs() const { return m_lhs; }
|
||||
/** \returns the right hand side nested expression */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const _RhsNested& rhs() const { return m_rhs; }
|
||||
/** \returns the functor representing the binary operation */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const BinaryOp& functor() const { return m_functor; }
|
||||
|
||||
protected:
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
@@ -171,7 +171,7 @@ MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
@@ -181,4 +181,3 @@ MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_CWISE_BINARY_OP_H
|
||||
|
||||
@@ -74,10 +74,10 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const { return m_cols.value(); }
|
||||
|
||||
/** \returns the functor representing the nullary operation */
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -105,7 +105,12 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
const CwiseNullaryOp<CustomNullaryOp,typename DenseBase<Derived>::PlainObject>
|
||||
#else
|
||||
const CwiseNullaryOp<CustomNullaryOp,PlainObject>
|
||||
#endif
|
||||
DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, PlainObject>(rows, cols, func);
|
||||
@@ -126,12 +131,17 @@ DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& f
|
||||
*
|
||||
* Here is an example with C++11 random generators: \include random_cpp11.cpp
|
||||
* Output: \verbinclude random_cpp11.out
|
||||
*
|
||||
*
|
||||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
#else
|
||||
const CwiseNullaryOp<CustomNullaryOp, PlainObject>
|
||||
#endif
|
||||
DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
@@ -150,7 +160,12 @@ DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
#else
|
||||
const CwiseNullaryOp<CustomNullaryOp, PlainObject>
|
||||
#endif
|
||||
DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, PlainObject>(RowsAtCompileTime, ColsAtCompileTime, func);
|
||||
@@ -170,7 +185,7 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
|
||||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
|
||||
{
|
||||
return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_constant_op<Scalar>(value));
|
||||
@@ -217,27 +232,32 @@ DenseBase<Derived>::Constant(const Scalar& value)
|
||||
|
||||
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*
|
||||
* \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
* \only_for_vectors
|
||||
*
|
||||
* Example: \include DenseBase_LinSpaced_seq_deprecated.cpp
|
||||
* Output: \verbinclude DenseBase_LinSpaced_seq_deprecated.out
|
||||
*
|
||||
* \sa LinSpaced(Index,const Scalar&, const Scalar&), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar>(low,high,size));
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar>(low,high,size));
|
||||
}
|
||||
|
||||
/** \deprecated because of accuracy loss. In Eigen 3.3, it is an alias for LinSpaced(const Scalar&,const Scalar&)
|
||||
*
|
||||
* \sa LinSpaced(Scalar,Scalar)
|
||||
* \sa LinSpaced(const Scalar&, const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar>(low,high,Derived::SizeAtCompileTime));
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar>(low,high,Derived::SizeAtCompileTime));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,7 +288,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomA
|
||||
DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,PacketScalar>(low,high,size));
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar>(low,high,size));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +301,7 @@ DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,PacketScalar>(low,high,Derived::SizeAtCompileTime));
|
||||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar>(low,high,Derived::SizeAtCompileTime));
|
||||
}
|
||||
|
||||
/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */
|
||||
@@ -363,6 +383,33 @@ PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& val)
|
||||
return setConstant(val);
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of columns, and sets all
|
||||
* coefficients in this expression to the given value \a val. For the parameter
|
||||
* of type NoChange_t, just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setConstant(NoChange_t, Index cols, const Scalar& val)
|
||||
{
|
||||
return setConstant(rows(), cols, val);
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of rows, and sets all
|
||||
* coefficients in this expression to the given value \a val. For the parameter
|
||||
* of type NoChange_t, just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setConstant(Index rows, NoChange_t, const Scalar& val)
|
||||
{
|
||||
return setConstant(rows, cols(), val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sets a linearly spaced vector.
|
||||
*
|
||||
@@ -383,7 +430,7 @@ template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,PacketScalar>(low,high,newSize));
|
||||
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar>(low,high,newSize));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -536,6 +583,32 @@ PlainObjectBase<Derived>::setZero(Index rows, Index cols)
|
||||
return setConstant(Scalar(0));
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of columns, and sets all
|
||||
* coefficients in this expression to zero. For the parameter of type NoChange_t,
|
||||
* just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa DenseBase::setZero(), setZero(Index), setZero(Index, Index), setZero(Index, NoChange_t), class CwiseNullaryOp, DenseBase::Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setZero(NoChange_t, Index cols)
|
||||
{
|
||||
return setZero(rows(), cols);
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of rows, and sets all
|
||||
* coefficients in this expression to zero. For the parameter of type NoChange_t,
|
||||
* just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa DenseBase::setZero(), setZero(Index), setZero(Index, Index), setZero(NoChange_t, Index), class CwiseNullaryOp, DenseBase::Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setZero(Index rows, NoChange_t)
|
||||
{
|
||||
return setZero(rows, cols());
|
||||
}
|
||||
|
||||
// ones:
|
||||
|
||||
/** \returns an expression of a matrix where all coefficients equal one.
|
||||
@@ -662,6 +735,32 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
|
||||
return setConstant(Scalar(1));
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of rows, and sets all
|
||||
* coefficients in this expression to one. For the parameter of type NoChange_t,
|
||||
* just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa MatrixBase::setOnes(), setOnes(Index), setOnes(Index, Index), setOnes(NoChange_t, Index), class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setOnes(Index rows, NoChange_t)
|
||||
{
|
||||
return setOnes(rows, cols());
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of columns, and sets all
|
||||
* coefficients in this expression to one. For the parameter of type NoChange_t,
|
||||
* just pass the special value \c NoChange.
|
||||
*
|
||||
* \sa MatrixBase::setOnes(), setOnes(Index), setOnes(Index, Index), setOnes(Index, NoChange_t) class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setOnes(NoChange_t, Index cols)
|
||||
{
|
||||
return setOnes(rows(), cols);
|
||||
}
|
||||
|
||||
// Identity:
|
||||
|
||||
/** \returns an expression of the identity matrix (not necessarily square).
|
||||
@@ -861,6 +960,42 @@ template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW()
|
||||
{ return Derived::Unit(3); }
|
||||
|
||||
/** \brief Set the coefficients of \c *this to the i-th unit (basis) vector
|
||||
*
|
||||
* \param i index of the unique coefficient to be set to 1
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Unit(Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setUnit(Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
eigen_assert(i<size());
|
||||
derived().setZero();
|
||||
derived().coeffRef(i) = Scalar(1);
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \brief Resizes to the given \a newSize, and writes the i-th unit (basis) vector into *this.
|
||||
*
|
||||
* \param newSize the new size of the vector
|
||||
* \param i index of the unique coefficient to be set to 1
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Unit(Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setUnit(Index newSize, Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
eigen_assert(i<newSize);
|
||||
derived().resize(newSize);
|
||||
return setUnit(i);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_CWISE_NULLARY_OP_H
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef EIGEN_CWISE_UNARY_OP_H
|
||||
#define EIGEN_CWISE_UNARY_OP_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename UnaryOp, typename XprType>
|
||||
@@ -24,7 +24,7 @@ struct traits<CwiseUnaryOp<UnaryOp, XprType> >
|
||||
typedef typename XprType::Nested XprTypeNested;
|
||||
typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
|
||||
enum {
|
||||
Flags = _XprTypeNested::Flags & RowMajorBit
|
||||
Flags = _XprTypeNested::Flags & RowMajorBit
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -65,10 +65,10 @@ class CwiseUnaryOp : public CwiseUnaryOpImpl<UnaryOp, XprType, typename internal
|
||||
explicit CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp())
|
||||
: m_xpr(xpr), m_functor(func) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Index rows() const { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Index cols() const { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
|
||||
|
||||
/** \returns the functor representing the unary operation */
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
|
||||
@@ -64,24 +64,26 @@ class CwiseUnaryView : public CwiseUnaryViewImpl<ViewOp, MatrixType, typename in
|
||||
typedef typename internal::ref_selector<MatrixType>::non_const_type MatrixTypeNested;
|
||||
typedef typename internal::remove_all<MatrixType>::type NestedExpression;
|
||||
|
||||
explicit inline CwiseUnaryView(MatrixType& mat, const ViewOp& func = ViewOp())
|
||||
explicit EIGEN_DEVICE_FUNC inline CwiseUnaryView(MatrixType& mat, const ViewOp& func = ViewOp())
|
||||
: m_matrix(mat), m_functor(func) {}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryView)
|
||||
|
||||
EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); }
|
||||
EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
|
||||
|
||||
/** \returns the functor representing unary operation */
|
||||
const ViewOp& functor() const { return m_functor; }
|
||||
EIGEN_DEVICE_FUNC const ViewOp& functor() const { return m_functor; }
|
||||
|
||||
/** \returns the nested expression */
|
||||
const typename internal::remove_all<MatrixTypeNested>::type&
|
||||
EIGEN_DEVICE_FUNC const typename internal::remove_all<MatrixTypeNested>::type&
|
||||
nestedExpression() const { return m_matrix; }
|
||||
|
||||
/** \returns the nested expression */
|
||||
typename internal::remove_reference<MatrixTypeNested>::type&
|
||||
nestedExpression() { return m_matrix.const_cast_derived(); }
|
||||
EIGEN_DEVICE_FUNC typename internal::remove_reference<MatrixTypeNested>::type&
|
||||
nestedExpression() { return m_matrix; }
|
||||
|
||||
protected:
|
||||
MatrixTypeNested m_matrix;
|
||||
@@ -108,19 +110,21 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
|
||||
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl)
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Scalar* data() { return &(this->coeffRef(0)); }
|
||||
EIGEN_DEVICE_FUNC inline const Scalar* data() const { return &(this->coeff(0)); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const
|
||||
{
|
||||
return derived().nestedExpression().innerStride() * sizeof(typename internal::traits<MatrixType>::Scalar) / sizeof(Scalar);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const
|
||||
{
|
||||
return derived().nestedExpression().outerStride() * sizeof(typename internal::traits<MatrixType>::Scalar) / sizeof(Scalar);
|
||||
}
|
||||
protected:
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(CwiseUnaryViewImpl)
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
+132
-42
@@ -14,15 +14,15 @@
|
||||
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);
|
||||
EIGEN_STATIC_ASSERT(NumTraits<DenseIndex>::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE)
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
||||
/** \class DenseBase
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
@@ -40,7 +40,7 @@ static inline void check_DenseIndex_is_signed() {
|
||||
*/
|
||||
template<typename Derived> class DenseBase
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
: public DenseCoeffsBase<Derived>
|
||||
: public DenseCoeffsBase<Derived, internal::accessors_level<Derived>::value>
|
||||
#else
|
||||
: public DenseCoeffsBase<Derived,DirectWriteAccessors>
|
||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||
@@ -64,14 +64,14 @@ template<typename Derived> class DenseBase
|
||||
|
||||
/** The numeric type of the expression' coefficients, e.g. float, double, int or std::complex<float>, etc. */
|
||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||
|
||||
|
||||
/** The numeric type of the expression' coefficients, e.g. float, double, int or std::complex<float>, etc.
|
||||
*
|
||||
* It is an alias for the Scalar type */
|
||||
typedef Scalar value_type;
|
||||
|
||||
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef DenseCoeffsBase<Derived> Base;
|
||||
typedef DenseCoeffsBase<Derived, internal::accessors_level<Derived>::value> Base;
|
||||
|
||||
using Base::derived;
|
||||
using Base::const_cast_derived;
|
||||
@@ -150,13 +150,18 @@ template<typename Derived> class DenseBase
|
||||
* \sa SizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime
|
||||
*/
|
||||
|
||||
IsVectorAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime == 1
|
||||
|| internal::traits<Derived>::MaxColsAtCompileTime == 1,
|
||||
IsVectorAtCompileTime = internal::traits<Derived>::RowsAtCompileTime == 1
|
||||
|| internal::traits<Derived>::ColsAtCompileTime == 1,
|
||||
/**< This is set to true if either the number of rows or the number of
|
||||
* columns is known at compile-time to be equal to 1. Indeed, in that case,
|
||||
* we are dealing with a column-vector (if there is only one column) or with
|
||||
* a row-vector (if there is only one row). */
|
||||
|
||||
NumDimensions = int(MaxSizeAtCompileTime) == 1 ? 0 : bool(IsVectorAtCompileTime) ? 1 : 2,
|
||||
/**< This value is equal to Tensor::NumDimensions, i.e. 0 for scalars, 1 for vectors,
|
||||
* and 2 for matrices.
|
||||
*/
|
||||
|
||||
Flags = internal::traits<Derived>::Flags,
|
||||
/**< This stores expression \ref flags flags which may or may not be inherited by new expressions
|
||||
* constructed from this one. See the \ref flags "list of flags".
|
||||
@@ -170,11 +175,11 @@ template<typename Derived> class DenseBase
|
||||
InnerStrideAtCompileTime = internal::inner_stride_at_compile_time<Derived>::ret,
|
||||
OuterStrideAtCompileTime = internal::outer_stride_at_compile_time<Derived>::ret
|
||||
};
|
||||
|
||||
|
||||
typedef typename internal::find_best_packet<Scalar,SizeAtCompileTime>::type PacketScalar;
|
||||
|
||||
enum { IsPlainObjectBase = 0 };
|
||||
|
||||
|
||||
/** The plain matrix type corresponding to this expression.
|
||||
* \sa PlainObject */
|
||||
typedef Matrix<typename internal::traits<Derived>::Scalar,
|
||||
@@ -184,7 +189,7 @@ template<typename Derived> class DenseBase
|
||||
internal::traits<Derived>::MaxRowsAtCompileTime,
|
||||
internal::traits<Derived>::MaxColsAtCompileTime
|
||||
> PlainMatrix;
|
||||
|
||||
|
||||
/** The plain array type corresponding to this expression.
|
||||
* \sa PlainObject */
|
||||
typedef Array<typename internal::traits<Derived>::Scalar,
|
||||
@@ -206,7 +211,7 @@ template<typename Derived> class DenseBase
|
||||
|
||||
/** \returns the number of nonzero coefficients which is in practice the number
|
||||
* of stored coefficients. */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index nonZeros() const { return size(); }
|
||||
|
||||
/** \returns the outer size.
|
||||
@@ -214,7 +219,7 @@ template<typename Derived> class DenseBase
|
||||
* \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
|
||||
* column-major matrix, and the number of rows for a row-major matrix. */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
Index outerSize() const
|
||||
{
|
||||
return IsVectorAtCompileTime ? 1
|
||||
@@ -224,9 +229,9 @@ template<typename Derived> class DenseBase
|
||||
/** \returns the inner size.
|
||||
*
|
||||
* \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. */
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
Index innerSize() const
|
||||
{
|
||||
return IsVectorAtCompileTime ? this->size()
|
||||
@@ -261,9 +266,9 @@ template<typename Derived> class DenseBase
|
||||
/** \internal Represents a matrix with all coefficients equal to one another*/
|
||||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,PlainObject> ConstantReturnType;
|
||||
/** \internal \deprecated Represents a vector with linearly spaced coefficients that allows sequential access only. */
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar>,PlainObject> SequentialLinSpacedReturnType;
|
||||
EIGEN_DEPRECATED typedef CwiseNullaryOp<internal::linspaced_op<Scalar>,PlainObject> SequentialLinSpacedReturnType;
|
||||
/** \internal Represents a vector with linearly spaced coefficients that allows random access. */
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,PacketScalar>,PlainObject> RandomAccessLinSpacedReturnType;
|
||||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar>,PlainObject> RandomAccessLinSpacedReturnType;
|
||||
/** \internal the return type of MatrixBase::eigenvalues() */
|
||||
typedef Matrix<typename NumTraits<typename internal::traits<Derived>::Scalar>::Real, internal::traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
|
||||
|
||||
@@ -297,17 +302,17 @@ template<typename Derived> class DenseBase
|
||||
Derived& operator=(const ReturnByValue<OtherDerived>& func);
|
||||
|
||||
/** \internal
|
||||
* Copies \a other into *this without evaluating other. \returns a reference to *this.
|
||||
* \deprecated */
|
||||
* Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
/** \deprecated */
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC
|
||||
Derived& lazyAssign(const DenseBase<OtherDerived>& other);
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
CommaInitializer<Derived> operator<< (const Scalar& s);
|
||||
|
||||
/** \deprecated it now returns \c *this */
|
||||
template<unsigned int Added,unsigned int Removed>
|
||||
/** \deprecated it now returns \c *this */
|
||||
EIGEN_DEPRECATED
|
||||
const Derived& flagged() const
|
||||
{ return derived(); }
|
||||
@@ -332,12 +337,13 @@ template<typename Derived> class DenseBase
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType
|
||||
Constant(const Scalar& value);
|
||||
|
||||
EIGEN_DEVICE_FUNC static const SequentialLinSpacedReturnType
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType
|
||||
LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high);
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType
|
||||
LinSpaced(Sequential_t, const Scalar& low, const Scalar& high);
|
||||
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType
|
||||
LinSpaced(Index size, const Scalar& low, const Scalar& high);
|
||||
EIGEN_DEVICE_FUNC static const SequentialLinSpacedReturnType
|
||||
LinSpaced(Sequential_t, const Scalar& low, const Scalar& high);
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType
|
||||
LinSpaced(const Scalar& low, const Scalar& high);
|
||||
|
||||
@@ -369,7 +375,7 @@ template<typename Derived> class DenseBase
|
||||
template<typename OtherDerived> EIGEN_DEVICE_FUNC
|
||||
bool isApprox(const DenseBase<OtherDerived>& other,
|
||||
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
bool isMuchSmallerThan(const RealScalar& other,
|
||||
const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
template<typename OtherDerived> EIGEN_DEVICE_FUNC
|
||||
@@ -380,7 +386,7 @@ template<typename Derived> class DenseBase
|
||||
EIGEN_DEVICE_FUNC bool isConstant(const Scalar& value, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
EIGEN_DEVICE_FUNC bool isZero(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
EIGEN_DEVICE_FUNC bool isOnes(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
|
||||
|
||||
inline bool hasNaN() const;
|
||||
inline bool allFinite() const;
|
||||
|
||||
@@ -394,8 +400,8 @@ template<typename Derived> class DenseBase
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \warning Be carefull with eval() and the auto C++ keyword, as detailed in this \link TopicPitfalls_auto_keyword page \endlink.
|
||||
*
|
||||
* \warning Be careful with eval() and the auto C++ keyword, as detailed in this \link TopicPitfalls_auto_keyword page \endlink.
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE EvalReturnType eval() const
|
||||
@@ -405,12 +411,12 @@ template<typename Derived> class DenseBase
|
||||
// size types on MSVC.
|
||||
return typename internal::eval<Derived>::type(derived());
|
||||
}
|
||||
|
||||
|
||||
/** swaps *this with the expression \a other.
|
||||
*
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void swap(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(!OtherDerived::IsPlainObjectBase,THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
@@ -422,7 +428,7 @@ template<typename Derived> class DenseBase
|
||||
*
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void swap(PlainObjectBase<OtherDerived>& other)
|
||||
{
|
||||
eigen_assert(rows()==other.rows() && cols()==other.cols());
|
||||
@@ -443,18 +449,58 @@ template<typename Derived> class DenseBase
|
||||
|
||||
EIGEN_DEVICE_FUNC Scalar prod() const;
|
||||
|
||||
template<int NaNPropagation>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar minCoeff() const;
|
||||
template<int NaNPropagation>
|
||||
EIGEN_DEVICE_FUNC typename internal::traits<Derived>::Scalar maxCoeff() const;
|
||||
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
|
||||
// By default, the fastest version with undefined NaN propagation semantics is
|
||||
// used.
|
||||
// TODO(rmlarsen): Replace with default template argument when we move to
|
||||
// c++11 or beyond.
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar minCoeff() const {
|
||||
return minCoeff<PropagateFast>();
|
||||
}
|
||||
EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar maxCoeff() const {
|
||||
return maxCoeff<PropagateFast>();
|
||||
}
|
||||
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const;
|
||||
template<typename IndexType> EIGEN_DEVICE_FUNC
|
||||
template<int NaNPropagation, typename IndexType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const;
|
||||
|
||||
// TODO(rmlarsen): Replace these methods with a default template argument.
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const {
|
||||
return minCoeff<PropagateFast>(row, col);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const {
|
||||
return maxCoeff<PropagateFast>(row, col);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const {
|
||||
return minCoeff<PropagateFast>(index);
|
||||
}
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const {
|
||||
return maxCoeff<PropagateFast>(index);
|
||||
}
|
||||
|
||||
template<typename BinaryOp>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Scalar redux(const BinaryOp& func) const;
|
||||
@@ -493,7 +539,7 @@ template<typename Derived> class DenseBase
|
||||
typedef VectorwiseOp<Derived, Vertical> ColwiseReturnType;
|
||||
typedef const VectorwiseOp<const Derived, Vertical> ConstColwiseReturnType;
|
||||
|
||||
/** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations
|
||||
/** \returns a VectorwiseOp wrapper of *this for broadcasting and partial reductions
|
||||
*
|
||||
* Example: \include MatrixBase_rowwise.cpp
|
||||
* Output: \verbinclude MatrixBase_rowwise.out
|
||||
@@ -506,7 +552,7 @@ template<typename Derived> class DenseBase
|
||||
}
|
||||
EIGEN_DEVICE_FUNC RowwiseReturnType rowwise();
|
||||
|
||||
/** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations
|
||||
/** \returns a VectorwiseOp wrapper of *this broadcasting and partial reductions
|
||||
*
|
||||
* Example: \include MatrixBase_colwise.cpp
|
||||
* Output: \verbinclude MatrixBase_colwise.out
|
||||
@@ -524,16 +570,16 @@ template<typename Derived> class DenseBase
|
||||
static const RandomReturnType Random();
|
||||
|
||||
template<typename ThenDerived,typename ElseDerived>
|
||||
const Select<Derived,ThenDerived,ElseDerived>
|
||||
inline EIGEN_DEVICE_FUNC const Select<Derived,ThenDerived,ElseDerived>
|
||||
select(const DenseBase<ThenDerived>& thenMatrix,
|
||||
const DenseBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
template<typename ThenDerived>
|
||||
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
||||
inline EIGEN_DEVICE_FUNC const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
|
||||
select(const DenseBase<ThenDerived>& thenMatrix, const typename ThenDerived::Scalar& elseScalar) const;
|
||||
|
||||
template<typename ElseDerived>
|
||||
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
||||
inline EIGEN_DEVICE_FUNC const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
|
||||
select(const typename ElseDerived::Scalar& thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
|
||||
|
||||
template<int p> RealScalar lpNorm() const;
|
||||
@@ -567,16 +613,59 @@ template<typename Derived> class DenseBase
|
||||
}
|
||||
EIGEN_DEVICE_FUNC void reverseInPlace();
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** STL-like <a href="https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator">RandomAccessIterator</a>
|
||||
* iterator type as returned by the begin() and end() methods.
|
||||
*/
|
||||
typedef random_access_iterator_type iterator;
|
||||
/** This is the const version of iterator (aka read-only) */
|
||||
typedef random_access_iterator_type const_iterator;
|
||||
#else
|
||||
typedef typename internal::conditional< (Flags&DirectAccessBit)==DirectAccessBit,
|
||||
internal::pointer_based_stl_iterator<Derived>,
|
||||
internal::generic_randaccess_stl_iterator<Derived>
|
||||
>::type iterator_type;
|
||||
|
||||
typedef typename internal::conditional< (Flags&DirectAccessBit)==DirectAccessBit,
|
||||
internal::pointer_based_stl_iterator<const Derived>,
|
||||
internal::generic_randaccess_stl_iterator<const Derived>
|
||||
>::type const_iterator_type;
|
||||
|
||||
// Stl-style iterators are supported only for vectors.
|
||||
|
||||
typedef typename internal::conditional< IsVectorAtCompileTime,
|
||||
iterator_type,
|
||||
void
|
||||
>::type iterator;
|
||||
|
||||
typedef typename internal::conditional< IsVectorAtCompileTime,
|
||||
const_iterator_type,
|
||||
void
|
||||
>::type const_iterator;
|
||||
#endif
|
||||
|
||||
inline iterator begin();
|
||||
inline const_iterator begin() const;
|
||||
inline const_iterator cbegin() const;
|
||||
inline iterator end();
|
||||
inline const_iterator end() const;
|
||||
inline const_iterator cend() const;
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND)
|
||||
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||
# include "../plugins/BlockMethods.h"
|
||||
# include "../plugins/IndexedViewMethods.h"
|
||||
# include "../plugins/ReshapedMethods.h"
|
||||
# ifdef EIGEN_DENSEBASE_PLUGIN
|
||||
# include EIGEN_DENSEBASE_PLUGIN
|
||||
# endif
|
||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||
#undef EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
|
||||
#undef EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF
|
||||
#undef EIGEN_DOC_UNARY_ADDONS
|
||||
|
||||
// disable the use of evalTo for dense objects with a nice compilation error
|
||||
template<typename Dest>
|
||||
@@ -587,11 +676,12 @@ template<typename Derived> class DenseBase
|
||||
}
|
||||
|
||||
protected:
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase)
|
||||
/** Default constructor. Do nothing. */
|
||||
EIGEN_DEVICE_FUNC DenseBase()
|
||||
{
|
||||
/* 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 paranoia and could slow compilation down
|
||||
*/
|
||||
#ifdef EIGEN_INTERNAL_DEBUGGING
|
||||
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor))
|
||||
|
||||
@@ -22,11 +22,12 @@ template<typename T> struct add_const_on_value_type_if_arithmetic
|
||||
/** \brief Base class providing read-only coefficient access to matrices and arrays.
|
||||
* \ingroup Core_Module
|
||||
* \tparam Derived Type of the derived class
|
||||
* \tparam #ReadOnlyAccessors Constant indicating read-only access
|
||||
*
|
||||
* \note #ReadOnlyAccessors Constant indicating read-only access
|
||||
*
|
||||
* This class defines the \c operator() \c const function and friends, which can be used to read specific
|
||||
* entries of a matrix or array.
|
||||
*
|
||||
*
|
||||
* \sa DenseCoeffsBase<Derived, WriteAccessors>, DenseCoeffsBase<Derived, DirectAccessors>,
|
||||
* \ref TopicClassHierarchy
|
||||
*/
|
||||
@@ -288,12 +289,13 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
|
||||
/** \brief Base class providing read/write coefficient access to matrices and arrays.
|
||||
* \ingroup Core_Module
|
||||
* \tparam Derived Type of the derived class
|
||||
* \tparam #WriteAccessors Constant indicating read/write access
|
||||
*
|
||||
* \note #WriteAccessors Constant indicating read/write access
|
||||
*
|
||||
* This class defines the non-const \c operator() function and friends, which can be used to write specific
|
||||
* entries of a matrix or array. This class inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which
|
||||
* defines the const variant for reading specific entries.
|
||||
*
|
||||
*
|
||||
* \sa DenseCoeffsBase<Derived, DirectAccessors>, \ref TopicClassHierarchy
|
||||
*/
|
||||
template<typename Derived>
|
||||
@@ -466,7 +468,8 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
/** \brief Base class providing direct read-only coefficient access to matrices and arrays.
|
||||
* \ingroup Core_Module
|
||||
* \tparam Derived Type of the derived class
|
||||
* \tparam #DirectAccessors Constant indicating direct access
|
||||
*
|
||||
* \note #DirectAccessors Constant indicating direct access
|
||||
*
|
||||
* This class defines functions to work with strides which can be used to access entries directly. This class
|
||||
* inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which defines functions to access entries read-only using
|
||||
@@ -492,7 +495,7 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
*
|
||||
* \sa outerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const
|
||||
{
|
||||
return derived().innerStride();
|
||||
@@ -503,14 +506,14 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
*
|
||||
* \sa innerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const
|
||||
{
|
||||
return derived().outerStride();
|
||||
}
|
||||
|
||||
// FIXME shall we remove it ?
|
||||
inline Index stride() const
|
||||
EIGEN_CONSTEXPR inline Index stride() const
|
||||
{
|
||||
return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
|
||||
}
|
||||
@@ -519,7 +522,7 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
*
|
||||
* \sa innerStride(), outerStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rowStride() const
|
||||
{
|
||||
return Derived::IsRowMajor ? outerStride() : innerStride();
|
||||
@@ -529,7 +532,7 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
*
|
||||
* \sa innerStride(), outerStride(), rowStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index colStride() const
|
||||
{
|
||||
return Derived::IsRowMajor ? innerStride() : outerStride();
|
||||
@@ -539,7 +542,8 @@ class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived
|
||||
/** \brief Base class providing direct read/write coefficient access to matrices and arrays.
|
||||
* \ingroup Core_Module
|
||||
* \tparam Derived Type of the derived class
|
||||
* \tparam #DirectWriteAccessors Constant indicating direct access
|
||||
*
|
||||
* \note #DirectWriteAccessors Constant indicating direct access
|
||||
*
|
||||
* This class defines functions to work with strides which can be used to access entries directly. This class
|
||||
* inherits DenseCoeffsBase<Derived, WriteAccessors> which defines functions to access entries read/write using
|
||||
@@ -566,8 +570,8 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
|
||||
*
|
||||
* \sa outerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return derived().innerStride();
|
||||
}
|
||||
@@ -577,14 +581,14 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
|
||||
*
|
||||
* \sa innerStride(), rowStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index outerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return derived().outerStride();
|
||||
}
|
||||
|
||||
// FIXME shall we remove it ?
|
||||
inline Index stride() const
|
||||
EIGEN_CONSTEXPR inline Index stride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
|
||||
}
|
||||
@@ -593,8 +597,8 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
|
||||
*
|
||||
* \sa innerStride(), outerStride(), colStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index rowStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rowStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return Derived::IsRowMajor ? outerStride() : innerStride();
|
||||
}
|
||||
@@ -603,8 +607,8 @@ class DenseCoeffsBase<Derived, DirectWriteAccessors>
|
||||
*
|
||||
* \sa innerStride(), outerStride(), rowStride()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index colStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index colStride() const EIGEN_NOEXCEPT
|
||||
{
|
||||
return Derived::IsRowMajor ? innerStride() : outerStride();
|
||||
}
|
||||
@@ -615,7 +619,7 @@ namespace internal {
|
||||
template<int Alignment, typename Derived, bool JustReturnZero>
|
||||
struct first_aligned_impl
|
||||
{
|
||||
static inline Index run(const Derived&)
|
||||
static EIGEN_CONSTEXPR inline Index run(const Derived&) EIGEN_NOEXCEPT
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -47,21 +47,21 @@ struct plain_array
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
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)
|
||||
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
|
||||
#elif EIGEN_GNUC_AT_LEAST(4,7)
|
||||
// GCC 4.7 is too aggressive in its optimizations and remove the alignement test based on the fact the array is declared to be aligned.
|
||||
#elif EIGEN_GNUC_AT_LEAST(4,7)
|
||||
// GCC 4.7 is too aggressive in its optimizations and remove the alignment test based on the fact the array is declared to be aligned.
|
||||
// See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
|
||||
// Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
|
||||
template<typename PtrType>
|
||||
@@ -85,15 +85,15 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 8>
|
||||
EIGEN_ALIGN_TO_BOUNDARY(8) T array[Size];
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array()
|
||||
plain_array()
|
||||
{
|
||||
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(7);
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
};
|
||||
@@ -104,15 +104,15 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 16>
|
||||
EIGEN_ALIGN_TO_BOUNDARY(16) T array[Size];
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array()
|
||||
{
|
||||
plain_array()
|
||||
{
|
||||
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(15);
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
};
|
||||
@@ -123,15 +123,15 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 32>
|
||||
EIGEN_ALIGN_TO_BOUNDARY(32) T array[Size];
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array()
|
||||
plain_array()
|
||||
{
|
||||
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(31);
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
};
|
||||
@@ -142,15 +142,15 @@ struct plain_array<T, Size, MatrixOrArrayOptions, 64>
|
||||
EIGEN_ALIGN_TO_BOUNDARY(64) T array[Size];
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array()
|
||||
{
|
||||
plain_array()
|
||||
{
|
||||
EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(63);
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
plain_array(constructor_without_unaligned_array_assert)
|
||||
{
|
||||
check_static_allocation_size<T,Size>();
|
||||
}
|
||||
};
|
||||
@@ -163,6 +163,30 @@ struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
|
||||
EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {}
|
||||
};
|
||||
|
||||
struct plain_array_helper {
|
||||
template<typename T, int Size, int MatrixOrArrayOptions, int Alignment>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
static void copy(const plain_array<T, Size, MatrixOrArrayOptions, Alignment>& src, const Eigen::Index size,
|
||||
plain_array<T, Size, MatrixOrArrayOptions, Alignment>& dst) {
|
||||
smart_copy(src.array, src.array + size, dst.array);
|
||||
}
|
||||
|
||||
template<typename T, int Size, int MatrixOrArrayOptions, int Alignment>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
static void swap(plain_array<T, Size, MatrixOrArrayOptions, Alignment>& a, const Eigen::Index a_size,
|
||||
plain_array<T, Size, MatrixOrArrayOptions, Alignment>& b, const Eigen::Index b_size) {
|
||||
if (a_size < b_size) {
|
||||
std::swap_ranges(b.array, b.array + a_size, a.array);
|
||||
smart_move(b.array + a_size, b.array + b_size, a.array + a_size);
|
||||
} else if (a_size > b_size) {
|
||||
std::swap_ranges(a.array, a.array + b_size, b.array);
|
||||
smart_move(a.array + b_size, a.array + a_size, b.array + b_size);
|
||||
} else {
|
||||
std::swap_ranges(a.array, a.array + a_size, b.array);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \internal
|
||||
@@ -190,16 +214,41 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()) {}
|
||||
EIGEN_DEVICE_FUNC
|
||||
#if !EIGEN_HAS_CXX11 || defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN)
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage&) = default;
|
||||
#endif
|
||||
#if !EIGEN_HAS_CXX11
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
{
|
||||
if (this != &other) m_data = other.m_data;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage&) = default;
|
||||
#endif
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
#if !EIGEN_HAS_CXX11
|
||||
EIGEN_DEVICE_FUNC DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
: m_data(std::move(other.m_data))
|
||||
{
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
m_data = std::move(other.m_data);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
EIGEN_DEVICE_FUNC DenseStorage(DenseStorage&&) = default;
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(DenseStorage&&) = default;
|
||||
#endif
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols);
|
||||
@@ -207,9 +256,11 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
||||
EIGEN_UNUSED_VARIABLE(rows);
|
||||
EIGEN_UNUSED_VARIABLE(cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
|
||||
EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) {
|
||||
numext::swap(m_data, other.m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index rows(void) EIGEN_NOEXCEPT {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index cols(void) EIGEN_NOEXCEPT {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index,Index,Index) {}
|
||||
EIGEN_DEVICE_FUNC void resize(Index,Index,Index) {}
|
||||
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
|
||||
@@ -226,8 +277,8 @@ template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage&) { return *this; }
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index,Index,Index) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& ) {}
|
||||
EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index rows(void) EIGEN_NOEXCEPT {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index cols(void) EIGEN_NOEXCEPT {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index,Index,Index) {}
|
||||
EIGEN_DEVICE_FUNC void resize(Index,Index,Index) {}
|
||||
EIGEN_DEVICE_FUNC const T *data() const { return 0; }
|
||||
@@ -254,20 +305,28 @@ template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(other.m_rows), m_cols(other.m_cols)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_rows = other.m_rows;
|
||||
m_cols = other.m_cols;
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * m_cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index cols) : m_rows(rows), m_cols(cols) {}
|
||||
EIGEN_DEVICE_FUNC 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); }
|
||||
{
|
||||
internal::plain_array_helper::swap(m_data, m_rows * m_cols, other.m_data, other.m_rows * other.m_cols);
|
||||
numext::swap(m_rows,other.m_rows);
|
||||
numext::swap(m_cols,other.m_cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC Index rows() const {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols() const {return m_cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index, Index rows, Index cols) { m_rows = rows; m_cols = cols; }
|
||||
@@ -285,20 +344,29 @@ template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Si
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(other.m_rows)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * _Cols, m_data);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_rows = other.m_rows;
|
||||
internal::plain_array_helper::copy(other.m_data, m_rows * _Cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index) : m_rows(rows) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other)
|
||||
{
|
||||
internal::plain_array_helper::swap(m_data, m_rows * _Cols, other.m_data, other.m_rows * _Cols);
|
||||
numext::swap(m_rows, other.m_rows);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const EIGEN_NOEXCEPT {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols(void) const EIGEN_NOEXCEPT {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index, Index rows, Index) { m_rows = rows; }
|
||||
EIGEN_DEVICE_FUNC void resize(Index, Index rows, Index) { m_rows = rows; }
|
||||
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
|
||||
@@ -314,22 +382,29 @@ template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Si
|
||||
EIGEN_DEVICE_FUNC DenseStorage() : m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(other.m_cols)
|
||||
{
|
||||
internal::plain_array_helper::copy(other.m_data, _Rows * m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
m_cols = other.m_cols;
|
||||
internal::plain_array_helper::copy(other.m_data, _Rows * m_cols, m_data);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index, Index, Index cols) : m_cols(cols) {}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
|
||||
void conservativeResize(Index, Index, Index cols) { m_cols = cols; }
|
||||
void resize(Index, Index, Index cols) { m_cols = cols; }
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) {
|
||||
internal::plain_array_helper::swap(m_data, _Rows * m_cols, other.m_data, _Rows * other.m_cols);
|
||||
numext::swap(m_cols, other.m_cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows(void) const EIGEN_NOEXCEPT {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const EIGEN_NOEXCEPT {return m_cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index, Index, Index cols) { m_cols = cols; }
|
||||
EIGEN_DEVICE_FUNC void resize(Index, Index, Index cols) { m_cols = cols; }
|
||||
EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
|
||||
EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
|
||||
};
|
||||
@@ -381,18 +456,21 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_data, other.m_data);
|
||||
swap(m_rows, other.m_rows);
|
||||
swap(m_cols, other.m_cols);
|
||||
numext::swap(m_data, other.m_data);
|
||||
numext::swap(m_rows, other.m_rows);
|
||||
numext::swap(m_cols, other.m_cols);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
|
||||
EIGEN_DEVICE_FUNC 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); }
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
|
||||
{
|
||||
numext::swap(m_data,other.m_data);
|
||||
numext::swap(m_rows,other.m_rows);
|
||||
numext::swap(m_cols,other.m_cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const EIGEN_NOEXCEPT {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const EIGEN_NOEXCEPT {return m_cols;}
|
||||
void conservativeResize(Index size, Index rows, Index cols)
|
||||
{
|
||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
|
||||
@@ -404,7 +482,7 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
||||
if(size != m_rows*m_cols)
|
||||
{
|
||||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
|
||||
if (size)
|
||||
if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative
|
||||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
@@ -446,7 +524,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
||||
this->swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
@@ -459,16 +537,18 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_data, other.m_data);
|
||||
swap(m_cols, other.m_cols);
|
||||
numext::swap(m_data, other.m_data);
|
||||
numext::swap(m_cols, other.m_cols);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
|
||||
EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) {
|
||||
numext::swap(m_data,other.m_data);
|
||||
numext::swap(m_cols,other.m_cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index rows(void) EIGEN_NOEXCEPT {return _Rows;}
|
||||
EIGEN_DEVICE_FUNC Index cols(void) const EIGEN_NOEXCEPT {return m_cols;}
|
||||
EIGEN_DEVICE_FUNC void conservativeResize(Index size, Index, Index cols)
|
||||
{
|
||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
|
||||
@@ -479,7 +559,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
||||
if(size != _Rows*m_cols)
|
||||
{
|
||||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
|
||||
if (size)
|
||||
if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative
|
||||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
@@ -520,7 +600,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
||||
this->swap(tmp);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
@@ -533,16 +613,18 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_data, other.m_data);
|
||||
swap(m_rows, other.m_rows);
|
||||
numext::swap(m_data, other.m_data);
|
||||
numext::swap(m_rows, other.m_rows);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
|
||||
EIGEN_DEVICE_FUNC void swap(DenseStorage& other) {
|
||||
numext::swap(m_data,other.m_data);
|
||||
numext::swap(m_rows,other.m_rows);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC Index rows(void) const EIGEN_NOEXCEPT {return m_rows;}
|
||||
EIGEN_DEVICE_FUNC static EIGEN_CONSTEXPR Index cols(void) {return _Cols;}
|
||||
void conservativeResize(Index size, Index rows, Index)
|
||||
{
|
||||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
|
||||
@@ -553,7 +635,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
||||
if(size != m_rows*_Cols)
|
||||
{
|
||||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
|
||||
if (size)
|
||||
if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative
|
||||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef EIGEN_DIAGONAL_H
|
||||
#define EIGEN_DIAGONAL_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
/** \class Diagonal
|
||||
* \ingroup Core_Module
|
||||
@@ -70,7 +70,10 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal)
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {}
|
||||
explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index)
|
||||
{
|
||||
eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() );
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
|
||||
|
||||
@@ -81,20 +84,16 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
||||
: numext::mini<Index>(m_matrix.rows(),m_matrix.cols()-m_index.value());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index cols() const { return 1; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return 1; }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT {
|
||||
return m_matrix.outerStride() + 1;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index outerStride() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return 0; }
|
||||
|
||||
typedef typename internal::conditional<
|
||||
internal::is_lvalue<MatrixType>::value,
|
||||
@@ -146,8 +145,8 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const typename internal::remove_all<typename MatrixType::Nested>::type&
|
||||
nestedExpression() const
|
||||
inline const typename internal::remove_all<typename MatrixType::Nested>::type&
|
||||
nestedExpression() const
|
||||
{
|
||||
return m_matrix;
|
||||
}
|
||||
@@ -164,12 +163,12 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
||||
|
||||
private:
|
||||
// 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_DEVICE_FUNC
|
||||
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_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index absDiagIndex() const EIGEN_NOEXCEPT { return m_index.value()>0 ? m_index.value() : -m_index.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rowOffset() const EIGEN_NOEXCEPT { return m_index.value()>0 ? 0 : -m_index.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index colOffset() const EIGEN_NOEXCEPT { return m_index.value()>0 ? m_index.value() : 0; }
|
||||
// trigger a compile-time error if someone try to call packet
|
||||
template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const;
|
||||
template<int LoadMode> typename MatrixType::PacketReturnType packet(Index,Index) const;
|
||||
@@ -184,7 +183,7 @@ template<typename MatrixType, int _DiagIndex> class Diagonal
|
||||
*
|
||||
* \sa class Diagonal */
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::DiagonalReturnType
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::DiagonalReturnType
|
||||
MatrixBase<Derived>::diagonal()
|
||||
{
|
||||
return DiagonalReturnType(derived());
|
||||
@@ -192,7 +191,7 @@ MatrixBase<Derived>::diagonal()
|
||||
|
||||
/** This is the const version of diagonal(). */
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::ConstDiagonalReturnType
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::ConstDiagonalReturnType
|
||||
MatrixBase<Derived>::diagonal() const
|
||||
{
|
||||
return ConstDiagonalReturnType(derived());
|
||||
@@ -210,7 +209,7 @@ MatrixBase<Derived>::diagonal() const
|
||||
*
|
||||
* \sa MatrixBase::diagonal(), class Diagonal */
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::DiagonalDynamicIndexReturnType
|
||||
MatrixBase<Derived>::diagonal(Index index)
|
||||
{
|
||||
return DiagonalDynamicIndexReturnType(derived(), index);
|
||||
@@ -218,7 +217,7 @@ MatrixBase<Derived>::diagonal(Index index)
|
||||
|
||||
/** This is the const version of diagonal(Index). */
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
|
||||
EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::ConstDiagonalDynamicIndexReturnType
|
||||
MatrixBase<Derived>::diagonal(Index index) const
|
||||
{
|
||||
return ConstDiagonalDynamicIndexReturnType(derived(), index);
|
||||
@@ -237,6 +236,7 @@ MatrixBase<Derived>::diagonal(Index index) const
|
||||
* \sa MatrixBase::diagonal(), class Diagonal */
|
||||
template<typename Derived>
|
||||
template<int Index_>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index_>::Type
|
||||
MatrixBase<Derived>::diagonal()
|
||||
{
|
||||
@@ -246,6 +246,7 @@ MatrixBase<Derived>::diagonal()
|
||||
/** This is the const version of diagonal<int>(). */
|
||||
template<typename Derived>
|
||||
template<int Index_>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index_>::Type
|
||||
MatrixBase<Derived>::diagonal() const
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ class DiagonalBase : public EigenBase<Derived>
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseMatrixType toDenseMatrix() const { return derived(); }
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -83,6 +83,30 @@ class DiagonalBase : public EigenBase<Derived>
|
||||
{
|
||||
return DiagonalWrapper<const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,DiagonalVectorType,product) >(scalar * other.diagonal());
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
inline unspecified_expression_type
|
||||
#else
|
||||
inline const DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(DiagonalVectorType,typename OtherDerived::DiagonalVectorType,sum) >
|
||||
#endif
|
||||
operator+(const DiagonalBase<OtherDerived>& other) const
|
||||
{
|
||||
return (diagonal() + other.diagonal()).asDiagonal();
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
inline unspecified_expression_type
|
||||
#else
|
||||
inline const DiagonalWrapper<const EIGEN_CWISE_BINARY_RETURN_TYPE(DiagonalVectorType,typename OtherDerived::DiagonalVectorType,difference) >
|
||||
#endif
|
||||
operator-(const DiagonalBase<OtherDerived>& other) const
|
||||
{
|
||||
return (diagonal() - other.diagonal()).asDiagonal();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -154,6 +178,30 @@ class DiagonalMatrix
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \brief Construct a diagonal matrix with fixed size from an arbitrary number of coefficients. \cpp11
|
||||
*
|
||||
* There exists C++98 anologue constructors for fixed-size diagonal matrices having 2 or 3 coefficients.
|
||||
*
|
||||
* \warning To construct a diagonal matrix of fixed size, the number of values passed to this
|
||||
* constructor must match the fixed dimension of \c *this.
|
||||
*
|
||||
* \sa DiagonalMatrix(const Scalar&, const Scalar&)
|
||||
* \sa DiagonalMatrix(const Scalar&, const Scalar&, const Scalar&)
|
||||
*/
|
||||
template <typename... ArgTypes>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
DiagonalMatrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const ArgTypes&... args)
|
||||
: m_diagonal(a0, a1, a2, args...) {}
|
||||
|
||||
/** \brief Constructs a DiagonalMatrix and initializes it by elements given by an initializer list of initializer
|
||||
* lists \cpp11
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit EIGEN_STRONG_INLINE DiagonalMatrix(const std::initializer_list<std::initializer_list<Scalar>>& list)
|
||||
: m_diagonal(list) {}
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
/** Copy constructor. */
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -273,7 +321,7 @@ class DiagonalWrapper
|
||||
* \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal()
|
||||
**/
|
||||
template<typename Derived>
|
||||
inline const DiagonalWrapper<const Derived>
|
||||
EIGEN_DEVICE_FUNC inline const DiagonalWrapper<const Derived>
|
||||
MatrixBase<Derived>::asDiagonal() const
|
||||
{
|
||||
return DiagonalWrapper<const Derived>(derived());
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Eigen {
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename DiagonalDerived>
|
||||
inline const Product<Derived, DiagonalDerived, LazyProduct>
|
||||
EIGEN_DEVICE_FUNC inline const Product<Derived, DiagonalDerived, LazyProduct>
|
||||
MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &a_diagonal) const
|
||||
{
|
||||
return Product<Derived, DiagonalDerived, LazyProduct>(derived(),a_diagonal.derived());
|
||||
|
||||
+15
-12
@@ -31,7 +31,8 @@ struct dot_nocheck
|
||||
typedef scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> conj_prod;
|
||||
typedef typename conj_prod::result_type ResScalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
|
||||
EIGEN_STRONG_INLINE
|
||||
static ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
|
||||
{
|
||||
return a.template binaryExpr<conj_prod>(b).sum();
|
||||
}
|
||||
@@ -43,7 +44,8 @@ struct dot_nocheck<T, U, true>
|
||||
typedef scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> conj_prod;
|
||||
typedef typename conj_prod::result_type ResScalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
|
||||
EIGEN_STRONG_INLINE
|
||||
static ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
|
||||
{
|
||||
return a.transpose().template binaryExpr<conj_prod>(b).sum();
|
||||
}
|
||||
@@ -65,6 +67,7 @@ struct dot_nocheck<T, U, true>
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE
|
||||
typename ScalarBinaryOpTraits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
||||
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
@@ -83,14 +86,14 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
|
||||
//---------- 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 squared Frobenius norm.
|
||||
* In both cases, it consists in the sum of the square of all the matrix entries.
|
||||
* For vectors, this is also equals to the dot product of \c *this with itself.
|
||||
*
|
||||
* \sa dot(), norm(), lpNorm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
|
||||
{
|
||||
return numext::real((*this).cwiseAbs2().sum());
|
||||
}
|
||||
@@ -102,7 +105,7 @@ EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scala
|
||||
* \sa lpNorm(), dot(), squaredNorm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
|
||||
{
|
||||
return numext::sqrt(squaredNorm());
|
||||
}
|
||||
@@ -117,7 +120,7 @@ inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real Matr
|
||||
* \sa norm(), normalize()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::PlainObject
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::normalized() const
|
||||
{
|
||||
typedef typename internal::nested_eval<Derived,2>::type _Nested;
|
||||
@@ -139,7 +142,7 @@ MatrixBase<Derived>::normalized() const
|
||||
* \sa norm(), normalized()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline void MatrixBase<Derived>::normalize()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::normalize()
|
||||
{
|
||||
RealScalar z = squaredNorm();
|
||||
// NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
|
||||
@@ -160,7 +163,7 @@ inline void MatrixBase<Derived>::normalize()
|
||||
* \sa stableNorm(), stableNormalize(), normalized()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::PlainObject
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::stableNormalized() const
|
||||
{
|
||||
typedef typename internal::nested_eval<Derived,3>::type _Nested;
|
||||
@@ -185,7 +188,7 @@ MatrixBase<Derived>::stableNormalized() const
|
||||
* \sa stableNorm(), stableNormalized(), normalize()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline void MatrixBase<Derived>::stableNormalize()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::stableNormalize()
|
||||
{
|
||||
RealScalar w = cwiseAbs().maxCoeff();
|
||||
RealScalar z = (derived()/w).squaredNorm();
|
||||
@@ -204,7 +207,7 @@ struct lpNorm_selector
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline RealScalar run(const MatrixBase<Derived>& m)
|
||||
{
|
||||
EIGEN_USING_STD_MATH(pow)
|
||||
EIGEN_USING_STD(pow)
|
||||
return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
|
||||
}
|
||||
};
|
||||
@@ -257,9 +260,9 @@ struct lpNorm_selector<Derived, Infinity>
|
||||
template<typename Derived>
|
||||
template<int p>
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
||||
EIGEN_DEVICE_FUNC inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
|
||||
#else
|
||||
MatrixBase<Derived>::RealScalar
|
||||
EIGEN_DEVICE_FUNC MatrixBase<Derived>::RealScalar
|
||||
#endif
|
||||
MatrixBase<Derived>::lpNorm() const
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Eigen {
|
||||
|
||||
/** \class EigenBase
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
*
|
||||
* Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T).
|
||||
*
|
||||
* In other words, an EigenBase object is an object that can be copied into a MatrixBase.
|
||||
@@ -29,11 +29,12 @@ namespace Eigen {
|
||||
template<typename Derived> struct EigenBase
|
||||
{
|
||||
// typedef typename internal::plain_matrix_type<Derived>::type PlainObject;
|
||||
|
||||
|
||||
/** \brief The interface type of indices
|
||||
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
|
||||
* \deprecated Since Eigen 3.3, its usage is deprecated. Use Eigen::Index instead.
|
||||
* \sa StorageIndex, \ref TopicPreprocessorDirectives.
|
||||
* DEPRECATED: Since Eigen 3.3, its usage is deprecated. Use Eigen::Index instead.
|
||||
* Deprecation is not marked with a doxygen comment because there are too many existing usages to add the deprecation attribute.
|
||||
*/
|
||||
typedef Eigen::Index Index;
|
||||
|
||||
@@ -55,15 +56,15 @@ template<typename Derived> struct EigenBase
|
||||
{ return *static_cast<const Derived*>(this); }
|
||||
|
||||
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index rows() const { return derived().rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return derived().rows(); }
|
||||
/** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index cols() const { return derived().cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return derived().cols(); }
|
||||
/** \returns the number of coefficients, which is rows()*cols().
|
||||
* \sa rows(), cols(), SizeAtCompileTime. */
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index size() const { return rows() * cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index size() const EIGEN_NOEXCEPT { return rows() * cols(); }
|
||||
|
||||
/** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */
|
||||
template<typename Dest>
|
||||
|
||||
@@ -41,10 +41,14 @@ template<typename ExpressionType> class ForceAlignedAccess
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline ForceAlignedAccess(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const { return m_expression.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
|
||||
@@ -100,7 +100,7 @@ struct isMuchSmallerThan_scalar_selector<Derived, true>
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
bool DenseBase<Derived>::isApprox(
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isApprox(
|
||||
const DenseBase<OtherDerived>& other,
|
||||
const RealScalar& prec
|
||||
) const
|
||||
@@ -122,7 +122,7 @@ bool DenseBase<Derived>::isApprox(
|
||||
* \sa isApprox(), isMuchSmallerThan(const DenseBase<OtherDerived>&, RealScalar) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool DenseBase<Derived>::isMuchSmallerThan(
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isMuchSmallerThan(
|
||||
const typename NumTraits<Scalar>::Real& other,
|
||||
const RealScalar& prec
|
||||
) const
|
||||
@@ -142,7 +142,7 @@ bool DenseBase<Derived>::isMuchSmallerThan(
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
bool DenseBase<Derived>::isMuchSmallerThan(
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isMuchSmallerThan(
|
||||
const DenseBase<OtherDerived>& other,
|
||||
const RealScalar& prec
|
||||
) const
|
||||
|
||||
@@ -18,18 +18,33 @@ enum {
|
||||
Small = 3
|
||||
};
|
||||
|
||||
// Define the threshold value to fallback from the generic matrix-matrix product
|
||||
// implementation (heavy) to the lightweight coeff-based product one.
|
||||
// See generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemmProduct>
|
||||
// in products/GeneralMatrixMatrix.h for more details.
|
||||
// TODO This threshold should also be used in the compile-time selector below.
|
||||
#ifndef EIGEN_GEMM_TO_COEFFBASED_THRESHOLD
|
||||
// This default value has been obtained on a Haswell architecture.
|
||||
#define EIGEN_GEMM_TO_COEFFBASED_THRESHOLD 20
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<int Rows, int Cols, int Depth> struct product_type_selector;
|
||||
|
||||
template<int Size, int MaxSize> struct product_size_category
|
||||
{
|
||||
enum { is_large = MaxSize == Dynamic ||
|
||||
Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD ||
|
||||
(Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD),
|
||||
value = is_large ? Large
|
||||
: Size == 1 ? 1
|
||||
: Small
|
||||
enum {
|
||||
#ifndef EIGEN_GPU_COMPILE_PHASE
|
||||
is_large = MaxSize == Dynamic ||
|
||||
Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD ||
|
||||
(Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD),
|
||||
#else
|
||||
is_large = 0,
|
||||
#endif
|
||||
value = is_large ? Large
|
||||
: Size == 1 ? 1
|
||||
: Small
|
||||
};
|
||||
};
|
||||
|
||||
@@ -148,13 +163,13 @@ template<typename Scalar,int Size,int MaxSize,bool Cond> struct gemv_static_vect
|
||||
template<typename Scalar,int Size,int MaxSize>
|
||||
struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; }
|
||||
};
|
||||
|
||||
template<typename Scalar,int Size>
|
||||
struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
|
||||
{
|
||||
EIGEN_STRONG_INLINE Scalar* data() { return 0; }
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Scalar* data() { return 0; }
|
||||
};
|
||||
|
||||
template<typename Scalar,int Size,int MaxSize>
|
||||
@@ -213,8 +228,7 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,true>
|
||||
ActualLhsType actualLhs = LhsBlasTraits::extract(lhs);
|
||||
ActualRhsType actualRhs = RhsBlasTraits::extract(rhs);
|
||||
|
||||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs)
|
||||
* RhsBlasTraits::extractScalarFactor(rhs);
|
||||
ResScalar actualAlpha = combine_scalar_factors(alpha, lhs, rhs);
|
||||
|
||||
// make sure Dest is a compile-time vector type (bug 1166)
|
||||
typedef typename conditional<Dest::IsVectorAtCompileTime, Dest, typename Dest::ColXpr>::type ActualDest;
|
||||
@@ -224,7 +238,7 @@ template<> struct gemv_dense_selector<OnTheRight,ColMajor,true>
|
||||
// on, the other hand it is good for the cache to pack the vector anyways...
|
||||
EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
|
||||
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
|
||||
MightCannotUseDest = (!EvalToDestAtCompileTime) || ComplexByReal
|
||||
MightCannotUseDest = ((!EvalToDestAtCompileTime) || ComplexByReal) && (ActualDest::MaxSizeAtCompileTime!=0)
|
||||
};
|
||||
|
||||
typedef const_blas_data_mapper<LhsScalar,Index,ColMajor> LhsMapper;
|
||||
@@ -305,13 +319,12 @@ template<> struct gemv_dense_selector<OnTheRight,RowMajor,true>
|
||||
typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(lhs);
|
||||
typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(rhs);
|
||||
|
||||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs)
|
||||
* RhsBlasTraits::extractScalarFactor(rhs);
|
||||
ResScalar actualAlpha = combine_scalar_factors(alpha, lhs, rhs);
|
||||
|
||||
enum {
|
||||
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
|
||||
// on, the other hand it is good for the cache to pack the vector anyways...
|
||||
DirectlyUseRhs = ActualRhsTypeCleaned::InnerStrideAtCompileTime==1
|
||||
DirectlyUseRhs = ActualRhsTypeCleaned::InnerStrideAtCompileTime==1 || ActualRhsTypeCleaned::MaxSizeAtCompileTime==0
|
||||
};
|
||||
|
||||
gemv_static_vector_if<RhsScalar,ActualRhsTypeCleaned::SizeAtCompileTime,ActualRhsTypeCleaned::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
|
||||
@@ -379,11 +392,10 @@ template<> struct gemv_dense_selector<OnTheRight,RowMajor,false>
|
||||
*
|
||||
* \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*()
|
||||
*/
|
||||
#ifndef __CUDACC__
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline const Product<Derived, OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_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
|
||||
@@ -412,8 +424,6 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
return Product<Derived, OtherDerived>(derived(), other.derived());
|
||||
}
|
||||
|
||||
#endif // __CUDACC__
|
||||
|
||||
/** \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
|
||||
@@ -427,6 +437,7 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Product<Derived,OtherDerived,LazyProduct>
|
||||
MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
|
||||
@@ -44,23 +44,29 @@ struct default_packet_traits
|
||||
enum {
|
||||
HasHalfPacket = 0,
|
||||
|
||||
HasAdd = 1,
|
||||
HasSub = 1,
|
||||
HasMul = 1,
|
||||
HasNegate = 1,
|
||||
HasAbs = 1,
|
||||
HasArg = 0,
|
||||
HasAbs2 = 1,
|
||||
HasMin = 1,
|
||||
HasMax = 1,
|
||||
HasConj = 1,
|
||||
HasAdd = 1,
|
||||
HasSub = 1,
|
||||
HasShift = 1,
|
||||
HasMul = 1,
|
||||
HasNegate = 1,
|
||||
HasAbs = 1,
|
||||
HasArg = 0,
|
||||
HasAbs2 = 1,
|
||||
HasAbsDiff = 0,
|
||||
HasMin = 1,
|
||||
HasMax = 1,
|
||||
HasConj = 1,
|
||||
HasSetLinear = 1,
|
||||
HasBlend = 0,
|
||||
HasBlend = 0,
|
||||
// This flag is used to indicate whether packet comparison is supported.
|
||||
// pcmp_eq, pcmp_lt and pcmp_le should be defined for it to be true.
|
||||
HasCmp = 0,
|
||||
|
||||
HasDiv = 0,
|
||||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
HasExp = 0,
|
||||
HasExpm1 = 0,
|
||||
HasLog = 0,
|
||||
HasLog1p = 0,
|
||||
HasLog10 = 0,
|
||||
@@ -81,14 +87,18 @@ struct default_packet_traits
|
||||
HasPolygamma = 0,
|
||||
HasErf = 0,
|
||||
HasErfc = 0,
|
||||
HasNdtri = 0,
|
||||
HasBessel = 0,
|
||||
HasIGamma = 0,
|
||||
HasIGammaDerA = 0,
|
||||
HasGammaSampleDerAlpha = 0,
|
||||
HasIGammac = 0,
|
||||
HasBetaInc = 0,
|
||||
|
||||
HasRound = 0,
|
||||
HasRint = 0,
|
||||
HasFloor = 0,
|
||||
HasCeil = 0,
|
||||
|
||||
HasSign = 0
|
||||
};
|
||||
};
|
||||
@@ -119,6 +129,22 @@ template<typename T> struct packet_traits : default_packet_traits
|
||||
|
||||
template<typename T> struct packet_traits<const T> : packet_traits<T> { };
|
||||
|
||||
template<typename T> struct unpacket_traits
|
||||
{
|
||||
typedef T type;
|
||||
typedef T half;
|
||||
enum
|
||||
{
|
||||
size = 1,
|
||||
alignment = 1,
|
||||
vectorizable = false,
|
||||
masked_load_available=false,
|
||||
masked_store_available=false
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T> struct unpacket_traits<const T> : unpacket_traits<T> { };
|
||||
|
||||
template <typename Src, typename Tgt> struct type_casting_traits {
|
||||
enum {
|
||||
VectorizedCast = 0,
|
||||
@@ -127,6 +153,34 @@ template <typename Src, typename Tgt> struct type_casting_traits {
|
||||
};
|
||||
};
|
||||
|
||||
/** \internal Wrapper to ensure that multiple packet types can map to the same
|
||||
same underlying vector type. */
|
||||
template<typename T, int unique_id = 0>
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
/** \internal A convenience utility for determining if the type is a scalar.
|
||||
* This is used to enable some generic packet implementations.
|
||||
*/
|
||||
template<typename Packet>
|
||||
struct is_scalar {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
enum {
|
||||
value = internal::is_same<Packet, Scalar>::value
|
||||
};
|
||||
};
|
||||
|
||||
/** \internal \returns static_cast<TgtType>(a) (coeff-wise) */
|
||||
template <typename SrcPacket, typename TgtPacket>
|
||||
@@ -139,75 +193,406 @@ EIGEN_DEVICE_FUNC inline TgtPacket
|
||||
pcast(const SrcPacket& a, const SrcPacket& /*b*/) {
|
||||
return static_cast<TgtPacket>(a);
|
||||
}
|
||||
|
||||
template <typename SrcPacket, typename TgtPacket>
|
||||
EIGEN_DEVICE_FUNC inline TgtPacket
|
||||
pcast(const SrcPacket& a, const SrcPacket& /*b*/, const SrcPacket& /*c*/, const SrcPacket& /*d*/) {
|
||||
return static_cast<TgtPacket>(a);
|
||||
}
|
||||
template <typename SrcPacket, typename TgtPacket>
|
||||
EIGEN_DEVICE_FUNC inline TgtPacket
|
||||
pcast(const SrcPacket& a, const SrcPacket& /*b*/, const SrcPacket& /*c*/, const SrcPacket& /*d*/,
|
||||
const SrcPacket& /*e*/, const SrcPacket& /*f*/, const SrcPacket& /*g*/, const SrcPacket& /*h*/) {
|
||||
return static_cast<TgtPacket>(a);
|
||||
}
|
||||
|
||||
/** \internal \returns reinterpret_cast<Target>(a) */
|
||||
template <typename Target, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Target
|
||||
preinterpret(const Packet& a); /* { return reinterpret_cast<const Target&>(a); } */
|
||||
|
||||
/** \internal \returns a + b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
padd(const Packet& a,
|
||||
const Packet& b) { return a+b; }
|
||||
padd(const Packet& a, const Packet& b) { return a+b; }
|
||||
// Avoid compiler warning for boolean algebra.
|
||||
template<> EIGEN_DEVICE_FUNC inline bool
|
||||
padd(const bool& a, const bool& b) { return a || b; }
|
||||
|
||||
/** \internal \returns a - b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
psub(const Packet& a,
|
||||
const Packet& b) { return a-b; }
|
||||
psub(const Packet& a, const Packet& b) { return a-b; }
|
||||
|
||||
/** \internal \returns -a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pnegate(const Packet& a) { return -a; }
|
||||
|
||||
/** \internal \returns conj(a) (coeff-wise) */
|
||||
template<> EIGEN_DEVICE_FUNC inline bool
|
||||
pnegate(const bool& a) { return !a; }
|
||||
|
||||
/** \internal \returns conj(a) (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pconj(const Packet& a) { return numext::conj(a); }
|
||||
|
||||
/** \internal \returns a * b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pmul(const Packet& a,
|
||||
const Packet& b) { return a*b; }
|
||||
pmul(const Packet& a, const Packet& b) { return a*b; }
|
||||
// Avoid compiler warning for boolean algebra.
|
||||
template<> EIGEN_DEVICE_FUNC inline bool
|
||||
pmul(const bool& a, const bool& b) { return a && b; }
|
||||
|
||||
/** \internal \returns a / b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pdiv(const Packet& a,
|
||||
const Packet& b) { return a/b; }
|
||||
pdiv(const Packet& a, const Packet& b) { return a/b; }
|
||||
|
||||
/** \internal \returns the min of \a a and \a b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pmin(const Packet& a,
|
||||
const Packet& b) { return numext::mini(a, b); }
|
||||
// In the generic case, memset to all one bits.
|
||||
template<typename Packet, typename EnableIf = void>
|
||||
struct ptrue_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/){
|
||||
Packet b;
|
||||
memset(static_cast<void*>(&b), 0xff, sizeof(Packet));
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns the max of \a a and \a b (coeff-wise) */
|
||||
// For non-trivial scalars, set to Scalar(1) (i.e. a non-zero value).
|
||||
// Although this is technically not a valid bitmask, the scalar path for pselect
|
||||
// uses a comparison to zero, so this should still work in most cases. We don't
|
||||
// have another option, since the scalar type requires initialization.
|
||||
template<typename T>
|
||||
struct ptrue_impl<T,
|
||||
typename internal::enable_if<is_scalar<T>::value && NumTraits<T>::RequireInitialization>::type > {
|
||||
static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/){
|
||||
return T(1);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns one bits. */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pmax(const Packet& a,
|
||||
const Packet& b) { return numext::maxi(a, b); }
|
||||
ptrue(const Packet& a) {
|
||||
return ptrue_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
// In the general case, memset to zero.
|
||||
template<typename Packet, typename EnableIf = void>
|
||||
struct pzero_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) {
|
||||
Packet b;
|
||||
memset(static_cast<void*>(&b), 0x00, sizeof(Packet));
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
// For scalars, explicitly set to Scalar(0), since the underlying representation
|
||||
// for zero may not consist of all-zero bits.
|
||||
template<typename T>
|
||||
struct pzero_impl<T,
|
||||
typename internal::enable_if<is_scalar<T>::value>::type> {
|
||||
static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) {
|
||||
return T(0);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns packet of zeros */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pzero(const Packet& a) {
|
||||
return pzero_impl<Packet>::run(a);
|
||||
}
|
||||
|
||||
/** \internal \returns a <= b as a bit mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pcmp_le(const Packet& a, const Packet& b) { return a<=b ? ptrue(a) : pzero(a); }
|
||||
|
||||
/** \internal \returns a < b as a bit mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pcmp_lt(const Packet& a, const Packet& b) { return a<b ? ptrue(a) : pzero(a); }
|
||||
|
||||
/** \internal \returns a == b as a bit mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pcmp_eq(const Packet& a, const Packet& b) { return a==b ? ptrue(a) : pzero(a); }
|
||||
|
||||
/** \internal \returns a < b or a==NaN or b==NaN as a bit mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pcmp_lt_or_nan(const Packet& a, const Packet& b) { return a>=b ? pzero(a) : ptrue(a); }
|
||||
|
||||
template<typename T>
|
||||
struct bit_and {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
|
||||
return a & b;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct bit_or {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
|
||||
return a | b;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct bit_xor {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
|
||||
return a ^ b;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct bit_not {
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a) const {
|
||||
return ~a;
|
||||
}
|
||||
};
|
||||
|
||||
// Use operators &, |, ^, ~.
|
||||
template<typename T>
|
||||
struct operator_bitwise_helper {
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) { return bit_and<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { return bit_or<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) { return bit_xor<T>()(a, b); }
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { return bit_not<T>()(a); }
|
||||
};
|
||||
|
||||
// Apply binary operations byte-by-byte
|
||||
template<typename T>
|
||||
struct bytewise_bitwise_helper {
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) {
|
||||
return binary(a, b, bit_and<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) {
|
||||
return binary(a, b, bit_or<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) {
|
||||
return binary(a, b, bit_xor<unsigned char>());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) {
|
||||
return unary(a,bit_not<unsigned char>());
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Op>
|
||||
EIGEN_DEVICE_FUNC static inline T unary(const T& a, Op op) {
|
||||
const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
|
||||
T c;
|
||||
unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
*c_ptr++ = op(*a_ptr++);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
EIGEN_DEVICE_FUNC static inline T binary(const T& a, const T& b, Op op) {
|
||||
const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
|
||||
const unsigned char* b_ptr = reinterpret_cast<const unsigned char*>(&b);
|
||||
T c;
|
||||
unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
*c_ptr++ = op(*a_ptr++, *b_ptr++);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
// In the general case, use byte-by-byte manipulation.
|
||||
template<typename T, typename EnableIf = void>
|
||||
struct bitwise_helper : public bytewise_bitwise_helper<T> {};
|
||||
|
||||
// For integers or non-trivial scalars, use binary operators.
|
||||
template<typename T>
|
||||
struct bitwise_helper<T,
|
||||
typename internal::enable_if<
|
||||
is_scalar<T>::value && (NumTraits<T>::IsInteger || NumTraits<T>::RequireInitialization)>::type
|
||||
> : public operator_bitwise_helper<T> {};
|
||||
|
||||
/** \internal \returns the bitwise and of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pand(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper<Packet>::bitwise_and(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise or of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
por(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper<Packet>::bitwise_or(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise xor of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pxor(const Packet& a, const Packet& b) {
|
||||
return bitwise_helper<Packet>::bitwise_xor(a, b);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise not of \a a */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pnot(const Packet& a) {
|
||||
return bitwise_helper<Packet>::bitwise_not(a);
|
||||
}
|
||||
|
||||
/** \internal \returns the bitwise and of \a a and not \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pandnot(const Packet& a, const Packet& b) { return pand(a, pnot(b)); }
|
||||
|
||||
// In the general case, use bitwise select.
|
||||
template<typename Packet, typename EnableIf = void>
|
||||
struct pselect_impl {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return por(pand(a,mask),pandnot(b,mask));
|
||||
}
|
||||
};
|
||||
|
||||
// For scalars, use ternary select.
|
||||
template<typename Packet>
|
||||
struct pselect_impl<Packet,
|
||||
typename internal::enable_if<is_scalar<Packet>::value>::type > {
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return numext::equal_strict(mask, Packet(0)) ? b : a;
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns \a or \b for each field in packet according to \mask */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pselect(const Packet& mask, const Packet& a, const Packet& b) {
|
||||
return pselect_impl<Packet>::run(mask, a, b);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline bool pselect<bool>(
|
||||
const bool& cond, const bool& a, const bool& b) {
|
||||
return cond ? a : b;
|
||||
}
|
||||
|
||||
/** \internal \returns the min or of \a a and \a b (coeff-wise)
|
||||
If either \a a or \a b are NaN, the result is implementation defined. */
|
||||
template<int NaNPropagation>
|
||||
struct pminmax_impl {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
return op(a,b);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns the min or max of \a a and \a b (coeff-wise)
|
||||
If either \a a or \a b are NaN, NaN is returned. */
|
||||
template<>
|
||||
struct pminmax_impl<PropagateNaN> {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
Packet not_nan_mask_a = pcmp_eq(a, a);
|
||||
Packet not_nan_mask_b = pcmp_eq(b, b);
|
||||
return pselect(not_nan_mask_a,
|
||||
pselect(not_nan_mask_b, op(a, b), b),
|
||||
a);
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal \returns the min or max of \a a and \a b (coeff-wise)
|
||||
If both \a a and \a b are NaN, NaN is returned.
|
||||
Equivalent to std::fmin(a, b). */
|
||||
template<>
|
||||
struct pminmax_impl<PropagateNumbers> {
|
||||
template <typename Packet, typename Op>
|
||||
static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
|
||||
Packet not_nan_mask_a = pcmp_eq(a, a);
|
||||
Packet not_nan_mask_b = pcmp_eq(b, b);
|
||||
return pselect(not_nan_mask_a,
|
||||
pselect(not_nan_mask_b, op(a, b), a),
|
||||
b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef SYCL_DEVICE_ONLY
|
||||
#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) Func
|
||||
#else
|
||||
#define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) \
|
||||
[](const Type& a, const Type& b) { \
|
||||
return Func(a, b);}
|
||||
#endif
|
||||
|
||||
/** \internal \returns the min of \a a and \a b (coeff-wise).
|
||||
If \a a or \b b is NaN, the return value is implementation defined. */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pmin(const Packet& a, const Packet& b) { return numext::mini(a,b); }
|
||||
|
||||
/** \internal \returns the min of \a a and \a b (coeff-wise).
|
||||
NaNPropagation determines the NaN propagation semantics. */
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) {
|
||||
return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin<Packet>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the max of \a a and \a b (coeff-wise)
|
||||
If \a a or \b b is NaN, the return value is implementation defined. */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pmax(const Packet& a, const Packet& b) { return numext::maxi(a, b); }
|
||||
|
||||
/** \internal \returns the max of \a a and \a b (coeff-wise).
|
||||
NaNPropagation determines the NaN propagation semantics. */
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) {
|
||||
return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet,(pmax<Packet>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the absolute value of \a a */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pabs(const Packet& a) { using std::abs; return abs(a); }
|
||||
pabs(const Packet& a) { return numext::abs(a); }
|
||||
template<> EIGEN_DEVICE_FUNC inline unsigned int
|
||||
pabs(const unsigned int& a) { return a; }
|
||||
template<> EIGEN_DEVICE_FUNC inline unsigned long
|
||||
pabs(const unsigned long& a) { return a; }
|
||||
template<> EIGEN_DEVICE_FUNC inline unsigned long long
|
||||
pabs(const unsigned long long& a) { return a; }
|
||||
|
||||
/** \internal \returns the addsub value of \a a,b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
paddsub(const Packet& a, const Packet& b) {
|
||||
return pselect(peven_mask(a), padd(a, b), psub(a, b));
|
||||
}
|
||||
|
||||
/** \internal \returns the phase angle of \a a */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
parg(const Packet& a) { using numext::arg; return arg(a); }
|
||||
|
||||
/** \internal \returns the bitwise and of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pand(const Packet& a, const Packet& b) { return a & b; }
|
||||
|
||||
/** \internal \returns the bitwise or of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
por(const Packet& a, const Packet& b) { return a | b; }
|
||||
/** \internal \returns \a a logically shifted by N bits to the right */
|
||||
template<int N> EIGEN_DEVICE_FUNC inline int
|
||||
parithmetic_shift_right(const int& a) { return a >> N; }
|
||||
template<int N> EIGEN_DEVICE_FUNC inline long int
|
||||
parithmetic_shift_right(const long int& a) { return a >> N; }
|
||||
|
||||
/** \internal \returns the bitwise xor of \a a and \a b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pxor(const Packet& a, const Packet& b) { return a ^ b; }
|
||||
/** \internal \returns \a a arithmetically shifted by N bits to the right */
|
||||
template<int N> EIGEN_DEVICE_FUNC inline int
|
||||
plogical_shift_right(const int& a) { return static_cast<int>(static_cast<unsigned int>(a) >> N); }
|
||||
template<int N> EIGEN_DEVICE_FUNC inline long int
|
||||
plogical_shift_right(const long int& a) { return static_cast<long>(static_cast<unsigned long>(a) >> N); }
|
||||
|
||||
/** \internal \returns the bitwise andnot of \a a and \a b */
|
||||
/** \internal \returns \a a shifted by N bits to the left */
|
||||
template<int N> EIGEN_DEVICE_FUNC inline int
|
||||
plogical_shift_left(const int& a) { return a << N; }
|
||||
template<int N> EIGEN_DEVICE_FUNC inline long int
|
||||
plogical_shift_left(const long int& a) { return a << N; }
|
||||
|
||||
/** \internal \returns the significant and exponent of the underlying floating point numbers
|
||||
* See https://en.cppreference.com/w/cpp/numeric/math/frexp
|
||||
*/
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pfrexp(const Packet& a, Packet& exponent) {
|
||||
int exp;
|
||||
EIGEN_USING_STD(frexp);
|
||||
Packet result = static_cast<Packet>(frexp(a, &exp));
|
||||
exponent = static_cast<Packet>(exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \internal \returns a * 2^((int)exponent)
|
||||
* See https://en.cppreference.com/w/cpp/numeric/math/ldexp
|
||||
*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pandnot(const Packet& a, const Packet& b) { return a & (!b); }
|
||||
pldexp(const Packet &a, const Packet &exponent) {
|
||||
EIGEN_USING_STD(ldexp)
|
||||
return static_cast<Packet>(ldexp(a, static_cast<int>(exponent)));
|
||||
}
|
||||
|
||||
/** \internal \returns the min of \a a and \a b (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pabsdiff(const Packet& a, const Packet& b) { return pselect(pcmp_lt(a, b), psub(b, a), psub(a, b)); }
|
||||
|
||||
/** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
@@ -217,10 +602,22 @@ pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||
|
||||
/** \internal \returns a packet version of \a *from, (un-aligned masked load)
|
||||
* There is no generic implementation. We only have implementations for specialized
|
||||
* cases. Generic case should not be called.
|
||||
*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline
|
||||
typename enable_if<unpacket_traits<Packet>::masked_load_available, Packet>::type
|
||||
ploadu(const typename unpacket_traits<Packet>::type* from, typename unpacket_traits<Packet>::mask_t umask);
|
||||
|
||||
/** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
|
||||
|
||||
/** \internal \returns a packet with constant coefficients set from bits */
|
||||
template<typename Packet,typename BitsType> EIGEN_DEVICE_FUNC inline Packet
|
||||
pset1frombits(BitsType 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); }
|
||||
@@ -237,7 +634,7 @@ ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||
* For instance, for a packet of 8 elements, 2 scalars will be read from \a *from and
|
||||
* replicated to form: {from[0],from[0],from[0],from[0],from[1],from[1],from[1],from[1]}
|
||||
* Currently, this function is only used in matrix products.
|
||||
* For packet-size smaller or equal to 4, this function is equivalent to pload1
|
||||
* 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)
|
||||
@@ -281,6 +678,20 @@ inline void pbroadcast2(const typename unpacket_traits<Packet>::type *a,
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet
|
||||
plset(const typename unpacket_traits<Packet>::type& a) { return a; }
|
||||
|
||||
/** \internal \returns a packet with constant coefficients \a a, e.g.: (x, 0, x, 0),
|
||||
where x is the value of all 1-bits. */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
peven_mask(const Packet& /*a*/) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
const size_t n = unpacket_traits<Packet>::size;
|
||||
EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
|
||||
for(size_t i = 0; i < n; ++i) {
|
||||
memset(elements+i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar));
|
||||
}
|
||||
return ploadu<Packet>(elements);
|
||||
}
|
||||
|
||||
|
||||
/** \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)
|
||||
{ (*to) = from; }
|
||||
@@ -289,6 +700,15 @@ template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstore(
|
||||
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstoreu(Scalar* to, const Packet& from)
|
||||
{ (*to) = from; }
|
||||
|
||||
/** \internal copy the packet \a from to \a *to, (un-aligned store with a mask)
|
||||
* There is no generic implementation. We only have implementations for specialized
|
||||
* cases. Generic case should not be called.
|
||||
*/
|
||||
template<typename Scalar, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
typename enable_if<unpacket_traits<Packet>::masked_store_available, void>::type
|
||||
pstoreu(Scalar* to, const Packet& from, typename unpacket_traits<Packet>::mask_t umask);
|
||||
|
||||
template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline Packet pgather(const Scalar* from, Index /*stride*/)
|
||||
{ return ploadu<Packet>(from); }
|
||||
|
||||
@@ -298,8 +718,10 @@ template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstoreu
|
||||
/** \internal tries to do cache prefetching of \a addr */
|
||||
template<typename Scalar> EIGEN_DEVICE_FUNC inline void prefetch(const Scalar* addr)
|
||||
{
|
||||
#ifdef __CUDA_ARCH__
|
||||
#if defined(__LP64__)
|
||||
#if defined(EIGEN_HIP_DEVICE_COMPILE)
|
||||
// do nothing
|
||||
#elif defined(EIGEN_CUDA_ARCH)
|
||||
#if defined(__LP64__) || EIGEN_OS_WIN64
|
||||
// 64-bit pointer operand constraint for inlined asm
|
||||
asm(" prefetch.L1 [ %1 ];" : "=l"(addr) : "l"(addr));
|
||||
#else
|
||||
@@ -311,39 +733,6 @@ template<typename Scalar> EIGEN_DEVICE_FUNC inline void prefetch(const Scalar* a
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \internal \returns the first element of a packet */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type pfirst(const Packet& a)
|
||||
{ return a; }
|
||||
|
||||
/** \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
|
||||
preduxp(const Packet* vecs) { return vecs[0]; }
|
||||
|
||||
/** \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)
|
||||
{ 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
|
||||
predux_downto4(const Packet& a)
|
||||
{ return 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)
|
||||
{ return 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)
|
||||
{ return 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)
|
||||
{ return a; }
|
||||
|
||||
/** \internal \returns the reversed elements of \a a*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& a)
|
||||
{ return a; }
|
||||
@@ -351,10 +740,7 @@ template<typename Packet> EIGEN_DEVICE_FUNC inline Packet preverse(const Packet&
|
||||
/** \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)
|
||||
{
|
||||
// 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));
|
||||
return Packet(numext::imag(a),numext::real(a));
|
||||
}
|
||||
|
||||
/**************************
|
||||
@@ -363,47 +749,51 @@ template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet
|
||||
|
||||
/** \internal \returns the sine of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(sin); return sin(a); }
|
||||
|
||||
/** \internal \returns the cosine of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(cos); return cos(a); }
|
||||
|
||||
/** \internal \returns the tan of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(tan); return tan(a); }
|
||||
|
||||
/** \internal \returns the arc sine of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(asin); return asin(a); }
|
||||
|
||||
/** \internal \returns the arc cosine of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(acos); return acos(a); }
|
||||
|
||||
/** \internal \returns the arc tangent 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); }
|
||||
Packet patan(const Packet& a) { EIGEN_USING_STD(atan); return atan(a); }
|
||||
|
||||
/** \internal \returns the hyperbolic sine of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet psinh(const Packet& a) { using std::sinh; return sinh(a); }
|
||||
Packet psinh(const Packet& a) { EIGEN_USING_STD(sinh); return sinh(a); }
|
||||
|
||||
/** \internal \returns the hyperbolic cosine of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pcosh(const Packet& a) { using std::cosh; return cosh(a); }
|
||||
Packet pcosh(const Packet& a) { EIGEN_USING_STD(cosh); return cosh(a); }
|
||||
|
||||
/** \internal \returns the hyperbolic tan of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet ptanh(const Packet& a) { using std::tanh; return tanh(a); }
|
||||
Packet ptanh(const Packet& a) { EIGEN_USING_STD(tanh); return tanh(a); }
|
||||
|
||||
/** \internal \returns the exp of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(exp); return exp(a); }
|
||||
|
||||
/** \internal \returns the expm1 of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pexpm1(const Packet& a) { return numext::expm1(a); }
|
||||
|
||||
/** \internal \returns the log of \a a (coeff-wise) */
|
||||
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) { EIGEN_USING_STD(log); return log(a); }
|
||||
|
||||
/** \internal \returns the log1p of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
@@ -411,16 +801,24 @@ Packet plog1p(const Packet& a) { return numext::log1p(a); }
|
||||
|
||||
/** \internal \returns the log10 of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet plog10(const Packet& a) { using std::log10; return log10(a); }
|
||||
Packet plog10(const Packet& a) { EIGEN_USING_STD(log10); return log10(a); }
|
||||
|
||||
/** \internal \returns the log10 of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet plog2(const Packet& a) {
|
||||
typedef typename internal::unpacket_traits<Packet>::type Scalar;
|
||||
return pmul(pset1<Packet>(Scalar(EIGEN_LOG2E)), plog(a));
|
||||
}
|
||||
|
||||
/** \internal \returns the square-root of \a a (coeff-wise) */
|
||||
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 numext::sqrt(a); }
|
||||
|
||||
/** \internal \returns the reciprocal square-root of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet prsqrt(const Packet& a) {
|
||||
return pdiv(pset1<Packet>(1), psqrt(a));
|
||||
typedef typename internal::unpacket_traits<Packet>::type Scalar;
|
||||
return pdiv(pset1<Packet>(Scalar(1)), psqrt(a));
|
||||
}
|
||||
|
||||
/** \internal \returns the rounded value of \a a (coeff-wise) */
|
||||
@@ -431,15 +829,121 @@ Packet pround(const Packet& a) { using numext::round; return round(a); }
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pfloor(const Packet& a) { using numext::floor; return floor(a); }
|
||||
|
||||
/** \internal \returns the rounded value of \a a (coeff-wise) with current
|
||||
* rounding mode */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet print(const Packet& a) { using numext::rint; return rint(a); }
|
||||
|
||||
/** \internal \returns the ceil of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pceil(const Packet& a) { using numext::ceil; return ceil(a); }
|
||||
|
||||
/** \internal \returns the first element of a packet */
|
||||
template<typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type
|
||||
pfirst(const Packet& a)
|
||||
{ return a; }
|
||||
|
||||
/** \internal \returns the sum of the elements of upper and lower half of \a a if \a a is larger than 4.
|
||||
* 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
|
||||
predux_half_dowto4(const Packet& a)
|
||||
{ return a; }
|
||||
|
||||
// Slow generic implementation of Packet reduction.
|
||||
template <typename Packet, typename Op>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type
|
||||
predux_helper(const Packet& a, Op op) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
const size_t n = unpacket_traits<Packet>::size;
|
||||
EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
|
||||
pstoreu<Scalar>(elements, a);
|
||||
for(size_t k = n / 2; k > 0; k /= 2) {
|
||||
for(size_t i = 0; i < k; ++i) {
|
||||
elements[i] = op(elements[i], elements[i + k]);
|
||||
}
|
||||
}
|
||||
return elements[0];
|
||||
}
|
||||
|
||||
/** \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)
|
||||
{
|
||||
return 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) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmul<Scalar>)));
|
||||
}
|
||||
|
||||
/** \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) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<PropagateFast, Scalar>)));
|
||||
}
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(
|
||||
const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<NaNPropagation, Scalar>)));
|
||||
}
|
||||
|
||||
/** \internal \returns the min of the elements of \a a */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(
|
||||
const Packet &a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<PropagateFast, Scalar>)));
|
||||
}
|
||||
|
||||
template <int NaNPropagation, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(
|
||||
const Packet& a) {
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<NaNPropagation, Scalar>)));
|
||||
}
|
||||
|
||||
#undef EIGEN_BINARY_OP_NAN_PROPAGATION
|
||||
|
||||
/** \internal \returns true if all coeffs of \a a means "true"
|
||||
* It is supposed to be called on values returned by pcmp_*.
|
||||
*/
|
||||
// not needed yet
|
||||
// template<typename Packet> EIGEN_DEVICE_FUNC inline bool predux_all(const Packet& a)
|
||||
// { return bool(a); }
|
||||
|
||||
/** \internal \returns true if any coeffs of \a a means "true"
|
||||
* It is supposed to be called on values returned by pcmp_*.
|
||||
*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline bool predux_any(const Packet& a)
|
||||
{
|
||||
// Dirty but generic implementation where "true" is assumed to be non 0 and all the sames.
|
||||
// It is expected that "true" is either:
|
||||
// - Scalar(1)
|
||||
// - bits full of ones (NaN for floats),
|
||||
// - or first bit equals to 1 (1 for ints, smallest denormal for floats).
|
||||
// For all these cases, taking the sum is just fine, and this boils down to a no-op for scalars.
|
||||
typedef typename unpacket_traits<Packet>::type Scalar;
|
||||
return numext::not_equal_strict(predux(a), Scalar(0));
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* The following functions might not have to be overwritten for vectorized types
|
||||
***************************************************************************/
|
||||
|
||||
/** \internal copy a packet with constant coeficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned */
|
||||
/** \internal copy a packet with constant coefficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned */
|
||||
// NOTE: this function must really be templated on the packet type (think about different packet types for the same scalar type)
|
||||
template<typename Packet>
|
||||
inline void pstore1(typename unpacket_traits<Packet>::type* to, const typename unpacket_traits<Packet>::type& a)
|
||||
@@ -487,47 +991,18 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_t
|
||||
return ploadt<Packet, LoadMode>(from);
|
||||
}
|
||||
|
||||
/** \internal default implementation of palign() allowing partial specialization */
|
||||
template<int Offset,typename PacketType>
|
||||
struct palign_impl
|
||||
{
|
||||
// by default data are aligned, so there is nothing to be done :)
|
||||
static inline void run(PacketType&, const PacketType&) {}
|
||||
};
|
||||
|
||||
/** \internal update \a first using the concatenation of the packet_size minus \a Offset last elements
|
||||
* of \a first and \a Offset first elements of \a second.
|
||||
*
|
||||
* This function is currently only used to optimize matrix-vector products on unligned matrices.
|
||||
* It takes 2 packets that represent a contiguous memory array, and returns a packet starting
|
||||
* at the position \a Offset. For instance, for packets of 4 elements, we have:
|
||||
* Input:
|
||||
* - first = {f0,f1,f2,f3}
|
||||
* - second = {s0,s1,s2,s3}
|
||||
* Output:
|
||||
* - if Offset==0 then {f0,f1,f2,f3}
|
||||
* - if Offset==1 then {f1,f2,f3,s0}
|
||||
* - if Offset==2 then {f2,f3,s0,s1}
|
||||
* - if Offset==3 then {f3,s0,s1,s3}
|
||||
*/
|
||||
template<int Offset,typename PacketType>
|
||||
inline void palign(PacketType& first, const PacketType& second)
|
||||
{
|
||||
palign_impl<Offset,PacketType>::run(first,second);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Fast complex products (GCC generates a function call which is very slow)
|
||||
***************************************************************************/
|
||||
|
||||
// Eigen+CUDA does not support complexes.
|
||||
#ifndef __CUDACC__
|
||||
#if !defined(EIGEN_GPUCC)
|
||||
|
||||
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>(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); }
|
||||
|
||||
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>(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -558,34 +1033,6 @@ pblend(const Selector<unpacket_traits<Packet>::size>& ifPacket, const Packet& th
|
||||
return ifPacket.select[0] ? thenPacket : elsePacket;
|
||||
}
|
||||
|
||||
/** \internal \returns \a a with the first coefficient replaced by the scalar b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pinsertfirst(const Packet& a, typename unpacket_traits<Packet>::type b)
|
||||
{
|
||||
// Default implementation based on pblend.
|
||||
// It must be specialized for higher performance.
|
||||
Selector<unpacket_traits<Packet>::size> mask;
|
||||
mask.select[0] = true;
|
||||
// This for loop should be optimized away by the compiler.
|
||||
for(Index i=1; i<unpacket_traits<Packet>::size; ++i)
|
||||
mask.select[i] = false;
|
||||
return pblend(mask, pset1<Packet>(b), a);
|
||||
}
|
||||
|
||||
/** \internal \returns \a a with the last coefficient replaced by the scalar b */
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
pinsertlast(const Packet& a, typename unpacket_traits<Packet>::type b)
|
||||
{
|
||||
// Default implementation based on pblend.
|
||||
// It must be specialized for higher performance.
|
||||
Selector<unpacket_traits<Packet>::size> mask;
|
||||
// This for loop should be optimized away by the compiler.
|
||||
for(Index i=0; i<unpacket_traits<Packet>::size-1; ++i)
|
||||
mask.select[i] = false;
|
||||
mask.select[unpacket_traits<Packet>::size-1] = true;
|
||||
return pblend(mask, pset1<Packet>(b), a);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -66,21 +66,31 @@ namespace Eigen
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sinh,scalar_sinh_op,hyperbolic sine,\sa ArrayBase::sinh)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cosh,scalar_cosh_op,hyperbolic cosine,\sa ArrayBase::cosh)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(tanh,scalar_tanh_op,hyperbolic tangent,\sa ArrayBase::tanh)
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(asinh,scalar_asinh_op,inverse hyperbolic sine,\sa ArrayBase::asinh)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(acosh,scalar_acosh_op,inverse hyperbolic cosine,\sa ArrayBase::acosh)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(atanh,scalar_atanh_op,inverse hyperbolic tangent,\sa ArrayBase::atanh)
|
||||
#endif
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(logistic,scalar_logistic_op,logistic function,\sa ArrayBase::logistic)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(lgamma,scalar_lgamma_op,natural logarithm of the gamma function,\sa ArrayBase::lgamma)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(digamma,scalar_digamma_op,derivative of lgamma,\sa ArrayBase::digamma)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erf,scalar_erf_op,error function,\sa ArrayBase::erf)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erfc,scalar_erfc_op,complement error function,\sa ArrayBase::erfc)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(ndtri,scalar_ndtri_op,inverse normal distribution function,\sa ArrayBase::ndtri)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op,exponential,\sa ArrayBase::exp)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(expm1,scalar_expm1_op,exponential of a value minus 1,\sa ArrayBase::expm1)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op,natural logarithm,\sa Eigen::log10 DOXCOMMA ArrayBase::log)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log1p,scalar_log1p_op,natural logarithm of 1 plus the value,\sa ArrayBase::log1p)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10,scalar_log10_op,base 10 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10,scalar_log10_op,base 10 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log10)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log2,scalar_log2_op,base 2 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log2)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs,scalar_abs_op,absolute value,\sa ArrayBase::abs DOXCOMMA MatrixBase::cwiseAbs)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(abs2,scalar_abs2_op,squared absolute value,\sa ArrayBase::abs2 DOXCOMMA MatrixBase::cwiseAbs2)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(arg,scalar_arg_op,complex argument,\sa ArrayBase::arg)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(arg,scalar_arg_op,complex argument,\sa ArrayBase::arg DOXCOMMA MatrixBase::cwiseArg)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sqrt,scalar_sqrt_op,square root,\sa ArrayBase::sqrt DOXCOMMA MatrixBase::cwiseSqrt)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(rsqrt,scalar_rsqrt_op,reciprocal square root,\sa ArrayBase::rsqrt)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(square,scalar_square_op,square (power 2),\sa Eigen::abs2 DOXCOMMA Eigen::pow DOXCOMMA ArrayBase::square)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(cube,scalar_cube_op,cube (power 3),\sa Eigen::pow DOXCOMMA ArrayBase::cube)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(rint,scalar_rint_op,nearest integer,\sa Eigen::floor DOXCOMMA Eigen::ceil DOXCOMMA ArrayBase::round)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(round,scalar_round_op,nearest integer,\sa Eigen::floor DOXCOMMA Eigen::ceil DOXCOMMA ArrayBase::round)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(floor,scalar_floor_op,nearest integer not greater than the giben value,\sa Eigen::ceil DOXCOMMA ArrayBase::floor)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(ceil,scalar_ceil_op,nearest integer not less than the giben value,\sa Eigen::floor DOXCOMMA ArrayBase::ceil)
|
||||
@@ -88,7 +98,7 @@ namespace Eigen
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isinf,scalar_isinf_op,infinite value test,\sa Eigen::isnan DOXCOMMA Eigen::isfinite DOXCOMMA ArrayBase::isinf)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(isfinite,scalar_isfinite_op,finite value test,\sa Eigen::isinf DOXCOMMA Eigen::isnan DOXCOMMA ArrayBase::isfinite)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(sign,scalar_sign_op,sign (or 0),\sa ArrayBase::sign)
|
||||
|
||||
|
||||
/** \returns an expression of the coefficient-wise power of \a x to the given constant \a exponent.
|
||||
*
|
||||
* \tparam ScalarExponent is the scalar type of \a exponent. It must be compatible with the scalar type of the given expression (\c Derived::Scalar).
|
||||
@@ -102,17 +112,18 @@ namespace Eigen
|
||||
inline const CwiseBinaryOp<internal::scalar_pow_op<Derived::Scalar,ScalarExponent>,Derived,Constant<ScalarExponent> >
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const ScalarExponent& exponent);
|
||||
#else
|
||||
template<typename Derived,typename ScalarExponent>
|
||||
inline typename internal::enable_if< !(internal::is_same<typename Derived::Scalar,ScalarExponent>::value) && EIGEN_SCALAR_BINARY_SUPPORTED(pow,typename Derived::Scalar,ScalarExponent),
|
||||
const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived,ScalarExponent,pow) >::type
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const ScalarExponent& exponent) {
|
||||
return x.derived().pow(exponent);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived,typename Derived::Scalar,pow)
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const typename Derived::Scalar& exponent) {
|
||||
return x.derived().pow(exponent);
|
||||
template <typename Derived,typename ScalarExponent>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
EIGEN_MSVC10_WORKAROUND_BINARYOP_RETURN_TYPE(
|
||||
const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived,typename internal::promote_scalar_arg<typename Derived::Scalar
|
||||
EIGEN_COMMA ScalarExponent EIGEN_COMMA
|
||||
EIGEN_SCALAR_BINARY_SUPPORTED(pow,typename Derived::Scalar,ScalarExponent)>::type,pow))
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const ScalarExponent& exponent)
|
||||
{
|
||||
typedef typename internal::promote_scalar_arg<typename Derived::Scalar,ScalarExponent,
|
||||
EIGEN_SCALAR_BINARY_SUPPORTED(pow,typename Derived::Scalar,ScalarExponent)>::type PromotedExponent;
|
||||
return EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived,PromotedExponent,pow)(x.derived(),
|
||||
typename internal::plain_constant_type<Derived,PromotedExponent>::type(x.derived().rows(), x.derived().cols(), internal::scalar_constant_op<PromotedExponent>(exponent)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -122,21 +133,21 @@ namespace Eigen
|
||||
*
|
||||
* Example: \include Cwise_array_power_array.cpp
|
||||
* Output: \verbinclude Cwise_array_power_array.out
|
||||
*
|
||||
*
|
||||
* \sa ArrayBase::pow()
|
||||
*
|
||||
* \relates ArrayBase
|
||||
*/
|
||||
template<typename Derived,typename ExponentDerived>
|
||||
inline const Eigen::CwiseBinaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar, typename ExponentDerived::Scalar>, const Derived, const ExponentDerived>
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const Eigen::ArrayBase<ExponentDerived>& exponents)
|
||||
pow(const Eigen::ArrayBase<Derived>& x, const Eigen::ArrayBase<ExponentDerived>& exponents)
|
||||
{
|
||||
return Eigen::CwiseBinaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar, typename ExponentDerived::Scalar>, const Derived, const ExponentDerived>(
|
||||
x.derived(),
|
||||
exponents.derived()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** \returns an expression of the coefficient-wise power of the scalar \a x to the given array of \a exponents.
|
||||
*
|
||||
* This function computes the coefficient-wise power between a scalar and an array of exponents.
|
||||
@@ -145,7 +156,7 @@ namespace Eigen
|
||||
*
|
||||
* Example: \include Cwise_scalar_power_array.cpp
|
||||
* Output: \verbinclude Cwise_scalar_power_array.out
|
||||
*
|
||||
*
|
||||
* \sa ArrayBase::pow()
|
||||
*
|
||||
* \relates ArrayBase
|
||||
@@ -155,21 +166,17 @@ namespace Eigen
|
||||
inline const CwiseBinaryOp<internal::scalar_pow_op<Scalar,Derived::Scalar>,Constant<Scalar>,Derived>
|
||||
pow(const Scalar& x,const Eigen::ArrayBase<Derived>& x);
|
||||
#else
|
||||
template<typename Scalar, typename Derived>
|
||||
inline typename internal::enable_if< !(internal::is_same<typename Derived::Scalar,Scalar>::value) && EIGEN_SCALAR_BINARY_SUPPORTED(pow,Scalar,typename Derived::Scalar),
|
||||
const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,Derived,pow) >::type
|
||||
pow(const Scalar& x, const Eigen::ArrayBase<Derived>& exponents)
|
||||
{
|
||||
return EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar,Derived,pow)(
|
||||
typename internal::plain_constant_type<Derived,Scalar>::type(exponents.rows(), exponents.cols(), x), exponents.derived() );
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(typename Derived::Scalar,Derived,pow)
|
||||
pow(const typename Derived::Scalar& x, const Eigen::ArrayBase<Derived>& exponents)
|
||||
{
|
||||
return EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(typename Derived::Scalar,Derived,pow)(
|
||||
typename internal::plain_constant_type<Derived,typename Derived::Scalar>::type(exponents.rows(), exponents.cols(), x), exponents.derived() );
|
||||
template <typename Scalar, typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline
|
||||
EIGEN_MSVC10_WORKAROUND_BINARYOP_RETURN_TYPE(
|
||||
const EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(typename internal::promote_scalar_arg<typename Derived::Scalar
|
||||
EIGEN_COMMA Scalar EIGEN_COMMA
|
||||
EIGEN_SCALAR_BINARY_SUPPORTED(pow,Scalar,typename Derived::Scalar)>::type,Derived,pow))
|
||||
pow(const Scalar& x, const Eigen::ArrayBase<Derived>& exponents) {
|
||||
typedef typename internal::promote_scalar_arg<typename Derived::Scalar,Scalar,
|
||||
EIGEN_SCALAR_BINARY_SUPPORTED(pow,Scalar,typename Derived::Scalar)>::type PromotedScalar;
|
||||
return EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(PromotedScalar,Derived,pow)(
|
||||
typename internal::plain_constant_type<Derived,PromotedScalar>::type(exponents.derived().rows(), exponents.derived().cols(), internal::scalar_constant_op<PromotedScalar>(x)), exponents.derived());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+40
-7
@@ -41,6 +41,7 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
|
||||
* - \b rowSuffix string printed at the end of each row
|
||||
* - \b matPrefix string printed at the beginning of the matrix
|
||||
* - \b matSuffix string printed at the end of the matrix
|
||||
* - \b fill character printed to fill the empty space in aligned columns
|
||||
*
|
||||
* Example: \include IOFormat.cpp
|
||||
* Output: \verbinclude IOFormat.out
|
||||
@@ -53,9 +54,9 @@ struct IOFormat
|
||||
IOFormat(int _precision = StreamPrecision, int _flags = 0,
|
||||
const std::string& _coeffSeparator = " ",
|
||||
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="", const char _fill=' ')
|
||||
: matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
|
||||
rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
|
||||
rowSpacer(""), coeffSeparator(_coeffSeparator), fill(_fill), precision(_precision), flags(_flags)
|
||||
{
|
||||
// TODO check if rowPrefix, rowSuffix or rowSeparator contains a newline
|
||||
// don't add rowSpacer if columns are not to be aligned
|
||||
@@ -71,6 +72,7 @@ struct IOFormat
|
||||
std::string matPrefix, matSuffix;
|
||||
std::string rowPrefix, rowSuffix, rowSeparator, rowSpacer;
|
||||
std::string coeffSeparator;
|
||||
char fill;
|
||||
int precision;
|
||||
int flags;
|
||||
};
|
||||
@@ -128,6 +130,9 @@ struct significant_decimals_impl
|
||||
template<typename Derived>
|
||||
std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
|
||||
{
|
||||
using internal::is_same;
|
||||
using internal::conditional;
|
||||
|
||||
if(_m.size() == 0)
|
||||
{
|
||||
s << fmt.matPrefix << fmt.matSuffix;
|
||||
@@ -136,6 +141,22 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
|
||||
|
||||
typename Derived::Nested m = _m;
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename
|
||||
conditional<
|
||||
is_same<Scalar, char>::value ||
|
||||
is_same<Scalar, unsigned char>::value ||
|
||||
is_same<Scalar, numext::int8_t>::value ||
|
||||
is_same<Scalar, numext::uint8_t>::value,
|
||||
int,
|
||||
typename conditional<
|
||||
is_same<Scalar, std::complex<char> >::value ||
|
||||
is_same<Scalar, std::complex<unsigned char> >::value ||
|
||||
is_same<Scalar, std::complex<numext::int8_t> >::value ||
|
||||
is_same<Scalar, std::complex<numext::uint8_t> >::value,
|
||||
std::complex<int>,
|
||||
const Scalar&
|
||||
>::type
|
||||
>::type PrintType;
|
||||
|
||||
Index width = 0;
|
||||
|
||||
@@ -172,23 +193,31 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr.copyfmt(s);
|
||||
sstr << m.coeff(i,j);
|
||||
sstr << static_cast<PrintType>(m.coeff(i,j));
|
||||
width = std::max<Index>(width, Index(sstr.str().length()));
|
||||
}
|
||||
}
|
||||
std::streamsize old_width = s.width();
|
||||
char old_fill_character = s.fill();
|
||||
s << fmt.matPrefix;
|
||||
for(Index i = 0; i < m.rows(); ++i)
|
||||
{
|
||||
if (i)
|
||||
s << fmt.rowSpacer;
|
||||
s << fmt.rowPrefix;
|
||||
if(width) s.width(width);
|
||||
s << m.coeff(i, 0);
|
||||
if(width) {
|
||||
s.fill(fmt.fill);
|
||||
s.width(width);
|
||||
}
|
||||
s << static_cast<PrintType>(m.coeff(i, 0));
|
||||
for(Index j = 1; j < m.cols(); ++j)
|
||||
{
|
||||
s << fmt.coeffSeparator;
|
||||
if (width) s.width(width);
|
||||
s << m.coeff(i, j);
|
||||
if(width) {
|
||||
s.fill(fmt.fill);
|
||||
s.width(width);
|
||||
}
|
||||
s << static_cast<PrintType>(m.coeff(i, j));
|
||||
}
|
||||
s << fmt.rowSuffix;
|
||||
if( i < m.rows() - 1)
|
||||
@@ -196,6 +225,10 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
|
||||
}
|
||||
s << fmt.matSuffix;
|
||||
if(explicit_precision) s.precision(old_precision);
|
||||
if(width) {
|
||||
s.fill(old_fill_character);
|
||||
s.width(old_width);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2017 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_INDEXED_VIEW_H
|
||||
#define EIGEN_INDEXED_VIEW_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename XprType, typename RowIndices, typename ColIndices>
|
||||
struct traits<IndexedView<XprType, RowIndices, ColIndices> >
|
||||
: traits<XprType>
|
||||
{
|
||||
enum {
|
||||
RowsAtCompileTime = int(array_size<RowIndices>::value),
|
||||
ColsAtCompileTime = int(array_size<ColIndices>::value),
|
||||
MaxRowsAtCompileTime = RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) : Dynamic,
|
||||
MaxColsAtCompileTime = ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) : Dynamic,
|
||||
|
||||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
|
||||
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
: XprTypeIsRowMajor,
|
||||
|
||||
RowIncr = int(get_compile_time_incr<RowIndices>::value),
|
||||
ColIncr = int(get_compile_time_incr<ColIndices>::value),
|
||||
InnerIncr = IsRowMajor ? ColIncr : RowIncr,
|
||||
OuterIncr = IsRowMajor ? RowIncr : ColIncr,
|
||||
|
||||
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
|
||||
XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType>::ret) : int(outer_stride_at_compile_time<XprType>::ret),
|
||||
XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType>::ret) : int(inner_stride_at_compile_time<XprType>::ret),
|
||||
|
||||
InnerSize = XprTypeIsRowMajor ? ColsAtCompileTime : RowsAtCompileTime,
|
||||
IsBlockAlike = InnerIncr==1 && OuterIncr==1,
|
||||
IsInnerPannel = HasSameStorageOrderAsXprType && is_same<AllRange<InnerSize>,typename conditional<XprTypeIsRowMajor,ColIndices,RowIndices>::type>::value,
|
||||
|
||||
InnerStrideAtCompileTime = InnerIncr<0 || InnerIncr==DynamicIndex || XprInnerStride==Dynamic ? Dynamic : XprInnerStride * InnerIncr,
|
||||
OuterStrideAtCompileTime = OuterIncr<0 || OuterIncr==DynamicIndex || XprOuterstride==Dynamic ? Dynamic : XprOuterstride * OuterIncr,
|
||||
|
||||
ReturnAsScalar = is_same<RowIndices,SingleRange>::value && is_same<ColIndices,SingleRange>::value,
|
||||
ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike,
|
||||
ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock),
|
||||
|
||||
// FIXME we deal with compile-time strides if and only if we have DirectAccessBit flag,
|
||||
// but this is too strict regarding negative strides...
|
||||
DirectAccessMask = (int(InnerIncr)!=UndefinedIncr && int(OuterIncr)!=UndefinedIncr && InnerIncr>=0 && OuterIncr>=0) ? DirectAccessBit : 0,
|
||||
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
|
||||
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
|
||||
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
|
||||
Flags = (traits<XprType>::Flags & (HereditaryBits | DirectAccessMask )) | FlagsLvalueBit | FlagsRowMajorBit | FlagsLinearAccessBit
|
||||
};
|
||||
|
||||
typedef Block<XprType,RowsAtCompileTime,ColsAtCompileTime,IsInnerPannel> BlockType;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename XprType, typename RowIndices, typename ColIndices, typename StorageKind>
|
||||
class IndexedViewImpl;
|
||||
|
||||
|
||||
/** \class IndexedView
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* \brief Expression of a non-sequential sub-matrix defined by arbitrary sequences of row and column indices
|
||||
*
|
||||
* \tparam XprType the type of the expression in which we are taking the intersections of sub-rows and sub-columns
|
||||
* \tparam RowIndices the type of the object defining the sequence of row indices
|
||||
* \tparam ColIndices the type of the object defining the sequence of column indices
|
||||
*
|
||||
* This class represents an expression of a sub-matrix (or sub-vector) defined as the intersection
|
||||
* of sub-sets of rows and columns, that are themself defined by generic sequences of row indices \f$ \{r_0,r_1,..r_{m-1}\} \f$
|
||||
* and column indices \f$ \{c_0,c_1,..c_{n-1} \}\f$. Let \f$ A \f$ be the nested matrix, then the resulting matrix \f$ B \f$ has \c m
|
||||
* rows and \c n columns, and its entries are given by: \f$ B(i,j) = A(r_i,c_j) \f$.
|
||||
*
|
||||
* The \c RowIndices and \c ColIndices types must be compatible with the following API:
|
||||
* \code
|
||||
* <integral type> operator[](Index) const;
|
||||
* Index size() const;
|
||||
* \endcode
|
||||
*
|
||||
* Typical supported types thus include:
|
||||
* - std::vector<int>
|
||||
* - std::valarray<int>
|
||||
* - std::array<int>
|
||||
* - Plain C arrays: int[N]
|
||||
* - Eigen::ArrayXi
|
||||
* - decltype(ArrayXi::LinSpaced(...))
|
||||
* - Any view/expressions of the previous types
|
||||
* - Eigen::ArithmeticSequence
|
||||
* - Eigen::internal::AllRange (helper for Eigen::all)
|
||||
* - Eigen::internal::SingleRange (helper for single index)
|
||||
* - etc.
|
||||
*
|
||||
* In typical usages of %Eigen, this class should never be used directly. It is the return type of
|
||||
* DenseBase::operator()(const RowIndices&, const ColIndices&).
|
||||
*
|
||||
* \sa class Block
|
||||
*/
|
||||
template<typename XprType, typename RowIndices, typename ColIndices>
|
||||
class IndexedView : public IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind>
|
||||
{
|
||||
public:
|
||||
typedef typename IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind>::Base Base;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(IndexedView)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedView)
|
||||
|
||||
typedef typename internal::ref_selector<XprType>::non_const_type MatrixTypeNested;
|
||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||
|
||||
template<typename T0, typename T1>
|
||||
IndexedView(XprType& xpr, const T0& rowIndices, const T1& colIndices)
|
||||
: m_xpr(xpr), m_rowIndices(rowIndices), m_colIndices(colIndices)
|
||||
{}
|
||||
|
||||
/** \returns number of rows */
|
||||
Index rows() const { return internal::size(m_rowIndices); }
|
||||
|
||||
/** \returns number of columns */
|
||||
Index cols() const { return internal::size(m_colIndices); }
|
||||
|
||||
/** \returns the nested expression */
|
||||
const typename internal::remove_all<XprType>::type&
|
||||
nestedExpression() const { return m_xpr; }
|
||||
|
||||
/** \returns the nested expression */
|
||||
typename internal::remove_reference<XprType>::type&
|
||||
nestedExpression() { return m_xpr; }
|
||||
|
||||
/** \returns a const reference to the object storing/generating the row indices */
|
||||
const RowIndices& rowIndices() const { return m_rowIndices; }
|
||||
|
||||
/** \returns a const reference to the object storing/generating the column indices */
|
||||
const ColIndices& colIndices() const { return m_colIndices; }
|
||||
|
||||
protected:
|
||||
MatrixTypeNested m_xpr;
|
||||
RowIndices m_rowIndices;
|
||||
ColIndices m_colIndices;
|
||||
};
|
||||
|
||||
|
||||
// Generic API dispatcher
|
||||
template<typename XprType, typename RowIndices, typename ColIndices, typename StorageKind>
|
||||
class IndexedViewImpl
|
||||
: public internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices> >::type
|
||||
{
|
||||
public:
|
||||
typedef typename internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices> >::type Base;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
template<typename ArgType, typename RowIndices, typename ColIndices>
|
||||
struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
: evaluator_base<IndexedView<ArgType, RowIndices, ColIndices> >
|
||||
{
|
||||
typedef IndexedView<ArgType, RowIndices, ColIndices> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of row/col index */,
|
||||
|
||||
FlagsLinearAccessBit = (traits<XprType>::RowsAtCompileTime == 1 || traits<XprType>::ColsAtCompileTime == 1) ? LinearAccessBit : 0,
|
||||
|
||||
FlagsRowMajorBit = traits<XprType>::FlagsRowMajorBit,
|
||||
|
||||
Flags = (evaluator<ArgType>::Flags & (HereditaryBits & ~RowMajorBit /*| LinearAccessBit | DirectAccessBit*/)) | FlagsLinearAccessBit | FlagsRowMajorBit,
|
||||
|
||||
Alignment = 0
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_xpr(xpr)
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index index)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_LVALUE(XprType)
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
return m_argImpl.coeffRef( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Scalar& coeffRef(Index index) const
|
||||
{
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
return m_argImpl.coeffRef( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
Index row = XprType::RowsAtCompileTime == 1 ? 0 : index;
|
||||
Index col = XprType::RowsAtCompileTime == 1 ? index : 0;
|
||||
return m_argImpl.coeff( m_xpr.rowIndices()[row], m_xpr.colIndices()[col]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
evaluator<ArgType> m_argImpl;
|
||||
const XprType& m_xpr;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_INDEXED_VIEW_H
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2014-2019 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
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_INVERSE_H
|
||||
#define EIGEN_INVERSE_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
template<typename XprType,typename StorageKind> class InverseImpl;
|
||||
|
||||
@@ -44,19 +44,18 @@ class Inverse : public InverseImpl<XprType,typename internal::traits<XprType>::S
|
||||
{
|
||||
public:
|
||||
typedef typename XprType::StorageIndex StorageIndex;
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
typedef typename internal::ref_selector<XprType>::type XprTypeNested;
|
||||
typedef typename internal::remove_all<XprTypeNested>::type XprTypeNestedCleaned;
|
||||
typedef typename internal::ref_selector<Inverse>::type Nested;
|
||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||
|
||||
|
||||
explicit EIGEN_DEVICE_FUNC Inverse(const XprType &xpr)
|
||||
: m_xpr(xpr)
|
||||
{}
|
||||
|
||||
EIGEN_DEVICE_FUNC Index rows() const { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC Index cols() const { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC const XprTypeNestedCleaned& nestedExpression() const { return m_xpr; }
|
||||
|
||||
@@ -82,7 +81,7 @@ namespace internal {
|
||||
|
||||
/** \internal
|
||||
* \brief Default evaluator for Inverse expression.
|
||||
*
|
||||
*
|
||||
* This default evaluator for Inverse expression simply evaluate the inverse into a temporary
|
||||
* by a call to internal::call_assignment_no_alias.
|
||||
* Therefore, inverse implementers only have to specialize Assignment<Dst,Inverse<...>, ...> for
|
||||
@@ -97,7 +96,7 @@ struct unary_evaluator<Inverse<ArgType> >
|
||||
typedef Inverse<ArgType> InverseType;
|
||||
typedef typename InverseType::PlainObject PlainObject;
|
||||
typedef evaluator<PlainObject> Base;
|
||||
|
||||
|
||||
enum { Flags = Base::Flags | EvalBeforeNestingBit };
|
||||
|
||||
unary_evaluator(const InverseType& inv_xpr)
|
||||
@@ -106,11 +105,11 @@ struct unary_evaluator<Inverse<ArgType> >
|
||||
::new (static_cast<Base*>(this)) Base(m_result);
|
||||
internal::call_assignment_no_alias(m_result, inv_xpr);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
PlainObject m_result;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef EIGEN_MAP_H
|
||||
#define EIGEN_MAP_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename PlainObjectType, int MapOptions, typename StrideType>
|
||||
@@ -20,11 +20,17 @@ struct traits<Map<PlainObjectType, MapOptions, StrideType> >
|
||||
{
|
||||
typedef traits<PlainObjectType> TraitsBase;
|
||||
enum {
|
||||
PlainObjectTypeInnerSize = ((traits<PlainObjectType>::Flags&RowMajorBit)==RowMajorBit)
|
||||
? PlainObjectType::ColsAtCompileTime
|
||||
: PlainObjectType::RowsAtCompileTime,
|
||||
|
||||
InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0
|
||||
? int(PlainObjectType::InnerStrideAtCompileTime)
|
||||
: int(StrideType::InnerStrideAtCompileTime),
|
||||
OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0
|
||||
? int(PlainObjectType::OuterStrideAtCompileTime)
|
||||
? (InnerStrideAtCompileTime==Dynamic || PlainObjectTypeInnerSize==Dynamic
|
||||
? Dynamic
|
||||
: int(InnerStrideAtCompileTime) * int(PlainObjectTypeInnerSize))
|
||||
: int(StrideType::OuterStrideAtCompileTime),
|
||||
Alignment = int(MapOptions)&int(AlignedMask),
|
||||
Flags0 = TraitsBase::Flags & (~NestByRefBit),
|
||||
@@ -41,7 +47,7 @@ private:
|
||||
* \brief A matrix or vector expression mapping an existing array of data.
|
||||
*
|
||||
* \tparam PlainObjectType the equivalent matrix type of the mapped data
|
||||
* \tparam MapOptions specifies the pointer alignment in bytes. It can be: \c #Aligned128, , \c #Aligned64, \c #Aligned32, \c #Aligned16, \c #Aligned8 or \c #Unaligned.
|
||||
* \tparam MapOptions specifies the pointer alignment in bytes. It can be: \c #Aligned128, \c #Aligned64, \c #Aligned32, \c #Aligned16, \c #Aligned8 or \c #Unaligned.
|
||||
* The default is \c #Unaligned.
|
||||
* \tparam StrideType optionally specifies strides. By default, Map assumes the memory layout
|
||||
* of an ordinary, contiguous array. This can be overridden by specifying strides.
|
||||
@@ -98,19 +104,20 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const
|
||||
{
|
||||
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const
|
||||
{
|
||||
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
|
||||
: IsVectorAtCompileTime ? this->size()
|
||||
: int(Flags)&RowMajorBit ? this->cols()
|
||||
: this->rows();
|
||||
: internal::traits<Map>::OuterStrideAtCompileTime != Dynamic ? Index(internal::traits<Map>::OuterStrideAtCompileTime)
|
||||
: IsVectorAtCompileTime ? (this->size() * innerStride())
|
||||
: int(Flags)&RowMajorBit ? (this->cols() * innerStride())
|
||||
: (this->rows() * innerStride());
|
||||
}
|
||||
|
||||
/** Constructor in the fixed-size case.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
EIGEN_STATIC_ASSERT((int(internal::evaluator<Derived>::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \
|
||||
YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT)
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
/** \ingroup Core_Module
|
||||
*
|
||||
@@ -43,6 +43,7 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
||||
enum {
|
||||
RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
|
||||
ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
|
||||
InnerStrideAtCompileTime = internal::traits<Derived>::InnerStrideAtCompileTime,
|
||||
SizeAtCompileTime = Base::SizeAtCompileTime
|
||||
};
|
||||
|
||||
@@ -86,9 +87,11 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
||||
typedef typename Base::CoeffReturnType CoeffReturnType;
|
||||
|
||||
/** \copydoc DenseBase::rows() */
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_rows.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return m_rows.value(); }
|
||||
/** \copydoc DenseBase::cols() */
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_cols.value(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return m_cols.value(); }
|
||||
|
||||
/** Returns a pointer to the first coefficient of the matrix or vector.
|
||||
*
|
||||
@@ -181,14 +184,19 @@ template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
|
||||
#endif
|
||||
|
||||
protected:
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase)
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase)
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void checkSanity(typename internal::enable_if<(internal::traits<T>::Alignment>0),void*>::type = 0) const
|
||||
{
|
||||
#if EIGEN_MAX_ALIGN_BYTES>0
|
||||
// innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible value:
|
||||
const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime);
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride);
|
||||
eigen_assert(( ((internal::UIntPtr(m_data) % internal::traits<Derived>::Alignment) == 0)
|
||||
|| (cols() * rows() * innerStride() * sizeof(Scalar)) < internal::traits<Derived>::Alignment ) && "data is not aligned");
|
||||
|| (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits<Derived>::Alignment ) && "data is not aligned");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -290,6 +298,9 @@ template<typename Derived> class MapBase<Derived, WriteAccessors>
|
||||
// In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
|
||||
// see bugs 821 and 920.
|
||||
using ReadOnlyMapBase::Base::operator=;
|
||||
protected:
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase)
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase)
|
||||
};
|
||||
|
||||
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
|
||||
|
||||
+792
-166
File diff suppressed because it is too large.
Load diff
@@ -17,24 +17,28 @@ namespace internal {
|
||||
|
||||
/** \internal \returns the hyperbolic tan of \a a (coeff-wise)
|
||||
Doesn't do anything fancy, just a 13/6-degree rational interpolant which
|
||||
is accurate up to a couple of ulp in the range [-9, 9], outside of which
|
||||
the tanh(x) = +/-1.
|
||||
is accurate up to a couple of ulps in the (approximate) range [-8, 8],
|
||||
outside of which tanh(x) = +/-1 in single precision. The input is clamped
|
||||
to the range [-c, c]. The value c is chosen as the smallest value where
|
||||
the approximation evaluates to exactly 1. In the reange [-0.0004, 0.0004]
|
||||
the approxmation tanh(x) ~= x is used for better accuracy as x tends to zero.
|
||||
|
||||
This implementation works on both scalars and packets.
|
||||
*/
|
||||
template<typename T>
|
||||
T generic_fast_tanh_float(const T& a_x)
|
||||
{
|
||||
// Clamp the inputs to the range [-9, 9] since anything outside
|
||||
// this range is +/-1.0f in single-precision.
|
||||
const T plus_9 = pset1<T>(9.f);
|
||||
const T minus_9 = pset1<T>(-9.f);
|
||||
// NOTE GCC prior to 6.3 might improperly optimize this max/min
|
||||
// step such that if a_x is nan, x will be either 9 or -9,
|
||||
// and tanh will return 1 or -1 instead of nan.
|
||||
// This is supposed to be fixed in gcc6.3,
|
||||
// see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72867
|
||||
const T x = pmax(minus_9,pmin(plus_9,a_x));
|
||||
// Clamp the inputs to the range [-c, c]
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
const T plus_clamp = pset1<T>(7.99881172180175781f);
|
||||
const T minus_clamp = pset1<T>(-7.99881172180175781f);
|
||||
#else
|
||||
const T plus_clamp = pset1<T>(7.90531110763549805f);
|
||||
const T minus_clamp = pset1<T>(-7.90531110763549805f);
|
||||
#endif
|
||||
const T tiny = pset1<T>(0.0004f);
|
||||
const T x = pmax(pmin(a_x, plus_clamp), minus_clamp);
|
||||
const T tiny_mask = pcmp_lt(pabs(a_x), tiny);
|
||||
// The monomial coefficients of the numerator polynomial (odd).
|
||||
const T alpha_1 = pset1<T>(4.89352455891786e-03f);
|
||||
const T alpha_3 = pset1<T>(6.37261928875436e-04f);
|
||||
@@ -62,13 +66,131 @@ T generic_fast_tanh_float(const T& a_x)
|
||||
p = pmadd(x2, p, alpha_1);
|
||||
p = pmul(x, p);
|
||||
|
||||
// Evaluate the denominator polynomial p.
|
||||
// Evaluate the denominator polynomial q.
|
||||
T q = pmadd(x2, beta_6, beta_4);
|
||||
q = pmadd(x2, q, beta_2);
|
||||
q = pmadd(x2, q, beta_0);
|
||||
|
||||
// Divide the numerator by the denominator.
|
||||
return pdiv(p, q);
|
||||
return pselect(tiny_mask, x, pdiv(p, q));
|
||||
}
|
||||
|
||||
template<typename RealScalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
RealScalar positive_real_hypot(const RealScalar& x, const RealScalar& y)
|
||||
{
|
||||
// IEEE IEC 6059 special cases.
|
||||
if ((numext::isinf)(x) || (numext::isinf)(y))
|
||||
return NumTraits<RealScalar>::infinity();
|
||||
if ((numext::isnan)(x) || (numext::isnan)(y))
|
||||
return NumTraits<RealScalar>::quiet_NaN();
|
||||
|
||||
EIGEN_USING_STD(sqrt);
|
||||
RealScalar p, qp;
|
||||
p = numext::maxi(x,y);
|
||||
if(p==RealScalar(0)) return RealScalar(0);
|
||||
qp = numext::mini(y,x) / p;
|
||||
return p * sqrt(RealScalar(1) + qp*qp);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
struct hypot_impl
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
static EIGEN_DEVICE_FUNC
|
||||
inline RealScalar run(const Scalar& x, const Scalar& y)
|
||||
{
|
||||
EIGEN_USING_STD(abs);
|
||||
return positive_real_hypot<RealScalar>(abs(x), abs(y));
|
||||
}
|
||||
};
|
||||
|
||||
// Generic complex sqrt implementation that correctly handles corner cases
|
||||
// according to https://en.cppreference.com/w/cpp/numeric/complex/sqrt
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_sqrt(const std::complex<T>& z) {
|
||||
// Computes the principal sqrt of the input.
|
||||
//
|
||||
// For a complex square root of the number x + i*y. We want to find real
|
||||
// numbers u and v such that
|
||||
// (u + i*v)^2 = x + i*y <=>
|
||||
// u^2 - v^2 + i*2*u*v = x + i*v.
|
||||
// By equating the real and imaginary parts we get:
|
||||
// u^2 - v^2 = x
|
||||
// 2*u*v = y.
|
||||
//
|
||||
// For x >= 0, this has the numerically stable solution
|
||||
// u = sqrt(0.5 * (x + sqrt(x^2 + y^2)))
|
||||
// v = y / (2 * u)
|
||||
// and for x < 0,
|
||||
// v = sign(y) * sqrt(0.5 * (-x + sqrt(x^2 + y^2)))
|
||||
// u = y / (2 * v)
|
||||
//
|
||||
// Letting w = sqrt(0.5 * (|x| + |z|)),
|
||||
// if x == 0: u = w, v = sign(y) * w
|
||||
// if x > 0: u = w, v = y / (2 * w)
|
||||
// if x < 0: u = |y| / (2 * w), v = sign(y) * w
|
||||
|
||||
const T x = numext::real(z);
|
||||
const T y = numext::imag(z);
|
||||
const T zero = T(0);
|
||||
const T w = numext::sqrt(T(0.5) * (numext::abs(x) + numext::hypot(x, y)));
|
||||
|
||||
return
|
||||
(numext::isinf)(y) ? std::complex<T>(NumTraits<T>::infinity(), y)
|
||||
: x == zero ? std::complex<T>(w, y < zero ? -w : w)
|
||||
: x > zero ? std::complex<T>(w, y / (2 * w))
|
||||
: std::complex<T>(numext::abs(y) / (2 * w), y < zero ? -w : w );
|
||||
}
|
||||
|
||||
// Generic complex rsqrt implementation.
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& z) {
|
||||
// Computes the principal reciprocal sqrt of the input.
|
||||
//
|
||||
// For a complex reciprocal square root of the number z = x + i*y. We want to
|
||||
// find real numbers u and v such that
|
||||
// (u + i*v)^2 = 1 / (x + i*y) <=>
|
||||
// u^2 - v^2 + i*2*u*v = x/|z|^2 - i*v/|z|^2.
|
||||
// By equating the real and imaginary parts we get:
|
||||
// u^2 - v^2 = x/|z|^2
|
||||
// 2*u*v = y/|z|^2.
|
||||
//
|
||||
// For x >= 0, this has the numerically stable solution
|
||||
// u = sqrt(0.5 * (x + |z|)) / |z|
|
||||
// v = -y / (2 * u * |z|)
|
||||
// and for x < 0,
|
||||
// v = -sign(y) * sqrt(0.5 * (-x + |z|)) / |z|
|
||||
// u = -y / (2 * v * |z|)
|
||||
//
|
||||
// Letting w = sqrt(0.5 * (|x| + |z|)),
|
||||
// if x == 0: u = w / |z|, v = -sign(y) * w / |z|
|
||||
// if x > 0: u = w / |z|, v = -y / (2 * w * |z|)
|
||||
// if x < 0: u = |y| / (2 * w * |z|), v = -sign(y) * w / |z|
|
||||
|
||||
const T x = numext::real(z);
|
||||
const T y = numext::imag(z);
|
||||
const T zero = T(0);
|
||||
|
||||
const T abs_z = numext::hypot(x, y);
|
||||
const T w = numext::sqrt(T(0.5) * (numext::abs(x) + abs_z));
|
||||
const T woz = w / abs_z;
|
||||
// Corner cases consistent with 1/sqrt(z) on gcc/clang.
|
||||
return
|
||||
abs_z == zero ? std::complex<T>(NumTraits<T>::infinity(), NumTraits<T>::quiet_NaN())
|
||||
: ((numext::isinf)(x) || (numext::isinf)(y)) ? std::complex<T>(zero, zero)
|
||||
: x == zero ? std::complex<T>(woz, y < zero ? woz : -woz)
|
||||
: x > zero ? std::complex<T>(woz, -y / (2 * w * abs_z))
|
||||
: std::complex<T>(numext::abs(y) / (2 * w * abs_z), y < zero ? woz : -woz );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC std::complex<T> complex_log(const std::complex<T>& z) {
|
||||
// Computes complex log.
|
||||
T a = numext::abs(z);
|
||||
EIGEN_USING_STD(atan2);
|
||||
T b = atan2(z.imag(), z.real());
|
||||
return std::complex<T>(numext::log(a), b);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
+132
-28
@@ -29,7 +29,7 @@ private:
|
||||
required_alignment = unpacket_traits<PacketScalar>::alignment,
|
||||
packet_access_bit = (packet_traits<_Scalar>::Vectorizable && (EIGEN_UNALIGNED_VECTORIZE || (actual_alignment>=required_alignment))) ? PacketAccessBit : 0
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
typedef Dense StorageKind;
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
Options = _Options,
|
||||
InnerStrideAtCompileTime = 1,
|
||||
OuterStrideAtCompileTime = (Options&RowMajor) ? ColsAtCompileTime : RowsAtCompileTime,
|
||||
|
||||
|
||||
// FIXME, the following flag in only used to define NeedsToAlign in PlainObjectBase
|
||||
EvaluatorFlags = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit,
|
||||
Alignment = actual_alignment
|
||||
@@ -255,55 +255,93 @@ class Matrix
|
||||
*
|
||||
* \sa resize(Index,Index)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Matrix() : Base()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Matrix() : Base()
|
||||
{
|
||||
Base::_check_template_params();
|
||||
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
|
||||
// FIXME is it still needed
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
explicit Matrix(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 }
|
||||
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Matrix(Matrix&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_constructible<Scalar>::value)
|
||||
: Base(std::move(other))
|
||||
{
|
||||
Base::_check_template_params();
|
||||
if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic)
|
||||
Base::_set_noalias(other);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Matrix& operator=(Matrix&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value)
|
||||
{
|
||||
other.swap(*this);
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \copydoc PlainObjectBase(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&... args)
|
||||
*
|
||||
* Example: \include Matrix_variadic_ctor_cxx11.cpp
|
||||
* Output: \verbinclude Matrix_variadic_ctor_cxx11.out
|
||||
*
|
||||
* \sa Matrix(const std::initializer_list<std::initializer_list<Scalar>>&)
|
||||
*/
|
||||
template <typename... ArgTypes>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Matrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
: Base(a0, a1, a2, a3, args...) {}
|
||||
|
||||
/** \brief Constructs a Matrix and initializes it from the coefficients given as initializer-lists grouped by row. \cpp11
|
||||
*
|
||||
* In the general case, the constructor takes a list of rows, each row being represented as a list of coefficients:
|
||||
*
|
||||
* Example: \include Matrix_initializer_list_23_cxx11.cpp
|
||||
* Output: \verbinclude Matrix_initializer_list_23_cxx11.out
|
||||
*
|
||||
* Each of the inner initializer lists must contain the exact same number of elements, otherwise an assertion is triggered.
|
||||
*
|
||||
* In the case of a compile-time column vector, implicit transposition from a single row is allowed.
|
||||
* Therefore <code>VectorXd{{1,2,3,4,5}}</code> is legal and the more verbose syntax
|
||||
* <code>RowVectorXd{{1},{2},{3},{4},{5}}</code> can be avoided:
|
||||
*
|
||||
* Example: \include Matrix_initializer_list_vector_cxx11.cpp
|
||||
* Output: \verbinclude Matrix_initializer_list_vector_cxx11.out
|
||||
*
|
||||
* In the case of fixed-sized matrices, the initializer list sizes must exactly match the matrix sizes,
|
||||
* and implicit transposition is allowed for compile-time vectors only.
|
||||
*
|
||||
* \sa Matrix(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit EIGEN_STRONG_INLINE Matrix(const std::initializer_list<std::initializer_list<Scalar>>& list) : Base(list) {}
|
||||
#endif // end EIGEN_HAS_CXX11
|
||||
|
||||
#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)
|
||||
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>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Matrix(const T0& x, const T1& y)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Matrix(const T0& x, const T1& y)
|
||||
{
|
||||
Base::_check_template_params();
|
||||
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);
|
||||
@@ -313,7 +351,7 @@ class Matrix
|
||||
* 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 therefore recommended to use the default
|
||||
@@ -321,14 +359,15 @@ class Matrix
|
||||
* \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 */
|
||||
/** \brief Constructs an initialized 1x1 matrix with the given coefficient
|
||||
* \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) */
|
||||
Matrix(const Scalar& x);
|
||||
/** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns.
|
||||
*
|
||||
* 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
|
||||
* 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 therefore recommended to use the default
|
||||
@@ -337,12 +376,15 @@ class Matrix
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
Matrix(Index rows, Index cols);
|
||||
|
||||
/** \brief Constructs an initialized 2D vector with given coefficients */
|
||||
Matrix(const Scalar& x, const Scalar& y);
|
||||
#endif
|
||||
|
||||
/** \brief Constructs an initialized 3D vector with given coefficients */
|
||||
/** \brief Constructs an initialized 2D vector with given coefficients
|
||||
* \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...) */
|
||||
Matrix(const Scalar& x, const Scalar& y);
|
||||
#endif // end EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
/** \brief Constructs an initialized 3D vector with given coefficients
|
||||
* \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
|
||||
{
|
||||
@@ -352,7 +394,9 @@ class Matrix
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
}
|
||||
/** \brief Constructs an initialized 4D vector with given coefficients */
|
||||
/** \brief Constructs an initialized 4D vector with given coefficients
|
||||
* \sa Matrix(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&...)
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
|
||||
{
|
||||
@@ -379,8 +423,10 @@ class Matrix
|
||||
: Base(other.derived())
|
||||
{ }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const { return 1; }
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const { return this->innerSize(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const EIGEN_NOEXCEPT { return 1; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const EIGEN_NOEXCEPT { return this->innerSize(); }
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
@@ -407,7 +453,7 @@ class Matrix
|
||||
*
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* Eigen defines several typedef shortcuts for most common matrix and vector types.
|
||||
* %Eigen defines several typedef shortcuts for most common matrix and vector types.
|
||||
*
|
||||
* The general patterns are the following:
|
||||
*
|
||||
@@ -420,6 +466,15 @@ class Matrix
|
||||
* There are also \c VectorSizeType and \c RowVectorSizeType which are self-explanatory. For example, \c Vector4cf is
|
||||
* a fixed-size vector of 4 complex floats.
|
||||
*
|
||||
* With \cpp11, template alias are also defined for common sizes.
|
||||
* They follow the same pattern as above except that the scalar type suffix is replaced by a
|
||||
* template parameter, i.e.:
|
||||
* - `MatrixSize<Type>` where `Size` can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size.
|
||||
* - `MatrixXSize<Type>` and `MatrixSizeX<Type>` where `Size` can be \c 2,\c 3,\c 4 for hybrid dynamic/fixed matrices.
|
||||
* - `VectorSize<Type>` and `RowVectorSize<Type>` for column and row vectors.
|
||||
*
|
||||
* With \cpp11, you can also use fully generic column and row vector types: `Vector<Type,Size>` and `RowVector<Type,Size>`.
|
||||
*
|
||||
* \sa class Matrix
|
||||
*/
|
||||
|
||||
@@ -456,6 +511,55 @@ EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
|
||||
#undef EIGEN_MAKE_TYPEDEFS
|
||||
#undef EIGEN_MAKE_FIXED_TYPEDEFS
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
|
||||
#define EIGEN_MAKE_TYPEDEFS(Size, SizeSuffix) \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Matrix##SizeSuffix = Matrix<Type, Size, Size>; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Vector##SizeSuffix = Matrix<Type, Size, 1>; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using RowVector##SizeSuffix = Matrix<Type, 1, Size>;
|
||||
|
||||
#define EIGEN_MAKE_FIXED_TYPEDEFS(Size) \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Matrix##Size##X = Matrix<Type, Size, Dynamic>; \
|
||||
/** \ingroup matrixtypedefs */ \
|
||||
/** \brief \cpp11 */ \
|
||||
template <typename Type> \
|
||||
using Matrix##X##Size = Matrix<Type, Dynamic, Size>;
|
||||
|
||||
EIGEN_MAKE_TYPEDEFS(2, 2)
|
||||
EIGEN_MAKE_TYPEDEFS(3, 3)
|
||||
EIGEN_MAKE_TYPEDEFS(4, 4)
|
||||
EIGEN_MAKE_TYPEDEFS(Dynamic, X)
|
||||
EIGEN_MAKE_FIXED_TYPEDEFS(2)
|
||||
EIGEN_MAKE_FIXED_TYPEDEFS(3)
|
||||
EIGEN_MAKE_FIXED_TYPEDEFS(4)
|
||||
|
||||
/** \ingroup matrixtypedefs
|
||||
* \brief \cpp11 */
|
||||
template <typename Type, int Size>
|
||||
using Vector = Matrix<Type, Size, 1>;
|
||||
|
||||
/** \ingroup matrixtypedefs
|
||||
* \brief \cpp11 */
|
||||
template <typename Type, int Size>
|
||||
using RowVector = Matrix<Type, 1, Size>;
|
||||
|
||||
#undef EIGEN_MAKE_TYPEDEFS
|
||||
#undef EIGEN_MAKE_FIXED_TYPEDEFS
|
||||
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_MATRIX_H
|
||||
@@ -76,6 +76,7 @@ template<typename Derived> class MatrixBase
|
||||
using Base::coeffRef;
|
||||
using Base::lazyAssign;
|
||||
using Base::eval;
|
||||
using Base::operator-;
|
||||
using Base::operator+=;
|
||||
using Base::operator-=;
|
||||
using Base::operator*=;
|
||||
@@ -122,7 +123,6 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase
|
||||
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
|
||||
# include "../plugins/CommonCwiseUnaryOps.h"
|
||||
# include "../plugins/CommonCwiseBinaryOps.h"
|
||||
# include "../plugins/MatrixCwiseUnaryOps.h"
|
||||
# include "../plugins/MatrixCwiseBinaryOps.h"
|
||||
@@ -160,20 +160,11 @@ template<typename Derived> class MatrixBase
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Derived& operator-=(const MatrixBase<OtherDerived>& other);
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
const Product<Derived,OtherDerived,LazyProduct>
|
||||
operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{ return this->lazyProduct(other); }
|
||||
#else
|
||||
|
||||
template<typename OtherDerived>
|
||||
const Product<Derived,OtherDerived>
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
#endif
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
const Product<Derived,OtherDerived,LazyProduct>
|
||||
@@ -277,6 +268,8 @@ template<typename Derived> class MatrixBase
|
||||
Derived& setIdentity();
|
||||
EIGEN_DEVICE_FUNC
|
||||
Derived& setIdentity(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC Derived& setUnit(Index i);
|
||||
EIGEN_DEVICE_FUNC Derived& setUnit(Index newSize, Index i);
|
||||
|
||||
bool isIdentity(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
bool isDiagonal(const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;
|
||||
@@ -305,7 +298,7 @@ template<typename Derived> class MatrixBase
|
||||
EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase<OtherDerived>& other) const
|
||||
{ return cwiseNotEqual(other).any(); }
|
||||
|
||||
NoAlias<Derived,Eigen::MatrixBase > noalias();
|
||||
NoAlias<Derived,Eigen::MatrixBase > EIGEN_DEVICE_FUNC noalias();
|
||||
|
||||
// TODO forceAlignedAccess is temporarily disabled
|
||||
// Need to find a nicer workaround.
|
||||
@@ -335,6 +328,7 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
inline const PartialPivLU<PlainObject> lu() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Inverse<Derived> inverse() const;
|
||||
|
||||
template<typename ResultType>
|
||||
@@ -344,12 +338,15 @@ template<typename Derived> class MatrixBase
|
||||
bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision()
|
||||
) const;
|
||||
|
||||
template<typename ResultType>
|
||||
inline void computeInverseWithCheck(
|
||||
ResultType& inverse,
|
||||
bool& invertible,
|
||||
const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision()
|
||||
) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
Scalar determinant() const;
|
||||
|
||||
/////////// Cholesky module ///////////
|
||||
@@ -421,15 +418,19 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
////////// Householder module ///////////
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
void makeHouseholderInPlace(Scalar& tau, RealScalar& beta);
|
||||
template<typename EssentialPart>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void makeHouseholder(EssentialPart& essential,
|
||||
Scalar& tau, RealScalar& beta) const;
|
||||
template<typename EssentialPart>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void applyHouseholderOnTheLeft(const EssentialPart& essential,
|
||||
const Scalar& tau,
|
||||
Scalar* workspace);
|
||||
template<typename EssentialPart>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void applyHouseholderOnTheRight(const EssentialPart& essential,
|
||||
const Scalar& tau,
|
||||
Scalar* workspace);
|
||||
@@ -437,8 +438,10 @@ template<typename Derived> class MatrixBase
|
||||
///////// Jacobi module /////////
|
||||
|
||||
template<typename OtherScalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void applyOnTheLeft(Index p, Index q, const JacobiRotation<OtherScalar>& j);
|
||||
template<typename OtherScalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j);
|
||||
|
||||
///////// SparseCore module /////////
|
||||
@@ -453,19 +456,33 @@ template<typename Derived> class MatrixBase
|
||||
///////// MatrixFunctions module /////////
|
||||
|
||||
typedef typename internal::stem_function<Scalar>::type StemFunction;
|
||||
const MatrixExponentialReturnValue<Derived> exp() const;
|
||||
#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description) \
|
||||
/** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a href="unsupported/group__MatrixFunctions__Module.html"> unsupported MatrixFunctions module</a>. To compute the coefficient-wise Description use ArrayBase::##Name . */ \
|
||||
const ReturnType<Derived> Name() const;
|
||||
#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument) \
|
||||
/** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a href="unsupported/group__MatrixFunctions__Module.html"> unsupported MatrixFunctions module</a>. To compute the coefficient-wise Description use ArrayBase::##Name . */ \
|
||||
const ReturnType<Derived> Name(Argument) const;
|
||||
|
||||
EIGEN_MATRIX_FUNCTION(MatrixExponentialReturnValue, exp, exponential)
|
||||
/** \brief Helper function for the <a href="unsupported/group__MatrixFunctions__Module.html"> unsupported MatrixFunctions module</a>.*/
|
||||
const MatrixFunctionReturnValue<Derived> matrixFunction(StemFunction f) const;
|
||||
const MatrixFunctionReturnValue<Derived> cosh() const;
|
||||
const MatrixFunctionReturnValue<Derived> sinh() const;
|
||||
const MatrixFunctionReturnValue<Derived> cos() const;
|
||||
const MatrixFunctionReturnValue<Derived> sin() const;
|
||||
const MatrixSquareRootReturnValue<Derived> sqrt() const;
|
||||
const MatrixLogarithmReturnValue<Derived> log() const;
|
||||
const MatrixPowerReturnValue<Derived> pow(const RealScalar& p) const;
|
||||
const MatrixComplexPowerReturnValue<Derived> pow(const std::complex<RealScalar>& p) const;
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cosh, hyperbolic cosine)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sinh, hyperbolic sine)
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, atanh, inverse hyperbolic cosine)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, acosh, inverse hyperbolic cosine)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, asinh, inverse hyperbolic sine)
|
||||
#endif
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cos, cosine)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sin, sine)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixSquareRootReturnValue, sqrt, square root)
|
||||
EIGEN_MATRIX_FUNCTION(MatrixLogarithmReturnValue, log, logarithm)
|
||||
EIGEN_MATRIX_FUNCTION_1(MatrixPowerReturnValue, pow, power to \c p, const RealScalar& p)
|
||||
EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const std::complex<RealScalar>& p)
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC MatrixBase() : Base() {}
|
||||
EIGEN_DEFAULT_COPY_CONSTRUCTOR(MatrixBase)
|
||||
EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MatrixBase)
|
||||
|
||||
private:
|
||||
EIGEN_DEVICE_FUNC explicit MatrixBase(int);
|
||||
|
||||
@@ -16,7 +16,11 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
template<typename ExpressionType>
|
||||
struct traits<NestByValue<ExpressionType> > : public traits<ExpressionType>
|
||||
{};
|
||||
{
|
||||
enum {
|
||||
Flags = traits<ExpressionType>::Flags & ~NestByRefBit
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/** \class NestByValue
|
||||
@@ -41,57 +45,13 @@ template<typename ExpressionType> class NestByValue
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit inline NestByValue(const ExpressionType& matrix) : m_expression(matrix) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_expression.cols(); }
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const { return m_expression.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const { return m_expression.innerStride(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_expression.coeff(row, col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_expression.const_cast_derived().coeffRef(row, col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline const CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_expression.coeff(index);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_expression.const_cast_derived().coeffRef(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index row, Index col) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(row, col);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index row, Index col, const PacketScalar& x)
|
||||
{
|
||||
m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_expression.template packet<LoadMode>(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index index, const PacketScalar& x)
|
||||
{
|
||||
m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index rows() const EIGEN_NOEXCEPT { return m_expression.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index cols() const EIGEN_NOEXCEPT { return m_expression.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC operator const ExpressionType&() const { return m_expression; }
|
||||
|
||||
EIGEN_DEVICE_FUNC const ExpressionType& nestedExpression() const { return m_expression; }
|
||||
|
||||
protected:
|
||||
const ExpressionType m_expression;
|
||||
};
|
||||
@@ -99,12 +59,27 @@ template<typename ExpressionType> class NestByValue
|
||||
/** \returns an expression of the temporary version of *this.
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const NestByValue<Derived>
|
||||
EIGEN_DEVICE_FUNC inline const NestByValue<Derived>
|
||||
DenseBase<Derived>::nestByValue() const
|
||||
{
|
||||
return NestByValue<Derived>(derived());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Evaluator of Solve -> eval into a temporary
|
||||
template<typename ArgType>
|
||||
struct evaluator<NestByValue<ArgType> >
|
||||
: public evaluator<ArgType>
|
||||
{
|
||||
typedef evaluator<ArgType> Base;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const NestByValue<ArgType>& xpr)
|
||||
: Base(xpr.nestedExpression())
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_NESTBYVALUE_H
|
||||
@@ -33,6 +33,7 @@ class NoAlias
|
||||
public:
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit NoAlias(ExpressionType& expression) : m_expression(expression) {}
|
||||
|
||||
template<typename OtherDerived>
|
||||
@@ -74,10 +75,10 @@ class NoAlias
|
||||
*
|
||||
* More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag.
|
||||
* Currently, even though several expressions may alias, only product
|
||||
* expressions have this flag. Therefore, noalias() is only usefull when
|
||||
* expressions have this flag. Therefore, noalias() is only useful when
|
||||
* the source expression contains a matrix product.
|
||||
*
|
||||
* Here are some examples where noalias is usefull:
|
||||
* Here are some examples where noalias is useful:
|
||||
* \code
|
||||
* D.noalias() = A * B;
|
||||
* D.noalias() += A.transpose() * B;
|
||||
@@ -98,7 +99,7 @@ class NoAlias
|
||||
* \sa class NoAlias
|
||||
*/
|
||||
template<typename Derived>
|
||||
NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias()
|
||||
NoAlias<Derived,MatrixBase> EIGEN_DEVICE_FUNC MatrixBase<Derived>::noalias()
|
||||
{
|
||||
return NoAlias<Derived, Eigen::MatrixBase >(derived());
|
||||
}
|
||||
|
||||
+107
-20
@@ -21,12 +21,14 @@ template< typename T,
|
||||
bool is_integer = NumTraits<T>::IsInteger>
|
||||
struct default_digits10_impl
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() { return std::numeric_limits<T>::digits10; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_digits10_impl<T,false,false> // Floating point
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() {
|
||||
using std::log10;
|
||||
using std::ceil;
|
||||
@@ -38,11 +40,64 @@ struct default_digits10_impl<T,false,false> // Floating point
|
||||
template<typename T>
|
||||
struct default_digits10_impl<T,false,true> // Integer
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() { return 0; }
|
||||
};
|
||||
|
||||
|
||||
// default implementation of digits(), based on numeric_limits if specialized,
|
||||
// 0 for integer types, and log2(epsilon()) otherwise.
|
||||
template< typename T,
|
||||
bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
|
||||
bool is_integer = NumTraits<T>::IsInteger>
|
||||
struct default_digits_impl
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() { return std::numeric_limits<T>::digits; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_digits_impl<T,false,false> // Floating point
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() {
|
||||
using std::log;
|
||||
using std::ceil;
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
return int(ceil(-log(NumTraits<Real>::epsilon())/log(static_cast<Real>(2))));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_digits_impl<T,false,true> // Integer
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static int run() { return 0; }
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
namespace numext {
|
||||
/** \internal bit-wise cast without changing the underlying bit representation. */
|
||||
|
||||
// TODO: Replace by std::bit_cast (available in C++20)
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
#if EIGEN_HAS_TYPE_TRAITS
|
||||
// The behaviour of memcpy is not specified for non-trivially copyable types
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Src>::value, THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Tgt>::value && std::is_default_constructible<Tgt>::value,
|
||||
THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
#endif
|
||||
|
||||
EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED);
|
||||
Tgt tgt;
|
||||
EIGEN_USING_STD(memcpy)
|
||||
memcpy(&tgt, &src, sizeof(Tgt));
|
||||
return tgt;
|
||||
}
|
||||
} // namespace numext
|
||||
|
||||
/** \class NumTraits
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
@@ -71,7 +126,7 @@ struct default_digits10_impl<T,false,true> // Integer
|
||||
* and to \c 0 otherwise.
|
||||
* \li Enum values ReadCost, AddCost and MulCost representing a rough estimate of the number of CPU cycles needed
|
||||
* to by move / add / mul instructions respectively, assuming the data is already stored in CPU registers.
|
||||
* Stay vague here. No need to do architecture-specific stuff.
|
||||
* Stay vague here. No need to do architecture-specific stuff. If you don't know what this means, just use \c Eigen::HugeCost.
|
||||
* \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned.
|
||||
* \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must
|
||||
* be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise.
|
||||
@@ -80,9 +135,18 @@ struct default_digits10_impl<T,false,true> // Integer
|
||||
* \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default
|
||||
* value by the fuzzy comparison operators.
|
||||
* \li highest() and lowest() functions returning the highest and lowest possible values respectively.
|
||||
* \li digits() function returning the number of radix digits (non-sign digits for integers, mantissa for floating-point). This is
|
||||
* the analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits">std::numeric_limits<T>::digits</a>
|
||||
* which is used as the default implementation if specialized.
|
||||
* \li digits10() function returning the number of decimal digits that can be represented without change. This is
|
||||
* the analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits10">std::numeric_limits<T>::digits10</a>
|
||||
* which is used as the default implementation if specialized.
|
||||
* \li min_exponent() and max_exponent() functions returning the highest and lowest possible values, respectively,
|
||||
* such that the radix raised to the power exponent-1 is a normalized floating-point number. These are equivalent to
|
||||
* <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/min_exponent">std::numeric_limits<T>::min_exponent</a>/
|
||||
* <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_exponent">std::numeric_limits<T>::max_exponent</a>.
|
||||
* \li infinity() function returning a representation of positive infinity, if available.
|
||||
* \li quiet_NaN function returning a non-signaling "not-a-number", if available.
|
||||
*/
|
||||
|
||||
template<typename T> struct GenericNumTraits
|
||||
@@ -106,42 +170,60 @@ template<typename T> struct GenericNumTraits
|
||||
typedef T Nested;
|
||||
typedef T Literal;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline Real epsilon()
|
||||
{
|
||||
return numext::numeric_limits<T>::epsilon();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline int digits10()
|
||||
{
|
||||
return internal::default_digits10_impl<T>::run();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline int digits()
|
||||
{
|
||||
return internal::default_digits_impl<T>::run();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline int min_exponent()
|
||||
{
|
||||
return numext::numeric_limits<T>::min_exponent;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline int max_exponent()
|
||||
{
|
||||
return numext::numeric_limits<T>::max_exponent;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline Real dummy_precision()
|
||||
{
|
||||
// make sure to override this for floating-point types
|
||||
return Real(0);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline T highest() {
|
||||
return (numext::numeric_limits<T>::max)();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline T lowest() {
|
||||
return IsInteger ? (numext::numeric_limits<T>::min)() : (-(numext::numeric_limits<T>::max)());
|
||||
return IsInteger ? (numext::numeric_limits<T>::min)()
|
||||
: static_cast<T>(-(numext::numeric_limits<T>::max)());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline T infinity() {
|
||||
return numext::numeric_limits<T>::infinity();
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline T quiet_NaN() {
|
||||
return numext::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
@@ -153,19 +235,20 @@ template<typename T> struct NumTraits : GenericNumTraits<T>
|
||||
template<> struct NumTraits<float>
|
||||
: GenericNumTraits<float>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline float dummy_precision() { return 1e-5f; }
|
||||
};
|
||||
|
||||
template<> struct NumTraits<double> : GenericNumTraits<double>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline double dummy_precision() { return 1e-12; }
|
||||
};
|
||||
|
||||
template<> struct NumTraits<long double>
|
||||
: GenericNumTraits<long double>
|
||||
{
|
||||
EIGEN_CONSTEXPR
|
||||
static inline long double dummy_precision() { return 1e-15l; }
|
||||
};
|
||||
|
||||
@@ -182,11 +265,11 @@ template<typename _Real> struct NumTraits<std::complex<_Real> >
|
||||
MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline Real epsilon() { return NumTraits<Real>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline Real dummy_precision() { return NumTraits<Real>::dummy_precision(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline int digits10() { return NumTraits<Real>::digits10(); }
|
||||
};
|
||||
|
||||
@@ -206,16 +289,17 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
||||
IsInteger = NumTraits<Scalar>::IsInteger,
|
||||
IsSigned = NumTraits<Scalar>::IsSigned,
|
||||
RequireInitialization = 1,
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::ReadCost,
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::ReadCost),
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::AddCost),
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::MulCost)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
static inline RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
|
||||
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int digits10() { return NumTraits<Scalar>::digits10(); }
|
||||
};
|
||||
|
||||
@@ -229,6 +313,7 @@ template<> struct NumTraits<std::string>
|
||||
MulCost = HugeCost
|
||||
};
|
||||
|
||||
EIGEN_CONSTEXPR
|
||||
static inline int digits10() { return 0; }
|
||||
|
||||
private:
|
||||
@@ -243,6 +328,8 @@ private:
|
||||
// Empty specialization for void to allow template specialization based on NumTraits<T>::Real with T==void and SFINAE.
|
||||
template<> struct NumTraits<void> {};
|
||||
|
||||
template<> struct NumTraits<bool> : GenericNumTraits<bool> {};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_NUMTRAITS_H
|
||||
@@ -0,0 +1,232 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011-2018 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_PARTIALREDUX_H
|
||||
#define EIGEN_PARTIALREDUX_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* This file provides evaluators for partial reductions.
|
||||
* There are two modes:
|
||||
*
|
||||
* - scalar path: simply calls the respective function on the column or row.
|
||||
* -> nothing special here, all the tricky part is handled by the return
|
||||
* types of VectorwiseOp's members. They embed the functor calling the
|
||||
* respective DenseBase's member function.
|
||||
*
|
||||
* - vectorized path: implements a packet-wise reductions followed by
|
||||
* some (optional) processing of the outcome, e.g., division by n for mean.
|
||||
*
|
||||
* For the vectorized path let's observe that the packet-size and outer-unrolling
|
||||
* are both decided by the assignement logic. So all we have to do is to decide
|
||||
* on the inner unrolling.
|
||||
*
|
||||
* For the unrolling, we can reuse "internal::redux_vec_unroller" from Redux.h,
|
||||
* but be need to be careful to specify correct increment.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/* logic deciding a strategy for unrolling of vectorized paths */
|
||||
template<typename Func, typename Evaluator>
|
||||
struct packetwise_redux_traits
|
||||
{
|
||||
enum {
|
||||
OuterSize = int(Evaluator::IsRowMajor) ? Evaluator::RowsAtCompileTime : Evaluator::ColsAtCompileTime,
|
||||
Cost = OuterSize == Dynamic ? HugeCost
|
||||
: OuterSize * Evaluator::CoeffReadCost + (OuterSize-1) * functor_traits<Func>::Cost,
|
||||
Unrolling = Cost <= EIGEN_UNROLLING_LIMIT ? CompleteUnrolling : NoUnrolling
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* Value to be returned when size==0 , by default let's return 0 */
|
||||
template<typename PacketType,typename Func>
|
||||
EIGEN_DEVICE_FUNC
|
||||
PacketType packetwise_redux_empty_value(const Func& ) { return pset1<PacketType>(0); }
|
||||
|
||||
/* For products the default is 1 */
|
||||
template<typename PacketType,typename Scalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
PacketType packetwise_redux_empty_value(const scalar_product_op<Scalar,Scalar>& ) { return pset1<PacketType>(1); }
|
||||
|
||||
/* Perform the actual reduction */
|
||||
template<typename Func, typename Evaluator,
|
||||
int Unrolling = packetwise_redux_traits<Func, Evaluator>::Unrolling
|
||||
>
|
||||
struct packetwise_redux_impl;
|
||||
|
||||
/* Perform the actual reduction with unrolling */
|
||||
template<typename Func, typename Evaluator>
|
||||
struct packetwise_redux_impl<Func, Evaluator, CompleteUnrolling>
|
||||
{
|
||||
typedef redux_novec_unroller<Func,Evaluator, 0, Evaluator::SizeAtCompileTime> Base;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE
|
||||
PacketType run(const Evaluator &eval, const Func& func, Index /*size*/)
|
||||
{
|
||||
return redux_vec_unroller<Func, Evaluator, 0, packetwise_redux_traits<Func, Evaluator>::OuterSize>::template run<PacketType>(eval,func);
|
||||
}
|
||||
};
|
||||
|
||||
/* Add a specialization of redux_vec_unroller for size==0 at compiletime.
|
||||
* This specialization is not required for general reductions, which is
|
||||
* why it is defined here.
|
||||
*/
|
||||
template<typename Func, typename Evaluator, int Start>
|
||||
struct redux_vec_unroller<Func, Evaluator, Start, 0>
|
||||
{
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE PacketType run(const Evaluator &, const Func& f)
|
||||
{
|
||||
return packetwise_redux_empty_value<PacketType>(f);
|
||||
}
|
||||
};
|
||||
|
||||
/* Perform the actual reduction for dynamic sizes */
|
||||
template<typename Func, typename Evaluator>
|
||||
struct packetwise_redux_impl<Func, Evaluator, NoUnrolling>
|
||||
{
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Evaluator>::PacketType PacketScalar;
|
||||
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static PacketType run(const Evaluator &eval, const Func& func, Index size)
|
||||
{
|
||||
if(size==0)
|
||||
return packetwise_redux_empty_value<PacketType>(func);
|
||||
|
||||
const Index size4 = (size-1)&(~3);
|
||||
PacketType p = eval.template packetByOuterInner<Unaligned,PacketType>(0,0);
|
||||
Index i = 1;
|
||||
// This loop is optimized for instruction pipelining:
|
||||
// - each iteration generates two independent instructions
|
||||
// - thanks to branch prediction and out-of-order execution we have independent instructions across loops
|
||||
for(; i<size4; i+=4)
|
||||
p = func.packetOp(p,
|
||||
func.packetOp(
|
||||
func.packetOp(eval.template packetByOuterInner<Unaligned,PacketType>(i+0,0),eval.template packetByOuterInner<Unaligned,PacketType>(i+1,0)),
|
||||
func.packetOp(eval.template packetByOuterInner<Unaligned,PacketType>(i+2,0),eval.template packetByOuterInner<Unaligned,PacketType>(i+3,0))));
|
||||
for(; i<size; ++i)
|
||||
p = func.packetOp(p, eval.template packetByOuterInner<Unaligned,PacketType>(i,0));
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename ArgType, typename MemberOp, int Direction>
|
||||
struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
: evaluator_base<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
{
|
||||
typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType;
|
||||
typedef typename internal::nested_eval<ArgType,1>::type ArgTypeNested;
|
||||
typedef typename internal::add_const_on_value_type<ArgTypeNested>::type ConstArgTypeNested;
|
||||
typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
|
||||
typedef typename ArgType::Scalar InputScalar;
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
enum {
|
||||
TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(ArgType::ColsAtCompileTime)
|
||||
};
|
||||
typedef typename MemberOp::template Cost<int(TraversalSize)> CostOpType;
|
||||
enum {
|
||||
CoeffReadCost = TraversalSize==Dynamic ? HugeCost
|
||||
: TraversalSize==0 ? 1
|
||||
: int(TraversalSize) * int(evaluator<ArgType>::CoeffReadCost) + int(CostOpType::value),
|
||||
|
||||
_ArgFlags = evaluator<ArgType>::Flags,
|
||||
|
||||
_Vectorizable = bool(int(_ArgFlags)&PacketAccessBit)
|
||||
&& bool(MemberOp::Vectorizable)
|
||||
&& (Direction==int(Vertical) ? bool(_ArgFlags&RowMajorBit) : (_ArgFlags&RowMajorBit)==0)
|
||||
&& (TraversalSize!=0),
|
||||
|
||||
Flags = (traits<XprType>::Flags&RowMajorBit)
|
||||
| (evaluator<ArgType>::Flags&(HereditaryBits&(~RowMajorBit)))
|
||||
| (_Vectorizable ? PacketAccessBit : 0)
|
||||
| LinearAccessBit,
|
||||
|
||||
Alignment = 0 // FIXME this will need to be improved once PartialReduxExpr is vectorized
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr)
|
||||
: m_arg(xpr.nestedExpression()), m_functor(xpr.functor())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize==Dynamic ? HugeCost : (TraversalSize==0 ? 1 : int(CostOpType::value)));
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Scalar coeff(Index i, Index j) const
|
||||
{
|
||||
return coeff(Direction==Vertical ? j : i);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const Scalar coeff(Index index) const
|
||||
{
|
||||
return m_functor(m_arg.template subVector<DirectionType(Direction)>(index));
|
||||
}
|
||||
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index i, Index j) const
|
||||
{
|
||||
return packet<LoadMode,PacketType>(Direction==Vertical ? j : i);
|
||||
}
|
||||
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
|
||||
PacketType packet(Index idx) const
|
||||
{
|
||||
enum { PacketSize = internal::unpacket_traits<PacketType>::size };
|
||||
typedef Block<const ArgTypeNestedCleaned,
|
||||
Direction==Vertical ? int(ArgType::RowsAtCompileTime) : int(PacketSize),
|
||||
Direction==Vertical ? int(PacketSize) : int(ArgType::ColsAtCompileTime),
|
||||
true /* InnerPanel */> PanelType;
|
||||
|
||||
PanelType panel(m_arg,
|
||||
Direction==Vertical ? 0 : idx,
|
||||
Direction==Vertical ? idx : 0,
|
||||
Direction==Vertical ? m_arg.rows() : Index(PacketSize),
|
||||
Direction==Vertical ? Index(PacketSize) : m_arg.cols());
|
||||
|
||||
// FIXME
|
||||
// See bug 1612, currently if PacketSize==1 (i.e. complex<double> with 128bits registers) then the storage-order of panel get reversed
|
||||
// and methods like packetByOuterInner do not make sense anymore in this context.
|
||||
// So let's just by pass "vectorization" in this case:
|
||||
if(PacketSize==1)
|
||||
return internal::pset1<PacketType>(coeff(idx));
|
||||
|
||||
typedef typename internal::redux_evaluator<PanelType> PanelEvaluator;
|
||||
PanelEvaluator panel_eval(panel);
|
||||
typedef typename MemberOp::BinaryOp BinaryOp;
|
||||
PacketType p = internal::packetwise_redux_impl<BinaryOp,PanelEvaluator>::template run<PacketType>(panel_eval,m_functor.binaryFunc(),m_arg.outerSize());
|
||||
return p;
|
||||
}
|
||||
|
||||
protected:
|
||||
ConstArgTypeNested m_arg;
|
||||
const MemberOp m_functor;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_PARTIALREDUX_H
|
||||
@@ -87,25 +87,14 @@ class PermutationBase : public EigenBase<Derived>
|
||||
return derived();
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This is a special case of the templated operator=. Its purpose is to
|
||||
* prevent a default operator= from hiding the templated operator=.
|
||||
*/
|
||||
Derived& operator=(const PermutationBase& other)
|
||||
{
|
||||
indices() = other.indices();
|
||||
return derived();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \returns the number of rows */
|
||||
inline Index rows() const { return Index(indices().size()); }
|
||||
inline EIGEN_DEVICE_FUNC Index rows() const { return Index(indices().size()); }
|
||||
|
||||
/** \returns the number of columns */
|
||||
inline Index cols() const { return Index(indices().size()); }
|
||||
inline EIGEN_DEVICE_FUNC Index cols() const { return Index(indices().size()); }
|
||||
|
||||
/** \returns the size of a side of the respective square matrix, i.e., the number of indices */
|
||||
inline Index size() const { return Index(indices().size()); }
|
||||
inline EIGEN_DEVICE_FUNC Index size() const { return Index(indices().size()); }
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename DenseDerived>
|
||||
@@ -333,12 +322,6 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
|
||||
inline PermutationMatrix(const PermutationBase<OtherDerived>& other)
|
||||
: m_indices(other.indices()) {}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** Standard copy constructor. Defined only to prevent a default copy constructor
|
||||
* from hiding the other templated constructor */
|
||||
inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {}
|
||||
#endif
|
||||
|
||||
/** Generic constructor from expression of the indices. The indices
|
||||
* array has the meaning that the permutations sends each integer i to indices[i].
|
||||
*
|
||||
@@ -373,17 +356,6 @@ class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompile
|
||||
return Base::operator=(tr.derived());
|
||||
}
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This is a special case of the templated operator=. Its purpose is to
|
||||
* prevent a default operator= from hiding the templated operator=.
|
||||
*/
|
||||
PermutationMatrix& operator=(const PermutationMatrix& other)
|
||||
{
|
||||
m_indices = other.m_indices;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** const version of indices(). */
|
||||
const IndicesType& indices() const { return m_indices; }
|
||||
/** \returns a reference to the stored array representing the permutation. */
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
#if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO)
|
||||
# define EIGEN_INITIALIZE_COEFFS
|
||||
# define EIGEN_INITIALIZE_COEFFS_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(Index 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();
|
||||
# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(Index i=0;i<base().size();++i) coeffRef(i)=std::numeric_limits<Scalar>::quiet_NaN();
|
||||
#else
|
||||
# undef EIGEN_INITIALIZE_COEFFS
|
||||
# define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
@@ -104,7 +104,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
|
||||
typedef typename internal::traits<Derived>::StorageKind StorageKind;
|
||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||
|
||||
|
||||
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Derived DenseType;
|
||||
@@ -118,16 +118,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
using Base::IsVectorAtCompileTime;
|
||||
using Base::Flags;
|
||||
|
||||
template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
|
||||
friend class Eigen::Map<Derived, Unaligned>;
|
||||
typedef Eigen::Map<Derived, Unaligned> MapType;
|
||||
friend class Eigen::Map<const Derived, Unaligned>;
|
||||
typedef const Eigen::Map<const Derived, Unaligned> ConstMapType;
|
||||
#if EIGEN_MAX_ALIGN_BYTES>0
|
||||
// for EIGEN_MAX_ALIGN_BYTES==0, AlignedMax==Unaligned, and many compilers generate warnings for friend-ing a class twice.
|
||||
friend class Eigen::Map<Derived, AlignedMax>;
|
||||
friend class Eigen::Map<const Derived, AlignedMax>;
|
||||
#endif
|
||||
typedef Eigen::Map<Derived, AlignedMax> AlignedMapType;
|
||||
typedef const Eigen::Map<const Derived, AlignedMax> ConstAlignedMapType;
|
||||
template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; };
|
||||
@@ -147,10 +139,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
EIGEN_DEVICE_FUNC
|
||||
const Base& base() const { return *static_cast<const Base*>(this); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const EIGEN_NOEXCEPT { return m_storage.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const EIGEN_NOEXCEPT { return m_storage.cols(); }
|
||||
|
||||
/** This is an overloaded version of DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index,Index) const
|
||||
* provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts.
|
||||
@@ -358,7 +350,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* remain row-vectors and vectors remain vectors.
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
|
||||
{
|
||||
const OtherDerived& other = _other.derived();
|
||||
@@ -383,7 +375,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or
|
||||
* conservativeResize(Index, NoChange_t).
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -440,7 +432,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or
|
||||
* conservativeResize(Index, NoChange_t).
|
||||
*
|
||||
* 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 copied from \c other.
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
@@ -508,8 +500,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
EIGEN_DEVICE_FUNC
|
||||
PlainObjectBase& operator=(PlainObjectBase&& other) EIGEN_NOEXCEPT
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_storage, other.m_storage);
|
||||
_check_template_params();
|
||||
m_storage = std::move(other.m_storage);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@@ -526,6 +518,71 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
// EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
/** \brief Construct a row of column vector with fixed size from an arbitrary number of coefficients. \cpp11
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* This constructor is for 1D array or vectors with more than 4 coefficients.
|
||||
* There exists C++98 analogue constructors for fixed-size array/vector having 1, 2, 3, or 4 coefficients.
|
||||
*
|
||||
* \warning To construct a column (resp. row) vector of fixed length, the number of values passed to this
|
||||
* constructor must match the the fixed number of rows (resp. columns) of \c *this.
|
||||
*/
|
||||
template <typename... ArgTypes>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
|
||||
: m_storage()
|
||||
{
|
||||
_check_template_params();
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, sizeof...(args) + 4);
|
||||
m_storage.data()[0] = a0;
|
||||
m_storage.data()[1] = a1;
|
||||
m_storage.data()[2] = a2;
|
||||
m_storage.data()[3] = a3;
|
||||
Index i = 4;
|
||||
auto x = {(m_storage.data()[i++] = args, 0)...};
|
||||
static_cast<void>(x);
|
||||
}
|
||||
|
||||
/** \brief Constructs a Matrix or Array and initializes it by elements given by an initializer list of initializer
|
||||
* lists \cpp11
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit EIGEN_STRONG_INLINE PlainObjectBase(const std::initializer_list<std::initializer_list<Scalar>>& list)
|
||||
: m_storage()
|
||||
{
|
||||
_check_template_params();
|
||||
|
||||
size_t list_size = 0;
|
||||
if (list.begin() != list.end()) {
|
||||
list_size = list.begin()->size();
|
||||
}
|
||||
|
||||
// This is to allow syntax like VectorXi {{1, 2, 3, 4}}
|
||||
if (ColsAtCompileTime == 1 && list.size() == 1) {
|
||||
eigen_assert(list_size == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
|
||||
resize(list_size, ColsAtCompileTime);
|
||||
std::copy(list.begin()->begin(), list.begin()->end(), m_storage.data());
|
||||
} else {
|
||||
eigen_assert(list.size() == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
|
||||
eigen_assert(list_size == static_cast<size_t>(ColsAtCompileTime) || ColsAtCompileTime == Dynamic);
|
||||
resize(list.size(), list_size);
|
||||
|
||||
Index row_index = 0;
|
||||
for (const std::initializer_list<Scalar>& row : list) {
|
||||
eigen_assert(list_size == row.size());
|
||||
Index col_index = 0;
|
||||
for (const Scalar& e : row) {
|
||||
coeffRef(row_index, col_index) = e;
|
||||
++col_index;
|
||||
}
|
||||
++row_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // end EIGEN_HAS_CXX11
|
||||
|
||||
/** \sa PlainObjectBase::operator=(const EigenBase<OtherDerived>&) */
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -564,7 +621,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
|
||||
{
|
||||
_resize_to_match(other);
|
||||
@@ -577,6 +634,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
|
||||
* \a data pointers.
|
||||
*
|
||||
* Here is an example using strides:
|
||||
* \include Matrix_Map_stride.cpp
|
||||
* Output: \verbinclude Matrix_Map_stride.out
|
||||
*
|
||||
* \see class Map
|
||||
*/
|
||||
//@{
|
||||
@@ -648,18 +709,26 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
using Base::setConstant;
|
||||
EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& val);
|
||||
EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& val);
|
||||
EIGEN_DEVICE_FUNC Derived& setConstant(NoChange_t, Index cols, const Scalar& val);
|
||||
EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, NoChange_t, const Scalar& val);
|
||||
|
||||
using Base::setZero;
|
||||
EIGEN_DEVICE_FUNC Derived& setZero(Index size);
|
||||
EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC Derived& setZero(NoChange_t, Index cols);
|
||||
EIGEN_DEVICE_FUNC Derived& setZero(Index rows, NoChange_t);
|
||||
|
||||
using Base::setOnes;
|
||||
EIGEN_DEVICE_FUNC Derived& setOnes(Index size);
|
||||
EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols);
|
||||
EIGEN_DEVICE_FUNC Derived& setOnes(NoChange_t, Index cols);
|
||||
EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, NoChange_t);
|
||||
|
||||
using Base::setRandom;
|
||||
Derived& setRandom(Index size);
|
||||
Derived& setRandom(Index rows, Index cols);
|
||||
Derived& setRandom(NoChange_t, Index cols);
|
||||
Derived& setRandom(Index rows, NoChange_t);
|
||||
|
||||
#ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
|
||||
#include EIGEN_PLAINOBJECTBASE_PLUGIN
|
||||
@@ -674,7 +743,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* remain row-vectors and vectors remain vectors.
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
|
||||
{
|
||||
#ifdef EIGEN_NO_AUTOMATIC_RESIZING
|
||||
@@ -701,10 +770,10 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
// aliasing is dealt once in internall::call_assignment
|
||||
// aliasing is dealt once in internal::call_assignment
|
||||
// so at this stage we have to assume aliasing... and resising has to be done later.
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
internal::call_assignment(this->derived(), other.derived());
|
||||
@@ -717,7 +786,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
* \sa operator=(const MatrixBase<OtherDerived>&), _set()
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
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
|
||||
@@ -733,23 +802,25 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
|
||||
bool(NumTraits<T1>::IsInteger),
|
||||
const bool t0_is_integer_alike = internal::is_valid_index_type<T0>::value;
|
||||
const bool t1_is_integer_alike = internal::is_valid_index_type<T1>::value;
|
||||
EIGEN_STATIC_ASSERT(t0_is_integer_alike &&
|
||||
t1_is_integer_alike,
|
||||
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
|
||||
resize(rows,cols);
|
||||
}
|
||||
|
||||
|
||||
template<typename T0, typename T1>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _init2(const T0& val0, const T1& val1, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
|
||||
m_storage.data()[0] = Scalar(val0);
|
||||
m_storage.data()[1] = Scalar(val1);
|
||||
}
|
||||
|
||||
|
||||
template<typename T0, typename T1>
|
||||
EIGEN_DEVICE_FUNC
|
||||
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)
|
||||
@@ -769,14 +840,14 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
&& ((!internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),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_UNUSED_VARIABLE(is_integer);
|
||||
EIGEN_STATIC_ASSERT(is_integer,
|
||||
const bool is_integer_alike = internal::is_valid_index_type<T>::value;
|
||||
EIGEN_UNUSED_VARIABLE(is_integer_alike);
|
||||
EIGEN_STATIC_ASSERT(is_integer_alike,
|
||||
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
|
||||
resize(size);
|
||||
}
|
||||
|
||||
// We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type can be implicitely converted)
|
||||
|
||||
// We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type can be implicitly converted)
|
||||
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)
|
||||
@@ -784,7 +855,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1)
|
||||
m_storage.data()[0] = val0;
|
||||
}
|
||||
|
||||
|
||||
// We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type match the index type)
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -840,7 +911,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
{
|
||||
this->derived() = r;
|
||||
}
|
||||
|
||||
|
||||
// For fixed-size Array<Scalar,...>
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -852,7 +923,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
{
|
||||
Base::setConstant(val0);
|
||||
}
|
||||
|
||||
|
||||
// For fixed-size Array<Index,...>
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
@@ -866,38 +937,38 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
{
|
||||
Base::setConstant(val0);
|
||||
}
|
||||
|
||||
|
||||
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
|
||||
friend struct internal::matrix_swap_impl;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \internal
|
||||
* \brief Override DenseBase::swap() since for dynamic-sized matrices
|
||||
* of same type it is enough to swap the data pointers.
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void swap(DenseBase<OtherDerived> & other)
|
||||
{
|
||||
enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
|
||||
internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.derived());
|
||||
}
|
||||
|
||||
|
||||
/** \internal
|
||||
* \brief const version forwarded to DenseBase::swap
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void swap(DenseBase<OtherDerived> const & other)
|
||||
{ Base::swap(other.derived()); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE void _check_template_params()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
|
||||
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
|
||||
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (int(Options)&RowMajor)==RowMajor)
|
||||
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (int(Options)&RowMajor)==0)
|
||||
&& ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
|
||||
&& ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
|
||||
&& ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
|
||||
@@ -909,6 +980,17 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
}
|
||||
|
||||
enum { IsPlainObjectBase = 1 };
|
||||
#endif
|
||||
public:
|
||||
// These apparently need to be down here for nvcc+icc to prevent duplicate
|
||||
// Map symbol.
|
||||
template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
|
||||
friend class Eigen::Map<Derived, Unaligned>;
|
||||
friend class Eigen::Map<const Derived, Unaligned>;
|
||||
#if EIGEN_MAX_ALIGN_BYTES>0
|
||||
// for EIGEN_MAX_ALIGN_BYTES==0, AlignedMax==Unaligned, and many compilers generate warnings for friend-ing a class twice.
|
||||
friend class Eigen::Map<Derived, AlignedMax>;
|
||||
friend class Eigen::Map<const Derived, AlignedMax>;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -917,13 +999,19 @@ namespace internal {
|
||||
template <typename Derived, typename OtherDerived, bool IsVector>
|
||||
struct conservative_resize_like_impl
|
||||
{
|
||||
#if EIGEN_HAS_TYPE_TRAITS
|
||||
static const bool IsRelocatable = std::is_trivially_copyable<typename Derived::Scalar>::value;
|
||||
#else
|
||||
static const bool IsRelocatable = !NumTraits<typename Derived::Scalar>::RequireInitialization;
|
||||
#endif
|
||||
static void run(DenseBase<Derived>& _this, Index rows, Index cols)
|
||||
{
|
||||
if (_this.rows() == rows && _this.cols() == cols) return;
|
||||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
|
||||
|
||||
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
|
||||
if ( IsRelocatable
|
||||
&& (( 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
|
||||
{
|
||||
internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime>::run(rows, cols);
|
||||
_this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
|
||||
@@ -931,7 +1019,7 @@ struct conservative_resize_like_impl
|
||||
else
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(rows,cols);
|
||||
Derived tmp(rows,cols);
|
||||
const Index common_rows = numext::mini(rows, _this.rows());
|
||||
const Index common_cols = numext::mini(cols, _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
@@ -951,8 +1039,9 @@ struct conservative_resize_like_impl
|
||||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
|
||||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
|
||||
|
||||
if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
|
||||
(!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns
|
||||
if ( IsRelocatable &&
|
||||
(( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
|
||||
(!Derived::IsRowMajor && _this.rows() == other.rows()) )) // column-major and we change only the number of columns
|
||||
{
|
||||
const Index new_rows = other.rows() - _this.rows();
|
||||
const Index new_cols = other.cols() - _this.cols();
|
||||
@@ -965,7 +1054,7 @@ struct conservative_resize_like_impl
|
||||
else
|
||||
{
|
||||
// The storage order does not allow us to use reallocation.
|
||||
typename Derived::PlainObject tmp(other);
|
||||
Derived tmp(other);
|
||||
const Index common_rows = numext::mini(tmp.rows(), _this.rows());
|
||||
const Index common_cols = numext::mini(tmp.cols(), _this.cols());
|
||||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
|
||||
@@ -980,13 +1069,18 @@ template <typename Derived, typename OtherDerived>
|
||||
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 conservative_resize_like_impl<Derived,OtherDerived,false> Base;
|
||||
using Base::run;
|
||||
using Base::IsRelocatable;
|
||||
|
||||
static void run(DenseBase<Derived>& _this, Index size)
|
||||
{
|
||||
const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
|
||||
const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
|
||||
_this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
|
||||
if(IsRelocatable)
|
||||
_this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
|
||||
else
|
||||
Base::run(_this.derived(), new_rows, new_cols);
|
||||
}
|
||||
|
||||
static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
|
||||
@@ -997,7 +1091,10 @@ struct conservative_resize_like_impl<Derived,OtherDerived,true>
|
||||
|
||||
const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
|
||||
const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
|
||||
_this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
|
||||
if(IsRelocatable)
|
||||
_this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
|
||||
else
|
||||
Base::run(_this.derived(), new_rows, new_cols);
|
||||
|
||||
if (num_new_elements > 0)
|
||||
_this.tail(num_new_elements) = other.tail(num_new_elements);
|
||||
@@ -1008,7 +1105,7 @@ template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
|
||||
struct matrix_swap_impl
|
||||
{
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline void run(MatrixTypeA& a, MatrixTypeB& b)
|
||||
static EIGEN_STRONG_INLINE void run(MatrixTypeA& a, MatrixTypeB& b)
|
||||
{
|
||||
a.base().swap(b);
|
||||
}
|
||||
|
||||
@@ -23,25 +23,25 @@ struct traits<Product<Lhs, Rhs, Option> >
|
||||
typedef typename remove_all<Rhs>::type RhsCleaned;
|
||||
typedef traits<LhsCleaned> LhsTraits;
|
||||
typedef traits<RhsCleaned> RhsTraits;
|
||||
|
||||
|
||||
typedef MatrixXpr XprKind;
|
||||
|
||||
|
||||
typedef typename ScalarBinaryOpTraits<typename traits<LhsCleaned>::Scalar, typename traits<RhsCleaned>::Scalar>::ReturnType Scalar;
|
||||
typedef typename product_promote_storage_type<typename LhsTraits::StorageKind,
|
||||
typename RhsTraits::StorageKind,
|
||||
internal::product_type<Lhs,Rhs>::ret>::ret StorageKind;
|
||||
typedef typename promote_index_type<typename LhsTraits::StorageIndex,
|
||||
typename RhsTraits::StorageIndex>::type StorageIndex;
|
||||
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = LhsTraits::RowsAtCompileTime,
|
||||
ColsAtCompileTime = RhsTraits::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = LhsTraits::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = RhsTraits::MaxColsAtCompileTime,
|
||||
|
||||
|
||||
// FIXME: only needed by GeneralMatrixMatrixTriangular
|
||||
InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(LhsTraits::ColsAtCompileTime, RhsTraits::RowsAtCompileTime),
|
||||
|
||||
|
||||
// The storage order is somewhat arbitrary here. The correct one will be determined through the evaluator.
|
||||
Flags = (MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1) ? RowMajorBit
|
||||
: (MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1) ? 0
|
||||
@@ -74,10 +74,10 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
|
||||
internal::product_type<_Lhs,_Rhs>::ret>::ret>
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
typedef _Lhs Lhs;
|
||||
typedef _Rhs Rhs;
|
||||
|
||||
|
||||
typedef typename ProductImpl<
|
||||
Lhs, Rhs, Option,
|
||||
typename internal::product_promote_storage_type<typename internal::traits<Lhs>::StorageKind,
|
||||
@@ -90,18 +90,23 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
|
||||
typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned;
|
||||
typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned;
|
||||
|
||||
EIGEN_DEVICE_FUNC Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs)
|
||||
{
|
||||
eigen_assert(lhs.cols() == rhs.rows()
|
||||
&& "invalid matrix product"
|
||||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions");
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index rows() const EIGEN_NOEXCEPT { return m_lhs.rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
|
||||
Index cols() const EIGEN_NOEXCEPT { return m_rhs.cols(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC const LhsNestedCleaned& lhs() const { return m_lhs; }
|
||||
EIGEN_DEVICE_FUNC const RhsNestedCleaned& rhs() const { return m_rhs; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const LhsNestedCleaned& lhs() const { return m_lhs; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const RhsNestedCleaned& rhs() const { return m_rhs; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -110,13 +115,13 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
template<typename Lhs, typename Rhs, int Option, int ProductTag = internal::product_type<Lhs,Rhs>::ret>
|
||||
class dense_product_base
|
||||
: public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type
|
||||
{};
|
||||
|
||||
/** Convertion to scalar for inner-products */
|
||||
/** Conversion to scalar for inner-products */
|
||||
template<typename Lhs, typename Rhs, int Option>
|
||||
class dense_product_base<Lhs, Rhs, Option, InnerProduct>
|
||||
: public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type
|
||||
@@ -126,8 +131,8 @@ class dense_product_base<Lhs, Rhs, Option, InnerProduct>
|
||||
public:
|
||||
using Base::derived;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
|
||||
operator const Scalar() const
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE operator const Scalar() const
|
||||
{
|
||||
return internal::evaluator<ProductXpr>(derived()).coeff(0,0);
|
||||
}
|
||||
@@ -148,37 +153,37 @@ class ProductImpl<Lhs,Rhs,Option,Dense>
|
||||
: public internal::dense_product_base<Lhs,Rhs,Option>
|
||||
{
|
||||
typedef Product<Lhs, Rhs, Option> Derived;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
typedef typename internal::dense_product_base<Lhs, Rhs, Option> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
|
||||
protected:
|
||||
enum {
|
||||
IsOneByOne = (RowsAtCompileTime == 1 || RowsAtCompileTime == Dynamic) &&
|
||||
IsOneByOne = (RowsAtCompileTime == 1 || RowsAtCompileTime == Dynamic) &&
|
||||
(ColsAtCompileTime == 1 || ColsAtCompileTime == Dynamic),
|
||||
EnableCoeff = IsOneByOne || Option==LazyProduct
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
|
||||
EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS);
|
||||
eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) );
|
||||
|
||||
|
||||
return internal::evaluator<Derived>(derived()).coeff(row,col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC Scalar coeff(Index i) const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS);
|
||||
eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) );
|
||||
|
||||
|
||||
return internal::evaluator<Derived>(derived()).coeff(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -14,27 +14,27 @@
|
||||
#define EIGEN_PRODUCTEVALUATORS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal
|
||||
* Evaluator of a product expression.
|
||||
* Since products require special treatments to handle all possible cases,
|
||||
* we simply deffer the evaluation logic to a product_evaluator class
|
||||
* we simply defer the evaluation logic to a product_evaluator class
|
||||
* which offers more partial specialization possibilities.
|
||||
*
|
||||
*
|
||||
* \sa class product_evaluator
|
||||
*/
|
||||
template<typename Lhs, typename Rhs, int Options>
|
||||
struct evaluator<Product<Lhs, Rhs, Options> >
|
||||
struct evaluator<Product<Lhs, Rhs, Options> >
|
||||
: public product_evaluator<Product<Lhs, Rhs, Options> >
|
||||
{
|
||||
typedef Product<Lhs, Rhs, Options> XprType;
|
||||
typedef product_evaluator<XprType> Base;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {}
|
||||
};
|
||||
|
||||
|
||||
// Catch "scalar * ( A * B )" and transform it to "(A*scalar) * B"
|
||||
// TODO we should apply that rule only if that's really helpful
|
||||
template<typename Lhs, typename Rhs, typename Scalar1, typename Scalar2, typename Plain1>
|
||||
@@ -55,20 +55,20 @@ struct evaluator<CwiseBinaryOp<internal::scalar_product_op<Scalar1,Scalar2>,
|
||||
const Product<Lhs, Rhs, DefaultProduct> > XprType;
|
||||
typedef evaluator<Product<EIGEN_SCALAR_BINARYOP_EXPR_RETURN_TYPE(Scalar1,Lhs,product), Rhs, DefaultProduct> > Base;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr)
|
||||
: Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs())
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template<typename Lhs, typename Rhs, int DiagIndex>
|
||||
struct evaluator<Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> >
|
||||
struct evaluator<Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> >
|
||||
: public evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex> >
|
||||
{
|
||||
typedef Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> XprType;
|
||||
typedef evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex> > Base;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr)
|
||||
: Base(Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>(
|
||||
Product<Lhs, Rhs, LazyProduct>(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()),
|
||||
xpr.index() ))
|
||||
@@ -108,27 +108,27 @@ struct product_evaluator<Product<Lhs, Rhs, Options>, ProductTag, LhsShape, RhsSh
|
||||
: m_result(xpr.rows(), xpr.cols())
|
||||
{
|
||||
::new (static_cast<Base*>(this)) Base(m_result);
|
||||
|
||||
|
||||
// FIXME shall we handle nested_eval here?,
|
||||
// if so, then we must take care at removing the call to nested_eval in the specializations (e.g., in permutation_matrix_product, transposition_matrix_product, etc.)
|
||||
// typedef typename internal::nested_eval<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
|
||||
// typedef typename internal::nested_eval<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
|
||||
// typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned;
|
||||
// typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned;
|
||||
//
|
||||
//
|
||||
// const LhsNested lhs(xpr.lhs());
|
||||
// const RhsNested rhs(xpr.rhs());
|
||||
//
|
||||
//
|
||||
// generic_product_impl<LhsNestedCleaned, RhsNestedCleaned>::evalTo(m_result, lhs, rhs);
|
||||
|
||||
generic_product_impl<Lhs, Rhs, LhsShape, RhsShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
PlainObject m_result;
|
||||
};
|
||||
|
||||
// The following three shortcuts are enabled only if the scalar types match excatly.
|
||||
// The following three shortcuts are enabled only if the scalar types match exactly.
|
||||
// TODO: we could enable them for different scalar types when the product is not vectorized.
|
||||
|
||||
// Dense = Product
|
||||
@@ -137,7 +137,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::assign_op<Scal
|
||||
typename enable_if<(Options==DefaultProduct || Options==AliasFreeProduct)>::type>
|
||||
{
|
||||
typedef Product<Lhs,Rhs,Options> SrcXprType;
|
||||
static EIGEN_STRONG_INLINE
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
@@ -155,7 +155,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::add_assign_op<
|
||||
typename enable_if<(Options==DefaultProduct || Options==AliasFreeProduct)>::type>
|
||||
{
|
||||
typedef Product<Lhs,Rhs,Options> SrcXprType;
|
||||
static EIGEN_STRONG_INLINE
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
@@ -170,7 +170,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,Options>, internal::sub_assign_op<
|
||||
typename enable_if<(Options==DefaultProduct || Options==AliasFreeProduct)>::type>
|
||||
{
|
||||
typedef Product<Lhs,Rhs,Options> SrcXprType;
|
||||
static EIGEN_STRONG_INLINE
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar,Scalar> &)
|
||||
{
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
@@ -190,7 +190,7 @@ struct Assignment<DstXprType, CwiseBinaryOp<internal::scalar_product_op<ScalarBi
|
||||
typedef CwiseBinaryOp<internal::scalar_product_op<ScalarBis,Scalar>,
|
||||
const CwiseNullaryOp<internal::scalar_constant_op<ScalarBis>,Plain>,
|
||||
const Product<Lhs,Rhs,DefaultProduct> > SrcXprType;
|
||||
static EIGEN_STRONG_INLINE
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const AssignFunc& func)
|
||||
{
|
||||
call_assignment_no_alias(dst, (src.lhs().functor().m_other * src.rhs().lhs())*src.rhs().rhs(), func);
|
||||
@@ -217,7 +217,7 @@ template<typename DstXprType, typename OtherXpr, typename ProductType, typename
|
||||
struct assignment_from_xpr_op_product
|
||||
{
|
||||
template<typename SrcXprType, typename InitialFunc>
|
||||
static EIGEN_STRONG_INLINE
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void run(DstXprType &dst, const SrcXprType &src, const InitialFunc& /*func*/)
|
||||
{
|
||||
call_assignment_no_alias(dst, src.lhs(), Func1());
|
||||
@@ -246,19 +246,19 @@ template<typename Lhs, typename Rhs>
|
||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,InnerProduct>
|
||||
{
|
||||
template<typename Dst>
|
||||
static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
dst.coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
dst.coeffRef(0,0) += (lhs.transpose().cwiseProduct(rhs)).sum();
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{ dst.coeffRef(0,0) -= (lhs.transpose().cwiseProduct(rhs)).sum(); }
|
||||
};
|
||||
|
||||
@@ -269,10 +269,10 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,InnerProduct>
|
||||
|
||||
// Column major result
|
||||
template<typename Dst, typename Lhs, typename Rhs, typename Func>
|
||||
void outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const Func& func, const false_type&)
|
||||
void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const Func& func, const false_type&)
|
||||
{
|
||||
evaluator<Rhs> rhsEval(rhs);
|
||||
typename nested_eval<Lhs,Rhs::SizeAtCompileTime>::type actual_lhs(lhs);
|
||||
ei_declare_local_nested_eval(Lhs,lhs,Rhs::SizeAtCompileTime,actual_lhs);
|
||||
// FIXME if cols is large enough, then it might be useful to make sure that lhs is sequentially stored
|
||||
// FIXME not very good if rhs is real and lhs complex while alpha is real too
|
||||
const Index cols = dst.cols();
|
||||
@@ -282,10 +282,10 @@ void outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const
|
||||
|
||||
// Row major result
|
||||
template<typename Dst, typename Lhs, typename Rhs, typename Func>
|
||||
void outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const Func& func, const true_type&)
|
||||
void EIGEN_DEVICE_FUNC outer_product_selector_run(Dst& dst, const Lhs &lhs, const Rhs &rhs, const Func& func, const true_type&)
|
||||
{
|
||||
evaluator<Lhs> lhsEval(lhs);
|
||||
typename nested_eval<Rhs,Lhs::SizeAtCompileTime>::type actual_rhs(rhs);
|
||||
ei_declare_local_nested_eval(Rhs,rhs,Lhs::SizeAtCompileTime,actual_rhs);
|
||||
// FIXME if rows is large enough, then it might be useful to make sure that rhs is sequentially stored
|
||||
// FIXME not very good if lhs is real and rhs complex while alpha is real too
|
||||
const Index rows = dst.rows();
|
||||
@@ -298,43 +298,43 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,OuterProduct>
|
||||
{
|
||||
template<typename T> struct is_row_major : internal::conditional<(int(T::Flags)&RowMajorBit), internal::true_type, internal::false_type>::type {};
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
// TODO it would be nice to be able to exploit our *_assign_op functors for that purpose
|
||||
struct set { template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
||||
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 set { template<typename Dst, typename Src> EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() = src; } };
|
||||
struct add { template<typename Dst, typename Src> EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() += src; } };
|
||||
struct sub { template<typename Dst, typename Src> EIGEN_DEVICE_FUNC void operator()(const Dst& dst, const Src& src) const { dst.const_cast_derived() -= src; } };
|
||||
struct adds {
|
||||
Scalar m_scale;
|
||||
explicit adds(const Scalar& s) : m_scale(s) {}
|
||||
template<typename Dst, typename Src> void operator()(const Dst& dst, const Src& src) const {
|
||||
template<typename Dst, typename Src> void EIGEN_DEVICE_FUNC operator()(const Dst& dst, const Src& src) const {
|
||||
dst.const_cast_derived() += m_scale * src;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major<Dst>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major<Dst>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static inline void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major<Dst>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major<Dst>());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -343,21 +343,21 @@ template<typename Lhs, typename Rhs, typename Derived>
|
||||
struct generic_product_impl_base
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{ dst.setZero(); scaleAndAddTo(dst, lhs, rhs, Scalar(1)); }
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{ scaleAndAddTo(dst,lhs, rhs, Scalar(1)); }
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{ scaleAndAddTo(dst, lhs, rhs, Scalar(-1)); }
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{ Derived::scaleAndAddTo(dst,lhs,rhs,alpha); }
|
||||
|
||||
};
|
||||
@@ -373,8 +373,13 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemvProduct>
|
||||
typedef typename internal::remove_all<typename internal::conditional<int(Side)==OnTheRight,LhsNested,RhsNested>::type>::type MatrixType;
|
||||
|
||||
template<typename Dest>
|
||||
static EIGEN_STRONG_INLINE void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
// Fallback to inner product if both the lhs and rhs is a runtime vector.
|
||||
if (lhs.rows() == 1 && rhs.cols() == 1) {
|
||||
dst.coeffRef(0,0) += alpha * lhs.row(0).conjugate().dot(rhs.col(0));
|
||||
return;
|
||||
}
|
||||
LhsNested actual_lhs(lhs);
|
||||
RhsNested actual_rhs(rhs);
|
||||
internal::gemv_dense_selector<Side,
|
||||
@@ -385,35 +390,84 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,GemvProduct>
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode>
|
||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode>
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
// Same as: dst.noalias() = lhs.lazyProduct(rhs);
|
||||
// but easier on the compiler side
|
||||
call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op<typename Dst::Scalar,Scalar>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
// dst.noalias() += lhs.lazyProduct(rhs);
|
||||
call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::add_assign_op<typename Dst::Scalar,Scalar>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Dst>
|
||||
static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
// dst.noalias() -= lhs.lazyProduct(rhs);
|
||||
call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::sub_assign_op<typename Dst::Scalar,Scalar>());
|
||||
}
|
||||
|
||||
// template<typename Dst>
|
||||
// static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
// { dst.noalias() += alpha * lhs.lazyProduct(rhs); }
|
||||
|
||||
// This is a special evaluation path called from generic_product_impl<...,GemmProduct> in file GeneralMatrixMatrix.h
|
||||
// This variant tries to extract scalar multiples from both the LHS and RHS and factor them out. For instance:
|
||||
// dst {,+,-}= (s1*A)*(B*s2)
|
||||
// will be rewritten as:
|
||||
// dst {,+,-}= (s1*s2) * (A.lazyProduct(B))
|
||||
// There are at least four benefits of doing so:
|
||||
// 1 - huge performance gain for heap-allocated matrix types as it save costly allocations.
|
||||
// 2 - it is faster than simply by-passing the heap allocation through stack allocation.
|
||||
// 3 - it makes this fallback consistent with the heavy GEMM routine.
|
||||
// 4 - it fully by-passes huge stack allocation attempts when multiplying huge fixed-size matrices.
|
||||
// (see https://stackoverflow.com/questions/54738495)
|
||||
// For small fixed sizes matrices, howver, the gains are less obvious, it is sometimes x2 faster, but sometimes x3 slower,
|
||||
// and the behavior depends also a lot on the compiler... This is why this re-writting strategy is currently
|
||||
// enabled only when falling back from the main GEMM.
|
||||
template<typename Dst, typename Func>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void eval_dynamic(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Func &func)
|
||||
{
|
||||
enum {
|
||||
HasScalarFactor = blas_traits<Lhs>::HasScalarFactor || blas_traits<Rhs>::HasScalarFactor,
|
||||
ConjLhs = blas_traits<Lhs>::NeedToConjugate,
|
||||
ConjRhs = blas_traits<Rhs>::NeedToConjugate
|
||||
};
|
||||
// FIXME: in c++11 this should be auto, and extractScalarFactor should also return auto
|
||||
// this is important for real*complex_mat
|
||||
Scalar actualAlpha = combine_scalar_factors<Scalar>(lhs, rhs);
|
||||
|
||||
eval_dynamic_impl(dst,
|
||||
blas_traits<Lhs>::extract(lhs).template conjugateIf<ConjLhs>(),
|
||||
blas_traits<Rhs>::extract(rhs).template conjugateIf<ConjRhs>(),
|
||||
func,
|
||||
actualAlpha,
|
||||
typename conditional<HasScalarFactor,true_type,false_type>::type());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template<typename Dst, typename LhsT, typename RhsT, typename Func, typename Scalar>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void eval_dynamic_impl(Dst& dst, const LhsT& lhs, const RhsT& rhs, const Func &func, const Scalar& s /* == 1 */, false_type)
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(s);
|
||||
eigen_internal_assert(s==Scalar(1));
|
||||
call_restricted_packet_assignment_no_alias(dst, lhs.lazyProduct(rhs), func);
|
||||
}
|
||||
|
||||
template<typename Dst, typename LhsT, typename RhsT, typename Func, typename Scalar>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void eval_dynamic_impl(Dst& dst, const LhsT& lhs, const RhsT& rhs, const Func &func, const Scalar& s, true_type)
|
||||
{
|
||||
call_restricted_packet_assignment_no_alias(dst, s * lhs.lazyProduct(rhs), func);
|
||||
}
|
||||
};
|
||||
|
||||
// This specialization enforces the use of a coefficient-based evaluation strategy
|
||||
@@ -471,7 +525,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
|
||||
typedef typename internal::nested_eval<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
|
||||
typedef typename internal::nested_eval<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
|
||||
|
||||
|
||||
typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned;
|
||||
typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned;
|
||||
|
||||
@@ -490,19 +544,19 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
typedef typename find_best_packet<Scalar,ColsAtCompileTime>::type RhsVecPacketType;
|
||||
|
||||
enum {
|
||||
|
||||
|
||||
LhsCoeffReadCost = LhsEtorType::CoeffReadCost,
|
||||
RhsCoeffReadCost = RhsEtorType::CoeffReadCost,
|
||||
CoeffReadCost = InnerSize==0 ? NumTraits<Scalar>::ReadCost
|
||||
: InnerSize == Dynamic ? HugeCost
|
||||
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
||||
: InnerSize * (NumTraits<Scalar>::MulCost + int(LhsCoeffReadCost) + int(RhsCoeffReadCost))
|
||||
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
|
||||
|
||||
Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
|
||||
|
||||
|
||||
LhsFlags = LhsEtorType::Flags,
|
||||
RhsFlags = RhsEtorType::Flags,
|
||||
|
||||
|
||||
LhsRowMajor = LhsFlags & RowMajorBit,
|
||||
RhsRowMajor = RhsFlags & RowMajorBit,
|
||||
|
||||
@@ -512,7 +566,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
// Here, we don't care about alignment larger than the usable packet size.
|
||||
LhsAlignment = EIGEN_PLAIN_ENUM_MIN(LhsEtorType::Alignment,LhsVecPacketSize*int(sizeof(typename LhsNestedCleaned::Scalar))),
|
||||
RhsAlignment = EIGEN_PLAIN_ENUM_MIN(RhsEtorType::Alignment,RhsVecPacketSize*int(sizeof(typename RhsNestedCleaned::Scalar))),
|
||||
|
||||
|
||||
SameType = is_same<typename LhsNestedCleaned::Scalar,typename RhsNestedCleaned::Scalar>::value,
|
||||
|
||||
CanVectorizeRhs = bool(RhsRowMajor) && (RhsFlags & PacketAccessBit) && (ColsAtCompileTime!=1),
|
||||
@@ -522,12 +576,12 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
: (bool(RhsRowMajor) && !CanVectorizeLhs),
|
||||
|
||||
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & ~RowMajorBit)
|
||||
Flags = ((int(LhsFlags) | int(RhsFlags)) & HereditaryBits & ~RowMajorBit)
|
||||
| (EvalToRowMajor ? RowMajorBit : 0)
|
||||
// TODO enable vectorization for mixed types
|
||||
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0)
|
||||
| (XprType::IsVectorAtCompileTime ? LinearAccessBit : 0),
|
||||
|
||||
|
||||
LhsOuterStrideBytes = int(LhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename LhsNestedCleaned::Scalar)),
|
||||
RhsOuterStrideBytes = int(RhsNestedCleaned::OuterStrideAtCompileTime) * int(sizeof(typename RhsNestedCleaned::Scalar)),
|
||||
|
||||
@@ -543,10 +597,10 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
CanVectorizeInner = SameType
|
||||
&& LhsRowMajor
|
||||
&& (!RhsRowMajor)
|
||||
&& (LhsFlags & RhsFlags & ActualPacketAccessBit)
|
||||
&& (InnerSize % packet_traits<Scalar>::size == 0)
|
||||
&& (int(LhsFlags) & int(RhsFlags) & ActualPacketAccessBit)
|
||||
&& (int(InnerSize) % packet_traits<Scalar>::size == 0)
|
||||
};
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return (m_lhs.row(row).transpose().cwiseProduct( m_rhs.col(col) )).sum();
|
||||
@@ -556,7 +610,8 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
* which is why we don't set the LinearAccessBit.
|
||||
* TODO: this seems possible when the result is a vector
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC const CoeffReturnType coeff(Index index) const
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||
const Index col = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? index : 0;
|
||||
@@ -564,6 +619,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const PacketType packet(Index row, Index col) const
|
||||
{
|
||||
PacketType res;
|
||||
@@ -575,6 +631,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const PacketType packet(Index index) const
|
||||
{
|
||||
const Index row = (RowsAtCompileTime == 1 || MaxRowsAtCompileTime==1) ? 0 : index;
|
||||
@@ -585,7 +642,7 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
protected:
|
||||
typename internal::add_const_on_value_type<LhsNested>::type m_lhs;
|
||||
typename internal::add_const_on_value_type<RhsNested>::type m_rhs;
|
||||
|
||||
|
||||
LhsEtorType m_lhsImpl;
|
||||
RhsEtorType m_rhsImpl;
|
||||
|
||||
@@ -603,7 +660,8 @@ struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, LazyCoeffBasedProduc
|
||||
enum {
|
||||
Flags = Base::Flags | EvalBeforeNestingBit
|
||||
};
|
||||
EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
explicit product_evaluator(const XprType& xpr)
|
||||
: Base(BaseProduct(xpr.lhs(),xpr.rhs()))
|
||||
{}
|
||||
};
|
||||
@@ -615,7 +673,7 @@ struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, LazyCoeffBasedProduc
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC 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, Index(UnrollingIndex-1))), rhs.template packet<LoadMode,Packet>(Index(UnrollingIndex-1), col), res);
|
||||
@@ -625,7 +683,7 @@ struct etor_product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC 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,Packet>(row, Index(UnrollingIndex-1)), pset1<Packet>(rhs.coeff(Index(UnrollingIndex-1), col)), res);
|
||||
@@ -635,7 +693,7 @@ struct etor_product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, Load
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC 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, Index(0))),rhs.template packet<LoadMode,Packet>(Index(0), col));
|
||||
}
|
||||
@@ -644,7 +702,7 @@ struct etor_product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index /*innerDim*/, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC 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,Packet>(row, Index(0)), pset1<Packet>(rhs.coeff(Index(0), col)));
|
||||
}
|
||||
@@ -653,7 +711,7 @@ struct etor_product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
@@ -662,7 +720,7 @@ struct etor_product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Index /*innerDim*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
}
|
||||
@@ -671,7 +729,7 @@ struct etor_product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for(Index i = 0; i < innerDim; ++i)
|
||||
@@ -682,7 +740,7 @@ struct etor_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct etor_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Index innerDim, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(typename unpacket_traits<Packet>::type(0));
|
||||
for(Index i = 0; i < innerDim; ++i)
|
||||
@@ -704,7 +762,7 @@ struct generic_product_impl<Lhs,Rhs,TriangularShape,DenseShape,ProductTag>
|
||||
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,TriangularShape,DenseShape,ProductTag> >
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
@@ -718,7 +776,7 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,TriangularShape,ProductTag>
|
||||
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,DenseShape,TriangularShape,ProductTag> >
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
@@ -739,9 +797,10 @@ struct generic_product_impl<Lhs,Rhs,SelfAdjointShape,DenseShape,ProductTag>
|
||||
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,SelfAdjointShape,DenseShape,ProductTag> >
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
static EIGEN_DEVICE_FUNC
|
||||
void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
selfadjoint_product_impl<typename Lhs::MatrixType,Lhs::Mode,false,Rhs,0,Rhs::IsVectorAtCompileTime>::run(dst, lhs.nestedExpression(), rhs, alpha);
|
||||
}
|
||||
@@ -752,7 +811,7 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,SelfAdjointShape,ProductTag>
|
||||
: generic_product_impl_base<Lhs,Rhs,generic_product_impl<Lhs,Rhs,DenseShape,SelfAdjointShape,ProductTag> >
|
||||
{
|
||||
typedef typename Product<Lhs,Rhs>::Scalar Scalar;
|
||||
|
||||
|
||||
template<typename Dest>
|
||||
static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha)
|
||||
{
|
||||
@@ -764,7 +823,7 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,SelfAdjointShape,ProductTag>
|
||||
/***************************************************************************
|
||||
* Diagonal products
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
template<typename MatrixType, typename DiagonalType, typename Derived, int ProductOrder>
|
||||
struct diagonal_product_evaluator_base
|
||||
: evaluator_base<Derived>
|
||||
@@ -772,34 +831,49 @@ struct diagonal_product_evaluator_base
|
||||
typedef typename ScalarBinaryOpTraits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
|
||||
public:
|
||||
enum {
|
||||
CoeffReadCost = NumTraits<Scalar>::MulCost + evaluator<MatrixType>::CoeffReadCost + evaluator<DiagonalType>::CoeffReadCost,
|
||||
|
||||
CoeffReadCost = int(NumTraits<Scalar>::MulCost) + int(evaluator<MatrixType>::CoeffReadCost) + int(evaluator<DiagonalType>::CoeffReadCost),
|
||||
|
||||
MatrixFlags = evaluator<MatrixType>::Flags,
|
||||
DiagFlags = evaluator<DiagonalType>::Flags,
|
||||
_StorageOrder = MatrixFlags & RowMajorBit ? RowMajor : ColMajor,
|
||||
|
||||
_StorageOrder = (Derived::MaxRowsAtCompileTime==1 && Derived::MaxColsAtCompileTime!=1) ? RowMajor
|
||||
: (Derived::MaxColsAtCompileTime==1 && Derived::MaxRowsAtCompileTime!=1) ? ColMajor
|
||||
: MatrixFlags & RowMajorBit ? RowMajor : ColMajor,
|
||||
_SameStorageOrder = _StorageOrder == (MatrixFlags & RowMajorBit ? RowMajor : ColMajor),
|
||||
|
||||
_ScalarAccessOnDiag = !((int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheLeft)
|
||||
||(int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheRight)),
|
||||
_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
|
||||
//_Vectorizable = bool(int(MatrixFlags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagFlags)&PacketAccessBit))),
|
||||
_Vectorizable = bool(int(MatrixFlags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagFlags)&PacketAccessBit))),
|
||||
_Vectorizable = bool(int(MatrixFlags)&PacketAccessBit)
|
||||
&& _SameTypes
|
||||
&& (_SameStorageOrder || (MatrixFlags&LinearAccessBit)==LinearAccessBit)
|
||||
&& (_ScalarAccessOnDiag || (bool(int(DiagFlags)&PacketAccessBit))),
|
||||
_LinearAccessMask = (MatrixType::RowsAtCompileTime==1 || MatrixType::ColsAtCompileTime==1) ? LinearAccessBit : 0,
|
||||
Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixFlags)) | (_Vectorizable ? PacketAccessBit : 0),
|
||||
Alignment = evaluator<MatrixType>::Alignment
|
||||
Alignment = evaluator<MatrixType>::Alignment,
|
||||
|
||||
AsScalarProduct = (DiagonalType::SizeAtCompileTime==1)
|
||||
|| (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::RowsAtCompileTime==1 && ProductOrder==OnTheLeft)
|
||||
|| (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==1 && ProductOrder==OnTheRight)
|
||||
};
|
||||
|
||||
diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag)
|
||||
|
||||
EIGEN_DEVICE_FUNC diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag)
|
||||
: m_diagImpl(diag), m_matImpl(mat)
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::MulCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const
|
||||
{
|
||||
return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx);
|
||||
if(AsScalarProduct)
|
||||
return m_diagImpl.coeff(0) * m_matImpl.coeff(idx);
|
||||
else
|
||||
return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index id, internal::true_type) const
|
||||
@@ -807,7 +881,7 @@ protected:
|
||||
return internal::pmul(m_matImpl.template packet<LoadMode,PacketType>(row, col),
|
||||
internal::pset1<PacketType>(m_diagImpl.coeff(id)));
|
||||
}
|
||||
|
||||
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet_impl(Index row, Index col, Index id, internal::false_type) const
|
||||
{
|
||||
@@ -818,7 +892,7 @@ protected:
|
||||
return internal::pmul(m_matImpl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_diagImpl.template packet<DiagonalPacketLoadMode,PacketType>(id));
|
||||
}
|
||||
|
||||
|
||||
evaluator<DiagonalType> m_diagImpl;
|
||||
evaluator<MatrixType> m_matImpl;
|
||||
};
|
||||
@@ -833,25 +907,25 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
|
||||
using Base::m_matImpl;
|
||||
using Base::coeff;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
|
||||
|
||||
typedef Product<Lhs, Rhs, ProductKind> XprType;
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
|
||||
enum {
|
||||
StorageOrder = int(Rhs::Flags) & RowMajorBit ? RowMajor : ColMajor
|
||||
};
|
||||
typedef typename Lhs::DiagonalVectorType DiagonalType;
|
||||
|
||||
|
||||
enum { StorageOrder = Base::_StorageOrder };
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
|
||||
: Base(xpr.rhs(), xpr.lhs().diagonal())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
return m_diagImpl.coeff(row) * m_matImpl.coeff(row, col);
|
||||
}
|
||||
|
||||
#ifndef __CUDACC__
|
||||
|
||||
#ifndef EIGEN_GPUCC
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const
|
||||
{
|
||||
@@ -860,7 +934,7 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
|
||||
return this->template packet_impl<LoadMode,PacketType>(row,col, row,
|
||||
typename internal::conditional<int(StorageOrder)==RowMajor, internal::true_type, internal::false_type>::type());
|
||||
}
|
||||
|
||||
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index idx) const
|
||||
{
|
||||
@@ -879,30 +953,30 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DenseShape,
|
||||
using Base::m_matImpl;
|
||||
using Base::coeff;
|
||||
typedef typename Base::Scalar Scalar;
|
||||
|
||||
|
||||
typedef Product<Lhs, Rhs, ProductKind> XprType;
|
||||
typedef typename XprType::PlainObject PlainObject;
|
||||
|
||||
enum { StorageOrder = int(Lhs::Flags) & RowMajorBit ? RowMajor : ColMajor };
|
||||
|
||||
enum { StorageOrder = Base::_StorageOrder };
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
|
||||
: Base(xpr.lhs(), xpr.rhs().diagonal())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
return m_matImpl.coeff(row, col) * m_diagImpl.coeff(col);
|
||||
}
|
||||
|
||||
#ifndef __CUDACC__
|
||||
|
||||
#ifndef EIGEN_GPUCC
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const
|
||||
{
|
||||
return this->template packet_impl<LoadMode,PacketType>(row,col, col,
|
||||
typename internal::conditional<int(StorageOrder)==ColMajor, internal::true_type, internal::false_type>::type());
|
||||
}
|
||||
|
||||
|
||||
template<int LoadMode,typename PacketType>
|
||||
EIGEN_STRONG_INLINE PacketType packet(Index idx) const
|
||||
{
|
||||
@@ -930,7 +1004,7 @@ struct permutation_matrix_product<ExpressionType, Side, Transposed, DenseShape>
|
||||
typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
|
||||
|
||||
template<typename Dest, typename PermutationType>
|
||||
static inline void run(Dest& dst, const PermutationType& perm, const ExpressionType& xpr)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Dest& dst, const PermutationType& perm, const ExpressionType& xpr)
|
||||
{
|
||||
MatrixType mat(xpr);
|
||||
const Index n = Side==OnTheLeft ? mat.rows() : mat.cols();
|
||||
@@ -984,7 +1058,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, PermutationShape, MatrixShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
permutation_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
|
||||
}
|
||||
@@ -994,7 +1068,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, MatrixShape, PermutationShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
permutation_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
|
||||
}
|
||||
@@ -1004,7 +1078,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Inverse<Lhs>, Rhs, PermutationShape, MatrixShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Inverse<Lhs>& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Inverse<Lhs>& lhs, const Rhs& rhs)
|
||||
{
|
||||
permutation_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
|
||||
}
|
||||
@@ -1014,7 +1088,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Inverse<Rhs>, MatrixShape, PermutationShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Inverse<Rhs>& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Inverse<Rhs>& rhs)
|
||||
{
|
||||
permutation_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
|
||||
}
|
||||
@@ -1036,9 +1110,9 @@ struct transposition_matrix_product
|
||||
{
|
||||
typedef typename nested_eval<ExpressionType, 1>::type MatrixType;
|
||||
typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
|
||||
|
||||
|
||||
template<typename Dest, typename TranspositionType>
|
||||
static inline void run(Dest& dst, const TranspositionType& tr, const ExpressionType& xpr)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Dest& dst, const TranspositionType& tr, const ExpressionType& xpr)
|
||||
{
|
||||
MatrixType mat(xpr);
|
||||
typedef typename TranspositionType::StorageIndex StorageIndex;
|
||||
@@ -1061,7 +1135,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, TranspositionsShape, MatrixShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
transposition_matrix_product<Rhs, OnTheLeft, false, MatrixShape>::run(dst, lhs, rhs);
|
||||
}
|
||||
@@ -1071,7 +1145,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Rhs, MatrixShape, TranspositionsShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs)
|
||||
{
|
||||
transposition_matrix_product<Lhs, OnTheRight, false, MatrixShape>::run(dst, rhs, lhs);
|
||||
}
|
||||
@@ -1082,7 +1156,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Transpose<Lhs>, Rhs, TranspositionsShape, MatrixShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Transpose<Lhs>& lhs, const Rhs& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Transpose<Lhs>& lhs, const Rhs& rhs)
|
||||
{
|
||||
transposition_matrix_product<Rhs, OnTheLeft, true, MatrixShape>::run(dst, lhs.nestedExpression(), rhs);
|
||||
}
|
||||
@@ -1092,7 +1166,7 @@ template<typename Lhs, typename Rhs, int ProductTag, typename MatrixShape>
|
||||
struct generic_product_impl<Lhs, Transpose<Rhs>, MatrixShape, TranspositionsShape, ProductTag>
|
||||
{
|
||||
template<typename Dest>
|
||||
static void evalTo(Dest& dst, const Lhs& lhs, const Transpose<Rhs>& rhs)
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dest& dst, const Lhs& lhs, const Transpose<Rhs>& rhs)
|
||||
{
|
||||
transposition_matrix_product<Lhs, OnTheRight, true, MatrixShape>::run(dst, rhs.nestedExpression(), lhs);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ DenseBase<Derived>::Random()
|
||||
* \sa class CwiseNullaryOp, setRandom(Index), setRandom(Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Derived& DenseBase<Derived>::setRandom()
|
||||
EIGEN_DEVICE_FUNC inline Derived& DenseBase<Derived>::setRandom()
|
||||
{
|
||||
return *this = Random(rows(), cols());
|
||||
}
|
||||
@@ -177,6 +177,42 @@ PlainObjectBase<Derived>::setRandom(Index rows, Index cols)
|
||||
return setRandom();
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of columns, and sets all
|
||||
* coefficients in this expression to random values. For the parameter of type
|
||||
* NoChange_t, just pass the special value \c NoChange.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* \sa DenseBase::setRandom(), setRandom(Index), setRandom(Index, NoChange_t), class CwiseNullaryOp, DenseBase::Random()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setRandom(NoChange_t, Index cols)
|
||||
{
|
||||
return setRandom(rows(), cols);
|
||||
}
|
||||
|
||||
/** Resizes to the given size, changing only the number of rows, and sets all
|
||||
* coefficients in this expression to random values. For the parameter of type
|
||||
* NoChange_t, just pass the special value \c NoChange.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* \sa DenseBase::setRandom(), setRandom(Index), setRandom(NoChange_t, Index), class CwiseNullaryOp, DenseBase::Random()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setRandom(Index rows, NoChange_t)
|
||||
{
|
||||
return setRandom(rows, cols());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_RANDOM_H
|
||||
+182
-172
@@ -23,23 +23,29 @@ namespace internal {
|
||||
* Part 1 : the logic deciding a strategy for vectorization and unrolling
|
||||
***************************************************************************/
|
||||
|
||||
template<typename Func, typename Derived>
|
||||
template<typename Func, typename Evaluator>
|
||||
struct redux_traits
|
||||
{
|
||||
public:
|
||||
typedef typename find_best_packet<typename Derived::Scalar,Derived::SizeAtCompileTime>::type PacketType;
|
||||
typedef typename find_best_packet<typename Evaluator::Scalar,Evaluator::SizeAtCompileTime>::type PacketType;
|
||||
enum {
|
||||
PacketSize = unpacket_traits<PacketType>::size,
|
||||
InnerMaxSize = int(Derived::IsRowMajor)
|
||||
? Derived::MaxColsAtCompileTime
|
||||
: Derived::MaxRowsAtCompileTime
|
||||
InnerMaxSize = int(Evaluator::IsRowMajor)
|
||||
? Evaluator::MaxColsAtCompileTime
|
||||
: Evaluator::MaxRowsAtCompileTime,
|
||||
OuterMaxSize = int(Evaluator::IsRowMajor)
|
||||
? Evaluator::MaxRowsAtCompileTime
|
||||
: Evaluator::MaxColsAtCompileTime,
|
||||
SliceVectorizedWork = int(InnerMaxSize)==Dynamic ? Dynamic
|
||||
: int(OuterMaxSize)==Dynamic ? (int(InnerMaxSize)>=int(PacketSize) ? Dynamic : 0)
|
||||
: (int(InnerMaxSize)/int(PacketSize)) * int(OuterMaxSize)
|
||||
};
|
||||
|
||||
enum {
|
||||
MightVectorize = (int(Derived::Flags)&ActualPacketAccessBit)
|
||||
MightVectorize = (int(Evaluator::Flags)&ActualPacketAccessBit)
|
||||
&& (functor_traits<Func>::PacketAccess),
|
||||
MayLinearVectorize = bool(MightVectorize) && (int(Derived::Flags)&LinearAccessBit),
|
||||
MaySliceVectorize = bool(MightVectorize) && int(InnerMaxSize)>=3*PacketSize
|
||||
MayLinearVectorize = bool(MightVectorize) && (int(Evaluator::Flags)&LinearAccessBit),
|
||||
MaySliceVectorize = bool(MightVectorize) && (int(SliceVectorizedWork)==Dynamic || int(SliceVectorizedWork)>=3)
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -51,8 +57,8 @@ public:
|
||||
|
||||
public:
|
||||
enum {
|
||||
Cost = Derived::SizeAtCompileTime == Dynamic ? HugeCost
|
||||
: Derived::SizeAtCompileTime * Derived::CoeffReadCost + (Derived::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
|
||||
Cost = Evaluator::SizeAtCompileTime == Dynamic ? HugeCost
|
||||
: int(Evaluator::SizeAtCompileTime) * int(Evaluator::CoeffReadCost) + (Evaluator::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
|
||||
UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize))
|
||||
};
|
||||
|
||||
@@ -64,18 +70,20 @@ public:
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
static void debug()
|
||||
{
|
||||
std::cerr << "Xpr: " << typeid(typename Derived::XprType).name() << std::endl;
|
||||
std::cerr << "Xpr: " << typeid(typename Evaluator::XprType).name() << std::endl;
|
||||
std::cerr.setf(std::ios::hex, std::ios::basefield);
|
||||
EIGEN_DEBUG_VAR(Derived::Flags)
|
||||
EIGEN_DEBUG_VAR(Evaluator::Flags)
|
||||
std::cerr.unsetf(std::ios::hex);
|
||||
EIGEN_DEBUG_VAR(InnerMaxSize)
|
||||
EIGEN_DEBUG_VAR(OuterMaxSize)
|
||||
EIGEN_DEBUG_VAR(SliceVectorizedWork)
|
||||
EIGEN_DEBUG_VAR(PacketSize)
|
||||
EIGEN_DEBUG_VAR(MightVectorize)
|
||||
EIGEN_DEBUG_VAR(MayLinearVectorize)
|
||||
EIGEN_DEBUG_VAR(MaySliceVectorize)
|
||||
EIGEN_DEBUG_VAR(Traversal)
|
||||
std::cerr << "Traversal" << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl;
|
||||
EIGEN_DEBUG_VAR(UnrollingLimit)
|
||||
EIGEN_DEBUG_VAR(Unrolling)
|
||||
std::cerr << "Unrolling" << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
#endif
|
||||
@@ -87,88 +95,86 @@ public:
|
||||
|
||||
/*** no vectorization ***/
|
||||
|
||||
template<typename Func, typename Derived, int Start, int Length>
|
||||
template<typename Func, typename Evaluator, int Start, int Length>
|
||||
struct redux_novec_unroller
|
||||
{
|
||||
enum {
|
||||
HalfLength = Length/2
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func)
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Evaluator &eval, const Func& func)
|
||||
{
|
||||
return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
|
||||
redux_novec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func));
|
||||
return func(redux_novec_unroller<Func, Evaluator, Start, HalfLength>::run(eval,func),
|
||||
redux_novec_unroller<Func, Evaluator, Start+HalfLength, Length-HalfLength>::run(eval,func));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Func, typename Derived, int Start>
|
||||
struct redux_novec_unroller<Func, Derived, Start, 1>
|
||||
template<typename Func, typename Evaluator, int Start>
|
||||
struct redux_novec_unroller<Func, Evaluator, Start, 1>
|
||||
{
|
||||
enum {
|
||||
outer = Start / Derived::InnerSizeAtCompileTime,
|
||||
inner = Start % Derived::InnerSizeAtCompileTime
|
||||
outer = Start / Evaluator::InnerSizeAtCompileTime,
|
||||
inner = Start % Evaluator::InnerSizeAtCompileTime
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func&)
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Evaluator &eval, const Func&)
|
||||
{
|
||||
return mat.coeffByOuterInner(outer, inner);
|
||||
return eval.coeffByOuterInner(outer, inner);
|
||||
}
|
||||
};
|
||||
|
||||
// This is actually dead code and will never be called. It is required
|
||||
// to prevent false warnings regarding failed inlining though
|
||||
// for 0 length run() will never be called at all.
|
||||
template<typename Func, typename Derived, int Start>
|
||||
struct redux_novec_unroller<Func, Derived, Start, 0>
|
||||
template<typename Func, typename Evaluator, int Start>
|
||||
struct redux_novec_unroller<Func, Evaluator, Start, 0>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Derived&, const Func&) { return Scalar(); }
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Evaluator&, const Func&) { return Scalar(); }
|
||||
};
|
||||
|
||||
/*** vectorization ***/
|
||||
|
||||
template<typename Func, typename Derived, int Start, int Length>
|
||||
template<typename Func, typename Evaluator, int Start, int Length>
|
||||
struct redux_vec_unroller
|
||||
{
|
||||
enum {
|
||||
PacketSize = redux_traits<Func, Derived>::PacketSize,
|
||||
HalfLength = Length/2
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Derived>::PacketType PacketScalar;
|
||||
|
||||
static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func& func)
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE PacketType run(const Evaluator &eval, const Func& func)
|
||||
{
|
||||
enum {
|
||||
PacketSize = unpacket_traits<PacketType>::size,
|
||||
HalfLength = Length/2
|
||||
};
|
||||
|
||||
return func.packetOp(
|
||||
redux_vec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
|
||||
redux_vec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func) );
|
||||
redux_vec_unroller<Func, Evaluator, Start, HalfLength>::template run<PacketType>(eval,func),
|
||||
redux_vec_unroller<Func, Evaluator, Start+HalfLength, Length-HalfLength>::template run<PacketType>(eval,func) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Func, typename Derived, int Start>
|
||||
struct redux_vec_unroller<Func, Derived, Start, 1>
|
||||
template<typename Func, typename Evaluator, int Start>
|
||||
struct redux_vec_unroller<Func, Evaluator, Start, 1>
|
||||
{
|
||||
enum {
|
||||
index = Start * redux_traits<Func, Derived>::PacketSize,
|
||||
outer = index / int(Derived::InnerSizeAtCompileTime),
|
||||
inner = index % int(Derived::InnerSizeAtCompileTime),
|
||||
alignment = Derived::Alignment
|
||||
};
|
||||
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Derived>::PacketType PacketScalar;
|
||||
|
||||
static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func&)
|
||||
template<typename PacketType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE PacketType run(const Evaluator &eval, const Func&)
|
||||
{
|
||||
return mat.template packetByOuterInner<alignment,PacketScalar>(outer, inner);
|
||||
enum {
|
||||
PacketSize = unpacket_traits<PacketType>::size,
|
||||
index = Start * PacketSize,
|
||||
outer = index / int(Evaluator::InnerSizeAtCompileTime),
|
||||
inner = index % int(Evaluator::InnerSizeAtCompileTime),
|
||||
alignment = Evaluator::Alignment
|
||||
};
|
||||
return eval.template packetByOuterInner<alignment,PacketType>(outer, inner);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,53 +182,65 @@ struct redux_vec_unroller<Func, Derived, Start, 1>
|
||||
* Part 3 : implementation of all cases
|
||||
***************************************************************************/
|
||||
|
||||
template<typename Func, typename Derived,
|
||||
int Traversal = redux_traits<Func, Derived>::Traversal,
|
||||
int Unrolling = redux_traits<Func, Derived>::Unrolling
|
||||
template<typename Func, typename Evaluator,
|
||||
int Traversal = redux_traits<Func, Evaluator>::Traversal,
|
||||
int Unrolling = redux_traits<Func, Evaluator>::Unrolling
|
||||
>
|
||||
struct redux_impl;
|
||||
|
||||
template<typename Func, typename Derived>
|
||||
struct redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>
|
||||
template<typename Func, typename Evaluator>
|
||||
struct redux_impl<Func, Evaluator, DefaultTraversal, NoUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func)
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
|
||||
template<typename XprType>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE
|
||||
Scalar run(const Evaluator &eval, const Func& func, const XprType& xpr)
|
||||
{
|
||||
eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
|
||||
eigen_assert(xpr.rows()>0 && xpr.cols()>0 && "you are using an empty matrix");
|
||||
Scalar res;
|
||||
res = mat.coeffByOuterInner(0, 0);
|
||||
for(Index i = 1; i < mat.innerSize(); ++i)
|
||||
res = func(res, mat.coeffByOuterInner(0, i));
|
||||
for(Index i = 1; i < mat.outerSize(); ++i)
|
||||
for(Index j = 0; j < mat.innerSize(); ++j)
|
||||
res = func(res, mat.coeffByOuterInner(i, j));
|
||||
res = eval.coeffByOuterInner(0, 0);
|
||||
for(Index i = 1; i < xpr.innerSize(); ++i)
|
||||
res = func(res, eval.coeffByOuterInner(0, i));
|
||||
for(Index i = 1; i < xpr.outerSize(); ++i)
|
||||
for(Index j = 0; j < xpr.innerSize(); ++j)
|
||||
res = func(res, eval.coeffByOuterInner(i, j));
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Func, typename Derived>
|
||||
struct redux_impl<Func,Derived, DefaultTraversal, CompleteUnrolling>
|
||||
: public redux_novec_unroller<Func,Derived, 0, Derived::SizeAtCompileTime>
|
||||
{};
|
||||
|
||||
template<typename Func, typename Derived>
|
||||
struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
|
||||
template<typename Func, typename Evaluator>
|
||||
struct redux_impl<Func,Evaluator, DefaultTraversal, CompleteUnrolling>
|
||||
: redux_novec_unroller<Func,Evaluator, 0, Evaluator::SizeAtCompileTime>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Derived>::PacketType PacketScalar;
|
||||
|
||||
static Scalar run(const Derived &mat, const Func& func)
|
||||
typedef redux_novec_unroller<Func,Evaluator, 0, Evaluator::SizeAtCompileTime> Base;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
template<typename XprType>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE
|
||||
Scalar run(const Evaluator &eval, const Func& func, const XprType& /*xpr*/)
|
||||
{
|
||||
const Index size = mat.size();
|
||||
return Base::run(eval,func);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Func, typename Evaluator>
|
||||
struct redux_impl<Func, Evaluator, LinearVectorizedTraversal, NoUnrolling>
|
||||
{
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Evaluator>::PacketType PacketScalar;
|
||||
|
||||
template<typename XprType>
|
||||
static Scalar run(const Evaluator &eval, const Func& func, const XprType& xpr)
|
||||
{
|
||||
const Index size = xpr.size();
|
||||
|
||||
const Index packetSize = redux_traits<Func, Derived>::PacketSize;
|
||||
const Index packetSize = redux_traits<Func, Evaluator>::PacketSize;
|
||||
const int packetAlignment = unpacket_traits<PacketScalar>::alignment;
|
||||
enum {
|
||||
alignment0 = (bool(Derived::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::AlignedOnScalar)) ? int(packetAlignment) : int(Unaligned),
|
||||
alignment = EIGEN_PLAIN_ENUM_MAX(alignment0, Derived::Alignment)
|
||||
alignment0 = (bool(Evaluator::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::AlignedOnScalar)) ? int(packetAlignment) : int(Unaligned),
|
||||
alignment = EIGEN_PLAIN_ENUM_MAX(alignment0, Evaluator::Alignment)
|
||||
};
|
||||
const Index alignedStart = internal::first_default_aligned(mat.nestedExpression());
|
||||
const Index alignedStart = internal::first_default_aligned(xpr);
|
||||
const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize);
|
||||
const Index alignedSize = ((size-alignedStart)/(packetSize))*(packetSize);
|
||||
const Index alignedEnd2 = alignedStart + alignedSize2;
|
||||
@@ -230,34 +248,34 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
|
||||
Scalar res;
|
||||
if(alignedSize)
|
||||
{
|
||||
PacketScalar packet_res0 = mat.template packet<alignment,PacketScalar>(alignedStart);
|
||||
PacketScalar packet_res0 = eval.template packet<alignment,PacketScalar>(alignedStart);
|
||||
if(alignedSize>packetSize) // we have at least two packets to partly unroll the loop
|
||||
{
|
||||
PacketScalar packet_res1 = mat.template packet<alignment,PacketScalar>(alignedStart+packetSize);
|
||||
PacketScalar packet_res1 = eval.template packet<alignment,PacketScalar>(alignedStart+packetSize);
|
||||
for(Index index = alignedStart + 2*packetSize; index < alignedEnd2; index += 2*packetSize)
|
||||
{
|
||||
packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment,PacketScalar>(index));
|
||||
packet_res1 = func.packetOp(packet_res1, mat.template packet<alignment,PacketScalar>(index+packetSize));
|
||||
packet_res0 = func.packetOp(packet_res0, eval.template packet<alignment,PacketScalar>(index));
|
||||
packet_res1 = func.packetOp(packet_res1, eval.template packet<alignment,PacketScalar>(index+packetSize));
|
||||
}
|
||||
|
||||
packet_res0 = func.packetOp(packet_res0,packet_res1);
|
||||
if(alignedEnd>alignedEnd2)
|
||||
packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment,PacketScalar>(alignedEnd2));
|
||||
packet_res0 = func.packetOp(packet_res0, eval.template packet<alignment,PacketScalar>(alignedEnd2));
|
||||
}
|
||||
res = func.predux(packet_res0);
|
||||
|
||||
for(Index index = 0; index < alignedStart; ++index)
|
||||
res = func(res,mat.coeff(index));
|
||||
res = func(res,eval.coeff(index));
|
||||
|
||||
for(Index index = alignedEnd; index < size; ++index)
|
||||
res = func(res,mat.coeff(index));
|
||||
res = func(res,eval.coeff(index));
|
||||
}
|
||||
else // too small to vectorize anything.
|
||||
// since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
|
||||
{
|
||||
res = mat.coeff(0);
|
||||
res = eval.coeff(0);
|
||||
for(Index index = 1; index < size; ++index)
|
||||
res = func(res,mat.coeff(index));
|
||||
res = func(res,eval.coeff(index));
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -265,130 +283,108 @@ struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
|
||||
};
|
||||
|
||||
// NOTE: for SliceVectorizedTraversal we simply bypass unrolling
|
||||
template<typename Func, typename Derived, int Unrolling>
|
||||
struct redux_impl<Func, Derived, SliceVectorizedTraversal, Unrolling>
|
||||
template<typename Func, typename Evaluator, int Unrolling>
|
||||
struct redux_impl<Func, Evaluator, SliceVectorizedTraversal, Unrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Derived>::PacketType PacketType;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
typedef typename redux_traits<Func, Evaluator>::PacketType PacketType;
|
||||
|
||||
EIGEN_DEVICE_FUNC static Scalar run(const Derived &mat, const Func& func)
|
||||
template<typename XprType>
|
||||
EIGEN_DEVICE_FUNC static Scalar run(const Evaluator &eval, const Func& func, const XprType& xpr)
|
||||
{
|
||||
eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
|
||||
const Index innerSize = mat.innerSize();
|
||||
const Index outerSize = mat.outerSize();
|
||||
eigen_assert(xpr.rows()>0 && xpr.cols()>0 && "you are using an empty matrix");
|
||||
const Index innerSize = xpr.innerSize();
|
||||
const Index outerSize = xpr.outerSize();
|
||||
enum {
|
||||
packetSize = redux_traits<Func, Derived>::PacketSize
|
||||
packetSize = redux_traits<Func, Evaluator>::PacketSize
|
||||
};
|
||||
const Index packetedInnerSize = ((innerSize)/packetSize)*packetSize;
|
||||
Scalar res;
|
||||
if(packetedInnerSize)
|
||||
{
|
||||
PacketType packet_res = mat.template packet<Unaligned,PacketType>(0,0);
|
||||
PacketType packet_res = eval.template packet<Unaligned,PacketType>(0,0);
|
||||
for(Index j=0; j<outerSize; ++j)
|
||||
for(Index i=(j==0?packetSize:0); i<packetedInnerSize; i+=Index(packetSize))
|
||||
packet_res = func.packetOp(packet_res, mat.template packetByOuterInner<Unaligned,PacketType>(j,i));
|
||||
packet_res = func.packetOp(packet_res, eval.template packetByOuterInner<Unaligned,PacketType>(j,i));
|
||||
|
||||
res = func.predux(packet_res);
|
||||
for(Index j=0; j<outerSize; ++j)
|
||||
for(Index i=packetedInnerSize; i<innerSize; ++i)
|
||||
res = func(res, mat.coeffByOuterInner(j,i));
|
||||
res = func(res, eval.coeffByOuterInner(j,i));
|
||||
}
|
||||
else // too small to vectorize anything.
|
||||
// since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
|
||||
{
|
||||
res = redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>::run(mat, func);
|
||||
res = redux_impl<Func, Evaluator, DefaultTraversal, NoUnrolling>::run(eval, func, xpr);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Func, typename Derived>
|
||||
struct redux_impl<Func, Derived, LinearVectorizedTraversal, CompleteUnrolling>
|
||||
template<typename Func, typename Evaluator>
|
||||
struct redux_impl<Func, Evaluator, LinearVectorizedTraversal, CompleteUnrolling>
|
||||
{
|
||||
typedef typename Derived::Scalar Scalar;
|
||||
typedef typename Evaluator::Scalar Scalar;
|
||||
|
||||
typedef typename redux_traits<Func, Derived>::PacketType PacketScalar;
|
||||
typedef typename redux_traits<Func, Evaluator>::PacketType PacketType;
|
||||
enum {
|
||||
PacketSize = redux_traits<Func, Derived>::PacketSize,
|
||||
Size = Derived::SizeAtCompileTime,
|
||||
VectorizedSize = (Size / PacketSize) * PacketSize
|
||||
PacketSize = redux_traits<Func, Evaluator>::PacketSize,
|
||||
Size = Evaluator::SizeAtCompileTime,
|
||||
VectorizedSize = (int(Size) / int(PacketSize)) * int(PacketSize)
|
||||
};
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func)
|
||||
|
||||
template<typename XprType>
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE
|
||||
Scalar run(const Evaluator &eval, const Func& func, const XprType &xpr)
|
||||
{
|
||||
eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(xpr)
|
||||
eigen_assert(xpr.rows()>0 && xpr.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, Evaluator, 0, Size / PacketSize>::template run<PacketType>(eval,func));
|
||||
if (VectorizedSize != Size)
|
||||
res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
|
||||
res = func(res,redux_novec_unroller<Func, Evaluator, VectorizedSize, Size-VectorizedSize>::run(eval,func));
|
||||
return res;
|
||||
}
|
||||
else {
|
||||
return redux_novec_unroller<Func, Derived, 0, Size>::run(mat,func);
|
||||
return redux_novec_unroller<Func, Evaluator, 0, Size>::run(eval,func);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// evaluator adaptor
|
||||
template<typename _XprType>
|
||||
class redux_evaluator
|
||||
class redux_evaluator : public internal::evaluator<_XprType>
|
||||
{
|
||||
typedef internal::evaluator<_XprType> Base;
|
||||
public:
|
||||
typedef _XprType XprType;
|
||||
EIGEN_DEVICE_FUNC explicit redux_evaluator(const XprType &xpr) : m_evaluator(xpr), m_xpr(xpr) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
explicit redux_evaluator(const XprType &xpr) : Base(xpr) {}
|
||||
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
typedef typename XprType::PacketScalar PacketScalar;
|
||||
typedef typename XprType::PacketReturnType PacketReturnType;
|
||||
|
||||
enum {
|
||||
MaxRowsAtCompileTime = XprType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = XprType::MaxColsAtCompileTime,
|
||||
// TODO we should not remove DirectAccessBit and rather find an elegant way to query the alignment offset at runtime from the evaluator
|
||||
Flags = evaluator<XprType>::Flags & ~DirectAccessBit,
|
||||
Flags = Base::Flags & ~DirectAccessBit,
|
||||
IsRowMajor = XprType::IsRowMajor,
|
||||
SizeAtCompileTime = XprType::SizeAtCompileTime,
|
||||
InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime,
|
||||
CoeffReadCost = evaluator<XprType>::CoeffReadCost,
|
||||
Alignment = evaluator<XprType>::Alignment
|
||||
InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC Index rows() const { return m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC Index cols() const { return m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC Index size() const { return m_xpr.size(); }
|
||||
EIGEN_DEVICE_FUNC Index innerSize() const { return m_xpr.innerSize(); }
|
||||
EIGEN_DEVICE_FUNC Index outerSize() const { return m_xpr.outerSize(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{ return m_evaluator.coeff(row, col); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{ return m_evaluator.coeff(index); }
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
PacketType packet(Index row, Index col) const
|
||||
{ return m_evaluator.template packet<LoadMode,PacketType>(row, col); }
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
PacketType packet(Index index) const
|
||||
{ return m_evaluator.template packet<LoadMode,PacketType>(index); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeffByOuterInner(Index outer, Index inner) const
|
||||
{ return m_evaluator.coeff(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
|
||||
{ return Base::coeff(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
PacketType packetByOuterInner(Index outer, Index inner) const
|
||||
{ return m_evaluator.template packet<LoadMode,PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
|
||||
{ return Base::template packet<LoadMode,PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
|
||||
|
||||
const XprType & nestedExpression() const { return m_xpr; }
|
||||
|
||||
protected:
|
||||
internal::evaluator<XprType> m_evaluator;
|
||||
const XprType &m_xpr;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
@@ -403,39 +399,53 @@ protected:
|
||||
* The template parameter \a BinaryOp is the type of the functor \a func which must be
|
||||
* an associative operator. Both current C++98 and C++11 functor styles are handled.
|
||||
*
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*
|
||||
* \sa DenseBase::sum(), DenseBase::minCoeff(), DenseBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename Func>
|
||||
typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::redux(const Func& func) const
|
||||
{
|
||||
eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
|
||||
|
||||
typedef typename internal::redux_evaluator<Derived> ThisEvaluator;
|
||||
ThisEvaluator thisEval(derived());
|
||||
|
||||
return internal::redux_impl<Func, ThisEvaluator>::run(thisEval, func);
|
||||
|
||||
// The initial expression is passed to the reducer as an additional argument instead of
|
||||
// passing it as a member of redux_evaluator to help
|
||||
return internal::redux_impl<Func, ThisEvaluator>::run(thisEval, func, derived());
|
||||
}
|
||||
|
||||
/** \returns the minimum of all coefficients of \c *this.
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is minimum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
template<int NaNPropagation>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::minCoeff() const
|
||||
{
|
||||
return derived().redux(Eigen::internal::scalar_min_op<Scalar,Scalar>());
|
||||
return derived().redux(Eigen::internal::scalar_min_op<Scalar,Scalar, NaNPropagation>());
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of \c *this.
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
/** \returns the maximum of all coefficients of \c *this.
|
||||
* In case \c *this contains NaN, NaNPropagation determines the behavior:
|
||||
* NaNPropagation == PropagateFast : undefined
|
||||
* NaNPropagation == PropagateNaN : result is NaN
|
||||
* NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
|
||||
* \warning the matrix must be not empty, otherwise an assertion is triggered.
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
template<int NaNPropagation>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::maxCoeff() const
|
||||
{
|
||||
return derived().redux(Eigen::internal::scalar_max_op<Scalar,Scalar>());
|
||||
return derived().redux(Eigen::internal::scalar_max_op<Scalar,Scalar, NaNPropagation>());
|
||||
}
|
||||
|
||||
/** \returns the sum of all coefficients of \c *this
|
||||
@@ -445,7 +455,7 @@ DenseBase<Derived>::maxCoeff() const
|
||||
* \sa trace(), prod(), mean()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::sum() const
|
||||
{
|
||||
if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
|
||||
@@ -458,7 +468,7 @@ DenseBase<Derived>::sum() const
|
||||
* \sa trace(), prod(), sum()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::mean() const
|
||||
{
|
||||
#ifdef __INTEL_COMPILER
|
||||
@@ -479,7 +489,7 @@ DenseBase<Derived>::mean() const
|
||||
* \sa sum(), mean(), trace()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
DenseBase<Derived>::prod() const
|
||||
{
|
||||
if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
|
||||
@@ -494,7 +504,7 @@ DenseBase<Derived>::prod() const
|
||||
* \sa diagonal(), sum()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
|
||||
MatrixBase<Derived>::trace() const
|
||||
{
|
||||
return derived().diagonal().sum();
|
||||
|
||||
+121
-21
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_REF_H
|
||||
#define EIGEN_REF_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -28,12 +28,13 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
||||
|
||||
template<typename Derived> struct match {
|
||||
enum {
|
||||
IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime,
|
||||
HasDirectAccess = internal::has_direct_access<Derived>::ret,
|
||||
StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
|
||||
StorageOrderMatch = 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
|
||||
OuterStrideMatch = IsVectorAtCompileTime
|
||||
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
||||
// NOTE, this indirection of evaluator<Derived>::Alignment is needed
|
||||
// to workaround a very strange bug in MSVC related to the instantiation
|
||||
@@ -47,7 +48,7 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
||||
};
|
||||
typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
@@ -66,12 +67,12 @@ public:
|
||||
typedef MapBase<Derived> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const
|
||||
{
|
||||
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const
|
||||
{
|
||||
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
|
||||
: IsVectorAtCompileTime ? this->size()
|
||||
@@ -85,34 +86,122 @@ public:
|
||||
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;
|
||||
|
||||
// Resolves inner stride if default 0.
|
||||
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveInnerStride(Index inner) {
|
||||
return inner == 0 ? 1 : inner;
|
||||
}
|
||||
|
||||
// Resolves outer stride if default 0.
|
||||
static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols, bool isVectorAtCompileTime, bool isRowMajor) {
|
||||
return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols : isRowMajor ? inner * cols : inner * rows : outer;
|
||||
}
|
||||
|
||||
// Returns true if construction is valid, false if there is a stride mismatch,
|
||||
// and fails if there is a size mismatch.
|
||||
template<typename Expression>
|
||||
EIGEN_DEVICE_FUNC void construct(Expression& expr)
|
||||
EIGEN_DEVICE_FUNC bool construct(Expression& expr)
|
||||
{
|
||||
// Check matrix sizes. If this is a compile-time vector, we do allow
|
||||
// implicitly transposing.
|
||||
EIGEN_STATIC_ASSERT(
|
||||
EIGEN_PREDICATE_SAME_MATRIX_SIZE(PlainObjectType, Expression)
|
||||
// If it is a vector, the transpose sizes might match.
|
||||
|| ( PlainObjectType::IsVectorAtCompileTime
|
||||
&& ((int(PlainObjectType::RowsAtCompileTime)==Eigen::Dynamic
|
||||
|| int(Expression::ColsAtCompileTime)==Eigen::Dynamic
|
||||
|| int(PlainObjectType::RowsAtCompileTime)==int(Expression::ColsAtCompileTime))
|
||||
&& (int(PlainObjectType::ColsAtCompileTime)==Eigen::Dynamic
|
||||
|| int(Expression::RowsAtCompileTime)==Eigen::Dynamic
|
||||
|| int(PlainObjectType::ColsAtCompileTime)==int(Expression::RowsAtCompileTime)))),
|
||||
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
|
||||
)
|
||||
|
||||
// Determine runtime rows and columns.
|
||||
Index rows = expr.rows();
|
||||
Index cols = expr.cols();
|
||||
if(PlainObjectType::RowsAtCompileTime==1)
|
||||
{
|
||||
eigen_assert(expr.rows()==1 || expr.cols()==1);
|
||||
::new (static_cast<Base*>(this)) Base(expr.data(), 1, expr.size());
|
||||
rows = 1;
|
||||
cols = 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);
|
||||
rows = expr.size();
|
||||
cols = 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());
|
||||
// Verify that the sizes are valid.
|
||||
eigen_assert(
|
||||
(PlainObjectType::RowsAtCompileTime == Dynamic) || (PlainObjectType::RowsAtCompileTime == rows));
|
||||
eigen_assert(
|
||||
(PlainObjectType::ColsAtCompileTime == Dynamic) || (PlainObjectType::ColsAtCompileTime == cols));
|
||||
|
||||
|
||||
// If this is a vector, we might be transposing, which means that stride should swap.
|
||||
const bool transpose = PlainObjectType::IsVectorAtCompileTime && (rows != expr.rows());
|
||||
// If the storage format differs, we also need to swap the stride.
|
||||
const bool row_major = ((PlainObjectType::Flags)&RowMajorBit) != 0;
|
||||
const bool expr_row_major = (Expression::Flags&RowMajorBit) != 0;
|
||||
const bool storage_differs = (row_major != expr_row_major);
|
||||
|
||||
const bool swap_stride = (transpose != storage_differs);
|
||||
|
||||
// Determine expr's actual strides, resolving any defaults if zero.
|
||||
const Index expr_inner_actual = resolveInnerStride(expr.innerStride());
|
||||
const Index expr_outer_actual = resolveOuterStride(expr_inner_actual,
|
||||
expr.outerStride(),
|
||||
expr.rows(),
|
||||
expr.cols(),
|
||||
Expression::IsVectorAtCompileTime != 0,
|
||||
expr_row_major);
|
||||
|
||||
// If this is a column-major row vector or row-major column vector, the inner-stride
|
||||
// is arbitrary, so set it to either the compile-time inner stride or 1.
|
||||
const bool row_vector = (rows == 1);
|
||||
const bool col_vector = (cols == 1);
|
||||
const Index inner_stride =
|
||||
( (!row_major && row_vector) || (row_major && col_vector) ) ?
|
||||
( StrideType::InnerStrideAtCompileTime > 0 ? Index(StrideType::InnerStrideAtCompileTime) : 1)
|
||||
: swap_stride ? expr_outer_actual : expr_inner_actual;
|
||||
|
||||
// If this is a column-major column vector or row-major row vector, the outer-stride
|
||||
// is arbitrary, so set it to either the compile-time outer stride or vector size.
|
||||
const Index outer_stride =
|
||||
( (!row_major && col_vector) || (row_major && row_vector) ) ?
|
||||
( StrideType::OuterStrideAtCompileTime > 0 ? Index(StrideType::OuterStrideAtCompileTime) : rows * cols * inner_stride)
|
||||
: swap_stride ? expr_inner_actual : expr_outer_actual;
|
||||
|
||||
// Check if given inner/outer strides are compatible with compile-time strides.
|
||||
const bool inner_valid = (StrideType::InnerStrideAtCompileTime == Dynamic)
|
||||
|| (resolveInnerStride(Index(StrideType::InnerStrideAtCompileTime)) == inner_stride);
|
||||
if (!inner_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool outer_valid = (StrideType::OuterStrideAtCompileTime == Dynamic)
|
||||
|| (resolveOuterStride(
|
||||
inner_stride,
|
||||
Index(StrideType::OuterStrideAtCompileTime),
|
||||
rows, cols, PlainObjectType::IsVectorAtCompileTime != 0,
|
||||
row_major)
|
||||
== outer_stride);
|
||||
if (!outer_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
::new (static_cast<Base*>(this)) Base(expr.data(), rows, cols);
|
||||
::new (&m_stride) StrideBase(
|
||||
(StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride,
|
||||
(StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride );
|
||||
return true;
|
||||
}
|
||||
|
||||
StrideBase m_stride;
|
||||
@@ -184,6 +273,8 @@ protected:
|
||||
* void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); }
|
||||
* \endcode
|
||||
*
|
||||
* See also the following stackoverflow questions for further references:
|
||||
* - <a href="http://stackoverflow.com/questions/21132538/correct-usage-of-the-eigenref-class">Correct usage of the Eigen::Ref<> class</a>
|
||||
*
|
||||
* \sa PlainObjectBase::Map(), \ref TopicStorageOrders
|
||||
*/
|
||||
@@ -207,7 +298,10 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
||||
typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||
Base::construct(expr.derived());
|
||||
// Construction must pass since we will not create temprary storage in the non-const case.
|
||||
const bool success = Base::construct(expr.derived());
|
||||
EIGEN_UNUSED_VARIABLE(success)
|
||||
eigen_assert(success);
|
||||
}
|
||||
template<typename Derived>
|
||||
EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr,
|
||||
@@ -221,7 +315,10 @@ template<typename PlainObjectType, int Options, typename StrideType> class Ref
|
||||
EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
|
||||
EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase,THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
|
||||
Base::construct(expr.const_cast_derived());
|
||||
// Construction must pass since we will not create temporary storage in the non-const case.
|
||||
const bool success = Base::construct(expr.const_cast_derived());
|
||||
EIGEN_UNUSED_VARIABLE(success)
|
||||
eigen_assert(success);
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
|
||||
@@ -262,7 +359,10 @@ template<typename TPlainObjectType, int Options, typename StrideType> class Ref<
|
||||
template<typename Expression>
|
||||
EIGEN_DEVICE_FUNC void construct(const Expression& expr,internal::true_type)
|
||||
{
|
||||
Base::construct(expr);
|
||||
// Check if we can use the underlying expr's storage directly, otherwise call the copy version.
|
||||
if (!Base::construct(expr)) {
|
||||
construct(expr, internal::false_type());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Expression>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#ifndef EIGEN_REPLICATE_H
|
||||
#define EIGEN_REPLICATE_H
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType,int RowFactor,int ColFactor>
|
||||
@@ -35,7 +35,7 @@ struct traits<Replicate<MatrixType,RowFactor,ColFactor> >
|
||||
IsRowMajor = MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1 ? 1
|
||||
: MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1 ? 0
|
||||
: (MatrixType::Flags & RowMajorBit) ? 1 : 0,
|
||||
|
||||
|
||||
// FIXME enable DirectAccess with negative strides?
|
||||
Flags = IsRowMajor ? RowMajorBit : 0
|
||||
};
|
||||
@@ -88,15 +88,15 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
|
||||
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const _MatrixTypeNested& nestedExpression() const
|
||||
{
|
||||
return m_matrix;
|
||||
{
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -115,7 +115,7 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int RowFactor, int ColFactor>
|
||||
const Replicate<Derived,RowFactor,ColFactor>
|
||||
EIGEN_DEVICE_FUNC const Replicate<Derived,RowFactor,ColFactor>
|
||||
DenseBase<Derived>::replicate() const
|
||||
{
|
||||
return Replicate<Derived,RowFactor,ColFactor>(derived());
|
||||
@@ -130,7 +130,7 @@ DenseBase<Derived>::replicate() const
|
||||
* \sa VectorwiseOp::replicate(), DenseBase::replicate(), class Replicate
|
||||
*/
|
||||
template<typename ExpressionType, int Direction>
|
||||
const typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType
|
||||
EIGEN_DEVICE_FUNC const typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType
|
||||
VectorwiseOp<ExpressionType,Direction>::replicate(Index factor) const
|
||||
{
|
||||
return typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2017 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2014 yoco <peter.xiau@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_RESHAPED_H
|
||||
#define EIGEN_RESHAPED_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \class Reshaped
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* \brief Expression of a fixed-size or dynamic-size reshape
|
||||
*
|
||||
* \tparam XprType the type of the expression in which we are taking a reshape
|
||||
* \tparam Rows the number of rows of the reshape we are taking at compile time (optional)
|
||||
* \tparam Cols the number of columns of the reshape we are taking at compile time (optional)
|
||||
* \tparam Order can be ColMajor or RowMajor, default is ColMajor.
|
||||
*
|
||||
* This class represents an expression of either a fixed-size or dynamic-size reshape.
|
||||
* It is the return type of DenseBase::reshaped(NRowsType,NColsType) and
|
||||
* most of the time this is the only way it is used.
|
||||
*
|
||||
* However, in C++98, if you want to directly maniputate reshaped expressions,
|
||||
* for instance if you want to write a function returning such an expression, you
|
||||
* will need to use this class. In C++11, it is advised to use the \em auto
|
||||
* keyword for such use cases.
|
||||
*
|
||||
* Here is an example illustrating the dynamic case:
|
||||
* \include class_Reshaped.cpp
|
||||
* Output: \verbinclude class_Reshaped.out
|
||||
*
|
||||
* Here is an example illustrating the fixed-size case:
|
||||
* \include class_FixedReshaped.cpp
|
||||
* Output: \verbinclude class_FixedReshaped.out
|
||||
*
|
||||
* \sa DenseBase::reshaped(NRowsType,NColsType)
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename XprType, int Rows, int Cols, int Order>
|
||||
struct traits<Reshaped<XprType, Rows, Cols, Order> > : traits<XprType>
|
||||
{
|
||||
typedef typename traits<XprType>::Scalar Scalar;
|
||||
typedef typename traits<XprType>::StorageKind StorageKind;
|
||||
typedef typename traits<XprType>::XprKind XprKind;
|
||||
enum{
|
||||
MatrixRows = traits<XprType>::RowsAtCompileTime,
|
||||
MatrixCols = traits<XprType>::ColsAtCompileTime,
|
||||
RowsAtCompileTime = Rows,
|
||||
ColsAtCompileTime = Cols,
|
||||
MaxRowsAtCompileTime = Rows,
|
||||
MaxColsAtCompileTime = Cols,
|
||||
XpxStorageOrder = ((int(traits<XprType>::Flags) & RowMajorBit) == RowMajorBit) ? RowMajor : ColMajor,
|
||||
ReshapedStorageOrder = (RowsAtCompileTime == 1 && ColsAtCompileTime != 1) ? RowMajor
|
||||
: (ColsAtCompileTime == 1 && RowsAtCompileTime != 1) ? ColMajor
|
||||
: XpxStorageOrder,
|
||||
HasSameStorageOrderAsXprType = (ReshapedStorageOrder == XpxStorageOrder),
|
||||
InnerSize = (ReshapedStorageOrder==int(RowMajor)) ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
|
||||
InnerStrideAtCompileTime = HasSameStorageOrderAsXprType
|
||||
? int(inner_stride_at_compile_time<XprType>::ret)
|
||||
: Dynamic,
|
||||
OuterStrideAtCompileTime = Dynamic,
|
||||
|
||||
HasDirectAccess = internal::has_direct_access<XprType>::ret
|
||||
&& (Order==int(XpxStorageOrder))
|
||||
&& ((evaluator<XprType>::Flags&LinearAccessBit)==LinearAccessBit),
|
||||
|
||||
MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
|
||||
&& (InnerStrideAtCompileTime == 1)
|
||||
? PacketAccessBit : 0,
|
||||
//MaskAlignedBit = ((OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
|
||||
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
|
||||
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
|
||||
FlagsRowMajorBit = (ReshapedStorageOrder==int(RowMajor)) ? RowMajorBit : 0,
|
||||
FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0,
|
||||
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) | MaskPacketAccessBit),
|
||||
|
||||
Flags = (Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit | FlagsDirectAccessBit)
|
||||
};
|
||||
};
|
||||
|
||||
template<typename XprType, int Rows, int Cols, int Order, bool HasDirectAccess> class ReshapedImpl_dense;
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
template<typename XprType, int Rows, int Cols, int Order, typename StorageKind> class ReshapedImpl;
|
||||
|
||||
template<typename XprType, int Rows, int Cols, int Order> class Reshaped
|
||||
: public ReshapedImpl<XprType, Rows, Cols, Order, typename internal::traits<XprType>::StorageKind>
|
||||
{
|
||||
typedef ReshapedImpl<XprType, Rows, Cols, Order, typename internal::traits<XprType>::StorageKind> Impl;
|
||||
public:
|
||||
//typedef typename Impl::Base Base;
|
||||
typedef Impl Base;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Reshaped)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reshaped)
|
||||
|
||||
/** Fixed-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Reshaped(XprType& xpr)
|
||||
: Impl(xpr)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
|
||||
eigen_assert(Rows * Cols == xpr.rows() * xpr.cols());
|
||||
}
|
||||
|
||||
/** Dynamic-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Reshaped(XprType& xpr,
|
||||
Index reshapeRows, Index reshapeCols)
|
||||
: Impl(xpr, reshapeRows, reshapeCols)
|
||||
{
|
||||
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==reshapeRows)
|
||||
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==reshapeCols));
|
||||
eigen_assert(reshapeRows * reshapeCols == xpr.rows() * xpr.cols());
|
||||
}
|
||||
};
|
||||
|
||||
// The generic default implementation for dense reshape simply forward to the internal::ReshapedImpl_dense
|
||||
// that must be specialized for direct and non-direct access...
|
||||
template<typename XprType, int Rows, int Cols, int Order>
|
||||
class ReshapedImpl<XprType, Rows, Cols, Order, Dense>
|
||||
: public internal::ReshapedImpl_dense<XprType, Rows, Cols, Order,internal::traits<Reshaped<XprType,Rows,Cols,Order> >::HasDirectAccess>
|
||||
{
|
||||
typedef internal::ReshapedImpl_dense<XprType, Rows, Cols, Order,internal::traits<Reshaped<XprType,Rows,Cols,Order> >::HasDirectAccess> Impl;
|
||||
public:
|
||||
typedef Impl Base;
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl)
|
||||
EIGEN_DEVICE_FUNC inline ReshapedImpl(XprType& xpr) : Impl(xpr) {}
|
||||
EIGEN_DEVICE_FUNC inline ReshapedImpl(XprType& xpr, Index reshapeRows, Index reshapeCols)
|
||||
: Impl(xpr, reshapeRows, reshapeCols) {}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal Internal implementation of dense Reshaped in the general case. */
|
||||
template<typename XprType, int Rows, int Cols, int Order>
|
||||
class ReshapedImpl_dense<XprType,Rows,Cols,Order,false>
|
||||
: public internal::dense_xpr_base<Reshaped<XprType, Rows, Cols, Order> >::type
|
||||
{
|
||||
typedef Reshaped<XprType, Rows, Cols, Order> ReshapedType;
|
||||
public:
|
||||
|
||||
typedef typename internal::dense_xpr_base<ReshapedType>::type Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense)
|
||||
|
||||
typedef typename internal::ref_selector<XprType>::non_const_type MatrixTypeNested;
|
||||
typedef typename internal::remove_all<XprType>::type NestedExpression;
|
||||
|
||||
class InnerIterator;
|
||||
|
||||
/** Fixed-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ReshapedImpl_dense(XprType& xpr)
|
||||
: m_xpr(xpr), m_rows(Rows), m_cols(Cols)
|
||||
{}
|
||||
|
||||
/** Dynamic-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols)
|
||||
: m_xpr(xpr), m_rows(nRows), m_cols(nCols)
|
||||
{}
|
||||
|
||||
EIGEN_DEVICE_FUNC Index rows() const { return m_rows; }
|
||||
EIGEN_DEVICE_FUNC Index cols() const { return m_cols; }
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** \sa MapBase::data() */
|
||||
EIGEN_DEVICE_FUNC inline const Scalar* data() const;
|
||||
EIGEN_DEVICE_FUNC inline Index innerStride() const;
|
||||
EIGEN_DEVICE_FUNC inline Index outerStride() const;
|
||||
#endif
|
||||
|
||||
/** \returns the nested expression */
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename internal::remove_all<XprType>::type&
|
||||
nestedExpression() const { return m_xpr; }
|
||||
|
||||
/** \returns the nested expression */
|
||||
EIGEN_DEVICE_FUNC
|
||||
typename internal::remove_reference<XprType>::type&
|
||||
nestedExpression() { return m_xpr; }
|
||||
|
||||
protected:
|
||||
|
||||
MatrixTypeNested m_xpr;
|
||||
const internal::variable_if_dynamic<Index, Rows> m_rows;
|
||||
const internal::variable_if_dynamic<Index, Cols> m_cols;
|
||||
};
|
||||
|
||||
|
||||
/** \internal Internal implementation of dense Reshaped in the direct access case. */
|
||||
template<typename XprType, int Rows, int Cols, int Order>
|
||||
class ReshapedImpl_dense<XprType, Rows, Cols, Order, true>
|
||||
: public MapBase<Reshaped<XprType, Rows, Cols, Order> >
|
||||
{
|
||||
typedef Reshaped<XprType, Rows, Cols, Order> ReshapedType;
|
||||
typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested;
|
||||
public:
|
||||
|
||||
typedef MapBase<ReshapedType> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(ReshapedType)
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ReshapedImpl_dense)
|
||||
|
||||
/** Fixed-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ReshapedImpl_dense(XprType& xpr)
|
||||
: Base(xpr.data()), m_xpr(xpr)
|
||||
{}
|
||||
|
||||
/** Dynamic-size constructor
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline ReshapedImpl_dense(XprType& xpr, Index nRows, Index nCols)
|
||||
: Base(xpr.data(), nRows, nCols),
|
||||
m_xpr(xpr)
|
||||
{}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const
|
||||
{
|
||||
return m_xpr;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
XprType& nestedExpression() { return m_xpr; }
|
||||
|
||||
/** \sa MapBase::innerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index innerStride() const
|
||||
{
|
||||
return m_xpr.innerStride();
|
||||
}
|
||||
|
||||
/** \sa MapBase::outerStride() */
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index outerStride() const
|
||||
{
|
||||
return ((Flags&RowMajorBit)==RowMajorBit) ? this->cols() : this->rows();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
XprTypeNested m_xpr;
|
||||
};
|
||||
|
||||
// Evaluators
|
||||
template<typename ArgType, int Rows, int Cols, int Order, bool HasDirectAccess> struct reshaped_evaluator;
|
||||
|
||||
template<typename ArgType, int Rows, int Cols, int Order>
|
||||
struct evaluator<Reshaped<ArgType, Rows, Cols, Order> >
|
||||
: reshaped_evaluator<ArgType, Rows, Cols, Order, traits<Reshaped<ArgType,Rows,Cols,Order> >::HasDirectAccess>
|
||||
{
|
||||
typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
// TODO: should check for smaller packet types
|
||||
typedef typename packet_traits<Scalar>::type PacketScalar;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
|
||||
HasDirectAccess = traits<XprType>::HasDirectAccess,
|
||||
|
||||
// RowsAtCompileTime = traits<XprType>::RowsAtCompileTime,
|
||||
// ColsAtCompileTime = traits<XprType>::ColsAtCompileTime,
|
||||
// MaxRowsAtCompileTime = traits<XprType>::MaxRowsAtCompileTime,
|
||||
// MaxColsAtCompileTime = traits<XprType>::MaxColsAtCompileTime,
|
||||
//
|
||||
// InnerStrideAtCompileTime = traits<XprType>::HasSameStorageOrderAsXprType
|
||||
// ? int(inner_stride_at_compile_time<ArgType>::ret)
|
||||
// : Dynamic,
|
||||
// OuterStrideAtCompileTime = Dynamic,
|
||||
|
||||
FlagsLinearAccessBit = (traits<XprType>::RowsAtCompileTime == 1 || traits<XprType>::ColsAtCompileTime == 1 || HasDirectAccess) ? LinearAccessBit : 0,
|
||||
FlagsRowMajorBit = (traits<XprType>::ReshapedStorageOrder==int(RowMajor)) ? RowMajorBit : 0,
|
||||
FlagsDirectAccessBit = HasDirectAccess ? DirectAccessBit : 0,
|
||||
Flags0 = evaluator<ArgType>::Flags & (HereditaryBits & ~RowMajorBit),
|
||||
Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit | FlagsDirectAccessBit,
|
||||
|
||||
PacketAlignment = unpacket_traits<PacketScalar>::alignment,
|
||||
Alignment = evaluator<ArgType>::Alignment
|
||||
};
|
||||
typedef reshaped_evaluator<ArgType, Rows, Cols, Order, HasDirectAccess> reshaped_evaluator_type;
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : reshaped_evaluator_type(xpr)
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ArgType, int Rows, int Cols, int Order>
|
||||
struct reshaped_evaluator<ArgType, Rows, Cols, Order, /* HasDirectAccess */ false>
|
||||
: evaluator_base<Reshaped<ArgType, Rows, Cols, Order> >
|
||||
{
|
||||
typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
|
||||
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of index computations */,
|
||||
|
||||
Flags = (evaluator<ArgType>::Flags & (HereditaryBits /*| LinearAccessBit | DirectAccessBit*/)),
|
||||
|
||||
Alignment = 0
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit reshaped_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_xpr(xpr)
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
typedef std::pair<Index, Index> RowCol;
|
||||
|
||||
inline RowCol index_remap(Index rowId, Index colId) const
|
||||
{
|
||||
if(Order==ColMajor)
|
||||
{
|
||||
const Index nth_elem_idx = colId * m_xpr.rows() + rowId;
|
||||
return RowCol(nth_elem_idx % m_xpr.nestedExpression().rows(),
|
||||
nth_elem_idx / m_xpr.nestedExpression().rows());
|
||||
}
|
||||
else
|
||||
{
|
||||
const Index nth_elem_idx = colId + rowId * m_xpr.cols();
|
||||
return RowCol(nth_elem_idx / m_xpr.nestedExpression().cols(),
|
||||
nth_elem_idx % m_xpr.nestedExpression().cols());
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index rowId, Index colId)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_LVALUE(XprType)
|
||||
const RowCol row_col = index_remap(rowId, colId);
|
||||
return m_argImpl.coeffRef(row_col.first, row_col.second);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index rowId, Index colId) const
|
||||
{
|
||||
const RowCol row_col = index_remap(rowId, colId);
|
||||
return m_argImpl.coeffRef(row_col.first, row_col.second);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const
|
||||
{
|
||||
const RowCol row_col = index_remap(rowId, colId);
|
||||
return m_argImpl.coeff(row_col.first, row_col.second);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Scalar& coeffRef(Index index)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_LVALUE(XprType)
|
||||
const RowCol row_col = index_remap(Rows == 1 ? 0 : index,
|
||||
Rows == 1 ? index : 0);
|
||||
return m_argImpl.coeffRef(row_col.first, row_col.second);
|
||||
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const Scalar& coeffRef(Index index) const
|
||||
{
|
||||
const RowCol row_col = index_remap(Rows == 1 ? 0 : index,
|
||||
Rows == 1 ? index : 0);
|
||||
return m_argImpl.coeffRef(row_col.first, row_col.second);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
const RowCol row_col = index_remap(Rows == 1 ? 0 : index,
|
||||
Rows == 1 ? index : 0);
|
||||
return m_argImpl.coeff(row_col.first, row_col.second);
|
||||
}
|
||||
#if 0
|
||||
EIGEN_DEVICE_FUNC
|
||||
template<int LoadMode>
|
||||
inline PacketScalar packet(Index rowId, Index colId) const
|
||||
{
|
||||
const RowCol row_col = index_remap(rowId, colId);
|
||||
return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second);
|
||||
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
|
||||
{
|
||||
const RowCol row_col = index_remap(rowId, colId);
|
||||
m_argImpl.const_cast_derived().template writePacket<Unaligned>
|
||||
(row_col.first, row_col.second, val);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline PacketScalar packet(Index index) const
|
||||
{
|
||||
const RowCol row_col = index_remap(RowsAtCompileTime == 1 ? 0 : index,
|
||||
RowsAtCompileTime == 1 ? index : 0);
|
||||
return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void writePacket(Index index, const PacketScalar& val)
|
||||
{
|
||||
const RowCol row_col = index_remap(RowsAtCompileTime == 1 ? 0 : index,
|
||||
RowsAtCompileTime == 1 ? index : 0);
|
||||
return m_argImpl.template packet<Unaligned>(row_col.first, row_col.second, val);
|
||||
}
|
||||
#endif
|
||||
protected:
|
||||
|
||||
evaluator<ArgType> m_argImpl;
|
||||
const XprType& m_xpr;
|
||||
|
||||
};
|
||||
|
||||
template<typename ArgType, int Rows, int Cols, int Order>
|
||||
struct reshaped_evaluator<ArgType, Rows, Cols, Order, /* HasDirectAccess */ true>
|
||||
: mapbase_evaluator<Reshaped<ArgType, Rows, Cols, Order>,
|
||||
typename Reshaped<ArgType, Rows, Cols, Order>::PlainObject>
|
||||
{
|
||||
typedef Reshaped<ArgType, Rows, Cols, Order> XprType;
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit reshaped_evaluator(const XprType& xpr)
|
||||
: mapbase_evaluator<XprType, typename XprType::PlainObject>(xpr)
|
||||
{
|
||||
// TODO: for the 3.4 release, this should be turned to an internal assertion, but let's keep it as is for the beta lifetime
|
||||
eigen_assert(((internal::UIntPtr(xpr.data()) % EIGEN_PLAIN_ENUM_MAX(1,evaluator<XprType>::Alignment)) == 0) && "data is not aligned");
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_RESHAPED_H
|
||||
@@ -60,8 +60,10 @@ template<typename Derived> class ReturnByValue
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline void evalTo(Dest& dst) const
|
||||
{ static_cast<const Derived*>(this)->evalTo(dst); }
|
||||
EIGEN_DEVICE_FUNC 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(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index rows() const EIGEN_NOEXCEPT { return static_cast<const Derived*>(this)->rows(); }
|
||||
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
|
||||
inline Index cols() const EIGEN_NOEXCEPT { return static_cast<const Derived*>(this)->cols(); }
|
||||
|
||||
#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
|
||||
@@ -79,7 +81,7 @@ template<typename Derived> class ReturnByValue
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
||||
EIGEN_DEVICE_FUNC Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
||||
{
|
||||
other.evalTo(derived());
|
||||
return derived();
|
||||
@@ -90,7 +92,7 @@ namespace internal {
|
||||
// Expression is evaluated in a temporary; default implementation of Assignment is bypassed so that
|
||||
// when a ReturnByValue expression is assigned, the evaluator is not constructed.
|
||||
// TODO: Finalize port to new regime; ReturnByValue should not exist in the expression world
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
struct evaluator<ReturnByValue<Derived> >
|
||||
: public evaluator<typename internal::traits<Derived>::ReturnType>
|
||||
@@ -98,7 +100,7 @@ struct evaluator<ReturnByValue<Derived> >
|
||||
typedef ReturnByValue<Derived> XprType;
|
||||
typedef typename internal::traits<Derived>::ReturnType PlainObject;
|
||||
typedef evaluator<PlainObject> Base;
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
|
||||
: m_result(xpr.rows(), xpr.cols())
|
||||
{
|
||||
|
||||
Loaded 100 of 399 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user