Compare commits

..

54 Commits

Author SHA1 Message Date
a2a7ca6aa1 SLIM: Fix uppercase folder name in CMake file 2018-05-27 19:46:34 +02:00
bbfee34e9e Merge remote-tracking branch 'origin/master' into uv_unwrapping_slim_algorithm 2018-05-01 17:03:20 +02:00
Aurel Gruber
ae7b679021 SLIM: disallowing pins to move to places that the SLIM algorithm can't handle. Also, this simplifiey the way we transfer uv coords back to native part. 2017-04-13 16:33:11 +02:00
Aurel Gruber
3cae116704 SLIM: In live Unwrap mode unpinned vertices can now be moved. Also, a single pin also invokes SLIM. That also avoids crashing minimize_stretch when invoked on chart with one pin. 2017-04-13 16:22:49 +02:00
58caf3121e SLIM: reuse LSCM logic for pinning, to fix issue with multiple charts. 2017-03-25 16:55:59 +01:00
183ca1af3f SLIM: move most SLIM integration behind param_* API, reuse more code. 2017-03-25 16:55:24 +01:00
bf2603baf6 SLIM: transfer weights in construction, fix subsurf case. 2017-03-25 16:37:58 +01:00
2e662bbca4 SLIM: use operator history instead of toolsettings for remembering settings. 2017-03-25 16:37:58 +01:00
21bccefd12 SLIM: move code around, no functional changes. 2017-03-25 16:37:33 +01:00
65f32e105f SLIM: match code style. 2017-03-25 14:18:04 +01:00
Aurel Gruber
9fdc5345cd merging master into release 2017-03-23 16:44:22 +01:00
Aurel Gruber
0475c0c41e UV Unwrapping SLIM reducing SLIM iterations per live-unwrap-step to 3, taking care of memory leaks, removing packing when minimizi-stretch with non-fix border 2017-03-16 11:08:02 +01:00
Aurel Gruber
be22fc6720 Merge branch 'live_unwrap' 2017-03-15 16:44:39 +01:00
Aurel Gruber
92d7b4b1c2 merging in master 2017-03-15 16:39:37 +01:00
AurelGruber
c1a242ab58 Merge branch 'slim' into 'master'
Slim

See merge request !3
2017-03-15 15:36:00 +00:00
Aurel Gruber
47e71e8746 taking care of compiler warnings 2017-03-15 16:33:38 +01:00
Aurel Gruber
e4e202cb1c UV Unwrapping SLIM Changing ui parameter names and showing parameters based on method 2017-03-15 16:06:40 +01:00
Aurel Gruber
7b59b53938 UV Unwrapping SLIM adding liveUnwrap with slim 2017-03-15 14:16:13 +01:00
Aurel Gruber
dbe69d982f UV Unwrapping SLIM: small bugfixes and putting char array and not just pointer into toolsettings for vertexgroupname 2017-03-14 09:37:00 +01:00
Aurel Gruber
968f1c0de3 UV Unwrapping SLIM: reordering functino definitions to remove prototypes and cleaning header files 2017-03-14 09:37:00 +01:00
Aurel Gruber
901f02b8ec UV Unwrapping SLIM: removing remainder of old minimize stretch 2017-03-14 09:37:00 +01:00
Aurel Gruber
2a76f4ea7d UV Unwrapping SLIM: space added after if 2017-03-14 09:37:00 +01:00
Aurel Gruber
c9b3e34b9a UV Unwrapping SLIM: minimize_stretch now only affects selected vertices. RESPECTS user defined pins! 2017-03-14 09:37:00 +01:00
Aurel Gruber
f5b51e4c65 UV Unwrapping SLIM: removing unnecessary ui parameters from minimize_stretch_operator 2017-03-14 09:37:00 +01:00
Aurel Gruber
c603ba9e7c UV Unwrapping SLIM: renaming slim_c_interface to slim_capi and renaming contained functions 2017-03-14 09:36:59 +01:00
Aurel Gruber
eef1392c47 UV Unwrapping SLIM: renaming src to intern 2017-03-14 09:36:59 +01:00
Aurel Gruber
c35c83a3ab UV Unwrapping SLIM: adding slim_matrix_transfer.h 2017-03-14 09:36:59 +01:00
Aurel Gruber
732159dcf8 UV Unwrapping SLIM: further refactoring according to discussion on D2530 2017-03-14 09:36:59 +01:00
Aurel Gruber
bccca31bd1 UV Unwrapping SLIM: removing old minimize stretch operator 2017-03-14 09:36:59 +01:00
Aurel Gruber
67ef01a2c3 UV Unwrapping SLIM: respecting source/blender style conventions 2017-03-14 09:36:59 +01:00
Aurel Gruber
118d63712d UV Unwrapping SLIM: removing thesis marker-comments from code 2017-03-14 09:36:59 +01:00
Aurel Gruber
3027e0bdca UV Unwrapping SLIM: adding GPL header comment 2017-03-14 09:36:59 +01:00
Aurel Gruber
99ed9041e0 UV Unwrapping SLIM: renaming another file 2017-03-14 09:36:59 +01:00
Aurel Gruber
ebae2d6aa2 UV Unwrapping SLIM: renaming files and moving headers 2017-03-14 09:36:58 +01:00
Aurel Gruber
5c4eedc91f UV Unwrapping SLIM: renaming intern/SLIM to intern/slim 2017-03-14 09:36:58 +01:00
Aurel Gruber
5681b886a0 UV Unwrapping SLIM: refactoring UVInitializer 2017-03-14 09:36:58 +01:00
Aurel Gruber
31dd611003 UV Unwrapping SLIM: adding harmonic and mvc to uvinitializer 2017-03-14 09:36:58 +01:00
Aurel Gruber
95863bbb98 Merge branch 'uv_unwrapping_slim_algorithm' of git.blender.org:blender into uv_unwrapping_slim_algorithm 2017-02-27 14:15:46 +01:00
Aurel Gruber
2f86198cee Implementation of UV unwrapping with SLIM as disdussed on T48036.
commits:

Category: UV Unwrapping SLIM Algorithm Integration

Added SLIM Subfolder

Category: UV Unwrapping SLIM Algorithm Integration

added subfolder SLIM to CMakeFile of /intern

Category: UV Unwrapping SLIM Algorithm Integration

integrating SLIM including data gathering and transfer from Blender to SLIM

This commit is huge, because I copied over the code from a different repository. Not commit-by-commit.

The Algorithm can be invoked either by choosing SLIM from the dropdown in the unwrapping settings or by
hitting ctrl. + m in the uv editor for relaxation. Tried adding it to the menu the same way as minimizing stretch is there but failed.

Category: UV Unwrapping SLIM Algorithm Integration

preserving vertex ids and gathering weights

Category: UV Unwrapping SLIM Algorithm Integration

adding more members to phandle and creating param_begin

Category: UV Unwrapping SLIM Algorithm Integration

fixing bug that causes weight-per-vertex mapping to be wrong

Category: UV Unwrapping SLIM Algorithm Integration

adjustments to the UI parameters

Category: UV Unwrapping SLIM Algorithm Integration

adding weightinfluence

Category: UV Unwrapping SLIM Algorithm Integration

slim interactive exec now only for changing parameters

Category: UV Unwrapping SLIM Algorithm Integration

taking care of memory leaks

Category: UV Unwrapping SLIM Algorithm Integration

adding relative scale, reflection mode and Vertex group input

Category: UV Unwrapping SLIM Algorithm Integration

correcting wrong comment on SLIM phases

Category: UV Unwrapping SLIM Algorithm Integration

Adding SLIM code by means of git read-tree

Category: UV Unwrapping SLIM Algorithm Integration

freeing matrix_transfer properly

Category: UV Unwrapping SLIM Algorithm Integration

adding (unsupported-) eigen files

Reviewers: brecht, sergey

Differential Revision: https://developer.blender.org/D2530
2017-02-27 14:04:24 +01:00
Aurel Gruber
16c6c8a1c4 Category: UV Unwrapping SLIM Algorithm Integration
adding (unsupported-) eigen files
2017-02-24 09:31:38 +01:00
Aurel Gruber
1cb016491a Category: UV Unwrapping SLIM Algorithm Integration
freeing matrix_transfer properly
2017-02-24 09:28:33 +01:00
Aurel Gruber
7e2e77714c Category: UV Unwrapping SLIM Algorithm Integration
Adding SLIM code by means of git read-tree
2017-02-23 16:34:16 +01:00
Aurel Gruber
15785145b1 Category: UV Unwrapping SLIM Algorithm Integration
correcting wrong comment on SLIM phases
2017-02-23 16:34:16 +01:00
Aurel Gruber
26fd7e084f Category: UV Unwrapping SLIM Algorithm Integration
adding relative scale, reflection mode and Vertex group input
2017-02-23 16:34:16 +01:00
Aurel Gruber
88a327d3ed Category: UV Unwrapping SLIM Algorithm Integration
taking care of memory leaks
2017-02-23 16:34:16 +01:00
Aurel Gruber
2bf059ad3b Category: UV Unwrapping SLIM Algorithm Integration
slim interactive exec now only for changing parameters
2017-02-23 16:34:16 +01:00
Aurel Gruber
9c55a8374e Category: UV Unwrapping SLIM Algorithm Integration
adding weightinfluence
2017-02-23 16:34:16 +01:00
Aurel Gruber
1f88850826 Category: UV Unwrapping SLIM Algorithm Integration
adjustments to the UI parameters
2017-02-23 16:34:16 +01:00
Aurel Gruber
9f7c4aa581 Category: UV Unwrapping SLIM Algorithm Integration
fixing bug that causes weight-per-vertex mapping to be wrong
2017-02-23 16:34:16 +01:00
Aurel Gruber
3e184a57c5 Category: UV Unwrapping SLIM Algorithm Integration
adding more members to phandle and creating param_begin
2017-02-23 16:34:16 +01:00
Aurel Gruber
b6ab20876b Category: UV Unwrapping SLIM Algorithm Integration
preserving vertex ids and gathering weights
2017-02-23 16:34:16 +01:00
Aurel Gruber
08d1b312be Category: UV Unwrapping SLIM Algorithm Integration
integrating SLIM including data gathering and transfer from Blender to SLIM

This commit is huge, because I copied over the code from a different repository. Not commit-by-commit.

The Algorithm can be invoked either by choosing SLIM from the dropdown in the unwrapping settings or by
hitting ctrl. + m in the uv editor for relaxation. Tried adding it to the menu the same way as minimizing stretch is there but failed.
2017-02-23 16:34:16 +01:00
Aurel Gruber
5793441a35 Category: UV Unwrapping SLIM Algorithm Integration
added subfolder SLIM to CMakeFile of /intern
2017-02-23 16:34:16 +01:00
Aurel Gruber
979b1b1159 Category: UV Unwrapping SLIM Algorithm Integration
Added SLIM Subfolder
2017-02-23 16:34:16 +01:00
3167 changed files with 94122 additions and 72996 deletions

View File

@@ -1,44 +0,0 @@
# C/C++
[*.{c,cc,h,hh,inl,glsl}]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4
max_line_length = 120
# CMake & Text
[*.{cmake,txt}]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4
max_line_length = 120
# Python
[*.py]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
max_line_length = 120
# Shell
[*.sh]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4
max_line_length = 120
# reStructuredText
[*.rst]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 3
max_line_length = 120

View File

@@ -66,12 +66,21 @@ endif()
# set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
# global compile definitions since add_definitions() adds for all.
if(NOT (${CMAKE_VERSION} VERSION_LESS 3.0))
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS
$<$<CONFIG:Debug>:DEBUG;_DEBUG>
$<$<CONFIG:Release>:NDEBUG>
$<$<CONFIG:MinSizeRel>:NDEBUG>
$<$<CONFIG:RelWithDebInfo>:NDEBUG>
)
else()
# keep until CMake-3.0 is min requirement
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG _DEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE NDEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL NDEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO NDEBUG)
endif()
#-----------------------------------------------------------------------------
# Set policy
@@ -444,7 +453,7 @@ mark_as_advanced(WITH_MEM_VALGRIND)
option(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation tracking (only enable for development)" OFF)
mark_as_advanced(WITH_CXX_GUARDEDALLOC)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" ON)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
mark_as_advanced(WITH_ASSERT_ABORT)
option(WITH_BOOST "Enable features depending on boost" ON)
@@ -527,49 +536,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
mark_as_advanced(WITH_LINKER_GOLD)
endif()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
mark_as_advanced(WITH_COMPILER_ASAN)
if(WITH_COMPILER_ASAN)
set(_asan_defaults "\
-fsanitize=address \
-fsanitize=bool \
-fsanitize=bounds \
-fsanitize=enum \
-fsanitize=float-cast-overflow \
-fsanitize=float-divide-by-zero \
-fsanitize=nonnull-attribute \
-fsanitize=returns-nonnull-attribute \
-fsanitize=signed-integer-overflow \
-fsanitize=undefined \
-fsanitize=vla-bound \
-fno-sanitize=alignment \
")
if(NOT MSVC) # not all sanitizers are supported with clang-cl, these two however are very vocal about it
set(_asan_defaults "${_asan_defaults} -fsanitize=leak -fsanitize=object-size" )
endif()
set(COMPILER_ASAN_CFLAGS "${_asan_defaults}" CACHE STRING "C flags for address sanitizer")
mark_as_advanced(COMPILER_ASAN_CFLAGS)
set(COMPILER_ASAN_CXXFLAGS "${_asan_defaults}" CACHE STRING "C++ flags for address sanitizer")
mark_as_advanced(COMPILER_ASAN_CXXFLAGS)
unset(_asan_defaults)
if(NOT MSVC)
find_library(COMPILER_ASAN_LIBRARY asan ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
else()
find_library( COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
endif()
mark_as_advanced(COMPILER_ASAN_LIBRARY)
endif()
endif()
# Dependency graph
option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON)
mark_as_advanced(WITH_LEGACY_DEPSGRAPH)
@@ -638,12 +604,10 @@ endif()
if(NOT WITH_AUDASPACE)
if(WITH_OPENAL)
message(WARNING "WITH_OPENAL requires WITH_AUDASPACE which is disabled")
set(WITH_OPENAL OFF)
message(FATAL_ERROR "WITH_OPENAL requires WITH_AUDASPACE")
endif()
if(WITH_JACK)
message(WARNING "WITH_JACK requires WITH_AUDASPACE which is disabled")
set(WITH_JACK OFF)
message(FATAL_ERROR "WITH_JACK requires WITH_AUDASPACE")
endif()
if(WITH_GAMEENGINE)
message(FATAL_ERROR "WITH_GAMEENGINE requires WITH_AUDASPACE")
@@ -855,8 +819,7 @@ set(C_WARNINGS)
set(CXX_WARNINGS)
# for gcc -Wno-blah-blah
set(C_REMOVE_STRICT_FLAGS)
set(CXX_REMOVE_STRICT_FLAGS)
set(CC_REMOVE_STRICT_FLAGS)
# libraries to link the binary with passed to target_link_libraries()
# known as LLIBS to scons
@@ -868,21 +831,6 @@ set(PLATFORM_LINKLIBS "")
set(PLATFORM_LINKFLAGS "")
set(PLATFORM_LINKFLAGS_DEBUG "")
if (NOT CMAKE_BUILD_TYPE MATCHES "Release")
if(WITH_COMPILER_ASAN)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${COMPILER_ASAN_CFLAGS}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${COMPILER_ASAN_CFLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMPILER_ASAN_CXXFLAGS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMPILER_ASAN_CXXFLAGS}")
if(MSVC)
set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6")
endif()
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
endif()
endif()
#-----------------------------------------------------------------------------
#Platform specifics
@@ -1483,22 +1431,16 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
# flags to undo strict flags
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_TYPE_LIMITS -Wno-type-limits)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_IN_BOOL_CONTEXT -Wno-int-in-bool-context)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_FORMAT -Wno-format)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_SWITCH -Wno-switch)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CLASS_MEMACCESS -Wno-class-memaccess)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0"))
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough)
endif()
if(NOT APPLE)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
@@ -1527,23 +1469,23 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
# ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
# flags to undo strict flags
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INCOMPAT_PTR_DISCARD_QUAL -Wno-incompatible-pointer-types-discards-qualifiers)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_TO_VOID_POINTER_CAST -Wno-int-to-void-pointer-cast)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_PROTOTYPES -Wno-missing-prototypes)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_INCOMPAT_PTR_DISCARD_QUAL -Wno-incompatible-pointer-types-discards-qualifiers)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_INT_TO_VOID_POINTER_CAST -Wno-int-to-void-pointer-cast)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_PROTOTYPES -Wno-missing-prototypes)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CXX11_NARROWING -Wno-c++11-narrowing)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_NON_VIRTUAL_DTOR -Wno-non-virtual-dtor)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_REORDER -Wno-reorder)
ADD_CHECK_CXX_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
ADD_CHECK_CXX_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS CXX_WARN_NO_CXX11_NARROWING -Wno-c++11-narrowing)
ADD_CHECK_CXX_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS CXX_WARN_NO_NON_VIRTUAL_DTOR -Wno-non-virtual-dtor)
ADD_CHECK_CXX_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
ADD_CHECK_CXX_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS CXX_WARN_NO_REORDER -Wno-reorder)
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
@@ -1635,12 +1577,7 @@ else()
endif()
# Visual Studio has all standards it supports available by default
# Clang on windows copies this behavior and does not support these switches
if(
CMAKE_COMPILER_IS_GNUCC OR
(CMAKE_C_COMPILER_ID MATCHES "Clang" AND (NOT MSVC)) OR
(CMAKE_C_COMPILER_ID MATCHES "Intel")
)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "Intel")
# Use C99 + GNU extensions, works with GCC, Clang, ICC
if(WITH_C11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")

View File

@@ -236,9 +236,7 @@ help: .FORCE
@echo " * check_descriptions - check for duplicate/invalid descriptions"
@echo ""
@echo "Utilities (not associated with building blender)"
@echo " * icons - Updates PNG icons from SVG files."
@echo " Set environment variables 'BLENDER_BIN' and 'INKSCAPE_BIN'"
@echo " to define your own commands."
@echo " * icons - updates PNG icons from SVG files."
@echo " * tgz - create a compressed archive of the source code."
@echo " * update - updates git and all submodules"
@echo ""

View File

@@ -58,3 +58,4 @@ if(MSVC)
DEPENDEES mkdir update patch download configure build install
)
endif()

View File

@@ -39,6 +39,5 @@ if(BUILD_MODE STREQUAL Release)
PREFIX ${BUILD_DIR}/openal
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openal ${DEFAULT_CMAKE_FLAGS} ${OPENAL_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openal
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openal/src/external_openal < ${PATCH_DIR}/openal.diff
)
endif()

View File

@@ -56,27 +56,24 @@ if(WIN32)
# For OIIO and OSL
set(COMMON_DEFINES /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS)
if(MSVC_VERSION GREATER 1909)
set(COMMON_MSVC_FLAGS "/Wv:18") #some deps with warnings as error aren't quite ready for dealing with the new 2017 warnings.
# TODO FIXME highly MSVC specific
if(WITH_OPTIMIZED_DEBUG)
set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
else()
set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd /Zi /Ob0 /Od /RTC1 /D_DEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
endif()
set(BLENDER_CMAKE_C_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_C_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
if(WITH_OPTIMIZED_DEBUG)
set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd ${COMMON_MSVC_FLAGS} /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/MTd /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
else()
set(BLENDER_CMAKE_C_FLAGS_DEBUG "/MTd ${COMMON_MSVC_FLAGS} /Zi /Ob0 /Od /RTC1 /D_DEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /D PLATFORM_WINDOWS /MTd /Zi /Ob0 /Od /RTC1 /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
endif()
set(BLENDER_CMAKE_C_FLAGS_MINSIZEREL "/MT ${COMMON_MSVC_FLAGS} /O1 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_C_FLAGS_RELEASE "/MT ${COMMON_MSVC_FLAGS} /O2 /Ob2 /DNDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_C_FLAGS_RELWITHDEBINFO "/MT ${COMMON_MSVC_FLAGS} /Zi /O2 /Ob1 /D NDEBUG /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
if(WITH_OPTIMIZED_DEBUG)
set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/MTd ${COMMON_MSVC_FLAGS} /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
else()
set(BLENDER_CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /D PLATFORM_WINDOWS /MTd ${COMMON_MSVC_FLAGS} /Zi /Ob0 /Od /RTC1 /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
endif()
set(BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL "/MT /${COMMON_MSVC_FLAGS} /O1 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_RELEASE "/MT ${COMMON_MSVC_FLAGS} /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT ${COMMON_MSVC_FLAGS} /Zi /O2 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(BLENDER_CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /D PLATFORM_WINDOWS /DPSAPI_VERSION=1 /DOIIO_STATIC_BUILD /DTINYFORMAT_ALLOW_WCHAR_STRINGS")
set(PLATFORM_FLAGS)
set(PLATFORM_CXX_FLAGS)

View File

@@ -216,3 +216,4 @@ if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe")
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/ranlib.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe"
)
endif()

View File

@@ -216,3 +216,4 @@ if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ranlib.exe")
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw64/bin/ranlib.exe" "${DOWNLOAD_DIR}/mingw/mingw64/bin/x86_64-w64-mingw32-ranlib.exe"
)
endif()

View File

@@ -37,3 +37,4 @@ endif()
if(MSVC)
set_target_properties(external_zlib_mingw PROPERTIES FOLDER Mingw)
endif()

View File

@@ -13,25 +13,3 @@
-# pragma message("Unknown compiler version - please run the configure tests and report the results")
-# endif
-#endif
--- a/boost/type_traits/has_nothrow_assign.hpp 2015-12-13 05:49:42 -0700
+++ b/boost/type_traits/has_nothrow_assign.hpp 2018-05-27 11:11:02 -0600
@@ -24,7 +24,7 @@
#include <boost/type_traits/remove_reference.hpp>
#endif
#endif
-#if defined(__GNUC__) || defined(__SUNPRO_CC)
+#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__)
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_assignable.hpp>
--- a/boost/type_traits/has_nothrow_constructor.hpp 2015-12-13 05:49:42 -0700
+++ b/boost/type_traits/has_nothrow_constructor.hpp 2018-05-27 11:11:02 -0600
@@ -17,7 +17,7 @@
#if defined(BOOST_MSVC) || defined(BOOST_INTEL)
#include <boost/type_traits/has_trivial_constructor.hpp>
#endif
-#if defined(__GNUC__ ) || defined(__SUNPRO_CC)
+#if defined(__GNUC__ ) || defined(__SUNPRO_CC) || defined(__clang__)
#include <boost/type_traits/is_default_constructible.hpp>
#endif

View File

@@ -79,3 +79,4 @@ macro( select_library_configurations basename )
${basename}_LIBRARY_DEBUG
)
endmacro( select_library_configurations )

View File

@@ -1,13 +0,0 @@
diff -Naur external_openal_original/CMakeLists.txt external_openal/CMakeLists.txt
--- external_openal_original/CMakeLists.txt 2016-01-24 20:12:39 -0700
+++ external_openal/CMakeLists.txt 2018-06-02 12:16:52 -0600
@@ -885,7 +885,8 @@
OPTION(ALSOFT_REQUIRE_MMDEVAPI "Require MMDevApi backend" OFF)
IF(HAVE_WINDOWS_H)
# Check MMSystem backend
- CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0502)
+ set(CMAKE_REQUIRED_FLAGS "-D_WIN32_WINNT=0x0502")
+ CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H)
IF(HAVE_MMSYSTEM_H)
CHECK_SHARED_FUNCTION_EXISTS(waveOutOpen "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM)
IF(HAVE_LIBWINMM)

View File

@@ -10,29 +10,3 @@ diff -Naur osl/src/external_osl/src/cmake/flexbison.cmake osl_bak/src/external_o
MAIN_DEPENDENCY ${flexsrc}
DEPENDS ${${compiler_headers}}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
--- osl/src/external_osl/src/include/OSL/oslconfig.h 2016-10-31 16:48:19 -0600
+++ osl/src/external_osl/src/include/OSL/oslconfig.h 2018-05-27 11:18:08 -0600
@@ -44,12 +44,18 @@
// same if another packages is compiling against OSL and using these headers
// (OSL may be C++11 but the client package may be older, or vice versa --
// use these two symbols to differentiate these cases, when important).
-#if (__cplusplus >= 201402L)
-# define OSL_CPLUSPLUS_VERSION 14
-#elif (__cplusplus >= 201103L)
-# define OSL_CPLUSPLUS_VERSION 11
+
+// Force C++03 for MSVC in blender since svn the libraries are build with that
+#if !defined(_MSC_VER)
+ #if (__cplusplus >= 201402L)
+ # define OSL_CPLUSPLUS_VERSION 14
+ #elif (__cplusplus >= 201103L)
+ # define OSL_CPLUSPLUS_VERSION 11
+ #else
+ # define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */
+ #endif
#else
-# define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */
+ # define OSL_CPLUSPLUS_VERSION 3 /* presume C++03 */
#endif
// Symbol export defines

View File

@@ -14,18 +14,10 @@ if NOT "%1" == "" (
set BuildDir=VS14
goto par2
)
if "%1" == "2017" (
echo "Building for VS2017"
set VSVER=15.0
set VSVER_SHORT=15
set BuildDir=VS15
goto par2
)
)
:usage
Echo Usage build_deps 2013/2015/2017 x64/x86
Echo Usage build_deps 2013/2015 x64/x86
goto exit
:par2
if NOT "%2" == "" (
@@ -39,10 +31,6 @@ if NOT "%2" == "" (
if "%1" == "2015" (
set CMAKE_BUILDER=Visual Studio 14 2015
)
if "%1" == "2017" (
set CMAKE_BUILDER=Visual Studio 15 2017
)
goto start
)
if "%2" == "x64" (
@@ -55,10 +43,6 @@ if NOT "%2" == "" (
if "%1" == "2015" (
set CMAKE_BUILDER=Visual Studio 14 2015 Win64
)
if "%1" == "2017" (
set CMAKE_BUILDER=Visual Studio 15 2017 Win64
)
goto start
)
)

View File

@@ -78,13 +78,7 @@ if 'cmake' in builder:
# cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/nvcc')
elif builder.startswith('win'):
if builder.endswith('_vs2017'):
if builder.startswith('win64'):
cmake_options.extend(['-G', 'Visual Studio 15 2017 Win64'])
elif builder.startswith('win32'):
bits = 32
cmake_options.extend(['-G', 'Visual Studio 15 2017'])
elif builder.endswith('_vc2015'):
if builder.endswith('_vc2015'):
if builder.startswith('win64'):
cmake_options.extend(['-G', 'Visual Studio 14 2015 Win64'])
elif builder.startswith('win32'):

View File

@@ -93,3 +93,4 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LLVM DEFAULT_MSG
MARK_AS_ADVANCED(
LLVM_LIBRARY
)

View File

@@ -352,11 +352,6 @@ function(SETUP_LIBDIRS)
endif()
endfunction()
macro(setup_platform_linker_flags)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
endmacro()
function(setup_liblinks
target
)
@@ -1041,19 +1036,13 @@ macro(remove_cc_flag
endmacro()
macro(add_c_flag
macro(add_cc_flag
flag)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
endmacro()
macro(add_cxx_flag
flag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
endmacro()
macro(remove_strict_flags)
if(CMAKE_COMPILER_IS_GNUCC)
@@ -1076,8 +1065,7 @@ macro(remove_strict_flags)
)
# negate flags implied by '-Wall'
add_c_flag("${C_REMOVE_STRICT_FLAGS}")
add_cxx_flag("${CXX_REMOVE_STRICT_FLAGS}")
add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
@@ -1089,8 +1077,7 @@ macro(remove_strict_flags)
)
# negate flags implied by '-Wall'
add_c_flag("${C_REMOVE_STRICT_FLAGS}")
add_cxx_flag("${CXX_REMOVE_STRICT_FLAGS}")
add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
endif()
if(MSVC)
@@ -1120,39 +1107,28 @@ endmacro()
# note, we can only append flags on a single file so we need to negate the options.
# at the moment we cant shut up ffmpeg deprecations, so use this, but will
# probably add more removals here.
macro(remove_strict_c_flags_file
macro(remove_strict_flags_file
filenames)
foreach(_SOURCE ${ARGV})
if(CMAKE_COMPILER_IS_GNUCC OR
(CMAKE_C_COMPILER_ID MATCHES "Clang"))
set_source_files_properties(${_SOURCE}
PROPERTIES
COMPILE_FLAGS "${C_REMOVE_STRICT_FLAGS}"
)
endif()
if(MSVC)
# TODO
endif()
endforeach()
unset(_SOURCE)
endmacro()
macro(remove_strict_cxx_flags_file
filenames)
remove_strict_c_flags_file(${filenames} ${ARHV})
foreach(_SOURCE ${ARGV})
if(CMAKE_COMPILER_IS_GNUCC OR
(CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set_source_files_properties(${_SOURCE}
PROPERTIES
COMPILE_FLAGS "${CXX_REMOVE_STRICT_FLAGS}"
COMPILE_FLAGS "${CC_REMOVE_STRICT_FLAGS}"
)
endif()
if(MSVC)
# TODO
endif()
endforeach()
unset(_SOURCE)
endmacro()
# External libs may need 'signed char' to be default.

View File

@@ -356,7 +356,7 @@ if(WITH_LLVM)
execute_process(COMMAND ${LLVM_CONFIG} --libfiles
OUTPUT_VARIABLE LLVM_LIBRARY
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE ".a /" ".a;/" LLVM_LIBRARY ${LLVM_LIBRARY})
string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY})
else()
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lLLVM-3.4")
endif()
@@ -416,7 +416,7 @@ if(${XCODE_VERSION} VERSION_EQUAL 5 OR ${XCODE_VERSION} VERSION_GREATER 5)
endif()
# Get rid of eventually clashes, we export some symbols explicite as local
set(PLATFORM_LINKFLAGS
"${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker '${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map'"
"${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker ${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map"
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")

View File

@@ -29,16 +29,7 @@ if(NOT MSVC)
message(FATAL_ERROR "Compiler is unsupported")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(MSVC_CLANG On)
set(VC_TOOLS_DIR $ENV{VCToolsRedistDir} CACHE STRING "Location of the msvc redistributables")
set(MSVC_REDIST_DIR ${VC_TOOLS_DIR})
if (DEFINED MSVC_REDIST_DIR)
file(TO_CMAKE_PATH ${MSVC_REDIST_DIR} MSVC_REDIST_DIR)
else()
message("Unable to detect the Visual Studio redist directory, copying of the runtime dlls will not work, try running from the visual studio developer prompt.")
endif()
endif()
# Libraries configuration for Windows when compiling with MSVC.
set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_FOLDERS})
@@ -128,18 +119,8 @@ set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WITH_OPENMP})
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
include(InstallRequiredSystemLibraries)
remove_cc_flag("/MDd" "/MD")
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
if(NOT WITH_CXX11) # C++11 is on by default in clang-cl and can't be turned off, if c++11 is not enabled in blender repress some c++11 related warnings.
set(CXX_WARN_FLAGS "-Wno-inconsistent-missing-override")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
@@ -150,7 +131,7 @@ set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ")
set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib ")
# Ignore meaningless for us linker warnings.
@@ -163,7 +144,7 @@ else()
set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}")
endif()
set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
if(NOT DEFINED LIBDIR)

View File

@@ -1,14 +0,0 @@
echo No explicit msvc version requested, autodetecting version.
call "%~dp0\detect_msvc2017.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
call "%~dp0\detect_msvc2015.cmd"
if %ERRORLEVEL% EQU 0 goto DetectionComplete
echo Compiler Detection failed. Use verbose switch for more information.
exit /b 1
:DetectionComplete
echo Compiler Detection successfull, detected VS%BUILD_VS_YEAR%
exit /b 0

View File

@@ -1,26 +0,0 @@
if "%NOBUILD%"=="1" goto EOF
echo %TIME% > %BUILD_DIR%\buildtime.txt
msbuild ^
%BUILD_DIR%\Blender.sln ^
/target:build ^
/property:Configuration=%BUILD_TYPE% ^
/maxcpucount:2 ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM% ^
/flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log
if errorlevel 1 (
echo Error during build, see %BUILD_DIR%\Build.log for details
exit /b 1
)
msbuild ^
%BUILD_DIR%\INSTALL.vcxproj ^
/property:Configuration=%BUILD_TYPE% ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM%
if errorlevel 1 (
echo Error during install phase
exit /b 1
)
echo %TIME% >> %BUILD_DIR%\buildtime.txt
:EOF

View File

@@ -1,16 +0,0 @@
if "%NOBUILD%"=="1" goto EOF
set HAS_ERROR=
cd %BUILD_DIR%
echo %TIME% > buildtime.txt
ninja install
if errorlevel 1 (
set HAS_ERROR=1
)
echo %TIME% >>buildtime.txt
cd %BLENDER_DIR%
if "%HAS_ERROR%" == "1" (
echo Error during build
exit /b 1
)
:EOF

View File

@@ -1,53 +0,0 @@
if "%BUILD_VS_YEAR%"=="2015" set BUILD_VS_LIBDIRPOST=vc14
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc14
if "%BUILD_ARCH%"=="x64" (
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
) else if "%BUILD_ARCH%"=="x86" (
set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
)
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
if NOT "%verbose%" == "" (
echo Library Directory = "%BUILD_VS_LIBDIR%"
)
if NOT EXIST %BUILD_VS_LIBDIR% (
rem libs not found, but svn is on the system
echo
if not "%SVN%"=="" (
echo.
echo The required external libraries in %BUILD_VS_LIBDIR% are missing
echo.
set /p GetLibs= "Would you like to download them? (y/n)"
if /I "!GetLibs!"=="Y" (
echo.
echo Downloading %BUILD_VS_SVNDIR% libraries, please wait.
echo.
:RETRY
"%SVN%" checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR%
if errorlevel 1 (
set /p LibRetry= "Error during donwload, retry? y/n"
if /I "!LibRetry!"=="Y" (
cd %BUILD_VS_LIBDIR%
"%SVN%" cleanup
cd %BLENDER_DIR%
goto RETRY
)
echo.
echo Error: Download of external libraries failed.
echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successfull blender build
echo.
exit /b 1
)
)
)
)
if NOT EXIST %BUILD_VS_LIBDIR% (
echo.
echo Error: Required libraries not found at "%BUILD_VS_LIBDIR%"
echo This is needed for building, aborting!
echo.
exit /b 1
)

View File

@@ -1,6 +0,0 @@
set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
exit /b 1
)

View File

@@ -1,20 +0,0 @@
if NOT exist "%BLENDER_DIR%/source/tools" (
echo Checking out sub-modules
if not "%GIT%" == "" (
"%GIT%" submodule update --init --recursive --progress
if errorlevel 1 goto FAIL
"%GIT%" submodule foreach git checkout master
if errorlevel 1 goto FAIL
"%GIT%" submodule foreach git pull --rebase origin master
if errorlevel 1 goto FAIL
goto EOF
) else (
echo Blender submodules not found, and git not found in path to retrieve them.
goto FAIL
)
)
goto EOF
:FAIL
exit /b 1
:EOF

View File

@@ -1,74 +0,0 @@
if "%BUILD_ARCH%"=="x64" (
set MSBUILD_PLATFORM=x64
) else if "%BUILD_ARCH%"=="x86" (
set MSBUILD_PLATFORM=win32
if "%WITH_CLANG%"=="1" (
echo Clang not supported for X86
exit /b 1
)
)
if "%WITH_CLANG%"=="1" (
set CLANG_CMAKE_ARGS=-T"LLVM-vs2017"
if "%WITH_ASAN%"=="1" (
set ASAN_CMAKE_ARGS=-DWITH_COMPILER_ASAN=On
)
) else (
if "%WITH_ASAN%"=="1" (
echo ASAN is only supported with clang.
exit /b 1
)
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS%
if NOT EXIST %BUILD_DIR%\nul (
mkdir %BUILD_DIR%
)
if "%MUST_CLEAN%"=="1" (
echo Cleaning %BUILD_DIR%
msbuild ^
%BUILD_DIR%\Blender.sln ^
/target:clean ^
/property:Configuration=%BUILD_TYPE% ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM%
)
if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
if "%MUST_CONFIGURE%"=="1" (
if NOT "%verbose%" == "" (
echo %CMAKE% %BUILD_CMAKE_ARGS% -H%BLENDER_DIR% -B%BUILD_DIR%
)
cmake ^
%BUILD_CMAKE_ARGS% ^
-H%BLENDER_DIR% ^
-B%BUILD_DIR%
if %ERRORLEVEL% NEQ 0 (
echo "Configuration Failed"
exit /b 1
)
)
echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
echo "%CMAKE%" . >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
echo msbuild ^
%BUILD_DIR%\Blender.sln ^
/target:build ^
/property:Configuration=%BUILD_TYPE% ^
/maxcpucount:2 ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM% ^
/flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd
echo msbuild ^
%BUILD_DIR%\INSTALL.vcxproj ^
/property:Configuration=%BUILD_TYPE% ^
/verbosity:minimal ^
/p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd

View File

@@ -1,80 +0,0 @@
ninja --version 1>NUL 2>&1
if %ERRORLEVEL% NEQ 0 (
echo "Ninja not detected in the path"
exit /b 1
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
if "%WITH_CLANG%" == "1" (
set LLVM_DIR=
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C
if DEFINED LLVM_DIR (
if NOT "%verbose%" == "" (
echo LLVM Detected at "%LLVM_DIR%"
)
goto DetectionComplete
)
REM Check 32 bits
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C
if DEFINED LLVM_DIR (
if NOT "%verbose%" == "" (
echo LLVM Detected at "%LLVM_DIR%"
)
goto DetectionComplete
)
echo LLVM not found
exit /b 1
:DetectionComplete
set CC=%LLVM_DIR%\bin\clang-cl
set CXX=%LLVM_DIR%\bin\clang-cl
rem build and tested against 2017 15.7
set CFLAGS=-m64 -fmsc-version=1914
set CXXFLAGS=-m64 -fmsc-version=1914
if "%WITH_ASAN%"=="1" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
)
)
if "%WITH_ASAN%"=="1" (
if "%WITH_CLANG%" == "" (
echo ASAN is only supported with clang.
exit /b 1
)
)
if NOT "%verbose%" == "" (
echo BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS%
)
if NOT EXIST %BUILD_DIR%\nul (
mkdir %BUILD_DIR%
)
if "%MUST_CLEAN%"=="1" (
echo Cleaning %BUILD_DIR%
cd %BUILD_DIR%
%CMAKE% cmake --build . --config Clean
)
if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
if "%MUST_CONFIGURE%"=="1" (
cmake ^
%BUILD_CMAKE_ARGS% ^
-H%BLENDER_DIR% ^
-B%BUILD_DIR%
if %ERRORLEVEL% NEQ 0 (
echo "Configuration Failed"
exit /b 1
)
)
echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
echo ninja install >> %BUILD_DIR%\rebuild.cmd
echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd

View File

@@ -1,16 +0,0 @@
if "%BUILD_ARCH%"=="" (
if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
set WINDOWS_ARCH= Win64
set BUILD_ARCH=x64
) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
set WINDOWS_ARCH= Win64
set BUILD_ARCH=x64
) else (
set WINDOWS_ARCH=
set BUILD_ARCH=x86
)
) else if "%BUILD_ARCH%"=="x64" (
set WINDOWS_ARCH= Win64
) else if "%BUILD_ARCH%"=="x86" (
set WINDOWS_ARCH=
)

View File

@@ -1,3 +0,0 @@
set BUILD_VS_VER=14
set BUILD_VS_YEAR=2015
call "%~dp0\detect_msvc_classic.cmd"

View File

@@ -1,76 +0,0 @@
if NOT "%verbose%" == "" (
echo Detecting msvc 2017
)
set BUILD_VS_VER=15
set BUILD_VS_YEAR=2017
set ProgramFilesX86=%ProgramFiles(x86)%
if not exist "%ProgramFilesX86%" set ProgramFilesX86=%ProgramFiles%
set vs_where=%ProgramFilesX86%\Microsoft Visual Studio\Installer\vswhere.exe
if not exist "%vs_where%" (
if NOT "%verbose%" == "" (
echo Visual Studio 2017 ^(15.2 or newer^) is not detected
goto FAIL
)
)
if NOT "%verbose%" == "" (
echo "%vs_where%" -latest %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64`
)
for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64`) do (
if /i "%%i"=="installationPath" set VS_InstallDir=%%j
)
if "%VS_InstallDir%"=="" (
if NOT "%verbose%" == "" (
echo Visual Studio is detected but the "Desktop development with C++" workload has not been instlled
goto FAIL
)
)
set VCVARS=%VS_InstallDir%\VC\Auxiliary\Build\vcvarsall.bat
if exist "%VCVARS%" (
call "%VCVARS%" %BUILD_ARCH%
) else (
if NOT "%verbose%" == "" (
echo "%VCVARS%" not found
)
goto FAIL
)
rem try msbuild
msbuild /version > NUL
if errorlevel 1 (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% msbuild not found
)
goto FAIL
)
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% msbuild found
)
REM try the c++ compiler
cl 2> NUL 1>&2
if errorlevel 1 (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found
)
goto FAIL
)
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found
)
if NOT "%verbose%" == "" (
echo Visual Studio 2017 is detected successfully
)
goto EOF
:FAIL
exit /b 1
:EOF

View File

@@ -1,69 +0,0 @@
if NOT "%verbose%" == "" (
echo Detecting msvc %BUILD_VS_YEAR%
)
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C
if DEFINED MSVC_VC_DIR (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% on Win64 detected at "%MSVC_VC_DIR%"
)
goto msvc_detect_finally
)
REM Check 32 bits
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C
if DEFINED MSVC_VC_DIR (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% on Win32 detected at "%MSVC_VC_DIR%"
)
goto msvc_detect_finally
)
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% not found.
)
goto FAIL
:msvc_detect_finally
set VCVARS=%MSVC_VC_DIR%\vcvarsall.bat
if not exist "%VCVARS%" (
echo "%VCVARS%" not found.
goto FAIL
)
call "%vcvars%" %BUILD_ARCH%
rem try msbuild
msbuild /version > NUL
if errorlevel 1 (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% msbuild not found
)
goto FAIL
)
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% msbuild found
)
REM try the c++ compiler
cl 2> NUL 1>&2
if errorlevel 1 (
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found
)
goto FAIL
)
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found
)
goto DetectionComplete
:FAIL
exit /b 1
:DetectionComplete
if NOT "%verbose%" == "" (
echo Visual Studio %BUILD_VS_YEAR% Detected successfuly
)
exit /b 0

View File

@@ -1,13 +0,0 @@
REM find all dependencies and set the corresponding environement variables.
for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
if NOT "%verbose%" == "" (
echo svn : %SVN%
echo cmake : %CMAKE%
echo git : %GIT%
)
if "%CMAKE%" == "" (
echo Cmake not found in path, required for building, exiting...
exit /b 1
)

View File

@@ -1,86 +0,0 @@
set BUILD_DIR=%BLENDER_DIR%..\build_windows
set BUILD_TYPE=Release
:argv_loop
if NOT "%1" == "" (
REM Help Message
if "%1" == "help" (
set SHOW_HELP=1
goto EOF
)
REM Build Types
if "%1" == "debug" (
set BUILD_TYPE=Debug
REM Build Configurations
) else if "%1" == "noge" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF
set BUILD_NGE=_noge
) else if "%1" == "builddir" (
set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2"
shift /1
) else if "%1" == "with_tests" (
set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On
) else if "%1" == "full" (
set TARGET=Full
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake"
) else if "%1" == "lite" (
set TARGET=Lite
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake"
) else if "%1" == "cycles" (
set TARGET=Cycles
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake"
) else if "%1" == "headless" (
set TARGET=Headless
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake"
) else if "%1" == "bpy" (
set TARGET=Bpy
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
) else if "%1" == "clang" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS%
set WITH_CLANG=1
) else if "%1" == "release" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
set TARGET=Release
) else if "%1" == "asan" (
set WITH_ASAN=1
) else if "%1" == "x86" (
set BUILD_ARCH=x86
) else if "%1" == "x64" (
set BUILD_ARCH=x64
) else if "%1" == "2017" (
set BUILD_VS_YEAR=2017
) else if "%1" == "2017pre" (
set BUILD_VS_YEAR=2017
set VSWHERE_ARGS=-prerelease
set BUILD_VS_YEAR=2017
) else if "%1" == "2017b" (
set BUILD_VS_YEAR=2017
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
) else if "%1" == "2015" (
set BUILD_VS_YEAR=2015
) else if "%1" == "packagename" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
shift /1
) else if "%1" == "nobuild" (
set NOBUILD=1
) else if "%1" == "showhash" (
SET BUILD_SHOW_HASHES=1
REM Non-Build Commands
) else if "%1" == "update" (
SET BUILD_UPDATE=1
) else if "%1" == "ninja" (
SET BUILD_WITH_NINJA=1
) else if "%1" == "clean" (
set MUST_CLEAN=1
) else if "%1" == "verbose" (
set VERBOSE=1
) else (
echo Command "%1" unknown, aborting!
exit /b 1
)
shift /1
goto argv_loop
)
:EOF
exit /b 0

View File

@@ -1,27 +0,0 @@
rem reset all variables so they do not get accidentally get carried over from previous builds
set BUILD_DIR_OVERRRIDE=
set BUILD_CMAKE_ARGS=
set BUILD_ARCH=
set BUILD_VS_VER=
set BUILD_VS_YEAR=
set BUILD_VS_LIBDIRPOST=
set BUILD_VS_LIBDIR=
set BUILD_VS_SVNDIR=
set BUILD_NGE=
set KEY_NAME=
set MSBUILD_PLATFORM=
set MUST_CLEAN=
set NOBUILD=
set TARGET=
set VERBOSE=
set WINDOWS_ARCH=
set TESTS_CMAKE_ARGS=
set VSWHERE_ARGS=
set BUILD_UPDATE=
set BUILD_SHOW_HASHES=
set SHOW_HELP=
set BUILD_WITH_NINJA=
set WITH_CLANG=
set WITH_ASAN=
set CLANG_CMAKE_ARGS=
set ASAN_CMAKE_ARGS=

View File

@@ -1,4 +0,0 @@
set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE%
if NOT "%BUILD_DIR_OVERRRIDE%"=="" (
set BUILD_DIR=%BUILD_DIR_OVERRRIDE%
)

View File

@@ -1,12 +0,0 @@
if "%GIT%" == "" (
echo Git not found, cannot show hashes.
goto EOF
)
cd "%BLENDER_DIR%"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Branch_hash=%%i
cd "%BLENDER_DIR%/release/datafiles/locale"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Locale_hash=%%i
cd "%BLENDER_DIR%/release/scripts/addons"
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Addons_Hash=%%i
cd "%BLENDER_DIR%"
:EOF

View File

@@ -1,35 +0,0 @@
echo.
echo Convenience targets
echo - release ^(identical to the official blender.org builds^)
echo - full ^(same as release minus the cuda kernels^)
echo - lite
echo - headless
echo - cycles
echo - bpy
echo.
echo Utilities ^(not associated with building^)
echo - clean ^(Target must be set^)
echo - update
echo - nobuild ^(only generate project files^)
echo - showhash ^(Show git hashes of source tree^)
echo.
echo Configuration options
echo - verbose ^(enable diagnostic output during configuration^)
echo - with_tests ^(enable building unit tests^)
echo - noge ^(disable building game enginge and player^)
echo - debug ^(Build an unoptimized debuggable build^)
echo - packagename [newname] ^(override default cpack package name^)
echo - buildir [newdir] ^(override default build folder^)
echo - x86 ^(override host auto-detect and build 32 bit code^)
echo - x64 ^(override host auto-detect and build 64 bit code^)
echo - 2017 ^(build with visual studio 2017^)
echo - 2017pre ^(build with visual studio 2017 pre-release^)
echo - 2017b ^(build with visual studio 2017 Build Tools^)
echo.
echo Experimental options
echo - 2015 ^(build with visual studio 2015^)
echo - clang ^(enable building with clang^)
echo - asan ^(enable asan when building with clang^)
echo - ninja ^(enable building with ninja instead of msbuild^)
echo.

View File

@@ -1,16 +0,0 @@
if "%SVN%" == "" (
echo svn not found, cannot update libraries
goto UPDATE_GIT
)
"%SVN%" up "%BLENDER_DIR%/../lib/*"
:UPDATE_GIT
if "%GIT%" == "" (
echo Git not found, cannot update code
goto EOF
)
"%GIT%" pull --rebase
"%GIT%" submodule foreach git pull --rebase origin master
:EOF

View File

@@ -34,7 +34,6 @@ log = logging.getLogger("BlendFileReader")
# module global routines
######################################################
def ReadString(handle, length):
'''
ReadString reads a String of given length or a zero terminating String
@@ -339,7 +338,7 @@ class DNAName:
return result
def ShortName(self):
result = self.Name
result = self.Name;
result = result.replace("*", "")
result = result.replace("(", "")
result = result.replace(")", "")
@@ -399,7 +398,7 @@ class DNAStructure:
splitted = path.partition(".")
name = splitted[0]
rest = splitted[2]
offset = 0
offset = 0;
for field in self.Fields:
if field.Name.ShortName() == name:
log.debug("found "+name+"@"+str(offset))
@@ -444,3 +443,4 @@ class DNAField:
return ReadString(handle, self.Name.ArraySize())
else:
return self.Type.Structure.GetField(header, handle, path)

View File

@@ -42,7 +42,6 @@ def man_format(data):
data = data.replace("\t", " ")
return data
if len(sys.argv) != 3:
import getopt
raise getopt.GetoptError("Usage: %s <path-to-blender> <output-filename>" % sys.argv[0])

View File

@@ -220,8 +220,6 @@ def config_video(obj, format, pixel, is3D=False, mat=0, card=0):
# Attach this function to an object that has a material with texture
# and call it once to initialize the object
#
def init(cont):
# config_video(cont.owner, 'HD720p5994', '8BitBGRA')
# config_video(cont.owner, 'HD720p5994', '8BitYUV')

View File

@@ -15,7 +15,6 @@ font_info = {
"handler": None,
}
def init():
"""init function - runs once"""
import os

View File

@@ -17,5 +17,4 @@ from bpy.app.handlers import persistent
def load_handler(dummy):
print("Load Handler:", bpy.data.filepath)
bpy.app.handlers.load_post.append(load_handler)

View File

@@ -11,5 +11,4 @@ import bpy
def my_handler(scene):
print("Frame Change", scene.frame_current)
bpy.app.handlers.frame_change_pre.append(my_handler)

View File

@@ -81,7 +81,6 @@ for msg in translations_tuple:
# Define remaining addon (operators, UI...) here.
def register():
# Usual operator/UI/etc. registration...

View File

@@ -14,7 +14,6 @@ class MaterialSettings(bpy.types.PropertyGroup):
my_float = bpy.props.FloatProperty()
my_string = bpy.props.StringProperty()
bpy.utils.register_class(MaterialSettings)
bpy.types.Material.my_settings = \

View File

@@ -14,7 +14,6 @@ class SceneSettingItem(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(name="Test Prop", default="Unknown")
value = bpy.props.IntProperty(name="Test Prop", default=22)
bpy.utils.register_class(SceneSettingItem)
bpy.types.Scene.my_settings = \

View File

@@ -14,7 +14,6 @@ import bpy
def update_func(self, context):
print("my test function", self)
bpy.types.Scene.testprop = bpy.props.FloatProperty(update=update_func)
bpy.context.scene.testprop = 11.0

View File

@@ -19,7 +19,6 @@ def get_float(self):
def set_float(self, value):
self["testprop"] = value
bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)
@@ -28,7 +27,6 @@ def get_date(self):
import datetime
return str(datetime.datetime.now())
bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
@@ -42,7 +40,6 @@ def get_array(self):
def set_array(self, values):
self["somebool"] = values[0] and values[1]
bpy.types.Scene.test_array = bpy.props.BoolVectorProperty(size=2, get=get_array, set=set_array)
@@ -64,7 +61,6 @@ def get_enum(self):
def set_enum(self, value):
print("setting value", value)
bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum)

View File

@@ -14,5 +14,4 @@ import bpy
def menu_draw(self, context):
self.layout.operator("wm.save_homefile")
bpy.types.INFO_MT_file.append(menu_draw)

View File

@@ -60,7 +60,6 @@ def menu_func(self, context):
layout.separator()
layout.operator(WM_OT_button_context_test.bl_idname)
classes = (
WM_OT_button_context_test,
WM_MT_button_context,
@@ -78,6 +77,5 @@ def unregister():
bpy.utils.unregister_class(cls)
bpy.types.WM_MT_button_context.remove(menu_func)
if __name__ == "__main__":
register()

View File

@@ -21,5 +21,4 @@ class CyclesNodeTree(bpy.types.NodeTree):
def poll(cls, context):
return context.scene.render.engine == 'CYCLES'
bpy.utils.register_class(CyclesNodeTree)

View File

@@ -42,7 +42,6 @@ class SimpleMouseOperator(bpy.types.Operator):
self.y = event.mouse_y
return self.execute(context)
bpy.utils.register_class(SimpleMouseOperator)
# Test call to the newly defined operator.

View File

@@ -42,7 +42,6 @@ def menu_func(self, context):
self.layout.operator_context = 'INVOKE_DEFAULT'
self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
# Register and add to the file selector
bpy.utils.register_class(ExportSomeData)
bpy.types.INFO_MT_file_export.append(menu_func)

View File

@@ -41,7 +41,6 @@ class CustomDrawOperator(bpy.types.Operator):
col.prop(self, "my_string")
bpy.utils.register_class(CustomDrawOperator)
# test call

View File

@@ -22,7 +22,6 @@ class HelloWorldOperator(bpy.types.Operator):
print("Hello World")
return {'FINISHED'}
bpy.utils.register_class(HelloWorldOperator)
# test call to the newly defined operator

View File

@@ -31,7 +31,6 @@ class MyPropertyGroup(bpy.types.PropertyGroup):
custom_1 = bpy.props.FloatProperty(name="My Float")
custom_2 = bpy.props.IntProperty(name="My Int")
bpy.utils.register_class(MyPropertyGroup)
bpy.types.Object.my_prop_grp = bpy.props.PointerProperty(type=MyPropertyGroup)

View File

@@ -10,5 +10,4 @@ import bpy
def draw(self, context):
self.layout.label("Hello World")
bpy.context.window_manager.popup_menu(draw, title="Greeting", icon='INFO')

View File

@@ -12,7 +12,6 @@ from bpy.props import PointerProperty
class MyPropGroup(bpy.types.PropertyGroup):
nested = bpy.props.FloatProperty(name="Nested", default=0.0)
# register it so its available for all bones
bpy.utils.register_class(MyPropGroup)
bpy.types.Bone.my_prop = PointerProperty(type=MyPropGroup,

View File

@@ -73,8 +73,6 @@ def rna_info_BuildRNAInfo_cache():
if rna_info_BuildRNAInfo_cache.ret is None:
rna_info_BuildRNAInfo_cache.ret = rna_info.BuildRNAInfo()
return rna_info_BuildRNAInfo_cache.ret
rna_info_BuildRNAInfo_cache.ret = None
# --- end rna_info cache
@@ -515,8 +513,6 @@ def escape_rst(text):
""" Escape plain text which may contain characters used by RST.
"""
return text.translate(escape_rst.trans)
escape_rst.trans = str.maketrans({
"`": "\\`",
"|": "\\|",
@@ -1019,7 +1015,6 @@ def pymodule2sphinx(basepath, module_name, module, title):
file.close()
# Changes in Blender will force errors here
context_type_map = {
"active_base": ("ObjectBase", False),

View File

@@ -107,16 +107,14 @@ def main():
with tempfile.TemporaryDirectory() as tmp_dir:
# II) Generate doc source in temp dir.
doc_gen_cmd = (
args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
doc_gen_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
"--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--",
"--output", tmp_dir
)
"--output", tmp_dir)
subprocess.run(doc_gen_cmd)
# III) Get Blender version info.
getver_file = os.path.join(tmp_dir, "blendver.txt")
getver_script = (
getver_script = (""
"import sys, bpy\n"
"with open(sys.argv[-1], 'w') as f:\n"
" is_release = bpy.app.version_cycle in {'rc', 'release'}\n"
@@ -126,8 +124,7 @@ def main():
" f.write('%d.%d%s\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
" if is_release else '%s\\n' % branch)\n"
" f.write('%d_%d%s_release' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
" if is_release else '%d_%d_%d' % bpy.app.version)\n"
)
" if is_release else '%d_%d_%d' % bpy.app.version)\n")
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
"--python-expr", getver_script, "--", getver_file)
subprocess.run(get_ver_cmd)

View File

@@ -335,7 +335,7 @@ template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_p
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__)
#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
// Direct of the struct members fixed bug #62.
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; }

View File

@@ -1,12 +0,0 @@
diff -Naur c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
--- c:\blender-git\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h 2018-05-25 13:29:14 -0600
+++ k:\BlenderGit\blender\extern\Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h 2018-05-26 19:56:36 -0600
@@ -335,7 +335,7 @@
template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && !defined(__clang__)
// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
// Direct of the struct members fixed bug #62.
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; }

View File

@@ -0,0 +1,156 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.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_ADLOC_FORWARD
#define EIGEN_ADLOC_FORWARD
//--------------------------------------------------------------------------------
//
// This file provides support for adolc's adouble type in forward mode.
// ADOL-C is a C++ automatic differentiation library,
// see https://projects.coin-or.org/ADOL-C for more information.
//
// Note that the maximal number of directions is controlled by
// the preprocessor token NUMBER_DIRECTIONS. The default is 2.
//
//--------------------------------------------------------------------------------
#define ADOLC_TAPELESS
#ifndef NUMBER_DIRECTIONS
# define NUMBER_DIRECTIONS 2
#endif
#include <adolc/adouble.h>
// adolc defines some very stupid macros:
#if defined(malloc)
# undef malloc
#endif
#if defined(calloc)
# undef calloc
#endif
#if defined(realloc)
# undef realloc
#endif
#include <Eigen/Core>
namespace Eigen {
/**
* \defgroup AdolcForward_Module Adolc forward module
* This module provides support for adolc's adouble type in forward mode.
* ADOL-C is a C++ automatic differentiation library,
* see https://projects.coin-or.org/ADOL-C for more information.
* It mainly consists in:
* - a struct Eigen::NumTraits<adtl::adouble> specialization
* - overloads of internal::* math function for adtl::adouble type.
*
* Note that the maximal number of directions is controlled by
* the preprocessor token NUMBER_DIRECTIONS. The default is 2.
*
* \code
* #include <unsupported/Eigen/AdolcSupport>
* \endcode
*/
//@{
} // namespace Eigen
// Eigen's require a few additional functions which must be defined in the same namespace
// than the custom scalar type own namespace
namespace adtl {
inline const adouble& conj(const adouble& x) { return x; }
inline const adouble& real(const adouble& x) { return x; }
inline adouble imag(const adouble&) { return 0.; }
inline adouble abs(const adouble& x) { return fabs(x); }
inline adouble abs2(const adouble& x) { return x*x; }
}
namespace Eigen {
template<> struct NumTraits<adtl::adouble>
: NumTraits<double>
{
typedef adtl::adouble Real;
typedef adtl::adouble NonInteger;
typedef adtl::adouble Nested;
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 1,
AddCost = 1,
MulCost = 1
};
};
template<typename Functor> class AdolcForwardJacobian : public Functor
{
typedef adtl::adouble ActiveScalar;
public:
AdolcForwardJacobian() : Functor() {}
AdolcForwardJacobian(const Functor& f) : Functor(f) {}
// forward constructors
template<typename T0>
AdolcForwardJacobian(const T0& a0) : Functor(a0) {}
template<typename T0, typename T1>
AdolcForwardJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {}
template<typename T0, typename T1, typename T2>
AdolcForwardJacobian(const T0& a0, const T1& a1, const T1& a2) : Functor(a0, a1, a2) {}
typedef typename Functor::InputType InputType;
typedef typename Functor::ValueType ValueType;
typedef typename Functor::JacobianType JacobianType;
typedef Matrix<ActiveScalar, InputType::SizeAtCompileTime, 1> ActiveInput;
typedef Matrix<ActiveScalar, ValueType::SizeAtCompileTime, 1> ActiveValue;
void operator() (const InputType& x, ValueType* v, JacobianType* _jac) const
{
eigen_assert(v!=0);
if (!_jac)
{
Functor::operator()(x, v);
return;
}
JacobianType& jac = *_jac;
ActiveInput ax = x.template cast<ActiveScalar>();
ActiveValue av(jac.rows());
for (int j=0; j<jac.cols(); j++)
for (int i=0; i<jac.cols(); i++)
ax[i].setADValue(j, i==j ? 1 : 0);
Functor::operator()(ax, &av);
for (int i=0; i<jac.rows(); i++)
{
(*v)[i] = av[i].getValue();
for (int j=0; j<jac.cols(); j++)
jac.coeffRef(i,j) = av[i].getADValue(j);
}
}
protected:
};
//@}
}
#endif // EIGEN_ADLOC_FORWARD

View File

@@ -0,0 +1,190 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <g.gael@free.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_ALIGNED_VECTOR3
#define EIGEN_ALIGNED_VECTOR3
#include <Eigen/Geometry>
namespace Eigen {
/**
* \defgroup AlignedVector3_Module Aligned vector3 module
*
* \code
* #include <unsupported/Eigen/AlignedVector3>
* \endcode
*/
//@{
/** \class AlignedVector3
*
* \brief A vectorization friendly 3D vector
*
* This class represents a 3D vector internally using a 4D vector
* such that vectorization can be seamlessly enabled. Of course,
* the same result can be achieved by directly using a 4D vector.
* This class makes this process simpler.
*
*/
// TODO specialize Cwise
template<typename _Scalar> class AlignedVector3;
namespace internal {
template<typename _Scalar> struct traits<AlignedVector3<_Scalar> >
: traits<Matrix<_Scalar,3,1,0,4,1> >
{
};
}
template<typename _Scalar> class AlignedVector3
: public MatrixBase<AlignedVector3<_Scalar> >
{
typedef Matrix<_Scalar,4,1> CoeffType;
CoeffType m_coeffs;
public:
typedef MatrixBase<AlignedVector3<_Scalar> > Base;
EIGEN_DENSE_PUBLIC_INTERFACE(AlignedVector3)
using Base::operator*;
inline Index rows() const { return 3; }
inline Index cols() const { return 1; }
inline const Scalar& coeff(Index row, Index col) const
{ return m_coeffs.coeff(row, col); }
inline Scalar& coeffRef(Index row, Index col)
{ return m_coeffs.coeffRef(row, col); }
inline const Scalar& coeff(Index index) const
{ return m_coeffs.coeff(index); }
inline Scalar& coeffRef(Index index)
{ return m_coeffs.coeffRef(index);}
inline AlignedVector3(const Scalar& x, const Scalar& y, const Scalar& z)
: m_coeffs(x, y, z, Scalar(0))
{}
inline AlignedVector3(const AlignedVector3& other)
: Base(), m_coeffs(other.m_coeffs)
{}
template<typename XprType, int Size=XprType::SizeAtCompileTime>
struct generic_assign_selector {};
template<typename XprType> struct generic_assign_selector<XprType,4>
{
inline static void run(AlignedVector3& dest, const XprType& src)
{
dest.m_coeffs = src;
}
};
template<typename XprType> struct generic_assign_selector<XprType,3>
{
inline static void run(AlignedVector3& dest, const XprType& src)
{
dest.m_coeffs.template head<3>() = src;
dest.m_coeffs.w() = Scalar(0);
}
};
template<typename Derived>
inline explicit AlignedVector3(const MatrixBase<Derived>& other)
{
generic_assign_selector<Derived>::run(*this,other.derived());
}
inline AlignedVector3& operator=(const AlignedVector3& other)
{ m_coeffs = other.m_coeffs; return *this; }
inline AlignedVector3 operator+(const AlignedVector3& other) const
{ return AlignedVector3(m_coeffs + other.m_coeffs); }
inline AlignedVector3& operator+=(const AlignedVector3& other)
{ m_coeffs += other.m_coeffs; return *this; }
inline AlignedVector3 operator-(const AlignedVector3& other) const
{ return AlignedVector3(m_coeffs - other.m_coeffs); }
inline AlignedVector3 operator-=(const AlignedVector3& other)
{ m_coeffs -= other.m_coeffs; return *this; }
inline AlignedVector3 operator*(const Scalar& s) const
{ return AlignedVector3(m_coeffs * s); }
inline friend AlignedVector3 operator*(const Scalar& s,const AlignedVector3& vec)
{ return AlignedVector3(s * vec.m_coeffs); }
inline AlignedVector3& operator*=(const Scalar& s)
{ m_coeffs *= s; return *this; }
inline AlignedVector3 operator/(const Scalar& s) const
{ return AlignedVector3(m_coeffs / s); }
inline AlignedVector3& operator/=(const Scalar& s)
{ m_coeffs /= s; return *this; }
inline Scalar dot(const AlignedVector3& other) const
{
eigen_assert(m_coeffs.w()==Scalar(0));
eigen_assert(other.m_coeffs.w()==Scalar(0));
return m_coeffs.dot(other.m_coeffs);
}
inline void normalize()
{
m_coeffs /= norm();
}
inline AlignedVector3 normalized()
{
return AlignedVector3(m_coeffs / norm());
}
inline Scalar sum() const
{
eigen_assert(m_coeffs.w()==Scalar(0));
return m_coeffs.sum();
}
inline Scalar squaredNorm() const
{
eigen_assert(m_coeffs.w()==Scalar(0));
return m_coeffs.squaredNorm();
}
inline Scalar norm() const
{
using std::sqrt;
return sqrt(squaredNorm());
}
inline AlignedVector3 cross(const AlignedVector3& other) const
{
return AlignedVector3(m_coeffs.cross3(other.m_coeffs));
}
template<typename Derived>
inline bool isApprox(const MatrixBase<Derived>& other, const RealScalar& eps=NumTraits<Scalar>::dummy_precision()) const
{
return m_coeffs.template head<3>().isApprox(other,eps);
}
};
//@}
}
#endif // EIGEN_ALIGNED_VECTOR3

View File

@@ -0,0 +1,31 @@
// 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_ARPACKSUPPORT_MODULE_H
#define EIGEN_ARPACKSUPPORT_MODULE_H
#include <Eigen/Core>
#include <Eigen/src/Core/util/DisableStupidWarnings.h>
/** \defgroup ArpackSupport_Module Arpack support module
*
* This module provides a wrapper to Arpack, a library for sparse eigenvalue decomposition.
*
* \code
* #include <Eigen/ArpackSupport>
* \endcode
*/
#include <Eigen/SparseCholesky>
#include "src/Eigenvalues/ArpackSelfAdjointEigenSolver.h"
#include <Eigen/src/Core/util/ReenableStupidWarnings.h>
#endif // EIGEN_ARPACKSUPPORT_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

View File

@@ -0,0 +1,40 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.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_AUTODIFF_MODULE
#define EIGEN_AUTODIFF_MODULE
namespace Eigen {
/**
* \defgroup AutoDiff_Module Auto Diff module
*
* This module features forward automatic differentation via a simple
* templated scalar type wrapper AutoDiffScalar.
*
* Warning : this should NOT be confused with numerical differentiation, which
* is a different method and has its own module in Eigen : \ref NumericalDiff_Module.
*
* \code
* #include <unsupported/Eigen/AutoDiff>
* \endcode
*/
//@{
}
#include "src/AutoDiff/AutoDiffScalar.h"
// #include "src/AutoDiff/AutoDiffVector.h"
#include "src/AutoDiff/AutoDiffJacobian.h"
namespace Eigen {
//@}
}
#endif // EIGEN_AUTODIFF_MODULE

95
extern/Eigen3/unsupported/Eigen/BVH vendored Normal file
View File

@@ -0,0 +1,95 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu>
//
// 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_BVH_MODULE_H
#define EIGEN_BVH_MODULE_H
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/StdVector>
#include <algorithm>
#include <queue>
namespace Eigen {
/**
* \defgroup BVH_Module BVH module
* \brief This module provides generic bounding volume hierarchy algorithms
* and reference tree implementations.
*
*
* \code
* #include <unsupported/Eigen/BVH>
* \endcode
*
* A bounding volume hierarchy (BVH) can accelerate many geometric queries. This module provides a generic implementation
* of the two basic algorithms over a BVH: intersection of a query object against all objects in the hierarchy and minimization
* of a function over the objects in the hierarchy. It also provides intersection and minimization over a cartesian product of
* two BVH's. A BVH accelerates intersection by using the fact that if a query object does not intersect a volume, then it cannot
* intersect any object contained in that volume. Similarly, a BVH accelerates minimization because the minimum of a function
* over a volume is no greater than the minimum of a function over any object contained in it.
*
* Some sample queries that can be written in terms of intersection are:
* - Determine all points where a ray intersects a triangle mesh
* - Given a set of points, determine which are contained in a query sphere
* - Given a set of spheres, determine which contain the query point
* - Given a set of disks, determine if any is completely contained in a query rectangle (represent each 2D disk as a point \f$(x,y,r)\f$
* in 3D and represent the rectangle as a pyramid based on the original rectangle and shrinking in the \f$r\f$ direction)
* - Given a set of points, count how many pairs are \f$d\pm\epsilon\f$ apart (done by looking at the cartesian product of the set
* of points with itself)
*
* Some sample queries that can be written in terms of function minimization over a set of objects are:
* - Find the intersection between a ray and a triangle mesh closest to the ray origin (function is infinite off the ray)
* - Given a polyline and a query point, determine the closest point on the polyline to the query
* - Find the diameter of a point cloud (done by looking at the cartesian product and using negative distance as the function)
* - Determine how far two meshes are from colliding (this is also a cartesian product query)
*
* This implementation decouples the basic algorithms both from the type of hierarchy (and the types of the bounding volumes) and
* from the particulars of the query. To enable abstraction from the BVH, the BVH is required to implement a generic mechanism
* for traversal. To abstract from the query, the query is responsible for keeping track of results.
*
* To be used in the algorithms, a hierarchy must implement the following traversal mechanism (see KdBVH for a sample implementation): \code
typedef Volume //the type of bounding volume
typedef Object //the type of object in the hierarchy
typedef Index //a reference to a node in the hierarchy--typically an int or a pointer
typedef VolumeIterator //an iterator type over node children--returns Index
typedef ObjectIterator //an iterator over object (leaf) children--returns const Object &
Index getRootIndex() const //returns the index of the hierarchy root
const Volume &getVolume(Index index) const //returns the bounding volume of the node at given index
void getChildren(Index index, VolumeIterator &outVBegin, VolumeIterator &outVEnd,
ObjectIterator &outOBegin, ObjectIterator &outOEnd) const
//getChildren takes a node index and makes [outVBegin, outVEnd) range over its node children
//and [outOBegin, outOEnd) range over its object children
\endcode
*
* To use the hierarchy, call BVIntersect or BVMinimize, passing it a BVH (or two, for cartesian product) and a minimizer or intersector.
* For an intersection query on a single BVH, the intersector encapsulates the query and must provide two functions:
* \code
bool intersectVolume(const Volume &volume) //returns true if the query intersects the volume
bool intersectObject(const Object &object) //returns true if the intersection search should terminate immediately
\endcode
* The guarantee that BVIntersect provides is that intersectObject will be called on every object whose bounding volume
* intersects the query (but possibly on other objects too) unless the search is terminated prematurely. It is the
* responsibility of the intersectObject function to keep track of the results in whatever manner is appropriate.
* The cartesian product intersection and the BVMinimize queries are similar--see their individual documentation.
*
* The following is a simple but complete example for how to use the BVH to accelerate the search for a closest red-blue point pair:
* \include BVH_Example.cpp
* Output: \verbinclude BVH_Example.out
*/
}
//@{
#include "src/BVH/BVAlgorithms.h"
#include "src/BVH/KdBVH.h"
//@}
#endif // EIGEN_BVH_MODULE_H

View File

@@ -0,0 +1,11 @@
set(Eigen_HEADERS AdolcForward AlignedVector3 ArpackSupport AutoDiff BVH FFT IterativeSolvers KroneckerProduct LevenbergMarquardt
MatrixFunctions MoreVectorization MPRealSupport NonLinearOptimization NumericalDiff OpenGLSupport Polynomials
Skyline SparseExtra Splines
)
install(FILES
${Eigen_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen COMPONENT Devel
)
add_subdirectory(src)

418
extern/Eigen3/unsupported/Eigen/FFT vendored Normal file
View File

@@ -0,0 +1,418 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Mark Borgerding mark a borgerding net
//
// 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_FFT_H
#define EIGEN_FFT_H
#include <complex>
#include <vector>
#include <map>
#include <Eigen/Core>
/**
* \defgroup FFT_Module Fast Fourier Transform module
*
* \code
* #include <unsupported/Eigen/FFT>
* \endcode
*
* This module provides Fast Fourier transformation, with a configurable backend
* implementation.
*
* The default implementation is based on kissfft. It is a small, free, and
* reasonably efficient default.
*
* There are currently two implementation backend:
*
* - fftw (http://www.fftw.org) : faster, GPL -- incompatible with Eigen in LGPL form, bigger code size.
* - MKL (http://en.wikipedia.org/wiki/Math_Kernel_Library) : fastest, commercial -- may be incompatible with Eigen in GPL form.
*
* \section FFTDesign Design
*
* The following design decisions were made concerning scaling and
* half-spectrum for real FFT.
*
* The intent is to facilitate generic programming and ease migrating code
* from Matlab/octave.
* We think the default behavior of Eigen/FFT should favor correctness and
* generality over speed. Of course, the caller should be able to "opt-out" from this
* behavior and get the speed increase if they want it.
*
* 1) %Scaling:
* Other libraries (FFTW,IMKL,KISSFFT) do not perform scaling, so there
* is a constant gain incurred after the forward&inverse transforms , so
* IFFT(FFT(x)) = Kx; this is done to avoid a vector-by-value multiply.
* The downside is that algorithms that worked correctly in Matlab/octave
* don't behave the same way once implemented in C++.
*
* How Eigen/FFT differs: invertible scaling is performed so IFFT( FFT(x) ) = x.
*
* 2) Real FFT half-spectrum
* Other libraries use only half the frequency spectrum (plus one extra
* sample for the Nyquist bin) for a real FFT, the other half is the
* conjugate-symmetric of the first half. This saves them a copy and some
* memory. The downside is the caller needs to have special logic for the
* number of bins in complex vs real.
*
* How Eigen/FFT differs: The full spectrum is returned from the forward
* transform. This facilitates generic template programming by obviating
* separate specializations for real vs complex. On the inverse
* transform, only half the spectrum is actually used if the output type is real.
*/
#ifdef EIGEN_FFTW_DEFAULT
// FFTW: faster, GPL -- incompatible with Eigen in LGPL form, bigger code size
# include <fftw3.h>
# include "src/FFT/ei_fftw_impl.h"
namespace Eigen {
//template <typename T> typedef struct internal::fftw_impl default_fft_impl; this does not work
template <typename T> struct default_fft_impl : public internal::fftw_impl<T> {};
}
#elif defined EIGEN_MKL_DEFAULT
// TODO
// intel Math Kernel Library: fastest, commercial -- may be incompatible with Eigen in GPL form
# include "src/FFT/ei_imklfft_impl.h"
namespace Eigen {
template <typename T> struct default_fft_impl : public internal::imklfft_impl {};
}
#else
// internal::kissfft_impl: small, free, reasonably efficient default, derived from kissfft
//
# include "src/FFT/ei_kissfft_impl.h"
namespace Eigen {
template <typename T>
struct default_fft_impl : public internal::kissfft_impl<T> {};
}
#endif
namespace Eigen {
//
template<typename T_SrcMat,typename T_FftIfc> struct fft_fwd_proxy;
template<typename T_SrcMat,typename T_FftIfc> struct fft_inv_proxy;
namespace internal {
template<typename T_SrcMat,typename T_FftIfc>
struct traits< fft_fwd_proxy<T_SrcMat,T_FftIfc> >
{
typedef typename T_SrcMat::PlainObject ReturnType;
};
template<typename T_SrcMat,typename T_FftIfc>
struct traits< fft_inv_proxy<T_SrcMat,T_FftIfc> >
{
typedef typename T_SrcMat::PlainObject ReturnType;
};
}
template<typename T_SrcMat,typename T_FftIfc>
struct fft_fwd_proxy
: public ReturnByValue<fft_fwd_proxy<T_SrcMat,T_FftIfc> >
{
typedef DenseIndex Index;
fft_fwd_proxy(const T_SrcMat& src,T_FftIfc & fft, Index nfft) : m_src(src),m_ifc(fft), m_nfft(nfft) {}
template<typename T_DestMat> void evalTo(T_DestMat& dst) const;
Index rows() const { return m_src.rows(); }
Index cols() const { return m_src.cols(); }
protected:
const T_SrcMat & m_src;
T_FftIfc & m_ifc;
Index m_nfft;
private:
fft_fwd_proxy& operator=(const fft_fwd_proxy&);
};
template<typename T_SrcMat,typename T_FftIfc>
struct fft_inv_proxy
: public ReturnByValue<fft_inv_proxy<T_SrcMat,T_FftIfc> >
{
typedef DenseIndex Index;
fft_inv_proxy(const T_SrcMat& src,T_FftIfc & fft, Index nfft) : m_src(src),m_ifc(fft), m_nfft(nfft) {}
template<typename T_DestMat> void evalTo(T_DestMat& dst) const;
Index rows() const { return m_src.rows(); }
Index cols() const { return m_src.cols(); }
protected:
const T_SrcMat & m_src;
T_FftIfc & m_ifc;
Index m_nfft;
private:
fft_inv_proxy& operator=(const fft_inv_proxy&);
};
template <typename T_Scalar,
typename T_Impl=default_fft_impl<T_Scalar> >
class FFT
{
public:
typedef T_Impl impl_type;
typedef DenseIndex Index;
typedef typename impl_type::Scalar Scalar;
typedef typename impl_type::Complex Complex;
enum Flag {
Default=0, // goof proof
Unscaled=1,
HalfSpectrum=2,
// SomeOtherSpeedOptimization=4
Speedy=32767
};
FFT( const impl_type & impl=impl_type() , Flag flags=Default ) :m_impl(impl),m_flag(flags) { }
inline
bool HasFlag(Flag f) const { return (m_flag & (int)f) == f;}
inline
void SetFlag(Flag f) { m_flag |= (int)f;}
inline
void ClearFlag(Flag f) { m_flag &= (~(int)f);}
inline
void fwd( Complex * dst, const Scalar * src, Index nfft)
{
m_impl.fwd(dst,src,static_cast<int>(nfft));
if ( HasFlag(HalfSpectrum) == false)
ReflectSpectrum(dst,nfft);
}
inline
void fwd( Complex * dst, const Complex * src, Index nfft)
{
m_impl.fwd(dst,src,static_cast<int>(nfft));
}
/*
inline
void fwd2(Complex * dst, const Complex * src, int n0,int n1)
{
m_impl.fwd2(dst,src,n0,n1);
}
*/
template <typename _Input>
inline
void fwd( std::vector<Complex> & dst, const std::vector<_Input> & src)
{
if ( NumTraits<_Input>::IsComplex == 0 && HasFlag(HalfSpectrum) )
dst.resize( (src.size()>>1)+1); // half the bins + Nyquist bin
else
dst.resize(src.size());
fwd(&dst[0],&src[0],src.size());
}
template<typename InputDerived, typename ComplexDerived>
inline
void fwd( MatrixBase<ComplexDerived> & dst, const MatrixBase<InputDerived> & src, Index nfft=-1)
{
typedef typename ComplexDerived::Scalar dst_type;
typedef typename InputDerived::Scalar src_type;
EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputDerived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived,InputDerived) // size at compile-time
EIGEN_STATIC_ASSERT((internal::is_same<dst_type, Complex>::value),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
EIGEN_STATIC_ASSERT(int(InputDerived::Flags)&int(ComplexDerived::Flags)&DirectAccessBit,
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
if (nfft<1)
nfft = src.size();
if ( NumTraits< src_type >::IsComplex == 0 && HasFlag(HalfSpectrum) )
dst.derived().resize( (nfft>>1)+1);
else
dst.derived().resize(nfft);
if ( src.innerStride() != 1 || src.size() < nfft ) {
Matrix<src_type,1,Dynamic> tmp;
if (src.size()<nfft) {
tmp.setZero(nfft);
tmp.block(0,0,src.size(),1 ) = src;
}else{
tmp = src;
}
fwd( &dst[0],&tmp[0],nfft );
}else{
fwd( &dst[0],&src[0],nfft );
}
}
template<typename InputDerived>
inline
fft_fwd_proxy< MatrixBase<InputDerived>, FFT<T_Scalar,T_Impl> >
fwd( const MatrixBase<InputDerived> & src, Index nfft=-1)
{
return fft_fwd_proxy< MatrixBase<InputDerived> ,FFT<T_Scalar,T_Impl> >( src, *this,nfft );
}
template<typename InputDerived>
inline
fft_inv_proxy< MatrixBase<InputDerived>, FFT<T_Scalar,T_Impl> >
inv( const MatrixBase<InputDerived> & src, Index nfft=-1)
{
return fft_inv_proxy< MatrixBase<InputDerived> ,FFT<T_Scalar,T_Impl> >( src, *this,nfft );
}
inline
void inv( Complex * dst, const Complex * src, Index nfft)
{
m_impl.inv( dst,src,static_cast<int>(nfft) );
if ( HasFlag( Unscaled ) == false)
scale(dst,Scalar(1./nfft),nfft); // scale the time series
}
inline
void inv( Scalar * dst, const Complex * src, Index nfft)
{
m_impl.inv( dst,src,static_cast<int>(nfft) );
if ( HasFlag( Unscaled ) == false)
scale(dst,Scalar(1./nfft),nfft); // scale the time series
}
template<typename OutputDerived, typename ComplexDerived>
inline
void inv( MatrixBase<OutputDerived> & dst, const MatrixBase<ComplexDerived> & src, Index nfft=-1)
{
typedef typename ComplexDerived::Scalar src_type;
typedef typename OutputDerived::Scalar dst_type;
const bool realfft= (NumTraits<dst_type>::IsComplex == 0);
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OutputDerived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived,OutputDerived) // size at compile-time
EIGEN_STATIC_ASSERT((internal::is_same<src_type, Complex>::value),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
EIGEN_STATIC_ASSERT(int(OutputDerived::Flags)&int(ComplexDerived::Flags)&DirectAccessBit,
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
if (nfft<1) { //automatic FFT size determination
if ( realfft && HasFlag(HalfSpectrum) )
nfft = 2*(src.size()-1); //assume even fft size
else
nfft = src.size();
}
dst.derived().resize( nfft );
// check for nfft that does not fit the input data size
Index resize_input= ( realfft && HasFlag(HalfSpectrum) )
? ( (nfft/2+1) - src.size() )
: ( nfft - src.size() );
if ( src.innerStride() != 1 || resize_input ) {
// if the vector is strided, then we need to copy it to a packed temporary
Matrix<src_type,1,Dynamic> tmp;
if ( resize_input ) {
size_t ncopy = (std::min)(src.size(),src.size() + resize_input);
tmp.setZero(src.size() + resize_input);
if ( realfft && HasFlag(HalfSpectrum) ) {
// pad at the Nyquist bin
tmp.head(ncopy) = src.head(ncopy);
tmp(ncopy-1) = real(tmp(ncopy-1)); // enforce real-only Nyquist bin
}else{
size_t nhead,ntail;
nhead = 1+ncopy/2-1; // range [0:pi)
ntail = ncopy/2-1; // range (-pi:0)
tmp.head(nhead) = src.head(nhead);
tmp.tail(ntail) = src.tail(ntail);
if (resize_input<0) { //shrinking -- create the Nyquist bin as the average of the two bins that fold into it
tmp(nhead) = ( src(nfft/2) + src( src.size() - nfft/2 ) )*src_type(.5);
}else{ // expanding -- split the old Nyquist bin into two halves
tmp(nhead) = src(nhead) * src_type(.5);
tmp(tmp.size()-nhead) = tmp(nhead);
}
}
}else{
tmp = src;
}
inv( &dst[0],&tmp[0], nfft);
}else{
inv( &dst[0],&src[0], nfft);
}
}
template <typename _Output>
inline
void inv( std::vector<_Output> & dst, const std::vector<Complex> & src,Index nfft=-1)
{
if (nfft<1)
nfft = ( NumTraits<_Output>::IsComplex == 0 && HasFlag(HalfSpectrum) ) ? 2*(src.size()-1) : src.size();
dst.resize( nfft );
inv( &dst[0],&src[0],nfft);
}
/*
// TODO: multi-dimensional FFTs
inline
void inv2(Complex * dst, const Complex * src, int n0,int n1)
{
m_impl.inv2(dst,src,n0,n1);
if ( HasFlag( Unscaled ) == false)
scale(dst,1./(n0*n1),n0*n1);
}
*/
inline
impl_type & impl() {return m_impl;}
private:
template <typename T_Data>
inline
void scale(T_Data * x,Scalar s,Index nx)
{
#if 1
for (int k=0;k<nx;++k)
*x++ *= s;
#else
if ( ((ptrdiff_t)x) & 15 )
Matrix<T_Data, Dynamic, 1>::Map(x,nx) *= s;
else
Matrix<T_Data, Dynamic, 1>::MapAligned(x,nx) *= s;
//Matrix<T_Data, Dynamic, Dynamic>::Map(x,nx) * s;
#endif
}
inline
void ReflectSpectrum(Complex * freq, Index nfft)
{
// create the implicit right-half spectrum (conjugate-mirror of the left-half)
Index nhbins=(nfft>>1)+1;
for (Index k=nhbins;k < nfft; ++k )
freq[k] = conj(freq[nfft-k]);
}
impl_type m_impl;
int m_flag;
};
template<typename T_SrcMat,typename T_FftIfc>
template<typename T_DestMat> inline
void fft_fwd_proxy<T_SrcMat,T_FftIfc>::evalTo(T_DestMat& dst) const
{
m_ifc.fwd( dst, m_src, m_nfft);
}
template<typename T_SrcMat,typename T_FftIfc>
template<typename T_DestMat> inline
void fft_inv_proxy<T_SrcMat,T_FftIfc>::evalTo(T_DestMat& dst) const
{
m_ifc.inv( dst, m_src, m_nfft);
}
}
#endif
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

View File

@@ -0,0 +1,45 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.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_ITERATIVE_SOLVERS_MODULE_H
#define EIGEN_ITERATIVE_SOLVERS_MODULE_H
#include <Eigen/Sparse>
/**
* \defgroup IterativeSolvers_Module Iterative solvers module
* This module aims to provide various iterative linear and non linear solver algorithms.
* It currently provides:
* - a constrained conjugate gradient
* - a Householder GMRES implementation
* \code
* #include <unsupported/Eigen/IterativeSolvers>
* \endcode
*/
//@{
#include "../../Eigen/src/misc/Solve.h"
#include "../../Eigen/src/misc/SparseSolve.h"
#ifndef EIGEN_MPL2_ONLY
#include "src/IterativeSolvers/IterationController.h"
#include "src/IterativeSolvers/ConstrainedConjGrad.h"
#endif
#include "src/IterativeSolvers/IncompleteLU.h"
#include "../../Eigen/Jacobi"
#include "../../Eigen/Householder"
#include "src/IterativeSolvers/GMRES.h"
#include "src/IterativeSolvers/IncompleteCholesky.h"
//#include "src/IterativeSolvers/SSORPreconditioner.h"
#include "src/IterativeSolvers/MINRES.h"
//@}
#endif // EIGEN_ITERATIVE_SOLVERS_MODULE_H

View File

@@ -0,0 +1,34 @@
// 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_KRONECKER_PRODUCT_MODULE_H
#define EIGEN_KRONECKER_PRODUCT_MODULE_H
#include "../../Eigen/Core"
#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
namespace Eigen {
/**
* \defgroup KroneckerProduct_Module KroneckerProduct module
*
* This module contains an experimental Kronecker product implementation.
*
* \code
* #include <Eigen/KroneckerProduct>
* \endcode
*/
} // namespace Eigen
#include "src/KroneckerProduct/KroneckerTensorProduct.h"
#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_KRONECKER_PRODUCT_MODULE_H

View File

@@ -0,0 +1,45 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
//
// 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_LEVENBERGMARQUARDT_MODULE
#define EIGEN_LEVENBERGMARQUARDT_MODULE
// #include <vector>
#include <Eigen/Core>
#include <Eigen/Jacobi>
#include <Eigen/QR>
#include <unsupported/Eigen/NumericalDiff>
#include <Eigen/SparseQR>
/**
* \defgroup LevenbergMarquardt_Module Levenberg-Marquardt module
*
* \code
* #include </Eigen/LevenbergMarquardt>
* \endcode
*
*
*/
#include "Eigen/SparseCore"
#ifndef EIGEN_PARSED_BY_DOXYGEN
#include "src/LevenbergMarquardt/LMqrsolv.h"
#include "src/LevenbergMarquardt/LMcovar.h"
#include "src/LevenbergMarquardt/LMpar.h"
#endif
#include "src/LevenbergMarquardt/LevenbergMarquardt.h"
#include "src/LevenbergMarquardt/LMonestep.h"
#endif // EIGEN_LEVENBERGMARQUARDT_MODULE

View File

@@ -0,0 +1,203 @@
// This file is part of a joint effort between Eigen, a lightweight C++ template library
// for linear algebra, and MPFR C++, a C++ interface to MPFR library (http://www.holoborodko.com/pavel/)
//
// Copyright (C) 2010-2012 Pavel Holoborodko <pavel@holoborodko.com>
// Copyright (C) 2010 Konstantin Holoborodko <konstantin@holoborodko.com>
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_MPREALSUPPORT_MODULE_H
#define EIGEN_MPREALSUPPORT_MODULE_H
#include <Eigen/Core>
#include <mpreal.h>
namespace Eigen {
/**
* \defgroup MPRealSupport_Module MPFRC++ Support module
* \code
* #include <Eigen/MPRealSupport>
* \endcode
*
* This module provides support for multi precision floating point numbers
* via the <a href="http://www.holoborodko.com/pavel/mpfr">MPFR C++</a>
* library which itself is built upon <a href="http://www.mpfr.org/">MPFR</a>/<a href="http://gmplib.org/">GMP</a>.
*
* You can find a copy of MPFR C++ that is known to be compatible in the unsupported/test/mpreal folder.
*
* Here is an example:
*
\code
#include <iostream>
#include <Eigen/MPRealSupport>
#include <Eigen/LU>
using namespace mpfr;
using namespace Eigen;
int main()
{
// set precision to 256 bits (double has only 53 bits)
mpreal::set_default_prec(256);
// Declare matrix and vector types with multi-precision scalar type
typedef Matrix<mpreal,Dynamic,Dynamic> MatrixXmp;
typedef Matrix<mpreal,Dynamic,1> VectorXmp;
MatrixXmp A = MatrixXmp::Random(100,100);
VectorXmp b = VectorXmp::Random(100);
// Solve Ax=b using LU
VectorXmp x = A.lu().solve(b);
std::cout << "relative error: " << (A*x - b).norm() / b.norm() << std::endl;
return 0;
}
\endcode
*
*/
template<> struct NumTraits<mpfr::mpreal>
: GenericNumTraits<mpfr::mpreal>
{
enum {
IsInteger = 0,
IsSigned = 1,
IsComplex = 0,
RequireInitialization = 1,
ReadCost = 10,
AddCost = 10,
MulCost = 40
};
typedef mpfr::mpreal Real;
typedef mpfr::mpreal NonInteger;
inline static Real highest (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(Precision); }
inline static Real lowest (long Precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(Precision); }
// Constants
inline static Real Pi (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_pi(Precision); }
inline static Real Euler (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_euler(Precision); }
inline static Real Log2 (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_log2(Precision); }
inline static Real Catalan (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_catalan(Precision); }
inline static Real epsilon (long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::machine_epsilon(Precision); }
inline static Real epsilon (const Real& x) { return mpfr::machine_epsilon(x); }
inline static Real dummy_precision()
{
unsigned int weak_prec = ((mpfr::mpreal::get_default_prec()-1) * 90) / 100;
return mpfr::machine_epsilon(weak_prec);
}
};
namespace internal {
template<> inline mpfr::mpreal random<mpfr::mpreal>()
{
return mpfr::random();
}
template<> inline mpfr::mpreal random<mpfr::mpreal>(const mpfr::mpreal& a, const mpfr::mpreal& b)
{
return a + (b-a) * random<mpfr::mpreal>();
}
inline bool isMuchSmallerThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
return mpfr::abs(a) <= mpfr::abs(b) * eps;
}
inline bool isApprox(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
return mpfr::isEqualFuzzy(a,b,eps);
}
inline bool isApproxOrLessThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps)
{
return a <= b || mpfr::isEqualFuzzy(a,b,eps);
}
template<> inline long double cast<mpfr::mpreal,long double>(const mpfr::mpreal& x)
{ return x.toLDouble(); }
template<> inline double cast<mpfr::mpreal,double>(const mpfr::mpreal& x)
{ return x.toDouble(); }
template<> inline long cast<mpfr::mpreal,long>(const mpfr::mpreal& x)
{ return x.toLong(); }
template<> inline int cast<mpfr::mpreal,int>(const mpfr::mpreal& x)
{ return int(x.toLong()); }
// Specialize GEBP kernel and traits for mpreal (no need for peeling, nor complicated stuff)
// This also permits to directly call mpfr's routines and avoid many temporaries produced by mpreal
template<>
class gebp_traits<mpfr::mpreal, mpfr::mpreal, false, false>
{
public:
typedef mpfr::mpreal ResScalar;
enum {
nr = 2, // must be 2 for proper packing...
mr = 1,
WorkSpaceFactor = nr,
LhsProgress = 1,
RhsProgress = 1
};
};
template<typename Index, int mr, int nr, bool ConjugateLhs, bool ConjugateRhs>
struct gebp_kernel<mpfr::mpreal,mpfr::mpreal,Index,mr,nr,ConjugateLhs,ConjugateRhs>
{
typedef mpfr::mpreal mpreal;
EIGEN_DONT_INLINE
void operator()(mpreal* res, Index resStride, const mpreal* blockA, const mpreal* blockB, Index rows, Index depth, Index cols, mpreal alpha,
Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, mpreal* /*unpackedB*/ = 0)
{
mpreal acc1, acc2, tmp;
if(strideA==-1) strideA = depth;
if(strideB==-1) strideB = depth;
for(Index j=0; j<cols; j+=nr)
{
Index actual_nr = (std::min<Index>)(nr,cols-j);
mpreal *C1 = res + j*resStride;
mpreal *C2 = res + (j+1)*resStride;
for(Index i=0; i<rows; i++)
{
mpreal *B = const_cast<mpreal*>(blockB) + j*strideB + offsetB*actual_nr;
mpreal *A = const_cast<mpreal*>(blockA) + i*strideA + offsetA;
acc1 = 0;
acc2 = 0;
for(Index k=0; k<depth; k++)
{
mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_ptr(), B[0].mpfr_ptr(), mpreal::get_default_rnd());
mpfr_add(acc1.mpfr_ptr(), acc1.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
if(actual_nr==2) {
mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_ptr(), B[1].mpfr_ptr(), mpreal::get_default_rnd());
mpfr_add(acc2.mpfr_ptr(), acc2.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
}
B+=actual_nr;
}
mpfr_mul(acc1.mpfr_ptr(), acc1.mpfr_ptr(), alpha.mpfr_ptr(), mpreal::get_default_rnd());
mpfr_add(C1[i].mpfr_ptr(), C1[i].mpfr_ptr(), acc1.mpfr_ptr(), mpreal::get_default_rnd());
if(actual_nr==2) {
mpfr_mul(acc2.mpfr_ptr(), acc2.mpfr_ptr(), alpha.mpfr_ptr(), mpreal::get_default_rnd());
mpfr_add(C2[i].mpfr_ptr(), C2[i].mpfr_ptr(), acc2.mpfr_ptr(), mpreal::get_default_rnd());
}
}
}
}
};
} // end namespace internal
}
#endif // EIGEN_MPREALSUPPORT_MODULE_H

View File

@@ -0,0 +1,447 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Jitse Niesen <jitse@maths.leeds.ac.uk>
// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
//
// 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_MATRIX_FUNCTIONS
#define EIGEN_MATRIX_FUNCTIONS
#include <cfloat>
#include <list>
#include <functional>
#include <iterator>
#include <Eigen/Core>
#include <Eigen/LU>
#include <Eigen/Eigenvalues>
/**
* \defgroup MatrixFunctions_Module Matrix functions module
* \brief This module aims to provide various methods for the computation of
* matrix functions.
*
* To use this module, add
* \code
* #include <unsupported/Eigen/MatrixFunctions>
* \endcode
* at the start of your source file.
*
* This module defines the following MatrixBase methods.
* - \ref matrixbase_cos "MatrixBase::cos()", for computing the matrix cosine
* - \ref matrixbase_cosh "MatrixBase::cosh()", for computing the matrix hyperbolic cosine
* - \ref matrixbase_exp "MatrixBase::exp()", for computing the matrix exponential
* - \ref matrixbase_log "MatrixBase::log()", for computing the matrix logarithm
* - \ref matrixbase_pow "MatrixBase::pow()", for computing the matrix power
* - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
* - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
* - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
* - \ref matrixbase_sqrt "MatrixBase::sqrt()", for computing the matrix square root
*
* These methods are the main entry points to this module.
*
* %Matrix functions are defined as follows. Suppose that \f$ f \f$
* is an entire function (that is, a function on the complex plane
* that is everywhere complex differentiable). Then its Taylor
* series
* \f[ f(0) + f'(0) x + \frac{f''(0)}{2} x^2 + \frac{f'''(0)}{3!} x^3 + \cdots \f]
* converges to \f$ f(x) \f$. In this case, we can define the matrix
* function by the same series:
* \f[ f(M) = f(0) + f'(0) M + \frac{f''(0)}{2} M^2 + \frac{f'''(0)}{3!} M^3 + \cdots \f]
*
*/
#include "src/MatrixFunctions/MatrixExponential.h"
#include "src/MatrixFunctions/MatrixFunction.h"
#include "src/MatrixFunctions/MatrixSquareRoot.h"
#include "src/MatrixFunctions/MatrixLogarithm.h"
#include "src/MatrixFunctions/MatrixPower.h"
/**
\page matrixbaseextra_page
\ingroup MatrixFunctions_Module
\section matrixbaseextra MatrixBase methods defined in the MatrixFunctions module
The remainder of the page documents the following MatrixBase methods
which are defined in the MatrixFunctions module.
\subsection matrixbase_cos MatrixBase::cos()
Compute the matrix cosine.
\code
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const
\endcode
\param[in] M a square matrix.
\returns expression representing \f$ \cos(M) \f$.
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cos().
\sa \ref matrixbase_sin "sin()" for an example.
\subsection matrixbase_cosh MatrixBase::cosh()
Compute the matrix hyberbolic cosine.
\code
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cosh() const
\endcode
\param[in] M a square matrix.
\returns expression representing \f$ \cosh(M) \f$
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cosh().
\sa \ref matrixbase_sinh "sinh()" for an example.
\subsection matrixbase_exp MatrixBase::exp()
Compute the matrix exponential.
\code
const MatrixExponentialReturnValue<Derived> MatrixBase<Derived>::exp() const
\endcode
\param[in] M matrix whose exponential is to be computed.
\returns expression representing the matrix exponential of \p M.
The matrix exponential of \f$ M \f$ is defined by
\f[ \exp(M) = \sum_{k=0}^\infty \frac{M^k}{k!}. \f]
The matrix exponential can be used to solve linear ordinary
differential equations: the solution of \f$ y' = My \f$ with the
initial condition \f$ y(0) = y_0 \f$ is given by
\f$ y(t) = \exp(M) y_0 \f$.
The cost of the computation is approximately \f$ 20 n^3 \f$ for
matrices of size \f$ n \f$. The number 20 depends weakly on the
norm of the matrix.
The matrix exponential is computed using the scaling-and-squaring
method combined with Pad&eacute; approximation. The matrix is first
rescaled, then the exponential of the reduced matrix is computed
approximant, and then the rescaling is undone by repeated
squaring. The degree of the Pad&eacute; approximant is chosen such
that the approximation error is less than the round-off
error. However, errors may accumulate during the squaring phase.
Details of the algorithm can be found in: Nicholas J. Higham, "The
scaling and squaring method for the matrix exponential revisited,"
<em>SIAM J. %Matrix Anal. Applic.</em>, <b>26</b>:1179&ndash;1193,
2005.
Example: The following program checks that
\f[ \exp \left[ \begin{array}{ccc}
0 & \frac14\pi & 0 \\
-\frac14\pi & 0 & 0 \\
0 & 0 & 0
\end{array} \right] = \left[ \begin{array}{ccc}
\frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
\frac12\sqrt2 & \frac12\sqrt2 & 0 \\
0 & 0 & 1
\end{array} \right]. \f]
This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
the z-axis.
\include MatrixExponential.cpp
Output: \verbinclude MatrixExponential.out
\note \p M has to be a matrix of \c float, \c double, \c long double
\c complex<float>, \c complex<double>, or \c complex<long double> .
\subsection matrixbase_log MatrixBase::log()
Compute the matrix logarithm.
\code
const MatrixLogarithmReturnValue<Derived> MatrixBase<Derived>::log() const
\endcode
\param[in] M invertible matrix whose logarithm is to be computed.
\returns expression representing the matrix logarithm root of \p M.
The matrix logarithm of \f$ M \f$ is a matrix \f$ X \f$ such that
\f$ \exp(X) = M \f$ where exp denotes the matrix exponential. As for
the scalar logarithm, the equation \f$ \exp(X) = M \f$ may have
multiple solutions; this function returns a matrix whose eigenvalues
have imaginary part in the interval \f$ (-\pi,\pi] \f$.
In the real case, the matrix \f$ M \f$ should be invertible and
it should have no eigenvalues which are real and negative (pairs of
complex conjugate eigenvalues are allowed). In the complex case, it
only needs to be invertible.
This function computes the matrix logarithm using the Schur-Parlett
algorithm as implemented by MatrixBase::matrixFunction(). The
logarithm of an atomic block is computed by MatrixLogarithmAtomic,
which uses direct computation for 1-by-1 and 2-by-2 blocks and an
inverse scaling-and-squaring algorithm for bigger blocks, with the
square roots computed by MatrixBase::sqrt().
Details of the algorithm can be found in Section 11.6.2 of:
Nicholas J. Higham,
<em>Functions of Matrices: Theory and Computation</em>,
SIAM 2008. ISBN 978-0-898716-46-7.
Example: The following program checks that
\f[ \log \left[ \begin{array}{ccc}
\frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
\frac12\sqrt2 & \frac12\sqrt2 & 0 \\
0 & 0 & 1
\end{array} \right] = \left[ \begin{array}{ccc}
0 & \frac14\pi & 0 \\
-\frac14\pi & 0 & 0 \\
0 & 0 & 0
\end{array} \right]. \f]
This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
the z-axis. This is the inverse of the example used in the
documentation of \ref matrixbase_exp "exp()".
\include MatrixLogarithm.cpp
Output: \verbinclude MatrixLogarithm.out
\note \p M has to be a matrix of \c float, \c double, <tt>long
double</tt>, \c complex<float>, \c complex<double>, or \c complex<long
double> .
\sa MatrixBase::exp(), MatrixBase::matrixFunction(),
class MatrixLogarithmAtomic, MatrixBase::sqrt().
\subsection matrixbase_pow MatrixBase::pow()
Compute the matrix raised to arbitrary real power.
\code
const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(RealScalar p) const
\endcode
\param[in] M base of the matrix power, should be a square matrix.
\param[in] p exponent of the matrix power, should be real.
The matrix power \f$ M^p \f$ is defined as \f$ \exp(p \log(M)) \f$,
where exp denotes the matrix exponential, and log denotes the matrix
logarithm.
The matrix \f$ M \f$ should meet the conditions to be an argument of
matrix logarithm. If \p p is not of the real scalar type of \p M, it
is casted into the real scalar type of \p M.
This function computes the matrix power using the Schur-Pad&eacute;
algorithm as implemented by class MatrixPower. The exponent is split
into integral part and fractional part, where the fractional part is
in the interval \f$ (-1, 1) \f$. The main diagonal and the first
super-diagonal is directly computed.
Details of the algorithm can be found in: Nicholas J. Higham and
Lijing Lin, "A Schur-Pad&eacute; algorithm for fractional powers of a
matrix," <em>SIAM J. %Matrix Anal. Applic.</em>,
<b>32(3)</b>:1056&ndash;1078, 2011.
Example: The following program checks that
\f[ \left[ \begin{array}{ccc}
\cos1 & -\sin1 & 0 \\
\sin1 & \cos1 & 0 \\
0 & 0 & 1
\end{array} \right]^{\frac14\pi} = \left[ \begin{array}{ccc}
\frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
\frac12\sqrt2 & \frac12\sqrt2 & 0 \\
0 & 0 & 1
\end{array} \right]. \f]
This corresponds to \f$ \frac14\pi \f$ rotations of 1 radian around
the z-axis.
\include MatrixPower.cpp
Output: \verbinclude MatrixPower.out
MatrixBase::pow() is user-friendly. However, there are some
circumstances under which you should use class MatrixPower directly.
MatrixPower can save the result of Schur decomposition, so it's
better for computing various powers for the same matrix.
Example:
\include MatrixPower_optimal.cpp
Output: \verbinclude MatrixPower_optimal.out
\note \p M has to be a matrix of \c float, \c double, <tt>long
double</tt>, \c complex<float>, \c complex<double>, or \c complex<long
double> .
\sa MatrixBase::exp(), MatrixBase::log(), class MatrixPower.
\subsection matrixbase_matrixfunction MatrixBase::matrixFunction()
Compute a matrix function.
\code
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::matrixFunction(typename internal::stem_function<typename internal::traits<Derived>::Scalar>::type f) const
\endcode
\param[in] M argument of matrix function, should be a square matrix.
\param[in] f an entire function; \c f(x,n) should compute the n-th
derivative of f at x.
\returns expression representing \p f applied to \p M.
Suppose that \p M is a matrix whose entries have type \c Scalar.
Then, the second argument, \p f, should be a function with prototype
\code
ComplexScalar f(ComplexScalar, int)
\endcode
where \c ComplexScalar = \c std::complex<Scalar> if \c Scalar is
real (e.g., \c float or \c double) and \c ComplexScalar =
\c Scalar if \c Scalar is complex. The return value of \c f(x,n)
should be \f$ f^{(n)}(x) \f$, the n-th derivative of f at x.
This routine uses the algorithm described in:
Philip Davies and Nicholas J. Higham,
"A Schur-Parlett algorithm for computing matrix functions",
<em>SIAM J. %Matrix Anal. Applic.</em>, <b>25</b>:464&ndash;485, 2003.
The actual work is done by the MatrixFunction class.
Example: The following program checks that
\f[ \exp \left[ \begin{array}{ccc}
0 & \frac14\pi & 0 \\
-\frac14\pi & 0 & 0 \\
0 & 0 & 0
\end{array} \right] = \left[ \begin{array}{ccc}
\frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
\frac12\sqrt2 & \frac12\sqrt2 & 0 \\
0 & 0 & 1
\end{array} \right]. \f]
This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
the z-axis. This is the same example as used in the documentation
of \ref matrixbase_exp "exp()".
\include MatrixFunction.cpp
Output: \verbinclude MatrixFunction.out
Note that the function \c expfn is defined for complex numbers
\c x, even though the matrix \c A is over the reals. Instead of
\c expfn, we could also have used StdStemFunctions::exp:
\code
A.matrixFunction(StdStemFunctions<std::complex<double> >::exp, &B);
\endcode
\subsection matrixbase_sin MatrixBase::sin()
Compute the matrix sine.
\code
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const
\endcode
\param[in] M a square matrix.
\returns expression representing \f$ \sin(M) \f$.
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sin().
Example: \include MatrixSine.cpp
Output: \verbinclude MatrixSine.out
\subsection matrixbase_sinh MatrixBase::sinh()
Compute the matrix hyperbolic sine.
\code
MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sinh() const
\endcode
\param[in] M a square matrix.
\returns expression representing \f$ \sinh(M) \f$
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sinh().
Example: \include MatrixSinh.cpp
Output: \verbinclude MatrixSinh.out
\subsection matrixbase_sqrt MatrixBase::sqrt()
Compute the matrix square root.
\code
const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
\endcode
\param[in] M invertible matrix whose square root is to be computed.
\returns expression representing the matrix square root of \p M.
The matrix square root of \f$ M \f$ is the matrix \f$ M^{1/2} \f$
whose square is the original matrix; so if \f$ S = M^{1/2} \f$ then
\f$ S^2 = M \f$.
In the <b>real case</b>, the matrix \f$ M \f$ should be invertible and
it should have no eigenvalues which are real and negative (pairs of
complex conjugate eigenvalues are allowed). In that case, the matrix
has a square root which is also real, and this is the square root
computed by this function.
The matrix square root is computed by first reducing the matrix to
quasi-triangular form with the real Schur decomposition. The square
root of the quasi-triangular matrix can then be computed directly. The
cost is approximately \f$ 25 n^3 \f$ real flops for the real Schur
decomposition and \f$ 3\frac13 n^3 \f$ real flops for the remainder
(though the computation time in practice is likely more than this
indicates).
Details of the algorithm can be found in: Nicholas J. Highan,
"Computing real square roots of a real matrix", <em>Linear Algebra
Appl.</em>, 88/89:405&ndash;430, 1987.
If the matrix is <b>positive-definite symmetric</b>, then the square
root is also positive-definite symmetric. In this case, it is best to
use SelfAdjointEigenSolver::operatorSqrt() to compute it.
In the <b>complex case</b>, the matrix \f$ M \f$ should be invertible;
this is a restriction of the algorithm. The square root computed by
this algorithm is the one whose eigenvalues have an argument in the
interval \f$ (-\frac12\pi, \frac12\pi] \f$. This is the usual branch
cut.
The computation is the same as in the real case, except that the
complex Schur decomposition is used to reduce the matrix to a
triangular matrix. The theoretical cost is the same. Details are in:
&Aring;ke Bj&ouml;rck and Sven Hammarling, "A Schur method for the
square root of a matrix", <em>Linear Algebra Appl.</em>,
52/53:127&ndash;140, 1983.
Example: The following program checks that the square root of
\f[ \left[ \begin{array}{cc}
\cos(\frac13\pi) & -\sin(\frac13\pi) \\
\sin(\frac13\pi) & \cos(\frac13\pi)
\end{array} \right], \f]
corresponding to a rotation over 60 degrees, is a rotation over 30 degrees:
\f[ \left[ \begin{array}{cc}
\cos(\frac16\pi) & -\sin(\frac16\pi) \\
\sin(\frac16\pi) & \cos(\frac16\pi)
\end{array} \right]. \f]
\include MatrixSquareRoot.cpp
Output: \verbinclude MatrixSquareRoot.out
\sa class RealSchur, class ComplexSchur, class MatrixSquareRoot,
SelfAdjointEigenSolver::operatorSqrt().
*/
#endif // EIGEN_MATRIX_FUNCTIONS

View File

@@ -0,0 +1,24 @@
// 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_MOREVECTORIZATION_MODULE_H
#define EIGEN_MOREVECTORIZATION_MODULE_H
#include <Eigen/Core>
namespace Eigen {
/**
* \defgroup MoreVectorization More vectorization module
*/
}
#include "src/MoreVectorization/MathFunctions.h"
#endif // EIGEN_MOREVECTORIZATION_MODULE_H

View File

@@ -0,0 +1,134 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
//
// 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_NONLINEAROPTIMIZATION_MODULE
#define EIGEN_NONLINEAROPTIMIZATION_MODULE
#include <vector>
#include <Eigen/Core>
#include <Eigen/Jacobi>
#include <Eigen/QR>
#include <unsupported/Eigen/NumericalDiff>
/**
* \defgroup NonLinearOptimization_Module Non linear optimization module
*
* \code
* #include <unsupported/Eigen/NonLinearOptimization>
* \endcode
*
* This module provides implementation of two important algorithms in non linear
* optimization. In both cases, we consider a system of non linear functions. Of
* course, this should work, and even work very well if those functions are
* actually linear. But if this is so, you should probably better use other
* methods more fitted to this special case.
*
* One algorithm allows to find an extremum of such a system (Levenberg
* Marquardt algorithm) and the second one is used to find
* a zero for the system (Powell hybrid "dogleg" method).
*
* This code is a port of minpack (http://en.wikipedia.org/wiki/MINPACK).
* Minpack is a very famous, old, robust and well-reknown package, written in
* fortran. Those implementations have been carefully tuned, tested, and used
* for several decades.
*
* The original fortran code was automatically translated using f2c (http://en.wikipedia.org/wiki/F2c) in C,
* then c++, and then cleaned by several different authors.
* The last one of those cleanings being our starting point :
* http://devernay.free.fr/hacks/cminpack.html
*
* Finally, we ported this code to Eigen, creating classes and API
* coherent with Eigen. When possible, we switched to Eigen
* implementation, such as most linear algebra (vectors, matrices, stable norms).
*
* Doing so, we were very careful to check the tests we setup at the very
* beginning, which ensure that the same results are found.
*
* \section Tests Tests
*
* The tests are placed in the file unsupported/test/NonLinear.cpp.
*
* There are two kinds of tests : those that come from examples bundled with cminpack.
* They guaranty we get the same results as the original algorithms (value for 'x',
* for the number of evaluations of the function, and for the number of evaluations
* of the jacobian if ever).
*
* Other tests were added by myself at the very beginning of the
* process and check the results for levenberg-marquardt using the reference data
* on http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml. Since then i've
* carefully checked that the same results were obtained when modifiying the
* code. Please note that we do not always get the exact same decimals as they do,
* but this is ok : they use 128bits float, and we do the tests using the C type 'double',
* which is 64 bits on most platforms (x86 and amd64, at least).
* I've performed those tests on several other implementations of levenberg-marquardt, and
* (c)minpack performs VERY well compared to those, both in accuracy and speed.
*
* The documentation for running the tests is on the wiki
* http://eigen.tuxfamily.org/index.php?title=Tests
*
* \section API API : overview of methods
*
* Both algorithms can use either the jacobian (provided by the user) or compute
* an approximation by themselves (actually using Eigen \ref NumericalDiff_Module).
* The part of API referring to the latter use 'NumericalDiff' in the method names
* (exemple: LevenbergMarquardt.minimizeNumericalDiff() )
*
* The methods LevenbergMarquardt.lmder1()/lmdif1()/lmstr1() and
* HybridNonLinearSolver.hybrj1()/hybrd1() are specific methods from the original
* minpack package that you probably should NOT use until you are porting a code that
* was previously using minpack. They just define a 'simple' API with default values
* for some parameters.
*
* All algorithms are provided using Two APIs :
* - one where the user inits the algorithm, and uses '*OneStep()' as much as he wants :
* this way the caller have control over the steps
* - one where the user just calls a method (optimize() or solve()) which will
* handle the loop: init + loop until a stop condition is met. Those are provided for
* convenience.
*
* As an example, the method LevenbergMarquardt::minimize() is
* implemented as follow :
* \code
* Status LevenbergMarquardt<FunctorType,Scalar>::minimize(FVectorType &x, const int mode)
* {
* Status status = minimizeInit(x, mode);
* do {
* status = minimizeOneStep(x, mode);
* } while (status==Running);
* return status;
* }
* \endcode
*
* \section examples Examples
*
* The easiest way to understand how to use this module is by looking at the many examples in the file
* unsupported/test/NonLinearOptimization.cpp.
*/
#ifndef EIGEN_PARSED_BY_DOXYGEN
#include "src/NonLinearOptimization/qrsolv.h"
#include "src/NonLinearOptimization/r1updt.h"
#include "src/NonLinearOptimization/r1mpyq.h"
#include "src/NonLinearOptimization/rwupdt.h"
#include "src/NonLinearOptimization/fdjac1.h"
#include "src/NonLinearOptimization/lmpar.h"
#include "src/NonLinearOptimization/dogleg.h"
#include "src/NonLinearOptimization/covar.h"
#include "src/NonLinearOptimization/chkder.h"
#endif
#include "src/NonLinearOptimization/HybridNonLinearSolver.h"
#include "src/NonLinearOptimization/LevenbergMarquardt.h"
#endif // EIGEN_NONLINEAROPTIMIZATION_MODULE

View File

@@ -0,0 +1,56 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
//
// 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_NUMERICALDIFF_MODULE
#define EIGEN_NUMERICALDIFF_MODULE
#include <Eigen/Core>
namespace Eigen {
/**
* \defgroup NumericalDiff_Module Numerical differentiation module
*
* \code
* #include <unsupported/Eigen/NumericalDiff>
* \endcode
*
* See http://en.wikipedia.org/wiki/Numerical_differentiation
*
* Warning : this should NOT be confused with automatic differentiation, which
* is a different method and has its own module in Eigen : \ref
* AutoDiff_Module.
*
* Currently only "Forward" and "Central" schemes are implemented. Those
* are basic methods, and there exist some more elaborated way of
* computing such approximates. They are implemented using both
* proprietary and free software, and usually requires linking to an
* external library. It is very easy for you to write a functor
* using such software, and the purpose is quite orthogonal to what we
* want to achieve with Eigen.
*
* This is why we will not provide wrappers for every great numerical
* differentiation software that exist, but should rather stick with those
* basic ones, that still are useful for testing.
*
* Also, the \ref NonLinearOptimization_Module needs this in order to
* provide full features compatibility with the original (c)minpack
* package.
*
*/
}
//@{
#include "src/NumericalDiff/NumericalDiff.h"
//@}
#endif // EIGEN_NUMERICALDIFF_MODULE

View File

@@ -0,0 +1,322 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_OPENGL_MODULE
#define EIGEN_OPENGL_MODULE
#include <Eigen/Geometry>
#if defined(__APPLE_CC__)
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
namespace Eigen {
/**
* \defgroup OpenGLSUpport_Module OpenGL Support module
*
* This module provides wrapper functions for a couple of OpenGL functions
* which simplify the way to pass Eigen's object to openGL.
* Here is an exmaple:
*
* \code
* // You need to add path_to_eigen/unsupported to your include path.
* #include <Eigen/OpenGLSupport>
* // ...
* Vector3f x, y;
* Matrix3f rot;
*
* glVertex(y + x * rot);
*
* Quaternion q;
* glRotate(q);
*
* // ...
* \endcode
*
*/
//@{
#define EIGEN_GL_FUNC_DECLARATION(FUNC) \
namespace internal { \
template< typename XprType, \
typename Scalar = typename XprType::Scalar, \
int Rows = XprType::RowsAtCompileTime, \
int Cols = XprType::ColsAtCompileTime, \
bool IsGLCompatible = bool(XprType::Flags&LinearAccessBit) \
&& bool(XprType::Flags&DirectAccessBit) \
&& (XprType::IsVectorAtCompileTime || (XprType::Flags&RowMajorBit)==0)> \
struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl); \
\
template<typename XprType, typename Scalar, int Rows, int Cols> \
struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType,Scalar,Rows,Cols,false> { \
inline static void run(const XprType& p) { \
EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<typename plain_matrix_type_column_major<XprType>::type>::run(p); } \
}; \
} \
\
template<typename Derived> inline void FUNC(const Eigen::DenseBase<Derived>& p) { \
EIGEN_CAT(EIGEN_CAT(internal::gl_,FUNC),_impl)<Derived>::run(p.derived()); \
}
#define EIGEN_GL_FUNC_SPECIALIZATION_MAT(FUNC,SCALAR,ROWS,COLS,SUFFIX) \
namespace internal { \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, ROWS, COLS, true> { \
inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \
}; \
}
#define EIGEN_GL_FUNC_SPECIALIZATION_VEC(FUNC,SCALAR,SIZE,SUFFIX) \
namespace internal { \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, SIZE, 1, true> { \
inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \
}; \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, 1, SIZE, true> { \
inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \
}; \
}
EIGEN_GL_FUNC_DECLARATION (glVertex)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 2,2iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 2,2sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 2,2fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 2,2dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 3,3iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 3,3sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 3,3dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 4,4iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 4,4sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 4,4fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 4,4dv)
EIGEN_GL_FUNC_DECLARATION (glTexCoord)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 2,2iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 2,2sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 2,2fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 2,2dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 3,3iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 3,3sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 3,3dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 4,4iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 4,4sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 4,4fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 4,4dv)
EIGEN_GL_FUNC_DECLARATION (glColor)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 2,2iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 2,2sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 2,2fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 2,2dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 3,3iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 3,3sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 3,3dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 4,4iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 4,4sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 4,4fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 4,4dv)
EIGEN_GL_FUNC_DECLARATION (glNormal)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,int, 3,3iv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,short, 3,3sv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,double, 3,3dv)
inline void glScale2fv(const float* v) { glScalef(v[0], v[1], 1.f); }
inline void glScale2dv(const double* v) { glScaled(v[0], v[1], 1.0); }
inline void glScale3fv(const float* v) { glScalef(v[0], v[1], v[2]); }
inline void glScale3dv(const double* v) { glScaled(v[0], v[1], v[2]); }
EIGEN_GL_FUNC_DECLARATION (glScale)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,float, 2,2fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,double, 2,2dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,double, 3,3dv)
template<typename Scalar> void glScale(const UniformScaling<Scalar>& s) { glScale(Matrix<Scalar,3,1>::Constant(s.factor())); }
inline void glTranslate2fv(const float* v) { glTranslatef(v[0], v[1], 0.f); }
inline void glTranslate2dv(const double* v) { glTranslated(v[0], v[1], 0.0); }
inline void glTranslate3fv(const float* v) { glTranslatef(v[0], v[1], v[2]); }
inline void glTranslate3dv(const double* v) { glTranslated(v[0], v[1], v[2]); }
EIGEN_GL_FUNC_DECLARATION (glTranslate)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,float, 2,2fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,double, 2,2dv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,float, 3,3fv)
EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,double, 3,3dv)
template<typename Scalar> void glTranslate(const Translation<Scalar,2>& t) { glTranslate(t.vector()); }
template<typename Scalar> void glTranslate(const Translation<Scalar,3>& t) { glTranslate(t.vector()); }
EIGEN_GL_FUNC_DECLARATION (glMultMatrix)
EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix,float, 4,4,f)
EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix,double, 4,4,d)
template<typename Scalar> void glMultMatrix(const Transform<Scalar,3,Affine>& t) { glMultMatrix(t.matrix()); }
template<typename Scalar> void glMultMatrix(const Transform<Scalar,3,Projective>& t) { glMultMatrix(t.matrix()); }
template<typename Scalar> void glMultMatrix(const Transform<Scalar,3,AffineCompact>& t) { glMultMatrix(Transform<Scalar,3,Affine>(t).matrix()); }
EIGEN_GL_FUNC_DECLARATION (glLoadMatrix)
EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix,float, 4,4,f)
EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix,double, 4,4,d)
template<typename Scalar> void glLoadMatrix(const Transform<Scalar,3,Affine>& t) { glLoadMatrix(t.matrix()); }
template<typename Scalar> void glLoadMatrix(const Transform<Scalar,3,Projective>& t) { glLoadMatrix(t.matrix()); }
template<typename Scalar> void glLoadMatrix(const Transform<Scalar,3,AffineCompact>& t) { glLoadMatrix(Transform<Scalar,3,Affine>(t).matrix()); }
inline void glRotate(const Rotation2D<float>& rot)
{
glRotatef(rot.angle()*180.f/float(M_PI), 0.f, 0.f, 1.f);
}
inline void glRotate(const Rotation2D<double>& rot)
{
glRotated(rot.angle()*180.0/M_PI, 0.0, 0.0, 1.0);
}
template<typename Derived> void glRotate(const RotationBase<Derived,3>& rot)
{
Transform<typename Derived::Scalar,3,Projective> tr(rot);
glMultMatrix(tr.matrix());
}
#define EIGEN_GL_MAKE_CONST_const const
#define EIGEN_GL_MAKE_CONST__
#define EIGEN_GL_EVAL(X) X
#define EIGEN_GL_FUNC1_DECLARATION(FUNC,ARG1,CONST) \
namespace internal { \
template< typename XprType, \
typename Scalar = typename XprType::Scalar, \
int Rows = XprType::RowsAtCompileTime, \
int Cols = XprType::ColsAtCompileTime, \
bool IsGLCompatible = bool(XprType::Flags&LinearAccessBit) \
&& bool(XprType::Flags&DirectAccessBit) \
&& (XprType::IsVectorAtCompileTime || (XprType::Flags&RowMajorBit)==0)> \
struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl); \
\
template<typename XprType, typename Scalar, int Rows, int Cols> \
struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType,Scalar,Rows,Cols,false> { \
inline static void run(ARG1 a,EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<typename plain_matrix_type_column_major<XprType>::type>::run(a,p); } \
}; \
} \
\
template<typename Derived> inline void FUNC(ARG1 a,EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) Eigen::DenseBase<Derived>& p) { \
EIGEN_CAT(EIGEN_CAT(internal::gl_,FUNC),_impl)<Derived>::run(a,p.derived()); \
}
#define EIGEN_GL_FUNC1_SPECIALIZATION_MAT(FUNC,ARG1,CONST,SCALAR,ROWS,COLS,SUFFIX) \
namespace internal { \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, ROWS, COLS, true> { \
inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { FUNC##SUFFIX(a,p.data()); } \
}; \
}
#define EIGEN_GL_FUNC1_SPECIALIZATION_VEC(FUNC,ARG1,CONST,SCALAR,SIZE,SUFFIX) \
namespace internal { \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, SIZE, 1, true> { \
inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { FUNC##SUFFIX(a,p.data()); } \
}; \
template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(gl_,FUNC),_impl)<XprType, SCALAR, 1, SIZE, true> { \
inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { FUNC##SUFFIX(a,p.data()); } \
}; \
}
EIGEN_GL_FUNC1_DECLARATION (glGet,GLenum,_)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet,GLenum,_,float, 4,4,Floatv)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet,GLenum,_,double, 4,4,Doublev)
// glUniform API
#ifdef GL_VERSION_2_0
inline void glUniform2fv_ei (GLint loc, const float* v) { glUniform2fv(loc,1,v); }
inline void glUniform2iv_ei (GLint loc, const int* v) { glUniform2iv(loc,1,v); }
inline void glUniform3fv_ei (GLint loc, const float* v) { glUniform3fv(loc,1,v); }
inline void glUniform3iv_ei (GLint loc, const int* v) { glUniform3iv(loc,1,v); }
inline void glUniform4fv_ei (GLint loc, const float* v) { glUniform4fv(loc,1,v); }
inline void glUniform4iv_ei (GLint loc, const int* v) { glUniform4iv(loc,1,v); }
inline void glUniformMatrix2fv_ei (GLint loc, const float* v) { glUniformMatrix2fv(loc,1,false,v); }
inline void glUniformMatrix3fv_ei (GLint loc, const float* v) { glUniformMatrix3fv(loc,1,false,v); }
inline void glUniformMatrix4fv_ei (GLint loc, const float* v) { glUniformMatrix4fv(loc,1,false,v); }
EIGEN_GL_FUNC1_DECLARATION (glUniform,GLint,const)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,float, 2,2fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,int, 2,2iv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,float, 3,3fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,int, 3,3iv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,float, 4,4fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,int, 4,4iv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 2,2,Matrix2fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 3,3,Matrix3fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 4,4,Matrix4fv_ei)
#endif
#ifdef GL_VERSION_2_1
static void glUniformMatrix2x3fv_ei(GLint loc, const float* v) { glUniformMatrix2x3fv(loc,1,false,v); }
static void glUniformMatrix3x2fv_ei(GLint loc, const float* v) { glUniformMatrix3x2fv(loc,1,false,v); }
static void glUniformMatrix2x4fv_ei(GLint loc, const float* v) { glUniformMatrix2x4fv(loc,1,false,v); }
static void glUniformMatrix4x2fv_ei(GLint loc, const float* v) { glUniformMatrix4x2fv(loc,1,false,v); }
static void glUniformMatrix3x4fv_ei(GLint loc, const float* v) { glUniformMatrix3x4fv(loc,1,false,v); }
static void glUniformMatrix4x3fv_ei(GLint loc, const float* v) { glUniformMatrix4x3fv(loc,1,false,v); }
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 2,3,Matrix2x3fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 3,2,Matrix3x2fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 2,4,Matrix2x4fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 4,2,Matrix4x2fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 3,4,Matrix3x4fv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform,GLint,const,float, 4,3,Matrix4x3fv_ei)
#endif
#ifdef GL_VERSION_3_0
inline void glUniform2uiv_ei (GLint loc, const unsigned int* v) { glUniform2uiv(loc,1,v); }
inline void glUniform3uiv_ei (GLint loc, const unsigned int* v) { glUniform3uiv(loc,1,v); }
inline void glUniform4uiv_ei (GLint loc, const unsigned int* v) { glUniform4uiv(loc,1,v); }
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,unsigned int, 2,2uiv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,unsigned int, 3,3uiv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,unsigned int, 4,4uiv_ei)
#endif
#ifdef GL_ARB_gpu_shader_fp64
inline void glUniform2dv_ei (GLint loc, const double* v) { glUniform2dv(loc,1,v); }
inline void glUniform3dv_ei (GLint loc, const double* v) { glUniform3dv(loc,1,v); }
inline void glUniform4dv_ei (GLint loc, const double* v) { glUniform4dv(loc,1,v); }
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,double, 2,2dv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,double, 3,3dv_ei)
EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform,GLint,const,double, 4,4dv_ei)
#endif
//@}
}
#endif // EIGEN_OPENGL_MODULE

View File

@@ -0,0 +1,138 @@
// 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_POLYNOMIALS_MODULE_H
#define EIGEN_POLYNOMIALS_MODULE_H
#include <Eigen/Core>
#include <Eigen/src/Core/util/DisableStupidWarnings.h>
#include <Eigen/Eigenvalues>
// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS>=2)
#ifndef EIGEN_HIDE_HEAVY_CODE
#define EIGEN_HIDE_HEAVY_CODE
#endif
#elif defined EIGEN_HIDE_HEAVY_CODE
#undef EIGEN_HIDE_HEAVY_CODE
#endif
/**
* \defgroup Polynomials_Module Polynomials module
* \brief This module provides a QR based polynomial solver.
*
* To use this module, add
* \code
* #include <unsupported/Eigen/Polynomials>
* \endcode
* at the start of your source file.
*/
#include "src/Polynomials/PolynomialUtils.h"
#include "src/Polynomials/Companion.h"
#include "src/Polynomials/PolynomialSolver.h"
/**
\page polynomials Polynomials defines functions for dealing with polynomials
and a QR based polynomial solver.
\ingroup Polynomials_Module
The remainder of the page documents first the functions for evaluating, computing
polynomials, computing estimates about polynomials and next the QR based polynomial
solver.
\section polynomialUtils convenient functions to deal with polynomials
\subsection roots_to_monicPolynomial
The function
\code
void roots_to_monicPolynomial( const RootVector& rv, Polynomial& poly )
\endcode
computes the coefficients \f$ a_i \f$ of
\f$ p(x) = a_0 + a_{1}x + ... + a_{n-1}x^{n-1} + x^n \f$
where \f$ p \f$ is known through its roots i.e. \f$ p(x) = (x-r_1)(x-r_2)...(x-r_n) \f$.
\subsection poly_eval
The function
\code
T poly_eval( const Polynomials& poly, const T& x )
\endcode
evaluates a polynomial at a given point using stabilized H&ouml;rner method.
The following code: first computes the coefficients in the monomial basis of the monic polynomial that has the provided roots;
then, it evaluates the computed polynomial, using a stabilized H&ouml;rner method.
\include PolynomialUtils1.cpp
Output: \verbinclude PolynomialUtils1.out
\subsection Cauchy bounds
The function
\code
Real cauchy_max_bound( const Polynomial& poly )
\endcode
provides a maximum bound (the Cauchy one: \f$C(p)\f$) for the absolute value of a root of the given polynomial i.e.
\f$ \forall r_i \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$,
\f$ |r_i| \le C(p) = \sum_{k=0}^{d} \left | \frac{a_k}{a_d} \right | \f$
The leading coefficient \f$ p \f$: should be non zero \f$a_d \neq 0\f$.
The function
\code
Real cauchy_min_bound( const Polynomial& poly )
\endcode
provides a minimum bound (the Cauchy one: \f$c(p)\f$) for the absolute value of a non zero root of the given polynomial i.e.
\f$ \forall r_i \neq 0 \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$,
\f$ |r_i| \ge c(p) = \left( \sum_{k=0}^{d} \left | \frac{a_k}{a_0} \right | \right)^{-1} \f$
\section QR polynomial solver class
Computes the complex roots of a polynomial by computing the eigenvalues of the associated companion matrix with the QR algorithm.
The roots of \f$ p(x) = a_0 + a_1 x + a_2 x^2 + a_{3} x^3 + x^4 \f$ are the eigenvalues of
\f$
\left [
\begin{array}{cccc}
0 & 0 & 0 & a_0 \\
1 & 0 & 0 & a_1 \\
0 & 1 & 0 & a_2 \\
0 & 0 & 1 & a_3
\end{array} \right ]
\f$
However, the QR algorithm is not guaranteed to converge when there are several eigenvalues with same modulus.
Therefore the current polynomial solver is guaranteed to provide a correct result only when the complex roots \f$r_1,r_2,...,r_d\f$ have distinct moduli i.e.
\f$ \forall i,j \in [1;d],~ \| r_i \| \neq \| r_j \| \f$.
With 32bit (float) floating types this problem shows up frequently.
However, almost always, correct accuracy is reached even in these cases for 64bit
(double) floating types and small polynomial degree (<20).
\include PolynomialSolver1.cpp
In the above example:
-# a simple use of the polynomial solver is shown;
-# the accuracy problem with the QR algorithm is presented: a polynomial with almost conjugate roots is provided to the solver.
Those roots have almost same module therefore the QR algorithm failed to converge: the accuracy
of the last root is bad;
-# a simple way to circumvent the problem is shown: use doubles instead of floats.
Output: \verbinclude PolynomialSolver1.out
*/
#include <Eigen/src/Core/util/ReenableStupidWarnings.h>
#endif // EIGEN_POLYNOMIALS_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

39
extern/Eigen3/unsupported/Eigen/SVD vendored Normal file
View File

@@ -0,0 +1,39 @@
#ifndef EIGEN_SVD_MODULE_H
#define EIGEN_SVD_MODULE_H
#include <Eigen/QR>
#include <Eigen/Householder>
#include <Eigen/Jacobi>
#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
/** \defgroup SVD_Module SVD module
*
*
*
* This module provides SVD decomposition for matrices (both real and complex).
* This decomposition is accessible via the following MatrixBase method:
* - MatrixBase::jacobiSvd()
*
* \code
* #include <Eigen/SVD>
* \endcode
*/
#include "../../Eigen/src/misc/Solve.h"
#include "../../Eigen/src/SVD/UpperBidiagonalization.h"
#include "src/SVD/SVDBase.h"
#include "src/SVD/JacobiSVD.h"
#include "src/SVD/BDCSVD.h"
#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT)
#include "../../Eigen/src/SVD/JacobiSVD_MKL.h"
#endif
#ifdef EIGEN2_SUPPORT
#include "../../Eigen/src/Eigen2Support/SVD.h"
#endif
#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SVD_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

39
extern/Eigen3/unsupported/Eigen/Skyline vendored Normal file
View File

@@ -0,0 +1,39 @@
// 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_SKYLINE_MODULE_H
#define EIGEN_SKYLINE_MODULE_H
#include "Eigen/Core"
#include "Eigen/src/Core/util/DisableStupidWarnings.h"
#include <map>
#include <cstdlib>
#include <cstring>
#include <algorithm>
/**
* \defgroup Skyline_Module Skyline module
*
*
*
*
*/
#include "src/Skyline/SkylineUtil.h"
#include "src/Skyline/SkylineMatrixBase.h"
#include "src/Skyline/SkylineStorage.h"
#include "src/Skyline/SkylineMatrix.h"
#include "src/Skyline/SkylineInplaceLU.h"
#include "src/Skyline/SkylineProduct.h"
#include "Eigen/src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SKYLINE_MODULE_H

View File

@@ -0,0 +1,56 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.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_SPARSE_EXTRA_MODULE_H
#define EIGEN_SPARSE_EXTRA_MODULE_H
#include "../../Eigen/Sparse"
#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
#include <vector>
#include <map>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <fstream>
#include <sstream>
#ifdef EIGEN_GOOGLEHASH_SUPPORT
#include <google/dense_hash_map>
#endif
/**
* \defgroup SparseExtra_Module SparseExtra module
*
* This module contains some experimental features extending the sparse module.
*
* \code
* #include <Eigen/SparseExtra>
* \endcode
*/
#include "../../Eigen/src/misc/Solve.h"
#include "../../Eigen/src/misc/SparseSolve.h"
#include "src/SparseExtra/DynamicSparseMatrix.h"
#include "src/SparseExtra/BlockOfDynamicSparseMatrix.h"
#include "src/SparseExtra/RandomSetter.h"
#include "src/SparseExtra/MarketIO.h"
#if !defined(_WIN32)
#include <dirent.h>
#include "src/SparseExtra/MatrixMarketIterator.h"
#endif
#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SPARSE_EXTRA_MODULE_H

31
extern/Eigen3/unsupported/Eigen/Splines vendored Normal file
View File

@@ -0,0 +1,31 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 20010-2011 Hauke Heibel <hauke.heibel@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_SPLINES_MODULE_H
#define EIGEN_SPLINES_MODULE_H
namespace Eigen
{
/**
* \defgroup Splines_Module Spline and spline fitting module
*
* This module provides a simple multi-dimensional spline class while
* offering most basic functionality to fit a spline to point sets.
*
* \code
* #include <unsupported/Eigen/Splines>
* \endcode
*/
}
#include "src/Splines/SplineFwd.h"
#include "src/Splines/Spline.h"
#include "src/Splines/SplineFitting.h"
#endif // EIGEN_SPLINES_MODULE_H

View File

@@ -0,0 +1,83 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_AUTODIFF_JACOBIAN_H
#define EIGEN_AUTODIFF_JACOBIAN_H
namespace Eigen
{
template<typename Functor> class AutoDiffJacobian : public Functor
{
public:
AutoDiffJacobian() : Functor() {}
AutoDiffJacobian(const Functor& f) : Functor(f) {}
// forward constructors
template<typename T0>
AutoDiffJacobian(const T0& a0) : Functor(a0) {}
template<typename T0, typename T1>
AutoDiffJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {}
template<typename T0, typename T1, typename T2>
AutoDiffJacobian(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2) {}
enum {
InputsAtCompileTime = Functor::InputsAtCompileTime,
ValuesAtCompileTime = Functor::ValuesAtCompileTime
};
typedef typename Functor::InputType InputType;
typedef typename Functor::ValueType ValueType;
typedef typename Functor::JacobianType JacobianType;
typedef typename JacobianType::Scalar Scalar;
typedef typename JacobianType::Index Index;
typedef Matrix<Scalar,InputsAtCompileTime,1> DerivativeType;
typedef AutoDiffScalar<DerivativeType> ActiveScalar;
typedef Matrix<ActiveScalar, InputsAtCompileTime, 1> ActiveInput;
typedef Matrix<ActiveScalar, ValuesAtCompileTime, 1> ActiveValue;
void operator() (const InputType& x, ValueType* v, JacobianType* _jac=0) const
{
eigen_assert(v!=0);
if (!_jac)
{
Functor::operator()(x, v);
return;
}
JacobianType& jac = *_jac;
ActiveInput ax = x.template cast<ActiveScalar>();
ActiveValue av(jac.rows());
if(InputsAtCompileTime==Dynamic)
for (Index j=0; j<jac.rows(); j++)
av[j].derivatives().resize(this->inputs());
for (Index i=0; i<jac.cols(); i++)
ax[i].derivatives() = DerivativeType::Unit(this->inputs(),i);
Functor::operator()(ax, &av);
for (Index i=0; i<jac.rows(); i++)
{
(*v)[i] = av[i].value();
jac.row(i) = av[i].derivatives();
}
}
protected:
};
}
#endif // EIGEN_AUTODIFF_JACOBIAN_H

View File

@@ -0,0 +1,642 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_AUTODIFF_SCALAR_H
#define EIGEN_AUTODIFF_SCALAR_H
namespace Eigen {
namespace internal {
template<typename A, typename B>
struct make_coherent_impl {
static void run(A&, B&) {}
};
// resize a to match b is a.size()==0, and conversely.
template<typename A, typename B>
void make_coherent(const A& a, const B&b)
{
make_coherent_impl<A,B>::run(a.const_cast_derived(), b.const_cast_derived());
}
template<typename _DerType, bool Enable> struct auto_diff_special_op;
} // end namespace internal
/** \class AutoDiffScalar
* \brief A scalar type replacement with automatic differentation capability
*
* \param _DerType the vector type used to store/represent the derivatives. The base scalar type
* as well as the number of derivatives to compute are determined from this type.
* Typical choices include, e.g., \c Vector4f for 4 derivatives, or \c VectorXf
* if the number of derivatives is not known at compile time, and/or, the number
* of derivatives is large.
* Note that _DerType can also be a reference (e.g., \c VectorXf&) to wrap a
* existing vector into an AutoDiffScalar.
* Finally, _DerType can also be any Eigen compatible expression.
*
* This class represents a scalar value while tracking its respective derivatives using Eigen's expression
* template mechanism.
*
* It supports the following list of global math function:
* - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos,
* - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos,
* - internal::conj, internal::real, internal::imag, numext::abs2.
*
* AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However,
* in that case, the expression template mechanism only occurs at the top Matrix level,
* while derivatives are computed right away.
*
*/
template<typename _DerType>
class AutoDiffScalar
: public internal::auto_diff_special_op
<_DerType, !internal::is_same<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar,
typename NumTraits<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar>::Real>::value>
{
public:
typedef internal::auto_diff_special_op
<_DerType, !internal::is_same<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar,
typename NumTraits<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar>::Real>::value> Base;
typedef typename internal::remove_all<_DerType>::type DerType;
typedef typename internal::traits<DerType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real Real;
using Base::operator+;
using Base::operator*;
/** Default constructor without any initialization. */
AutoDiffScalar() {}
/** Constructs an active scalar from its \a value,
and initializes the \a nbDer derivatives such that it corresponds to the \a derNumber -th variable */
AutoDiffScalar(const Scalar& value, int nbDer, int derNumber)
: m_value(value), m_derivatives(DerType::Zero(nbDer))
{
m_derivatives.coeffRef(derNumber) = Scalar(1);
}
/** Conversion from a scalar constant to an active scalar.
* The derivatives are set to zero. */
/*explicit*/ AutoDiffScalar(const Real& value)
: m_value(value)
{
if(m_derivatives.size()>0)
m_derivatives.setZero();
}
/** Constructs an active scalar from its \a value and derivatives \a der */
AutoDiffScalar(const Scalar& value, const DerType& der)
: m_value(value), m_derivatives(der)
{}
template<typename OtherDerType>
AutoDiffScalar(const AutoDiffScalar<OtherDerType>& other)
: m_value(other.value()), m_derivatives(other.derivatives())
{}
friend std::ostream & operator << (std::ostream & s, const AutoDiffScalar& a)
{
return s << a.value();
}
AutoDiffScalar(const AutoDiffScalar& other)
: m_value(other.value()), m_derivatives(other.derivatives())
{}
template<typename OtherDerType>
inline AutoDiffScalar& operator=(const AutoDiffScalar<OtherDerType>& other)
{
m_value = other.value();
m_derivatives = other.derivatives();
return *this;
}
inline AutoDiffScalar& operator=(const AutoDiffScalar& other)
{
m_value = other.value();
m_derivatives = other.derivatives();
return *this;
}
// inline operator const Scalar& () const { return m_value; }
// inline operator Scalar& () { return m_value; }
inline const Scalar& value() const { return m_value; }
inline Scalar& value() { return m_value; }
inline const DerType& derivatives() const { return m_derivatives; }
inline DerType& derivatives() { return m_derivatives; }
inline bool operator< (const Scalar& other) const { return m_value < other; }
inline bool operator<=(const Scalar& other) const { return m_value <= other; }
inline bool operator> (const Scalar& other) const { return m_value > other; }
inline bool operator>=(const Scalar& other) const { return m_value >= other; }
inline bool operator==(const Scalar& other) const { return m_value == other; }
inline bool operator!=(const Scalar& other) const { return m_value != other; }
friend inline bool operator< (const Scalar& a, const AutoDiffScalar& b) { return a < b.value(); }
friend inline bool operator<=(const Scalar& a, const AutoDiffScalar& b) { return a <= b.value(); }
friend inline bool operator> (const Scalar& a, const AutoDiffScalar& b) { return a > b.value(); }
friend inline bool operator>=(const Scalar& a, const AutoDiffScalar& b) { return a >= b.value(); }
friend inline bool operator==(const Scalar& a, const AutoDiffScalar& b) { return a == b.value(); }
friend inline bool operator!=(const Scalar& a, const AutoDiffScalar& b) { return a != b.value(); }
template<typename OtherDerType> inline bool operator< (const AutoDiffScalar<OtherDerType>& b) const { return m_value < b.value(); }
template<typename OtherDerType> inline bool operator<=(const AutoDiffScalar<OtherDerType>& b) const { return m_value <= b.value(); }
template<typename OtherDerType> inline bool operator> (const AutoDiffScalar<OtherDerType>& b) const { return m_value > b.value(); }
template<typename OtherDerType> inline bool operator>=(const AutoDiffScalar<OtherDerType>& b) const { return m_value >= b.value(); }
template<typename OtherDerType> inline bool operator==(const AutoDiffScalar<OtherDerType>& b) const { return m_value == b.value(); }
template<typename OtherDerType> inline bool operator!=(const AutoDiffScalar<OtherDerType>& b) const { return m_value != b.value(); }
inline const AutoDiffScalar<DerType&> operator+(const Scalar& other) const
{
return AutoDiffScalar<DerType&>(m_value + other, m_derivatives);
}
friend inline const AutoDiffScalar<DerType&> operator+(const Scalar& a, const AutoDiffScalar& b)
{
return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
}
// inline const AutoDiffScalar<DerType&> operator+(const Real& other) const
// {
// return AutoDiffScalar<DerType&>(m_value + other, m_derivatives);
// }
// friend inline const AutoDiffScalar<DerType&> operator+(const Real& a, const AutoDiffScalar& b)
// {
// return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
// }
inline AutoDiffScalar& operator+=(const Scalar& other)
{
value() += other;
return *this;
}
template<typename OtherDerType>
inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>,const DerType,const typename internal::remove_all<OtherDerType>::type> >
operator+(const AutoDiffScalar<OtherDerType>& other) const
{
internal::make_coherent(m_derivatives, other.derivatives());
return AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>,const DerType,const typename internal::remove_all<OtherDerType>::type> >(
m_value + other.value(),
m_derivatives + other.derivatives());
}
template<typename OtherDerType>
inline AutoDiffScalar&
operator+=(const AutoDiffScalar<OtherDerType>& other)
{
(*this) = (*this) + other;
return *this;
}
inline const AutoDiffScalar<DerType&> operator-(const Scalar& b) const
{
return AutoDiffScalar<DerType&>(m_value - b, m_derivatives);
}
friend inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> >
operator-(const Scalar& a, const AutoDiffScalar& b)
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> >
(a - b.value(), -b.derivatives());
}
inline AutoDiffScalar& operator-=(const Scalar& other)
{
value() -= other;
return *this;
}
template<typename OtherDerType>
inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> >
operator-(const AutoDiffScalar<OtherDerType>& other) const
{
internal::make_coherent(m_derivatives, other.derivatives());
return AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> >(
m_value - other.value(),
m_derivatives - other.derivatives());
}
template<typename OtherDerType>
inline AutoDiffScalar&
operator-=(const AutoDiffScalar<OtherDerType>& other)
{
*this = *this - other;
return *this;
}
inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> >
operator-() const
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> >(
-m_value,
-m_derivatives);
}
inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >
operator*(const Scalar& other) const
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >(
m_value * other,
(m_derivatives * other));
}
friend inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >
operator*(const Scalar& other, const AutoDiffScalar& a)
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >(
a.value() * other,
a.derivatives() * other);
}
// inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >
// operator*(const Real& other) const
// {
// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >(
// m_value * other,
// (m_derivatives * other));
// }
//
// friend inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >
// operator*(const Real& other, const AutoDiffScalar& a)
// {
// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >(
// a.value() * other,
// a.derivatives() * other);
// }
inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >
operator/(const Scalar& other) const
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >(
m_value / other,
(m_derivatives * (Scalar(1)/other)));
}
friend inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >
operator/(const Scalar& other, const AutoDiffScalar& a)
{
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType> >(
other / a.value(),
a.derivatives() * (Scalar(-other) / (a.value()*a.value())));
}
// inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >
// operator/(const Real& other) const
// {
// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >(
// m_value / other,
// (m_derivatives * (Real(1)/other)));
// }
//
// friend inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >
// operator/(const Real& other, const AutoDiffScalar& a)
// {
// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >(
// other / a.value(),
// a.derivatives() * (-Real(1)/other));
// }
template<typename OtherDerType>
inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>,
const CwiseBinaryOp<internal::scalar_difference_op<Scalar>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const typename internal::remove_all<OtherDerType>::type > > > >
operator/(const AutoDiffScalar<OtherDerType>& other) const
{
internal::make_coherent(m_derivatives, other.derivatives());
return AutoDiffScalar<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>,
const CwiseBinaryOp<internal::scalar_difference_op<Scalar>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const typename internal::remove_all<OtherDerType>::type > > > >(
m_value / other.value(),
((m_derivatives * other.value()) - (m_value * other.derivatives()))
* (Scalar(1)/(other.value()*other.value())));
}
template<typename OtherDerType>
inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const typename internal::remove_all<OtherDerType>::type> > >
operator*(const AutoDiffScalar<OtherDerType>& other) const
{
internal::make_coherent(m_derivatives, other.derivatives());
return AutoDiffScalar<const CwiseBinaryOp<internal::scalar_sum_op<Scalar>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DerType>,
const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const typename internal::remove_all<OtherDerType>::type > > >(
m_value * other.value(),
(m_derivatives * other.value()) + (m_value * other.derivatives()));
}
inline AutoDiffScalar& operator*=(const Scalar& other)
{
*this = *this * other;
return *this;
}
template<typename OtherDerType>
inline AutoDiffScalar& operator*=(const AutoDiffScalar<OtherDerType>& other)
{
*this = *this * other;
return *this;
}
inline AutoDiffScalar& operator/=(const Scalar& other)
{
*this = *this / other;
return *this;
}
template<typename OtherDerType>
inline AutoDiffScalar& operator/=(const AutoDiffScalar<OtherDerType>& other)
{
*this = *this / other;
return *this;
}
protected:
Scalar m_value;
DerType m_derivatives;
};
namespace internal {
template<typename _DerType>
struct auto_diff_special_op<_DerType, true>
// : auto_diff_scalar_op<_DerType, typename NumTraits<Scalar>::Real,
// is_same<Scalar,typename NumTraits<Scalar>::Real>::value>
{
typedef typename remove_all<_DerType>::type DerType;
typedef typename traits<DerType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real Real;
// typedef auto_diff_scalar_op<_DerType, typename NumTraits<Scalar>::Real,
// is_same<Scalar,typename NumTraits<Scalar>::Real>::value> Base;
// using Base::operator+;
// using Base::operator+=;
// using Base::operator-;
// using Base::operator-=;
// using Base::operator*;
// using Base::operator*=;
const AutoDiffScalar<_DerType>& derived() const { return *static_cast<const AutoDiffScalar<_DerType>*>(this); }
AutoDiffScalar<_DerType>& derived() { return *static_cast<AutoDiffScalar<_DerType>*>(this); }
inline const AutoDiffScalar<DerType&> operator+(const Real& other) const
{
return AutoDiffScalar<DerType&>(derived().value() + other, derived().derivatives());
}
friend inline const AutoDiffScalar<DerType&> operator+(const Real& a, const AutoDiffScalar<_DerType>& b)
{
return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
}
inline AutoDiffScalar<_DerType>& operator+=(const Real& other)
{
derived().value() += other;
return derived();
}
inline const AutoDiffScalar<typename CwiseUnaryOp<scalar_multiple2_op<Scalar,Real>, DerType>::Type >
operator*(const Real& other) const
{
return AutoDiffScalar<typename CwiseUnaryOp<scalar_multiple2_op<Scalar,Real>, DerType>::Type >(
derived().value() * other,
derived().derivatives() * other);
}
friend inline const AutoDiffScalar<typename CwiseUnaryOp<scalar_multiple2_op<Scalar,Real>, DerType>::Type >
operator*(const Real& other, const AutoDiffScalar<_DerType>& a)
{
return AutoDiffScalar<typename CwiseUnaryOp<scalar_multiple2_op<Scalar,Real>, DerType>::Type >(
a.value() * other,
a.derivatives() * other);
}
inline AutoDiffScalar<_DerType>& operator*=(const Scalar& other)
{
*this = *this * other;
return derived();
}
};
template<typename _DerType>
struct auto_diff_special_op<_DerType, false>
{
void operator*() const;
void operator-() const;
void operator+() const;
};
template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols, typename B>
struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>, B> {
typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> A;
static void run(A& a, B& b) {
if((A_Rows==Dynamic || A_Cols==Dynamic) && (a.size()==0))
{
a.resize(b.size());
a.setZero();
}
}
};
template<typename A, typename B_Scalar, int B_Rows, int B_Cols, int B_Options, int B_MaxRows, int B_MaxCols>
struct make_coherent_impl<A, Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> > {
typedef Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> B;
static void run(A& a, B& b) {
if((B_Rows==Dynamic || B_Cols==Dynamic) && (b.size()==0))
{
b.resize(a.size());
b.setZero();
}
}
};
template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols,
typename B_Scalar, int B_Rows, int B_Cols, int B_Options, int B_MaxRows, int B_MaxCols>
struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>,
Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> > {
typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> A;
typedef Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> B;
static void run(A& a, B& b) {
if((A_Rows==Dynamic || A_Cols==Dynamic) && (a.size()==0))
{
a.resize(b.size());
a.setZero();
}
else if((B_Rows==Dynamic || B_Cols==Dynamic) && (b.size()==0))
{
b.resize(a.size());
b.setZero();
}
}
};
template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols>
struct scalar_product_traits<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>,A_Scalar>
{
enum { Defined = 1 };
typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
};
template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols>
struct scalar_product_traits<A_Scalar, Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> >
{
enum { Defined = 1 };
typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> ReturnType;
};
template<typename DerType>
struct scalar_product_traits<AutoDiffScalar<DerType>,typename DerType::Scalar>
{
enum { Defined = 1 };
typedef AutoDiffScalar<DerType> ReturnType;
};
template<typename DerType>
struct scalar_product_traits<typename DerType::Scalar,AutoDiffScalar<DerType> >
{
enum { Defined = 1 };
typedef AutoDiffScalar<DerType> ReturnType;
};
} // end namespace internal
#define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC,CODE) \
template<typename DerType> \
inline const Eigen::AutoDiffScalar<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar>, const typename Eigen::internal::remove_all<DerType>::type> > \
FUNC(const Eigen::AutoDiffScalar<DerType>& x) { \
using namespace Eigen; \
typedef typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar Scalar; \
typedef AutoDiffScalar<CwiseUnaryOp<Eigen::internal::scalar_multiple_op<Scalar>, const typename Eigen::internal::remove_all<DerType>::type> > ReturnType; \
CODE; \
}
template<typename DerType>
inline const AutoDiffScalar<DerType>& conj(const AutoDiffScalar<DerType>& x) { return x; }
template<typename DerType>
inline const AutoDiffScalar<DerType>& real(const AutoDiffScalar<DerType>& x) { return x; }
template<typename DerType>
inline typename DerType::Scalar imag(const AutoDiffScalar<DerType>&) { return 0.; }
template<typename DerType, typename T>
inline AutoDiffScalar<DerType> (min)(const AutoDiffScalar<DerType>& x, const T& y) { return (x <= y ? x : y); }
template<typename DerType, typename T>
inline AutoDiffScalar<DerType> (max)(const AutoDiffScalar<DerType>& x, const T& y) { return (x >= y ? x : y); }
template<typename DerType, typename T>
inline AutoDiffScalar<DerType> (min)(const T& x, const AutoDiffScalar<DerType>& y) { return (x < y ? x : y); }
template<typename DerType, typename T>
inline AutoDiffScalar<DerType> (max)(const T& x, const AutoDiffScalar<DerType>& y) { return (x > y ? x : y); }
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs,
using std::abs;
return ReturnType(abs(x.value()), x.derivatives() * (x.value()<0 ? -1 : 1) );)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs2,
using numext::abs2;
return ReturnType(abs2(x.value()), x.derivatives() * (Scalar(2)*x.value()));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sqrt,
using std::sqrt;
Scalar sqrtx = sqrt(x.value());
return ReturnType(sqrtx,x.derivatives() * (Scalar(0.5) / sqrtx));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cos,
using std::cos;
using std::sin;
return ReturnType(cos(x.value()), x.derivatives() * (-sin(x.value())));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sin,
using std::sin;
using std::cos;
return ReturnType(sin(x.value()),x.derivatives() * cos(x.value()));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(exp,
using std::exp;
Scalar expx = exp(x.value());
return ReturnType(expx,x.derivatives() * expx);)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(log,
using std::log;
return ReturnType(log(x.value()),x.derivatives() * (Scalar(1)/x.value()));)
template<typename DerType>
inline const Eigen::AutoDiffScalar<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<typename Eigen::internal::traits<DerType>::Scalar>, const DerType> >
pow(const Eigen::AutoDiffScalar<DerType>& x, typename Eigen::internal::traits<DerType>::Scalar y)
{
using namespace Eigen;
typedef typename Eigen::internal::traits<DerType>::Scalar Scalar;
return AutoDiffScalar<CwiseUnaryOp<Eigen::internal::scalar_multiple_op<Scalar>, const DerType> >(
std::pow(x.value(),y),
x.derivatives() * (y * std::pow(x.value(),y-1)));
}
template<typename DerTypeA,typename DerTypeB>
inline const AutoDiffScalar<Matrix<typename internal::traits<DerTypeA>::Scalar,Dynamic,1> >
atan2(const AutoDiffScalar<DerTypeA>& a, const AutoDiffScalar<DerTypeB>& b)
{
using std::atan2;
using std::max;
typedef typename internal::traits<DerTypeA>::Scalar Scalar;
typedef AutoDiffScalar<Matrix<Scalar,Dynamic,1> > PlainADS;
PlainADS ret;
ret.value() = atan2(a.value(), b.value());
Scalar tmp2 = a.value() * a.value();
Scalar tmp3 = b.value() * b.value();
Scalar tmp4 = tmp3/(tmp2+tmp3);
if (tmp4!=0)
ret.derivatives() = (a.derivatives() * b.value() - a.value() * b.derivatives()) * (tmp2+tmp3);
return ret;
}
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(tan,
using std::tan;
using std::cos;
return ReturnType(tan(x.value()),x.derivatives() * (Scalar(1)/numext::abs2(cos(x.value()))));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(asin,
using std::sqrt;
using std::asin;
return ReturnType(asin(x.value()),x.derivatives() * (Scalar(1)/sqrt(1-numext::abs2(x.value()))));)
EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(acos,
using std::sqrt;
using std::acos;
return ReturnType(acos(x.value()),x.derivatives() * (Scalar(-1)/sqrt(1-numext::abs2(x.value()))));)
#undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY
template<typename DerType> struct NumTraits<AutoDiffScalar<DerType> >
: NumTraits< typename NumTraits<typename DerType::Scalar>::Real >
{
typedef AutoDiffScalar<Matrix<typename NumTraits<typename DerType::Scalar>::Real,DerType::RowsAtCompileTime,DerType::ColsAtCompileTime> > Real;
typedef AutoDiffScalar<DerType> NonInteger;
typedef AutoDiffScalar<DerType> Nested;
enum{
RequireInitialization = 1
};
};
}
#endif // EIGEN_AUTODIFF_SCALAR_H

View File

@@ -0,0 +1,220 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_AUTODIFF_VECTOR_H
#define EIGEN_AUTODIFF_VECTOR_H
namespace Eigen {
/* \class AutoDiffScalar
* \brief A scalar type replacement with automatic differentation capability
*
* \param DerType the vector type used to store/represent the derivatives (e.g. Vector3f)
*
* This class represents a scalar value while tracking its respective derivatives.
*
* It supports the following list of global math function:
* - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos,
* - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos,
* - internal::conj, internal::real, internal::imag, numext::abs2.
*
* AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However,
* in that case, the expression template mechanism only occurs at the top Matrix level,
* while derivatives are computed right away.
*
*/
template<typename ValueType, typename JacobianType>
class AutoDiffVector
{
public:
//typedef typename internal::traits<ValueType>::Scalar Scalar;
typedef typename internal::traits<ValueType>::Scalar BaseScalar;
typedef AutoDiffScalar<Matrix<BaseScalar,JacobianType::RowsAtCompileTime,1> > ActiveScalar;
typedef ActiveScalar Scalar;
typedef AutoDiffScalar<typename JacobianType::ColXpr> CoeffType;
typedef typename JacobianType::Index Index;
inline AutoDiffVector() {}
inline AutoDiffVector(const ValueType& values)
: m_values(values)
{
m_jacobian.setZero();
}
CoeffType operator[] (Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); }
const CoeffType operator[] (Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); }
CoeffType operator() (Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); }
const CoeffType operator() (Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); }
CoeffType coeffRef(Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); }
const CoeffType coeffRef(Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); }
Index size() const { return m_values.size(); }
// FIXME here we could return an expression of the sum
Scalar sum() const { /*std::cerr << "sum \n\n";*/ /*std::cerr << m_jacobian.rowwise().sum() << "\n\n";*/ return Scalar(m_values.sum(), m_jacobian.rowwise().sum()); }
inline AutoDiffVector(const ValueType& values, const JacobianType& jac)
: m_values(values), m_jacobian(jac)
{}
template<typename OtherValueType, typename OtherJacobianType>
inline AutoDiffVector(const AutoDiffVector<OtherValueType, OtherJacobianType>& other)
: m_values(other.values()), m_jacobian(other.jacobian())
{}
inline AutoDiffVector(const AutoDiffVector& other)
: m_values(other.values()), m_jacobian(other.jacobian())
{}
template<typename OtherValueType, typename OtherJacobianType>
inline AutoDiffVector& operator=(const AutoDiffVector<OtherValueType, OtherJacobianType>& other)
{
m_values = other.values();
m_jacobian = other.jacobian();
return *this;
}
inline AutoDiffVector& operator=(const AutoDiffVector& other)
{
m_values = other.values();
m_jacobian = other.jacobian();
return *this;
}
inline const ValueType& values() const { return m_values; }
inline ValueType& values() { return m_values; }
inline const JacobianType& jacobian() const { return m_jacobian; }
inline JacobianType& jacobian() { return m_jacobian; }
template<typename OtherValueType,typename OtherJacobianType>
inline const AutoDiffVector<
typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,ValueType,OtherValueType>::Type,
typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,JacobianType,OtherJacobianType>::Type >
operator+(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const
{
return AutoDiffVector<
typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,ValueType,OtherValueType>::Type,
typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,JacobianType,OtherJacobianType>::Type >(
m_values + other.values(),
m_jacobian + other.jacobian());
}
template<typename OtherValueType, typename OtherJacobianType>
inline AutoDiffVector&
operator+=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other)
{
m_values += other.values();
m_jacobian += other.jacobian();
return *this;
}
template<typename OtherValueType,typename OtherJacobianType>
inline const AutoDiffVector<
typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,ValueType,OtherValueType>::Type,
typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,JacobianType,OtherJacobianType>::Type >
operator-(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const
{
return AutoDiffVector<
typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,ValueType,OtherValueType>::Type,
typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,JacobianType,OtherJacobianType>::Type >(
m_values - other.values(),
m_jacobian - other.jacobian());
}
template<typename OtherValueType, typename OtherJacobianType>
inline AutoDiffVector&
operator-=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other)
{
m_values -= other.values();
m_jacobian -= other.jacobian();
return *this;
}
inline const AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, JacobianType>::Type >
operator-() const
{
return AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, JacobianType>::Type >(
-m_values,
-m_jacobian);
}
inline const AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type>
operator*(const BaseScalar& other) const
{
return AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type >(
m_values * other,
m_jacobian * other);
}
friend inline const AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type >
operator*(const Scalar& other, const AutoDiffVector& v)
{
return AutoDiffVector<
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type,
typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type >(
v.values() * other,
v.jacobian() * other);
}
// template<typename OtherValueType,typename OtherJacobianType>
// inline const AutoDiffVector<
// CwiseBinaryOp<internal::scalar_multiple_op<Scalar>, ValueType, OtherValueType>
// CwiseBinaryOp<internal::scalar_sum_op<Scalar>,
// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>,
// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, OtherJacobianType> > >
// operator*(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const
// {
// return AutoDiffVector<
// CwiseBinaryOp<internal::scalar_multiple_op<Scalar>, ValueType, OtherValueType>
// CwiseBinaryOp<internal::scalar_sum_op<Scalar>,
// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>,
// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, OtherJacobianType> > >(
// m_values.cwise() * other.values(),
// (m_jacobian * other.values()) + (m_values * other.jacobian()));
// }
inline AutoDiffVector& operator*=(const Scalar& other)
{
m_values *= other;
m_jacobian *= other;
return *this;
}
template<typename OtherValueType,typename OtherJacobianType>
inline AutoDiffVector& operator*=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other)
{
*this = *this * other;
return *this;
}
protected:
ValueType m_values;
JacobianType m_jacobian;
};
}
#endif // EIGEN_AUTODIFF_VECTOR_H

View File

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

View File

@@ -0,0 +1,293 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu>
//
// 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_BVALGORITHMS_H
#define EIGEN_BVALGORITHMS_H
namespace Eigen {
namespace internal {
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename BVH, typename Intersector>
bool intersect_helper(const BVH &tree, Intersector &intersector, typename BVH::Index root)
{
typedef typename BVH::Index Index;
typedef typename BVH::VolumeIterator VolIter;
typedef typename BVH::ObjectIterator ObjIter;
VolIter vBegin = VolIter(), vEnd = VolIter();
ObjIter oBegin = ObjIter(), oEnd = ObjIter();
std::vector<Index> todo(1, root);
while(!todo.empty()) {
tree.getChildren(todo.back(), vBegin, vEnd, oBegin, oEnd);
todo.pop_back();
for(; vBegin != vEnd; ++vBegin) //go through child volumes
if(intersector.intersectVolume(tree.getVolume(*vBegin)))
todo.push_back(*vBegin);
for(; oBegin != oEnd; ++oBegin) //go through child objects
if(intersector.intersectObject(*oBegin))
return true; //intersector said to stop query
}
return false;
}
#endif //not EIGEN_PARSED_BY_DOXYGEN
template<typename Volume1, typename Object1, typename Object2, typename Intersector>
struct intersector_helper1
{
intersector_helper1(const Object2 &inStored, Intersector &in) : stored(inStored), intersector(in) {}
bool intersectVolume(const Volume1 &vol) { return intersector.intersectVolumeObject(vol, stored); }
bool intersectObject(const Object1 &obj) { return intersector.intersectObjectObject(obj, stored); }
Object2 stored;
Intersector &intersector;
private:
intersector_helper1& operator=(const intersector_helper1&);
};
template<typename Volume2, typename Object2, typename Object1, typename Intersector>
struct intersector_helper2
{
intersector_helper2(const Object1 &inStored, Intersector &in) : stored(inStored), intersector(in) {}
bool intersectVolume(const Volume2 &vol) { return intersector.intersectObjectVolume(stored, vol); }
bool intersectObject(const Object2 &obj) { return intersector.intersectObjectObject(stored, obj); }
Object1 stored;
Intersector &intersector;
private:
intersector_helper2& operator=(const intersector_helper2&);
};
} // end namespace internal
/** Given a BVH, runs the query encapsulated by \a intersector.
* The Intersector type must provide the following members: \code
bool intersectVolume(const BVH::Volume &volume) //returns true if volume intersects the query
bool intersectObject(const BVH::Object &object) //returns true if the search should terminate immediately
\endcode
*/
template<typename BVH, typename Intersector>
void BVIntersect(const BVH &tree, Intersector &intersector)
{
internal::intersect_helper(tree, intersector, tree.getRootIndex());
}
/** Given two BVH's, runs the query on their Cartesian product encapsulated by \a intersector.
* The Intersector type must provide the following members: \code
bool intersectVolumeVolume(const BVH1::Volume &v1, const BVH2::Volume &v2) //returns true if product of volumes intersects the query
bool intersectVolumeObject(const BVH1::Volume &v1, const BVH2::Object &o2) //returns true if the volume-object product intersects the query
bool intersectObjectVolume(const BVH1::Object &o1, const BVH2::Volume &v2) //returns true if the volume-object product intersects the query
bool intersectObjectObject(const BVH1::Object &o1, const BVH2::Object &o2) //returns true if the search should terminate immediately
\endcode
*/
template<typename BVH1, typename BVH2, typename Intersector>
void BVIntersect(const BVH1 &tree1, const BVH2 &tree2, Intersector &intersector) //TODO: tandem descent when it makes sense
{
typedef typename BVH1::Index Index1;
typedef typename BVH2::Index Index2;
typedef internal::intersector_helper1<typename BVH1::Volume, typename BVH1::Object, typename BVH2::Object, Intersector> Helper1;
typedef internal::intersector_helper2<typename BVH2::Volume, typename BVH2::Object, typename BVH1::Object, Intersector> Helper2;
typedef typename BVH1::VolumeIterator VolIter1;
typedef typename BVH1::ObjectIterator ObjIter1;
typedef typename BVH2::VolumeIterator VolIter2;
typedef typename BVH2::ObjectIterator ObjIter2;
VolIter1 vBegin1 = VolIter1(), vEnd1 = VolIter1();
ObjIter1 oBegin1 = ObjIter1(), oEnd1 = ObjIter1();
VolIter2 vBegin2 = VolIter2(), vEnd2 = VolIter2(), vCur2 = VolIter2();
ObjIter2 oBegin2 = ObjIter2(), oEnd2 = ObjIter2(), oCur2 = ObjIter2();
std::vector<std::pair<Index1, Index2> > todo(1, std::make_pair(tree1.getRootIndex(), tree2.getRootIndex()));
while(!todo.empty()) {
tree1.getChildren(todo.back().first, vBegin1, vEnd1, oBegin1, oEnd1);
tree2.getChildren(todo.back().second, vBegin2, vEnd2, oBegin2, oEnd2);
todo.pop_back();
for(; vBegin1 != vEnd1; ++vBegin1) { //go through child volumes of first tree
const typename BVH1::Volume &vol1 = tree1.getVolume(*vBegin1);
for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree
if(intersector.intersectVolumeVolume(vol1, tree2.getVolume(*vCur2)))
todo.push_back(std::make_pair(*vBegin1, *vCur2));
}
for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree
Helper1 helper(*oCur2, intersector);
if(internal::intersect_helper(tree1, helper, *vBegin1))
return; //intersector said to stop query
}
}
for(; oBegin1 != oEnd1; ++oBegin1) { //go through child objects of first tree
for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree
Helper2 helper(*oBegin1, intersector);
if(internal::intersect_helper(tree2, helper, *vCur2))
return; //intersector said to stop query
}
for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree
if(intersector.intersectObjectObject(*oBegin1, *oCur2))
return; //intersector said to stop query
}
}
}
}
namespace internal {
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename BVH, typename Minimizer>
typename Minimizer::Scalar minimize_helper(const BVH &tree, Minimizer &minimizer, typename BVH::Index root, typename Minimizer::Scalar minimum)
{
typedef typename Minimizer::Scalar Scalar;
typedef typename BVH::Index Index;
typedef std::pair<Scalar, Index> QueueElement; //first element is priority
typedef typename BVH::VolumeIterator VolIter;
typedef typename BVH::ObjectIterator ObjIter;
VolIter vBegin = VolIter(), vEnd = VolIter();
ObjIter oBegin = ObjIter(), oEnd = ObjIter();
std::priority_queue<QueueElement, std::vector<QueueElement>, std::greater<QueueElement> > todo; //smallest is at the top
todo.push(std::make_pair(Scalar(), root));
while(!todo.empty()) {
tree.getChildren(todo.top().second, vBegin, vEnd, oBegin, oEnd);
todo.pop();
for(; oBegin != oEnd; ++oBegin) //go through child objects
minimum = (std::min)(minimum, minimizer.minimumOnObject(*oBegin));
for(; vBegin != vEnd; ++vBegin) { //go through child volumes
Scalar val = minimizer.minimumOnVolume(tree.getVolume(*vBegin));
if(val < minimum)
todo.push(std::make_pair(val, *vBegin));
}
}
return minimum;
}
#endif //not EIGEN_PARSED_BY_DOXYGEN
template<typename Volume1, typename Object1, typename Object2, typename Minimizer>
struct minimizer_helper1
{
typedef typename Minimizer::Scalar Scalar;
minimizer_helper1(const Object2 &inStored, Minimizer &m) : stored(inStored), minimizer(m) {}
Scalar minimumOnVolume(const Volume1 &vol) { return minimizer.minimumOnVolumeObject(vol, stored); }
Scalar minimumOnObject(const Object1 &obj) { return minimizer.minimumOnObjectObject(obj, stored); }
Object2 stored;
Minimizer &minimizer;
private:
minimizer_helper1& operator=(const minimizer_helper1&);
};
template<typename Volume2, typename Object2, typename Object1, typename Minimizer>
struct minimizer_helper2
{
typedef typename Minimizer::Scalar Scalar;
minimizer_helper2(const Object1 &inStored, Minimizer &m) : stored(inStored), minimizer(m) {}
Scalar minimumOnVolume(const Volume2 &vol) { return minimizer.minimumOnObjectVolume(stored, vol); }
Scalar minimumOnObject(const Object2 &obj) { return minimizer.minimumOnObjectObject(stored, obj); }
Object1 stored;
Minimizer &minimizer;
private:
minimizer_helper2& operator=(const minimizer_helper2&);
};
} // end namespace internal
/** Given a BVH, runs the query encapsulated by \a minimizer.
* \returns the minimum value.
* The Minimizer type must provide the following members: \code
typedef Scalar //the numeric type of what is being minimized--not necessarily the Scalar type of the BVH (if it has one)
Scalar minimumOnVolume(const BVH::Volume &volume)
Scalar minimumOnObject(const BVH::Object &object)
\endcode
*/
template<typename BVH, typename Minimizer>
typename Minimizer::Scalar BVMinimize(const BVH &tree, Minimizer &minimizer)
{
return internal::minimize_helper(tree, minimizer, tree.getRootIndex(), (std::numeric_limits<typename Minimizer::Scalar>::max)());
}
/** Given two BVH's, runs the query on their cartesian product encapsulated by \a minimizer.
* \returns the minimum value.
* The Minimizer type must provide the following members: \code
typedef Scalar //the numeric type of what is being minimized--not necessarily the Scalar type of the BVH (if it has one)
Scalar minimumOnVolumeVolume(const BVH1::Volume &v1, const BVH2::Volume &v2)
Scalar minimumOnVolumeObject(const BVH1::Volume &v1, const BVH2::Object &o2)
Scalar minimumOnObjectVolume(const BVH1::Object &o1, const BVH2::Volume &v2)
Scalar minimumOnObjectObject(const BVH1::Object &o1, const BVH2::Object &o2)
\endcode
*/
template<typename BVH1, typename BVH2, typename Minimizer>
typename Minimizer::Scalar BVMinimize(const BVH1 &tree1, const BVH2 &tree2, Minimizer &minimizer)
{
typedef typename Minimizer::Scalar Scalar;
typedef typename BVH1::Index Index1;
typedef typename BVH2::Index Index2;
typedef internal::minimizer_helper1<typename BVH1::Volume, typename BVH1::Object, typename BVH2::Object, Minimizer> Helper1;
typedef internal::minimizer_helper2<typename BVH2::Volume, typename BVH2::Object, typename BVH1::Object, Minimizer> Helper2;
typedef std::pair<Scalar, std::pair<Index1, Index2> > QueueElement; //first element is priority
typedef typename BVH1::VolumeIterator VolIter1;
typedef typename BVH1::ObjectIterator ObjIter1;
typedef typename BVH2::VolumeIterator VolIter2;
typedef typename BVH2::ObjectIterator ObjIter2;
VolIter1 vBegin1 = VolIter1(), vEnd1 = VolIter1();
ObjIter1 oBegin1 = ObjIter1(), oEnd1 = ObjIter1();
VolIter2 vBegin2 = VolIter2(), vEnd2 = VolIter2(), vCur2 = VolIter2();
ObjIter2 oBegin2 = ObjIter2(), oEnd2 = ObjIter2(), oCur2 = ObjIter2();
std::priority_queue<QueueElement, std::vector<QueueElement>, std::greater<QueueElement> > todo; //smallest is at the top
Scalar minimum = (std::numeric_limits<Scalar>::max)();
todo.push(std::make_pair(Scalar(), std::make_pair(tree1.getRootIndex(), tree2.getRootIndex())));
while(!todo.empty()) {
tree1.getChildren(todo.top().second.first, vBegin1, vEnd1, oBegin1, oEnd1);
tree2.getChildren(todo.top().second.second, vBegin2, vEnd2, oBegin2, oEnd2);
todo.pop();
for(; oBegin1 != oEnd1; ++oBegin1) { //go through child objects of first tree
for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree
minimum = (std::min)(minimum, minimizer.minimumOnObjectObject(*oBegin1, *oCur2));
}
for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree
Helper2 helper(*oBegin1, minimizer);
minimum = (std::min)(minimum, internal::minimize_helper(tree2, helper, *vCur2, minimum));
}
}
for(; vBegin1 != vEnd1; ++vBegin1) { //go through child volumes of first tree
const typename BVH1::Volume &vol1 = tree1.getVolume(*vBegin1);
for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree
Helper1 helper(*oCur2, minimizer);
minimum = (std::min)(minimum, internal::minimize_helper(tree1, helper, *vBegin1, minimum));
}
for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree
Scalar val = minimizer.minimumOnVolumeVolume(vol1, tree2.getVolume(*vCur2));
if(val < minimum)
todo.push(std::make_pair(val, std::make_pair(*vBegin1, *vCur2)));
}
}
}
return minimum;
}
} // end namespace Eigen
#endif // EIGEN_BVALGORITHMS_H

View File

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

View File

@@ -0,0 +1,222 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu>
//
// 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 KDBVH_H_INCLUDED
#define KDBVH_H_INCLUDED
namespace Eigen {
namespace internal {
//internal pair class for the BVH--used instead of std::pair because of alignment
template<typename Scalar, int Dim>
struct vector_int_pair
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar, Dim)
typedef Matrix<Scalar, Dim, 1> VectorType;
vector_int_pair(const VectorType &v, int i) : first(v), second(i) {}
VectorType first;
int second;
};
//these templates help the tree initializer get the bounding boxes either from a provided
//iterator range or using bounding_box in a unified way
template<typename ObjectList, typename VolumeList, typename BoxIter>
struct get_boxes_helper {
void operator()(const ObjectList &objects, BoxIter boxBegin, BoxIter boxEnd, VolumeList &outBoxes)
{
outBoxes.insert(outBoxes.end(), boxBegin, boxEnd);
eigen_assert(outBoxes.size() == objects.size());
}
};
template<typename ObjectList, typename VolumeList>
struct get_boxes_helper<ObjectList, VolumeList, int> {
void operator()(const ObjectList &objects, int, int, VolumeList &outBoxes)
{
outBoxes.reserve(objects.size());
for(int i = 0; i < (int)objects.size(); ++i)
outBoxes.push_back(bounding_box(objects[i]));
}
};
} // end namespace internal
/** \class KdBVH
* \brief A simple bounding volume hierarchy based on AlignedBox
*
* \param _Scalar The underlying scalar type of the bounding boxes
* \param _Dim The dimension of the space in which the hierarchy lives
* \param _Object The object type that lives in the hierarchy. It must have value semantics. Either bounding_box(_Object) must
* be defined and return an AlignedBox<_Scalar, _Dim> or bounding boxes must be provided to the tree initializer.
*
* This class provides a simple (as opposed to optimized) implementation of a bounding volume hierarchy analogous to a Kd-tree.
* Given a sequence of objects, it computes their bounding boxes, constructs a Kd-tree of their centers
* and builds a BVH with the structure of that Kd-tree. When the elements of the tree are too expensive to be copied around,
* it is useful for _Object to be a pointer.
*/
template<typename _Scalar, int _Dim, typename _Object> class KdBVH
{
public:
enum { Dim = _Dim };
typedef _Object Object;
typedef std::vector<Object, aligned_allocator<Object> > ObjectList;
typedef _Scalar Scalar;
typedef AlignedBox<Scalar, Dim> Volume;
typedef std::vector<Volume, aligned_allocator<Volume> > VolumeList;
typedef int Index;
typedef const int *VolumeIterator; //the iterators are just pointers into the tree's vectors
typedef const Object *ObjectIterator;
KdBVH() {}
/** Given an iterator range over \a Object references, constructs the BVH. Requires that bounding_box(Object) return a Volume. */
template<typename Iter> KdBVH(Iter begin, Iter end) { init(begin, end, 0, 0); } //int is recognized by init as not being an iterator type
/** Given an iterator range over \a Object references and an iterator range over their bounding boxes, constructs the BVH */
template<typename OIter, typename BIter> KdBVH(OIter begin, OIter end, BIter boxBegin, BIter boxEnd) { init(begin, end, boxBegin, boxEnd); }
/** Given an iterator range over \a Object references, constructs the BVH, overwriting whatever is in there currently.
* Requires that bounding_box(Object) return a Volume. */
template<typename Iter> void init(Iter begin, Iter end) { init(begin, end, 0, 0); }
/** Given an iterator range over \a Object references and an iterator range over their bounding boxes,
* constructs the BVH, overwriting whatever is in there currently. */
template<typename OIter, typename BIter> void init(OIter begin, OIter end, BIter boxBegin, BIter boxEnd)
{
objects.clear();
boxes.clear();
children.clear();
objects.insert(objects.end(), begin, end);
int n = static_cast<int>(objects.size());
if(n < 2)
return; //if we have at most one object, we don't need any internal nodes
VolumeList objBoxes;
VIPairList objCenters;
//compute the bounding boxes depending on BIter type
internal::get_boxes_helper<ObjectList, VolumeList, BIter>()(objects, boxBegin, boxEnd, objBoxes);
objCenters.reserve(n);
boxes.reserve(n - 1);
children.reserve(2 * n - 2);
for(int i = 0; i < n; ++i)
objCenters.push_back(VIPair(objBoxes[i].center(), i));
build(objCenters, 0, n, objBoxes, 0); //the recursive part of the algorithm
ObjectList tmp(n);
tmp.swap(objects);
for(int i = 0; i < n; ++i)
objects[i] = tmp[objCenters[i].second];
}
/** \returns the index of the root of the hierarchy */
inline Index getRootIndex() const { return (int)boxes.size() - 1; }
/** Given an \a index of a node, on exit, \a outVBegin and \a outVEnd range over the indices of the volume children of the node
* and \a outOBegin and \a outOEnd range over the object children of the node */
EIGEN_STRONG_INLINE void getChildren(Index index, VolumeIterator &outVBegin, VolumeIterator &outVEnd,
ObjectIterator &outOBegin, ObjectIterator &outOEnd) const
{ //inlining this function should open lots of optimization opportunities to the compiler
if(index < 0) {
outVBegin = outVEnd;
if(!objects.empty())
outOBegin = &(objects[0]);
outOEnd = outOBegin + objects.size(); //output all objects--necessary when the tree has only one object
return;
}
int numBoxes = static_cast<int>(boxes.size());
int idx = index * 2;
if(children[idx + 1] < numBoxes) { //second index is always bigger
outVBegin = &(children[idx]);
outVEnd = outVBegin + 2;
outOBegin = outOEnd;
}
else if(children[idx] >= numBoxes) { //if both children are objects
outVBegin = outVEnd;
outOBegin = &(objects[children[idx] - numBoxes]);
outOEnd = outOBegin + 2;
} else { //if the first child is a volume and the second is an object
outVBegin = &(children[idx]);
outVEnd = outVBegin + 1;
outOBegin = &(objects[children[idx + 1] - numBoxes]);
outOEnd = outOBegin + 1;
}
}
/** \returns the bounding box of the node at \a index */
inline const Volume &getVolume(Index index) const
{
return boxes[index];
}
private:
typedef internal::vector_int_pair<Scalar, Dim> VIPair;
typedef std::vector<VIPair, aligned_allocator<VIPair> > VIPairList;
typedef Matrix<Scalar, Dim, 1> VectorType;
struct VectorComparator //compares vectors, or, more specificall, VIPairs along a particular dimension
{
VectorComparator(int inDim) : dim(inDim) {}
inline bool operator()(const VIPair &v1, const VIPair &v2) const { return v1.first[dim] < v2.first[dim]; }
int dim;
};
//Build the part of the tree between objects[from] and objects[to] (not including objects[to]).
//This routine partitions the objCenters in [from, to) along the dimension dim, recursively constructs
//the two halves, and adds their parent node. TODO: a cache-friendlier layout
void build(VIPairList &objCenters, int from, int to, const VolumeList &objBoxes, int dim)
{
eigen_assert(to - from > 1);
if(to - from == 2) {
boxes.push_back(objBoxes[objCenters[from].second].merged(objBoxes[objCenters[from + 1].second]));
children.push_back(from + (int)objects.size() - 1); //there are objects.size() - 1 tree nodes
children.push_back(from + (int)objects.size());
}
else if(to - from == 3) {
int mid = from + 2;
std::nth_element(objCenters.begin() + from, objCenters.begin() + mid,
objCenters.begin() + to, VectorComparator(dim)); //partition
build(objCenters, from, mid, objBoxes, (dim + 1) % Dim);
int idx1 = (int)boxes.size() - 1;
boxes.push_back(boxes[idx1].merged(objBoxes[objCenters[mid].second]));
children.push_back(idx1);
children.push_back(mid + (int)objects.size() - 1);
}
else {
int mid = from + (to - from) / 2;
nth_element(objCenters.begin() + from, objCenters.begin() + mid,
objCenters.begin() + to, VectorComparator(dim)); //partition
build(objCenters, from, mid, objBoxes, (dim + 1) % Dim);
int idx1 = (int)boxes.size() - 1;
build(objCenters, mid, to, objBoxes, (dim + 1) % Dim);
int idx2 = (int)boxes.size() - 1;
boxes.push_back(boxes[idx1].merged(boxes[idx2]));
children.push_back(idx1);
children.push_back(idx2);
}
}
std::vector<int> children; //children of x are children[2x] and children[2x+1], indices bigger than boxes.size() index into objects.
VolumeList boxes;
ObjectList objects;
};
} // end namespace Eigen
#endif //KDBVH_H_INCLUDED

View File

@@ -0,0 +1,15 @@
ADD_SUBDIRECTORY(AutoDiff)
ADD_SUBDIRECTORY(BVH)
ADD_SUBDIRECTORY(Eigenvalues)
ADD_SUBDIRECTORY(FFT)
ADD_SUBDIRECTORY(IterativeSolvers)
ADD_SUBDIRECTORY(KroneckerProduct)
ADD_SUBDIRECTORY(LevenbergMarquardt)
ADD_SUBDIRECTORY(MatrixFunctions)
ADD_SUBDIRECTORY(MoreVectorization)
ADD_SUBDIRECTORY(NonLinearOptimization)
ADD_SUBDIRECTORY(NumericalDiff)
ADD_SUBDIRECTORY(Polynomials)
ADD_SUBDIRECTORY(Skyline)
ADD_SUBDIRECTORY(SparseExtra)
ADD_SUBDIRECTORY(Splines)

View File

@@ -0,0 +1,805 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 David Harmon <dharmon@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H
#define EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H
#include <Eigen/Dense>
namespace Eigen {
namespace internal {
template<typename Scalar, typename RealScalar> struct arpack_wrapper;
template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD> struct OP;
}
template<typename MatrixType, typename MatrixSolver=SimplicialLLT<MatrixType>, bool BisSPD=false>
class ArpackGeneralizedSelfAdjointEigenSolver
{
public:
//typedef typename MatrixSolver::MatrixType MatrixType;
/** \brief Scalar type for matrices of type \p MatrixType. */
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
/** \brief Real scalar type for \p MatrixType.
*
* This is just \c Scalar if #Scalar is real (e.g., \c float or
* \c Scalar), and the type of the real part of \c Scalar if #Scalar is
* complex.
*/
typedef typename NumTraits<Scalar>::Real RealScalar;
/** \brief Type for vector of eigenvalues as returned by eigenvalues().
*
* This is a column vector with entries of type #RealScalar.
* The length of the vector is the size of \p nbrEigenvalues.
*/
typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVectorType;
/** \brief Default constructor.
*
* The default constructor is for cases in which the user intends to
* perform decompositions via compute().
*
*/
ArpackGeneralizedSelfAdjointEigenSolver()
: m_eivec(),
m_eivalues(),
m_isInitialized(false),
m_eigenvectorsOk(false),
m_nbrConverged(0),
m_nbrIterations(0)
{ }
/** \brief Constructor; computes generalized eigenvalues of given matrix with respect to another matrix.
*
* \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will
* computed. By default, the upper triangular part is used, but can be changed
* through the template parameter.
* \param[in] B Self-adjoint matrix for the generalized eigenvalue problem.
* \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
* Must be less than the size of the input matrix, or an error is returned.
* \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
* respective meanings to find the largest magnitude , smallest magnitude,
* largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
* value can contain floating point value in string form, in which case the
* eigenvalues closest to this value will be found.
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
* \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
* means machine precision.
*
* This constructor calls compute(const MatrixType&, const MatrixType&, Index, string, int, RealScalar)
* to compute the eigenvalues of the matrix \p A with respect to \p B. The eigenvectors are computed if
* \p options equals #ComputeEigenvectors.
*
*/
ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A, const MatrixType& B,
Index nbrEigenvalues, std::string eigs_sigma="LM",
int options=ComputeEigenvectors, RealScalar tol=0.0)
: m_eivec(),
m_eivalues(),
m_isInitialized(false),
m_eigenvectorsOk(false),
m_nbrConverged(0),
m_nbrIterations(0)
{
compute(A, B, nbrEigenvalues, eigs_sigma, options, tol);
}
/** \brief Constructor; computes eigenvalues of given matrix.
*
* \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will
* computed. By default, the upper triangular part is used, but can be changed
* through the template parameter.
* \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
* Must be less than the size of the input matrix, or an error is returned.
* \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
* respective meanings to find the largest magnitude , smallest magnitude,
* largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
* value can contain floating point value in string form, in which case the
* eigenvalues closest to this value will be found.
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
* \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
* means machine precision.
*
* This constructor calls compute(const MatrixType&, Index, string, int, RealScalar)
* to compute the eigenvalues of the matrix \p A. The eigenvectors are computed if
* \p options equals #ComputeEigenvectors.
*
*/
ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A,
Index nbrEigenvalues, std::string eigs_sigma="LM",
int options=ComputeEigenvectors, RealScalar tol=0.0)
: m_eivec(),
m_eivalues(),
m_isInitialized(false),
m_eigenvectorsOk(false),
m_nbrConverged(0),
m_nbrIterations(0)
{
compute(A, nbrEigenvalues, eigs_sigma, options, tol);
}
/** \brief Computes generalized eigenvalues / eigenvectors of given matrix using the external ARPACK library.
*
* \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed.
* \param[in] B Selfadjoint matrix for generalized eigenvalues.
* \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
* Must be less than the size of the input matrix, or an error is returned.
* \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
* respective meanings to find the largest magnitude , smallest magnitude,
* largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
* value can contain floating point value in string form, in which case the
* eigenvalues closest to this value will be found.
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
* \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
* means machine precision.
*
* \returns Reference to \c *this
*
* This function computes the generalized eigenvalues of \p A with respect to \p B using ARPACK. The eigenvalues()
* function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
* then the eigenvectors are also computed and can be retrieved by
* calling eigenvectors().
*
*/
ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A, const MatrixType& B,
Index nbrEigenvalues, std::string eigs_sigma="LM",
int options=ComputeEigenvectors, RealScalar tol=0.0);
/** \brief Computes eigenvalues / eigenvectors of given matrix using the external ARPACK library.
*
* \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed.
* \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute.
* Must be less than the size of the input matrix, or an error is returned.
* \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with
* respective meanings to find the largest magnitude , smallest magnitude,
* largest algebraic, or smallest algebraic eigenvalues. Alternatively, this
* value can contain floating point value in string form, in which case the
* eigenvalues closest to this value will be found.
* \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
* \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which
* means machine precision.
*
* \returns Reference to \c *this
*
* This function computes the eigenvalues of \p A using ARPACK. The eigenvalues()
* function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
* then the eigenvectors are also computed and can be retrieved by
* calling eigenvectors().
*
*/
ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A,
Index nbrEigenvalues, std::string eigs_sigma="LM",
int options=ComputeEigenvectors, RealScalar tol=0.0);
/** \brief Returns the eigenvectors of given matrix.
*
* \returns A const reference to the matrix whose columns are the eigenvectors.
*
* \pre The eigenvectors have been computed before.
*
* Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
* to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
* eigenvectors are normalized to have (Euclidean) norm equal to one. If
* this object was used to solve the eigenproblem for the selfadjoint
* matrix \f$ A \f$, then the matrix returned by this function is the
* matrix \f$ V \f$ in the eigendecomposition \f$ A V = D V \f$.
* For the generalized eigenproblem, the matrix returned is the solution \f$ A V = D B V \f$
*
* Example: \include SelfAdjointEigenSolver_eigenvectors.cpp
* Output: \verbinclude SelfAdjointEigenSolver_eigenvectors.out
*
* \sa eigenvalues()
*/
const Matrix<Scalar, Dynamic, Dynamic>& eigenvectors() const
{
eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
return m_eivec;
}
/** \brief Returns the eigenvalues of given matrix.
*
* \returns A const reference to the column vector containing the eigenvalues.
*
* \pre The eigenvalues have been computed before.
*
* The eigenvalues are repeated according to their algebraic multiplicity,
* so there are as many eigenvalues as rows in the matrix. The eigenvalues
* are sorted in increasing order.
*
* Example: \include SelfAdjointEigenSolver_eigenvalues.cpp
* Output: \verbinclude SelfAdjointEigenSolver_eigenvalues.out
*
* \sa eigenvectors(), MatrixBase::eigenvalues()
*/
const Matrix<Scalar, Dynamic, 1>& eigenvalues() const
{
eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
return m_eivalues;
}
/** \brief Computes the positive-definite square root of the matrix.
*
* \returns the positive-definite square root of the matrix
*
* \pre The eigenvalues and eigenvectors of a positive-definite matrix
* have been computed before.
*
* The square root of a positive-definite matrix \f$ A \f$ is the
* positive-definite matrix whose square equals \f$ A \f$. This function
* uses the eigendecomposition \f$ A = V D V^{-1} \f$ to compute the
* square root as \f$ A^{1/2} = V D^{1/2} V^{-1} \f$.
*
* Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp
* Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out
*
* \sa operatorInverseSqrt(),
* \ref MatrixFunctions_Module "MatrixFunctions Module"
*/
Matrix<Scalar, Dynamic, Dynamic> operatorSqrt() const
{
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
}
/** \brief Computes the inverse square root of the matrix.
*
* \returns the inverse positive-definite square root of the matrix
*
* \pre The eigenvalues and eigenvectors of a positive-definite matrix
* have been computed before.
*
* This function uses the eigendecomposition \f$ A = V D V^{-1} \f$ to
* compute the inverse square root as \f$ V D^{-1/2} V^{-1} \f$. This is
* cheaper than first computing the square root with operatorSqrt() and
* then its inverse with MatrixBase::inverse().
*
* Example: \include SelfAdjointEigenSolver_operatorInverseSqrt.cpp
* Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out
*
* \sa operatorSqrt(), MatrixBase::inverse(),
* \ref MatrixFunctions_Module "MatrixFunctions Module"
*/
Matrix<Scalar, Dynamic, Dynamic> operatorInverseSqrt() const
{
eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint();
}
/** \brief Reports whether previous computation was successful.
*
* \returns \c Success if computation was succesful, \c NoConvergence otherwise.
*/
ComputationInfo info() const
{
eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized.");
return m_info;
}
size_t getNbrConvergedEigenValues() const
{ return m_nbrConverged; }
size_t getNbrIterations() const
{ return m_nbrIterations; }
protected:
Matrix<Scalar, Dynamic, Dynamic> m_eivec;
Matrix<Scalar, Dynamic, 1> m_eivalues;
ComputationInfo m_info;
bool m_isInitialized;
bool m_eigenvectorsOk;
size_t m_nbrConverged;
size_t m_nbrIterations;
};
template<typename MatrixType, typename MatrixSolver, bool BisSPD>
ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>&
ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>
::compute(const MatrixType& A, Index nbrEigenvalues,
std::string eigs_sigma, int options, RealScalar tol)
{
MatrixType B(0,0);
compute(A, B, nbrEigenvalues, eigs_sigma, options, tol);
return *this;
}
template<typename MatrixType, typename MatrixSolver, bool BisSPD>
ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>&
ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>
::compute(const MatrixType& A, const MatrixType& B, Index nbrEigenvalues,
std::string eigs_sigma, int options, RealScalar tol)
{
eigen_assert(A.cols() == A.rows());
eigen_assert(B.cols() == B.rows());
eigen_assert(B.rows() == 0 || A.cols() == B.rows());
eigen_assert((options &~ (EigVecMask | GenEigMask)) == 0
&& (options & EigVecMask) != EigVecMask
&& "invalid option parameter");
bool isBempty = (B.rows() == 0) || (B.cols() == 0);
// For clarity, all parameters match their ARPACK name
//
// Always 0 on the first call
//
int ido = 0;
int n = (int)A.cols();
// User options: "LA", "SA", "SM", "LM", "BE"
//
char whch[3] = "LM";
// Specifies the shift if iparam[6] = { 3, 4, 5 }, not used if iparam[6] = { 1, 2 }
//
RealScalar sigma = 0.0;
if (eigs_sigma.length() >= 2 && isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1]))
{
eigs_sigma[0] = toupper(eigs_sigma[0]);
eigs_sigma[1] = toupper(eigs_sigma[1]);
// In the following special case we're going to invert the problem, since solving
// for larger magnitude is much much faster
// i.e., if 'SM' is specified, we're going to really use 'LM', the default
//
if (eigs_sigma.substr(0,2) != "SM")
{
whch[0] = eigs_sigma[0];
whch[1] = eigs_sigma[1];
}
}
else
{
eigen_assert(false && "Specifying clustered eigenvalues is not yet supported!");
// If it's not scalar values, then the user may be explicitly
// specifying the sigma value to cluster the evs around
//
sigma = atof(eigs_sigma.c_str());
// If atof fails, it returns 0.0, which is a fine default
//
}
// "I" means normal eigenvalue problem, "G" means generalized
//
char bmat[2] = "I";
if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])) || (!isBempty && !BisSPD))
bmat[0] = 'G';
// Now we determine the mode to use
//
int mode = (bmat[0] == 'G') + 1;
if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])))
{
// We're going to use shift-and-invert mode, and basically find
// the largest eigenvalues of the inverse operator
//
mode = 3;
}
// The user-specified number of eigenvalues/vectors to compute
//
int nev = (int)nbrEigenvalues;
// Allocate space for ARPACK to store the residual
//
Scalar *resid = new Scalar[n];
// Number of Lanczos vectors, must satisfy nev < ncv <= n
// Note that this indicates that nev != n, and we cannot compute
// all eigenvalues of a mtrix
//
int ncv = std::min(std::max(2*nev, 20), n);
// The working n x ncv matrix, also store the final eigenvectors (if computed)
//
Scalar *v = new Scalar[n*ncv];
int ldv = n;
// Working space
//
Scalar *workd = new Scalar[3*n];
int lworkl = ncv*ncv+8*ncv; // Must be at least this length
Scalar *workl = new Scalar[lworkl];
int *iparam= new int[11];
iparam[0] = 1; // 1 means we let ARPACK perform the shifts, 0 means we'd have to do it
iparam[2] = std::max(300, (int)std::ceil(2*n/std::max(ncv,1)));
iparam[6] = mode; // The mode, 1 is standard ev problem, 2 for generalized ev, 3 for shift-and-invert
// Used during reverse communicate to notify where arrays start
//
int *ipntr = new int[11];
// Error codes are returned in here, initial value of 0 indicates a random initial
// residual vector is used, any other values means resid contains the initial residual
// vector, possibly from a previous run
//
int info = 0;
Scalar scale = 1.0;
//if (!isBempty)
//{
//Scalar scale = B.norm() / std::sqrt(n);
//scale = std::pow(2, std::floor(std::log(scale+1)));
////M /= scale;
//for (size_t i=0; i<(size_t)B.outerSize(); i++)
// for (typename MatrixType::InnerIterator it(B, i); it; ++it)
// it.valueRef() /= scale;
//}
MatrixSolver OP;
if (mode == 1 || mode == 2)
{
if (!isBempty)
OP.compute(B);
}
else if (mode == 3)
{
if (sigma == 0.0)
{
OP.compute(A);
}
else
{
// Note: We will never enter here because sigma must be 0.0
//
if (isBempty)
{
MatrixType AminusSigmaB(A);
for (Index i=0; i<A.rows(); ++i)
AminusSigmaB.coeffRef(i,i) -= sigma;
OP.compute(AminusSigmaB);
}
else
{
MatrixType AminusSigmaB = A - sigma * B;
OP.compute(AminusSigmaB);
}
}
}
if (!(mode == 1 && isBempty) && !(mode == 2 && isBempty) && OP.info() != Success)
std::cout << "Error factoring matrix" << std::endl;
do
{
internal::arpack_wrapper<Scalar, RealScalar>::saupd(&ido, bmat, &n, whch, &nev, &tol, resid,
&ncv, v, &ldv, iparam, ipntr, workd, workl,
&lworkl, &info);
if (ido == -1 || ido == 1)
{
Scalar *in = workd + ipntr[0] - 1;
Scalar *out = workd + ipntr[1] - 1;
if (ido == 1 && mode != 2)
{
Scalar *out2 = workd + ipntr[2] - 1;
if (isBempty || mode == 1)
Matrix<Scalar, Dynamic, 1>::Map(out2, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n);
else
Matrix<Scalar, Dynamic, 1>::Map(out2, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n);
in = workd + ipntr[2] - 1;
}
if (mode == 1)
{
if (isBempty)
{
// OP = A
//
Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n);
}
else
{
// OP = L^{-1}AL^{-T}
//
internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::applyOP(OP, A, n, in, out);
}
}
else if (mode == 2)
{
if (ido == 1)
Matrix<Scalar, Dynamic, 1>::Map(in, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n);
// OP = B^{-1} A
//
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
}
else if (mode == 3)
{
// OP = (A-\sigmaB)B (\sigma could be 0, and B could be I)
// The B * in is already computed and stored at in if ido == 1
//
if (ido == 1 || isBempty)
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
else
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(B * Matrix<Scalar, Dynamic, 1>::Map(in, n));
}
}
else if (ido == 2)
{
Scalar *in = workd + ipntr[0] - 1;
Scalar *out = workd + ipntr[1] - 1;
if (isBempty || mode == 1)
Matrix<Scalar, Dynamic, 1>::Map(out, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n);
else
Matrix<Scalar, Dynamic, 1>::Map(out, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n);
}
} while (ido != 99);
if (info == 1)
m_info = NoConvergence;
else if (info == 3)
m_info = NumericalIssue;
else if (info < 0)
m_info = InvalidInput;
else if (info != 0)
eigen_assert(false && "Unknown ARPACK return value!");
else
{
// Do we compute eigenvectors or not?
//
int rvec = (options & ComputeEigenvectors) == ComputeEigenvectors;
// "A" means "All", use "S" to choose specific eigenvalues (not yet supported in ARPACK))
//
char howmny[2] = "A";
// if howmny == "S", specifies the eigenvalues to compute (not implemented in ARPACK)
//
int *select = new int[ncv];
// Final eigenvalues
//
m_eivalues.resize(nev, 1);
internal::arpack_wrapper<Scalar, RealScalar>::seupd(&rvec, howmny, select, m_eivalues.data(), v, &ldv,
&sigma, bmat, &n, whch, &nev, &tol, resid, &ncv,
v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info);
if (info == -14)
m_info = NoConvergence;
else if (info != 0)
m_info = InvalidInput;
else
{
if (rvec)
{
m_eivec.resize(A.rows(), nev);
for (int i=0; i<nev; i++)
for (int j=0; j<n; j++)
m_eivec(j,i) = v[i*n+j] / scale;
if (mode == 1 && !isBempty && BisSPD)
internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::project(OP, n, nev, m_eivec.data());
m_eigenvectorsOk = true;
}
m_nbrIterations = iparam[2];
m_nbrConverged = iparam[4];
m_info = Success;
}
delete select;
}
delete v;
delete iparam;
delete ipntr;
delete workd;
delete workl;
delete resid;
m_isInitialized = true;
return *this;
}
// Single precision
//
extern "C" void ssaupd_(int *ido, char *bmat, int *n, char *which,
int *nev, float *tol, float *resid, int *ncv,
float *v, int *ldv, int *iparam, int *ipntr,
float *workd, float *workl, int *lworkl,
int *info);
extern "C" void sseupd_(int *rvec, char *All, int *select, float *d,
float *z, int *ldz, float *sigma,
char *bmat, int *n, char *which, int *nev,
float *tol, float *resid, int *ncv, float *v,
int *ldv, int *iparam, int *ipntr, float *workd,
float *workl, int *lworkl, int *ierr);
// Double precision
//
extern "C" void dsaupd_(int *ido, char *bmat, int *n, char *which,
int *nev, double *tol, double *resid, int *ncv,
double *v, int *ldv, int *iparam, int *ipntr,
double *workd, double *workl, int *lworkl,
int *info);
extern "C" void dseupd_(int *rvec, char *All, int *select, double *d,
double *z, int *ldz, double *sigma,
char *bmat, int *n, char *which, int *nev,
double *tol, double *resid, int *ncv, double *v,
int *ldv, int *iparam, int *ipntr, double *workd,
double *workl, int *lworkl, int *ierr);
namespace internal {
template<typename Scalar, typename RealScalar> struct arpack_wrapper
{
static inline void saupd(int *ido, char *bmat, int *n, char *which,
int *nev, RealScalar *tol, Scalar *resid, int *ncv,
Scalar *v, int *ldv, int *iparam, int *ipntr,
Scalar *workd, Scalar *workl, int *lworkl, int *info)
{
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
}
static inline void seupd(int *rvec, char *All, int *select, Scalar *d,
Scalar *z, int *ldz, RealScalar *sigma,
char *bmat, int *n, char *which, int *nev,
RealScalar *tol, Scalar *resid, int *ncv, Scalar *v,
int *ldv, int *iparam, int *ipntr, Scalar *workd,
Scalar *workl, int *lworkl, int *ierr)
{
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
}
};
template <> struct arpack_wrapper<float, float>
{
static inline void saupd(int *ido, char *bmat, int *n, char *which,
int *nev, float *tol, float *resid, int *ncv,
float *v, int *ldv, int *iparam, int *ipntr,
float *workd, float *workl, int *lworkl, int *info)
{
ssaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}
static inline void seupd(int *rvec, char *All, int *select, float *d,
float *z, int *ldz, float *sigma,
char *bmat, int *n, char *which, int *nev,
float *tol, float *resid, int *ncv, float *v,
int *ldv, int *iparam, int *ipntr, float *workd,
float *workl, int *lworkl, int *ierr)
{
sseupd_(rvec, All, select, d, z, ldz, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
workd, workl, lworkl, ierr);
}
};
template <> struct arpack_wrapper<double, double>
{
static inline void saupd(int *ido, char *bmat, int *n, char *which,
int *nev, double *tol, double *resid, int *ncv,
double *v, int *ldv, int *iparam, int *ipntr,
double *workd, double *workl, int *lworkl, int *info)
{
dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info);
}
static inline void seupd(int *rvec, char *All, int *select, double *d,
double *z, int *ldz, double *sigma,
char *bmat, int *n, char *which, int *nev,
double *tol, double *resid, int *ncv, double *v,
int *ldv, int *iparam, int *ipntr, double *workd,
double *workl, int *lworkl, int *ierr)
{
dseupd_(rvec, All, select, d, v, ldv, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr,
workd, workl, lworkl, ierr);
}
};
template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD>
struct OP
{
static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out);
static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs);
};
template<typename MatrixSolver, typename MatrixType, typename Scalar>
struct OP<MatrixSolver, MatrixType, Scalar, true>
{
static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out)
{
// OP = L^{-1} A L^{-T} (B = LL^T)
//
// First solve L^T out = in
//
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixU().solve(Matrix<Scalar, Dynamic, 1>::Map(in, n));
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationPinv() * Matrix<Scalar, Dynamic, 1>::Map(out, n);
// Then compute out = A out
//
Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(out, n);
// Then solve L out = out
//
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationP() * Matrix<Scalar, Dynamic, 1>::Map(out, n);
Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixL().solve(Matrix<Scalar, Dynamic, 1>::Map(out, n));
}
static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs)
{
// Solve L^T out = in
//
Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.matrixU().solve(Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k));
Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.permutationPinv() * Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k);
}
};
template<typename MatrixSolver, typename MatrixType, typename Scalar>
struct OP<MatrixSolver, MatrixType, Scalar, false>
{
static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out)
{
eigen_assert(false && "Should never be in here...");
}
static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs)
{
eigen_assert(false && "Should never be in here...");
}
};
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_ARPACKSELFADJOINTEIGENSOLVER_H

View File

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

View File

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

View File

@@ -0,0 +1,261 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Mark Borgerding mark a borgerding net
//
// 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/.
namespace Eigen {
namespace internal {
// FFTW uses non-const arguments
// so we must use ugly const_cast calls for all the args it uses
//
// This should be safe as long as
// 1. we use FFTW_ESTIMATE for all our planning
// see the FFTW docs section 4.3.2 "Planner Flags"
// 2. fftw_complex is compatible with std::complex
// This assumes std::complex<T> layout is array of size 2 with real,imag
template <typename T>
inline
T * fftw_cast(const T* p)
{
return const_cast<T*>( p);
}
inline
fftw_complex * fftw_cast( const std::complex<double> * p)
{
return const_cast<fftw_complex*>( reinterpret_cast<const fftw_complex*>(p) );
}
inline
fftwf_complex * fftw_cast( const std::complex<float> * p)
{
return const_cast<fftwf_complex*>( reinterpret_cast<const fftwf_complex*>(p) );
}
inline
fftwl_complex * fftw_cast( const std::complex<long double> * p)
{
return const_cast<fftwl_complex*>( reinterpret_cast<const fftwl_complex*>(p) );
}
template <typename T>
struct fftw_plan {};
template <>
struct fftw_plan<float>
{
typedef float scalar_type;
typedef fftwf_complex complex_type;
fftwf_plan m_plan;
fftw_plan() :m_plan(NULL) {}
~fftw_plan() {if (m_plan) fftwf_destroy_plan(m_plan);}
inline
void fwd(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft( m_plan, src,dst);
}
inline
void inv(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft( m_plan, src,dst);
}
inline
void fwd(complex_type * dst,scalar_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwf_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft_r2c( m_plan,src,dst);
}
inline
void inv(scalar_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL)
m_plan = fftwf_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft_c2r( m_plan, src,dst);
}
inline
void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft( m_plan, src,dst);
}
inline
void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwf_execute_dft( m_plan, src,dst);
}
};
template <>
struct fftw_plan<double>
{
typedef double scalar_type;
typedef fftw_complex complex_type;
::fftw_plan m_plan;
fftw_plan() :m_plan(NULL) {}
~fftw_plan() {if (m_plan) fftw_destroy_plan(m_plan);}
inline
void fwd(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft( m_plan, src,dst);
}
inline
void inv(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft( m_plan, src,dst);
}
inline
void fwd(complex_type * dst,scalar_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftw_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft_r2c( m_plan,src,dst);
}
inline
void inv(scalar_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL)
m_plan = fftw_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft_c2r( m_plan, src,dst);
}
inline
void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft( m_plan, src,dst);
}
inline
void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftw_execute_dft( m_plan, src,dst);
}
};
template <>
struct fftw_plan<long double>
{
typedef long double scalar_type;
typedef fftwl_complex complex_type;
fftwl_plan m_plan;
fftw_plan() :m_plan(NULL) {}
~fftw_plan() {if (m_plan) fftwl_destroy_plan(m_plan);}
inline
void fwd(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft( m_plan, src,dst);
}
inline
void inv(complex_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft( m_plan, src,dst);
}
inline
void fwd(complex_type * dst,scalar_type * src,int nfft) {
if (m_plan==NULL) m_plan = fftwl_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft_r2c( m_plan,src,dst);
}
inline
void inv(scalar_type * dst,complex_type * src,int nfft) {
if (m_plan==NULL)
m_plan = fftwl_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft_c2r( m_plan, src,dst);
}
inline
void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft( m_plan, src,dst);
}
inline
void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
fftwl_execute_dft( m_plan, src,dst);
}
};
template <typename _Scalar>
struct fftw_impl
{
typedef _Scalar Scalar;
typedef std::complex<Scalar> Complex;
inline
void clear()
{
m_plans.clear();
}
// complex-to-complex forward FFT
inline
void fwd( Complex * dst,const Complex *src,int nfft)
{
get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src),nfft );
}
// real-to-complex forward FFT
inline
void fwd( Complex * dst,const Scalar * src,int nfft)
{
get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src) ,nfft);
}
// 2-d complex-to-complex
inline
void fwd2(Complex * dst, const Complex * src, int n0,int n1)
{
get_plan(n0,n1,false,dst,src).fwd2(fftw_cast(dst), fftw_cast(src) ,n0,n1);
}
// inverse complex-to-complex
inline
void inv(Complex * dst,const Complex *src,int nfft)
{
get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft );
}
// half-complex to scalar
inline
void inv( Scalar * dst,const Complex * src,int nfft)
{
get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft );
}
// 2-d complex-to-complex
inline
void inv2(Complex * dst, const Complex * src, int n0,int n1)
{
get_plan(n0,n1,true,dst,src).inv2(fftw_cast(dst), fftw_cast(src) ,n0,n1);
}
protected:
typedef fftw_plan<Scalar> PlanData;
typedef std::map<int64_t,PlanData> PlanMap;
PlanMap m_plans;
inline
PlanData & get_plan(int nfft,bool inverse,void * dst,const void * src)
{
bool inplace = (dst==src);
bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0;
int64_t key = ( (nfft<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1;
return m_plans[key];
}
inline
PlanData & get_plan(int n0,int n1,bool inverse,void * dst,const void * src)
{
bool inplace = (dst==src);
bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0;
int64_t key = ( ( (((int64_t)n0) << 30)|(n1<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1 ) + 1;
return m_plans[key];
}
};
} // end namespace internal
} // end namespace Eigen
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

View File

@@ -0,0 +1,420 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Mark Borgerding mark a borgerding net
//
// 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/.
namespace Eigen {
namespace internal {
// This FFT implementation was derived from kissfft http:sourceforge.net/projects/kissfft
// Copyright 2003-2009 Mark Borgerding
template <typename _Scalar>
struct kiss_cpx_fft
{
typedef _Scalar Scalar;
typedef std::complex<Scalar> Complex;
std::vector<Complex> m_twiddles;
std::vector<int> m_stageRadix;
std::vector<int> m_stageRemainder;
std::vector<Complex> m_scratchBuf;
bool m_inverse;
inline
void make_twiddles(int nfft,bool inverse)
{
using std::acos;
m_inverse = inverse;
m_twiddles.resize(nfft);
Scalar phinc = (inverse?2:-2)* acos( (Scalar) -1) / nfft;
for (int i=0;i<nfft;++i)
m_twiddles[i] = exp( Complex(0,i*phinc) );
}
void factorize(int nfft)
{
//start factoring out 4's, then 2's, then 3,5,7,9,...
int n= nfft;
int p=4;
do {
while (n % p) {
switch (p) {
case 4: p = 2; break;
case 2: p = 3; break;
default: p += 2; break;
}
if (p*p>n)
p=n;// impossible to have a factor > sqrt(n)
}
n /= p;
m_stageRadix.push_back(p);
m_stageRemainder.push_back(n);
if ( p > 5 )
m_scratchBuf.resize(p); // scratchbuf will be needed in bfly_generic
}while(n>1);
}
template <typename _Src>
inline
void work( int stage,Complex * xout, const _Src * xin, size_t fstride,size_t in_stride)
{
int p = m_stageRadix[stage];
int m = m_stageRemainder[stage];
Complex * Fout_beg = xout;
Complex * Fout_end = xout + p*m;
if (m>1) {
do{
// recursive call:
// DFT of size m*p performed by doing
// p instances of smaller DFTs of size m,
// each one takes a decimated version of the input
work(stage+1, xout , xin, fstride*p,in_stride);
xin += fstride*in_stride;
}while( (xout += m) != Fout_end );
}else{
do{
*xout = *xin;
xin += fstride*in_stride;
}while(++xout != Fout_end );
}
xout=Fout_beg;
// recombine the p smaller DFTs
switch (p) {
case 2: bfly2(xout,fstride,m); break;
case 3: bfly3(xout,fstride,m); break;
case 4: bfly4(xout,fstride,m); break;
case 5: bfly5(xout,fstride,m); break;
default: bfly_generic(xout,fstride,m,p); break;
}
}
inline
void bfly2( Complex * Fout, const size_t fstride, int m)
{
for (int k=0;k<m;++k) {
Complex t = Fout[m+k] * m_twiddles[k*fstride];
Fout[m+k] = Fout[k] - t;
Fout[k] += t;
}
}
inline
void bfly4( Complex * Fout, const size_t fstride, const size_t m)
{
Complex scratch[6];
int negative_if_inverse = m_inverse * -2 +1;
for (size_t k=0;k<m;++k) {
scratch[0] = Fout[k+m] * m_twiddles[k*fstride];
scratch[1] = Fout[k+2*m] * m_twiddles[k*fstride*2];
scratch[2] = Fout[k+3*m] * m_twiddles[k*fstride*3];
scratch[5] = Fout[k] - scratch[1];
Fout[k] += scratch[1];
scratch[3] = scratch[0] + scratch[2];
scratch[4] = scratch[0] - scratch[2];
scratch[4] = Complex( scratch[4].imag()*negative_if_inverse , -scratch[4].real()* negative_if_inverse );
Fout[k+2*m] = Fout[k] - scratch[3];
Fout[k] += scratch[3];
Fout[k+m] = scratch[5] + scratch[4];
Fout[k+3*m] = scratch[5] - scratch[4];
}
}
inline
void bfly3( Complex * Fout, const size_t fstride, const size_t m)
{
size_t k=m;
const size_t m2 = 2*m;
Complex *tw1,*tw2;
Complex scratch[5];
Complex epi3;
epi3 = m_twiddles[fstride*m];
tw1=tw2=&m_twiddles[0];
do{
scratch[1]=Fout[m] * *tw1;
scratch[2]=Fout[m2] * *tw2;
scratch[3]=scratch[1]+scratch[2];
scratch[0]=scratch[1]-scratch[2];
tw1 += fstride;
tw2 += fstride*2;
Fout[m] = Complex( Fout->real() - Scalar(.5)*scratch[3].real() , Fout->imag() - Scalar(.5)*scratch[3].imag() );
scratch[0] *= epi3.imag();
*Fout += scratch[3];
Fout[m2] = Complex( Fout[m].real() + scratch[0].imag() , Fout[m].imag() - scratch[0].real() );
Fout[m] += Complex( -scratch[0].imag(),scratch[0].real() );
++Fout;
}while(--k);
}
inline
void bfly5( Complex * Fout, const size_t fstride, const size_t m)
{
Complex *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
size_t u;
Complex scratch[13];
Complex * twiddles = &m_twiddles[0];
Complex *tw;
Complex ya,yb;
ya = twiddles[fstride*m];
yb = twiddles[fstride*2*m];
Fout0=Fout;
Fout1=Fout0+m;
Fout2=Fout0+2*m;
Fout3=Fout0+3*m;
Fout4=Fout0+4*m;
tw=twiddles;
for ( u=0; u<m; ++u ) {
scratch[0] = *Fout0;
scratch[1] = *Fout1 * tw[u*fstride];
scratch[2] = *Fout2 * tw[2*u*fstride];
scratch[3] = *Fout3 * tw[3*u*fstride];
scratch[4] = *Fout4 * tw[4*u*fstride];
scratch[7] = scratch[1] + scratch[4];
scratch[10] = scratch[1] - scratch[4];
scratch[8] = scratch[2] + scratch[3];
scratch[9] = scratch[2] - scratch[3];
*Fout0 += scratch[7];
*Fout0 += scratch[8];
scratch[5] = scratch[0] + Complex(
(scratch[7].real()*ya.real() ) + (scratch[8].real() *yb.real() ),
(scratch[7].imag()*ya.real()) + (scratch[8].imag()*yb.real())
);
scratch[6] = Complex(
(scratch[10].imag()*ya.imag()) + (scratch[9].imag()*yb.imag()),
-(scratch[10].real()*ya.imag()) - (scratch[9].real()*yb.imag())
);
*Fout1 = scratch[5] - scratch[6];
*Fout4 = scratch[5] + scratch[6];
scratch[11] = scratch[0] +
Complex(
(scratch[7].real()*yb.real()) + (scratch[8].real()*ya.real()),
(scratch[7].imag()*yb.real()) + (scratch[8].imag()*ya.real())
);
scratch[12] = Complex(
-(scratch[10].imag()*yb.imag()) + (scratch[9].imag()*ya.imag()),
(scratch[10].real()*yb.imag()) - (scratch[9].real()*ya.imag())
);
*Fout2=scratch[11]+scratch[12];
*Fout3=scratch[11]-scratch[12];
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
}
}
/* perform the butterfly for one stage of a mixed radix FFT */
inline
void bfly_generic(
Complex * Fout,
const size_t fstride,
int m,
int p
)
{
int u,k,q1,q;
Complex * twiddles = &m_twiddles[0];
Complex t;
int Norig = static_cast<int>(m_twiddles.size());
Complex * scratchbuf = &m_scratchBuf[0];
for ( u=0; u<m; ++u ) {
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
scratchbuf[q1] = Fout[ k ];
k += m;
}
k=u;
for ( q1=0 ; q1<p ; ++q1 ) {
int twidx=0;
Fout[ k ] = scratchbuf[0];
for (q=1;q<p;++q ) {
twidx += static_cast<int>(fstride) * k;
if (twidx>=Norig) twidx-=Norig;
t=scratchbuf[q] * twiddles[twidx];
Fout[ k ] += t;
}
k += m;
}
}
}
};
template <typename _Scalar>
struct kissfft_impl
{
typedef _Scalar Scalar;
typedef std::complex<Scalar> Complex;
void clear()
{
m_plans.clear();
m_realTwiddles.clear();
}
inline
void fwd( Complex * dst,const Complex *src,int nfft)
{
get_plan(nfft,false).work(0, dst, src, 1,1);
}
inline
void fwd2( Complex * dst,const Complex *src,int n0,int n1)
{
EIGEN_UNUSED_VARIABLE(dst);
EIGEN_UNUSED_VARIABLE(src);
EIGEN_UNUSED_VARIABLE(n0);
EIGEN_UNUSED_VARIABLE(n1);
}
inline
void inv2( Complex * dst,const Complex *src,int n0,int n1)
{
EIGEN_UNUSED_VARIABLE(dst);
EIGEN_UNUSED_VARIABLE(src);
EIGEN_UNUSED_VARIABLE(n0);
EIGEN_UNUSED_VARIABLE(n1);
}
// real-to-complex forward FFT
// perform two FFTs of src even and src odd
// then twiddle to recombine them into the half-spectrum format
// then fill in the conjugate symmetric half
inline
void fwd( Complex * dst,const Scalar * src,int nfft)
{
if ( nfft&3 ) {
// use generic mode for odd
m_tmpBuf1.resize(nfft);
get_plan(nfft,false).work(0, &m_tmpBuf1[0], src, 1,1);
std::copy(m_tmpBuf1.begin(),m_tmpBuf1.begin()+(nfft>>1)+1,dst );
}else{
int ncfft = nfft>>1;
int ncfft2 = nfft>>2;
Complex * rtw = real_twiddles(ncfft2);
// use optimized mode for even real
fwd( dst, reinterpret_cast<const Complex*> (src), ncfft);
Complex dc = dst[0].real() + dst[0].imag();
Complex nyquist = dst[0].real() - dst[0].imag();
int k;
for ( k=1;k <= ncfft2 ; ++k ) {
Complex fpk = dst[k];
Complex fpnk = conj(dst[ncfft-k]);
Complex f1k = fpk + fpnk;
Complex f2k = fpk - fpnk;
Complex tw= f2k * rtw[k-1];
dst[k] = (f1k + tw) * Scalar(.5);
dst[ncfft-k] = conj(f1k -tw)*Scalar(.5);
}
dst[0] = dc;
dst[ncfft] = nyquist;
}
}
// inverse complex-to-complex
inline
void inv(Complex * dst,const Complex *src,int nfft)
{
get_plan(nfft,true).work(0, dst, src, 1,1);
}
// half-complex to scalar
inline
void inv( Scalar * dst,const Complex * src,int nfft)
{
if (nfft&3) {
m_tmpBuf1.resize(nfft);
m_tmpBuf2.resize(nfft);
std::copy(src,src+(nfft>>1)+1,m_tmpBuf1.begin() );
for (int k=1;k<(nfft>>1)+1;++k)
m_tmpBuf1[nfft-k] = conj(m_tmpBuf1[k]);
inv(&m_tmpBuf2[0],&m_tmpBuf1[0],nfft);
for (int k=0;k<nfft;++k)
dst[k] = m_tmpBuf2[k].real();
}else{
// optimized version for multiple of 4
int ncfft = nfft>>1;
int ncfft2 = nfft>>2;
Complex * rtw = real_twiddles(ncfft2);
m_tmpBuf1.resize(ncfft);
m_tmpBuf1[0] = Complex( src[0].real() + src[ncfft].real(), src[0].real() - src[ncfft].real() );
for (int k = 1; k <= ncfft / 2; ++k) {
Complex fk = src[k];
Complex fnkc = conj(src[ncfft-k]);
Complex fek = fk + fnkc;
Complex tmp = fk - fnkc;
Complex fok = tmp * conj(rtw[k-1]);
m_tmpBuf1[k] = fek + fok;
m_tmpBuf1[ncfft-k] = conj(fek - fok);
}
get_plan(ncfft,true).work(0, reinterpret_cast<Complex*>(dst), &m_tmpBuf1[0], 1,1);
}
}
protected:
typedef kiss_cpx_fft<Scalar> PlanData;
typedef std::map<int,PlanData> PlanMap;
PlanMap m_plans;
std::map<int, std::vector<Complex> > m_realTwiddles;
std::vector<Complex> m_tmpBuf1;
std::vector<Complex> m_tmpBuf2;
inline
int PlanKey(int nfft, bool isinverse) const { return (nfft<<1) | int(isinverse); }
inline
PlanData & get_plan(int nfft, bool inverse)
{
// TODO look for PlanKey(nfft, ! inverse) and conjugate the twiddles
PlanData & pd = m_plans[ PlanKey(nfft,inverse) ];
if ( pd.m_twiddles.size() == 0 ) {
pd.make_twiddles(nfft,inverse);
pd.factorize(nfft);
}
return pd;
}
inline
Complex * real_twiddles(int ncfft2)
{
using std::acos;
std::vector<Complex> & twidref = m_realTwiddles[ncfft2];// creates new if not there
if ( (int)twidref.size() != ncfft2 ) {
twidref.resize(ncfft2);
int ncfft= ncfft2<<1;
Scalar pi = acos( Scalar(-1) );
for (int k=1;k<=ncfft2;++k)
twidref[k-1] = exp( Complex(0,-pi * (Scalar(k) / ncfft + Scalar(.5)) ) );
}
return &twidref[0];
}
};
} // end namespace internal
} // end namespace Eigen
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

View File

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

View File

@@ -0,0 +1,189 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
/* NOTE The functions of this file have been adapted from the GMM++ library */
//========================================================================
//
// Copyright (C) 2002-2007 Yves Renard
//
// This file is a part of GETFEM++
//
// Getfem++ is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
// USA.
//
//========================================================================
#include "../../../../Eigen/src/Core/util/NonMPL2.h"
#ifndef EIGEN_CONSTRAINEDCG_H
#define EIGEN_CONSTRAINEDCG_H
#include <Eigen/Core>
namespace Eigen {
namespace internal {
/** \ingroup IterativeSolvers_Module
* Compute the pseudo inverse of the non-square matrix C such that
* \f$ CINV = (C * C^T)^{-1} * C \f$ based on a conjugate gradient method.
*
* This function is internally used by constrained_cg.
*/
template <typename CMatrix, typename CINVMatrix>
void pseudo_inverse(const CMatrix &C, CINVMatrix &CINV)
{
// optimisable : copie de la ligne, precalcul de C * trans(C).
typedef typename CMatrix::Scalar Scalar;
typedef typename CMatrix::Index Index;
// FIXME use sparse vectors ?
typedef Matrix<Scalar,Dynamic,1> TmpVec;
Index rows = C.rows(), cols = C.cols();
TmpVec d(rows), e(rows), l(cols), p(rows), q(rows), r(rows);
Scalar rho, rho_1, alpha;
d.setZero();
typedef Triplet<double> T;
std::vector<T> tripletList;
for (Index i = 0; i < rows; ++i)
{
d[i] = 1.0;
rho = 1.0;
e.setZero();
r = d;
p = d;
while (rho >= 1e-38)
{ /* conjugate gradient to compute e */
/* which is the i-th row of inv(C * trans(C)) */
l = C.transpose() * p;
q = C * l;
alpha = rho / p.dot(q);
e += alpha * p;
r += -alpha * q;
rho_1 = rho;
rho = r.dot(r);
p = (rho/rho_1) * p + r;
}
l = C.transpose() * e; // l is the i-th row of CINV
// FIXME add a generic "prune/filter" expression for both dense and sparse object to sparse
for (Index j=0; j<l.size(); ++j)
if (l[j]<1e-15)
tripletList.push_back(T(i,j,l(j)));
d[i] = 0.0;
}
CINV.setFromTriplets(tripletList.begin(), tripletList.end());
}
/** \ingroup IterativeSolvers_Module
* Constrained conjugate gradient
*
* Computes the minimum of \f$ 1/2((Ax).x) - bx \f$ under the contraint \f$ Cx \le f \f$
*/
template<typename TMatrix, typename CMatrix,
typename VectorX, typename VectorB, typename VectorF>
void constrained_cg(const TMatrix& A, const CMatrix& C, VectorX& x,
const VectorB& b, const VectorF& f, IterationController &iter)
{
using std::sqrt;
typedef typename TMatrix::Scalar Scalar;
typedef typename TMatrix::Index Index;
typedef Matrix<Scalar,Dynamic,1> TmpVec;
Scalar rho = 1.0, rho_1, lambda, gamma;
Index xSize = x.size();
TmpVec p(xSize), q(xSize), q2(xSize),
r(xSize), old_z(xSize), z(xSize),
memox(xSize);
std::vector<bool> satured(C.rows());
p.setZero();
iter.setRhsNorm(sqrt(b.dot(b))); // gael vect_sp(PS, b, b)
if (iter.rhsNorm() == 0.0) iter.setRhsNorm(1.0);
SparseMatrix<Scalar,RowMajor> CINV(C.rows(), C.cols());
pseudo_inverse(C, CINV);
while(true)
{
// computation of residual
old_z = z;
memox = x;
r = b;
r += A * -x;
z = r;
bool transition = false;
for (Index i = 0; i < C.rows(); ++i)
{
Scalar al = C.row(i).dot(x) - f.coeff(i);
if (al >= -1.0E-15)
{
if (!satured[i])
{
satured[i] = true;
transition = true;
}
Scalar bb = CINV.row(i).dot(z);
if (bb > 0.0)
// FIXME: we should allow that: z += -bb * C.row(i);
for (typename CMatrix::InnerIterator it(C,i); it; ++it)
z.coeffRef(it.index()) -= bb*it.value();
}
else
satured[i] = false;
}
// descent direction
rho_1 = rho;
rho = r.dot(z);
if (iter.finished(rho)) break;
if (iter.noiseLevel() > 0 && transition) std::cerr << "CCG: transition\n";
if (transition || iter.first()) gamma = 0.0;
else gamma = (std::max)(0.0, (rho - old_z.dot(z)) / rho_1);
p = z + gamma*p;
++iter;
// one dimensionnal optimization
q = A * p;
lambda = rho / q.dot(p);
for (Index i = 0; i < C.rows(); ++i)
{
if (!satured[i])
{
Scalar bb = C.row(i).dot(p) - f[i];
if (bb > 0.0)
lambda = (std::min)(lambda, (f.coeff(i)-C.row(i).dot(x)) / bb);
}
}
x += lambda * p;
memox -= x;
}
}
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_CONSTRAINEDCG_H

View File

@@ -0,0 +1,542 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// 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_DGMRES_H
#define EIGEN_DGMRES_H
#include <Eigen/Eigenvalues>
namespace Eigen {
template< typename _MatrixType,
typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> >
class DGMRES;
namespace internal {
template< typename _MatrixType, typename _Preconditioner>
struct traits<DGMRES<_MatrixType,_Preconditioner> >
{
typedef _MatrixType MatrixType;
typedef _Preconditioner Preconditioner;
};
/** \brief Computes a permutation vector to have a sorted sequence
* \param vec The vector to reorder.
* \param perm gives the sorted sequence on output. Must be initialized with 0..n-1
* \param ncut Put the ncut smallest elements at the end of the vector
* WARNING This is an expensive sort, so should be used only
* for small size vectors
* TODO Use modified QuickSplit or std::nth_element to get the smallest values
*/
template <typename VectorType, typename IndexType>
void sortWithPermutation (VectorType& vec, IndexType& perm, typename IndexType::Scalar& ncut)
{
eigen_assert(vec.size() == perm.size());
typedef typename IndexType::Scalar Index;
typedef typename VectorType::Scalar Scalar;
bool flag;
for (Index k = 0; k < ncut; k++)
{
flag = false;
for (Index j = 0; j < vec.size()-1; j++)
{
if ( vec(perm(j)) < vec(perm(j+1)) )
{
std::swap(perm(j),perm(j+1));
flag = true;
}
if (!flag) break; // The vector is in sorted order
}
}
}
}
/**
* \ingroup IterativeLInearSolvers_Module
* \brief A Restarted GMRES with deflation.
* This class implements a modification of the GMRES solver for
* sparse linear systems. The basis is built with modified
* Gram-Schmidt. At each restart, a few approximated eigenvectors
* corresponding to the smallest eigenvalues are used to build a
* preconditioner for the next cycle. This preconditioner
* for deflation can be combined with any other preconditioner,
* the IncompleteLUT for instance. The preconditioner is applied
* at right of the matrix and the combination is multiplicative.
*
* \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix.
* \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner
* Typical usage :
* \code
* SparseMatrix<double> A;
* VectorXd x, b;
* //Fill A and b ...
* DGMRES<SparseMatrix<double> > solver;
* solver.set_restart(30); // Set restarting value
* solver.setEigenv(1); // Set the number of eigenvalues to deflate
* solver.compute(A);
* x = solver.solve(b);
* \endcode
*
* References :
* [1] D. NUENTSA WAKAM and F. PACULL, Memory Efficient Hybrid
* Algebraic Solvers for Linear Systems Arising from Compressible
* Flows, Computers and Fluids, In Press,
* http://dx.doi.org/10.1016/j.compfluid.2012.03.023
* [2] K. Burrage and J. Erhel, On the performance of various
* adaptive preconditioned GMRES strategies, 5(1998), 101-121.
* [3] J. Erhel, K. Burrage and B. Pohl, Restarted GMRES
* preconditioned by deflation,J. Computational and Applied
* Mathematics, 69(1996), 303-318.
*
*/
template< typename _MatrixType, typename _Preconditioner>
class DGMRES : public IterativeSolverBase<DGMRES<_MatrixType,_Preconditioner> >
{
typedef IterativeSolverBase<DGMRES> Base;
using Base::mp_matrix;
using Base::m_error;
using Base::m_iterations;
using Base::m_info;
using Base::m_isInitialized;
using Base::m_tolerance;
public:
typedef _MatrixType MatrixType;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::Index Index;
typedef typename MatrixType::RealScalar RealScalar;
typedef _Preconditioner Preconditioner;
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<RealScalar,Dynamic,Dynamic> DenseRealMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
typedef Matrix<RealScalar,Dynamic,1> DenseRealVector;
typedef Matrix<std::complex<RealScalar>, Dynamic, 1> ComplexVector;
/** Default constructor. */
DGMRES() : Base(),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {}
/** Initialize the solver with matrix \a A for further \c Ax=b solving.
*
* This constructor is a shortcut for the default constructor followed
* by a call to compute().
*
* \warning this class stores a reference to the matrix A as well as some
* precomputed values that depend on it. Therefore, if \a A is changed
* this class becomes invalid. Call compute() to update it with the new
* matrix A, or modify a copy of A.
*/
template<typename MatrixDerived>
explicit DGMRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()), m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {}
~DGMRES() {}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
* \a x0 as an initial solution.
*
* \sa compute()
*/
template<typename Rhs,typename Guess>
inline const internal::solve_retval_with_guess<DGMRES, Rhs, Guess>
solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const
{
eigen_assert(m_isInitialized && "DGMRES is not initialized.");
eigen_assert(Base::rows()==b.rows()
&& "DGMRES::solve(): invalid number of rows of the right hand side matrix b");
return internal::solve_retval_with_guess
<DGMRES, Rhs, Guess>(*this, b.derived(), x0);
}
/** \internal */
template<typename Rhs,typename Dest>
void _solveWithGuess(const Rhs& b, Dest& x) const
{
bool failed = false;
for(int j=0; j<b.cols(); ++j)
{
m_iterations = Base::maxIterations();
m_error = Base::m_tolerance;
typename Dest::ColXpr xj(x,j);
dgmres(*mp_matrix, b.col(j), xj, Base::m_preconditioner);
}
m_info = failed ? NumericalIssue
: m_error <= Base::m_tolerance ? Success
: NoConvergence;
m_isInitialized = true;
}
/** \internal */
template<typename Rhs,typename Dest>
void _solve(const Rhs& b, Dest& x) const
{
x = b;
_solveWithGuess(b,x);
}
/**
* Get the restart value
*/
int restart() { return m_restart; }
/**
* Set the restart value (default is 30)
*/
void set_restart(const int restart) { m_restart=restart; }
/**
* Set the number of eigenvalues to deflate at each restart
*/
void setEigenv(const int neig)
{
m_neig = neig;
if (neig+1 > m_maxNeig) m_maxNeig = neig+1; // To allow for complex conjugates
}
/**
* Get the size of the deflation subspace size
*/
int deflSize() {return m_r; }
/**
* Set the maximum size of the deflation subspace
*/
void setMaxEigenv(const int maxNeig) { m_maxNeig = maxNeig; }
protected:
// DGMRES algorithm
template<typename Rhs, typename Dest>
void dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, const Preconditioner& precond) const;
// Perform one cycle of GMRES
template<typename Dest>
int dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const;
// Compute data to use for deflation
int dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const;
// Apply deflation to a vector
template<typename RhsType, typename DestType>
int dgmresApplyDeflation(const RhsType& In, DestType& Out) const;
ComplexVector schurValues(const ComplexSchur<DenseMatrix>& schurofH) const;
ComplexVector schurValues(const RealSchur<DenseMatrix>& schurofH) const;
// Init data for deflation
void dgmresInitDeflation(Index& rows) const;
mutable DenseMatrix m_V; // Krylov basis vectors
mutable DenseMatrix m_H; // Hessenberg matrix
mutable DenseMatrix m_Hes; // Initial hessenberg matrix wihout Givens rotations applied
mutable Index m_restart; // Maximum size of the Krylov subspace
mutable DenseMatrix m_U; // Vectors that form the basis of the invariant subspace
mutable DenseMatrix m_MU; // matrix operator applied to m_U (for next cycles)
mutable DenseMatrix m_T; /* T=U^T*M^{-1}*A*U */
mutable PartialPivLU<DenseMatrix> m_luT; // LU factorization of m_T
mutable int m_neig; //Number of eigenvalues to extract at each restart
mutable int m_r; // Current number of deflated eigenvalues, size of m_U
mutable int m_maxNeig; // Maximum number of eigenvalues to deflate
mutable RealScalar m_lambdaN; //Modulus of the largest eigenvalue of A
mutable bool m_isDeflAllocated;
mutable bool m_isDeflInitialized;
//Adaptive strategy
mutable RealScalar m_smv; // Smaller multiple of the remaining number of steps allowed
mutable bool m_force; // Force the use of deflation at each restart
};
/**
* \brief Perform several cycles of restarted GMRES with modified Gram Schmidt,
*
* A right preconditioner is used combined with deflation.
*
*/
template< typename _MatrixType, typename _Preconditioner>
template<typename Rhs, typename Dest>
void DGMRES<_MatrixType, _Preconditioner>::dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x,
const Preconditioner& precond) const
{
//Initialization
int n = mat.rows();
DenseVector r0(n);
int nbIts = 0;
m_H.resize(m_restart+1, m_restart);
m_Hes.resize(m_restart, m_restart);
m_V.resize(n,m_restart+1);
//Initial residual vector and intial norm
x = precond.solve(x);
r0 = rhs - mat * x;
RealScalar beta = r0.norm();
RealScalar normRhs = rhs.norm();
m_error = beta/normRhs;
if(m_error < m_tolerance)
m_info = Success;
else
m_info = NoConvergence;
// Iterative process
while (nbIts < m_iterations && m_info == NoConvergence)
{
dgmresCycle(mat, precond, x, r0, beta, normRhs, nbIts);
// Compute the new residual vector for the restart
if (nbIts < m_iterations && m_info == NoConvergence)
r0 = rhs - mat * x;
}
}
/**
* \brief Perform one restart cycle of DGMRES
* \param mat The coefficient matrix
* \param precond The preconditioner
* \param x the new approximated solution
* \param r0 The initial residual vector
* \param beta The norm of the residual computed so far
* \param normRhs The norm of the right hand side vector
* \param nbIts The number of iterations
*/
template< typename _MatrixType, typename _Preconditioner>
template<typename Dest>
int DGMRES<_MatrixType, _Preconditioner>::dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const
{
//Initialization
DenseVector g(m_restart+1); // Right hand side of the least square problem
g.setZero();
g(0) = Scalar(beta);
m_V.col(0) = r0/beta;
m_info = NoConvergence;
std::vector<JacobiRotation<Scalar> >gr(m_restart); // Givens rotations
int it = 0; // Number of inner iterations
int n = mat.rows();
DenseVector tv1(n), tv2(n); //Temporary vectors
while (m_info == NoConvergence && it < m_restart && nbIts < m_iterations)
{
// Apply preconditioner(s) at right
if (m_isDeflInitialized )
{
dgmresApplyDeflation(m_V.col(it), tv1); // Deflation
tv2 = precond.solve(tv1);
}
else
{
tv2 = precond.solve(m_V.col(it)); // User's selected preconditioner
}
tv1 = mat * tv2;
// Orthogonalize it with the previous basis in the basis using modified Gram-Schmidt
Scalar coef;
for (int i = 0; i <= it; ++i)
{
coef = tv1.dot(m_V.col(i));
tv1 = tv1 - coef * m_V.col(i);
m_H(i,it) = coef;
m_Hes(i,it) = coef;
}
// Normalize the vector
coef = tv1.norm();
m_V.col(it+1) = tv1/coef;
m_H(it+1, it) = coef;
// m_Hes(it+1,it) = coef;
// FIXME Check for happy breakdown
// Update Hessenberg matrix with Givens rotations
for (int i = 1; i <= it; ++i)
{
m_H.col(it).applyOnTheLeft(i-1,i,gr[i-1].adjoint());
}
// Compute the new plane rotation
gr[it].makeGivens(m_H(it, it), m_H(it+1,it));
// Apply the new rotation
m_H.col(it).applyOnTheLeft(it,it+1,gr[it].adjoint());
g.applyOnTheLeft(it,it+1, gr[it].adjoint());
beta = std::abs(g(it+1));
m_error = beta/normRhs;
std::cerr << nbIts << " Relative Residual Norm " << m_error << std::endl;
it++; nbIts++;
if (m_error < m_tolerance)
{
// The method has converged
m_info = Success;
break;
}
}
// Compute the new coefficients by solving the least square problem
// it++;
//FIXME Check first if the matrix is singular ... zero diagonal
DenseVector nrs(m_restart);
nrs = m_H.topLeftCorner(it,it).template triangularView<Upper>().solve(g.head(it));
// Form the new solution
if (m_isDeflInitialized)
{
tv1 = m_V.leftCols(it) * nrs;
dgmresApplyDeflation(tv1, tv2);
x = x + precond.solve(tv2);
}
else
x = x + precond.solve(m_V.leftCols(it) * nrs);
// Go for a new cycle and compute data for deflation
if(nbIts < m_iterations && m_info == NoConvergence && m_neig > 0 && (m_r+m_neig) < m_maxNeig)
dgmresComputeDeflationData(mat, precond, it, m_neig);
return 0;
}
template< typename _MatrixType, typename _Preconditioner>
void DGMRES<_MatrixType, _Preconditioner>::dgmresInitDeflation(Index& rows) const
{
m_U.resize(rows, m_maxNeig);
m_MU.resize(rows, m_maxNeig);
m_T.resize(m_maxNeig, m_maxNeig);
m_lambdaN = 0.0;
m_isDeflAllocated = true;
}
template< typename _MatrixType, typename _Preconditioner>
inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const ComplexSchur<DenseMatrix>& schurofH) const
{
return schurofH.matrixT().diagonal();
}
template< typename _MatrixType, typename _Preconditioner>
inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const RealSchur<DenseMatrix>& schurofH) const
{
typedef typename MatrixType::Index Index;
const DenseMatrix& T = schurofH.matrixT();
Index it = T.rows();
ComplexVector eig(it);
Index j = 0;
while (j < it-1)
{
if (T(j+1,j) ==Scalar(0))
{
eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0));
j++;
}
else
{
eig(j) = std::complex<RealScalar>(T(j,j),T(j+1,j));
eig(j+1) = std::complex<RealScalar>(T(j,j+1),T(j+1,j+1));
j++;
}
}
if (j < it-1) eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0));
return eig;
}
template< typename _MatrixType, typename _Preconditioner>
int DGMRES<_MatrixType, _Preconditioner>::dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const
{
// First, find the Schur form of the Hessenberg matrix H
typename internal::conditional<NumTraits<Scalar>::IsComplex, ComplexSchur<DenseMatrix>, RealSchur<DenseMatrix> >::type schurofH;
bool computeU = true;
DenseMatrix matrixQ(it,it);
matrixQ.setIdentity();
schurofH.computeFromHessenberg(m_Hes.topLeftCorner(it,it), matrixQ, computeU);
ComplexVector eig(it);
Matrix<Index,Dynamic,1>perm(it);
eig = this->schurValues(schurofH);
// Reorder the absolute values of Schur values
DenseRealVector modulEig(it);
for (int j=0; j<it; ++j) modulEig(j) = std::abs(eig(j));
perm.setLinSpaced(it,0,it-1);
internal::sortWithPermutation(modulEig, perm, neig);
if (!m_lambdaN)
{
m_lambdaN = (std::max)(modulEig.maxCoeff(), m_lambdaN);
}
//Count the real number of extracted eigenvalues (with complex conjugates)
int nbrEig = 0;
while (nbrEig < neig)
{
if(eig(perm(it-nbrEig-1)).imag() == RealScalar(0)) nbrEig++;
else nbrEig += 2;
}
// Extract the Schur vectors corresponding to the smallest Ritz values
DenseMatrix Sr(it, nbrEig);
Sr.setZero();
for (int j = 0; j < nbrEig; j++)
{
Sr.col(j) = schurofH.matrixU().col(perm(it-j-1));
}
// Form the Schur vectors of the initial matrix using the Krylov basis
DenseMatrix X;
X = m_V.leftCols(it) * Sr;
if (m_r)
{
// Orthogonalize X against m_U using modified Gram-Schmidt
for (int j = 0; j < nbrEig; j++)
for (int k =0; k < m_r; k++)
X.col(j) = X.col(j) - (m_U.col(k).dot(X.col(j)))*m_U.col(k);
}
// Compute m_MX = A * M^-1 * X
Index m = m_V.rows();
if (!m_isDeflAllocated)
dgmresInitDeflation(m);
DenseMatrix MX(m, nbrEig);
DenseVector tv1(m);
for (int j = 0; j < nbrEig; j++)
{
tv1 = mat * X.col(j);
MX.col(j) = precond.solve(tv1);
}
//Update m_T = [U'MU U'MX; X'MU X'MX]
m_T.block(m_r, m_r, nbrEig, nbrEig) = X.transpose() * MX;
if(m_r)
{
m_T.block(0, m_r, m_r, nbrEig) = m_U.leftCols(m_r).transpose() * MX;
m_T.block(m_r, 0, nbrEig, m_r) = X.transpose() * m_MU.leftCols(m_r);
}
// Save X into m_U and m_MX in m_MU
for (int j = 0; j < nbrEig; j++) m_U.col(m_r+j) = X.col(j);
for (int j = 0; j < nbrEig; j++) m_MU.col(m_r+j) = MX.col(j);
// Increase the size of the invariant subspace
m_r += nbrEig;
// Factorize m_T into m_luT
m_luT.compute(m_T.topLeftCorner(m_r, m_r));
//FIXME CHeck if the factorization was correctly done (nonsingular matrix)
m_isDeflInitialized = true;
return 0;
}
template<typename _MatrixType, typename _Preconditioner>
template<typename RhsType, typename DestType>
int DGMRES<_MatrixType, _Preconditioner>::dgmresApplyDeflation(const RhsType &x, DestType &y) const
{
DenseVector x1 = m_U.leftCols(m_r).transpose() * x;
y = x + m_U.leftCols(m_r) * ( m_lambdaN * m_luT.solve(x1) - x1);
return 0;
}
namespace internal {
template<typename _MatrixType, typename _Preconditioner, typename Rhs>
struct solve_retval<DGMRES<_MatrixType, _Preconditioner>, Rhs>
: solve_retval_base<DGMRES<_MatrixType, _Preconditioner>, Rhs>
{
typedef DGMRES<_MatrixType, _Preconditioner> Dec;
EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
template<typename Dest> void evalTo(Dest& dst) const
{
dec()._solve(rhs(),dst);
}
};
} // end namespace internal
} // end namespace Eigen
#endif

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