diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index f378c89d..00000000 --- a/.appveyor.yml +++ /dev/null @@ -1,59 +0,0 @@ -branches: - only: - - devel - -# Build worker image (VM template) -image: Visual Studio 2015 - -# clone directory -clone_folder: c:\projects\vcglib -# Build Configuration, i.e. Debug, Release, etc. -configuration: - - release -# - debug - -environment: - matrix: - # MinGW 32bit - - QTDIR: C:\Qt\5.6\mingw49_32 - SPEC: win32-g++ - COMPILER: mingw32-make - #ARTIFACT: $(APPVEYOR_PROJECT_NAME)-%APPVEYOR_REPO_TAG_NAME%.%APPVEYOR_BUILD_NUMBER%-win32.zip - #ARTIFACT: $(APPVEYOR_PROJECT_NAME)-%APPVEYOR_REPO_TAG_NAME%-win32.zip - # Microsoft Visual Studio 64bit - - QTDIR: C:\Qt\5.6\msvc2015_64 - VSVER: 14.0 - SPEC: win32-msvc2015 - COMPILER: nmake - #ARTIFACT: $(APPVEYOR_PROJECT_NAME)-%APPVEYOR_REPO_TAG_NAME%.%APPVEYOR_BUILD_NUMBER%-win64.zip - #ARTIFACT: $(APPVEYOR_PROJECT_NAME)-%APPVEYOR_REPO_TAG_NAME%-win64.zip - - - -# Set paths, etc. -before_build: - # Set paths - #- '%QTDIR%\bin\qtenv2.bat' - - call "%QTDIR%\bin\qtenv2.bat" - # Show qmake and make version - - qmake -v - - if %COMPILER%==mingw32-make call %COMPILER% -v - # Detect architecture (32bit or 64bit) - - if %QTDIR:_64=%==%QTDIR% (set ARCH=x86) else (set ARCH=x64) - # Set more... if Microsoft Visual Studio - - if %COMPILER%==nmake call "%ProgramFiles(x86)%\Microsoft Visual Studio %VSVER%\VC\vcvarsall.bat" %ARCH% - # Show build folder - #- echo %APPVEYOR_BUILD_FOLDER% - #- echo %CONFIGURATION% - -# To run your custom scripts instead of automatic MSBuild -build_script: - # Go to clone directory - - cd %APPVEYOR_BUILD_FOLDER% - - cd apps - - cd sample - # Run qmake - - qmake sample.pro -r -spec %SPEC% "CONFIG+=%CONFIGURATION%" - # Run compiler - #- '%COMPILER%' - - call %COMPILER% diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e81cb6a9..15f9de14 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,15 @@ -## Thank you for sending a Pull Request to the VCGLib! +## Thank you for sending a Pull Request to the VCGLib! VCGLib is fully owned by CNR, and all the VCGLib contributors that do not work at the VCLab of CNR must first sign the contributor license agreement that you can find at the following link: https://github.com/cnr-isti-vclab/vcglib/blob/devel/docs/ContributorLicenseAgreement.pdf If you will sign the CLA, then we will be able to merge your pull request after reviewing it. +The validity of the CLA is two years, therefore after signing it your PRs for the next two years can be merged without further actions. Please send the signed document to muntoni.alessandro@gmail.com and paolo.cignoni@isti.cnr.it . If you will not sign the CLA, we will review and then apply your changes as soon as possible. -Before opening the PR, please leave the follwing form with a check for your particluar case: +Before opening the PR, please leave the following form with a check for your particular case: ##### Check with `[x]` what is your case: - [ ] I already signed and sent via email the CLA; -- [ ] I wil sign and send the CLA via email as soon as possible; -- [ ] I don't want to sign the CLA. \ No newline at end of file +- [ ] I will sign and send the CLA via email as soon as possible; +- [ ] I don't want to sign the CLA. diff --git a/.github/workflows/BuildExamplesWindows.yml b/.github/workflows/BuildExamplesWindows.yml index f92285cc..193024c0 100644 --- a/.github/workflows/BuildExamplesWindows.yml +++ b/.github/workflows/BuildExamplesWindows.yml @@ -9,12 +9,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Download Jom - run: | - Invoke-WebRequest -Uri "http://mirrors.ukfast.co.uk/sites/qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" - New-Item -Name "jom" -ItemType "directory" - Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "$(Get-Location)\jom" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Setup env variables id: envs run: | @@ -27,5 +21,5 @@ jobs: run: | mkdir build cd build - cmake -G "NMake Makefiles" -DVCG_BUILD_EXAMPLES=ON .. - jom -j4 + cmake -GNinja -DVCG_BUILD_EXAMPLES=ON .. + ninja diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9c7935a6..00000000 --- a/.travis.yml +++ /dev/null @@ -1,49 +0,0 @@ - -# Enable C++ support -language: cpp - -os: - - linux - - osx - - -# Compiler selection -compiler: - - clang - - gcc - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.8 - - g++-4.8 - - clang - -matrix: - exclude: - - os: osx - compiler: gcc - - -install: -# Linux Setup - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget --no-check-certificate http://cmake.org/files/v3.1/cmake-3.1.3-Linux-x86_64.tar.gz ;fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xzf cmake-3.1.3-Linux-x86_64.tar.gz ;fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8" ;fi ;fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export PATH=$PWD/cmake-3.1.3-Linux-x86_64/bin:$PATH ;fi -# OSX Setup - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake ;fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then wget --no-check-certificate http://cmake.org/files/v3.7/cmake-3.7.2-Darwin-x86_64.tar.gz ;fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then tar -xzf cmake-3.7.2-Darwin-x86_64.tar.gz ;fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH=$PWD/cmake-3.1.3-Darwin-x86_64/CMake.app/Contents/bin:$PATH ;fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake ;fi - -# Build steps -script: - - cd apps - - mkdir build - - cd build - - cmake .. - - make diff --git a/CMakeLists.txt b/CMakeLists.txt index fc28d096..e48b6816 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council # SPDX-License-Identifier: BSL-1.0 -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.10) project(VCGLib) # Eigen options @@ -16,11 +16,6 @@ option(VCG_BUILD_EXAMPLES "Build a set of examples of the library" OFF) set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}) set (VCG_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE) -# Prefer GLVND -if(POLICY CMP0072) - cmake_policy(SET CMP0072 NEW) -endif() - ### Build settings set(CMAKE_CXX_STANDARD 11) @@ -35,263 +30,265 @@ elseif(ALLOW_BUNDLED_EIGEN AND EXISTS "${VCG_EIGEN_DIR}/Eigen/Eigen") set(EIGEN_INCLUDE_DIRS ${VCG_EIGEN_DIR}) else() message( - FATAL_ERROR + FATAL_ERROR "Eigen is required - at least one of ALLOW_SYSTEM_EIGEN or ALLOW_BUNDLED_EIGEN must be enabled and found.") endif() ### VCGLib headers and sources set(VCG_HEADERS - vcg/complex/append.h - vcg/complex/all_types.h - vcg/complex/complex.h - vcg/complex/allocate.h - vcg/complex/exception.h - vcg/complex/algorithms/overlap_estimation.h - vcg/complex/algorithms/dual_meshing.h - vcg/complex/algorithms/intersection.h - vcg/complex/algorithms/clip.h - vcg/complex/algorithms/geodesic.h - vcg/complex/algorithms/parametrization/poisson_solver.h - vcg/complex/algorithms/parametrization/uv_utils.h - vcg/complex/algorithms/parametrization/distortion.h - vcg/complex/algorithms/parametrization/tangent_field_operators.h - vcg/complex/algorithms/parametrization/voronoi_atlas.h - vcg/complex/algorithms/edge_collapse.h - vcg/complex/algorithms/hole.h - vcg/complex/algorithms/align_pair.h - vcg/complex/algorithms/closest.h - vcg/complex/algorithms/tetra_implicit_smooth.h - vcg/complex/algorithms/bitquad_support.h - vcg/complex/algorithms/skeleton.h - vcg/complex/algorithms/symmetry.h - vcg/complex/algorithms/voronoi_volume_sampling.h - vcg/complex/algorithms/polygon_polychord_collapse.h - vcg/complex/algorithms/inside.h - vcg/complex/algorithms/local_optimization/tri_edge_flip.h - vcg/complex/algorithms/local_optimization/quad_diag_collapse.h - vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric.h - vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric_tex.h - vcg/complex/algorithms/local_optimization/tri_edge_collapse.h - vcg/complex/algorithms/local_optimization/tetra_edge_collapse.h - vcg/complex/algorithms/polygonal_algorithms.h - vcg/complex/algorithms/inertia.h - vcg/complex/algorithms/mesh_assert.h - vcg/complex/algorithms/cut_tree.h - vcg/complex/algorithms/nring.h - vcg/complex/algorithms/tetra/tetfuse_collapse.h - vcg/complex/algorithms/stat.h - vcg/complex/algorithms/ransac_matching.h - vcg/complex/algorithms/refine.h - vcg/complex/algorithms/outline_support.h - vcg/complex/algorithms/convex_hull.h - vcg/complex/algorithms/clean.h - vcg/complex/algorithms/mesh_to_matrix.h - vcg/complex/algorithms/quadrangulator.h - vcg/complex/algorithms/isotropic_remeshing.h - vcg/complex/algorithms/smooth.h - vcg/complex/algorithms/autoalign_4pcs.h - vcg/complex/algorithms/local_optimization.h - vcg/complex/algorithms/curve_on_manifold.h - vcg/complex/algorithms/clustering.h - vcg/complex/algorithms/refine_loop.h - vcg/complex/algorithms/cylinder_clipping.h - vcg/complex/algorithms/pointcloud_normal.h - vcg/complex/algorithms/bitquad_creation.h - vcg/complex/algorithms/crease_cut.h - vcg/complex/algorithms/implicit_smooth.h - vcg/complex/algorithms/voronoi_remesher.h - vcg/complex/algorithms/polygon_support.h - vcg/complex/algorithms/point_sampling.h - vcg/complex/algorithms/create/mc_lookup_table.h - vcg/complex/algorithms/create/mc_trivial_walker.h - vcg/complex/algorithms/create/extrude.h - vcg/complex/algorithms/create/resampler.h - vcg/complex/algorithms/create/ball_pivoting.h - vcg/complex/algorithms/create/readme.txt - vcg/complex/algorithms/create/zonohedron.h - vcg/complex/algorithms/create/platonic.h - vcg/complex/algorithms/create/marching_cubes.h - vcg/complex/algorithms/create/plymc/voxel.h - vcg/complex/algorithms/create/plymc/simplemeshprovider.h - vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h - vcg/complex/algorithms/create/plymc/volume.h - vcg/complex/algorithms/create/plymc/plymc.h - vcg/complex/algorithms/create/plymc/svoxel.h - vcg/complex/algorithms/create/tetramesh_support.h - vcg/complex/algorithms/create/advancing_front.h - vcg/complex/algorithms/textcoord_optimization.h - vcg/complex/algorithms/bitquad_optimization.h - vcg/complex/algorithms/halfedge_quad_clean.h - vcg/complex/algorithms/voronoi_processing.h - vcg/complex/algorithms/update/quality.h - vcg/complex/algorithms/update/selection.h - vcg/complex/algorithms/update/fitmaps.h - vcg/complex/algorithms/update/component_ep.h - vcg/complex/algorithms/update/texture.h - vcg/complex/algorithms/update/curvature_fitting.h - vcg/complex/algorithms/update/normal.h - vcg/complex/algorithms/update/position.h - vcg/complex/algorithms/update/halfedge_topology.h - vcg/complex/algorithms/update/topology.h - vcg/complex/algorithms/update/flag.h - vcg/complex/algorithms/update/bounding.h - vcg/complex/algorithms/update/halfedge_indexed.h - vcg/complex/algorithms/update/color.h - vcg/complex/algorithms/update/curvature.h - vcg/complex/algorithms/point_outlier.h - vcg/complex/algorithms/harmonic.h - vcg/complex/algorithms/point_matching_scale.h - vcg/complex/algorithms/attribute_seam.h - vcg/complex/foreach.h - vcg/complex/base.h - vcg/complex/used_types.h - vcg/container/entries_allocation_table.h - vcg/container/container_allocation_table.h - vcg/container/derivation_chain.h - vcg/container/vector_occ.h - vcg/container/simple_temporary_data.h - vcg/space/segment2.h - vcg/space/fitting3.h - vcg/space/tetra3.h - vcg/space/triangle2.h - vcg/space/ray2.h - vcg/space/deprecated_point2.h - vcg/space/point4.h - vcg/space/box2.h - vcg/space/ray3.h - vcg/space/planar_polygon_tessellation.h - vcg/space/texcoord2.h - vcg/space/deprecated_point3.h - vcg/space/intersection/triangle_triangle3.h - vcg/space/distance2.h - vcg/space/point3.h - vcg/space/deprecated_point.h - vcg/space/space.h - vcg/space/point.h - vcg/space/colorspace.h - vcg/space/rect_packer.h - vcg/space/triangle3.h - vcg/space/obox3.h - vcg/space/point2.h - vcg/space/smallest_enclosing.h - vcg/space/color4.h - vcg/space/polygon3.h - vcg/space/line3.h - vcg/space/index/octree.h - vcg/space/index/grid_util2d.h - vcg/space/index/grid_closest.h - vcg/space/index/grid_static_ptr.h - vcg/space/index/grid_util.h - vcg/space/index/spatial_hashing.h - vcg/space/index/closest2d.h - vcg/space/index/grid_static_obj.h - vcg/space/index/kdtree/kdtree.h - vcg/space/index/kdtree/priorityqueue.h - vcg/space/index/kdtree/kdtree_face.h - vcg/space/index/kdtree/mlsutils.h - vcg/space/index/octree_template.h - vcg/space/index/aabb_binary_tree/kclosest.h - vcg/space/index/aabb_binary_tree/closest.h - vcg/space/index/aabb_binary_tree/ray.h - vcg/space/index/aabb_binary_tree/frustum_cull.h - vcg/space/index/aabb_binary_tree/aabb_binary_tree.h - vcg/space/index/aabb_binary_tree/base.h - vcg/space/index/grid_closest2d.h - vcg/space/index/spatial_hashing2d.h - vcg/space/index/space_iterators.h - vcg/space/index/grid_static_ptr2d.h - vcg/space/index/base2d.h - vcg/space/index/base.h - vcg/space/index/perfect_spatial_hashing.h - vcg/space/index/space_iterators2d.h - vcg/space/line2.h - vcg/space/point_matching.h - vcg/space/intersection3.h - vcg/space/deprecated_point4.h - vcg/space/rasterized_outline2_packer.h - vcg/space/box.h - vcg/space/plane3.h - vcg/space/outline2_packer.h - vcg/space/segment3.h - vcg/space/intersection2.h - vcg/space/sphere3.h - vcg/space/box3.h - vcg/space/distance3.h - vcg/math/quadric5.h - vcg/math/factorial.h - vcg/math/eigen_matrix_addons.h - vcg/math/quadric.h - vcg/math/perlin_noise.h - vcg/math/shot.h - vcg/math/spherical_harmonics.h - vcg/math/eigen_matrixbase_addons.h - vcg/math/quaternion.h - vcg/math/similarity.h - vcg/math/disjoint_set.h - vcg/math/random_generator.h - vcg/math/camera.h - vcg/math/linear.h - vcg/math/matrix44.h - vcg/math/eigen.h - vcg/math/old_lin_algebra.h - vcg/math/similarity2.h - vcg/math/gen_normal.h - vcg/math/old_matrix44.h - vcg/math/old_deprecated_matrix.h - vcg/math/old_matrix33.h - vcg/math/polar_decomposition.h - vcg/math/base.h - vcg/math/histogram.h - vcg/math/legendre.h - vcg/math/matrix33.h - vcg/math/old_matrix.h - vcg/simplex/edge/distance.h - vcg/simplex/edge/topology.h - vcg/simplex/edge/pos.h - vcg/simplex/edge/component.h - vcg/simplex/edge/base.h - vcg/simplex/tetrahedron/tetrahedron.h - vcg/simplex/tetrahedron/topology.h - vcg/simplex/tetrahedron/pos.h - vcg/simplex/tetrahedron/component.h - vcg/simplex/tetrahedron/base.h - vcg/simplex/face/component_occ.h - vcg/simplex/face/component_ep.h - vcg/simplex/face/jumping_pos.h - vcg/simplex/face/distance.h - vcg/simplex/face/component_polygon.h - vcg/simplex/face/topology.h - vcg/simplex/face/pos.h - vcg/simplex/face/component.h - vcg/simplex/face/component_ocf.h - vcg/simplex/face/base.h - vcg/simplex/vertex/component_occ.h - vcg/simplex/vertex/component_sph.h - vcg/simplex/vertex/distance.h - vcg/simplex/vertex/component.h - vcg/simplex/vertex/component_ocf.h - vcg/simplex/vertex/base.h - vcg/connectors/halfedge_pos.h - vcg/connectors/hedge.h - vcg/connectors/hedge_component.h + vcg/complex/append.h + vcg/complex/all_types.h + vcg/complex/complex.h + vcg/complex/allocate.h + vcg/complex/exception.h + vcg/complex/algorithms/overlap_estimation.h + vcg/complex/algorithms/dual_meshing.h + vcg/complex/algorithms/intersection.h + vcg/complex/algorithms/clip.h + vcg/complex/algorithms/geodesic.h + vcg/complex/algorithms/parametrization/poisson_solver.h + vcg/complex/algorithms/parametrization/uv_utils.h + vcg/complex/algorithms/parametrization/distortion.h + vcg/complex/algorithms/parametrization/tangent_field_operators.h + vcg/complex/algorithms/parametrization/voronoi_atlas.h + vcg/complex/algorithms/edge_collapse.h + vcg/complex/algorithms/hole.h + vcg/complex/algorithms/align_pair.h + vcg/complex/algorithms/closest.h + vcg/complex/algorithms/tetra_implicit_smooth.h + vcg/complex/algorithms/bitquad_support.h + vcg/complex/algorithms/skeleton.h + vcg/complex/algorithms/symmetry.h + vcg/complex/algorithms/voronoi_volume_sampling.h + vcg/complex/algorithms/polygon_polychord_collapse.h + vcg/complex/algorithms/inside.h + vcg/complex/algorithms/local_optimization/tri_edge_flip.h + vcg/complex/algorithms/local_optimization/quad_diag_collapse.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric_tex.h + vcg/complex/algorithms/local_optimization/tri_edge_collapse.h + vcg/complex/algorithms/local_optimization/tetra_edge_collapse.h + vcg/complex/algorithms/polygonal_algorithms.h + vcg/complex/algorithms/inertia.h + vcg/complex/algorithms/mesh_assert.h + vcg/complex/algorithms/occupancy_grid.h + vcg/complex/algorithms/meshtree.h + vcg/complex/algorithms/align_global.h + vcg/complex/algorithms/cut_tree.h + vcg/complex/algorithms/nring.h + vcg/complex/algorithms/tetra/tetfuse_collapse.h + vcg/complex/algorithms/stat.h + vcg/complex/algorithms/ransac_matching.h + vcg/complex/algorithms/refine.h + vcg/complex/algorithms/outline_support.h + vcg/complex/algorithms/convex_hull.h + vcg/complex/algorithms/clean.h + vcg/complex/algorithms/mesh_to_matrix.h + vcg/complex/algorithms/quadrangulator.h + vcg/complex/algorithms/isotropic_remeshing.h + vcg/complex/algorithms/smooth.h + vcg/complex/algorithms/autoalign_4pcs.h + vcg/complex/algorithms/local_optimization.h + vcg/complex/algorithms/curve_on_manifold.h + vcg/complex/algorithms/clustering.h + vcg/complex/algorithms/refine_loop.h + vcg/complex/algorithms/cylinder_clipping.h + vcg/complex/algorithms/pointcloud_normal.h + vcg/complex/algorithms/bitquad_creation.h + vcg/complex/algorithms/crease_cut.h + vcg/complex/algorithms/implicit_smooth.h + vcg/complex/algorithms/voronoi_remesher.h + vcg/complex/algorithms/polygon_support.h + vcg/complex/algorithms/point_sampling.h + vcg/complex/algorithms/create/mc_lookup_table.h + vcg/complex/algorithms/create/mc_trivial_walker.h + vcg/complex/algorithms/create/extrude.h + vcg/complex/algorithms/create/resampler.h + vcg/complex/algorithms/create/ball_pivoting.h + vcg/complex/algorithms/create/readme.txt + vcg/complex/algorithms/create/zonohedron.h + vcg/complex/algorithms/create/platonic.h + vcg/complex/algorithms/create/marching_cubes.h + vcg/complex/algorithms/create/plymc/voxel.h + vcg/complex/algorithms/create/plymc/simplemeshprovider.h + vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h + vcg/complex/algorithms/create/plymc/volume.h + vcg/complex/algorithms/create/plymc/plymc.h + vcg/complex/algorithms/create/plymc/svoxel.h + vcg/complex/algorithms/create/tetramesh_support.h + vcg/complex/algorithms/create/advancing_front.h + vcg/complex/algorithms/textcoord_optimization.h + vcg/complex/algorithms/bitquad_optimization.h + vcg/complex/algorithms/halfedge_quad_clean.h + vcg/complex/algorithms/voronoi_processing.h + vcg/complex/algorithms/update/quality.h + vcg/complex/algorithms/update/selection.h + vcg/complex/algorithms/update/fitmaps.h + vcg/complex/algorithms/update/component_ep.h + vcg/complex/algorithms/update/texture.h + vcg/complex/algorithms/update/curvature_fitting.h + vcg/complex/algorithms/update/normal.h + vcg/complex/algorithms/update/position.h + vcg/complex/algorithms/update/halfedge_topology.h + vcg/complex/algorithms/update/topology.h + vcg/complex/algorithms/update/flag.h + vcg/complex/algorithms/update/bounding.h + vcg/complex/algorithms/update/halfedge_indexed.h + vcg/complex/algorithms/update/color.h + vcg/complex/algorithms/update/curvature.h + vcg/complex/algorithms/point_outlier.h + vcg/complex/algorithms/harmonic.h + vcg/complex/algorithms/point_matching_scale.h + vcg/complex/algorithms/attribute_seam.h + vcg/complex/foreach.h + vcg/complex/base.h + vcg/complex/used_types.h + vcg/container/entries_allocation_table.h + vcg/container/container_allocation_table.h + vcg/container/derivation_chain.h + vcg/container/vector_occ.h + vcg/container/simple_temporary_data.h + vcg/space/segment2.h + vcg/space/fitting3.h + vcg/space/tetra3.h + vcg/space/triangle2.h + vcg/space/ray2.h + vcg/space/deprecated_point2.h + vcg/space/point4.h + vcg/space/box2.h + vcg/space/ray3.h + vcg/space/planar_polygon_tessellation.h + vcg/space/texcoord2.h + vcg/space/deprecated_point3.h + vcg/space/intersection/triangle_triangle3.h + vcg/space/distance2.h + vcg/space/point3.h + vcg/space/deprecated_point.h + vcg/space/space.h + vcg/space/point.h + vcg/space/colorspace.h + vcg/space/rect_packer.h + vcg/space/triangle3.h + vcg/space/obox3.h + vcg/space/point2.h + vcg/space/smallest_enclosing.h + vcg/space/color4.h + vcg/space/polygon3.h + vcg/space/line3.h + vcg/space/index/octree.h + vcg/space/index/grid_util2d.h + vcg/space/index/grid_closest.h + vcg/space/index/grid_static_ptr.h + vcg/space/index/grid_util.h + vcg/space/index/spatial_hashing.h + vcg/space/index/closest2d.h + vcg/space/index/grid_static_obj.h + vcg/space/index/kdtree/kdtree.h + vcg/space/index/kdtree/priorityqueue.h + vcg/space/index/kdtree/kdtree_face.h + vcg/space/index/kdtree/mlsutils.h + vcg/space/index/octree_template.h + vcg/space/index/aabb_binary_tree/kclosest.h + vcg/space/index/aabb_binary_tree/closest.h + vcg/space/index/aabb_binary_tree/ray.h + vcg/space/index/aabb_binary_tree/frustum_cull.h + vcg/space/index/aabb_binary_tree/aabb_binary_tree.h + vcg/space/index/aabb_binary_tree/base.h + vcg/space/index/grid_closest2d.h + vcg/space/index/spatial_hashing2d.h + vcg/space/index/space_iterators.h + vcg/space/index/grid_static_ptr2d.h + vcg/space/index/base2d.h + vcg/space/index/base.h + vcg/space/index/perfect_spatial_hashing.h + vcg/space/index/space_iterators2d.h + vcg/space/line2.h + vcg/space/point_matching.h + vcg/space/intersection3.h + vcg/space/deprecated_point4.h + vcg/space/rasterized_outline2_packer.h + vcg/space/box.h + vcg/space/plane3.h + vcg/space/outline2_packer.h + vcg/space/segment3.h + vcg/space/intersection2.h + vcg/space/sphere3.h + vcg/space/box3.h + vcg/space/distance3.h + vcg/math/quadric5.h + vcg/math/factorial.h + vcg/math/eigen_matrix_addons.h + vcg/math/quadric.h + vcg/math/perlin_noise.h + vcg/math/shot.h + vcg/math/spherical_harmonics.h + vcg/math/eigen_matrixbase_addons.h + vcg/math/quaternion.h + vcg/math/similarity.h + vcg/math/disjoint_set.h + vcg/math/random_generator.h + vcg/math/camera.h + vcg/math/linear.h + vcg/math/matrix44.h + vcg/math/eigen.h + vcg/math/similarity2.h + vcg/math/gen_normal.h + vcg/math/polar_decomposition.h + vcg/math/base.h + vcg/math/histogram.h + vcg/math/legendre.h + vcg/math/matrix33.h + vcg/simplex/edge/distance.h + vcg/simplex/edge/topology.h + vcg/simplex/edge/pos.h + vcg/simplex/edge/component.h + vcg/simplex/edge/base.h + vcg/simplex/tetrahedron/tetrahedron.h + vcg/simplex/tetrahedron/topology.h + vcg/simplex/tetrahedron/pos.h + vcg/simplex/tetrahedron/component.h + vcg/simplex/tetrahedron/base.h + vcg/simplex/face/component_occ.h + vcg/simplex/face/component_ep.h + vcg/simplex/face/jumping_pos.h + vcg/simplex/face/distance.h + vcg/simplex/face/component_polygon.h + vcg/simplex/face/topology.h + vcg/simplex/face/pos.h + vcg/simplex/face/component.h + vcg/simplex/face/component_ocf.h + vcg/simplex/face/base.h + vcg/simplex/vertex/component_occ.h + vcg/simplex/vertex/component_sph.h + vcg/simplex/vertex/distance.h + vcg/simplex/vertex/component.h + vcg/simplex/vertex/component_ocf.h + vcg/simplex/vertex/base.h + vcg/connectors/halfedge_pos.h + vcg/connectors/hedge.h + vcg/connectors/hedge_component.h - #wrap - wrap/callback.h -) + #wrap + wrap/callback.h + ) set(SOURCES -) + ) if (VCG_HEADER_ONLY) - add_library(vcglib INTERFACE) - target_include_directories( - vcglib INTERFACE - ${CMAKE_CURRENT_LIST_DIR} - ${EIGEN_INCLUDE_DIRS}) + if (NOT TARGET vcglib) # to be sure that vcglib target is created just one time + add_library(vcglib INTERFACE) + target_include_directories( + vcglib INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${EIGEN_INCLUDE_DIRS}) - #just to show headers in ide - add_custom_target(vcglib_ide SOURCES ${VCG_HEADERS}) + #just to show headers in ide + add_custom_target(vcglib_ide SOURCES ${VCG_HEADERS}) + else() + message(STATUS "- VCGLib - jumped - already included") + endif() else() #TODO make vcglib that includes all the wrap sources, checking everytime # if the the required targets (e.g. qt, gl, glew...) exists diff --git a/README.md b/README.md index d98ee6ec..28469735 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,37 @@ -The **_Visualization and Computer Graphics Library_** (VCGlib for short) is a open source, portable, C++, templated, no dependency, library for manipulation, processing, cleaning, simplifying triangle meshes. +The **_Visualization and Computer Graphics Library_** (VCGlib for short) is an open source, portable, and templated library written in C++, with no external dependencies, for manipulation, processing, cleaning, and simplifying triangle meshes. ![BuildExamplesLinux](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesLinux/badge.svg) ![BuildExamplesMacOS](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesMacOS/badge.svg) ![BuildExamplesWindows](https://github.com/cnr-isti-vclab/vcglib/workflows/BuildExamplesWindows/badge.svg) -The library, composed by more than 100k lines of code, is released under the GPL license, and it is the base of most of the software tools of the [Visual Computing Lab](http://vcg.isti.cnr.it) of the Italian National Research Council Institute ISTI, like MeshLab, metro and many others. +The library, composed by more than 100k lines of code, is released under the GPL license, and it is the base of most of the software tools of the [Visual Computing Lab](http://vcg.isti.cnr.it) of the Italian National Research Council Institute - ISTI, like [MeshLab](http://www.meshlab.net/), [Metro](http://vcg.isti.cnr.it/vcglib/metro.html) and many others. -The VCG library is tailored to mostly manage triangular meshes: The library is fairly large and offers many state of the art functionalities for processing meshes, like: +The VCG library is tailored to mostly manage triangular meshes: The library is fairly large and offers many state-of-the-art capabilities for processing meshes, such as: -- high quality quadric-error edge-collapse based simplfication, -- efficient spatial query structures (uniform grids, hashed grids, kdtree, ...) , -- advanced smoothing and fairing algorithms, -- computation of curvature, -- optimization of texture coordinates, -- Hausdorff distance computation, -- geodesic paths, -- mesh repairing capabilities, -- isosurface extraction and advancing front meshing algorithms, -- Poisson Disk sampling and other tools to sample point distributions over meshes, +- high quality quadric-error edge-collapse based simplfication +- efficient spatial query structures (uniform grids, hashed grids, kdtree, etc) +- advanced smoothing and fairing algorithms +- computation of curvature +- optimization of texture coordinates +- Hausdorff distance computation +- geodesic paths +- mesh repairing capabilities +- isosurface extraction and advancing front meshing algorithms +- Poisson Disk sampling and other tools to sample point distributions over meshes - subdivision surfaces ## Notable Applications -A number of applications have been developed using the vcglib: +A number of applications have been developed using the VCGlib: -- MeshLab: the renowed open source mesh processing is based on this library. +- MeshLab: the renowed open source mesh processing software - Metro, the tool for measuring differences between meshes - The first high quality out-of-core mesh simplifier that was used by the Stanford Digital Michelangelo project to process their huge 3D scanned models. ## Contacts -For any info about licensing (portion of) the library please contact us: -Paolo Cignoni (p.cignoni@isti.cnr.it) +For any info about licensing (portions of) the library please contact us: +Paolo Cignoni (p.cignoni@isti.cnr.it) Visual Computing Lab of the Italian National Research Council - ISTI -In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues) . +In case of bugs please report them [here](https://github.com/cnr-isti-vclab/vcglib/issues). diff --git a/apps/sample/trimesh_curvature/CMakeLists.txt b/apps/sample/trimesh_curvature/CMakeLists.txt index a09fe6e1..57265ce7 100644 --- a/apps/sample/trimesh_curvature/CMakeLists.txt +++ b/apps/sample/trimesh_curvature/CMakeLists.txt @@ -3,7 +3,8 @@ project(trimesh_curvature) if (VCG_HEADER_ONLY) set(SOURCES - trimesh_curvature.cpp) + trimesh_curvature.cpp + ${VCG_INCLUDE_DIRS}/wrap/ply/plylib.cpp) endif() add_executable(trimesh_curvature diff --git a/apps/sample/trimesh_curvature/trimesh_curvature.cpp b/apps/sample/trimesh_curvature/trimesh_curvature.cpp index 8569c6e5..47104819 100644 --- a/apps/sample/trimesh_curvature/trimesh_curvature.cpp +++ b/apps/sample/trimesh_curvature/trimesh_curvature.cpp @@ -23,46 +23,86 @@ /*! \file trimesh_curvature.cpp \ingroup code_sample -\brief an example showing the various techniques for computing curvatures +\brief an example showing various techniques for computing curvatures */ #include #include #include +#include -#include +#include -class MyEdge; class MyFace; class MyVertex; struct MyUsedTypes : public vcg::UsedTypes< vcg::Use ::AsVertexType, - vcg::Use ::AsEdgeType, vcg::Use ::AsFaceType>{}; -class MyVertex : public vcg::Vertex{}; -class MyFace : public vcg::Face< MyUsedTypes, vcg::face::FFAdj, vcg::face::VFAdj, vcg::face::VertexRef, vcg::face::BitFlags > {}; -class MyEdge : public vcg::Edge{}; -class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector , std::vector > {}; +class MyVertex : public vcg::Vertex{}; +class MyFace : public vcg::Face< MyUsedTypes, vcg::face::FFAdj, vcg::face::VFAdj, vcg::face::Normal3f, vcg::face::VertexRef, vcg::face::BitFlags > {}; +class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector > {}; int main( int /*argc*/, char **/*argv*/ ) { MyMesh m; - vcg::tri::Torus(m,30,10); + // in a torus with radii 1 and 4 + // on the outside the principal curvature should be 1 and 1/5 + // and internally the principal curvature should be 1 and -1/3 + // Gaussian range -0.333 .. 0.200 + // mean range 0.333 .. 0.600 + //vcg::tri::Torus(m,4,1,32,16); + + + // in a sphere of radius 2 the curvature is everywhere 0.5 + // Gaussian 0.25 + // Mean 0.5 + vcg::tri::Sphere(m,5); + vcg::tri::UpdatePosition::Scale(m, 2.0); vcg::tri::UpdateTopology::FaceFace(m); vcg::tri::UpdateTopology::VertexFace(m); + vcg::tri::UpdateNormal::PerVertexNormalizedPerFaceNormalized(m); + vcg::Distribution distr; + printf("Starting mesh vn:%i fn:%i\n",m.VN(),m.FN()); - // Two different techniques for computing Discrete Gaussian and Mean Curvature - // they require the presence of the vertex::Curvature component - vcg::tri::UpdateCurvature::PerVertex(m); + // Method 1 (discrete - Optimizing 3d triangulations using discrete curvature analysis 2003) + vcg::tri::UpdateCurvature::PerVertexAbsoluteMeanAndGaussian(m); + vcg::tri::UpdateQuality::VertexFromAttributeName(m,"KG"); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Gaussian Curvature method 1 Min %f Max %f\n",distr.Min(),distr.Max()); + vcg::tri::UpdateQuality::VertexFromAttributeName(m,"KH"); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Mean Curvature method 1 Min %f Max %f\n",distr.Min(),distr.Max()); + + // Method 2 (discrete - Discrete Differential-Geometry Operators for Triangulated 2-Manifolds 2002) vcg::tri::UpdateCurvature::MeanAndGaussian(m); + vcg::tri::UpdateQuality::VertexFromAttributeName(m,"KG"); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Gaussian Curvature method 2 Min %f Max %f\n",distr.Min(),distr.Max()); + vcg::tri::UpdateQuality::VertexFromAttributeName(m,"KH"); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Mean Curvature method 2 Min %f Max %f\n",distr.Min(),distr.Max()); + vcg::tri::io::ExporterPLY::Save(m,"Torus_Discrete_Mean2.ply",vcg::tri::io::Mask::IOM_VERTQUALITY); - // Two different techniques for computing Principal Curvature Directions - // they require the presence of the vertex::CurvatureDir component + // Method 3 (directions - Estimating the Tensor of Curvature of a Surface from a Polyhedral Approximation - 1995) vcg::tri::UpdateCurvature::PrincipalDirections(m); + vcg::tri::UpdateQuality::VertexGaussianFromCurvatureDir(m); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Gaussian Curvature method 3 Min %f Max %f\n",distr.Min(),distr.Max()); + vcg::tri::UpdateQuality::VertexMeanFromCurvatureDir(m); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Mean Curvature method 3 Min %f Max %f\n",distr.Min(),distr.Max()); + + // Method 4 (directions - Restricted delaunay triangulations and normal cycle ) vcg::tri::UpdateCurvature::PrincipalDirectionsNormalCycle(m); - printf("Input mesh vn:%i fn:%i\n",m.VN(),m.FN()); - + vcg::tri::UpdateQuality::VertexGaussianFromCurvatureDir(m); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Gaussian Curvature method 4 Min %f Max %f\n",distr.Min(),distr.Max()); + vcg::tri::UpdateQuality::VertexMeanFromCurvatureDir(m); + vcg::tri::Stat::ComputePerVertexQualityDistribution(m,distr); + printf("Mean Curvature method 4 Min %f Max %f\n",distr.Min(),distr.Max()); + + return 0; } diff --git a/apps/sample/trimesh_curvature/trimesh_curvature.pro b/apps/sample/trimesh_curvature/trimesh_curvature.pro index 8342dfa4..343a355e 100644 --- a/apps/sample/trimesh_curvature/trimesh_curvature.pro +++ b/apps/sample/trimesh_curvature/trimesh_curvature.pro @@ -1,3 +1,3 @@ include(../common.pri) TARGET = trimesh_curvature -SOURCES += trimesh_curvature.cpp +SOURCES += trimesh_curvature.cpp ../../../wrap/ply/plylib.cpp diff --git a/docs/ContributorLicenseAgreement.md b/docs/ContributorLicenseAgreement.md index 994c4e2f..20215eef 100644 --- a/docs/ContributorLicenseAgreement.md +++ b/docs/ContributorLicenseAgreement.md @@ -8,7 +8,7 @@ The following terms are used throughout this agreement: * **Submitted** - conveyed to a Project via a pull request, commit, issue, or any form of electronic, written, or verbal communication with GitHub, contributors or maintainers. ## 1. Grant of Copyright License. -Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers and to VCLab a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your contributions and such derivative works. Except for this license, You reserve all rights, title, and interest in your contributions. +Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers and to VCLab a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your contributions and such derivative works. Except for this license, You reserve all rights, title, and interest in your contributions. You agree that your perpetual licensing grant will be applied to all Your contributions to VCLab's Projects during the validity (two years) of this agreement. ## 2. Grant of Patent License. Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers and to VCLab a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer your contributions, where such license applies only to those patent claims licensable by you that are necessarily infringed by your contribution or by combination of your contribution with the project to which this contribution was submitted. @@ -25,9 +25,7 @@ Your contribution is either your original creation, based upon previous work tha   |   **Email** | **Physical home/office address**  |  -**Date of birth** | **Place of birth** -  |   -**github Project Contributed** | **Contribution** (id of the pull request) +**Date of birth** | **Place of birth**   |   @@ -37,4 +35,3 @@ Signature Date --- - diff --git a/docs/ContributorLicenseAgreement.pdf b/docs/ContributorLicenseAgreement.pdf index daa1cefc..c56c6392 100644 Binary files a/docs/ContributorLicenseAgreement.pdf and b/docs/ContributorLicenseAgreement.pdf differ diff --git a/docs/Doxygen/basic_concepts.dxy b/docs/Doxygen/basic_concepts.dxy index b0ab1ff8..5514636e 100644 --- a/docs/Doxygen/basic_concepts.dxy +++ b/docs/Doxygen/basic_concepts.dxy @@ -28,13 +28,13 @@ The face, the edge and the vertex type are the crucial bits to understand in ord \until Qualityf \c vcg::Vertex is the VCG base class for a vertex. -\c vcg::UsedTypes declares which are the types invoved in the definition of the mesh. It is a mapping between the names of your entity types (MyVertex,MyEdge,MyFace... and the role they play in the mesh definition). The mapping is established passing the template parameters with the syntax +\c vcg::UsedTypes declares which are the types involved in the definition of the mesh. It is a mapping between the names of your entity types (MyVertex,MyEdge,MyFace... and the role they play in the mesh definition). The mapping is established passing the template parameters with the syntax It can be annoying when you see it but it is useful that every entity involved knows the type of the others and this is the way VCG Lib does it. As you can see the three definitions of MyVertex0,1,2 differ for the remaining template parameters (the components). These specify which values will be stored with the vertex type: - MyVertex0 is a type storing coordinates as a triple of doubles and normal as a triple of floats, - MyVertex1 also store a color value specified as 4 bytes - MyVertex2 store a long list of different components. -Many other compenents are implemented in the library for the simplexes, the complete list can be found +Many other components are implemented in the library for the simplexes, the complete list can be found in the \ref VertexComponentGroup, \ref EdgeComponentGroup and \ref FaceComponentGroup pages. You can place any combination of them as a template parameters of your vertex/edge/face type (note that order is rather unimportant). Now we have all it takes for a working definition of MyMesh type: @@ -54,15 +54,15 @@ One more comment: \c vcg::face::VertexRef is an attribute that stores 3 pointers How to create a mesh -------------------- -Once you declared your mesh type, you may want to instance an object and to fill it with vertices and triangles. The typical approach is just to open some file like in the above example. It may cross your mind that you could just make some push_back on the vertexes and faces container (data member vert and face of class vcg::tri::Trimesh). In fact this is the wrong way since there can be side effects by adding element to a container. We describe this issue and the correct way of adding mesh element in the \ref allocation page. +Once you declared your mesh type, you may want to instance an object and to fill it with vertices and triangles. The typical approach is just to open some file like in the above example. It may cross your mind that you could just make some push_back on the vertexes and faces container (data member vert and face of class vcg::tri::Trimesh). In fact this is the wrong way since there can be side effects by adding an element to a container. We describe this issue and the correct way of adding mesh element in the \ref allocation page. The flags of the mesh elements ----------- -Usually to each element of the mesh we associate a small bit vector containing useful single-bit information about vertices and faces. For example the deletion of vertex simply mark a the Deletion bit in thsi vector (more details on the various deletion/allocation issues in the \ref allocation page. More details on the various kind of flags that can be associated are in the \ref flags page. +Usually to each element of the mesh we associate a small bit vector containing useful single-bit information about vertices and faces. For example the deletion of vertex simply mark a the Deletion bit in this vector (more details on the various deletion/allocation issues in the \ref allocation page. More details on the various kind of flags that can be associated are in the \ref flags page. How to process a mesh ------------- -The algorithms that do something on a mesh are generally written as static member functions of a class templated on the mesh type. For example the code snipped below is part of the class UpdateNormals, which contains the several algorithms to compute the value of the normal +The algorithms that do something on a mesh are generally written as a static member functions of a templated class on the mesh type. For example the code snipped below is part of the class UpdateNormals, which contains the several algorithms to compute the value of the normal \code ... @@ -73,16 +73,16 @@ class UpdateNormals{ static void PerFace(ComputeMeshType &m) // Calculates the vertex normal. Without exploiting or touching face normals -// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. +// The normal of a vertex v is the weighted average of the normals of the faces incident on v. static void PerVertex(ComputeMeshType &m) // Calculates both vertex and face normals. -// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. +// The normal of a vertex v is the weighted average of the normals of the faces incident on v. static void PerVertexPerFace(ComputeMeshType &m) ... }; \endcode -This class is part of a kernel of classes with name UpdateValue that compute the value of the vertex or face attributes and that can be found altogether in the folder vcg/complex/trimesh/update. For example, the following example show how to compute the value of the normal and the mean and gaussian curvature per vertex: +This class is part of a kernel of classes with name UpdateValue that compute the value of the vertex or face attributes and that can be found altogether in the folder vcg/complex/trimesh/update. For example, the following example shows how to compute the value of the normal and the mean and gaussian curvature per vertex: \code #include @@ -92,9 +92,9 @@ This class is part of a kernel of classes with name UpdateValue that compute the #include #include -#include -#include //class UpdateNormals -#include //class UpdateCurvature +#include +#include //class UpdateNormals +#include //class UpdateCurvature class MyVertex; class MyFace; @@ -120,6 +120,5 @@ int main() } \endcode -Other than algorithms that update values of the mesh attributes, VCG Lib provides algorithms to create a mesh from another source, for example from point sets (by means of the Ball Pivoting approach) or as isosurfaces from a volumetric dataset (by means of Marching Cubes algorithm). Those algorithm can be found in vcg/complex/trimesh/create/. +Other than algorithms that update values of the mesh attributes, VCG Lib provides algorithms to create a mesh from another source, for example from point sets (by means of the Ball Pivoting approach) or as isosurfaces from a volumetric dataset (by means of Marching Cubes algorithm). Those algorithms can be found in vcg/complex/trimesh/create/. Finally, you can find algorithms for refinement (midpoint, Loop, Butterfly...), for smoothing, for closing holes and other that are not currently classified under any specific heading and that you can find under /vcg/complex/trimesh.*/ - diff --git a/eigenlib/Eigen/Cholesky b/eigenlib/Eigen/Cholesky index 369d1f5e..b37dc4e4 100644 --- a/eigenlib/Eigen/Cholesky +++ b/eigenlib/Eigen/Cholesky @@ -3,12 +3,13 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CHOLESKY_MODULE_H #define EIGEN_CHOLESKY_MODULE_H #include "Core" +#include "Jacobi" #include "src/Core/util/DisableStupidWarnings.h" @@ -31,7 +32,11 @@ #include "src/Cholesky/LLT.h" #include "src/Cholesky/LDLT.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Cholesky/LLT_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/CholmodSupport b/eigenlib/Eigen/CholmodSupport index bed8924d..88913ad8 100644 --- a/eigenlib/Eigen/CholmodSupport +++ b/eigenlib/Eigen/CholmodSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CHOLMODSUPPORT_MODULE_H #define EIGEN_CHOLMODSUPPORT_MODULE_H @@ -19,7 +19,7 @@ extern "C" { /** \ingroup Support_modules * \defgroup CholmodSupport_Module CholmodSupport module * - * This module provides an interface to the Cholmod library which is part of the suitesparse package. + * This module provides an interface to the Cholmod library which is part of the suitesparse package. * It provides the two following main factorization classes: * - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization. * - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial). diff --git a/eigenlib/Eigen/Core b/eigenlib/Eigen/Core index 82558155..3a202c7a 100644 --- a/eigenlib/Eigen/Core +++ b/eigenlib/Eigen/Core @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CORE_H #define EIGEN_CORE_H @@ -14,6 +14,22 @@ // first thing Eigen does: stop the compiler from committing suicide #include "src/Core/util/DisableStupidWarnings.h" +#if defined(__CUDACC__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDACC __CUDACC__ +#endif + +#if defined(__CUDA_ARCH__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDA_ARCH __CUDA_ARCH__ +#endif + +#if defined(__CUDACC_VER_MAJOR__) && (__CUDACC_VER_MAJOR__ >= 9) +#define EIGEN_CUDACC_VER ((__CUDACC_VER_MAJOR__ * 10000) + (__CUDACC_VER_MINOR__ * 100)) +#elif defined(__CUDACC_VER__) +#define EIGEN_CUDACC_VER __CUDACC_VER__ +#else +#define EIGEN_CUDACC_VER 0 +#endif + // Handle NVCC/CUDA/SYCL #if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__) // Do not try asserts on CUDA and SYCL! @@ -37,9 +53,9 @@ #endif #define EIGEN_DEVICE_FUNC __host__ __device__ - // We need math_functions.hpp to ensure that that EIGEN_USING_STD_MATH macro + // We need cuda_runtime.h to ensure that that EIGEN_USING_STD_MATH macro // works properly on the device side - #include + #include #else #define EIGEN_DEVICE_FUNC #endif @@ -72,7 +88,7 @@ #include "src/Core/util/Macros.h" // Disable the ipa-cp-clone optimization flag with MinGW 6.x or newer (enabled by default with -O3) -// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details. +// See xxxp://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details. #if EIGEN_COMP_MINGW && EIGEN_GNUC_AT_LEAST(4,6) #pragma GCC optimize ("-fno-ipa-cp-clone") #endif @@ -155,12 +171,15 @@ #ifdef __AVX512DQ__ #define EIGEN_VECTORIZE_AVX512DQ #endif + #ifdef __AVX512ER__ + #define EIGEN_VECTORIZE_AVX512ER + #endif #endif // include files // This extern "C" works around a MINGW-w64 compilation issue - // https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354 + // xxxps://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354 // In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do). // However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations // with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know; @@ -229,7 +248,7 @@ #if defined __CUDACC__ #define EIGEN_VECTORIZE_CUDA #include - #if defined __CUDACC_VER__ && __CUDACC_VER__ >= 70500 + #if EIGEN_CUDACC_VER >= 70500 #define EIGEN_HAS_CUDA_FP16 #endif #endif @@ -260,7 +279,10 @@ #include #include #include -#include +#include +#ifndef EIGEN_NO_IO + #include +#endif #include #include #include @@ -318,15 +340,19 @@ inline static const char *SimdInstructionSetsInUse(void) { #if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS || defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API || defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS || defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API || defined EIGEN2_SUPPORT // This will generate an error message: -#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information +#error Eigen2-support is only available up to version 3.2. Please go to "xxxp://eigen.tuxfamily.org/index.php?title=Eigen2" for further information #endif +namespace Eigen { + // we use size_t frequently and we'll never remember to prepend it with std:: everytime just to // ensure QNX/QCC support using std::size_t; // gcc 4.6.0 wants std:: for ptrdiff_t using std::ptrdiff_t; +} + /** \defgroup Core_Module Core module * This is the main module of Eigen providing dense matrix and vector support * (both fixed and dynamic size) with all the features corresponding to a BLAS library @@ -348,10 +374,13 @@ using std::ptrdiff_t; #include "src/Core/MathFunctions.h" #include "src/Core/GenericPacketMath.h" #include "src/Core/MathFunctionsImpl.h" +#include "src/Core/arch/Default/ConjHelper.h" #if defined EIGEN_VECTORIZE_AVX512 #include "src/Core/arch/SSE/PacketMath.h" + #include "src/Core/arch/SSE/MathFunctions.h" #include "src/Core/arch/AVX/PacketMath.h" + #include "src/Core/arch/AVX/MathFunctions.h" #include "src/Core/arch/AVX512/PacketMath.h" #include "src/Core/arch/AVX512/MathFunctions.h" #elif defined EIGEN_VECTORIZE_AVX @@ -363,6 +392,7 @@ using std::ptrdiff_t; #include "src/Core/arch/AVX/MathFunctions.h" #include "src/Core/arch/AVX/Complex.h" #include "src/Core/arch/AVX/TypeCasting.h" + #include "src/Core/arch/SSE/TypeCasting.h" #elif defined EIGEN_VECTORIZE_SSE #include "src/Core/arch/SSE/PacketMath.h" #include "src/Core/arch/SSE/MathFunctions.h" @@ -405,6 +435,7 @@ using std::ptrdiff_t; // on CUDA devices #include "src/Core/arch/CUDA/Complex.h" +#include "src/Core/IO.h" #include "src/Core/DenseCoeffsBase.h" #include "src/Core/DenseBase.h" #include "src/Core/MatrixBase.h" @@ -452,7 +483,6 @@ using std::ptrdiff_t; #include "src/Core/Redux.h" #include "src/Core/Visitor.h" #include "src/Core/Fuzzy.h" -#include "src/Core/IO.h" #include "src/Core/Swap.h" #include "src/Core/CommaInitializer.h" #include "src/Core/GeneralProduct.h" diff --git a/eigenlib/Eigen/Eigenvalues b/eigenlib/Eigen/Eigenvalues index 009e529e..b740e0b6 100644 --- a/eigenlib/Eigen/Eigenvalues +++ b/eigenlib/Eigen/Eigenvalues @@ -3,21 +3,21 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_EIGENVALUES_MODULE_H #define EIGEN_EIGENVALUES_MODULE_H #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "Cholesky" #include "Jacobi" #include "Householder" #include "LU" #include "Geometry" +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup Eigenvalues_Module Eigenvalues module * * @@ -45,7 +45,11 @@ #include "src/Eigenvalues/GeneralizedEigenSolver.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Eigenvalues/RealSchur_LAPACKE.h" #include "src/Eigenvalues/ComplexSchur_LAPACKE.h" #include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h" diff --git a/eigenlib/Eigen/Geometry b/eigenlib/Eigen/Geometry index 716d5295..b053d41b 100644 --- a/eigenlib/Eigen/Geometry +++ b/eigenlib/Eigen/Geometry @@ -3,19 +3,19 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GEOMETRY_MODULE_H #define EIGEN_GEOMETRY_MODULE_H #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "SVD" #include "LU" #include +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup Geometry_Module Geometry module * * This module provides support for: diff --git a/eigenlib/Eigen/Householder b/eigenlib/Eigen/Householder index 89cd81b1..18eec747 100644 --- a/eigenlib/Eigen/Householder +++ b/eigenlib/Eigen/Householder @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HOUSEHOLDER_MODULE_H #define EIGEN_HOUSEHOLDER_MODULE_H diff --git a/eigenlib/Eigen/IterativeLinearSolvers b/eigenlib/Eigen/IterativeLinearSolvers index 957d5750..1865a38e 100644 --- a/eigenlib/Eigen/IterativeLinearSolvers +++ b/eigenlib/Eigen/IterativeLinearSolvers @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ITERATIVELINEARSOLVERS_MODULE_H #define EIGEN_ITERATIVELINEARSOLVERS_MODULE_H diff --git a/eigenlib/Eigen/Jacobi b/eigenlib/Eigen/Jacobi index 17c1d785..3116ea4e 100644 --- a/eigenlib/Eigen/Jacobi +++ b/eigenlib/Eigen/Jacobi @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_JACOBI_MODULE_H #define EIGEN_JACOBI_MODULE_H diff --git a/eigenlib/Eigen/LU b/eigenlib/Eigen/LU index 6f6c5562..ec6aa837 100644 --- a/eigenlib/Eigen/LU +++ b/eigenlib/Eigen/LU @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_LU_MODULE_H #define EIGEN_LU_MODULE_H @@ -28,7 +28,11 @@ #include "src/LU/FullPivLU.h" #include "src/LU/PartialPivLU.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/LU/PartialPivLU_LAPACKE.h" #endif #include "src/LU/Determinant.h" diff --git a/eigenlib/Eigen/MetisSupport b/eigenlib/Eigen/MetisSupport index 85c41bf3..8ced5fff 100644 --- a/eigenlib/Eigen/MetisSupport +++ b/eigenlib/Eigen/MetisSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_METISSUPPORT_MODULE_H #define EIGEN_METISSUPPORT_MODULE_H @@ -23,7 +23,7 @@ extern "C" { * \code * #include * \endcode - * This module defines an interface to the METIS reordering package (http://glaros.dtc.umn.edu/gkhome/views/metis). + * This module defines an interface to the METIS reordering package (xxxp://glaros.dtc.umn.edu/gkhome/views/metis). * It can be used just as any other built-in method as explained in \link OrderingMethods_Module here. \endlink */ diff --git a/eigenlib/Eigen/OrderingMethods b/eigenlib/Eigen/OrderingMethods index d8ea3619..14f718fe 100644 --- a/eigenlib/Eigen/OrderingMethods +++ b/eigenlib/Eigen/OrderingMethods @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ORDERINGMETHODS_MODULE_H #define EIGEN_ORDERINGMETHODS_MODULE_H diff --git a/eigenlib/Eigen/PaStiXSupport b/eigenlib/Eigen/PaStiXSupport index de3a63b4..90429aa4 100644 --- a/eigenlib/Eigen/PaStiXSupport +++ b/eigenlib/Eigen/PaStiXSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PASTIXSUPPORT_MODULE_H #define EIGEN_PASTIXSUPPORT_MODULE_H @@ -24,7 +24,7 @@ extern "C" { /** \ingroup Support_modules * \defgroup PaStiXSupport_Module PaStiXSupport module * - * This module provides an interface to the PaSTiX library. + * This module provides an interface to the PaSTiX library. * PaSTiX is a general \b supernodal, \b parallel and \b opensource sparse solver. * It provides the two following main factorization classes: * - class PastixLLT : a supernodal, parallel LLt Cholesky factorization. diff --git a/eigenlib/Eigen/PardisoSupport b/eigenlib/Eigen/PardisoSupport index 340edf51..7d1a211d 100755 --- a/eigenlib/Eigen/PardisoSupport +++ b/eigenlib/Eigen/PardisoSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARDISOSUPPORT_MODULE_H #define EIGEN_PARDISOSUPPORT_MODULE_H diff --git a/eigenlib/Eigen/QR b/eigenlib/Eigen/QR index 80838e3b..a6ebbb90 100644 --- a/eigenlib/Eigen/QR +++ b/eigenlib/Eigen/QR @@ -3,19 +3,19 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_QR_MODULE_H #define EIGEN_QR_MODULE_H #include "Core" -#include "src/Core/util/DisableStupidWarnings.h" - #include "Cholesky" #include "Jacobi" #include "Householder" +#include "src/Core/util/DisableStupidWarnings.h" + /** \defgroup QR_Module QR module * * @@ -36,7 +36,11 @@ #include "src/QR/ColPivHouseholderQR.h" #include "src/QR/CompleteOrthogonalDecomposition.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/QR/HouseholderQR_LAPACKE.h" #include "src/QR/ColPivHouseholderQR_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/QtAlignedMalloc b/eigenlib/Eigen/QtAlignedMalloc index 4044d5ac..f0e75efd 100644 --- a/eigenlib/Eigen/QtAlignedMalloc +++ b/eigenlib/Eigen/QtAlignedMalloc @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_QTMALLOC_MODULE_H #define EIGEN_QTMALLOC_MODULE_H @@ -14,7 +14,7 @@ #include "src/Core/util/DisableStupidWarnings.h" -void *qMalloc(size_t size) +void *qMalloc(std::size_t size) { return Eigen::internal::aligned_malloc(size); } @@ -24,10 +24,10 @@ void qFree(void *ptr) Eigen::internal::aligned_free(ptr); } -void *qRealloc(void *ptr, size_t size) +void *qRealloc(void *ptr, std::size_t size) { void* newPtr = Eigen::internal::aligned_malloc(size); - memcpy(newPtr, ptr, size); + std::memcpy(newPtr, ptr, size); Eigen::internal::aligned_free(ptr); return newPtr; } diff --git a/eigenlib/Eigen/SPQRSupport b/eigenlib/Eigen/SPQRSupport index f70390c1..eb83920a 100644 --- a/eigenlib/Eigen/SPQRSupport +++ b/eigenlib/Eigen/SPQRSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPQRSUPPORT_MODULE_H #define EIGEN_SPQRSUPPORT_MODULE_H @@ -17,7 +17,7 @@ /** \ingroup Support_modules * \defgroup SPQRSupport_Module SuiteSparseQR module * - * This module provides an interface to the SPQR library, which is part of the suitesparse package. + * This module provides an interface to the SPQR library, which is part of the suitesparse package. * * \code * #include diff --git a/eigenlib/Eigen/SVD b/eigenlib/Eigen/SVD index 86143c23..541181d8 100644 --- a/eigenlib/Eigen/SVD +++ b/eigenlib/Eigen/SVD @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SVD_MODULE_H #define EIGEN_SVD_MODULE_H @@ -37,7 +37,11 @@ #include "src/SVD/JacobiSVD.h" #include "src/SVD/BDCSVD.h" #if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT) +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/SVD/JacobiSVD_LAPACKE.h" #endif diff --git a/eigenlib/Eigen/Sparse b/eigenlib/Eigen/Sparse index a2ef7a66..77d4fe83 100644 --- a/eigenlib/Eigen/Sparse +++ b/eigenlib/Eigen/Sparse @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_MODULE_H #define EIGEN_SPARSE_MODULE_H @@ -25,7 +25,9 @@ #include "SparseCore" #include "OrderingMethods" +#ifndef EIGEN_MPL2_ONLY #include "SparseCholesky" +#endif #include "SparseLU" #include "SparseQR" #include "IterativeLinearSolvers" diff --git a/eigenlib/Eigen/SparseCholesky b/eigenlib/Eigen/SparseCholesky index b6a320c4..efa36126 100644 --- a/eigenlib/Eigen/SparseCholesky +++ b/eigenlib/Eigen/SparseCholesky @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSECHOLESKY_MODULE_H #define EIGEN_SPARSECHOLESKY_MODULE_H diff --git a/eigenlib/Eigen/SparseCore b/eigenlib/Eigen/SparseCore index 76966c4c..83466e64 100644 --- a/eigenlib/Eigen/SparseCore +++ b/eigenlib/Eigen/SparseCore @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSECORE_MODULE_H #define EIGEN_SPARSECORE_MODULE_H diff --git a/eigenlib/Eigen/SparseLU b/eigenlib/Eigen/SparseLU index 38b38b53..782ce834 100644 --- a/eigenlib/Eigen/SparseLU +++ b/eigenlib/Eigen/SparseLU @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSELU_MODULE_H #define EIGEN_SPARSELU_MODULE_H diff --git a/eigenlib/Eigen/SparseQR b/eigenlib/Eigen/SparseQR index a6f3b7f7..dc1d7dc5 100644 --- a/eigenlib/Eigen/SparseQR +++ b/eigenlib/Eigen/SparseQR @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEQR_MODULE_H #define EIGEN_SPARSEQR_MODULE_H @@ -28,7 +28,6 @@ * */ -#include "OrderingMethods" #include "src/SparseCore/SparseColEtree.h" #include "src/SparseQR/SparseQR.h" diff --git a/eigenlib/Eigen/StdDeque b/eigenlib/Eigen/StdDeque index be3a7f82..0b9e253d 100644 --- a/eigenlib/Eigen/StdDeque +++ b/eigenlib/Eigen/StdDeque @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDDEQUE_MODULE_H #define EIGEN_STDDEQUE_MODULE_H @@ -14,7 +14,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/StdList b/eigenlib/Eigen/StdList index 07ba1297..aadb0343 100644 --- a/eigenlib/Eigen/StdList +++ b/eigenlib/Eigen/StdList @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDLIST_MODULE_H #define EIGEN_STDLIST_MODULE_H @@ -13,7 +13,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/StdVector b/eigenlib/Eigen/StdVector index fdfc3776..17f348d1 100644 --- a/eigenlib/Eigen/StdVector +++ b/eigenlib/Eigen/StdVector @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDVECTOR_MODULE_H #define EIGEN_STDVECTOR_MODULE_H @@ -14,7 +14,7 @@ #include "Core" #include -#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */ +#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */ #define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) diff --git a/eigenlib/Eigen/SuperLUSupport b/eigenlib/Eigen/SuperLUSupport index 59312a82..296c953b 100644 --- a/eigenlib/Eigen/SuperLUSupport +++ b/eigenlib/Eigen/SuperLUSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SUPERLUSUPPORT_MODULE_H #define EIGEN_SUPERLUSUPPORT_MODULE_H @@ -38,7 +38,7 @@ namespace Eigen { struct SluMatrix; } /** \ingroup Support_modules * \defgroup SuperLUSupport_Module SuperLUSupport module * - * This module provides an interface to the SuperLU library. + * This module provides an interface to the SuperLU library. * It provides the following factorization class: * - class SuperLU: a supernodal sequential LU factorization. * - class SuperILU: a supernodal sequential incomplete LU factorization (to be used as a preconditioner for iterative methods). diff --git a/eigenlib/Eigen/UmfPackSupport b/eigenlib/Eigen/UmfPackSupport index 00eec808..5dcec6d7 100644 --- a/eigenlib/Eigen/UmfPackSupport +++ b/eigenlib/Eigen/UmfPackSupport @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_UMFPACKSUPPORT_MODULE_H #define EIGEN_UMFPACKSUPPORT_MODULE_H @@ -19,7 +19,7 @@ extern "C" { /** \ingroup Support_modules * \defgroup UmfPackSupport_Module UmfPackSupport module * - * This module provides an interface to the UmfPack library which is part of the suitesparse package. + * This module provides an interface to the UmfPack library which is part of the suitesparse package. * It provides the following factorization class: * - class UmfPackLU: a multifrontal sequential LU factorization. * diff --git a/eigenlib/Eigen/src/Cholesky/LDLT.h b/eigenlib/Eigen/src/Cholesky/LDLT.h index fcee7b2e..60d3e386 100644 --- a/eigenlib/Eigen/src/Cholesky/LDLT.h +++ b/eigenlib/Eigen/src/Cholesky/LDLT.h @@ -8,7 +8,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_LDLT_H #define EIGEN_LDLT_H @@ -248,7 +248,7 @@ template class LDLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the factorization failed because of a zero pivot. */ ComputationInfo info() const { @@ -305,7 +305,8 @@ template<> struct ldlt_inplace if (size <= 1) { transpositions.setIdentity(); - if (numext::real(mat.coeff(0,0)) > static_cast(0) ) sign = PositiveSemiDef; + if(size==0) sign = ZeroSign; + else if (numext::real(mat.coeff(0,0)) > static_cast(0) ) sign = PositiveSemiDef; else if (numext::real(mat.coeff(0,0)) < static_cast(0)) sign = NegativeSemiDef; else sign = ZeroSign; return true; @@ -376,6 +377,8 @@ template<> struct ldlt_inplace if((rs>0) && pivot_is_valid) A21 /= realAkk; + else if(rs>0) + ret = ret && (A21.array()==Scalar(0)).all(); if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed else if(!pivot_is_valid) found_zero_pivot = true; @@ -568,13 +571,14 @@ void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) cons // more precisely, use pseudo-inverse of D (see bug 241) using std::abs; const typename Diagonal::RealReturnType vecD(vectorD()); - // In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon - // as motivated by LAPACK's xGELSS: + // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min()) + // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS: // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits::epsilon(),RealScalar(1) / NumTraits::highest()); // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest // diagonal element is not well justified and leads to numerical issues in some cases. // Moreover, Lapack's xSYTRS routines use 0 for the tolerance. - RealScalar tolerance = RealScalar(1) / NumTraits::highest(); + // Using numeric_limits::min() gives us more robustness to denormals. + RealScalar tolerance = (std::numeric_limits::min)(); for (Index i = 0; i < vecD.size(); ++i) { diff --git a/eigenlib/Eigen/src/Cholesky/LLT.h b/eigenlib/Eigen/src/Cholesky/LLT.h index 87ca8d42..9dc23767 100644 --- a/eigenlib/Eigen/src/Cholesky/LLT.h +++ b/eigenlib/Eigen/src/Cholesky/LLT.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_LLT_H #define EIGEN_LLT_H @@ -24,7 +24,7 @@ template struct LLT_Traits; * * \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition * \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. - * The other triangular part won't be read. + * The other triangular part won't be read. * * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite * matrix A such that A = LL^* = U^*U, where L is lower triangular. @@ -41,14 +41,18 @@ template struct LLT_Traits; * Example: \include LLT_example.cpp * Output: \verbinclude LLT_example.out * + * \b Performance: for best performance, it is recommended to use a column-major storage format + * with the Lower triangular part (the default), or, equivalently, a row-major storage format + * with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization + * step, and rank-updates can be up to 3 times slower. + * * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. * + * Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered. + * Therefore, the strict lower part does not have to store correct values. + * * \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT */ - /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) - * Note that during the decomposition, only the upper triangular part of A is considered. Therefore, - * the strict lower part does not have to store correct values. - */ template class LLT { public: @@ -146,7 +150,7 @@ template class LLT } template - void solveInPlace(MatrixBase &bAndX) const; + void solveInPlace(const MatrixBase &bAndX) const; template LLT& compute(const EigenBase& matrix); @@ -177,7 +181,7 @@ template class LLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the matrix.appears not to be positive definite. */ ComputationInfo info() const { @@ -425,7 +429,8 @@ LLT& LLT::compute(const EigenBase eigen_assert(a.rows()==a.cols()); const Index size = a.rows(); m_matrix.resize(size, size); - m_matrix = a.derived(); + if (!internal::is_same_dense(m_matrix, a.derived())) + m_matrix = a.derived(); // Compute matrix L1 norm = max abs column sum. m_l1_norm = RealScalar(0); @@ -485,11 +490,14 @@ void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const * * This version avoids a copy when the right hand side matrix b is not needed anymore. * + * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. + * This function will const_cast it, so constness isn't honored here. + * * \sa LLT::solve(), MatrixBase::llt() */ template template -void LLT::solveInPlace(MatrixBase &bAndX) const +void LLT::solveInPlace(const MatrixBase &bAndX) const { eigen_assert(m_isInitialized && "LLT is not initialized."); eigen_assert(m_matrix.rows()==bAndX.rows()); diff --git a/eigenlib/Eigen/src/CholmodSupport/CholmodSupport.h b/eigenlib/Eigen/src/CholmodSupport/CholmodSupport.h index 57197202..291c3a93 100644 --- a/eigenlib/Eigen/src/CholmodSupport/CholmodSupport.h +++ b/eigenlib/Eigen/src/CholmodSupport/CholmodSupport.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CHOLMODSUPPORT_H #define EIGEN_CHOLMODSUPPORT_H diff --git a/eigenlib/Eigen/src/Core/Array.h b/eigenlib/Eigen/src/Core/Array.h index 0d34269f..5a651310 100644 --- a/eigenlib/Eigen/src/Core/Array.h +++ b/eigenlib/Eigen/src/Core/Array.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ARRAY_H #define EIGEN_ARRAY_H @@ -153,8 +153,6 @@ class Array : Base(std::move(other)) { Base::_check_template_params(); - if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic) - Base::_set_noalias(other); } EIGEN_DEVICE_FUNC Array& operator=(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) @@ -231,10 +229,16 @@ class Array : Base(other) { } + private: + struct PrivateType {}; + public: + /** \sa MatrixBase::operator=(const EigenBase&) */ template EIGEN_DEVICE_FUNC - EIGEN_STRONG_INLINE Array(const EigenBase &other) + EIGEN_STRONG_INLINE Array(const EigenBase &other, + typename internal::enable_if::value, + PrivateType>::type = PrivateType()) : Base(other.derived()) { } diff --git a/eigenlib/Eigen/src/Core/ArrayBase.h b/eigenlib/Eigen/src/Core/ArrayBase.h index f0232f65..e32601b1 100644 --- a/eigenlib/Eigen/src/Core/ArrayBase.h +++ b/eigenlib/Eigen/src/Core/ArrayBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ARRAYBASE_H #define EIGEN_ARRAYBASE_H @@ -153,8 +153,8 @@ template class ArrayBase // inline void evalTo(Dest& dst) const { dst = matrix(); } protected: - EIGEN_DEVICE_FUNC - ArrayBase() : Base() {} + EIGEN_DEFAULT_COPY_CONSTRUCTOR(ArrayBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(ArrayBase) private: explicit ArrayBase(Index); @@ -175,7 +175,7 @@ template class ArrayBase */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator-=(const ArrayBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); @@ -188,7 +188,7 @@ ArrayBase::operator-=(const ArrayBase &other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator+=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -201,7 +201,7 @@ ArrayBase::operator+=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator*=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::mul_assign_op()); @@ -214,7 +214,7 @@ ArrayBase::operator*=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator/=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::div_assign_op()); diff --git a/eigenlib/Eigen/src/Core/ArrayWrapper.h b/eigenlib/Eigen/src/Core/ArrayWrapper.h index a04521a1..e8e84190 100644 --- a/eigenlib/Eigen/src/Core/ArrayWrapper.h +++ b/eigenlib/Eigen/src/Core/ArrayWrapper.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ARRAYWRAPPER_H #define EIGEN_ARRAYWRAPPER_H @@ -32,7 +32,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } @@ -129,7 +130,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } diff --git a/eigenlib/Eigen/src/Core/Assign.h b/eigenlib/Eigen/src/Core/Assign.h index 53806ba3..1bb3af64 100644 --- a/eigenlib/Eigen/src/Core/Assign.h +++ b/eigenlib/Eigen/src/Core/Assign.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ASSIGN_H #define EIGEN_ASSIGN_H diff --git a/eigenlib/Eigen/src/Core/AssignEvaluator.h b/eigenlib/Eigen/src/Core/AssignEvaluator.h index 14400d24..67e28412 100644 --- a/eigenlib/Eigen/src/Core/AssignEvaluator.h +++ b/eigenlib/Eigen/src/Core/AssignEvaluator.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ASSIGN_EVALUATOR_H #define EIGEN_ASSIGN_EVALUATOR_H @@ -39,7 +39,7 @@ public: enum { DstAlignment = DstEvaluator::Alignment, SrcAlignment = SrcEvaluator::Alignment, - DstHasDirectAccess = DstFlags & DirectAccessBit, + DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit, JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment,SrcAlignment) }; @@ -83,7 +83,7 @@ private: && int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0 && (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)), MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit), - MayLinearVectorize = bool(MightVectorize) && MayLinearize && DstHasDirectAccess + MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess) && (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || MaxSizeAtCompileTime == Dynamic), /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, so it's only good for large enough sizes. */ @@ -515,7 +515,7 @@ struct dense_assignment_loop template struct dense_assignment_loop { - EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel) + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel) { typedef typename Kernel::Scalar Scalar; typedef typename Kernel::PacketType PacketType; @@ -563,7 +563,7 @@ struct dense_assignment_loop template struct dense_assignment_loop { - EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel) + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel) { typedef typename Kernel::DstEvaluatorType::XprType DstXprType; typedef typename Kernel::PacketType PacketType; @@ -701,6 +701,26 @@ protected: * Part 5 : Entry point for dense rectangular assignment ***************************************************************************/ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const Functor &/*func*/) +{ + EIGEN_ONLY_USED_FOR_DEBUG(dst); + EIGEN_ONLY_USED_FOR_DEBUG(src); + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); +} + +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const internal::assign_op &/*func*/) +{ + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if(((dst.rows()!=dstRows) || (dst.cols()!=dstCols))) + dst.resize(dstRows, dstCols); + eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols); +} + template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func) { @@ -711,10 +731,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType // NOTE To properly handle A = (A*A.transpose())/s with A rectangular, // we need to resize the destination after the source evaluator has been created. - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + resize_if_allowed(dst, src, func); DstEvaluatorType dstEvaluator(dst); diff --git a/eigenlib/Eigen/src/Core/Assign_MKL.h b/eigenlib/Eigen/src/Core/Assign_MKL.h index 6c2ab926..6866095b 100755 --- a/eigenlib/Eigen/src/Core/Assign_MKL.h +++ b/eigenlib/Eigen/src/Core/Assign_MKL.h @@ -84,7 +84,8 @@ class vml_assign_traits struct Assignment, SrcXprNested>, assign_op, \ Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseUnaryOp, SrcXprNested> SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ if(vml_assign_traits::Traversal==LinearTraversal) { \ VMLOP(dst.size(), (const VMLTYPE*)src.nestedExpression().data(), \ @@ -144,7 +145,8 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _) Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseBinaryOp, SrcXprNested, \ const CwiseNullaryOp,Plain> > SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ VMLTYPE exponent = reinterpret_cast(src.rhs().functor().m_other); \ if(vml_assign_traits::Traversal==LinearTraversal) \ diff --git a/eigenlib/Eigen/src/Core/BandMatrix.h b/eigenlib/Eigen/src/Core/BandMatrix.h index 4978c914..130fa201 100644 --- a/eigenlib/Eigen/src/Core/BandMatrix.h +++ b/eigenlib/Eigen/src/Core/BandMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BANDMATRIX_H #define EIGEN_BANDMATRIX_H diff --git a/eigenlib/Eigen/src/Core/Block.h b/eigenlib/Eigen/src/Core/Block.h index 11de45c2..86028c61 100644 --- a/eigenlib/Eigen/src/Core/Block.h +++ b/eigenlib/Eigen/src/Core/Block.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BLOCK_H #define EIGEN_BLOCK_H diff --git a/eigenlib/Eigen/src/Core/BooleanRedux.h b/eigenlib/Eigen/src/Core/BooleanRedux.h index 8409d874..23287ae0 100644 --- a/eigenlib/Eigen/src/Core/BooleanRedux.h +++ b/eigenlib/Eigen/src/Core/BooleanRedux.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ALLANDANY_H #define EIGEN_ALLANDANY_H diff --git a/eigenlib/Eigen/src/Core/CommaInitializer.h b/eigenlib/Eigen/src/Core/CommaInitializer.h index d218e981..cb89ed2a 100644 --- a/eigenlib/Eigen/src/Core/CommaInitializer.h +++ b/eigenlib/Eigen/src/Core/CommaInitializer.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMMAINITIALIZER_H #define EIGEN_COMMAINITIALIZER_H diff --git a/eigenlib/Eigen/src/Core/ConditionEstimator.h b/eigenlib/Eigen/src/Core/ConditionEstimator.h index aa7efdc7..e93a5568 100644 --- a/eigenlib/Eigen/src/Core/ConditionEstimator.h +++ b/eigenlib/Eigen/src/Core/ConditionEstimator.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CONDITIONESTIMATOR_H #define EIGEN_CONDITIONESTIMATOR_H @@ -37,7 +37,7 @@ struct rcond_compute_sign { * \a matrix that implements .solve() and .adjoint().solve() methods. * * This function implements Algorithms 4.1 and 5.1 from - * http://www.maths.manchester.ac.uk/~higham/narep/narep135.pdf + * xxxp://www.maths.manchester.ac.uk/~higham/narep/narep135.pdf * which also forms the basis for the condition number estimators in * LAPACK. Since at most 10 calls to the solve method of dec are * performed, the total cost is O(dims^2), as opposed to O(dims^3) @@ -160,7 +160,7 @@ rcond_estimate_helper(typename Decomposition::RealScalar matrix_norm, const Deco { typedef typename Decomposition::RealScalar RealScalar; eigen_assert(dec.rows() == dec.cols()); - if (dec.rows() == 0) return RealScalar(1); + if (dec.rows() == 0) return NumTraits::infinity(); if (matrix_norm == RealScalar(0)) return RealScalar(0); if (dec.rows() == 1) return RealScalar(1); const RealScalar inverse_matrix_norm = rcond_invmatrix_L1_norm_estimate(dec); diff --git a/eigenlib/Eigen/src/Core/CoreEvaluators.h b/eigenlib/Eigen/src/Core/CoreEvaluators.h index 1d14af65..3e12ad13 100644 --- a/eigenlib/Eigen/src/Core/CoreEvaluators.h +++ b/eigenlib/Eigen/src/Core/CoreEvaluators.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COREEVALUATORS_H @@ -977,7 +977,7 @@ struct evaluator > OuterStrideAtCompileTime = HasSameStorageOrderAsArgType ? int(outer_stride_at_compile_time::ret) : int(inner_stride_at_compile_time::ret), - MaskPacketAccessBit = (InnerStrideAtCompileTime == 1) ? PacketAccessBit : 0, + MaskPacketAccessBit = (InnerStrideAtCompileTime == 1 || HasSameStorageOrderAsArgType) ? PacketAccessBit : 0, FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator::Flags&LinearAccessBit))) ? LinearAccessBit : 0, FlagsRowMajorBit = XprType::Flags&RowMajorBit, @@ -987,7 +987,9 @@ struct evaluator > Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit, PacketAlignment = unpacket_traits::alignment, - Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, + Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) + && (OuterStrideAtCompileTime!=0) + && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator::Alignment, Alignment0) }; typedef block_evaluator block_evaluator_type; @@ -1018,14 +1020,16 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), - m_startCol(block.startCol()) + m_startCol(block.startCol()), + m_linear_offset(InnerPanel?(XprType::IsRowMajor ? block.startRow()*block.cols() : block.startCol()*block.rows()):0) { } typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; enum { - RowsAtCompileTime = XprType::RowsAtCompileTime + RowsAtCompileTime = XprType::RowsAtCompileTime, + ForwardLinearAccess = InnerPanel && bool(evaluator::Flags&LinearAccessBit) }; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1037,7 +1041,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { - return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeff(m_linear_offset.value() + index); + else + return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1049,7 +1056,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { - return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeffRef(m_linear_offset.value() + index); + else + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template @@ -1063,8 +1073,11 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE PacketType packet(Index index) const { - return packet(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.template packet(m_linear_offset.value() + index); + else + return packet(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); } template @@ -1078,15 +1091,19 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { - return writePacket(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0, - x); + if (ForwardLinearAccess) + return m_argImpl.template writePacket(m_linear_offset.value() + index, x); + else + return writePacket(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, + x); } protected: evaluator m_argImpl; const variable_if_dynamic m_startRow; const variable_if_dynamic m_startCol; + const variable_if_dynamic m_linear_offset; }; // TODO: This evaluator does not actually use the child evaluator; @@ -1556,9 +1573,7 @@ struct evaluator > { } typedef typename XprType::Scalar Scalar; - // FIXME having to check whether ArgType is sparse here i not very nice. - typedef typename internal::conditional::value, - typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType; + typedef typename XprType::CoeffReturnType CoeffReturnType; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index) const diff --git a/eigenlib/Eigen/src/Core/CoreIterators.h b/eigenlib/Eigen/src/Core/CoreIterators.h index 4eb42b93..5b20e935 100644 --- a/eigenlib/Eigen/src/Core/CoreIterators.h +++ b/eigenlib/Eigen/src/Core/CoreIterators.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COREITERATORS_H #define EIGEN_COREITERATORS_H diff --git a/eigenlib/Eigen/src/Core/CwiseBinaryOp.h b/eigenlib/Eigen/src/Core/CwiseBinaryOp.h index a36765e3..6348a7f0 100644 --- a/eigenlib/Eigen/src/Core/CwiseBinaryOp.h +++ b/eigenlib/Eigen/src/Core/CwiseBinaryOp.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CWISE_BINARY_OP_H #define EIGEN_CWISE_BINARY_OP_H diff --git a/eigenlib/Eigen/src/Core/CwiseNullaryOp.h b/eigenlib/Eigen/src/Core/CwiseNullaryOp.h index dd498f75..98a6385a 100644 --- a/eigenlib/Eigen/src/Core/CwiseNullaryOp.h +++ b/eigenlib/Eigen/src/Core/CwiseNullaryOp.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CWISE_NULLARY_OP_H #define EIGEN_CWISE_NULLARY_OP_H @@ -105,7 +105,7 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func) { return CwiseNullaryOp(rows, cols, func); @@ -150,7 +150,7 @@ DenseBase::NullaryExpr(Index size, const CustomNullaryOp& func) */ template template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(const CustomNullaryOp& func) { return CwiseNullaryOp(RowsAtCompileTime, ColsAtCompileTime, func); @@ -192,7 +192,7 @@ DenseBase::Constant(Index rows, Index cols, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(Index size, const Scalar& value) { return DenseBase::NullaryExpr(size, internal::scalar_constant_op(value)); @@ -208,7 +208,7 @@ DenseBase::Constant(Index size, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(const Scalar& value) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -220,7 +220,7 @@ DenseBase::Constant(const Scalar& value) * \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -232,7 +232,7 @@ DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const * \sa LinSpaced(Scalar,Scalar) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -264,7 +264,7 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -276,7 +276,7 @@ DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) * Special version for fixed size types which does not require the size parameter. */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -286,7 +286,7 @@ DenseBase::LinSpaced(const Scalar& low, const Scalar& high) /** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */ template -bool DenseBase::isApproxToConstant +EIGEN_DEVICE_FUNC bool DenseBase::isApproxToConstant (const Scalar& val, const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); @@ -301,7 +301,7 @@ bool DenseBase::isApproxToConstant * * \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ template -bool DenseBase::isConstant +EIGEN_DEVICE_FUNC bool DenseBase::isConstant (const Scalar& val, const RealScalar& prec) const { return isApproxToConstant(val, prec); @@ -312,7 +312,7 @@ bool DenseBase::isConstant * \sa setConstant(), Constant(), class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) { setConstant(val); } @@ -322,7 +322,7 @@ EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) { return derived() = Constant(rows(), cols(), val); } @@ -337,7 +337,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index size, const Scalar& val) { resize(size); @@ -356,7 +356,7 @@ PlainObjectBase::setConstant(Index size, const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) { resize(rows, cols); @@ -380,7 +380,7 @@ PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) * \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op(low,high,newSize)); @@ -400,7 +400,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, con * \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return setLinSpaced(size(), low, high); @@ -423,7 +423,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, * \sa Zero(), Zero(Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index rows, Index cols) { return Constant(rows, cols, Scalar(0)); @@ -446,7 +446,7 @@ DenseBase::Zero(Index rows, Index cols) * \sa Zero(), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index size) { return Constant(size, Scalar(0)); @@ -463,7 +463,7 @@ DenseBase::Zero(Index size) * \sa Zero(Index), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero() { return Constant(Scalar(0)); @@ -478,7 +478,7 @@ DenseBase::Zero() * \sa class CwiseNullaryOp, Zero() */ template -bool DenseBase::isZero(const RealScalar& prec) const +EIGEN_DEVICE_FUNC bool DenseBase::isZero(const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); for(Index j = 0; j < cols(); ++j) @@ -496,7 +496,7 @@ bool DenseBase::isZero(const RealScalar& prec) const * \sa class CwiseNullaryOp, Zero() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setZero() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setZero() { return setConstant(Scalar(0)); } @@ -511,7 +511,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setZero() * \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index newSize) { resize(newSize); @@ -529,7 +529,7 @@ PlainObjectBase::setZero(Index newSize) * \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index rows, Index cols) { resize(rows, cols); @@ -553,7 +553,7 @@ PlainObjectBase::setZero(Index rows, Index cols) * \sa Ones(), Ones(Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index rows, Index cols) { return Constant(rows, cols, Scalar(1)); @@ -576,7 +576,7 @@ DenseBase::Ones(Index rows, Index cols) * \sa Ones(), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index newSize) { return Constant(newSize, Scalar(1)); @@ -593,7 +593,7 @@ DenseBase::Ones(Index newSize) * \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones() { return Constant(Scalar(1)); @@ -608,7 +608,7 @@ DenseBase::Ones() * \sa class CwiseNullaryOp, Ones() */ template -bool DenseBase::isOnes +EIGEN_DEVICE_FUNC bool DenseBase::isOnes (const RealScalar& prec) const { return isApproxToConstant(Scalar(1), prec); @@ -622,7 +622,7 @@ bool DenseBase::isOnes * \sa class CwiseNullaryOp, Ones() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() { return setConstant(Scalar(1)); } @@ -637,7 +637,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() * \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index newSize) { resize(newSize); @@ -655,7 +655,7 @@ PlainObjectBase::setOnes(Index newSize) * \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index rows, Index cols) { resize(rows, cols); @@ -679,7 +679,7 @@ PlainObjectBase::setOnes(Index rows, Index cols) * \sa Identity(), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity(Index rows, Index cols) { return DenseBase::NullaryExpr(rows, cols, internal::scalar_identity_op()); @@ -696,7 +696,7 @@ MatrixBase::Identity(Index rows, Index cols) * \sa Identity(Index,Index), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity() { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -771,7 +771,7 @@ struct setIdentity_impl * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() { return internal::setIdentity_impl::run(derived()); } @@ -787,7 +787,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) { derived().resize(rows, cols); return setIdentity(); @@ -800,7 +800,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i); @@ -815,7 +815,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(),i); @@ -828,7 +828,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() { return Derived::Unit(0); } /** \returns an expression of the Y axis unit vector (0,1{,0}^*) @@ -838,7 +838,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() { return Derived::Unit(1); } /** \returns an expression of the Z axis unit vector (0,0,1{,0}^*) @@ -848,7 +848,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() { return Derived::Unit(2); } /** \returns an expression of the W axis unit vector (0,0,0,1) @@ -858,7 +858,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() { return Derived::Unit(3); } } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/CwiseTernaryOp.h b/eigenlib/Eigen/src/Core/CwiseTernaryOp.h index 9f3576fe..fef6e3c2 100644 --- a/eigenlib/Eigen/src/Core/CwiseTernaryOp.h +++ b/eigenlib/Eigen/src/Core/CwiseTernaryOp.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CWISE_TERNARY_OP_H #define EIGEN_CWISE_TERNARY_OP_H diff --git a/eigenlib/Eigen/src/Core/CwiseUnaryOp.h b/eigenlib/Eigen/src/Core/CwiseUnaryOp.h index 1d2dd19f..269b139c 100644 --- a/eigenlib/Eigen/src/Core/CwiseUnaryOp.h +++ b/eigenlib/Eigen/src/Core/CwiseUnaryOp.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CWISE_UNARY_OP_H #define EIGEN_CWISE_UNARY_OP_H diff --git a/eigenlib/Eigen/src/Core/CwiseUnaryView.h b/eigenlib/Eigen/src/Core/CwiseUnaryView.h index 27103305..ab165ebe 100644 --- a/eigenlib/Eigen/src/Core/CwiseUnaryView.h +++ b/eigenlib/Eigen/src/Core/CwiseUnaryView.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CWISE_UNARY_VIEW_H #define EIGEN_CWISE_UNARY_VIEW_H @@ -121,6 +121,8 @@ class CwiseUnaryViewImpl { return derived().nestedExpression().outerStride() * sizeof(typename internal::traits::Scalar) / sizeof(Scalar); } + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(CwiseUnaryViewImpl) }; } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/DenseBase.h b/eigenlib/Eigen/src/Core/DenseBase.h index bd74e8a1..c568378e 100644 --- a/eigenlib/Eigen/src/Core/DenseBase.h +++ b/eigenlib/Eigen/src/Core/DenseBase.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DENSEBASE_H #define EIGEN_DENSEBASE_H @@ -40,7 +40,7 @@ static inline void check_DenseIndex_is_signed() { */ template class DenseBase #ifndef EIGEN_PARSED_BY_DOXYGEN - : public DenseCoeffsBase + : public DenseCoeffsBase::value> #else : public DenseCoeffsBase #endif // not EIGEN_PARSED_BY_DOXYGEN @@ -71,7 +71,7 @@ template class DenseBase typedef Scalar value_type; typedef typename NumTraits::Real RealScalar; - typedef DenseCoeffsBase Base; + typedef DenseCoeffsBase::value> Base; using Base::derived; using Base::const_cast_derived; @@ -296,7 +296,7 @@ template class DenseBase EIGEN_DEVICE_FUNC Derived& operator=(const ReturnByValue& func); - /** \ínternal + /** \internal * Copies \a other into *this without evaluating other. \returns a reference to *this. * \deprecated */ template @@ -463,7 +463,17 @@ template class DenseBase EIGEN_DEVICE_FUNC void visit(Visitor& func) const; - inline const WithFormat format(const IOFormat& fmt) const; + /** \returns a WithFormat proxy object allowing to print a matrix the with given + * format \a fmt. + * + * See class IOFormat for some examples. + * + * \sa class IOFormat, class WithFormat + */ + inline const WithFormat format(const IOFormat& fmt) const + { + return WithFormat(derived(), fmt); + } /** \returns the unique coefficient of a 1x1 expression */ EIGEN_DEVICE_FUNC @@ -474,9 +484,9 @@ template class DenseBase return derived().coeff(0,0); } - bool all() const; - bool any() const; - Index count() const; + EIGEN_DEVICE_FUNC bool all() const; + EIGEN_DEVICE_FUNC bool any() const; + EIGEN_DEVICE_FUNC Index count() const; typedef VectorwiseOp RowwiseReturnType; typedef const VectorwiseOp ConstRowwiseReturnType; @@ -577,11 +587,12 @@ template class DenseBase } protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(DenseBase) /** Default constructor. Do nothing. */ EIGEN_DEVICE_FUNC DenseBase() { /* Just checks for self-consistency of the flags. - * Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down + * Only do it when debugging Eigen, as this borders on paranoia and could slow compilation down */ #ifdef EIGEN_INTERNAL_DEBUGGING EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor)) diff --git a/eigenlib/Eigen/src/Core/DenseCoeffsBase.h b/eigenlib/Eigen/src/Core/DenseCoeffsBase.h index c4af48ab..50269426 100644 --- a/eigenlib/Eigen/src/Core/DenseCoeffsBase.h +++ b/eigenlib/Eigen/src/Core/DenseCoeffsBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DENSECOEFFSBASE_H #define EIGEN_DENSECOEFFSBASE_H diff --git a/eigenlib/Eigen/src/Core/DenseStorage.h b/eigenlib/Eigen/src/Core/DenseStorage.h index 82201d96..191be539 100644 --- a/eigenlib/Eigen/src/Core/DenseStorage.h +++ b/eigenlib/Eigen/src/Core/DenseStorage.h @@ -7,15 +7,15 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATRIXSTORAGE_H #define EIGEN_MATRIXSTORAGE_H #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN; + #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) X; EIGEN_DENSE_STORAGE_CTOR_PLUGIN; #else - #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) #endif namespace Eigen { @@ -62,20 +62,20 @@ struct plain_array #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) #elif EIGEN_GNUC_AT_LEAST(4,7) // GCC 4.7 is too aggressive in its optimizations and remove the alignement test based on the fact the array is declared to be aligned. - // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900 + // See this bug report: xxxp://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900 // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined: template EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; } #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \ eigen_assert((internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (sizemask)) == 0 \ && "this assertion is explained here: " \ - "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ + "xxxp://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ " **** READ THIS WEB PAGE !!! ****"); #else #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \ eigen_assert((internal::UIntPtr(array) & (sizemask)) == 0 \ && "this assertion is explained here: " \ - "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ + "xxxp://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \ " **** READ THIS WEB PAGE !!! ****"); #endif @@ -184,12 +184,16 @@ template class DenseSt { internal::plain_array m_data; public: - EIGEN_DEVICE_FUNC DenseStorage() {} + EIGEN_DEVICE_FUNC DenseStorage() { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(internal::constructor_without_unaligned_array_assert()) {} EIGEN_DEVICE_FUNC - DenseStorage(const DenseStorage& other) : m_data(other.m_data) {} + DenseStorage(const DenseStorage& other) : m_data(other.m_data) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size) + } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) { @@ -197,7 +201,7 @@ template class DenseSt return *this; } EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols); EIGEN_UNUSED_VARIABLE(size); EIGEN_UNUSED_VARIABLE(rows); @@ -343,7 +347,7 @@ template class DenseStorage(size)), m_rows(rows), m_cols(cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows>=0 && cols >=0); } EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) @@ -351,6 +355,7 @@ template class DenseStorage class DenseStorage(m_data, m_rows*m_cols); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_rows = rows; m_cols = cols; @@ -422,7 +427,7 @@ template class DenseStorage(size)), m_cols(cols) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows==_Rows && cols >=0); EIGEN_UNUSED_VARIABLE(rows); } @@ -430,6 +435,7 @@ template class DenseStorage(_Rows*other.m_cols)) , m_cols(other.m_cols) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_cols*_Rows) internal::smart_copy(other.m_data, other.m_data+_Rows*m_cols, m_data); } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) @@ -473,11 +479,11 @@ template class DenseStorage(m_data, _Rows*m_cols); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_cols = cols; } @@ -495,7 +501,7 @@ template class DenseStorage(size)), m_rows(rows) { - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows>=0 && cols == _Cols); EIGEN_UNUSED_VARIABLE(cols); } @@ -503,6 +509,7 @@ template class DenseStorage(other.m_rows*_Cols)) , m_rows(other.m_rows) { + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*_Cols) internal::smart_copy(other.m_data, other.m_data+other.m_rows*_Cols, m_data); } EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other) @@ -546,11 +553,11 @@ template class DenseStorage(m_data, _Cols*m_rows); - if (size) + if (size>0) // >0 and not simply !=0 to let the compiler knows that size cannot be negative m_data = internal::conditional_aligned_new_auto(size); else m_data = 0; - EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN + EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) } m_rows = rows; } diff --git a/eigenlib/Eigen/src/Core/Diagonal.h b/eigenlib/Eigen/src/Core/Diagonal.h index bfea0584..0eb8d458 100644 --- a/eigenlib/Eigen/src/Core/Diagonal.h +++ b/eigenlib/Eigen/src/Core/Diagonal.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DIAGONAL_H #define EIGEN_DIAGONAL_H @@ -21,7 +21,7 @@ namespace Eigen { * \param MatrixType the type of the object in which we are taking a sub/main/super diagonal * \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal. * A positive value means a superdiagonal, a negative value means a subdiagonal. - * You can also use Dynamic so the index can be set at runtime. + * You can also use DynamicIndex so the index can be set at runtime. * * The matrix is not required to be square. * @@ -70,7 +70,10 @@ template class Diagonal EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) EIGEN_DEVICE_FUNC - explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {} + explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) + { + eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() ); + } EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) diff --git a/eigenlib/Eigen/src/Core/DiagonalMatrix.h b/eigenlib/Eigen/src/Core/DiagonalMatrix.h index ecfdce8e..98a2eac7 100644 --- a/eigenlib/Eigen/src/Core/DiagonalMatrix.h +++ b/eigenlib/Eigen/src/Core/DiagonalMatrix.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DIAGONALMATRIX_H #define EIGEN_DIAGONALMATRIX_H diff --git a/eigenlib/Eigen/src/Core/DiagonalProduct.h b/eigenlib/Eigen/src/Core/DiagonalProduct.h index d372b938..aead5fec 100644 --- a/eigenlib/Eigen/src/Core/DiagonalProduct.h +++ b/eigenlib/Eigen/src/Core/DiagonalProduct.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DIAGONALPRODUCT_H #define EIGEN_DIAGONALPRODUCT_H diff --git a/eigenlib/Eigen/src/Core/Dot.h b/eigenlib/Eigen/src/Core/Dot.h index 06ef18b8..d170aa09 100644 --- a/eigenlib/Eigen/src/Core/Dot.h +++ b/eigenlib/Eigen/src/Core/Dot.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DOT_H #define EIGEN_DOT_H @@ -31,7 +31,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.template binaryExpr(b).sum(); } @@ -43,7 +44,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.transpose().template binaryExpr(b).sum(); } @@ -65,6 +67,7 @@ struct dot_nocheck template template EIGEN_DEVICE_FUNC +EIGEN_STRONG_INLINE typename ScalarBinaryOpTraits::Scalar,typename internal::traits::Scalar>::ReturnType MatrixBase::dot(const MatrixBase& other) const { @@ -102,7 +105,7 @@ EIGEN_STRONG_INLINE typename NumTraits::Scala * \sa lpNorm(), dot(), squaredNorm() */ template -inline typename NumTraits::Scalar>::Real MatrixBase::norm() const +EIGEN_STRONG_INLINE typename NumTraits::Scalar>::Real MatrixBase::norm() const { return numext::sqrt(squaredNorm()); } @@ -117,7 +120,7 @@ inline typename NumTraits::Scalar>::Real Matr * \sa norm(), normalize() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::normalized() const { typedef typename internal::nested_eval::type _Nested; @@ -139,7 +142,7 @@ MatrixBase::normalized() const * \sa norm(), normalized() */ template -inline void MatrixBase::normalize() +EIGEN_STRONG_INLINE void MatrixBase::normalize() { RealScalar z = squaredNorm(); // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU @@ -160,7 +163,7 @@ inline void MatrixBase::normalize() * \sa stableNorm(), stableNormalize(), normalized() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::stableNormalized() const { typedef typename internal::nested_eval::type _Nested; @@ -185,7 +188,7 @@ MatrixBase::stableNormalized() const * \sa stableNorm(), stableNormalized(), normalize() */ template -inline void MatrixBase::stableNormalize() +EIGEN_STRONG_INLINE void MatrixBase::stableNormalize() { RealScalar w = cwiseAbs().maxCoeff(); RealScalar z = (derived()/w).squaredNorm(); @@ -250,7 +253,7 @@ struct lpNorm_selector * * In all cases, if \c *this is empty, then the value 0 is returned. * - * \note For matrices, this function does not compute the operator-norm. That is, if \c *this is a matrix, then its coefficients are interpreted as a 1D vector. Nonetheless, you can easily compute the 1-norm and \f$\infty\f$-norm matrix operator norms using \link TutorialReductionsVisitorsBroadcastingReductionsNorm partial reductions \endlink. + * \note For matrices, this function does not compute the operator-norm. That is, if \c *this is a matrix, then its coefficients are interpreted as a 1D vector. Nonetheless, you can easily compute the 1-norm and \f$\infty\f$-norm matrix operator norms using \link TutorialReductionsVisitorsBroadcastingReductionsNorm partial reductions \endlink. * * \sa norm() */ diff --git a/eigenlib/Eigen/src/Core/EigenBase.h b/eigenlib/Eigen/src/Core/EigenBase.h index f76995af..f1e4f685 100644 --- a/eigenlib/Eigen/src/Core/EigenBase.h +++ b/eigenlib/Eigen/src/Core/EigenBase.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_EIGENBASE_H #define EIGEN_EIGENBASE_H @@ -14,6 +14,7 @@ namespace Eigen { /** \class EigenBase + * \ingroup Core_Module * * Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T). * @@ -128,6 +129,7 @@ template struct EigenBase */ template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator=(const EigenBase &other) { call_assignment(derived(), other.derived()); @@ -136,6 +138,7 @@ Derived& DenseBase::operator=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator+=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -144,6 +147,7 @@ Derived& DenseBase::operator+=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator-=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); diff --git a/eigenlib/Eigen/src/Core/ForceAlignedAccess.h b/eigenlib/Eigen/src/Core/ForceAlignedAccess.h index 7b08b45e..d1669b75 100644 --- a/eigenlib/Eigen/src/Core/ForceAlignedAccess.h +++ b/eigenlib/Eigen/src/Core/ForceAlignedAccess.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_FORCEALIGNEDACCESS_H #define EIGEN_FORCEALIGNEDACCESS_H diff --git a/eigenlib/Eigen/src/Core/Fuzzy.h b/eigenlib/Eigen/src/Core/Fuzzy.h index 3e403a09..c5904f6b 100644 --- a/eigenlib/Eigen/src/Core/Fuzzy.h +++ b/eigenlib/Eigen/src/Core/Fuzzy.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_FUZZY_H #define EIGEN_FUZZY_H diff --git a/eigenlib/Eigen/src/Core/GeneralProduct.h b/eigenlib/Eigen/src/Core/GeneralProduct.h index 0f16cd8e..61401c96 100644 --- a/eigenlib/Eigen/src/Core/GeneralProduct.h +++ b/eigenlib/Eigen/src/Core/GeneralProduct.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERAL_PRODUCT_H #define EIGEN_GENERAL_PRODUCT_H @@ -24,12 +24,17 @@ template struct product_type_selector; template struct product_size_category { - enum { is_large = MaxSize == Dynamic || - Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || - (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), - value = is_large ? Large - : Size == 1 ? 1 - : Small + enum { + #ifndef EIGEN_CUDA_ARCH + is_large = MaxSize == Dynamic || + Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || + (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), + #else + is_large = 0, + #endif + value = is_large ? Large + : Size == 1 ? 1 + : Small }; }; @@ -379,8 +384,6 @@ template<> struct gemv_dense_selector * * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() */ -#ifndef __CUDACC__ - template template inline const Product @@ -412,8 +415,6 @@ MatrixBase::operator*(const MatrixBase &other) const return Product(derived(), other.derived()); } -#endif // __CUDACC__ - /** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. * * The returned product will behave like any other expressions: the coefficients of the product will be diff --git a/eigenlib/Eigen/src/Core/GenericPacketMath.h b/eigenlib/Eigen/src/Core/GenericPacketMath.h index 27033a2d..e7f1b283 100644 --- a/eigenlib/Eigen/src/Core/GenericPacketMath.h +++ b/eigenlib/Eigen/src/Core/GenericPacketMath.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERIC_PACKET_MATH_H #define EIGEN_GENERIC_PACKET_MATH_H @@ -230,7 +230,7 @@ pload1(const typename unpacket_traits::type *a) { return pset1( * duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]} * Currently, this function is only used for scalar * complex products. */ -template EIGEN_DEVICE_FUNC inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet ploaddup(const typename unpacket_traits::type* from) { return *from; } /** \internal \returns a packet with elements of \a *from quadrupled. @@ -278,7 +278,7 @@ inline void pbroadcast2(const typename unpacket_traits::type *a, } /** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */ -template inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_traits::type& a) { return a; } /** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */ @@ -351,10 +351,7 @@ template EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& /** \internal \returns \a a with real and imaginary part flipped (for complex type only) */ template EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet& a) { - // FIXME: uncomment the following in case we drop the internal imag and real functions. -// using std::imag; -// using std::real; - return Packet(imag(a),real(a)); + return Packet(a.imag(),a.real()); } /************************** @@ -482,7 +479,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& fro * by the current computation. */ template -inline Packet ploadt_ro(const typename unpacket_traits::type* from) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits::type* from) { return ploadt(from); } @@ -524,10 +521,10 @@ inline void palign(PacketType& first, const PacketType& second) #ifndef __CUDACC__ template<> inline std::complex pmul(const std::complex& a, const std::complex& b) -{ return std::complex(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } +{ return std::complex(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); } template<> inline std::complex pmul(const std::complex& a, const std::complex& b) -{ return std::complex(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); } +{ return std::complex(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); } #endif diff --git a/eigenlib/Eigen/src/Core/GlobalFunctions.h b/eigenlib/Eigen/src/Core/GlobalFunctions.h index 769dc255..ed9ea125 100644 --- a/eigenlib/Eigen/src/Core/GlobalFunctions.h +++ b/eigenlib/Eigen/src/Core/GlobalFunctions.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GLOBAL_FUNCTIONS_H #define EIGEN_GLOBAL_FUNCTIONS_H diff --git a/eigenlib/Eigen/src/Core/IO.h b/eigenlib/Eigen/src/Core/IO.h index 644228c3..ec72a1c5 100644 --- a/eigenlib/Eigen/src/Core/IO.h +++ b/eigenlib/Eigen/src/Core/IO.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_IO_H #define EIGEN_IO_H @@ -109,20 +109,6 @@ class WithFormat IOFormat m_format; }; -/** \returns a WithFormat proxy object allowing to print a matrix the with given - * format \a fmt. - * - * See class IOFormat for some examples. - * - * \sa class IOFormat, class WithFormat - */ -template -inline const WithFormat -DenseBase::format(const IOFormat& fmt) const -{ - return WithFormat(derived(), fmt); -} - namespace internal { // NOTE: This helper is kept for backward compatibility with previous code specializing diff --git a/eigenlib/Eigen/src/Core/Inverse.h b/eigenlib/Eigen/src/Core/Inverse.h index b76f0439..0f0787cf 100644 --- a/eigenlib/Eigen/src/Core/Inverse.h +++ b/eigenlib/Eigen/src/Core/Inverse.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_INVERSE_H #define EIGEN_INVERSE_H diff --git a/eigenlib/Eigen/src/Core/Map.h b/eigenlib/Eigen/src/Core/Map.h index 06d19670..166b61cc 100644 --- a/eigenlib/Eigen/src/Core/Map.h +++ b/eigenlib/Eigen/src/Core/Map.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MAP_H #define EIGEN_MAP_H @@ -20,11 +20,17 @@ struct traits > { typedef traits TraitsBase; enum { + PlainObjectTypeInnerSize = ((traits::Flags&RowMajorBit)==RowMajorBit) + ? PlainObjectType::ColsAtCompileTime + : PlainObjectType::RowsAtCompileTime, + InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 ? int(PlainObjectType::InnerStrideAtCompileTime) : int(StrideType::InnerStrideAtCompileTime), OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 - ? int(PlainObjectType::OuterStrideAtCompileTime) + ? (InnerStrideAtCompileTime==Dynamic || PlainObjectTypeInnerSize==Dynamic + ? Dynamic + : int(InnerStrideAtCompileTime) * int(PlainObjectTypeInnerSize)) : int(StrideType::OuterStrideAtCompileTime), Alignment = int(MapOptions)&int(AlignedMask), Flags0 = TraitsBase::Flags & (~NestByRefBit), @@ -107,10 +113,11 @@ template class Ma EIGEN_DEVICE_FUNC inline Index outerStride() const { - return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() - : IsVectorAtCompileTime ? this->size() - : int(Flags)&RowMajorBit ? this->cols() - : this->rows(); + return int(StrideType::OuterStrideAtCompileTime) != 0 ? m_stride.outer() + : int(internal::traits::OuterStrideAtCompileTime) != Dynamic ? Index(internal::traits::OuterStrideAtCompileTime) + : IsVectorAtCompileTime ? (this->size() * innerStride()) + : (int(Flags)&RowMajorBit) ? (this->cols() * innerStride()) + : (this->rows() * innerStride()); } /** Constructor in the fixed-size case. diff --git a/eigenlib/Eigen/src/Core/MapBase.h b/eigenlib/Eigen/src/Core/MapBase.h index 020f939a..af003116 100644 --- a/eigenlib/Eigen/src/Core/MapBase.h +++ b/eigenlib/Eigen/src/Core/MapBase.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MAPBASE_H #define EIGEN_MAPBASE_H @@ -43,6 +43,7 @@ template class MapBase enum { RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime, + InnerStrideAtCompileTime = internal::traits::InnerStrideAtCompileTime, SizeAtCompileTime = Base::SizeAtCompileTime }; @@ -181,14 +182,19 @@ template class MapBase #endif protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) template EIGEN_DEVICE_FUNC void checkSanity(typename internal::enable_if<(internal::traits::Alignment>0),void*>::type = 0) const { #if EIGEN_MAX_ALIGN_BYTES>0 + // innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible value: + const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime); + EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride); eigen_assert(( ((internal::UIntPtr(m_data) % internal::traits::Alignment) == 0) - || (cols() * rows() * innerStride() * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); + || (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); #endif } @@ -290,6 +296,9 @@ template class MapBase // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base, // see bugs 821 and 920. using ReadOnlyMapBase::Base::operator=; + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) }; #undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS diff --git a/eigenlib/Eigen/src/Core/MathFunctions.h b/eigenlib/Eigen/src/Core/MathFunctions.h index 8d47fb8a..c262ede9 100644 --- a/eigenlib/Eigen/src/Core/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/MathFunctions.h @@ -5,12 +5,12 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATHFUNCTIONS_H #define EIGEN_MATHFUNCTIONS_H -// source: http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html +// source: xxxp://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html // TODO this should better be moved to NumTraits #define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406L @@ -287,7 +287,7 @@ struct abs2_impl_default // IsComplex EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { - return real(x)*real(x) + imag(x)*imag(x); + return x.real()*x.real() + x.imag()*x.imag(); } }; @@ -313,14 +313,17 @@ struct abs2_retval ****************************************************************************/ template -struct norm1_default_impl +struct norm1_default_impl; + +template +struct norm1_default_impl { typedef typename NumTraits::Real RealScalar; EIGEN_DEVICE_FUNC static inline RealScalar run(const Scalar& x) { EIGEN_USING_STD_MATH(abs); - return abs(real(x)) + abs(imag(x)); + return abs(x.real()) + abs(x.imag()); } }; @@ -348,31 +351,7 @@ struct norm1_retval * Implementation of hypot * ****************************************************************************/ -template -struct hypot_impl -{ - typedef typename NumTraits::Real RealScalar; - static inline RealScalar run(const Scalar& x, const Scalar& y) - { - EIGEN_USING_STD_MATH(abs); - EIGEN_USING_STD_MATH(sqrt); - RealScalar _x = abs(x); - RealScalar _y = abs(y); - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - if(p==RealScalar(0)) return RealScalar(0); - return p * sqrt(RealScalar(1) + qp*qp); - } -}; +template struct hypot_impl; template struct hypot_retval @@ -495,7 +474,7 @@ namespace std_fallback { typedef typename NumTraits::Real RealScalar; EIGEN_USING_STD_MATH(log); Scalar x1p = RealScalar(1) + x; - return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); + return numext::equal_strict(x1p, Scalar(1)) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); } } @@ -640,21 +619,28 @@ template struct random_default_impl { static inline Scalar run(const Scalar& x, const Scalar& y) - { - typedef typename conditional::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX; - if(y=x the result converted to an unsigned long is still correct. - std::size_t range = ScalarX(y)-ScalarX(x); - std::size_t offset = 0; - // rejection sampling - std::size_t divisor = 1; - std::size_t multiplier = 1; - if(range::type ScalarU; + // ScalarX is the widest of ScalarU and unsigned int. + // We'll deal only with ScalarX and unsigned int below thus avoiding signed + // types and arithmetic and signed overflows (which are undefined behavior). + typedef typename conditional<(ScalarU(-1) > unsigned(-1)), ScalarU, unsigned>::type ScalarX; + // The following difference doesn't overflow, provided our integer types are two's + // complement and have the same number of padding bits in signed and unsigned variants. + // This is the case in most modern implementations of C++. + ScalarX range = ScalarX(y) - ScalarX(x); + ScalarX offset = 0; + ScalarX divisor = 1; + ScalarX multiplier = 1; + const unsigned rand_max = RAND_MAX; + if (range <= rand_max) divisor = (rand_max + 1) / (range + 1); + else multiplier = 1 + range / (rand_max + 1); + // Rejection sampling. do { - offset = (std::size_t(std::rand()) * multiplier) / divisor; + offset = (unsigned(std::rand()) * multiplier) / divisor; } while (offset > range); return Scalar(ScalarX(x) + offset); } @@ -679,8 +665,8 @@ struct random_default_impl { static inline Scalar run(const Scalar& x, const Scalar& y) { - return Scalar(random(real(x), real(y)), - random(imag(x), imag(y))); + return Scalar(random(x.real(), y.real()), + random(x.imag(), y.imag())); } static inline Scalar run() { @@ -933,6 +919,9 @@ inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); } +EIGEN_DEVICE_FUNC +inline bool abs2(bool x) { return x; } + template EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) @@ -1030,7 +1019,8 @@ inline int log2(int x) /** \returns the square root of \a x. * - * It is essentially equivalent to \code using std::sqrt; return sqrt(x); \endcode, + * It is essentially equivalent to + * \code using std::sqrt; return sqrt(x); \endcode * but slightly faster for float/double and some compilers (e.g., gcc), thanks to * specializations when SSE is enabled. * @@ -1061,11 +1051,24 @@ double log(const double &x) { return ::log(x); } template EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE -typename NumTraits::Real abs(const T &x) { +typename internal::enable_if::IsSigned || NumTraits::IsComplex,typename NumTraits::Real>::type +abs(const T &x) { EIGEN_USING_STD_MATH(abs); return abs(x); } +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE +typename internal::enable_if::IsSigned || NumTraits::IsComplex),typename NumTraits::Real>::type +abs(const T &x) { + return x; +} + +#if defined(__SYCL_DEVICE_ONLY__) +EIGEN_ALWAYS_INLINE float abs(float x) { return cl::sycl::fabs(x); } +EIGEN_ALWAYS_INLINE double abs(double x) { return cl::sycl::fabs(x); } +#endif // defined(__SYCL_DEVICE_ONLY__) + #ifdef __CUDACC__ template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float abs(const float &x) { return ::fabsf(x); } diff --git a/eigenlib/Eigen/src/Core/MathFunctionsImpl.h b/eigenlib/Eigen/src/Core/MathFunctionsImpl.h index 3c9ef22f..42da1d6d 100644 --- a/eigenlib/Eigen/src/Core/MathFunctionsImpl.h +++ b/eigenlib/Eigen/src/Core/MathFunctionsImpl.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATHFUNCTIONSIMPL_H #define EIGEN_MATHFUNCTIONSIMPL_H @@ -33,7 +33,7 @@ T generic_fast_tanh_float(const T& a_x) // step such that if a_x is nan, x will be either 9 or -9, // and tanh will return 1 or -1 instead of nan. // This is supposed to be fixed in gcc6.3, - // see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72867 + // see: xxxps://gcc.gnu.org/bugzilla/show_bug.cgi?id=72867 const T x = pmax(minus_9,pmin(plus_9,a_x)); // The monomial coefficients of the numerator polynomial (odd). const T alpha_1 = pset1(4.89352455891786e-03f); @@ -71,6 +71,29 @@ T generic_fast_tanh_float(const T& a_x) return pdiv(p, q); } +template +EIGEN_STRONG_INLINE +RealScalar positive_real_hypot(const RealScalar& x, const RealScalar& y) +{ + EIGEN_USING_STD_MATH(sqrt); + RealScalar p, qp; + p = numext::maxi(x,y); + if(p==RealScalar(0)) return RealScalar(0); + qp = numext::mini(y,x) / p; + return p * sqrt(RealScalar(1) + qp*qp); +} + +template +struct hypot_impl +{ + typedef typename NumTraits::Real RealScalar; + static inline RealScalar run(const Scalar& x, const Scalar& y) + { + EIGEN_USING_STD_MATH(abs); + return positive_real_hypot(abs(x), abs(y)); + } +}; + } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/Matrix.h b/eigenlib/Eigen/src/Core/Matrix.h index 90c336d8..b66a3958 100644 --- a/eigenlib/Eigen/src/Core/Matrix.h +++ b/eigenlib/Eigen/src/Core/Matrix.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATRIX_H #define EIGEN_MATRIX_H @@ -274,8 +274,6 @@ class Matrix : Base(std::move(other)) { Base::_check_template_params(); - if (RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic) - Base::_set_noalias(other); } EIGEN_DEVICE_FUNC Matrix& operator=(Matrix&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) diff --git a/eigenlib/Eigen/src/Core/MatrixBase.h b/eigenlib/Eigen/src/Core/MatrixBase.h index f7cf04cd..8c5b93fc 100644 --- a/eigenlib/Eigen/src/Core/MatrixBase.h +++ b/eigenlib/Eigen/src/Core/MatrixBase.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATRIXBASE_H #define EIGEN_MATRIXBASE_H @@ -160,20 +160,11 @@ template class MatrixBase EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const MatrixBase& other); -#ifdef __CUDACC__ template EIGEN_DEVICE_FUNC - const Product - operator*(const MatrixBase &other) const - { return this->lazyProduct(other); } -#else - - template const Product operator*(const MatrixBase &other) const; -#endif - template EIGEN_DEVICE_FUNC const Product @@ -294,7 +285,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator!= */ template - inline bool operator==(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator==(const MatrixBase& other) const { return cwiseEqual(other).all(); } /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other. @@ -302,7 +293,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator== */ template - inline bool operator!=(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase& other) const { return cwiseNotEqual(other).any(); } NoAlias noalias(); @@ -453,19 +444,28 @@ template class MatrixBase ///////// MatrixFunctions module ///////// typedef typename internal::stem_function::type StemFunction; - const MatrixExponentialReturnValue exp() const; +#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name() const; +#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument) \ + /** \returns an expression of the matrix Description of \c *this. \brief This function requires the unsupported MatrixFunctions module. To compute the coefficient-wise Description use ArrayBase::##Name . */ \ + const ReturnType Name(Argument) const; + + EIGEN_MATRIX_FUNCTION(MatrixExponentialReturnValue, exp, exponential) + /** \brief Helper function for the unsupported MatrixFunctions module.*/ const MatrixFunctionReturnValue matrixFunction(StemFunction f) const; - const MatrixFunctionReturnValue cosh() const; - const MatrixFunctionReturnValue sinh() const; - const MatrixFunctionReturnValue cos() const; - const MatrixFunctionReturnValue sin() const; - const MatrixSquareRootReturnValue sqrt() const; - const MatrixLogarithmReturnValue log() const; - const MatrixPowerReturnValue pow(const RealScalar& p) const; - const MatrixComplexPowerReturnValue pow(const std::complex& p) const; + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cosh, hyperbolic cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sinh, hyperbolic sine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cos, cosine) + EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, sin, sine) + EIGEN_MATRIX_FUNCTION(MatrixSquareRootReturnValue, sqrt, square root) + EIGEN_MATRIX_FUNCTION(MatrixLogarithmReturnValue, log, logarithm) + EIGEN_MATRIX_FUNCTION_1(MatrixPowerReturnValue, pow, power to \c p, const RealScalar& p) + EIGEN_MATRIX_FUNCTION_1(MatrixComplexPowerReturnValue, pow, power to \c p, const std::complex& p) protected: - EIGEN_DEVICE_FUNC MatrixBase() : Base() {} + EIGEN_DEFAULT_COPY_CONSTRUCTOR(MatrixBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MatrixBase) private: EIGEN_DEVICE_FUNC explicit MatrixBase(int); diff --git a/eigenlib/Eigen/src/Core/NestByValue.h b/eigenlib/Eigen/src/Core/NestByValue.h index 13adf070..a00255d4 100644 --- a/eigenlib/Eigen/src/Core/NestByValue.h +++ b/eigenlib/Eigen/src/Core/NestByValue.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_NESTBYVALUE_H #define EIGEN_NESTBYVALUE_H diff --git a/eigenlib/Eigen/src/Core/NoAlias.h b/eigenlib/Eigen/src/Core/NoAlias.h index 33908010..198792d4 100644 --- a/eigenlib/Eigen/src/Core/NoAlias.h +++ b/eigenlib/Eigen/src/Core/NoAlias.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_NOALIAS_H #define EIGEN_NOALIAS_H diff --git a/eigenlib/Eigen/src/Core/NumTraits.h b/eigenlib/Eigen/src/Core/NumTraits.h index dd61195b..c811ea6a 100644 --- a/eigenlib/Eigen/src/Core/NumTraits.h +++ b/eigenlib/Eigen/src/Core/NumTraits.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_NUMTRAITS_H #define EIGEN_NUMTRAITS_H @@ -75,13 +75,13 @@ struct default_digits10_impl // Integer * \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned. * \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must * be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise. - * \li An epsilon() function which, unlike std::numeric_limits::epsilon(), + * \li An epsilon() function which, unlike std::numeric_limits::epsilon(), * it returns a \a Real instead of a \a T. * \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default * value by the fuzzy comparison operators. * \li highest() and lowest() functions returning the highest and lowest possible values respectively. * \li digits10() function returning the number of decimal digits that can be represented without change. This is - * the analogue of std::numeric_limits::digits10 + * the analogue of std::numeric_limits::digits10 * which is used as the default implementation if specialized. */ @@ -215,6 +215,8 @@ struct NumTraits > static inline RealScalar epsilon() { return NumTraits::epsilon(); } EIGEN_DEVICE_FUNC static inline RealScalar dummy_precision() { return NumTraits::dummy_precision(); } + + static inline int digits10() { return NumTraits::digits10(); } }; template<> struct NumTraits diff --git a/eigenlib/Eigen/src/Core/PermutationMatrix.h b/eigenlib/Eigen/src/Core/PermutationMatrix.h index b1fb455b..142a04ff 100644 --- a/eigenlib/Eigen/src/Core/PermutationMatrix.h +++ b/eigenlib/Eigen/src/Core/PermutationMatrix.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PERMUTATIONMATRIX_H #define EIGEN_PERMUTATIONMATRIX_H @@ -87,17 +87,6 @@ class PermutationBase : public EigenBase return derived(); } - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** This is a special case of the templated operator=. Its purpose is to - * prevent a default operator= from hiding the templated operator=. - */ - Derived& operator=(const PermutationBase& other) - { - indices() = other.indices(); - return derived(); - } - #endif - /** \returns the number of rows */ inline Index rows() const { return Index(indices().size()); } @@ -333,12 +322,6 @@ class PermutationMatrix : public PermutationBase& other) : m_indices(other.indices()) {} - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** Standard copy constructor. Defined only to prevent a default copy constructor - * from hiding the other templated constructor */ - inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {} - #endif - /** Generic constructor from expression of the indices. The indices * array has the meaning that the permutations sends each integer i to indices[i]. * @@ -373,17 +356,6 @@ class PermutationMatrix : public PermutationBase struct check_rows_cols_for_overflow { EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE void run(Index rows, Index cols) { - // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 + // xxxp://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 // we assume Index is signed - Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed + Index max_index = (std::size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed bool error = (rows == 0 || cols == 0) ? false : (rows > max_index / cols); if (error) @@ -577,6 +577,10 @@ class PlainObjectBase : public internal::dense_xpr_base::type * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned * \a data pointers. * + * Here is an example using strides: + * \include Matrix_Map_stride.cpp + * Output: \verbinclude Matrix_Map_stride.out + * * \see class Map */ //@{ @@ -733,8 +737,10 @@ class PlainObjectBase : public internal::dense_xpr_base::type EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if::type* = 0) { - EIGEN_STATIC_ASSERT(bool(NumTraits::IsInteger) && - bool(NumTraits::IsInteger), + const bool t0_is_integer_alike = internal::is_valid_index_type::value; + const bool t1_is_integer_alike = internal::is_valid_index_type::value; + EIGEN_STATIC_ASSERT(t0_is_integer_alike && + t1_is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) resize(rows,cols); } @@ -769,9 +775,9 @@ class PlainObjectBase : public internal::dense_xpr_base::type && ((!internal::is_same::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),T>::type* = 0) { // NOTE MSVC 2008 complains if we directly put bool(NumTraits::IsInteger) as the EIGEN_STATIC_ASSERT argument. - const bool is_integer = NumTraits::IsInteger; - EIGEN_UNUSED_VARIABLE(is_integer); - EIGEN_STATIC_ASSERT(is_integer, + const bool is_integer_alike = internal::is_valid_index_type::value; + EIGEN_UNUSED_VARIABLE(is_integer_alike); + EIGEN_STATIC_ASSERT(is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) resize(size); } @@ -812,6 +818,13 @@ class PlainObjectBase : public internal::dense_xpr_base::type this->_set_noalias(other); } + // Initialize an arbitrary matrix from an object convertible to the Derived type. + template + EIGEN_DEVICE_FUNC + EIGEN_STRONG_INLINE void _init1(const Derived& other){ + this->_set_noalias(other); + } + // Initialize an arbitrary matrix from a generic Eigen expression template EIGEN_DEVICE_FUNC @@ -834,7 +847,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type this->derived() = r; } - // For fixed -size arrays: + // For fixed-size Array template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Scalar& val0, @@ -846,6 +859,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type Base::setConstant(val0); } + // For fixed-size Array template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Index& val0, diff --git a/eigenlib/Eigen/src/Core/Product.h b/eigenlib/Eigen/src/Core/Product.h index ae0c94b3..1ec2130e 100644 --- a/eigenlib/Eigen/src/Core/Product.h +++ b/eigenlib/Eigen/src/Core/Product.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PRODUCT_H #define EIGEN_PRODUCT_H @@ -97,8 +97,8 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option, && "if you wanted a coeff-wise or a dot product use the respective explicit functions"); } - EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); } - EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } EIGEN_DEVICE_FUNC const LhsNestedCleaned& lhs() const { return m_lhs; } EIGEN_DEVICE_FUNC const RhsNestedCleaned& rhs() const { return m_rhs; } @@ -127,7 +127,7 @@ public: using Base::derived; typedef typename Base::Scalar Scalar; - operator const Scalar() const + EIGEN_STRONG_INLINE operator const Scalar() const { return internal::evaluator(derived()).coeff(0,0); } @@ -162,7 +162,7 @@ class ProductImpl public: - EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); @@ -170,7 +170,7 @@ class ProductImpl return internal::evaluator(derived()).coeff(row,col); } - EIGEN_DEVICE_FUNC Scalar coeff(Index i) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); diff --git a/eigenlib/Eigen/src/Core/ProductEvaluators.h b/eigenlib/Eigen/src/Core/ProductEvaluators.h index 583b7f59..176e0ea3 100644 --- a/eigenlib/Eigen/src/Core/ProductEvaluators.h +++ b/eigenlib/Eigen/src/Core/ProductEvaluators.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PRODUCTEVALUATORS_H @@ -32,7 +32,7 @@ struct evaluator > typedef Product XprType; typedef product_evaluator Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} }; // Catch "scalar * ( A * B )" and transform it to "(A*scalar) * B" @@ -55,7 +55,7 @@ struct evaluator, const Product > XprType; typedef evaluator > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {} }; @@ -68,7 +68,7 @@ struct evaluator, DiagIndex> > typedef Diagonal, DiagIndex> XprType; typedef evaluator, DiagIndex> > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(Diagonal, DiagIndex>( Product(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index() )) @@ -207,6 +207,12 @@ struct evaluator_assume_aliasing +struct evaluator_assume_aliasing::Scalar>, const OtherXpr, + const Product >, DenseShape > { + static const bool value = true; +}; + template struct assignment_from_xpr_op_product { @@ -240,19 +246,19 @@ template struct generic_product_impl { template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) += (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) -= (lhs.transpose().cwiseProduct(rhs)).sum(); } }; @@ -306,25 +312,25 @@ struct generic_product_impl }; template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major()); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major()); } template - static inline void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major()); } template - static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) + static EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major()); } @@ -390,7 +396,7 @@ struct generic_product_impl // but easier on the compiler side call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::assign_op()); } - + template static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { @@ -404,6 +410,32 @@ struct generic_product_impl // dst.noalias() -= lhs.lazyProduct(rhs); call_assignment_no_alias(dst, lhs.lazyProduct(rhs), internal::sub_assign_op()); } + + // Catch "dst {,+,-}= (s*A)*B" and evaluate it lazily by moving out the scalar factor: + // dst {,+,-}= s * (A.lazyProduct(B)) + // This is a huge benefit for heap-allocated matrix types as it save one costly allocation. + // For them, this strategy is also faster than simply by-passing the heap allocation through + // stack allocation. + // For fixed sizes matrices, this is less obvious, it is sometimes x2 faster, but sometimes x3 slower, + // and the behavior depends also a lot on the compiler... so let's be conservative and enable them for dynamic-size only, + // that is when coming from generic_product_impl<...,GemmProduct> in file GeneralMatrixMatrix.h + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + void eval_dynamic(Dst& dst, const CwiseBinaryOp, + const CwiseNullaryOp, Plain1>, Xpr2>& lhs, const Rhs& rhs, const Func &func) + { + call_assignment_no_alias(dst, lhs.lhs().functor().m_other * lhs.rhs().lazyProduct(rhs), func); + } + + // Here, we we always have LhsT==Lhs, but we need to make it a template type to make the above + // overload more specialized. + template + static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + void eval_dynamic(Dst& dst, const LhsT& lhs, const Rhs& rhs, const Func &func) + { + call_assignment_no_alias(dst, lhs.lazyProduct(rhs), func); + } + // template // static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) @@ -779,7 +811,11 @@ public: _Vectorizable = bool(int(MatrixFlags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagFlags)&PacketAccessBit))), _LinearAccessMask = (MatrixType::RowsAtCompileTime==1 || MatrixType::ColsAtCompileTime==1) ? LinearAccessBit : 0, Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixFlags)) | (_Vectorizable ? PacketAccessBit : 0), - Alignment = evaluator::Alignment + Alignment = evaluator::Alignment, + + AsScalarProduct = (DiagonalType::SizeAtCompileTime==1) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::RowsAtCompileTime==1 && ProductOrder==OnTheLeft) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==1 && ProductOrder==OnTheRight) }; diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag) @@ -791,7 +827,10 @@ public: EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const { - return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); + if(AsScalarProduct) + return m_diagImpl.coeff(0) * m_matImpl.coeff(idx); + else + return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); } protected: diff --git a/eigenlib/Eigen/src/Core/Random.h b/eigenlib/Eigen/src/Core/Random.h index 6faf789c..ff1a8e67 100644 --- a/eigenlib/Eigen/src/Core/Random.h +++ b/eigenlib/Eigen/src/Core/Random.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_RANDOM_H #define EIGEN_RANDOM_H diff --git a/eigenlib/Eigen/src/Core/Redux.h b/eigenlib/Eigen/src/Core/Redux.h index b6e8f888..fc97f551 100644 --- a/eigenlib/Eigen/src/Core/Redux.h +++ b/eigenlib/Eigen/src/Core/Redux.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REDUX_H #define EIGEN_REDUX_H @@ -407,7 +407,7 @@ protected: */ template template -typename internal::traits::Scalar +EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::redux(const Func& func) const { eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix"); diff --git a/eigenlib/Eigen/src/Core/Ref.h b/eigenlib/Eigen/src/Core/Ref.h index bdf24f52..0698b011 100644 --- a/eigenlib/Eigen/src/Core/Ref.h +++ b/eigenlib/Eigen/src/Core/Ref.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REF_H #define EIGEN_REF_H @@ -28,12 +28,13 @@ struct traits > template struct match { enum { + IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime, HasDirectAccess = internal::has_direct_access::ret, - StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), + StorageOrderMatch = IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic) || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime) || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), - OuterStrideMatch = Derived::IsVectorAtCompileTime + OuterStrideMatch = IsVectorAtCompileTime || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime), // NOTE, this indirection of evaluator::Alignment is needed // to workaround a very strange bug in MSVC related to the instantiation @@ -95,6 +96,8 @@ protected: template EIGEN_DEVICE_FUNC void construct(Expression& expr) { + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(PlainObjectType,Expression); + if(PlainObjectType::RowsAtCompileTime==1) { eigen_assert(expr.rows()==1 || expr.cols()==1); diff --git a/eigenlib/Eigen/src/Core/Replicate.h b/eigenlib/Eigen/src/Core/Replicate.h index 9960ef88..271bbf3a 100644 --- a/eigenlib/Eigen/src/Core/Replicate.h +++ b/eigenlib/Eigen/src/Core/Replicate.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REPLICATE_H #define EIGEN_REPLICATE_H diff --git a/eigenlib/Eigen/src/Core/ReturnByValue.h b/eigenlib/Eigen/src/Core/ReturnByValue.h index c44b7673..89d77c62 100644 --- a/eigenlib/Eigen/src/Core/ReturnByValue.h +++ b/eigenlib/Eigen/src/Core/ReturnByValue.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_RETURNBYVALUE_H #define EIGEN_RETURNBYVALUE_H diff --git a/eigenlib/Eigen/src/Core/Reverse.h b/eigenlib/Eigen/src/Core/Reverse.h index 0640cda2..597c047a 100644 --- a/eigenlib/Eigen/src/Core/Reverse.h +++ b/eigenlib/Eigen/src/Core/Reverse.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REVERSE_H #define EIGEN_REVERSE_H diff --git a/eigenlib/Eigen/src/Core/Select.h b/eigenlib/Eigen/src/Core/Select.h index 79eec1b5..7cd3afb9 100644 --- a/eigenlib/Eigen/src/Core/Select.h +++ b/eigenlib/Eigen/src/Core/Select.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELECT_H #define EIGEN_SELECT_H diff --git a/eigenlib/Eigen/src/Core/SelfAdjointView.h b/eigenlib/Eigen/src/Core/SelfAdjointView.h index 504c98f0..c68a861e 100644 --- a/eigenlib/Eigen/src/Core/SelfAdjointView.h +++ b/eigenlib/Eigen/src/Core/SelfAdjointView.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFADJOINTMATRIX_H #define EIGEN_SELFADJOINTMATRIX_H @@ -71,7 +71,9 @@ template class SelfAdjointView EIGEN_DEVICE_FUNC explicit inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) - {} + { + EIGEN_STATIC_ASSERT(UpLo==Lower || UpLo==Upper,SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY); + } EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows(); } @@ -189,7 +191,7 @@ template class SelfAdjointView TriangularView >::type(tmp2); } - typedef SelfAdjointView ConjugateReturnType; + typedef SelfAdjointView ConjugateReturnType; /** \sa MatrixBase::conjugate() const */ EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const diff --git a/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h b/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h index 719ed72a..82d88955 100644 --- a/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h +++ b/eigenlib/Eigen/src/Core/SelfCwiseBinaryOp.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFCWISEBINARYOP_H #define EIGEN_SELFCWISEBINARYOP_H @@ -15,33 +15,29 @@ namespace Eigen { // TODO generalize the scalar type of 'other' template -EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::mul_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::add_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::sub_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::div_assign_op()); return derived(); } diff --git a/eigenlib/Eigen/src/Core/Solve.h b/eigenlib/Eigen/src/Core/Solve.h index 960a5859..6195e3af 100644 --- a/eigenlib/Eigen/src/Core/Solve.h +++ b/eigenlib/Eigen/src/Core/Solve.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SOLVE_H #define EIGEN_SOLVE_H @@ -34,12 +34,12 @@ template struct s template struct solve_traits { - typedef Matrix PlainObject; + RhsType::MaxColsAtCompileTime>::type PlainObject; }; template diff --git a/eigenlib/Eigen/src/Core/SolveTriangular.h b/eigenlib/Eigen/src/Core/SolveTriangular.h index 049890b2..d7f45e5f 100644 --- a/eigenlib/Eigen/src/Core/SolveTriangular.h +++ b/eigenlib/Eigen/src/Core/SolveTriangular.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SOLVETRIANGULAR_H #define EIGEN_SOLVETRIANGULAR_H @@ -19,7 +19,7 @@ namespace internal { template struct triangular_solve_vector; -template +template struct triangular_solve_matrix; // small helper struct extracting some traits on the underlying solver operation @@ -98,8 +98,8 @@ struct triangular_solver_selector BlockingType blocking(rhs.rows(), rhs.cols(), size, 1, false); triangular_solve_matrix - ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride(), blocking); + (Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor, Rhs::InnerStrideAtCompileTime> + ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.innerStride(), rhs.outerStride(), blocking); } }; @@ -169,6 +169,9 @@ void TriangularViewImpl::solveInPlace(const MatrixBase::Flags & RowMajorBit) && OtherDerived::IsVectorAtCompileTime && OtherDerived::SizeAtCompileTime!=1}; typedef typename internal::conditional::stableNorm() const typedef typename internal::nested_eval::type DerivedCopy; typedef typename internal::remove_all::type DerivedCopyClean; - DerivedCopy copy(derived()); + const DerivedCopy copy(derived()); enum { CanAlign = ( (int(DerivedCopyClean::Flags)&DirectAccessBit) || (int(internal::evaluator::Alignment)>0) // FIXME Alignment)>0 might not be enough - ) && (blockSize*sizeof(Scalar)*20) // if we cannot allocate on the stack, then let's not bother about this optimization }; typedef typename internal::conditional, internal::evaluator::Alignment>, typename DerivedCopyClean::ConstSegmentReturnType>::type SegmentWrapper; diff --git a/eigenlib/Eigen/src/Core/Stride.h b/eigenlib/Eigen/src/Core/Stride.h index 513742f3..cac9a278 100644 --- a/eigenlib/Eigen/src/Core/Stride.h +++ b/eigenlib/Eigen/src/Core/Stride.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STRIDE_H #define EIGEN_STRIDE_H diff --git a/eigenlib/Eigen/src/Core/Swap.h b/eigenlib/Eigen/src/Core/Swap.h index d7020091..bb5f2c10 100644 --- a/eigenlib/Eigen/src/Core/Swap.h +++ b/eigenlib/Eigen/src/Core/Swap.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SWAP_H #define EIGEN_SWAP_H diff --git a/eigenlib/Eigen/src/Core/Transpose.h b/eigenlib/Eigen/src/Core/Transpose.h index 79b767bc..0b3c8272 100644 --- a/eigenlib/Eigen/src/Core/Transpose.h +++ b/eigenlib/Eigen/src/Core/Transpose.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRANSPOSE_H #define EIGEN_TRANSPOSE_H @@ -146,6 +146,8 @@ template class TransposeImpl { return derived().nestedExpression().coeffRef(index); } + protected: + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TransposeImpl) }; /** \returns an expression of the transpose of *this. diff --git a/eigenlib/Eigen/src/Core/Transpositions.h b/eigenlib/Eigen/src/Core/Transpositions.h index 19c17bb4..41e2da49 100644 --- a/eigenlib/Eigen/src/Core/Transpositions.h +++ b/eigenlib/Eigen/src/Core/Transpositions.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRANSPOSITIONS_H #define EIGEN_TRANSPOSITIONS_H @@ -33,17 +33,6 @@ class TranspositionsBase indices() = other.indices(); return derived(); } - - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** This is a special case of the templated operator=. Its purpose is to - * prevent a default operator= from hiding the templated operator=. - */ - Derived& operator=(const TranspositionsBase& other) - { - indices() = other.indices(); - return derived(); - } - #endif /** \returns the number of transpositions */ Index size() const { return indices().size(); } @@ -171,12 +160,6 @@ class Transpositions : public TranspositionsBase& other) : m_indices(other.indices()) {} - #ifndef EIGEN_PARSED_BY_DOXYGEN - /** Standard copy constructor. Defined only to prevent a default copy constructor - * from hiding the other templated constructor */ - inline Transpositions(const Transpositions& other) : m_indices(other.indices()) {} - #endif - /** Generic constructor from expression of the transposition indices. */ template explicit inline Transpositions(const MatrixBase& indices) : m_indices(indices) @@ -189,17 +172,6 @@ class Transpositions : public TranspositionsBase > const Product operator*(const MatrixBase& matrix, const Transpose& trt) { - return Product(matrix.derived(), trt.derived()); + return Product(matrix.derived(), trt); } /** \returns the \a matrix with the inverse transpositions applied to the rows. diff --git a/eigenlib/Eigen/src/Core/TriangularMatrix.h b/eigenlib/Eigen/src/Core/TriangularMatrix.h index 667ef09d..1f2d3a70 100644 --- a/eigenlib/Eigen/src/Core/TriangularMatrix.h +++ b/eigenlib/Eigen/src/Core/TriangularMatrix.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRIANGULARMATRIX_H #define EIGEN_TRIANGULARMATRIX_H @@ -217,9 +217,7 @@ template class TriangularView explicit inline TriangularView(MatrixType& matrix) : m_matrix(matrix) {} - using Base::operator=; - TriangularView& operator=(const TriangularView &other) - { return Base::operator=(other); } + EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TriangularView) /** \copydoc EigenBase::rows() */ EIGEN_DEVICE_FUNC @@ -544,6 +542,10 @@ template class TriangularViewImpl<_Mat template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha, bool beta); + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(TriangularViewImpl) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TriangularViewImpl) + }; /*************************************************************************** diff --git a/eigenlib/Eigen/src/Core/VectorBlock.h b/eigenlib/Eigen/src/Core/VectorBlock.h index d72fbf7e..96bea9a8 100644 --- a/eigenlib/Eigen/src/Core/VectorBlock.h +++ b/eigenlib/Eigen/src/Core/VectorBlock.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_VECTORBLOCK_H #define EIGEN_VECTORBLOCK_H diff --git a/eigenlib/Eigen/src/Core/VectorwiseOp.h b/eigenlib/Eigen/src/Core/VectorwiseOp.h index 4fe267e9..0e167b9f 100644 --- a/eigenlib/Eigen/src/Core/VectorwiseOp.h +++ b/eigenlib/Eigen/src/Core/VectorwiseOp.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARTIAL_REDUX_H #define EIGEN_PARTIAL_REDUX_H diff --git a/eigenlib/Eigen/src/Core/Visitor.h b/eigenlib/Eigen/src/Core/Visitor.h index 54c1883d..98cd67fb 100644 --- a/eigenlib/Eigen/src/Core/Visitor.h +++ b/eigenlib/Eigen/src/Core/Visitor.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_VISITOR_H #define EIGEN_VISITOR_H diff --git a/eigenlib/Eigen/src/Core/arch/AVX/Complex.h b/eigenlib/Eigen/src/Core/arch/AVX/Complex.h index 99439c8a..fed35e5b 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/Complex.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_AVX_H #define EIGEN_COMPLEX_AVX_H @@ -204,23 +204,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet8f& x, const Packet4cf& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet8f& x, const Packet4cf& y) const - { return Packet4cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet8f& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& x, const Packet8f& y) const - { return Packet4cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cf,Packet8f) template<> EIGEN_STRONG_INLINE Packet4cf pdiv(const Packet4cf& a, const Packet4cf& b) { @@ -400,23 +384,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet4d& x, const Packet2cd& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet4d& x, const Packet2cd& y) const - { return Packet2cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet4d& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& x, const Packet4d& y) const - { return Packet2cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cd,Packet4d) template<> EIGEN_STRONG_INLINE Packet2cd pdiv(const Packet2cd& a, const Packet2cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/AVX/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/AVX/MathFunctions.h index 6af67ce2..aa90a6df 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/MathFunctions.h @@ -5,13 +5,13 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATH_FUNCTIONS_AVX_H #define EIGEN_MATH_FUNCTIONS_AVX_H /* The sin, cos, exp, and log functions of this file are loosely derived from - * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ + * Julien Pommier's sse math library: xxxp://gruntthepeon.free.fr/ssemath/ */ namespace Eigen { @@ -359,7 +359,7 @@ pexp(const Packet4d& _x) { // The main advantage of this approach is not just speed, but also the fact that // it can be inlined and pipelined with other computations, further reducing its // effective latency. This is similar to Quake3's fast inverse square root. -// For detail see here: http://www.beyond3d.com/content/articles/8/ +// For detail see here: xxxp://www.beyond3d.com/content/articles/8/ #if EIGEN_FAST_MATH template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8f diff --git a/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h index 195d40fb..9ab6dc9b 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_AVX_H #define EIGEN_PACKET_MATH_AVX_H @@ -159,11 +159,12 @@ template<> EIGEN_STRONG_INLINE Packet8i pdiv(const Packet8i& /*a*/, co #ifdef __FMA__ template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& b, const Packet8f& c) { -#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) ) - // clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers, - // and gcc stupidly generates a vfmadd132ps instruction, - // so let's enforce it to generate a vfmadd231ps instruction since the most common use case is to accumulate - // the result of the product. +#if ( (EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC<80) || (EIGEN_COMP_CLANG) ) + // Clang stupidly generates a vfmadd213ps instruction plus some vmovaps on registers, + // and even register spilling with clang>=6.0 (bug 1637). + // Gcc stupidly generates a vfmadd132ps instruction. + // So let's enforce it to generate a vfmadd231ps instruction since the most common use + // case is to accumulate the result of the product. Packet8f res = c; __asm__("vfmadd231ps %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b)); return res; @@ -172,7 +173,7 @@ template<> EIGEN_STRONG_INLINE Packet8f pmadd(const Packet8f& a, const Packet8f& #endif } template<> EIGEN_STRONG_INLINE Packet4d pmadd(const Packet4d& a, const Packet4d& b, const Packet4d& c) { -#if ( EIGEN_COMP_GNUC_STRICT || (EIGEN_COMP_CLANG && (EIGEN_COMP_CLANG<308)) ) +#if ( (EIGEN_COMP_GNUC_STRICT && EIGEN_COMP_GNUC<80) || (EIGEN_COMP_CLANG) ) // see above Packet4d res = c; __asm__("vfmadd231pd %[a], %[b], %[c]" : [c] "+x" (res) : [a] "x" (a), [b] "x" (b)); @@ -308,9 +309,9 @@ template<> EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) } #ifndef EIGEN_VECTORIZE_AVX512 -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif template<> EIGEN_STRONG_INLINE float pfirst(const Packet8f& a) { @@ -333,9 +334,12 @@ template<> EIGEN_STRONG_INLINE Packet4d preverse(const Packet4d& a) { __m256d tmp = _mm256_shuffle_pd(a,a,5); return _mm256_permute2f128_pd(tmp, tmp, 1); - + #if 0 + // This version is unlikely to be faster as _mm256_shuffle_ps and _mm256_permute_pd + // exhibit the same latency/throughput, but it is here for future reference/benchmarking... __m256d swap_halves = _mm256_permute2f128_pd(a,a,1); return _mm256_permute_pd(swap_halves,5); + #endif } // pabs should be ok diff --git a/eigenlib/Eigen/src/Core/arch/AVX/TypeCasting.h b/eigenlib/Eigen/src/Core/arch/AVX/TypeCasting.h index 83bfdc60..301eb4cb 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX/TypeCasting.h +++ b/eigenlib/Eigen/src/Core/arch/AVX/TypeCasting.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TYPE_CASTING_AVX_H #define EIGEN_TYPE_CASTING_AVX_H diff --git a/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h index 399be0ee..f30f2a9e 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/AVX512/MathFunctions.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef THIRD_PARTY_EIGEN3_EIGEN_SRC_CORE_ARCH_AVX512_MATHFUNCTIONS_H_ #define THIRD_PARTY_EIGEN3_EIGEN_SRC_CORE_ARCH_AVX512_MATHFUNCTIONS_H_ @@ -29,6 +29,7 @@ namespace internal { #define _EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(NAME, X) \ const Packet8d p8d_##NAME = _mm512_castsi512_pd(_mm512_set1_epi64(X)) + // Natural logarithm // Computes log(x) as log(2^e * m) = C*e + log(m), where the constant C =log(2) // and m is in the range [sqrt(1/2),sqrt(2)). In this range, the logarithm can @@ -47,6 +48,7 @@ plog(const Packet16f& _x) { // The smallest non denormalized float number. _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(min_norm_pos, 0x00800000); _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(minus_inf, 0xff800000); + _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(pos_inf, 0x7f800000); _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(nan, 0x7fc00000); // Polynomial coefficients. @@ -64,11 +66,9 @@ plog(const Packet16f& _x) { _EIGEN_DECLARE_CONST_Packet16f(cephes_log_q2, 0.693359375f); // invalid_mask is set to true when x is NaN - __mmask16 invalid_mask = - _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_NGE_UQ); - __mmask16 iszero_mask = - _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_EQ_UQ); - + __mmask16 invalid_mask = _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_NGE_UQ); + __mmask16 iszero_mask = _mm512_cmp_ps_mask(x, _mm512_setzero_ps(), _CMP_EQ_OQ); + // Truncate input values to the minimum positive normal. x = pmax(x, p16f_min_norm_pos); @@ -88,9 +88,9 @@ plog(const Packet16f& _x) { // x = x + x - 1.0; // } else { x = x - 1.0; } __mmask16 mask = _mm512_cmp_ps_mask(x, p16f_cephes_SQRTHF, _CMP_LT_OQ); - Packet16f tmp = _mm512_mask_blend_ps(mask, x, _mm512_setzero_ps()); + Packet16f tmp = _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), x); x = psub(x, p16f_1); - e = psub(e, _mm512_mask_blend_ps(mask, p16f_1, _mm512_setzero_ps())); + e = psub(e, _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), p16f_1)); x = padd(x, tmp); Packet16f x2 = pmul(x, x); @@ -118,10 +118,18 @@ plog(const Packet16f& _x) { x = padd(x, y); x = padd(x, y2); - // Filter out invalid inputs, i.e. negative arg will be NAN, 0 will be -INF. - return _mm512_mask_blend_ps(iszero_mask, p16f_minus_inf, - _mm512_mask_blend_ps(invalid_mask, p16f_nan, x)); + __mmask16 pos_inf_mask = _mm512_cmp_ps_mask(_x,p16f_pos_inf,_CMP_EQ_OQ); + // Filter out invalid inputs, i.e.: + // - negative arg will be NAN, + // - 0 will be -INF. + // - +INF will be +INF + return _mm512_mask_blend_ps(iszero_mask, + _mm512_mask_blend_ps(invalid_mask, + _mm512_mask_blend_ps(pos_inf_mask,x,p16f_pos_inf), + p16f_nan), + p16f_minus_inf); } + #endif // Exponential function. Works by writing "x = m*log(2) + r" where @@ -257,50 +265,39 @@ pexp(const Packet8d& _x) { template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet16f psqrt(const Packet16f& _x) { - _EIGEN_DECLARE_CONST_Packet16f(one_point_five, 1.5f); - _EIGEN_DECLARE_CONST_Packet16f(minus_half, -0.5f); - _EIGEN_DECLARE_CONST_Packet16f_FROM_INT(flt_min, 0x00800000); + Packet16f neg_half = pmul(_x, pset1(-.5f)); + __mmask16 denormal_mask = _mm512_kand( + _mm512_cmp_ps_mask(_x, pset1((std::numeric_limits::min)()), + _CMP_LT_OQ), + _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_GE_OQ)); - Packet16f neg_half = pmul(_x, p16f_minus_half); - - // select only the inverse sqrt of positive normal inputs (denormals are - // flushed to zero and cause infs as well). - __mmask16 non_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_GE_OQ); - Packet16f x = _mm512_mask_blend_ps(non_zero_mask, _mm512_rsqrt14_ps(_x), - _mm512_setzero_ps()); + Packet16f x = _mm512_rsqrt14_ps(_x); // Do a single step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5f))); - // Multiply the original _x by it's reciprocal square root to extract the - // square root. - return pmul(_x, x); + // Flush results for denormals to zero. + return _mm512_mask_blend_ps(denormal_mask, pmul(_x,x), _mm512_setzero_ps()); } template <> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet8d psqrt(const Packet8d& _x) { - _EIGEN_DECLARE_CONST_Packet8d(one_point_five, 1.5); - _EIGEN_DECLARE_CONST_Packet8d(minus_half, -0.5); - _EIGEN_DECLARE_CONST_Packet8d_FROM_INT64(dbl_min, 0x0010000000000000LL); + Packet8d neg_half = pmul(_x, pset1(-.5)); + __mmask16 denormal_mask = _mm512_kand( + _mm512_cmp_pd_mask(_x, pset1((std::numeric_limits::min)()), + _CMP_LT_OQ), + _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_GE_OQ)); - Packet8d neg_half = pmul(_x, p8d_minus_half); + Packet8d x = _mm512_rsqrt14_pd(_x); - // select only the inverse sqrt of positive normal inputs (denormals are - // flushed to zero and cause infs as well). - __mmask8 non_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_GE_OQ); - Packet8d x = _mm512_mask_blend_pd(non_zero_mask, _mm512_rsqrt14_pd(_x), - _mm512_setzero_pd()); - - // Do a first step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); + // Do a single step of Newton's iteration. + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5))); // Do a second step of Newton's iteration. - x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); + x = pmul(x, pmadd(neg_half, pmul(x, x), pset1(1.5))); - // Multiply the original _x by it's reciprocal square root to extract the - // square root. - return pmul(_x, x); + return _mm512_mask_blend_pd(denormal_mask, pmul(_x,x), _mm512_setzero_pd()); } #else template <> @@ -333,20 +330,18 @@ prsqrt(const Packet16f& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask16 le_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_LT_OQ); - Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), - _mm512_rsqrt14_ps(_x)); + Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_rsqrt14_ps(_x), _mm512_setzero_ps()); // Fill in NaNs and Infs for the negative/zero entries. __mmask16 neg_mask = _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_LT_OQ); Packet16f infs_and_nans = _mm512_mask_blend_ps( - neg_mask, p16f_nan, - _mm512_mask_blend_ps(le_zero_mask, p16f_inf, _mm512_setzero_ps())); + neg_mask, _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), p16f_inf), p16f_nan); // Do a single step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_ps(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_ps(le_zero_mask, x, infs_and_nans); } template <> @@ -363,14 +358,12 @@ prsqrt(const Packet8d& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask8 le_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_LT_OQ); - Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), - _mm512_rsqrt14_pd(_x)); + Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_rsqrt14_pd(_x), _mm512_setzero_pd()); // Fill in NaNs and Infs for the negative/zero entries. __mmask8 neg_mask = _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_LT_OQ); Packet8d infs_and_nans = _mm512_mask_blend_pd( - neg_mask, p8d_nan, - _mm512_mask_blend_pd(le_zero_mask, p8d_inf, _mm512_setzero_pd())); + neg_mask, _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), p8d_inf), p8d_nan); // Do a first step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); @@ -379,9 +372,9 @@ prsqrt(const Packet8d& _x) { x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_pd(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_pd(le_zero_mask, x, infs_and_nans); } -#else +#elif defined(EIGEN_VECTORIZE_AVX512ER) template <> EIGEN_STRONG_INLINE Packet16f prsqrt(const Packet16f& x) { return _mm512_rsqrt28_ps(x); diff --git a/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h index f6500a16..b8b11153 100644 --- a/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AVX512/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_AVX512_H #define EIGEN_PACKET_MATH_AVX512_H @@ -19,10 +19,10 @@ namespace internal { #endif #ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS -#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*)) +#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 32 #endif -#ifdef __FMA__ +#ifdef EIGEN_VECTORIZE_FMA #ifndef EIGEN_HAS_SINGLE_INSTRUCTION_MADD #define EIGEN_HAS_SINGLE_INSTRUCTION_MADD #endif @@ -54,13 +54,14 @@ template<> struct packet_traits : default_packet_traits AlignedOnScalar = 1, size = 16, HasHalfPacket = 1, -#if EIGEN_GNUC_AT_LEAST(5, 3) + HasBlend = 0, +#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT) #ifdef EIGEN_VECTORIZE_AVX512DQ HasLog = 1, #endif HasExp = 1, - HasSqrt = 1, - HasRsqrt = 1, + HasSqrt = EIGEN_FAST_MATH, + HasRsqrt = EIGEN_FAST_MATH, #endif HasDiv = 1 }; @@ -74,8 +75,8 @@ template<> struct packet_traits : default_packet_traits AlignedOnScalar = 1, size = 8, HasHalfPacket = 1, -#if EIGEN_GNUC_AT_LEAST(5, 3) - HasSqrt = 1, +#if EIGEN_GNUC_AT_LEAST(5, 3) || (!EIGEN_COMP_GNUC_STRICT) + HasSqrt = EIGEN_FAST_MATH, HasRsqrt = EIGEN_FAST_MATH, #endif HasDiv = 1 @@ -98,6 +99,7 @@ template <> struct unpacket_traits { typedef float type; typedef Packet8f half; + typedef Packet16i integer_packet; enum { size = 16, alignment=Aligned64 }; }; template <> @@ -132,7 +134,7 @@ EIGEN_STRONG_INLINE Packet16f pload1(const float* from) { } template <> EIGEN_STRONG_INLINE Packet8d pload1(const double* from) { - return _mm512_broadcastsd_pd(_mm_load_pd1(from)); + return _mm512_set1_pd(*from); } template <> @@ -158,6 +160,11 @@ EIGEN_STRONG_INLINE Packet8d padd(const Packet8d& a, const Packet8d& b) { return _mm512_add_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i padd(const Packet16i& a, + const Packet16i& b) { + return _mm512_add_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f psub(const Packet16f& a, @@ -169,6 +176,11 @@ EIGEN_STRONG_INLINE Packet8d psub(const Packet8d& a, const Packet8d& b) { return _mm512_sub_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i psub(const Packet16i& a, + const Packet16i& b) { + return _mm512_sub_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f pnegate(const Packet16f& a) { @@ -202,6 +214,11 @@ EIGEN_STRONG_INLINE Packet8d pmul(const Packet8d& a, const Packet8d& b) { return _mm512_mul_pd(a, b); } +template <> +EIGEN_STRONG_INLINE Packet16i pmul(const Packet16i& a, + const Packet16i& b) { + return _mm512_mul_epi32(a, b); +} template <> EIGEN_STRONG_INLINE Packet16f pdiv(const Packet16f& a, @@ -214,7 +231,7 @@ EIGEN_STRONG_INLINE Packet8d pdiv(const Packet8d& a, return _mm512_div_pd(a, b); } -#ifdef __FMA__ +#ifdef EIGEN_VECTORIZE_FMA template <> EIGEN_STRONG_INLINE Packet16f pmadd(const Packet16f& a, const Packet16f& b, const Packet16f& c) { @@ -230,23 +247,73 @@ EIGEN_STRONG_INLINE Packet8d pmadd(const Packet8d& a, const Packet8d& b, template <> EIGEN_STRONG_INLINE Packet16f pmin(const Packet16f& a, const Packet16f& b) { - return _mm512_min_ps(a, b); + // Arguments are reversed to match NaN propagation behavior of std::min. + return _mm512_min_ps(b, a); } template <> EIGEN_STRONG_INLINE Packet8d pmin(const Packet8d& a, const Packet8d& b) { - return _mm512_min_pd(a, b); + // Arguments are reversed to match NaN propagation behavior of std::min. + return _mm512_min_pd(b, a); } template <> EIGEN_STRONG_INLINE Packet16f pmax(const Packet16f& a, const Packet16f& b) { - return _mm512_max_ps(a, b); + // Arguments are reversed to match NaN propagation behavior of std::max. + return _mm512_max_ps(b, a); } template <> EIGEN_STRONG_INLINE Packet8d pmax(const Packet8d& a, const Packet8d& b) { - return _mm512_max_pd(a, b); + // Arguments are reversed to match NaN propagation behavior of std::max. + return _mm512_max_pd(b, a); +} + +#ifdef EIGEN_VECTORIZE_AVX512DQ +template EIGEN_STRONG_INLINE Packet8f extract256(Packet16f x) { return _mm512_extractf32x8_ps(x,I_); } +template EIGEN_STRONG_INLINE Packet2d extract128(Packet8d x) { return _mm512_extractf64x2_pd(x,I_); } +EIGEN_STRONG_INLINE Packet16f cat256(Packet8f a, Packet8f b) { return _mm512_insertf32x8(_mm512_castps256_ps512(a),b,1); } +#else +// AVX512F does not define _mm512_extractf32x8_ps to extract _m256 from _m512 +template EIGEN_STRONG_INLINE Packet8f extract256(Packet16f x) { + return _mm256_castsi256_ps(_mm512_extracti64x4_epi64( _mm512_castps_si512(x),I_)); +} + +// AVX512F does not define _mm512_extractf64x2_pd to extract _m128 from _m512 +template EIGEN_STRONG_INLINE Packet2d extract128(Packet8d x) { + return _mm_castsi128_pd(_mm512_extracti32x4_epi32( _mm512_castpd_si512(x),I_)); +} + +EIGEN_STRONG_INLINE Packet16f cat256(Packet8f a, Packet8f b) { + return _mm512_castsi512_ps(_mm512_inserti64x4(_mm512_castsi256_si512(_mm256_castps_si256(a)), + _mm256_castps_si256(b),1)); +} +#endif + +// Helper function for bit packing snippet of low precision comparison. +// It packs the flags from 32x16 to 16x16. +EIGEN_STRONG_INLINE __m256i Pack32To16(Packet16f rf) { + // Split data into small pieces and handle with AVX instructions + // to guarantee internal order of vector. + // Operation: + // dst[15:0] := Saturate16(rf[31:0]) + // dst[31:16] := Saturate16(rf[63:32]) + // ... + // dst[255:240] := Saturate16(rf[255:224]) + __m256i lo = _mm256_castps_si256(extract256<0>(rf)); + __m256i hi = _mm256_castps_si256(extract256<1>(rf)); + __m128i result_lo = _mm_packs_epi32(_mm256_extractf128_si256(lo, 0), + _mm256_extractf128_si256(lo, 1)); + __m128i result_hi = _mm_packs_epi32(_mm256_extractf128_si256(hi, 0), + _mm256_extractf128_si256(hi, 1)); + return _mm256_insertf128_si256(_mm256_castsi128_si256(result_lo), result_hi, 1); +} + +template <> +EIGEN_STRONG_INLINE Packet16i pand(const Packet16i& a, + const Packet16i& b) { + return _mm512_and_si512(a,b); } template <> @@ -255,24 +322,7 @@ EIGEN_STRONG_INLINE Packet16f pand(const Packet16f& a, #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_and_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_and_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_and_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_and_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_and_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pand(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } template <> @@ -288,35 +338,21 @@ EIGEN_STRONG_INLINE Packet8d pand(const Packet8d& a, Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_and_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_insertf64x4(res, _mm256_and_pd(lane1_a, lane1_b), 1); #endif } + template <> -EIGEN_STRONG_INLINE Packet16f por(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i por(const Packet16i& a, const Packet16i& b) { + return _mm512_or_si512(a, b); +} + +template <> +EIGEN_STRONG_INLINE Packet16f por(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_or_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_or_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_or_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_or_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_or_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(por(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } @@ -326,109 +362,67 @@ EIGEN_STRONG_INLINE Packet8d por(const Packet8d& a, #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_or_pd(a, b); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_or_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_or_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(por(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet16f pxor(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i pxor(const Packet16i& a, const Packet16i& b) { + return _mm512_xor_si512(a, b); +} + +template <> +EIGEN_STRONG_INLINE Packet16f pxor(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_xor_ps(a, b); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_xor_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pxor(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } + template <> -EIGEN_STRONG_INLINE Packet8d pxor(const Packet8d& a, - const Packet8d& b) { +EIGEN_STRONG_INLINE Packet8d pxor(const Packet8d& a, const Packet8d& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ return _mm512_xor_pd(a, b); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_xor_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_xor_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(pxor(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet16f pandnot(const Packet16f& a, - const Packet16f& b) { +EIGEN_STRONG_INLINE Packet16i pandnot(const Packet16i& a, const Packet16i& b) { + return _mm512_andnot_si512(b, a); +} + +template <> +EIGEN_STRONG_INLINE Packet16f pandnot(const Packet16f& a, const Packet16f& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ - return _mm512_andnot_ps(a, b); + return _mm512_andnot_ps(b, a); #else - Packet16f res = _mm512_undefined_ps(); - Packet4f lane0_a = _mm512_extractf32x4_ps(a, 0); - Packet4f lane0_b = _mm512_extractf32x4_ps(b, 0); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane0_a, lane0_b), 0); - - Packet4f lane1_a = _mm512_extractf32x4_ps(a, 1); - Packet4f lane1_b = _mm512_extractf32x4_ps(b, 1); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane1_a, lane1_b), 1); - - Packet4f lane2_a = _mm512_extractf32x4_ps(a, 2); - Packet4f lane2_b = _mm512_extractf32x4_ps(b, 2); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane2_a, lane2_b), 2); - - Packet4f lane3_a = _mm512_extractf32x4_ps(a, 3); - Packet4f lane3_b = _mm512_extractf32x4_ps(b, 3); - res = _mm512_insertf32x4(res, _mm_andnot_ps(lane3_a, lane3_b), 3); - - return res; + return _mm512_castsi512_ps(pandnot(_mm512_castps_si512(a),_mm512_castps_si512(b))); #endif } template <> -EIGEN_STRONG_INLINE Packet8d pandnot(const Packet8d& a, - const Packet8d& b) { +EIGEN_STRONG_INLINE Packet8d pandnot(const Packet8d& a,const Packet8d& b) { #ifdef EIGEN_VECTORIZE_AVX512DQ - return _mm512_andnot_pd(a, b); + return _mm512_andnot_pd(b, a); #else - Packet8d res = _mm512_undefined_pd(); - Packet4d lane0_a = _mm512_extractf64x4_pd(a, 0); - Packet4d lane0_b = _mm512_extractf64x4_pd(b, 0); - res = _mm512_insertf64x4(res, _mm256_andnot_pd(lane0_a, lane0_b), 0); - - Packet4d lane1_a = _mm512_extractf64x4_pd(a, 1); - Packet4d lane1_b = _mm512_extractf64x4_pd(b, 1); - res = _mm512_insertf64x4(res, _mm256_andnot_pd(lane1_a, lane1_b), 1); - - return res; + return _mm512_castsi512_pd(pandnot(_mm512_castpd_si512(a),_mm512_castpd_si512(b))); #endif } +template EIGEN_STRONG_INLINE Packet16i parithmetic_shift_right(Packet16i a) { + return _mm512_srai_epi32(a, N); +} + +template EIGEN_STRONG_INLINE Packet16i plogical_shift_right(Packet16i a) { + return _mm512_srli_epi32(a, N); +} + +template EIGEN_STRONG_INLINE Packet16i plogical_shift_left(Packet16i a) { + return _mm512_slli_epi32(a, N); +} + template <> EIGEN_STRONG_INLINE Packet16f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm512_load_ps(from); @@ -461,75 +455,55 @@ EIGEN_STRONG_INLINE Packet16i ploadu(const int* from) { // {a0, a0 a1, a1, a2, a2, a3, a3, a4, a4, a5, a5, a6, a6, a7, a7} template <> EIGEN_STRONG_INLINE Packet16f ploaddup(const float* from) { - Packet8f lane0 = _mm256_broadcast_ps((const __m128*)(const void*)from); - // mimic an "inplace" permutation of the lower 128bits using a blend - lane0 = _mm256_blend_ps( - lane0, _mm256_castps128_ps256(_mm_permute_ps( - _mm256_castps256_ps128(lane0), _MM_SHUFFLE(1, 0, 1, 0))), - 15); - // then we can perform a consistent permutation on the global register to get - // everything in shape: - lane0 = _mm256_permute_ps(lane0, _MM_SHUFFLE(3, 3, 2, 2)); - - Packet8f lane1 = _mm256_broadcast_ps((const __m128*)(const void*)(from + 4)); - // mimic an "inplace" permutation of the lower 128bits using a blend - lane1 = _mm256_blend_ps( - lane1, _mm256_castps128_ps256(_mm_permute_ps( - _mm256_castps256_ps128(lane1), _MM_SHUFFLE(1, 0, 1, 0))), - 15); - // then we can perform a consistent permutation on the global register to get - // everything in shape: - lane1 = _mm256_permute_ps(lane1, _MM_SHUFFLE(3, 3, 2, 2)); + // an unaligned load is required here as there is no requirement + // on the alignment of input pointer 'from' + __m256i low_half = _mm256_loadu_si256(reinterpret_cast(from)); + __m512 even_elements = _mm512_castsi512_ps(_mm512_cvtepu32_epi64(low_half)); + __m512 pairs = _mm512_permute_ps(even_elements, _MM_SHUFFLE(2, 2, 0, 0)); + return pairs; +} #ifdef EIGEN_VECTORIZE_AVX512DQ - Packet16f res = _mm512_undefined_ps(); - return _mm512_insertf32x8(res, lane0, 0); - return _mm512_insertf32x8(res, lane1, 1); - return res; -#else - Packet16f res = _mm512_undefined_ps(); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 0), 0); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 1), 1); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 0), 2); - res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 1), 3); - return res; -#endif -} +// FIXME: this does not look optimal, better load a Packet4d and shuffle... // Loads 4 doubles from memory a returns the packet {a0, a0 a1, a1, a2, a2, a3, // a3} template <> EIGEN_STRONG_INLINE Packet8d ploaddup(const double* from) { - Packet4d lane0 = _mm256_broadcast_pd((const __m128d*)(const void*)from); - lane0 = _mm256_permute_pd(lane0, 3 << 2); - - Packet4d lane1 = _mm256_broadcast_pd((const __m128d*)(const void*)(from + 2)); - lane1 = _mm256_permute_pd(lane1, 3 << 2); - - Packet8d res = _mm512_undefined_pd(); - res = _mm512_insertf64x4(res, lane0, 0); - return _mm512_insertf64x4(res, lane1, 1); + __m512d x = _mm512_setzero_pd(); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[0]), 0); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[1]), 1); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[2]), 2); + x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[3]), 3); + return x; } +#else +template <> +EIGEN_STRONG_INLINE Packet8d ploaddup(const double* from) { + __m512d x = _mm512_setzero_pd(); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<0, _mm_load_sd(from+0)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<2, _mm_load_sd(from+1)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<4, _mm_load_sd(from+2)); + x = _mm512_mask_broadcastsd_pd(x, 0x3<<6, _mm_load_sd(from+3)); + return x; +} +#endif // Loads 4 floats from memory a returns the packet // {a0, a0 a0, a0, a1, a1, a1, a1, a2, a2, a2, a2, a3, a3, a3, a3} template <> EIGEN_STRONG_INLINE Packet16f ploadquad(const float* from) { - Packet16f tmp = _mm512_undefined_ps(); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from), 0); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 1), 1); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 2), 2); - tmp = _mm512_insertf32x4(tmp, _mm_load_ps1(from + 3), 3); - return tmp; + Packet16f tmp = _mm512_castps128_ps512(ploadu(from)); + const Packet16i scatter_mask = _mm512_set_epi32(3,3,3,3, 2,2,2,2, 1,1,1,1, 0,0,0,0); + return _mm512_permutexvar_ps(scatter_mask, tmp); } + // Loads 2 doubles from memory a returns the packet // {a0, a0 a0, a0, a1, a1, a1, a1} template <> EIGEN_STRONG_INLINE Packet8d ploadquad(const double* from) { - Packet8d tmp = _mm512_undefined_pd(); - Packet2d tmp0 = _mm_load_pd1(from); - Packet2d tmp1 = _mm_load_pd1(from + 1); - Packet4d lane0 = _mm256_broadcastsd_pd(tmp0); - Packet4d lane1 = _mm256_broadcastsd_pd(tmp1); + __m256d lane0 = _mm256_set1_pd(*from); + __m256d lane1 = _mm256_set1_pd(*(from+1)); + __m512d tmp = _mm512_undefined_pd(); tmp = _mm512_insertf64x4(tmp, lane0, 0); return _mm512_insertf64x4(tmp, lane1, 1); } @@ -565,7 +539,7 @@ EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet16i& from) { template <> EIGEN_DEVICE_FUNC inline Packet16f pgather(const float* from, Index stride) { - Packet16i stride_vector = _mm512_set1_epi32(stride); + Packet16i stride_vector = _mm512_set1_epi32(convert_index(stride)); Packet16i stride_multiplier = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); Packet16i indices = _mm512_mullo_epi32(stride_vector, stride_multiplier); @@ -575,7 +549,7 @@ EIGEN_DEVICE_FUNC inline Packet16f pgather(const float* from, template <> EIGEN_DEVICE_FUNC inline Packet8d pgather(const double* from, Index stride) { - Packet8i stride_vector = _mm256_set1_epi32(stride); + Packet8i stride_vector = _mm256_set1_epi32(convert_index(stride)); Packet8i stride_multiplier = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); Packet8i indices = _mm256_mullo_epi32(stride_vector, stride_multiplier); @@ -586,7 +560,7 @@ template <> EIGEN_DEVICE_FUNC inline void pscatter(float* to, const Packet16f& from, Index stride) { - Packet16i stride_vector = _mm512_set1_epi32(stride); + Packet16i stride_vector = _mm512_set1_epi32(convert_index(stride)); Packet16i stride_multiplier = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); Packet16i indices = _mm512_mullo_epi32(stride_vector, stride_multiplier); @@ -596,7 +570,7 @@ template <> EIGEN_DEVICE_FUNC inline void pscatter(double* to, const Packet8d& from, Index stride) { - Packet8i stride_vector = _mm256_set1_epi32(stride); + Packet8i stride_vector = _mm256_set1_epi32(convert_index(stride)); Packet8i stride_multiplier = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); Packet8i indices = _mm256_mullo_epi32(stride_vector, stride_multiplier); _mm512_i32scatter_pd(to, indices, from, 8); @@ -618,9 +592,9 @@ EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) { pstore(to, pa); } -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template <> EIGEN_STRONG_INLINE float pfirst(const Packet16f& a) { @@ -648,20 +622,20 @@ template<> EIGEN_STRONG_INLINE Packet8d preverse(const Packet8d& a) template<> EIGEN_STRONG_INLINE Packet16f pabs(const Packet16f& a) { // _mm512_abs_ps intrinsic not found, so hack around it - return (__m512)_mm512_and_si512((__m512i)a, _mm512_set1_epi32(0x7fffffff)); + return _mm512_castsi512_ps(_mm512_and_si512(_mm512_castps_si512(a), _mm512_set1_epi32(0x7fffffff))); } template <> EIGEN_STRONG_INLINE Packet8d pabs(const Packet8d& a) { // _mm512_abs_ps intrinsic not found, so hack around it - return (__m512d)_mm512_and_si512((__m512i)a, - _mm512_set1_epi64(0x7fffffffffffffff)); + return _mm512_castsi512_pd(_mm512_and_si512(_mm512_castpd_si512(a), + _mm512_set1_epi64(0x7fffffffffffffff))); } #ifdef EIGEN_VECTORIZE_AVX512DQ // AVX512F does not define _mm512_extractf32x8_ps to extract _m256 from _m512 #define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \ - __m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0) __m256 OUTPUT##_1 = \ - _mm512_extractf32x8_ps(INPUT, 1) + __m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0); \ + __m256 OUTPUT##_1 = _mm512_extractf32x8_ps(INPUT, 1) #else #define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \ __m256 OUTPUT##_0 = _mm256_insertf128_ps( \ @@ -674,17 +648,136 @@ EIGEN_STRONG_INLINE Packet8d pabs(const Packet8d& a) { #ifdef EIGEN_VECTORIZE_AVX512DQ #define EIGEN_INSERT_8f_INTO_16f(OUTPUT, INPUTA, INPUTB) \ - OUTPUT = _mm512_insertf32x8(OUTPUT, INPUTA, 0); \ - OUTPUT = _mm512_insertf32x8(OUTPUT, INPUTB, 1); + OUTPUT = _mm512_insertf32x8(_mm512_castps256_ps512(INPUTA), INPUTB, 1); #else #define EIGEN_INSERT_8f_INTO_16f(OUTPUT, INPUTA, INPUTB) \ + OUTPUT = _mm512_undefined_ps(); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTA, 0), 0); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTA, 1), 1); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTB, 0), 2); \ OUTPUT = _mm512_insertf32x4(OUTPUT, _mm256_extractf128_ps(INPUTB, 1), 3); #endif -template<> EIGEN_STRONG_INLINE Packet16f preduxp(const Packet16f* -vecs) + +template <> +EIGEN_STRONG_INLINE float predux(const Packet16f& a) { +#ifdef EIGEN_VECTORIZE_AVX512DQ + __m256 lane0 = _mm512_extractf32x8_ps(a, 0); + __m256 lane1 = _mm512_extractf32x8_ps(a, 1); + Packet8f x = _mm256_add_ps(lane0, lane1); + return predux(x); +#else + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 sum = _mm_add_ps(_mm_add_ps(lane0, lane1), _mm_add_ps(lane2, lane3)); + sum = _mm_hadd_ps(sum, sum); + sum = _mm_hadd_ps(sum, _mm_permute_ps(sum, 1)); + return _mm_cvtss_f32(sum); +#endif +} +template <> +EIGEN_STRONG_INLINE double predux(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d sum = _mm256_add_pd(lane0, lane1); + __m256d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1)); + return _mm_cvtsd_f64(_mm256_castpd256_pd128(_mm256_hadd_pd(tmp0, tmp0))); +} + +template <> +EIGEN_STRONG_INLINE Packet8f predux_downto4(const Packet16f& a) { +#ifdef EIGEN_VECTORIZE_AVX512DQ + Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); + Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); + return padd(lane0, lane1); +#else + Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); + Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); + Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); + Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); + Packet4f sum0 = padd(lane0, lane2); + Packet4f sum1 = padd(lane1, lane3); + return _mm256_insertf128_ps(_mm256_castps128_ps256(sum0), sum1, 1); +#endif +} +template <> +EIGEN_STRONG_INLINE Packet4d predux_downto4(const Packet8d& a) { + Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); + Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); + Packet4d res = padd(lane0, lane1); + return res; +} + +template <> +EIGEN_STRONG_INLINE float predux_mul(const Packet16f& a) { +//#ifdef EIGEN_VECTORIZE_AVX512DQ +#if 0 + Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); + Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); + Packet8f res = pmul(lane0, lane1); + res = pmul(res, _mm256_permute2f128_ps(res, res, 1)); + res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +#else + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = pmul(pmul(lane0, lane1), pmul(lane2, lane3)); + res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +#endif +} +template <> +EIGEN_STRONG_INLINE double predux_mul(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = pmul(lane0, lane1); + res = pmul(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1))); +} + +template <> +EIGEN_STRONG_INLINE float predux_min(const Packet16f& a) { + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3)); + res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +} +template <> +EIGEN_STRONG_INLINE double predux_min(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = _mm256_min_pd(lane0, lane1); + res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1))); +} + +template <> +EIGEN_STRONG_INLINE float predux_max(const Packet16f& a) { + __m128 lane0 = _mm512_extractf32x4_ps(a, 0); + __m128 lane1 = _mm512_extractf32x4_ps(a, 1); + __m128 lane2 = _mm512_extractf32x4_ps(a, 2); + __m128 lane3 = _mm512_extractf32x4_ps(a, 3); + __m128 res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3)); + res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); + return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); +} + +template <> +EIGEN_STRONG_INLINE double predux_max(const Packet8d& a) { + __m256d lane0 = _mm512_extractf64x4_pd(a, 0); + __m256d lane1 = _mm512_extractf64x4_pd(a, 1); + __m256d res = _mm256_max_pd(lane0, lane1); + res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1)); + return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1))); +} + +template<> EIGEN_STRONG_INLINE Packet16f preduxp(const Packet16f* vecs) { EIGEN_EXTRACT_8f_FROM_16f(vecs[0], vecs0); EIGEN_EXTRACT_8f_FROM_16f(vecs[1], vecs1); @@ -873,174 +966,7 @@ template<> EIGEN_STRONG_INLINE Packet8d preduxp(const Packet8d* vecs) return _mm512_insertf64x4(final_output, final_1, 1); } - -template <> -EIGEN_STRONG_INLINE float predux(const Packet16f& a) { - //#ifdef EIGEN_VECTORIZE_AVX512DQ -#if 0 - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - Packet8f sum = padd(lane0, lane1); - Packet8f tmp0 = _mm256_hadd_ps(sum, _mm256_permute2f128_ps(a, a, 1)); - tmp0 = _mm256_hadd_ps(tmp0, tmp0); - return pfirst(_mm256_hadd_ps(tmp0, tmp0)); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f sum = padd(padd(lane0, lane1), padd(lane2, lane3)); - sum = _mm_hadd_ps(sum, sum); - sum = _mm_hadd_ps(sum, _mm_permute_ps(sum, 1)); - return pfirst(sum); -#endif -} -template <> -EIGEN_STRONG_INLINE double predux(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d sum = padd(lane0, lane1); - Packet4d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1)); - return pfirst(_mm256_hadd_pd(tmp0, tmp0)); -} - -template <> -EIGEN_STRONG_INLINE Packet8f predux_downto4(const Packet16f& a) { -#ifdef EIGEN_VECTORIZE_AVX512DQ - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - return padd(lane0, lane1); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f sum0 = padd(lane0, lane2); - Packet4f sum1 = padd(lane1, lane3); - return _mm256_insertf128_ps(_mm256_castps128_ps256(sum0), sum1, 1); -#endif -} -template <> -EIGEN_STRONG_INLINE Packet4d predux_downto4(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = padd(lane0, lane1); - return res; -} - -template <> -EIGEN_STRONG_INLINE float predux_mul(const Packet16f& a) { -//#ifdef EIGEN_VECTORIZE_AVX512DQ -#if 0 - Packet8f lane0 = _mm512_extractf32x8_ps(a, 0); - Packet8f lane1 = _mm512_extractf32x8_ps(a, 1); - Packet8f res = pmul(lane0, lane1); - res = pmul(res, _mm256_permute2f128_ps(res, res, 1)); - res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -#else - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = pmul(pmul(lane0, lane1), pmul(lane2, lane3)); - res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -#endif -} -template <> -EIGEN_STRONG_INLINE double predux_mul(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = pmul(lane0, lane1); - res = pmul(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1))); -} - -template <> -EIGEN_STRONG_INLINE float predux_min(const Packet16f& a) { - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3)); - res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -} -template <> -EIGEN_STRONG_INLINE double predux_min(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = _mm256_min_pd(lane0, lane1); - res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1))); -} - -template <> -EIGEN_STRONG_INLINE float predux_max(const Packet16f& a) { - Packet4f lane0 = _mm512_extractf32x4_ps(a, 0); - Packet4f lane1 = _mm512_extractf32x4_ps(a, 1); - Packet4f lane2 = _mm512_extractf32x4_ps(a, 2); - Packet4f lane3 = _mm512_extractf32x4_ps(a, 3); - Packet4f res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3)); - res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2))); - return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1)))); -} -template <> -EIGEN_STRONG_INLINE double predux_max(const Packet8d& a) { - Packet4d lane0 = _mm512_extractf64x4_pd(a, 0); - Packet4d lane1 = _mm512_extractf64x4_pd(a, 1); - Packet4d res = _mm256_max_pd(lane0, lane1); - res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1)); - return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1))); -} - -template -struct palign_impl { - static EIGEN_STRONG_INLINE void run(Packet16f& first, - const Packet16f& second) { - if (Offset != 0) { - __m512i first_idx = _mm512_set_epi32( - Offset + 15, Offset + 14, Offset + 13, Offset + 12, Offset + 11, - Offset + 10, Offset + 9, Offset + 8, Offset + 7, Offset + 6, - Offset + 5, Offset + 4, Offset + 3, Offset + 2, Offset + 1, Offset); - - __m512i second_idx = - _mm512_set_epi32(Offset - 1, Offset - 2, Offset - 3, Offset - 4, - Offset - 5, Offset - 6, Offset - 7, Offset - 8, - Offset - 9, Offset - 10, Offset - 11, Offset - 12, - Offset - 13, Offset - 14, Offset - 15, Offset - 16); - - unsigned short mask = 0xFFFF; - mask <<= (16 - Offset); - - first = _mm512_permutexvar_ps(first_idx, first); - Packet16f tmp = _mm512_permutexvar_ps(second_idx, second); - first = _mm512_mask_blend_ps(mask, first, tmp); - } - } -}; -template -struct palign_impl { - static EIGEN_STRONG_INLINE void run(Packet8d& first, const Packet8d& second) { - if (Offset != 0) { - __m512i first_idx = _mm512_set_epi32( - 0, Offset + 7, 0, Offset + 6, 0, Offset + 5, 0, Offset + 4, 0, - Offset + 3, 0, Offset + 2, 0, Offset + 1, 0, Offset); - - __m512i second_idx = _mm512_set_epi32( - 0, Offset - 1, 0, Offset - 2, 0, Offset - 3, 0, Offset - 4, 0, - Offset - 5, 0, Offset - 6, 0, Offset - 7, 0, Offset - 8); - - unsigned char mask = 0xFF; - mask <<= (8 - Offset); - - first = _mm512_permutexvar_pd(first_idx, first); - Packet8d tmp = _mm512_permutexvar_pd(second_idx, second); - first = _mm512_mask_blend_pd(mask, first, tmp); - } - } -}; + #define PACK_OUTPUT(OUTPUT, INPUT, INDEX, STRIDE) \ @@ -1302,13 +1228,76 @@ EIGEN_STRONG_INLINE Packet16f pblend(const Selector<16>& /*ifPacket*/, return Packet16f(); } template <> -EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& /*ifPacket*/, - const Packet8d& /*thenPacket*/, - const Packet8d& /*elsePacket*/) { - assert(false && "To be implemented"); - return Packet8d(); +EIGEN_STRONG_INLINE Packet8d pblend(const Selector<8>& ifPacket, + const Packet8d& thenPacket, + const Packet8d& elsePacket) { + __mmask8 m = (ifPacket.select[0] ) + | (ifPacket.select[1]<<1) + | (ifPacket.select[2]<<2) + | (ifPacket.select[3]<<3) + | (ifPacket.select[4]<<4) + | (ifPacket.select[5]<<5) + | (ifPacket.select[6]<<6) + | (ifPacket.select[7]<<7); + return _mm512_mask_blend_pd(m, elsePacket, thenPacket); } +template<> EIGEN_STRONG_INLINE Packet16i pcast(const Packet16f& a) { + return _mm512_cvttps_epi32(a); +} + +template<> EIGEN_STRONG_INLINE Packet16f pcast(const Packet16i& a) { + return _mm512_cvtepi32_ps(a); +} + +template +struct palign_impl { + static EIGEN_STRONG_INLINE void run(Packet16f& first, + const Packet16f& second) { + if (Offset != 0) { + __m512i first_idx = _mm512_set_epi32( + Offset + 15, Offset + 14, Offset + 13, Offset + 12, Offset + 11, + Offset + 10, Offset + 9, Offset + 8, Offset + 7, Offset + 6, + Offset + 5, Offset + 4, Offset + 3, Offset + 2, Offset + 1, Offset); + + __m512i second_idx = + _mm512_set_epi32(Offset - 1, Offset - 2, Offset - 3, Offset - 4, + Offset - 5, Offset - 6, Offset - 7, Offset - 8, + Offset - 9, Offset - 10, Offset - 11, Offset - 12, + Offset - 13, Offset - 14, Offset - 15, Offset - 16); + + unsigned short mask = 0xFFFF; + mask <<= (16 - Offset); + + first = _mm512_permutexvar_ps(first_idx, first); + Packet16f tmp = _mm512_permutexvar_ps(second_idx, second); + first = _mm512_mask_blend_ps(mask, first, tmp); + } + } +}; +template +struct palign_impl { + static EIGEN_STRONG_INLINE void run(Packet8d& first, const Packet8d& second) { + if (Offset != 0) { + __m512i first_idx = _mm512_set_epi32( + 0, Offset + 7, 0, Offset + 6, 0, Offset + 5, 0, Offset + 4, 0, + Offset + 3, 0, Offset + 2, 0, Offset + 1, 0, Offset); + + __m512i second_idx = _mm512_set_epi32( + 0, Offset - 1, 0, Offset - 2, 0, Offset - 3, 0, Offset - 4, 0, + Offset - 5, 0, Offset - 6, 0, Offset - 7, 0, Offset - 8); + + unsigned char mask = 0xFF; + mask <<= (8 - Offset); + + first = _mm512_permutexvar_pd(first_idx, first); + Packet8d tmp = _mm512_permutexvar_pd(second_idx, second); + first = _mm512_mask_blend_pd(mask, first, tmp); + } + } +}; + + } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h b/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h index 59367ba2..32590a53 100644 --- a/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/AltiVec/Complex.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX32_ALTIVEC_H #define EIGEN_COMPLEX32_ALTIVEC_H @@ -65,7 +65,7 @@ template<> struct unpacket_traits { typedef std::complex type; template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex& from) { Packet2cf res; - if((ptrdiff_t(&from) % 16) == 0) + if((std::ptrdiff_t(&from) % 16) == 0) res.v = pload((const float *)&from); else res.v = ploadu((const float *)&from); @@ -224,23 +224,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -416,23 +400,8 @@ template<> struct conj_helper return pconj(internal::pmul(a, b)); } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/AltiVec/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/AltiVec/MathFunctions.h index c5e4bede..e2c4ece2 100644 --- a/eigenlib/Eigen/src/Core/arch/AltiVec/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/AltiVec/MathFunctions.h @@ -7,10 +7,10 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* The sin, cos, exp, and log functions of this file come from - * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ + * Julien Pommier's sse math library: xxxp://gruntthepeon.free.fr/ssemath/ */ #ifndef EIGEN_MATH_FUNCTIONS_ALTIVEC_H @@ -230,7 +230,7 @@ Packet2d psqrt(const Packet2d& x) // vec_cts to efficiently convert Packet2d to Packet2l. Otherwise, use // a slow version that works with older compilers. // Update: apparently vec_cts/vec_ctf intrinsics for 64-bit doubles -// are buggy, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70963 +// are buggy, xxxps://gcc.gnu.org/bugzilla/show_bug.cgi?id=70963 static inline Packet2l ConvertToPacket2l(const Packet2d& x) { #if EIGEN_GNUC_AT_LEAST(5, 4) || \ (EIGEN_GNUC_AT(6, 1) && __GNUC_PATCHLEVEL__ >= 1) diff --git a/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h b/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h index e7d4f4d8..ccf3bc15 100755 --- a/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/AltiVec/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_ALTIVEC_H #define EIGEN_PACKET_MATH_ALTIVEC_H @@ -90,7 +90,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 }; #define _EIGEN_MASK_ALIGNMENT 0xfffffff0 #endif -#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) +#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) // Handle endianness properly while loading constants // Define global static constants: @@ -103,7 +103,7 @@ static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4u static Packet16uc p16uc_PSET32_WEVEN = vec_sld(p16uc_DUPLICATE32_HI, (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; static Packet16uc p16uc_HALF64_0_16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8); //{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16}; #else -static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; +static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; static Packet16uc p16uc_REVERSE64 = { 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 }; static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 1), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 }; static Packet16uc p16uc_PSET32_WEVEN = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; @@ -388,10 +388,28 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, co template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return vec_madd(a,b,c); } template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return a*b + c; } -template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgesp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_min(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmin(const Packet4i& a, const Packet4i& b) { return vec_min(a, b); } -template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgtsp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_max(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmax(const Packet4i& a, const Packet4i& b) { return vec_max(a, b); } template<> EIGEN_STRONG_INLINE Packet4f pand(const Packet4f& a, const Packet4f& b) { return vec_and(a, b); } @@ -425,7 +443,7 @@ template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD - // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html + // Taken from xxxp://developer.apple.com/hardwaredrivers/ve/alignment.html Packet16uc MSQ, LSQ; Packet16uc mask; MSQ = vec_ld(0, (unsigned char *)from); // most significant quadword @@ -450,15 +468,15 @@ template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { Packet4f p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_perm(p, p, p16uc_DUPLICATE32_HI); } template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) { Packet4i p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_perm(p, p, p16uc_DUPLICATE32_HI); } @@ -466,7 +484,7 @@ template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE - // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html + // Taken from xxxp://developer.apple.com/hardwaredrivers/ve/alignment.html // Warning: not thread safe! Packet16uc MSQ, LSQ, edges; Packet16uc edgeAlign, align; @@ -484,7 +502,7 @@ template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& f template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE - // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html + // Taken from xxxp://developer.apple.com/hardwaredrivers/ve/alignment.html // Warning: not thread safe! Packet16uc MSQ, LSQ, edges; Packet16uc edgeAlign, align; @@ -545,7 +563,7 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp(const Packet4f* vecs) Packet4f v[4], sum[4]; // It's easier and faster to transpose then add as columns - // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation + // Check: xxxp://www.freevec.org/function/matrix_4x4_transpose_floats for explanation // Do the transpose, first set of moves v[0] = vec_mergeh(vecs[0], vecs[2]); v[1] = vec_mergel(vecs[0], vecs[2]); @@ -585,7 +603,7 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp(const Packet4i* vecs) Packet4i v[4], sum[4]; // It's easier and faster to transpose then add as columns - // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation + // Check: xxxp://www.freevec.org/function/matrix_4x4_transpose_floats for explanation // Do the transpose, first set of moves v[0] = vec_mergeh(vecs[0], vecs[2]); v[1] = vec_mergel(vecs[0], vecs[2]); @@ -764,7 +782,7 @@ typedef __vector __bool long Packet2bl; static Packet2l p2l_ONE = { 1, 1 }; static Packet2l p2l_ZERO = reinterpret_cast(p4i_ZERO); -static Packet2d p2d_ONE = { 1.0, 1.0 }; +static Packet2d p2d_ONE = { 1.0, 1.0 }; static Packet2d p2d_ZERO = reinterpret_cast(p4f_ZERO); static Packet2d p2d_MZERO = { -0.0, -0.0 }; @@ -910,9 +928,19 @@ template<> EIGEN_STRONG_INLINE Packet2d pdiv(const Packet2d& a, const // for some weird raisons, it has to be overloaded for packet of integers template<> EIGEN_STRONG_INLINE Packet2d pmadd(const Packet2d& a, const Packet2d& b, const Packet2d& c) { return vec_madd(a, b, c); } -template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgedp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + } -template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgtdp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; +} template<> EIGEN_STRONG_INLINE Packet2d pand(const Packet2d& a, const Packet2d& b) { return vec_and(a, b); } @@ -935,8 +963,8 @@ template<> EIGEN_STRONG_INLINE Packet2d ploadu(const double* from) template<> EIGEN_STRONG_INLINE Packet2d ploaddup(const double* from) { Packet2d p; - if((ptrdiff_t(from) % 16) == 0) p = pload(from); - else p = ploadu(from); + if((std::ptrdiff_t(from) % 16) == 0) p = pload(from); + else p = ploadu(from); return vec_splat_dbl<0>(p); } @@ -969,7 +997,7 @@ template<> EIGEN_STRONG_INLINE Packet2d preduxp(const Packet2d* vecs) Packet2d v[2], sum; v[0] = vecs[0] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[0]), reinterpret_cast(vecs[0]), 8)); v[1] = vecs[1] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[1]), reinterpret_cast(vecs[1]), 8)); - + #ifdef _BIG_ENDIAN sum = reinterpret_cast(vec_sld(reinterpret_cast(v[0]), reinterpret_cast(v[1]), 8)); #else @@ -1022,7 +1050,7 @@ ptranspose(PacketBlock& kernel) { template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket, const Packet2d& elsePacket) { Packet2l select = { ifPacket.select[0], ifPacket.select[1] }; - Packet2bl mask = vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)); + Packet2bl mask = reinterpret_cast( vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)) ); return vec_sel(elsePacket, thenPacket, mask); } #endif // __VSX__ diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/Complex.h b/eigenlib/Eigen/src/Core/arch/CUDA/Complex.h index 9c253650..e82b52fb 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/Complex.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_CUDA_H #define EIGEN_COMPLEX_CUDA_H diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/Half.h b/eigenlib/Eigen/src/Core/arch/CUDA/Half.h index 52892db3..436f15d3 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/Half.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/Half.h @@ -3,7 +3,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // // The conversion routines are Copyright (c) Fabian Giesen, 2016. // The original license follows: @@ -13,7 +13,7 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -29,7 +29,7 @@ // type Eigen::half (inheriting from CUDA's __half struct) with // operator overloads such that it behaves basically as an arithmetic // type. It will be quite slow on CPUs (so it is recommended to stay -// in fp32 for CPUs, except for simple parameter conversions, I/O +// in float32_bits for CPUs, except for simple parameter conversions, I/O // to disk and the likes), but fast on GPUs. @@ -42,6 +42,7 @@ #define EIGEN_EXPLICIT_CAST(tgt_type) operator tgt_type() #endif +#include namespace Eigen { @@ -50,38 +51,45 @@ struct half; namespace half_impl { #if !defined(EIGEN_HAS_CUDA_FP16) - -// Make our own __half definition that is similar to CUDA's. -struct __half { - EIGEN_DEVICE_FUNC __half() {} - explicit EIGEN_DEVICE_FUNC __half(unsigned short raw) : x(raw) {} +// Make our own __half_raw definition that is similar to CUDA's. +struct __half_raw { + EIGEN_DEVICE_FUNC __half_raw() : x(0) {} + explicit EIGEN_DEVICE_FUNC __half_raw(unsigned short raw) : x(raw) {} unsigned short x; }; - +#elif defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER < 90000 +// In CUDA < 9.0, __half is the equivalent of CUDA 9's __half_raw +typedef __half __half_raw; #endif -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half raw_uint16_to_half(unsigned short x); -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff); -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw raw_uint16_to_half(unsigned short x); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw float_to_half_rtne(float ff); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half_raw h); -struct half_base : public __half { +struct half_base : public __half_raw { EIGEN_DEVICE_FUNC half_base() {} - EIGEN_DEVICE_FUNC half_base(const half_base& h) : __half(h) {} - EIGEN_DEVICE_FUNC half_base(const __half& h) : __half(h) {} + EIGEN_DEVICE_FUNC half_base(const half_base& h) : __half_raw(h) {} + EIGEN_DEVICE_FUNC half_base(const __half_raw& h) : __half_raw(h) {} +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER >= 90000 + EIGEN_DEVICE_FUNC half_base(const __half& h) : __half_raw(*(__half_raw*)&h) {} +#endif }; } // namespace half_impl // Class definition. struct half : public half_impl::half_base { - #if !defined(EIGEN_HAS_CUDA_FP16) - typedef half_impl::__half __half; + #if !defined(EIGEN_HAS_CUDA_FP16) || (defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER < 90000) + typedef half_impl::__half_raw __half_raw; #endif EIGEN_DEVICE_FUNC half() {} - EIGEN_DEVICE_FUNC half(const __half& h) : half_impl::half_base(h) {} + EIGEN_DEVICE_FUNC half(const __half_raw& h) : half_impl::half_base(h) {} EIGEN_DEVICE_FUNC half(const half& h) : half_impl::half_base(h) {} +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDACC_VER) && EIGEN_CUDACC_VER >= 90000 + EIGEN_DEVICE_FUNC half(const __half& h) : half_impl::half_base(h) {} +#endif explicit EIGEN_DEVICE_FUNC half(bool b) : half_impl::half_base(half_impl::raw_uint16_to_half(b ? 0x3c00 : 0)) {} @@ -138,71 +146,125 @@ struct half : public half_impl::half_base { } }; +} // end namespace Eigen + +namespace std { +template<> +struct numeric_limits { + static const bool is_specialized = true; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const bool has_infinity = true; + static const bool has_quiet_NaN = true; + static const bool has_signaling_NaN = true; + static const float_denorm_style has_denorm = denorm_present; + static const bool has_denorm_loss = false; + static const std::float_round_style round_style = std::round_to_nearest; + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const int digits = 11; + static const int digits10 = 3; // according to xxxp://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int max_digits10 = 5; // according to xxxp://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int radix = 2; + static const int min_exponent = -13; + static const int min_exponent10 = -4; + static const int max_exponent = 16; + static const int max_exponent10 = 4; + static const bool traps = true; + static const bool tinyness_before = false; + + static Eigen::half (min)() { return Eigen::half_impl::raw_uint16_to_half(0x400); } + static Eigen::half lowest() { return Eigen::half_impl::raw_uint16_to_half(0xfbff); } + static Eigen::half (max)() { return Eigen::half_impl::raw_uint16_to_half(0x7bff); } + static Eigen::half epsilon() { return Eigen::half_impl::raw_uint16_to_half(0x0800); } + static Eigen::half round_error() { return Eigen::half(0.5); } + static Eigen::half infinity() { return Eigen::half_impl::raw_uint16_to_half(0x7c00); } + static Eigen::half quiet_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half signaling_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half denorm_min() { return Eigen::half_impl::raw_uint16_to_half(0x1); } +}; + +// If std::numeric_limits is specialized, should also specialize +// std::numeric_limits, std::numeric_limits, and +// std::numeric_limits +// xxxps://stackoverflow.com/a/16519653/ +template<> +struct numeric_limits : numeric_limits {}; +template<> +struct numeric_limits : numeric_limits {}; +template<> +struct numeric_limits : numeric_limits {}; +} // end namespace std + +namespace Eigen { + namespace half_impl { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 // Intrinsics for native fp16 support. Note that on current hardware, -// these are no faster than fp32 arithmetic (you need to use the half2 +// these are no faster than float32_bits arithmetic (you need to use the half2 // versions to get the ALU speed increased), but you do save the // conversion steps back and forth. -__device__ half operator + (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator + (const half& a, const half& b) { return __hadd(a, b); } -__device__ half operator * (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator * (const half& a, const half& b) { return __hmul(a, b); } -__device__ half operator - (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a, const half& b) { return __hsub(a, b); } -__device__ half operator / (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator / (const half& a, const half& b) { float num = __half2float(a); float denom = __half2float(b); return __float2half(num / denom); } -__device__ half operator - (const half& a) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a) { return __hneg(a); } -__device__ half& operator += (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator += (half& a, const half& b) { a = a + b; return a; } -__device__ half& operator *= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator *= (half& a, const half& b) { a = a * b; return a; } -__device__ half& operator -= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator -= (half& a, const half& b) { a = a - b; return a; } -__device__ half& operator /= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator /= (half& a, const half& b) { a = a / b; return a; } -__device__ bool operator == (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator == (const half& a, const half& b) { return __heq(a, b); } -__device__ bool operator != (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator != (const half& a, const half& b) { return __hne(a, b); } -__device__ bool operator < (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator < (const half& a, const half& b) { return __hlt(a, b); } -__device__ bool operator <= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator <= (const half& a, const half& b) { return __hle(a, b); } -__device__ bool operator > (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator > (const half& a, const half& b) { return __hgt(a, b); } -__device__ bool operator >= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator >= (const half& a, const half& b) { return __hge(a, b); } #else // Emulate support for half floats // Definitions for CPUs and older CUDA, mostly working through conversion -// to/from fp32. +// to/from float32_bits. EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half operator + (const half& a, const half& b) { return half(float(a) + float(b)); @@ -238,10 +300,10 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half& operator /= (half& a, const half& b) return a; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator == (const half& a, const half& b) { - return float(a) == float(b); + return numext::equal_strict(float(a),float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator != (const half& a, const half& b) { - return float(a) != float(b); + return numext::not_equal_strict(float(a), float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator < (const half& a, const half& b) { return float(a) < float(b); @@ -269,34 +331,35 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half operator / (const half& a, Index b) { // these in hardware. If we need more performance on older/other CPUs, they are // also possible to vectorize directly. -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half raw_uint16_to_half(unsigned short x) { - __half h; +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw raw_uint16_to_half(unsigned short x) { + __half_raw h; h.x = x; return h; } -union FP32 { +union float32_bits { unsigned int u; float f; }; -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 - return __float2half(ff); +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half_raw float_to_half_rtne(float ff) { +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 + __half tmp_ff = __float2half(ff); + return *(__half_raw*)&tmp_ff; #elif defined(EIGEN_HAS_FP16_C) - __half h; + __half_raw h; h.x = _cvtss_sh(ff, 0); return h; #else - FP32 f; f.f = ff; + float32_bits f; f.f = ff; - const FP32 f32infty = { 255 << 23 }; - const FP32 f16max = { (127 + 16) << 23 }; - const FP32 denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; + const float32_bits f32infty = { 255 << 23 }; + const float32_bits f16max = { (127 + 16) << 23 }; + const float32_bits denorm_magic = { ((127 - 15) + (23 - 10) + 1) << 23 }; unsigned int sign_mask = 0x80000000u; - __half o; + __half_raw o; o.x = static_cast(0x0u); unsigned int sign = f.u & sign_mask; @@ -335,17 +398,17 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC __half float_to_half_rtne(float ff) { #endif } -EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half h) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 +EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC float half_to_float(__half_raw h) { +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 return __half2float(h); #elif defined(EIGEN_HAS_FP16_C) return _cvtsh_ss(h.x); #else - const FP32 magic = { 113 << 23 }; + const float32_bits magic = { 113 << 23 }; const unsigned int shifted_exp = 0x7c00 << 13; // exponent mask after shift - FP32 o; + float32_bits o; o.u = (h.x & 0x7fff) << 13; // exponent/mantissa bits unsigned int exp = shifted_exp & o.u; // just the exponent @@ -370,7 +433,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool (isinf)(const half& a) { return (a.x & 0x7fff) == 0x7c00; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool (isnan)(const half& a) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hisnan(a); #else return (a.x & 0x7fff) > 0x7c00; @@ -386,11 +449,15 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half& a) { return result; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half exp(const half& a) { - return half(::expf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hexp(a)); +#else + return half(::expf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& a) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 - return Eigen::half(::hlog(a)); +#if defined(EIGEN_HAS_CUDA_FP16) && EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 + return half(::hlog(a)); #else return half(::logf(float(a))); #endif @@ -402,7 +469,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) { return half(::log10f(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half sqrt(const half& a) { - return half(::sqrtf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hsqrt(a)); +#else + return half(::sqrtf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half& a, const half& b) { return half(::powf(float(a), float(b))); @@ -420,14 +491,22 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half tanh(const half& a) { return half(::tanhf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half floor(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hfloor(a)); +#else return half(::floorf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half ceil(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hceil(a)); +#else return half(::ceilf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hlt(b, a) ? b : a; #else const float f1 = static_cast(a); @@ -436,7 +515,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) { #endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (max)(const half& a, const half& b) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if defined(EIGEN_HAS_CUDA_FP16) && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return __hlt(a, b) ? b : a; #else const float f1 = static_cast(a); @@ -477,6 +556,13 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct NumTraits : GenericNumTraits { + enum { + IsSigned = true, + IsInteger = false, + IsComplex = false, + RequireInitialization = false + }; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half epsilon() { return half_impl::raw_uint16_to_half(0x0800); } @@ -507,7 +593,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half exph(const Eigen::half& a) { return Eigen::half(::expf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half logh(const Eigen::half& a) { -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return Eigen::half(::hlog(a)); #else return Eigen::half(::logf(float(a))); @@ -541,14 +627,18 @@ struct hash { // Add the missing shfl_xor intrinsic -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 300 +#if defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 300 __device__ EIGEN_STRONG_INLINE Eigen::half __shfl_xor(Eigen::half var, int laneMask, int width=warpSize) { + #if EIGEN_CUDACC_VER < 90000 return static_cast(__shfl_xor(static_cast(var), laneMask, width)); + #else + return static_cast(__shfl_xor_sync(0xFFFFFFFF, static_cast(var), laneMask, width)); + #endif } #endif -// ldg() has an overload for __half, but we also need one for Eigen::half. -#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 350 +// ldg() has an overload for __half_raw, but we also need one for Eigen::half. +#if defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 350 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) { return Eigen::half_impl::raw_uint16_to_half( __ldg(reinterpret_cast(ptr))); @@ -556,7 +646,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half __ldg(const Eigen::half* ptr) #endif -#if defined(__CUDA_ARCH__) +#if defined(EIGEN_CUDA_ARCH) namespace Eigen { namespace numext { diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/CUDA/MathFunctions.h index 0348b41d..df229ce1 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/MathFunctions.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATH_FUNCTIONS_CUDA_H #define EIGEN_MATH_FUNCTIONS_CUDA_H diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h index ad66399e..b4c55655 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_CUDA_H #define EIGEN_PACKET_MATH_CUDA_H @@ -291,7 +291,7 @@ template<> EIGEN_DEVICE_FUNC inline double2 pabs(const double2& a) { EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock& kernel) { - double tmp = kernel.packet[0].y; + float tmp = kernel.packet[0].y; kernel.packet[0].y = kernel.packet[1].x; kernel.packet[1].x = tmp; diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h index ae54225f..43378e23 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/PacketMathHalf.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_HALF_CUDA_H #define EIGEN_PACKET_MATH_HALF_CUDA_H @@ -99,7 +99,8 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& template<> __device__ EIGEN_STRONG_INLINE half2 pabs(const half2& a) { half2 result; - result.x = a.x & 0x7FFF7FFF; + unsigned temp = *(reinterpret_cast(&(a))); + *(reinterpret_cast(&(result))) = temp & 0x7FFF7FFF; return result; } @@ -229,7 +230,7 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux(const half2& #else float a1 = __low2float(a); float a2 = __high2float(a); - return Eigen::half(half_impl::raw_uint16_to_half(__float2half_rn(a1 + a2))); + return Eigen::half(__float2half_rn(a1 + a2)); #endif } @@ -263,7 +264,7 @@ template<> __device__ EIGEN_STRONG_INLINE Eigen::half predux_mul(const ha #else float a1 = __low2float(a); float a2 = __high2float(a); - return Eigen::half(half_impl::raw_uint16_to_half(__float2half_rn(a1 * a2))); + return Eigen::half(__float2half_rn(a1 * a2)); #endif } @@ -275,7 +276,7 @@ template<> __device__ EIGEN_STRONG_INLINE half2 plog1p(const half2& a) { return __floats2half2_rn(r1, r2); } -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 template<> __device__ EIGEN_STRONG_INLINE half2 plog(const half2& a) { diff --git a/eigenlib/Eigen/src/Core/arch/CUDA/TypeCasting.h b/eigenlib/Eigen/src/Core/arch/CUDA/TypeCasting.h index aa5fbce8..84c00611 100644 --- a/eigenlib/Eigen/src/Core/arch/CUDA/TypeCasting.h +++ b/eigenlib/Eigen/src/Core/arch/CUDA/TypeCasting.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TYPE_CASTING_CUDA_H #define EIGEN_TYPE_CASTING_CUDA_H diff --git a/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h b/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h new file mode 100644 index 00000000..279066e0 --- /dev/null +++ b/eigenlib/Eigen/src/Core/arch/Default/ConjHelper.h @@ -0,0 +1,29 @@ + +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2017 Gael Guennebaud +// +// 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 the mozilla.org home page + +#ifndef EIGEN_ARCH_CONJ_HELPER_H +#define EIGEN_ARCH_CONJ_HELPER_H + +#define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, const PACKET_CPLX& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x, y.v)); } \ + }; \ + \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, const PACKET_REAL& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x.v, y)); } \ + }; + +#endif // EIGEN_ARCH_CONJ_HELPER_H diff --git a/eigenlib/Eigen/src/Core/arch/Default/Settings.h b/eigenlib/Eigen/src/Core/arch/Default/Settings.h index 097373c8..2f2cf85d 100644 --- a/eigenlib/Eigen/src/Core/arch/Default/Settings.h +++ b/eigenlib/Eigen/src/Core/arch/Default/Settings.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* All the parameters defined in this file can be specialized in the diff --git a/eigenlib/Eigen/src/Core/arch/NEON/Complex.h b/eigenlib/Eigen/src/Core/arch/NEON/Complex.h index 57e9b431..097b3bb2 100644 --- a/eigenlib/Eigen/src/Core/arch/NEON/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/NEON/Complex.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_NEON_H #define EIGEN_COMPLEX_NEON_H @@ -67,7 +67,7 @@ template<> struct unpacket_traits { typedef std::complex type; template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex& from) { float32x2_t r64; - r64 = vld1_f32((float *)&from); + r64 = vld1_f32((const float *)&from); return Packet2cf(vcombine_f32(r64, r64)); } @@ -142,7 +142,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf to[stride*1] = std::complex(vgetq_lane_f32(from.v, 2), vgetq_lane_f32(from.v, 3)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((float *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const float *)addr); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -265,6 +265,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) + template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { // TODO optimize it for NEON @@ -275,7 +277,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, con s = vmulq_f32(b.v, b.v); rev_s = vrev64q_f32(s); - return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); + return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); } EIGEN_DEVICE_FUNC inline void @@ -381,7 +383,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((double *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const double *)addr); } template<> EIGEN_DEVICE_FUNC inline Packet1cd pgather, Packet1cd>(const std::complex* from, Index stride) { @@ -456,6 +458,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for NEON diff --git a/eigenlib/Eigen/src/Core/arch/NEON/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/NEON/MathFunctions.h index 6bb05bb9..89f16fe8 100644 --- a/eigenlib/Eigen/src/Core/arch/NEON/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/NEON/MathFunctions.h @@ -3,10 +3,10 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* The sin, cos, exp, and log functions of this file come from - * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ + * Julien Pommier's sse math library: xxxp://gruntthepeon.free.fr/ssemath/ */ #ifndef EIGEN_MATH_FUNCTIONS_NEON_H diff --git a/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h b/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h index d392bf3f..89ae2b83 100644 --- a/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/NEON/PacketMath.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_NEON_H #define EIGEN_PACKET_MATH_NEON_H @@ -36,29 +36,63 @@ namespace internal { #endif #endif +#if EIGEN_COMP_MSVC + +// In MSVC's arm_neon.h header file, all NEON vector types +// are aliases to the same underlying type __n128. +// We thus have to wrap them to make them different C++ types. +// (See also bug 1428) + +template +struct eigen_packet_wrapper +{ + operator T&() { return m_val; } + operator const T&() const { return m_val; } + eigen_packet_wrapper() {} + eigen_packet_wrapper(const T &v) : m_val(v) {} + eigen_packet_wrapper& operator=(const T &v) { + m_val = v; + return *this; + } + + T m_val; +}; +typedef eigen_packet_wrapper Packet2f; +typedef eigen_packet_wrapper Packet4f; +typedef eigen_packet_wrapper Packet4i; +typedef eigen_packet_wrapper Packet2i; +typedef eigen_packet_wrapper Packet4ui; + +#else + typedef float32x2_t Packet2f; typedef float32x4_t Packet4f; typedef int32x4_t Packet4i; typedef int32x2_t Packet2i; typedef uint32x4_t Packet4ui; +#endif // EIGEN_COMP_MSVC + #define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \ const Packet4f p4f_##NAME = pset1(X) #define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \ - const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1(X)) + const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1(X)) #define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \ const Packet4i p4i_##NAME = pset1(X) -// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function -// which available on LLVM and GCC (at least) -#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC +#if EIGEN_ARCH_ARM64 + // __builtin_prefetch tends to do nothing on ARM64 compilers because the + // prefetch instructions there are too detailed for __builtin_prefetch to map + // meaningfully to them. + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__("prfm pldl1keep, [%[addr]]\n" ::[addr] "r"(ADDR) : ); +#elif EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC #define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR); #elif defined __pld #define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR) -#elif !EIGEN_ARCH_ARM64 - #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" ); +#elif EIGEN_ARCH_ARM32 + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ("pld [%[addr]]\n" :: [addr] "r" (ADDR) : ); #else // by default no explicit prefetching #define EIGEN_ARM_PREFETCH(ADDR) @@ -83,7 +117,7 @@ template<> struct packet_traits : default_packet_traits HasSqrt = 0 }; }; -template<> struct packet_traits : default_packet_traits +template<> struct packet_traits : default_packet_traits { typedef Packet4i type; typedef Packet4i half; // Packet2i intrinsics not implemented yet @@ -105,19 +139,19 @@ EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); } #endif -template<> struct unpacket_traits { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; }; -template<> struct unpacket_traits { typedef int type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; }; +template<> struct unpacket_traits { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; }; +template<> struct unpacket_traits { typedef int32_t type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; }; template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return vdupq_n_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return vdupq_n_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4i pset1(const int32_t& from) { return vdupq_n_s32(from); } template<> EIGEN_STRONG_INLINE Packet4f plset(const float& a) { - const float32_t f[] = {0, 1, 2, 3}; + const float f[] = {0, 1, 2, 3}; Packet4f countdown = vld1q_f32(f); return vaddq_f32(pset1(a), countdown); } -template<> EIGEN_STRONG_INLINE Packet4i plset(const int& a) +template<> EIGEN_STRONG_INLINE Packet4i plset(const int32_t& a) { const int32_t i[] = {0, 1, 2, 3}; Packet4i countdown = vld1q_s32(i); @@ -173,7 +207,7 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, co // Clang/ARM wrongly advertises __ARM_FEATURE_FMA even when it's not available, // then implements a slow software scalar fallback calling fmaf()! // Filed LLVM bug: -// https://llvm.org/bugs/show_bug.cgi?id=27216 +// xxxps://llvm.org/bugs/show_bug.cgi?id=27216 #if (defined __ARM_FEATURE_FMA) && !(EIGEN_COMP_CLANG && EIGEN_ARCH_ARM) // See bug 936. // FMA is available on VFPv4 i.e. when compiling with -mfpu=neon-vfpv4. @@ -189,9 +223,9 @@ template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& // at least -mcpu=cortex-a8 and -mcpu=cortex-a7. Since the former is the default on // -march=armv7-a, that is a very common case. // See e.g. this thread: - // http://lists.llvm.org/pipermail/llvm-dev/2013-December/068806.html + // xxxp://lists.llvm.org/pipermail/llvm-dev/2013-December/068806.html // Filed LLVM bug: - // https://llvm.org/bugs/show_bug.cgi?id=27219 + // xxxps://llvm.org/bugs/show_bug.cgi?id=27219 Packet4f r = c; asm volatile( "vmla.f32 %q[r], %q[a], %q[b]" @@ -240,20 +274,20 @@ template<> EIGEN_STRONG_INLINE Packet4f pandnot(const Packet4f& a, con } template<> EIGEN_STRONG_INLINE Packet4i pandnot(const Packet4i& a, const Packet4i& b) { return vbicq_s32(a,b); } -template<> EIGEN_STRONG_INLINE Packet4f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i pload(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4f pload(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); } +template<> EIGEN_STRONG_INLINE Packet4i pload(const int32_t* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); } -template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); } -template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); } +template<> EIGEN_STRONG_INLINE Packet4f ploadu(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); } +template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int32_t* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); } -template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) +template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { float32x2_t lo, hi; lo = vld1_dup_f32(from); hi = vld1_dup_f32(from+1); return vcombine_f32(lo, hi); } -template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) +template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int32_t* from) { int32x2_t lo, hi; lo = vld1_dup_s32(from); @@ -261,11 +295,11 @@ template<> EIGEN_STRONG_INLINE Packet4i ploaddup(const int* from) return vcombine_s32(lo, hi); } -template<> EIGEN_STRONG_INLINE void pstore(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); } -template<> EIGEN_STRONG_INLINE void pstore(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); } +template<> EIGEN_STRONG_INLINE void pstore (float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); } +template<> EIGEN_STRONG_INLINE void pstore(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); } -template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); } -template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); } +template<> EIGEN_STRONG_INLINE void pstoreu (float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); } +template<> EIGEN_STRONG_INLINE void pstoreu(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); } template<> EIGEN_DEVICE_FUNC inline Packet4f pgather(const float* from, Index stride) { @@ -276,7 +310,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4f pgather(const floa res = vsetq_lane_f32(from[3*stride], res, 3); return res; } -template<> EIGEN_DEVICE_FUNC inline Packet4i pgather(const int* from, Index stride) +template<> EIGEN_DEVICE_FUNC inline Packet4i pgather(const int32_t* from, Index stride) { Packet4i res = pset1(0); res = vsetq_lane_s32(from[0*stride], res, 0); @@ -293,7 +327,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter(float* to, co to[stride*2] = vgetq_lane_f32(from, 2); to[stride*3] = vgetq_lane_f32(from, 3); } -template<> EIGEN_DEVICE_FUNC inline void pscatter(int* to, const Packet4i& from, Index stride) +template<> EIGEN_DEVICE_FUNC inline void pscatter(int32_t* to, const Packet4i& from, Index stride) { to[stride*0] = vgetq_lane_s32(from, 0); to[stride*1] = vgetq_lane_s32(from, 1); @@ -301,12 +335,12 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter(int* to, const to[stride*3] = vgetq_lane_s32(from, 3); } -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { EIGEN_ARM_PREFETCH(addr); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { EIGEN_ARM_PREFETCH(addr); } +template<> EIGEN_STRONG_INLINE void prefetch (const float* addr) { EIGEN_ARM_PREFETCH(addr); } +template<> EIGEN_STRONG_INLINE void prefetch(const int32_t* addr) { EIGEN_ARM_PREFETCH(addr); } // FIXME only store the 2 first elements ? -template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; } -template<> EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; } +template<> EIGEN_STRONG_INLINE float pfirst(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; } +template<> EIGEN_STRONG_INLINE int32_t pfirst(const Packet4i& a) { int32_t EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; } template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) { float32x2_t a_lo, a_hi; @@ -361,7 +395,7 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp(const Packet4f* vecs) return sum; } -template<> EIGEN_STRONG_INLINE int predux(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux(const Packet4i& a) { int32x2_t a_lo, a_hi, sum; @@ -408,7 +442,7 @@ template<> EIGEN_STRONG_INLINE float predux_mul(const Packet4f& a) return vget_lane_f32(prod, 0); } -template<> EIGEN_STRONG_INLINE int predux_mul(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_mul(const Packet4i& a) { int32x2_t a_lo, a_hi, prod; @@ -436,7 +470,7 @@ template<> EIGEN_STRONG_INLINE float predux_min(const Packet4f& a) return vget_lane_f32(min, 0); } -template<> EIGEN_STRONG_INLINE int predux_min(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_min(const Packet4i& a) { int32x2_t a_lo, a_hi, min; @@ -461,7 +495,7 @@ template<> EIGEN_STRONG_INLINE float predux_max(const Packet4f& a) return vget_lane_f32(max, 0); } -template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) +template<> EIGEN_STRONG_INLINE int32_t predux_max(const Packet4i& a) { int32x2_t a_lo, a_hi, max; @@ -474,7 +508,7 @@ template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) } // this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors, -// see bug 347 and this LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=11074 +// see bug 347 and this LLVM bug: xxxp://llvm.org/bugs/show_bug.cgi?id=11074 #define PALIGN_NEON(Offset,Type,Command) \ template<>\ struct palign_impl\ @@ -524,7 +558,7 @@ ptranspose(PacketBlock& kernel) { // Confirmed at least with __apple_build_version__ = 6000054. #ifdef __apple_build_version__ // Let's hope that by the time __apple_build_version__ hits the 601* range, the bug will be fixed. -// https://gist.github.com/yamaya/2924292 suggests that the 3 first digits are only updated with +// xxxps://gist.github.com/yamaya/2924292 suggests that the 3 first digits are only updated with // major toolchain updates. #define EIGEN_APPLE_DOUBLE_NEON_BUG (__apple_build_version__ < 6010000) #else @@ -693,7 +727,7 @@ template<> EIGEN_STRONG_INLINE double predux_min(const Packet2d& a) { template<> EIGEN_STRONG_INLINE double predux_max(const Packet2d& a) { return vgetq_lane_f64(vpmaxq_f64(a, a), 0); } // this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors, -// see bug 347 and this LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=11074 +// see bug 347 and this LLVM bug: xxxp://llvm.org/bugs/show_bug.cgi?id=11074 #define PALIGN_NEON(Offset,Type,Command) \ template<>\ struct palign_impl\ diff --git a/eigenlib/Eigen/src/Core/arch/SSE/Complex.h b/eigenlib/Eigen/src/Core/arch/SSE/Complex.h index 5607fe0a..0796ef30 100644 --- a/eigenlib/Eigen/src/Core/arch/SSE/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/Complex.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_SSE_H #define EIGEN_COMPLEX_SSE_H @@ -128,7 +128,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf _mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 3))); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -229,23 +229,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -340,7 +324,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, Packet2d(from.v)); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, Packet2d(from.v)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet1cd& a) { @@ -430,23 +414,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/eigenlib/Eigen/src/Core/arch/SSE/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/SSE/MathFunctions.h index 7b5f948e..53da97e2 100644 --- a/eigenlib/Eigen/src/Core/arch/SSE/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/MathFunctions.h @@ -6,10 +6,10 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* The sin, cos, exp, and log functions of this file come from - * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ + * Julien Pommier's sse math library: xxxp://gruntthepeon.free.fr/ssemath/ */ #ifndef EIGEN_MATH_FUNCTIONS_SSE_H @@ -451,7 +451,7 @@ Packet4f pcos(const Packet4f& _x) // The main advantage of this approach is not just speed, but also the fact that // it can be inlined and pipelined with other computations, further reducing its // effective latency. This is similar to Quake3's fast inverse square root. -// For detail see here: http://www.beyond3d.com/content/articles/8/ +// For detail see here: xxxp://www.beyond3d.com/content/articles/8/ template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED Packet4f psqrt(const Packet4f& _x) { @@ -548,7 +548,7 @@ double sqrt(const double &x) { #if EIGEN_COMP_GNUC_STRICT // This works around a GCC bug generating poor code for _mm_sqrt_pd - // See https://bitbucket.org/eigen/eigen/commits/14f468dba4d350d7c19c9b93072e19f7b3df563b + // See xxxps://bitbucket.org/eigen/eigen/commits/14f468dba4d350d7c19c9b93072e19f7b3df563b return internal::pfirst(internal::Packet2d(__builtin_ia32_sqrtsd(_mm_set_sd(x)))); #else return internal::pfirst(internal::Packet2d(_mm_sqrt_pd(_mm_set_sd(x)))); diff --git a/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h b/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h index 3832de14..0fe51aea 100755 --- a/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_SSE_H #define EIGEN_PACKET_MATH_SSE_H @@ -28,7 +28,7 @@ namespace internal { #endif #endif -#if (defined EIGEN_VECTORIZE_AVX) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_MINGW) && (__GXX_ABI_VERSION < 1004) +#if ((defined EIGEN_VECTORIZE_AVX) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_MINGW) && (__GXX_ABI_VERSION < 1004)) || EIGEN_OS_QNX // With GCC's default ABI version, a __m128 or __m256 are the same types and therefore we cannot // have overloads for both types without linking error. // One solution is to increase ABI version using -fabi-version=4 (or greater). @@ -409,10 +409,16 @@ template<> EIGEN_STRONG_INLINE void pstore1(double* to, const double& pstore(to, Packet2d(vec2d_swizzle1(pa,0,0))); } +#if EIGEN_COMP_PGI +typedef const void * SsePrefetchPtrType; +#else +typedef const char * SsePrefetchPtrType; +#endif + #ifndef EIGEN_VECTORIZE_AVX -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif #if EIGEN_COMP_MSVC_STRICT && EIGEN_OS_WIN64 @@ -876,4 +882,14 @@ template<> EIGEN_STRONG_INLINE double pmadd(const double& a, const double& b, co } // end namespace Eigen +#if EIGEN_COMP_PGI +// PGI++ does not define the following intrinsics in C++ mode. +static inline __m128 _mm_castpd_ps (__m128d x) { return reinterpret_cast<__m128&>(x); } +static inline __m128i _mm_castpd_si128(__m128d x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128d _mm_castps_pd (__m128 x) { return reinterpret_cast<__m128d&>(x); } +static inline __m128i _mm_castps_si128(__m128 x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128 _mm_castsi128_ps(__m128i x) { return reinterpret_cast<__m128&>(x); } +static inline __m128d _mm_castsi128_pd(__m128i x) { return reinterpret_cast<__m128d&>(x); } +#endif + #endif // EIGEN_PACKET_MATH_SSE_H diff --git a/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h b/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h index c8489323..81b5ba91 100644 --- a/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h +++ b/eigenlib/Eigen/src/Core/arch/SSE/TypeCasting.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TYPE_CASTING_SSE_H #define EIGEN_TYPE_CASTING_SSE_H @@ -14,6 +14,7 @@ namespace Eigen { namespace internal { +#ifndef EIGEN_VECTORIZE_AVX template <> struct type_casting_traits { enum { @@ -23,11 +24,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { - return _mm_cvttps_epi32(a); -} - - template <> struct type_casting_traits { enum { @@ -37,11 +33,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { - return _mm_cvtepi32_ps(a); -} - - template <> struct type_casting_traits { enum { @@ -51,10 +42,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { - return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); -} - template <> struct type_casting_traits { enum { @@ -63,6 +50,19 @@ struct type_casting_traits { TgtCoeffRatio = 2 }; }; +#endif + +template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { + return _mm_cvttps_epi32(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { + return _mm_cvtepi32_ps(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { + return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); +} template<> EIGEN_STRONG_INLINE Packet2d pcast(const Packet4f& a) { // Simply discard the second half of the input diff --git a/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h b/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h index d39d2d10..2a367b59 100644 --- a/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h +++ b/eigenlib/Eigen/src/Core/arch/ZVector/Complex.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX32_ALTIVEC_H #define EIGEN_COMPLEX32_ALTIVEC_H @@ -336,6 +336,9 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for AltiVec diff --git a/eigenlib/Eigen/src/Core/arch/ZVector/MathFunctions.h b/eigenlib/Eigen/src/Core/arch/ZVector/MathFunctions.h index 5c7aa725..25d52950 100644 --- a/eigenlib/Eigen/src/Core/arch/ZVector/MathFunctions.h +++ b/eigenlib/Eigen/src/Core/arch/ZVector/MathFunctions.h @@ -7,10 +7,10 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* The sin, cos, exp, and log functions of this file come from - * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ + * Julien Pommier's sse math library: xxxp://gruntthepeon.free.fr/ssemath/ */ #ifndef EIGEN_MATH_FUNCTIONS_ALTIVEC_H diff --git a/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h b/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h index e2deb25c..34878a8b 100755 --- a/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h +++ b/eigenlib/Eigen/src/Core/arch/ZVector/PacketMath.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PACKET_MATH_ZVECTOR_H #define EIGEN_PACKET_MATH_ZVECTOR_H @@ -100,7 +100,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 }; // Mask alignment #define _EIGEN_MASK_ALIGNMENT 0xfffffffffffffff0 -#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) +#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT) // Handle endianness properly while loading constants // Define global static constants: @@ -743,7 +743,7 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp(const Packet4i* vecs) Packet4i v[4], sum[4]; // It's easier and faster to transpose then add as columns - // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation + // Check: xxxp://www.freevec.org/function/matrix_4x4_transpose_floats for explanation // Do the transpose, first set of moves v[0] = vec_mergeh(vecs[0], vecs[2]); v[1] = vec_mergel(vecs[0], vecs[2]); diff --git a/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h b/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h index 9b373c78..9bf268da 100644 --- a/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/AssignmentFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ASSIGNMENT_FUNCTORS_H #define EIGEN_ASSIGNMENT_FUNCTORS_H @@ -28,7 +28,7 @@ template struct assign_op { { internal::pstoret(a,b); } }; -// Empty overload for void type (used by PermutationMatrix +// Empty overload for void type (used by PermutationMatrix) template struct assign_op {}; template diff --git a/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h b/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h index 96747bac..b056cdd2 100644 --- a/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/BinaryFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BINARY_FUNCTORS_H #define EIGEN_BINARY_FUNCTORS_H @@ -255,7 +255,7 @@ struct scalar_cmp_op : binary_op_base struct scalar_hypot_op : binary_op_base { EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op) -// typedef typename NumTraits::Real result_type; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const { - EIGEN_USING_STD_MATH(sqrt) - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - return p * sqrt(Scalar(1) + qp*qp); + // This functor is used by hypotNorm only for which it is faster to first apply abs + // on all coefficients prior to reduction through hypot. + // This way we avoid calling abs on positive and real entries, and this also permits + // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes + // through the same functor... + return internal::positive_real_hypot(x,y); } }; template diff --git a/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h b/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h index 0311d903..ba84d941 100644 --- a/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/NullaryFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_NULLARY_FUNCTORS_H #define EIGEN_NULLARY_FUNCTORS_H @@ -44,16 +44,16 @@ struct linspaced_op_impl { linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : m_low(low), m_high(high), m_size1(num_steps==1 ? 1 : num_steps-1), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)), - m_interPacket(plset(0)), m_flip(numext::abs(high) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const { + typedef typename NumTraits::Real RealScalar; if(m_flip) - return (i==0)? m_low : (m_high - (m_size1-i)*m_step); + return (i==0)? m_low : (m_high - RealScalar(m_size1-i)*m_step); else - return (i==m_size1)? m_high : (m_low + i*m_step); + return (i==m_size1)? m_high : (m_low + RealScalar(i)*m_step); } template @@ -63,7 +63,7 @@ struct linspaced_op_impl // [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) ) if(m_flip) { - Packet pi = padd(pset1(Scalar(i-m_size1)),m_interPacket); + Packet pi = plset(Scalar(i-m_size1)); Packet res = padd(pset1(m_high), pmul(pset1(m_step), pi)); if(i==0) res = pinsertfirst(res, m_low); @@ -71,7 +71,7 @@ struct linspaced_op_impl } else { - Packet pi = padd(pset1(Scalar(i)),m_interPacket); + Packet pi = plset(Scalar(i)); Packet res = padd(pset1(m_low), pmul(pset1(m_step), pi)); if(i==m_size1-unpacket_traits::size+1) res = pinsertlast(res, m_high); @@ -83,7 +83,6 @@ struct linspaced_op_impl const Scalar m_high; const Index m_size1; const Scalar m_step; - const Packet m_interPacket; const bool m_flip; }; @@ -93,8 +92,8 @@ struct linspaced_op_impl linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : m_low(low), m_multiplier((high-low)/convert_index(num_steps<=1 ? 1 : num_steps-1)), - m_divisor(convert_index(num_steps+high-low)/(high-low+1)), - m_use_divisor((high+1)<(low+num_steps)) + m_divisor(convert_index((high>=low?num_steps:-num_steps)+(high-low))/((numext::abs(high-low)+1)==0?1:(numext::abs(high-low)+1))), + m_use_divisor(num_steps>1 && (numext::abs(high-low)+1) diff --git a/eigenlib/Eigen/src/Core/functors/StlFunctors.h b/eigenlib/Eigen/src/Core/functors/StlFunctors.h index 6df3fa50..3ea133c7 100644 --- a/eigenlib/Eigen/src/Core/functors/StlFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/StlFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STL_FUNCTORS_H #define EIGEN_STL_FUNCTORS_H @@ -83,13 +83,17 @@ struct functor_traits > { enum { Cost = functor_traits::Cost, PacketAccess = false }; }; #endif +#if (__cplusplus < 201703L) && (EIGEN_COMP_MSVC < 1910) +// std::unary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +// std::binary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +#endif #ifdef EIGEN_STDEXT_SUPPORT diff --git a/eigenlib/Eigen/src/Core/functors/TernaryFunctors.h b/eigenlib/Eigen/src/Core/functors/TernaryFunctors.h index b254e96c..e6ae4ce0 100644 --- a/eigenlib/Eigen/src/Core/functors/TernaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/TernaryFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TERNARY_FUNCTORS_H #define EIGEN_TERNARY_FUNCTORS_H diff --git a/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h b/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h index 2e6a00ff..fcd8e7b5 100644 --- a/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h +++ b/eigenlib/Eigen/src/Core/functors/UnaryFunctors.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_UNARY_FUNCTORS_H #define EIGEN_UNARY_FUNCTORS_H @@ -768,7 +768,7 @@ struct scalar_sign_op { if (aa==real_type(0)) return Scalar(0); aa = real_type(1)/aa; - return Scalar(real(a)*aa, imag(a)*aa ); + return Scalar(a.real()*aa, a.imag()*aa ); } //TODO //template diff --git a/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h index 45230bce..3a6d29aa 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h +++ b/eigenlib/Eigen/src/Core/products/GeneralBlockPanelKernel.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERAL_BLOCK_PANEL_H #define EIGEN_GENERAL_BLOCK_PANEL_H @@ -115,7 +115,8 @@ void evaluateProductBlockingSizesHeuristic(Index& k, Index& m, Index& n, Index n // registers. However once the latency is hidden there is no point in // increasing the value of k, so we'll cap it at 320 (value determined // experimentally). - const Index k_cache = (numext::mini)((l1-ksub)/kdiv, 320); + // To avoid that k vanishes, we make k_cache at least as big as kr + const Index k_cache = numext::maxi(kr, (numext::mini)((l1-ksub)/kdiv, 320)); if (k_cache < k) { k = k_cache - (k_cache % kr); eigen_internal_assert(k > 0); @@ -648,8 +649,8 @@ public: // Vectorized path EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, DoublePacketType& dest) const { - dest.first = pset1(real(*b)); - dest.second = pset1(imag(*b)); + dest.first = pset1(numext::real(*b)); + dest.second = pset1(numext::imag(*b)); } EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, ResPacket& dest) const @@ -1197,10 +1198,16 @@ void gebp_kernel=6 without FMA (bug 1637) + #if EIGEN_GNUC_AT_LEAST(6,0) && defined(EIGEN_VECTORIZE_SSE) + #define EIGEN_GEBP_2PX4_SPILLING_WORKAROUND __asm__ ("" : [a0] "+x,m" (A0),[a1] "+x,m" (A1)); + #else + #define EIGEN_GEBP_2PX4_SPILLING_WORKAROUND + #endif + #define EIGEN_GEBGP_ONESTEP(K) \ do { \ EIGEN_ASM_COMMENT("begin step of gebp micro kernel 2pX4"); \ - EIGEN_ASM_COMMENT("Note: these asm comments work around bug 935!"); \ traits.loadLhs(&blA[(0+2*K)*LhsProgress], A0); \ traits.loadLhs(&blA[(1+2*K)*LhsProgress], A1); \ traits.broadcastRhs(&blB[(0+4*K)*RhsProgress], B_0, B1, B2, B3); \ @@ -1212,6 +1219,7 @@ void gebp_kernel::half SResPacketHalf; + const int SResPacketHalfSize = unpacket_traits::half>::size; if ((SwappedTraits::LhsProgress % 4) == 0 && (SwappedTraits::LhsProgress <= 8) && - (SwappedTraits::LhsProgress!=8 || unpacket_traits::size==nr)) + (SwappedTraits::LhsProgress!=8 || SResPacketHalfSize==nr)) { SAccPacket C0, C1, C2, C3; straits.initAcc(C0); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h index 61df3be5..2bb0815c 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERAL_MATRIX_MATRIX_H #define EIGEN_GENERAL_MATRIX_MATRIX_H @@ -20,8 +20,9 @@ template class level3_blocking; template< typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs, - typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs> -struct general_matrix_matrix_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct general_matrix_matrix_product { typedef gebp_traits Traits; @@ -30,7 +31,7 @@ struct general_matrix_matrix_product& blocking, GemmParallelInfo* info = 0) @@ -39,8 +40,8 @@ struct general_matrix_matrix_product - ::run(cols,rows,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha,blocking,info); + ColMajor,ResInnerStride> + ::run(cols,rows,depth,rhs,rhsStride,lhs,lhsStride,res,resIncr,resStride,alpha,blocking,info); } }; @@ -49,8 +50,9 @@ struct general_matrix_matrix_product -struct general_matrix_matrix_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct general_matrix_matrix_product { typedef gebp_traits Traits; @@ -59,17 +61,17 @@ typedef typename ScalarBinaryOpTraits::ReturnType ResScala static void run(Index rows, Index cols, Index depth, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsStride, - ResScalar* _res, Index resStride, + ResScalar* _res, Index resIncr, Index resStride, ResScalar alpha, level3_blocking& blocking, GemmParallelInfo* info = 0) { typedef const_blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; - LhsMapper lhs(_lhs,lhsStride); - RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + typedef blas_data_mapper ResMapper; + LhsMapper lhs(_lhs, lhsStride); + RhsMapper rhs(_rhs, rhsStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -83,8 +85,8 @@ static void run(Index rows, Index cols, Index depth, if(info) { // this is the parallel version! - Index tid = omp_get_thread_num(); - Index threads = omp_get_num_threads(); + int tid = omp_get_thread_num(); + int threads = omp_get_num_threads(); LhsScalar* blockA = blocking.blockA(); eigen_internal_assert(blockA!=0); @@ -116,9 +118,9 @@ static void run(Index rows, Index cols, Index depth, info[tid].sync = k; // Computes C_i += A' * B' per A'_i - for(Index shift=0; shift static void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::evalTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::assign_op()); else { dst.setZero(); @@ -440,7 +442,7 @@ struct generic_product_impl static void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::addTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::add_assign_op()); else scaleAndAddTo(dst,lhs, rhs, Scalar(1)); } @@ -449,7 +451,7 @@ struct generic_product_impl static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { if((rhs.rows()+dst.rows()+dst.cols())<20 && rhs.rows()>0) - lazyproduct::subTo(dst, lhs, rhs); + lazyproduct::eval_dynamic(dst, lhs, rhs, internal::sub_assign_op()); else scaleAndAddTo(dst, lhs, rhs, Scalar(-1)); } @@ -476,7 +478,8 @@ struct generic_product_impl Index, LhsScalar, (ActualLhsTypeCleaned::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(LhsBlasTraits::NeedToConjugate), RhsScalar, (ActualRhsTypeCleaned::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(RhsBlasTraits::NeedToConjugate), - (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor>, + (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor, + Dest::InnerStrideAtCompileTime>, ActualLhsTypeCleaned, ActualRhsTypeCleaned, Dest, BlockingType> GemmFunctor; BlockingType blocking(dst.rows(), dst.cols(), lhs.cols(), 1, true); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h index 5cd2794a..cc8697cb 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H #define EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H @@ -25,51 +25,54 @@ namespace internal { **********************************************************************/ // forward declarations (defined at the end of this file) -template +template struct tribb_kernel; /* Optimized matrix-matrix product evaluating only one triangular half */ template + int ResStorageOrder, int ResInnerStride, int UpLo, int Version = Specialized> struct general_matrix_matrix_triangular_product; // as usual if the result is row major => we transpose the product template -struct general_matrix_matrix_triangular_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int UpLo, int Version> +struct general_matrix_matrix_triangular_product { typedef typename ScalarBinaryOpTraits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs, Index lhsStride, - const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, + const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resIncr, Index resStride, const ResScalar& alpha, level3_blocking& blocking) { general_matrix_matrix_triangular_product - ::run(size,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha,blocking); + ColMajor, ResInnerStride, UpLo==Lower?Upper:Lower> + ::run(size,depth,rhs,rhsStride,lhs,lhsStride,res,resIncr,resStride,alpha,blocking); } }; template -struct general_matrix_matrix_triangular_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int UpLo, int Version> +struct general_matrix_matrix_triangular_product { typedef typename ScalarBinaryOpTraits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride, - const RhsScalar* _rhs, Index rhsStride, ResScalar* _res, Index resStride, + const RhsScalar* _rhs, Index rhsStride, + ResScalar* _res, Index resIncr, Index resStride, const ResScalar& alpha, level3_blocking& blocking) { typedef gebp_traits Traits; typedef const_blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); Index mc = (std::min)(size,blocking.mc()); @@ -87,7 +90,7 @@ struct general_matrix_matrix_triangular_product pack_lhs; gemm_pack_rhs pack_rhs; gebp_kernel gebp; - tribb_kernel sybb; + tribb_kernel sybb; for(Index k2=0; k2 +template struct tribb_kernel { typedef gebp_traits Traits; @@ -142,13 +144,15 @@ struct tribb_kernel enum { BlockSize = meta_least_common_multiple::ret }; - void operator()(ResScalar* _res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha) + void operator()(ResScalar* _res, Index resIncr, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, const ResScalar& alpha) { - typedef blas_data_mapper ResMapper; - ResMapper res(_res, resStride); - gebp_kernel gebp_kernel; + typedef blas_data_mapper ResMapper; + typedef blas_data_mapper BufferMapper; + ResMapper res(_res, resStride, resIncr); + gebp_kernel gebp_kernel1; + gebp_kernel gebp_kernel2; - Matrix buffer; + Matrix buffer((internal::constructor_without_unaligned_array_assert())); // let's process the block per panel of actual_mc x BlockSize, // again, each is split into three parts, etc. @@ -158,31 +162,32 @@ struct tribb_kernel const RhsScalar* actual_b = blockB+j*depth; if(UpLo==Upper) - gebp_kernel(res.getSubMapper(0, j), blockA, actual_b, j, depth, actualBlockSize, alpha, - -1, -1, 0, 0); - + gebp_kernel1(res.getSubMapper(0, j), blockA, actual_b, j, depth, actualBlockSize, alpha, + -1, -1, 0, 0); + // selfadjoint micro block { Index i = j; buffer.setZero(); // 1 - apply the kernel on the temporary buffer - gebp_kernel(ResMapper(buffer.data(), BlockSize), blockA+depth*i, actual_b, actualBlockSize, depth, actualBlockSize, alpha, - -1, -1, 0, 0); + gebp_kernel2(BufferMapper(buffer.data(), BlockSize), blockA+depth*i, actual_b, actualBlockSize, depth, actualBlockSize, alpha, + -1, -1, 0, 0); + // 2 - triangular accumulation for(Index j1=0; j1 enum { IsRowMajor = (internal::traits::Flags&RowMajorBit) ? 1 : 0, LhsIsRowMajor = _ActualLhs::Flags&RowMajorBit ? 1 : 0, - RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0 + RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0, + SkipDiag = (UpLo&(UnitDiag|ZeroDiag))!=0 }; Index size = mat.cols(); + if(SkipDiag) + size--; Index depth = actualLhs.cols(); typedef internal::gemm_blocking_space internal::general_matrix_matrix_triangular_product + IsRowMajor ? RowMajor : ColMajor, MatrixType::InnerStrideAtCompileTime, UpLo&(Lower|Upper)> ::run(size, depth, - &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(), - mat.data(), mat.outerStride(), actualAlpha, blocking); + &actualLhs.coeffRef(SkipDiag&&(UpLo&Lower)==Lower ? 1 : 0,0), actualLhs.outerStride(), + &actualRhs.coeffRef(0,SkipDiag&&(UpLo&Upper)==Upper ? 1 : 0), actualRhs.outerStride(), + mat.data() + (SkipDiag ? (bool(IsRowMajor) != ((UpLo&Lower)==Lower) ? mat.innerStride() : mat.outerStride() ) : 0), + mat.innerStride(), mat.outerStride(), actualAlpha, blocking); } }; @@ -294,6 +304,7 @@ template template TriangularView& TriangularViewImpl::_assignProduct(const ProductType& prod, const Scalar& alpha, bool beta) { + EIGEN_STATIC_ASSERT((UpLo&UnitDiag)==0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED); eigen_assert(derived().nestedExpression().rows() == prod.rows() && derived().cols() == prod.cols()); general_product_to_triangular_selector::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha, beta); diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h index 5b7c15cc..691f95d6 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h @@ -40,7 +40,7 @@ namespace internal { template struct general_matrix_matrix_rankupdate : general_matrix_matrix_triangular_product< - Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,UpLo,BuiltIn> {}; + Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,1,UpLo,BuiltIn> {}; // try to go to BLAS specialization @@ -48,19 +48,19 @@ struct general_matrix_matrix_rankupdate : template \ struct general_matrix_matrix_triangular_product { \ + Scalar,RhsStorageOrder,ConjugateRhs,ColMajor,1,UpLo,Specialized> { \ static EIGEN_STRONG_INLINE void run(Index size, Index depth,const Scalar* lhs, Index lhsStride, \ - const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking& blocking) \ + const Scalar* rhs, Index rhsStride, Scalar* res, Index resIncr, Index resStride, Scalar alpha, level3_blocking& blocking) \ { \ - if (lhs==rhs) { \ + if ( lhs==rhs && ((UpLo&(Lower|Upper))==UpLo) ) { \ general_matrix_matrix_rankupdate \ ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \ } else { \ general_matrix_matrix_triangular_product \ - ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \ + ColMajor, 1, UpLo, BuiltIn> \ + ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resIncr,resStride,alpha,blocking); \ } \ } \ }; @@ -88,7 +88,7 @@ struct general_matrix_matrix_rankupdate(lhsStride), ldc=convert_index(resStride), n=convert_index(size), k=convert_index(depth); \ char uplo=((IsLower) ? 'L' : 'U'), trans=((AStorageOrder==RowMajor) ? 'T':'N'); \ EIGTYPE beta(1); \ - BLASFUNC(&uplo, &trans, &n, &k, &numext::real_ref(alpha), lhs, &lda, &numext::real_ref(beta), res, &ldc); \ + BLASFUNC(&uplo, &trans, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), lhs, &lda, (const BLASTYPE*)&numext::real_ref(beta), res, &ldc); \ } \ }; @@ -125,9 +125,13 @@ struct general_matrix_matrix_rankupdate \ -struct general_matrix_matrix_product \ +struct general_matrix_matrix_product \ { \ typedef gebp_traits Traits; \ \ static void run(Index rows, Index cols, Index depth, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, \ level3_blocking& /*blocking*/, \ GemmParallelInfo* /*info = 0*/) \ { \ using std::conj; \ \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char transa, transb; \ BlasIndex m, n, k, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -100,13 +102,20 @@ static void run(Index rows, Index cols, Index depth, \ ldb = convert_index(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##gemm_(&transa, &transb, &m, &n, &k, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&transa, &transb, &m, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ }}; -GEMM_SPECIALIZATION(double, d, double, d) -GEMM_SPECIALIZATION(float, f, float, s) -GEMM_SPECIALIZATION(dcomplex, cd, double, z) -GEMM_SPECIALIZATION(scomplex, cf, float, c) +#ifdef EIGEN_USE_MKL +GEMM_SPECIALIZATION(double, d, double, dgemm) +GEMM_SPECIALIZATION(float, f, float, sgemm) +GEMM_SPECIALIZATION(dcomplex, cd, MKL_Complex16, zgemm) +GEMM_SPECIALIZATION(scomplex, cf, MKL_Complex8, cgemm) +#else +GEMM_SPECIALIZATION(double, d, double, dgemm_) +GEMM_SPECIALIZATION(float, f, float, sgemm_) +GEMM_SPECIALIZATION(dcomplex, cd, double, zgemm_) +GEMM_SPECIALIZATION(scomplex, cf, float, cgemm_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h b/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h index 3c1a7fc4..ab8d96e4 100644 --- a/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/eigenlib/Eigen/src/Core/products/GeneralMatrixVector.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERAL_MATRIX_VECTOR_H #define EIGEN_GENERAL_MATRIX_VECTOR_H @@ -183,8 +183,8 @@ EIGEN_DONT_INLINE void general_matrix_vector_product \ struct general_matrix_vector_product_gemv \ { \ @@ -113,14 +113,21 @@ static void run( \ x_ptr=x_tmp.data(); \ incx=1; \ } else x_ptr=rhs; \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, &numext::real_ref(beta), (BLASTYPE*)res, &incy); \ + BLASFUNC(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &incy); \ }\ }; -EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, d) -EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, s) -EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, z) -EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, MKL_Complex16, zgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, MKL_Complex8 , cgemv) +#else +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, zgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, cgemv_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/Parallelizer.h b/eigenlib/Eigen/src/Core/products/Parallelizer.h index 2a31e4cb..02d53a83 100644 --- a/eigenlib/Eigen/src/Core/products/Parallelizer.h +++ b/eigenlib/Eigen/src/Core/products/Parallelizer.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARALLELIZER_H #define EIGEN_PARALLELIZER_H @@ -17,7 +17,8 @@ namespace internal { /** \internal */ inline void manage_multi_threading(Action action, int* v) { - static EIGEN_UNUSED int m_maxThreads = -1; + static int m_maxThreads = -1; + EIGEN_UNUSED_VARIABLE(m_maxThreads); if(action==SetAction) { @@ -75,7 +76,7 @@ template struct GemmParallelInfo { GemmParallelInfo() : sync(-1), users(0), lhs_start(0), lhs_length(0) {} - int volatile sync; + Index volatile sync; int volatile users; Index lhs_start; @@ -104,13 +105,14 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth, // - the sizes are large enough // compute the maximal number of threads from the size of the product: - // FIXME this has to be fine tuned + // This first heuristic takes into account that the product kernel is fully optimized when working with nr columns at once. Index size = transpose ? rows : cols; - Index pb_max_threads = std::max(1,size / 32); + Index pb_max_threads = std::max(1,size / Functor::Traits::nr); + // compute the maximal number of threads from the total amount of work: double work = static_cast(rows) * static_cast(cols) * static_cast(depth); - double kMinTaskSize = 50000; // Heuristic. + double kMinTaskSize = 50000; // FIXME improve this heuristic. pb_max_threads = std::max(1, std::min(pb_max_threads, work / kMinTaskSize)); // compute the number of threads we are going to use @@ -149,8 +151,10 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth, info[i].lhs_start = r0; info[i].lhs_length = actualBlockRows; - if(transpose) func(c0, actualBlockCols, 0, rows, info); - else func(0, rows, c0, actualBlockCols, info); + if(transpose) + func(c0, actualBlockCols, 0, rows, info); + else + func(0, rows, c0, actualBlockCols, info); } #endif } diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h index da6f82ab..576c986e 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_H #define EIGEN_SELFADJOINT_MATRIX_MATRIX_H @@ -277,20 +277,21 @@ struct symm_pack_rhs template + int ResStorageOrder, int ResInnerStride> struct product_selfadjoint_matrix; template -struct product_selfadjoint_matrix + int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_STRONG_INLINE void run( Index rows, Index cols, const Scalar* lhs, Index lhsStride, const Scalar* rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { product_selfadjoint_matrix::IsComplex && EIGEN_LOGICAL_XOR(RhsSelfAdjoint,ConjugateRhs), EIGEN_LOGICAL_XOR(LhsSelfAdjoint,LhsStorageOrder==RowMajor) ? ColMajor : RowMajor, LhsSelfAdjoint, NumTraits::IsComplex && EIGEN_LOGICAL_XOR(LhsSelfAdjoint,ConjugateLhs), - ColMajor> - ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); + ColMajor,ResInnerStride> + ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resIncr, resStride, alpha, blocking); } }; template -struct product_selfadjoint_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_DONT_INLINE void run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking); }; template -EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { Index size = rows; @@ -334,11 +337,11 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix LhsMapper; typedef const_blas_data_mapper LhsTransposeMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); LhsTransposeMapper lhs_transpose(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -398,26 +401,28 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix -struct product_selfadjoint_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +struct product_selfadjoint_matrix { static EIGEN_DONT_INLINE void run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking); }; template -EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride> +EIGEN_DONT_INLINE void product_selfadjoint_matrix::run( Index rows, Index cols, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { Index size = cols; @@ -425,9 +430,9 @@ EIGEN_DONT_INLINE void product_selfadjoint_matrix Traits; typedef const_blas_data_mapper LhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); - ResMapper res(_res,resStride); + ResMapper res(_res,resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -503,12 +508,13 @@ struct selfadjoint_product_impl NumTraits::IsComplex && EIGEN_LOGICAL_XOR(LhsIsUpper,bool(LhsBlasTraits::NeedToConjugate)), EIGEN_LOGICAL_XOR(RhsIsUpper,internal::traits::Flags &RowMajorBit) ? RowMajor : ColMajor, RhsIsSelfAdjoint, NumTraits::IsComplex && EIGEN_LOGICAL_XOR(RhsIsUpper,bool(RhsBlasTraits::NeedToConjugate)), - internal::traits::Flags&RowMajorBit ? RowMajor : ColMajor> + internal::traits::Flags&RowMajorBit ? RowMajor : ColMajor, + Dest::InnerStrideAtCompileTime> ::run( lhs.rows(), rhs.cols(), // sizes &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info - &dst.coeffRef(0,0), dst.outerStride(), // result info + &dst.coeffRef(0,0), dst.innerStride(), dst.outerStride(), // result info actualAlpha, blocking // alpha ); } diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h index a45238d6..61396dbd 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h @@ -40,20 +40,22 @@ namespace internal { /* Optimized selfadjoint matrix * matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ \ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='L', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -81,25 +83,27 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='L', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -144,33 +148,41 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -EIGEN_BLAS_SYMM_L(double, double, d, d) -EIGEN_BLAS_SYMM_L(float, float, f, s) -EIGEN_BLAS_HEMM_L(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_L(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_L(double, double, d, dsymm) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm) +EIGEN_BLAS_HEMM_L(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_L(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_L(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_L(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_L(scomplex, float, cf, chemm_) +#endif /* Optimized matrix * selfadjoint matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ \ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='R', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -197,25 +209,27 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _lhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ -struct product_selfadjoint_matrix \ +struct product_selfadjoint_matrix \ {\ static void run( \ Index rows, Index cols, \ const EIGTYPE* _lhs, Index lhsStride, \ const EIGTYPE* _rhs, Index rhsStride, \ - EIGTYPE* res, Index resStride, \ + EIGTYPE* res, Index resIncr, Index resStride, \ EIGTYPE alpha, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ char side='R', uplo='L'; \ BlasIndex m, n, lda, ldb, ldc; \ const EIGTYPE *a, *b; \ @@ -259,15 +273,21 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ } \ }; -EIGEN_BLAS_SYMM_R(double, double, d, d) -EIGEN_BLAS_SYMM_R(float, float, f, s) -EIGEN_BLAS_HEMM_R(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_R(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_R(double, double, d, dsymm) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm) +EIGEN_BLAS_HEMM_R(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_R(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_R(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_R(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_R(scomplex, float, cf, chemm_) +#endif } // end namespace internal } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h index d97f8caa..c16dc61f 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointMatrixVector.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_H #define EIGEN_SELFADJOINT_MATRIX_VECTOR_H @@ -83,10 +83,10 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product(t3); - size_t starti = FirstTriangular ? 0 : j+2; - size_t endi = FirstTriangular ? j : size; - size_t alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti); - size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); + Index starti = FirstTriangular ? 0 : j+2; + Index endi = FirstTriangular ? j : size; + Index alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti); + Index alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); res[j] += cjd.pmul(numext::real(A0[j]), t0); res[j+1] += cjd.pmul(numext::real(A1[j+1]), t1); @@ -101,7 +101,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product(a0It); a0It += PacketSize; Packet A1i = ploadu(a1It); a1It += PacketSize; @@ -125,7 +125,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product internal::general_matrix_matrix_triangular_product::IsComplex, Scalar, OtherIsRowMajor ? ColMajor : RowMajor, (!OtherBlasTraits::NeedToConjugate) && NumTraits::IsComplex, - IsRowMajor ? RowMajor : ColMajor, UpLo> + IsRowMajor ? RowMajor : ColMajor, MatrixType::InnerStrideAtCompileTime, UpLo> ::run(size, depth, &actualOther.coeffRef(0,0), actualOther.outerStride(), &actualOther.coeffRef(0,0), actualOther.outerStride(), - mat.data(), mat.outerStride(), actualAlpha, blocking); + mat.data(), mat.innerStride(), mat.outerStride(), actualAlpha, blocking); } }; diff --git a/eigenlib/Eigen/src/Core/products/SelfadjointRank2Update.h b/eigenlib/Eigen/src/Core/products/SelfadjointRank2Update.h index 2ae36411..f1de1785 100644 --- a/eigenlib/Eigen/src/Core/products/SelfadjointRank2Update.h +++ b/eigenlib/Eigen/src/Core/products/SelfadjointRank2Update.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFADJOINTRANK2UPTADE_H #define EIGEN_SELFADJOINTRANK2UPTADE_H diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h index 8a2f7cd7..cbe49fbd 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRIANGULAR_MATRIX_MATRIX_H #define EIGEN_TRIANGULAR_MATRIX_MATRIX_H @@ -45,22 +45,24 @@ template + int ResStorageOrder, int ResInnerStride, + int Version = Specialized> struct product_triangular_matrix_matrix; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,RowMajor,ResInnerStride,Version> { static EIGEN_STRONG_INLINE void run( Index rows, Index cols, Index depth, const Scalar* lhs, Index lhsStride, const Scalar* rhs, Index rhsStride, - Scalar* res, Index resStride, + Scalar* res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { product_triangular_matrix_matrix - ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); + ColMajor, ResInnerStride> + ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resIncr, resStride, alpha, blocking); } }; // implements col-major += alpha * op(triangular) * op(general) template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version> { typedef gebp_traits Traits; @@ -95,20 +98,21 @@ struct product_triangular_matrix_matrix& blocking); }; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> EIGEN_DONT_INLINE void product_triangular_matrix_matrix::run( + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run( Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { // strip zeros @@ -119,10 +123,10 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -137,7 +141,13 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer; + // To work around an "error: member reference base type 'Matrix<...> + // (Eigen::internal::constructor_without_unaligned_array_assert (*)())' is + // not a structure or union" compilation error in nvcc (tested V8.0.61), + // create a dummy internal::constructor_without_unaligned_array_assert + // object to pass to the Matrix constructor. + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -229,10 +239,11 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version> { typedef gebp_traits Traits; enum { @@ -245,20 +256,21 @@ struct product_triangular_matrix_matrix& blocking); }; template + int RhsStorageOrder, bool ConjugateRhs, + int ResInnerStride, int Version> EIGEN_DONT_INLINE void product_triangular_matrix_matrix::run( + RhsStorageOrder,ConjugateRhs,ColMajor,ResInnerStride,Version>::run( Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride, const Scalar* _rhs, Index rhsStride, - Scalar* _res, Index resStride, + Scalar* _res, Index resIncr, Index resStride, const Scalar& alpha, level3_blocking& blocking) { const Index PacketBytes = packet_traits::size*sizeof(Scalar); @@ -270,10 +282,10 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix LhsMapper; typedef const_blas_data_mapper RhsMapper; - typedef blas_data_mapper ResMapper; + typedef blas_data_mapper ResMapper; LhsMapper lhs(_lhs,lhsStride); RhsMapper rhs(_rhs,rhsStride); - ResMapper res(_res, resStride); + ResMapper res(_res, resStride, resIncr); Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction @@ -284,7 +296,8 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer; + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -393,7 +406,9 @@ struct triangular_product_impl { template static void run(Dest& dst, const Lhs &a_lhs, const Rhs &a_rhs, const typename Dest::Scalar& alpha) { - typedef typename Dest::Scalar Scalar; + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef typename Dest::Scalar Scalar; typedef internal::blas_traits LhsBlasTraits; typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; @@ -405,8 +420,9 @@ struct triangular_product_impl typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(a_lhs); typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(a_rhs); - Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(a_lhs) - * RhsBlasTraits::extractScalarFactor(a_rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(a_lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(a_rhs); + Scalar actualAlpha = alpha * lhs_alpha * rhs_alpha; typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, Lhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxColsAtCompileTime,4> BlockingType; @@ -423,14 +439,29 @@ struct triangular_product_impl Mode, LhsIsTriangular, (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate, (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate, - (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor> + (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor, Dest::InnerStrideAtCompileTime> ::run( stripedRows, stripedCols, stripedDepth, // sizes &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info - &dst.coeffRef(0,0), dst.outerStride(), // result info + &dst.coeffRef(0,0), dst.innerStride(), dst.outerStride(), // result info actualAlpha, blocking ); + + // Apply correction if the diagonal is unit and a scalar factor was nested: + if ((Mode&UnitDiag)==UnitDiag) + { + if (LhsIsTriangular && lhs_alpha!=LhsScalar(1)) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dst.topRows(diagSize) -= ((lhs_alpha-LhsScalar(1))*a_rhs).topRows(diagSize); + } + else if ((!LhsIsTriangular) && rhs_alpha!=RhsScalar(1)) + { + Index diagSize = (std::min)(rhs.rows(),rhs.cols()); + dst.leftCols(diagSize) -= (rhs_alpha-RhsScalar(1))*a_lhs.leftCols(diagSize); + } + } } }; diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h index aecded6b..a98d12e4 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h @@ -46,7 +46,7 @@ template {}; + RhsStorageOrder, ConjugateRhs, ResStorageOrder, 1, BuiltIn> {}; // try to go to BLAS specialization @@ -55,13 +55,15 @@ template \ struct product_triangular_matrix_matrix { \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder,ConjugateRhs,ColMajor,1,Specialized> { \ static inline void run(Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride,\ - const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking& blocking) { \ + const Scalar* _rhs, Index rhsStride, Scalar* res, Index resIncr, Index resStride, Scalar alpha, level3_blocking& blocking) { \ + EIGEN_ONLY_USED_FOR_DEBUG(resIncr); \ + eigen_assert(resIncr == 1); \ product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ } \ }; @@ -75,7 +77,7 @@ EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, true) EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, false) // implements col-major += alpha * op(triangular) * op(general) -#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -115,8 +117,8 @@ struct product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, 1, BuiltIn>::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, 1, resStride, alpha, blocking); \ /*std::cout << "TRMM_L: A is not square! Go to Eigen TRMM implementation!\n";*/ \ } else { \ /* Make sense to call GEMM */ \ @@ -124,8 +126,8 @@ struct product_triangular_matrix_matrix_trmm(); \ BlasIndex aStride = convert_index(aa_tmp.outerStride()); \ gemm_blocking_space gemm_blocking(_rows,_cols,_depth, 1, true); \ - general_matrix_matrix_product::run( \ - rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, gemm_blocking, 0); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, 1, resStride, alpha, gemm_blocking, 0); \ \ /*std::cout << "TRMM_L: A is not square! Go to BLAS GEMM implementation! " << nthr<<" \n";*/ \ } \ @@ -172,7 +174,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -180,13 +182,20 @@ struct product_triangular_matrix_matrix_trmm \ @@ -225,8 +234,8 @@ struct product_triangular_matrix_matrix_trmm::run( \ - _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \ + LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, 1, BuiltIn>::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, 1, resStride, alpha, blocking); \ /*std::cout << "TRMM_R: A is not square! Go to Eigen TRMM implementation!\n";*/ \ } else { \ /* Make sense to call GEMM */ \ @@ -234,8 +243,8 @@ struct product_triangular_matrix_matrix_trmm(); \ BlasIndex aStride = convert_index(aa_tmp.outerStride()); \ gemm_blocking_space gemm_blocking(_rows,_cols,_depth, 1, true); \ - general_matrix_matrix_product::run( \ - rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, gemm_blocking, 0); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, 1, resStride, alpha, gemm_blocking, 0); \ \ /*std::cout << "TRMM_R: A is not square! Go to BLAS GEMM implementation! " << nthr<<" \n";*/ \ } \ @@ -282,7 +291,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -290,11 +299,17 @@ struct product_triangular_matrix_matrix_trmm struct trmv_selector typename internal::add_const_on_value_type::type actualLhs = LhsBlasTraits::extract(lhs); typename internal::add_const_on_value_type::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 @@ -274,6 +275,12 @@ template struct trmv_selector else dest = MappedDest(actualDestPtr, dest.size()); } + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; @@ -295,8 +302,9 @@ template struct trmv_selector typename add_const::type actualLhs = LhsBlasTraits::extract(lhs); typename add_const::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { DirectlyUseRhs = ActualRhsTypeCleaned::InnerStrideAtCompileTime==1 @@ -326,6 +334,12 @@ template struct trmv_selector actualRhsPtr,1, dest.data(),dest.innerStride(), actualAlpha); + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; diff --git a/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h b/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h index 07bf26ce..3d47a2b9 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +++ b/eigenlib/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h @@ -71,7 +71,7 @@ EIGEN_BLAS_TRMV_SPECIALIZE(dcomplex) EIGEN_BLAS_TRMV_SPECIALIZE(scomplex) // implements col-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -121,10 +121,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_CM(double, double, d, d) -EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_CM(float, float, f, s) -EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_CM(double, double, d, d,) +EIGEN_BLAS_TRMV_CM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_CM(float, float, f, s,) +EIGEN_BLAS_TRMV_CM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_CM(double, double, d, d, _) +EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z, _) +EIGEN_BLAS_TRMV_CM(float, float, f, s, _) +EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c, _) +#endif // implements row-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -203,10 +210,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &n, &m, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &n, &m, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_RM(double, double, d, d) -EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_RM(float, float, f, s) -EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_RM(double, double, d, d,) +EIGEN_BLAS_TRMV_RM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_RM(float, float, f, s,) +EIGEN_BLAS_TRMV_RM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_RM(double, double, d, d,_) +EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z,_) +EIGEN_BLAS_TRMV_RM(float, float, f, s,_) +EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c,_) +#endif } // end namespase internal diff --git a/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h b/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h index 223c38b8..c165ac73 100644 --- a/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/eigenlib/Eigen/src/Core/products/TriangularSolverMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRIANGULAR_SOLVER_MATRIX_H #define EIGEN_TRIANGULAR_SOLVER_MATRIX_H @@ -15,48 +15,48 @@ namespace Eigen { namespace internal { // if the rhs is row major, let's transpose the product -template -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static void run( Index size, Index cols, const Scalar* tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { triangular_solve_matrix< Scalar, Index, Side==OnTheLeft?OnTheRight:OnTheLeft, (Mode&UnitDiag) | ((Mode&Upper) ? Lower : Upper), NumTraits::IsComplex && Conjugate, - TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor> - ::run(size, cols, tri, triStride, _other, otherStride, blocking); + TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor, OtherInnerStride> + ::run(size, cols, tri, triStride, _other, otherIncr, otherStride, blocking); } }; /* Optimized triangular solver with multiple right hand side and the triangular matrix on the left */ -template -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static EIGEN_DONT_INLINE void run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking); }; -template -EIGEN_DONT_INLINE void triangular_solve_matrix::run( +template +EIGEN_DONT_INLINE void triangular_solve_matrix::run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { Index cols = otherSize; typedef const_blas_data_mapper TriMapper; - typedef blas_data_mapper OtherMapper; + typedef blas_data_mapper OtherMapper; TriMapper tri(_tri, triStride); - OtherMapper other(_other, otherStride); + OtherMapper other(_other, otherStride, otherIncr); typedef gebp_traits Traits; @@ -128,19 +128,19 @@ EIGEN_DONT_INLINE void triangular_solve_matrix -struct triangular_solve_matrix +template +struct triangular_solve_matrix { static EIGEN_DONT_INLINE void run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking); }; -template -EIGEN_DONT_INLINE void triangular_solve_matrix::run( +template +EIGEN_DONT_INLINE void triangular_solve_matrix::run( Index size, Index otherSize, const Scalar* _tri, Index triStride, - Scalar* _other, Index otherStride, + Scalar* _other, Index otherIncr, Index otherStride, level3_blocking& blocking) { Index rows = otherSize; typedef typename NumTraits::Real RealScalar; - typedef blas_data_mapper LhsMapper; + typedef blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - LhsMapper lhs(_other, otherStride); + LhsMapper lhs(_other, otherStride, otherIncr); RhsMapper rhs(_tri, triStride); typedef gebp_traits Traits; @@ -297,24 +297,24 @@ EIGEN_DONT_INLINE void triangular_solve_matrix \ -struct triangular_solve_matrix \ +struct triangular_solve_matrix \ { \ enum { \ IsLower = (Mode&Lower) == Lower, \ @@ -51,8 +51,10 @@ struct triangular_solve_matrix& /*blocking*/) \ + EIGTYPE* _other, Index otherIncr, Index otherStride, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(otherIncr); \ + eigen_assert(otherIncr == 1); \ BlasIndex m = convert_index(size), n = convert_index(otherSize), lda, ldb; \ char side = 'L', uplo, diag='N', transa; \ /* Set alpha_ */ \ @@ -80,20 +82,26 @@ struct triangular_solve_matrix \ -struct triangular_solve_matrix \ +struct triangular_solve_matrix \ { \ enum { \ IsLower = (Mode&Lower) == Lower, \ @@ -104,8 +112,10 @@ struct triangular_solve_matrix& /*blocking*/) \ + EIGTYPE* _other, Index otherIncr, Index otherStride, level3_blocking& /*blocking*/) \ { \ + EIGEN_ONLY_USED_FOR_DEBUG(otherIncr); \ + eigen_assert(otherIncr == 1); \ BlasIndex m = convert_index(otherSize), n = convert_index(size), lda, ldb; \ char side = 'R', uplo, diag='N', transa; \ /* Set alpha_ */ \ @@ -133,16 +143,22 @@ struct triangular_solve_matrix + int ResStorageOrder, int ResInnerStride> struct general_matrix_matrix_product; template +class BlasLinearMapper; + template -class BlasLinearMapper { +class BlasLinearMapper { public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; - EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data) : m_data(data) {} + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data, Index incr=1) + : m_data(data) + { + EIGEN_ONLY_USED_FOR_DEBUG(incr); + eigen_assert(incr==1); + } EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const { internal::prefetch(&operator()(i)); @@ -188,16 +196,25 @@ class BlasLinearMapper { }; // Lightweight helper class to access matrix coefficients. -template -class blas_data_mapper { - public: +template +class blas_data_mapper; + +template +class blas_data_mapper +{ +public: typedef typename packet_traits::type Packet; typedef typename packet_traits::half HalfPacket; typedef BlasLinearMapper LinearMapper; typedef BlasVectorMapper VectorMapper; - EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride) : m_data(data), m_stride(stride) {} + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr=1) + : m_data(data), m_stride(stride) + { + EIGEN_ONLY_USED_FOR_DEBUG(incr); + eigen_assert(incr==1); + } EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper getSubMapper(Index i, Index j) const { @@ -251,6 +268,90 @@ class blas_data_mapper { const Index m_stride; }; +// Implementation of non-natural increment (i.e. inner-stride != 1) +// The exposed API is not complete yet compared to the Incr==1 case +// because some features makes less sense in this case. +template +class BlasLinearMapper +{ +public: + typedef typename packet_traits::type Packet; + typedef typename packet_traits::half HalfPacket; + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BlasLinearMapper(Scalar *data,Index incr) : m_data(data), m_incr(incr) {} + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void prefetch(int i) const { + internal::prefetch(&operator()(i)); + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar& operator()(Index i) const { + return m_data[i*m_incr.value()]; + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet loadPacket(Index i) const { + return pgather(m_data + i*m_incr.value(), m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, const PacketType &p) const { + pscatter(m_data + i*m_incr.value(), p, m_incr.value()); + } + +protected: + Scalar *m_data; + const internal::variable_if_dynamic m_incr; +}; + +template +class blas_data_mapper +{ +public: + typedef typename packet_traits::type Packet; + typedef typename packet_traits::half HalfPacket; + + typedef BlasLinearMapper LinearMapper; + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper(Scalar* data, Index stride, Index incr) : m_data(data), m_stride(stride), m_incr(incr) {} + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE blas_data_mapper + getSubMapper(Index i, Index j) const { + return blas_data_mapper(&operator()(i, j), m_stride, m_incr.value()); + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LinearMapper getLinearMapper(Index i, Index j) const { + return LinearMapper(&operator()(i, j), m_incr.value()); + } + + EIGEN_DEVICE_FUNC + EIGEN_ALWAYS_INLINE Scalar& operator()(Index i, Index j) const { + return m_data[StorageOrder==RowMajor ? j*m_incr.value() + i*m_stride : i*m_incr.value() + j*m_stride]; + } + + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet loadPacket(Index i, Index j) const { + return pgather(&operator()(i, j),m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j) const { + return pgather(&operator()(i, j),m_incr.value()); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void scatterPacket(Index i, Index j, const SubPacket &p) const { + pscatter(&operator()(i, j), p, m_stride); + } + + template + EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE SubPacket gatherPacket(Index i, Index j) const { + return pgather(&operator()(i, j), m_stride); + } + +protected: + Scalar* EIGEN_RESTRICT m_data; + const Index m_stride; + const internal::variable_if_dynamic m_incr; +}; + // lightweight helper class to access matrix coefficients (const version) template class const_blas_data_mapper : public blas_data_mapper { diff --git a/eigenlib/Eigen/src/Core/util/Constants.h b/eigenlib/Eigen/src/Core/util/Constants.h index 7587d684..5beb0ba2 100644 --- a/eigenlib/Eigen/src/Core/util/Constants.h +++ b/eigenlib/Eigen/src/Core/util/Constants.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CONSTANTS_H #define EIGEN_CONSTANTS_H diff --git a/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h b/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h index 7559e129..3127053c 100755 --- a/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h +++ b/eigenlib/Eigen/src/Core/util/DisableStupidWarnings.h @@ -43,13 +43,24 @@ #endif #pragma clang diagnostic ignored "-Wconstant-logical-operand" -#elif defined __GNUC__ && __GNUC__>=6 +#elif defined __GNUC__ - #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS + #if (!defined(EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS)) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #pragma GCC diagnostic push #endif - #pragma GCC diagnostic ignored "-Wignored-attributes" - + // g++ warns about local variables shadowing member functions, which is too strict + #pragma GCC diagnostic ignored "-Wshadow" + #if __GNUC__ == 4 && __GNUC_MINOR__ < 8 + // Until g++-4.7 there are warnings when comparing unsigned int vs 0, even in templated functions: + #pragma GCC diagnostic ignored "-Wtype-limits" + #endif + #if __GNUC__>=6 + #pragma GCC diagnostic ignored "-Wignored-attributes" + #endif + #if __GNUC__==7 + // See: xxxps://gcc.gnu.org/bugzilla/show_bug.cgi?id=89325 + #pragma GCC diagnostic ignored "-Wattributes" + #endif #endif #if defined __NVCC__ @@ -72,4 +83,12 @@ #pragma diag_suppress 2737 #endif +#else +// warnings already disabled: +# ifndef EIGEN_WARNINGS_DISABLED_2 +# define EIGEN_WARNINGS_DISABLED_2 +# elif defined(EIGEN_INTERNAL_DEBUGGING) +# error "Do not include \"DisableStupidWarnings.h\" recursively more than twice!" +# endif + #endif // not EIGEN_WARNINGS_DISABLED diff --git a/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h b/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h index ea107393..f6bbee78 100644 --- a/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h +++ b/eigenlib/Eigen/src/Core/util/ForwardDeclarations.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_FORWARDDECLARATIONS_H #define EIGEN_FORWARDDECLARATIONS_H @@ -47,11 +47,7 @@ template struct NumTraits; template struct EigenBase; template class DenseBase; template class PlainObjectBase; - - -template::value > -class DenseCoeffsBase; +template class DenseCoeffsBase; template /*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/ @@ -108,6 +109,10 @@ #endif #endif +#if defined(EIGEN_USE_BLAS) && !defined(EIGEN_USE_MKL) +#include "../../misc/blas.h" +#endif + namespace Eigen { typedef std::complex dcomplex; @@ -121,8 +126,5 @@ typedef int BlasIndex; } // end namespace Eigen -#if defined(EIGEN_USE_BLAS) -#include "../../misc/blas.h" -#endif #endif // EIGEN_MKL_SUPPORT_H diff --git a/eigenlib/Eigen/src/Core/util/Macros.h b/eigenlib/Eigen/src/Core/util/Macros.h index ace330b3..1595da9f 100644 --- a/eigenlib/Eigen/src/Core/util/Macros.h +++ b/eigenlib/Eigen/src/Core/util/Macros.h @@ -6,14 +6,14 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MACROS_H #define EIGEN_MACROS_H #define EIGEN_WORLD_VERSION 3 #define EIGEN_MAJOR_VERSION 3 -#define EIGEN_MINOR_VERSION 2 +#define EIGEN_MINOR_VERSION 9 #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ @@ -80,8 +80,8 @@ // 2015 14 1900 // "15" 15 1900 -/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC -#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC) +/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC or clang-cl +#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC || EIGEN_COMP_LLVM || EIGEN_COMP_CLANG) #define EIGEN_COMP_MSVC_STRICT _MSC_VER #else #define EIGEN_COMP_MSVC_STRICT 0 @@ -380,7 +380,8 @@ #if EIGEN_MAX_CPP_VER>=11 && \ ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) \ || (defined(__GNUC__) && defined(_GLIBCXX_USE_C99)) \ - || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))) + || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) \ + || (EIGEN_COMP_MSVC >= 1900) ) #define EIGEN_HAS_C99_MATH 1 #else #define EIGEN_HAS_C99_MATH 0 @@ -396,10 +397,24 @@ #endif #endif +// Does the compiler support type_traits? +// - full support of type traits was added only to GCC 5.1.0. +// - 20150626 corresponds to the last release of 4.x libstdc++ +#ifndef EIGEN_HAS_TYPE_TRAITS +#if EIGEN_MAX_CPP_VER>=11 && (EIGEN_HAS_CXX11 || EIGEN_COMP_MSVC >= 1700) \ + && ((!EIGEN_COMP_GNUC_STRICT) || EIGEN_GNUC_AT_LEAST(5, 1)) \ + && ((!defined(__GLIBCXX__)) || __GLIBCXX__ > 20150626) +#define EIGEN_HAS_TYPE_TRAITS 1 +#define EIGEN_INCLUDE_TYPE_TRAITS +#else +#define EIGEN_HAS_TYPE_TRAITS 0 +#endif +#endif + // Does the compiler support variadic templates? #ifndef EIGEN_HAS_VARIADIC_TEMPLATES #if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \ - && ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) ) + && (!defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (EIGEN_CUDACC_VER >= 80000) ) // ^^ Disable the use of variadic templates when compiling with versions of nvcc older than 8.0 on ARM devices: // this prevents nvcc from crashing when compiling Eigen on Tegra X1 #define EIGEN_HAS_VARIADIC_TEMPLATES 1 @@ -413,7 +428,7 @@ #ifdef __CUDACC__ // Const expressions are supported provided that c++11 is enabled and we're using either clang or nvcc 7.5 or above -#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && defined(__CUDACC_VER__) && (EIGEN_COMP_CLANG || __CUDACC_VER__ >= 70500)) +#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && (EIGEN_COMP_CLANG || EIGEN_CUDACC_VER >= 70500)) #define EIGEN_HAS_CONSTEXPR 1 #endif #elif EIGEN_MAX_CPP_VER>=14 && (__has_feature(cxx_relaxed_constexpr) || (defined(__cplusplus) && __cplusplus >= 201402L) || \ @@ -487,11 +502,13 @@ // EIGEN_STRONG_INLINE is a stronger version of the inline, using __forceinline on MSVC, // but it still doesn't use GCC's always_inline. This is useful in (common) situations where MSVC needs forceinline // but GCC is still doing fine with just inline. +#ifndef EIGEN_STRONG_INLINE #if EIGEN_COMP_MSVC || EIGEN_COMP_ICC #define EIGEN_STRONG_INLINE __forceinline #else #define EIGEN_STRONG_INLINE inline #endif +#endif // EIGEN_ALWAYS_INLINE is the stronget, it has the effect of making the function inline and adding every possible // attribute to maximize inlining. This should only be used when really necessary: in particular, @@ -812,10 +829,11 @@ namespace Eigen { // just an empty macro ! #define EIGEN_EMPTY -#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || __CUDACC_VER__) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) +#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || EIGEN_CUDACC_VER>0) + // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) #define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ using Base::operator =; -#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653) +#elif EIGEN_COMP_CLANG // workaround clang bug (see xxxp://forum.kde.org/viewtopic.php?f=74&t=102653) #define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ using Base::operator =; \ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const Derived& other) { Base::operator=(other); return *this; } \ @@ -832,11 +850,48 @@ namespace Eigen { #endif +/** + * \internal + * \brief Macro to explicitly define the default copy constructor. + * This is necessary, because the implicit definition is deprecated if the copy-assignment is overridden. + */ +#if EIGEN_HAS_CXX11 +#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) EIGEN_DEVICE_FUNC CLASS(const CLASS&) = default; +#else +#define EIGEN_DEFAULT_COPY_CONSTRUCTOR(CLASS) +#endif + + + /** \internal * \brief Macro to manually inherit assignment operators. * This is necessary, because the implicitly defined assignment operator gets deleted when a custom operator= is defined. + * With C++11 or later this also default-implements the copy-constructor */ -#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) +#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \ + EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ + EIGEN_DEFAULT_COPY_CONSTRUCTOR(Derived) + +/** \internal + * \brief Macro to manually define default constructors and destructors. + * This is necessary when the copy constructor is re-defined. + * For empty helper classes this should usually be protected, to avoid accidentally creating empty objects. + * + * Hiding the default destructor lead to problems in C++03 mode together with boost::multiprecision + */ +#if EIGEN_HAS_CXX11 +#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \ + EIGEN_DEVICE_FUNC Derived() = default; \ + EIGEN_DEVICE_FUNC ~Derived() = default; +#else +#define EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(Derived) \ + EIGEN_DEVICE_FUNC Derived() {}; \ + /* EIGEN_DEVICE_FUNC ~Derived() {}; */ +#endif + + + + /** * Just a side note. Commenting within defines works only by documenting @@ -986,7 +1041,13 @@ namespace Eigen { # define EIGEN_NOEXCEPT # define EIGEN_NOEXCEPT_IF(x) # define EIGEN_NO_THROW throw() -# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# if EIGEN_COMP_MSVC + // MSVC does not support exception specifications (warning C4290), + // and they are deprecated in c++11 anyway. +# define EIGEN_EXCEPTION_SPEC(X) throw() +# else +# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# endif #endif #endif // EIGEN_MACROS_H diff --git a/eigenlib/Eigen/src/Core/util/Memory.h b/eigenlib/Eigen/src/Core/util/Memory.h index 67053db6..9368e97c 100644 --- a/eigenlib/Eigen/src/Core/util/Memory.h +++ b/eigenlib/Eigen/src/Core/util/Memory.h @@ -10,7 +10,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /***************************************************************************** @@ -25,10 +25,10 @@ // Try to determine automatically if malloc is already aligned. // On 64-bit systems, glibc's malloc returns 16-byte-aligned pointers, see: -// http://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html +// xxxp://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html // This is true at least since glibc 2.8. // This leaves the question how to detect 64-bit. According to this document, -// http://gcc.fyxm.net/summit/2003/Porting%20to%2064%20bit.pdf +// xxxp://gcc.fyxm.net/summit/2003/Porting%20to%2064%20bit.pdf // page 114, "[The] LP64 model [...] is used by all 64-bit UNIX ports" so it's indeed // quite safe, at least within the context of glibc, to equate 64-bit with LP64. #if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \ @@ -39,9 +39,9 @@ #endif // FreeBSD 6 seems to have 16-byte aligned malloc -// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup +// See xxxp://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup // FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures -// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup +// See xxxp://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup #if defined(__FreeBSD__) && !(EIGEN_ARCH_ARM || EIGEN_ARCH_MIPS) && (EIGEN_DEFAULT_ALIGN_BYTES == 16) #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1 #else @@ -70,7 +70,7 @@ inline void throw_std_bad_alloc() throw std::bad_alloc(); #else std::size_t huge = static_cast(-1); - new int[huge]; + ::operator new(huge); #endif } @@ -150,7 +150,7 @@ EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed() /** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 or 32 bytes alignment depending on the requirements. * On allocation error, the returned pointer is null, and std::bad_alloc is thrown. */ -EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size) +EIGEN_DEVICE_FUNC inline void* aligned_malloc(std::size_t size) { check_that_malloc_is_allowed(); @@ -185,7 +185,7 @@ EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr) * \brief Reallocates an aligned block of memory. * \throws std::bad_alloc on allocation failure */ -inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size) +inline void* aligned_realloc(void *ptr, std::size_t new_size, std::size_t old_size) { EIGEN_UNUSED_VARIABLE(old_size); @@ -209,12 +209,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size) /** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned. * On allocation error, the returned pointer is null, and a std::bad_alloc is thrown. */ -template EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(size_t size) +template EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(std::size_t size) { return aligned_malloc(size); } -template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(size_t size) +template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(std::size_t size) { check_that_malloc_is_allowed(); @@ -235,12 +235,12 @@ template<> EIGEN_DEVICE_FUNC inline void conditional_aligned_free(void *p std::free(ptr); } -template inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size) +template inline void* conditional_aligned_realloc(void* ptr, std::size_t new_size, std::size_t old_size) { return aligned_realloc(ptr, new_size, old_size); } -template<> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t) +template<> inline void* conditional_aligned_realloc(void* ptr, std::size_t new_size, std::size_t) { return std::realloc(ptr, new_size); } @@ -252,7 +252,7 @@ template<> inline void* conditional_aligned_realloc(void* ptr, size_t new /** \internal Destructs the elements of an array. * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, std::size_t size) { // always destruct an array starting from the end. if(ptr) @@ -262,9 +262,9 @@ template EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T /** \internal Constructs the elements of an array. * The \a size parameter tells on how many objects to call the constructor of T. */ -template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, std::size_t size) { - size_t i; + std::size_t i; EIGEN_TRY { for (i = 0; i < size; ++i) ::new (ptr + i) T; @@ -283,9 +283,9 @@ template EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T * *****************************************************************************/ template -EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(std::size_t size) { - if(size > size_t(-1) / sizeof(T)) + if(size > std::size_t(-1) / sizeof(T)) throw_std_bad_alloc(); } @@ -293,7 +293,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size) * On allocation error, the returned pointer is undefined, but a std::bad_alloc is thrown. * The default constructor of T is called. */ -template EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size) +template EIGEN_DEVICE_FUNC inline T* aligned_new(std::size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(aligned_malloc(sizeof(T)*size)); @@ -309,7 +309,7 @@ template EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size) return result; } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(size_t size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(std::size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); @@ -328,7 +328,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned /** \internal Deletes objects constructed with aligned_new * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, std::size_t size) { destruct_elements_of_array(ptr, size); aligned_free(ptr); @@ -337,13 +337,13 @@ template EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t /** \internal Deletes objects constructed with conditional_aligned_new * The \a size parameters tells on how many objects to call the destructor of T. */ -template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, std::size_t size) { destruct_elements_of_array(ptr, size); conditional_aligned_free(ptr); } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, std::size_t new_size, std::size_t old_size) { check_size_for_overflow(new_size); check_size_for_overflow(old_size); @@ -366,7 +366,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned } -template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(size_t size) +template EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(std::size_t size) { if(size==0) return 0; // short-cut. Also fixes Bug 884 @@ -387,7 +387,7 @@ template EIGEN_DEVICE_FUNC inline T* conditional_aligned return result; } -template inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size) +template inline T* conditional_aligned_realloc_new_auto(T* pts, std::size_t new_size, std::size_t old_size) { check_size_for_overflow(new_size); check_size_for_overflow(old_size); @@ -409,7 +409,7 @@ template inline T* conditional_aligned_realloc_new_auto( return result; } -template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, size_t size) +template EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, std::size_t size) { if(NumTraits::RequireInitialization) destruct_elements_of_array(ptr, size); @@ -493,7 +493,7 @@ template struct smart_copy_helper { IntPtr size = IntPtr(end)-IntPtr(start); if(size==0) return; eigen_internal_assert(start!=0 && end!=0 && target!=0); - memcpy(target, start, size); + std::memcpy(target, start, size); } }; @@ -561,7 +561,7 @@ template class aligned_stack_memory_handler : noncopyable * In this case, the buffer elements will also be destructed when this handler will be destructed. * Finally, if \a dealloc is true, then the pointer \a ptr is freed. **/ - aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc) + aligned_stack_memory_handler(T* ptr, std::size_t size, bool dealloc) : m_ptr(ptr), m_size(size), m_deallocate(dealloc) { if(NumTraits::RequireInitialization && m_ptr) @@ -576,7 +576,7 @@ template class aligned_stack_memory_handler : noncopyable } protected: T* m_ptr; - size_t m_size; + std::size_t m_size; bool m_deallocate; }; @@ -655,15 +655,15 @@ template void swap(scoped_array &a,scoped_array &b) #if EIGEN_MAX_ALIGN_BYTES!=0 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ - void* operator new(size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \ + void* operator new(std::size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \ EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc(size); } \ EIGEN_CATCH (...) { return 0; } \ } #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \ - void *operator new(size_t size) { \ + void *operator new(std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ - void *operator new[](size_t size) { \ + void *operator new[](std::size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ } \ void operator delete(void * ptr) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free(ptr); } \ @@ -673,8 +673,8 @@ template void swap(scoped_array &a,scoped_array &b) /* in-place new and delete. since (at least afaik) there is no actual */ \ /* memory allocated we can safely let the default implementation handle */ \ /* this particular case. */ \ - static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \ - static void *operator new[](size_t size, void* ptr) { return ::operator new[](size,ptr); } \ + static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \ + static void *operator new[](std::size_t size, void* ptr) { return ::operator new[](size,ptr); } \ void operator delete(void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete(memory,ptr); } \ void operator delete[](void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete[](memory,ptr); } \ /* nothrow-new (returns zero instead of std::bad_alloc) */ \ @@ -696,7 +696,15 @@ template void swap(scoped_array &a,scoped_array &b) /** \class aligned_allocator * \ingroup Core_Module * -* \brief STL compatible allocator to use with with 16 byte aligned types +* \brief STL compatible allocator to use with types requiring a non standrad alignment. +* +* The memory is aligned as for dynamically aligned matrix/array types such as MatrixXd. +* By default, it will thus provide at least 16 bytes alignment and more in following cases: +* - 32 bytes alignment if AVX is enabled. +* - 64 bytes alignment if AVX512 is enabled. +* +* This can be controled using the \c EIGEN_MAX_ALIGN_BYTES macro as documented +* \link TopicPreprocessorDirectivesPerformance there \endlink. * * Example: * \code @@ -713,7 +721,7 @@ template class aligned_allocator : public std::allocator { public: - typedef size_t size_type; + typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; @@ -739,7 +747,15 @@ public: pointer allocate(size_type num, const void* /*hint*/ = 0) { internal::check_size_for_overflow(num); - return static_cast( internal::aligned_malloc(num * sizeof(T)) ); + size_type size = num * sizeof(T); +#if EIGEN_COMP_GNUC_STRICT && EIGEN_GNUC_AT_LEAST(7,0) + // workaround gcc bug xxxps://gcc.gnu.org/bugzilla/show_bug.cgi?id=87544 + // It triggered eigen/Eigen/src/Core/util/Memory.h:189:12: warning: argument 1 value '18446744073709551612' exceeds maximum object size 9223372036854775807 + if(size>=std::size_t((std::numeric_limits::max)())) + return 0; + else +#endif + return static_cast( internal::aligned_malloc(size) ); } void deallocate(pointer p, size_type /*num*/) diff --git a/eigenlib/Eigen/src/Core/util/Meta.h b/eigenlib/Eigen/src/Core/util/Meta.h index 7f637075..72e02b03 100755 --- a/eigenlib/Eigen/src/Core/util/Meta.h +++ b/eigenlib/Eigen/src/Core/util/Meta.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_META_H #define EIGEN_META_H @@ -97,6 +97,9 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; +#if EIGEN_HAS_CXX11 +using std::is_integral; +#else template struct is_integral { enum { value = false }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; @@ -108,6 +111,33 @@ template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; template<> struct is_integral { enum { value = true }; }; +#if EIGEN_COMP_MSVC +template<> struct is_integral { enum { value = true }; }; +template<> struct is_integral{ enum { value = true }; }; +#endif +#endif + +#if EIGEN_HAS_CXX11 +using std::make_unsigned; +#else +// TODO: Possibly improve this implementation of make_unsigned. +// It is currently used only by +// template struct random_default_impl. +template struct make_unsigned; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned char type; }; +template<> struct make_unsigned { typedef unsigned short type; }; +template<> struct make_unsigned { typedef unsigned short type; }; +template<> struct make_unsigned { typedef unsigned int type; }; +template<> struct make_unsigned { typedef unsigned int type; }; +template<> struct make_unsigned { typedef unsigned long type; }; +template<> struct make_unsigned { typedef unsigned long type; }; +#if EIGEN_COMP_MSVC +template<> struct make_unsigned { typedef unsigned __int64 type; }; +template<> struct make_unsigned { typedef unsigned __int64 type; }; +#endif +#endif template struct add_const { typedef const T type; }; template struct add_const { typedef T& type; }; @@ -485,8 +515,54 @@ T div_ceil(const T &a, const T &b) return (a+b-1) / b; } +// The aim of the following functions is to bypass -Wfloat-equal warnings +// when we really want a strict equality comparison on floating points. +template EIGEN_STRONG_INLINE +bool equal_strict(const X& x,const Y& y) { return x == y; } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const float& x,const float& y) { return std::equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const double& x,const double& y) { return std::equal_to()(x,y); } + +template EIGEN_STRONG_INLINE +bool not_equal_strict(const X& x,const Y& y) { return x != y; } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to()(x,y); } + } // end namespace numext } // end namespace Eigen +// Define portable (u)int{32,64} types +#if EIGEN_HAS_CXX11 +#include +namespace Eigen { +namespace numext { +typedef std::uint32_t uint32_t; +typedef std::int32_t int32_t; +typedef std::uint64_t uint64_t; +typedef std::int64_t int64_t; +} +} +#else +// Without c++11, all compilers able to compile Eigen also +// provides the C99 stdint.h header file. +#include +namespace Eigen { +namespace numext { +typedef ::uint32_t uint32_t; +typedef ::int32_t int32_t; +typedef ::uint64_t uint64_t; +typedef ::int64_t int64_t; +} +} +#endif + + #endif // EIGEN_META_H diff --git a/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h b/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h index 86b60f52..1ce6fd1b 100644 --- a/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h +++ b/eigenlib/Eigen/src/Core/util/ReenableStupidWarnings.h @@ -1,4 +1,8 @@ -#ifdef EIGEN_WARNINGS_DISABLED +#ifdef EIGEN_WARNINGS_DISABLED_2 +// "DisableStupidWarnings.h" was included twice recursively: Do not reenable warnings yet! +# undef EIGEN_WARNINGS_DISABLED_2 + +#elif defined(EIGEN_WARNINGS_DISABLED) #undef EIGEN_WARNINGS_DISABLED #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS @@ -8,7 +12,7 @@ #pragma warning pop #elif defined __clang__ #pragma clang diagnostic pop - #elif defined __GNUC__ && __GNUC__>=6 + #elif defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #pragma GCC diagnostic pop #endif diff --git a/eigenlib/Eigen/src/Core/util/StaticAssert.h b/eigenlib/Eigen/src/Core/util/StaticAssert.h index 983361a4..9d8bfd33 100644 --- a/eigenlib/Eigen/src/Core/util/StaticAssert.h +++ b/eigenlib/Eigen/src/Core/util/StaticAssert.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STATIC_ASSERT_H #define EIGEN_STATIC_ASSERT_H @@ -24,6 +24,7 @@ * */ +#ifndef EIGEN_STATIC_ASSERT #ifndef EIGEN_NO_STATIC_ASSERT #if EIGEN_MAX_CPP_VER>=11 && (__has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600)) @@ -44,64 +45,65 @@ struct static_assertion { enum { - YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX, - YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES, - YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES, - THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE, - OUT_OF_RANGE_ACCESS, - YOU_MADE_A_PROGRAMMING_MISTAKE, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT, - EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE, - YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR, - YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR, - UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC, - THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES, - FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED, - NUMERIC_TYPE_MUST_BE_REAL, - COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED, - WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED, - THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE, - INVALID_MATRIX_PRODUCT, - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS, - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION, - YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY, - THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, - THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, - INVALID_MATRIX_TEMPLATE_PARAMETERS, - INVALID_MATRIXBASE_TEMPLATE_PARAMETERS, - BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER, - THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX, - THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES, - YOU_ALREADY_SPECIFIED_THIS_STRIDE, - INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION, - THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD, - PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1, - THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS, - YOU_CANNOT_MIX_ARRAYS_AND_MATRICES, - YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION, - THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY, - YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT, - THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS, - THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL, - THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES, - YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED, - YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED, - THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE, - THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH, - OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG, - IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY, - STORAGE_LAYOUT_DOES_NOT_MATCH, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE, - THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS, - MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY, - THIS_TYPE_IS_NOT_SUPPORTED, - STORAGE_KIND_MUST_MATCH, - STORAGE_INDEX_MUST_MATCH, - CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY + YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX=1, + YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES=1, + YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES=1, + THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE=1, + OUT_OF_RANGE_ACCESS=1, + YOU_MADE_A_PROGRAMMING_MISTAKE=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT=1, + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE=1, + YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR=1, + YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR=1, + UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC=1, + THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES=1, + FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED=1, + NUMERIC_TYPE_MUST_BE_REAL=1, + COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED=1, + WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED=1, + THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE=1, + INVALID_MATRIX_PRODUCT=1, + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS=1, + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION=1, + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY=1, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES=1, + THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES=1, + INVALID_MATRIX_TEMPLATE_PARAMETERS=1, + INVALID_MATRIXBASE_TEMPLATE_PARAMETERS=1, + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER=1, + THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX=1, + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES=1, + YOU_ALREADY_SPECIFIED_THIS_STRIDE=1, + INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION=1, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD=1, + PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1=1, + THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS=1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES=1, + YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION=1, + THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY=1, + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT=1, + THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS=1, + THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL=1, + THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES=1, + YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED=1, + YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED=1, + THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE=1, + THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH=1, + OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG=1, + IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY=1, + STORAGE_LAYOUT_DOES_NOT_MATCH=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE=1, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS=1, + MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY=1, + THIS_TYPE_IS_NOT_SUPPORTED=1, + STORAGE_KIND_MUST_MATCH=1, + STORAGE_INDEX_MUST_MATCH=1, + CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY=1, + SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY=1 }; }; @@ -131,7 +133,7 @@ #define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG); #endif // EIGEN_NO_STATIC_ASSERT - +#endif // EIGEN_STATIC_ASSERT // static assertion failing if the type \a TYPE is not a vector type #define EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) \ diff --git a/eigenlib/Eigen/src/Core/util/XprHelper.h b/eigenlib/Eigen/src/Core/util/XprHelper.h index e88510dc..80c0cb47 100644 --- a/eigenlib/Eigen/src/Core/util/XprHelper.h +++ b/eigenlib/Eigen/src/Core/util/XprHelper.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_XPRHELPER_H #define EIGEN_XPRHELPER_H @@ -34,6 +34,20 @@ inline IndexDest convert_index(const IndexSrc& idx) { return IndexDest(idx); } +// true if T can be considered as an integral index (i.e., and integral type or enum) +template struct is_valid_index_type +{ + enum { value = +#if EIGEN_HAS_TYPE_TRAITS + internal::is_integral::value || std::is_enum::value +#elif EIGEN_COMP_MSVC + internal::is_integral::value || __is_enum(T) +#else + // without C++11, we use is_convertible to Index instead of is_integral in order to treat enums as Index. + internal::is_convertible::value && !internal::is_same::value && !is_same::value +#endif + }; +}; // promote_scalar_arg is an helper used in operation between an expression and a scalar, like: // expression * scalar @@ -90,6 +104,9 @@ class no_assignment_operator { private: no_assignment_operator& operator=(const no_assignment_operator&); + protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(no_assignment_operator) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(no_assignment_operator) }; /** \internal return the index type with the largest number of bits */ @@ -638,7 +655,7 @@ struct plain_constant_type template struct is_lvalue { - enum { value = !bool(is_const::value) && + enum { value = (!bool(is_const::value)) && bool(traits::Flags & LvalueBit) }; }; diff --git a/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h index ec3b1633..fb11b600 100644 --- a/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/ComplexEigenSolver.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H #define EIGEN_COMPLEX_EIGEN_SOLVER_H @@ -250,7 +250,7 @@ template class ComplexEigenSolver EigenvectorType m_matX; private: - void doComputeEigenvectors(const RealScalar& matrixnorm); + void doComputeEigenvectors(RealScalar matrixnorm); void sortEigenvalues(bool computeEigenvectors); }; @@ -284,10 +284,12 @@ ComplexEigenSolver::compute(const EigenBase& matrix, bool template -void ComplexEigenSolver::doComputeEigenvectors(const RealScalar& matrixnorm) +void ComplexEigenSolver::doComputeEigenvectors(RealScalar matrixnorm) { const Index n = m_eivalues.size(); + matrixnorm = numext::maxi(matrixnorm,(std::numeric_limits::min)()); + // Compute X such that T = X D X^(-1), where D is the diagonal of T. // The matrix X is unit triangular. m_matX = EigenvectorType::Zero(n, n); diff --git a/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h b/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h index 7f38919f..baefac7e 100644 --- a/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h +++ b/eigenlib/Eigen/src/Eigenvalues/ComplexSchur.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLEX_SCHUR_H #define EIGEN_COMPLEX_SCHUR_H @@ -283,7 +283,7 @@ typename ComplexSchur::ComplexScalar ComplexSchur::compu using std::abs; if (iter == 10 || iter == 20) { - // exceptional shift, taken from http://www.netlib.org/eispack/comqr.f + // exceptional shift, taken from xxxp://www.netlib.org/eispack/comqr.f return abs(numext::real(m_matT.coeff(iu,iu-1))) + abs(numext::real(m_matT.coeff(iu-1,iu-2))); } @@ -300,10 +300,13 @@ typename ComplexSchur::ComplexScalar ComplexSchur::compu ComplexScalar trace = t.coeff(0,0) + t.coeff(1,1); ComplexScalar eival1 = (trace + disc) / RealScalar(2); ComplexScalar eival2 = (trace - disc) / RealScalar(2); - - if(numext::norm1(eival1) > numext::norm1(eival2)) + RealScalar eival1_norm = numext::norm1(eival1); + RealScalar eival2_norm = numext::norm1(eival2); + // A division by zero can only occur if eival1==eival2==0. + // In this case, det==0, and all we have to do is checking that eival2_norm!=0 + if(eival1_norm > eival2_norm) eival2 = det / eival1; - else + else if(eival2_norm!=RealScalar(0)) eival1 = det / eival2; // choose the eigenvalue closest to the bottom entry of the diagonal diff --git a/eigenlib/Eigen/src/Eigenvalues/EigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/EigenSolver.h index f205b185..141b6ae9 100644 --- a/eigenlib/Eigen/src/Eigenvalues/EigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/EigenSolver.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_EIGENSOLVER_H #define EIGEN_EIGENSOLVER_H @@ -56,7 +56,7 @@ namespace Eigen { * example of the typical use of this class. * * \note The implementation is adapted from - * JAMA (public domain). + * JAMA (public domain). * Their code is based on EISPACK. * * \sa MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver diff --git a/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h index 36a91dff..94d643cf 100644 --- a/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERALIZEDEIGENSOLVER_H #define EIGEN_GENERALIZEDEIGENSOLVER_H @@ -311,7 +311,6 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp // Aliases: Map v(reinterpret_cast(m_tmp.data()), size); ComplexVectorType &cv = m_tmp; - const MatrixType &mZ = m_realQZ.matrixZ(); const MatrixType &mS = m_realQZ.matrixS(); const MatrixType &mT = m_realQZ.matrixT(); @@ -351,7 +350,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp } } } - m_eivec.col(i).real().noalias() = mZ.transpose() * v; + m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v; m_eivec.col(i).real().normalize(); m_eivec.col(i).imag().setConstant(0); } @@ -400,7 +399,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp / (alpha*mT.coeffRef(j,j) - static_cast(beta*mS.coeffRef(j,j))); } } - m_eivec.col(i+1).noalias() = (mZ.transpose() * cv); + m_eivec.col(i+1).noalias() = (m_realQZ.matrixZ().transpose() * cv); m_eivec.col(i+1).normalize(); m_eivec.col(i) = m_eivec.col(i+1).conjugate(); } diff --git a/eigenlib/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h index 5f6bb828..41871709 100644 --- a/eigenlib/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H #define EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H diff --git a/eigenlib/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/eigenlib/Eigen/src/Eigenvalues/HessenbergDecomposition.h index f647f69b..e712b019 100644 --- a/eigenlib/Eigen/src/Eigenvalues/HessenbergDecomposition.h +++ b/eigenlib/Eigen/src/Eigenvalues/HessenbergDecomposition.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HESSENBERGDECOMPOSITION_H #define EIGEN_HESSENBERGDECOMPOSITION_H diff --git a/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h index 4fec8af0..633d76e9 100644 --- a/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +++ b/eigenlib/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MATRIXBASEEIGENVALUES_H #define EIGEN_MATRIXBASEEIGENVALUES_H @@ -66,7 +66,6 @@ template inline typename MatrixBase::EigenvaluesReturnType MatrixBase::eigenvalues() const { - typedef typename internal::traits::Scalar Scalar; return internal::eigenvalues_selector::IsComplex>::run(derived()); } @@ -88,7 +87,6 @@ template inline typename SelfAdjointView::EigenvaluesReturnType SelfAdjointView::eigenvalues() const { - typedef typename SelfAdjointView::PlainObject PlainObject; PlainObject thisAsMatrix(*this); return SelfAdjointEigenSolver(thisAsMatrix, false).eigenvalues(); } diff --git a/eigenlib/Eigen/src/Eigenvalues/RealQZ.h b/eigenlib/Eigen/src/Eigenvalues/RealQZ.h index b3a910dd..3d332d38 100644 --- a/eigenlib/Eigen/src/Eigenvalues/RealQZ.h +++ b/eigenlib/Eigen/src/Eigenvalues/RealQZ.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REAL_QZ_H #define EIGEN_REAL_QZ_H diff --git a/eigenlib/Eigen/src/Eigenvalues/RealSchur.h b/eigenlib/Eigen/src/Eigenvalues/RealSchur.h index d6a339f0..3d96b6bd 100644 --- a/eigenlib/Eigen/src/Eigenvalues/RealSchur.h +++ b/eigenlib/Eigen/src/Eigenvalues/RealSchur.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REAL_SCHUR_H #define EIGEN_REAL_SCHUR_H @@ -46,7 +46,7 @@ namespace Eigen { * of the typical use of this class. * * \note The implementation is adapted from - * JAMA (public domain). + * JAMA (public domain). * Their code is based on EISPACK. * * \sa class ComplexSchur, class EigenSolver, class ComplexEigenSolver @@ -236,7 +236,7 @@ template class RealSchur typedef Matrix Vector3s; Scalar computeNormOfT(); - Index findSmallSubdiagEntry(Index iu); + Index findSmallSubdiagEntry(Index iu, const Scalar& considerAsZero); void splitOffTwoRows(Index iu, bool computeU, const Scalar& exshift); void computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo); void initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector); @@ -248,12 +248,24 @@ template template RealSchur& RealSchur::compute(const EigenBase& matrix, bool computeU) { + const Scalar considerAsZero = (std::numeric_limits::min)(); + eigen_assert(matrix.cols() == matrix.rows()); Index maxIters = m_maxIters; if (maxIters == -1) maxIters = m_maxIterationsPerRow * matrix.rows(); Scalar scale = matrix.derived().cwiseAbs().maxCoeff(); + if(scale& RealSchur::computeFromHessenberg(const HessMa Index totalIter = 0; // iteration count for whole matrix Scalar exshift(0); // sum of exceptional shifts Scalar norm = computeNormOfT(); + // sub-diagonal entries smaller than considerAsZero will be treated as zero. + // We use eps^2 to enable more precision in small eigenvalues. + Scalar considerAsZero = numext::maxi( norm * numext::abs2(NumTraits::epsilon()), + (std::numeric_limits::min)() ); - if(norm!=0) + if(norm!=Scalar(0)) { while (iu >= 0) { - Index il = findSmallSubdiagEntry(iu); + Index il = findSmallSubdiagEntry(iu,considerAsZero); // Check for convergence if (il == iu) // One root found @@ -315,7 +331,7 @@ RealSchur& RealSchur::computeFromHessenberg(const HessMa else // No convergence yet { // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG ) - Vector3s firstHouseholderVector(0,0,0), shiftInfo; + Vector3s firstHouseholderVector = Vector3s::Zero(), shiftInfo; computeShift(iu, iter, exshift, shiftInfo); iter = iter + 1; totalIter = totalIter + 1; @@ -352,14 +368,17 @@ inline typename MatrixType::Scalar RealSchur::computeNormOfT() /** \internal Look for single small sub-diagonal element and returns its index */ template -inline Index RealSchur::findSmallSubdiagEntry(Index iu) +inline Index RealSchur::findSmallSubdiagEntry(Index iu, const Scalar& considerAsZero) { using std::abs; Index res = iu; while (res > 0) { Scalar s = abs(m_matT.coeff(res-1,res-1)) + abs(m_matT.coeff(res,res)); - if (abs(m_matT.coeff(res,res-1)) <= NumTraits::epsilon() * s) + + s = numext::maxi(s * NumTraits::epsilon(), considerAsZero); + + if (abs(m_matT.coeff(res,res-1)) <= s) break; res--; } diff --git a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h index a9f56c4f..350d4648 100644 --- a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +++ b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H #define EIGEN_SELFADJOINTEIGENSOLVER_H @@ -414,7 +414,8 @@ SelfAdjointEigenSolver& SelfAdjointEigenSolver if(n==1) { - m_eivalues.coeffRef(0,0) = numext::real(matrix.diagonal()[0]); + m_eivec = matrix; + m_eivalues.coeffRef(0,0) = numext::real(m_eivec.coeff(0,0)); if(computeEigenvectors) m_eivec.setOnes(n,n); m_info = Success; @@ -604,7 +605,8 @@ template struct direct_selfadjoint_eigenvalues res, Ref representative) { - using std::abs; + EIGEN_USING_STD_MATH(sqrt) + EIGEN_USING_STD_MATH(abs) Index i0; // Find non-zero column i0 (by construction, there must exist a non zero coefficient on the diagonal): mat.diagonal().cwiseAbs().maxCoeff(&i0); @@ -615,8 +617,8 @@ template struct direct_selfadjoint_eigenvaluesn1) res = c0/std::sqrt(n0); - else res = c1/std::sqrt(n1); + if(n0>n1) res = c0/sqrt(n0); + else res = c1/sqrt(n1); return true; } diff --git a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h index 3891cf88..b0c947dc 100644 --- a/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +++ b/eigenlib/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h @@ -37,7 +37,7 @@ namespace Eigen { /** \internal Specialization for the data types supported by LAPACKe */ -#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW, LAPACKE_COLROW ) \ +#define EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW ) \ template<> template inline \ SelfAdjointEigenSolver >& \ SelfAdjointEigenSolver >::compute(const EigenBase& matrix, int options) \ @@ -47,7 +47,7 @@ SelfAdjointEigenSolver >::compute(c && (options&EigVecMask)!=EigVecMask \ && "invalid option parameter"); \ bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; \ - lapack_int n = internal::convert_index(matrix.cols()), lda, matrix_order, info; \ + lapack_int n = internal::convert_index(matrix.cols()), lda, info; \ m_eivalues.resize(n,1); \ m_subdiag.resize(n-1); \ m_eivec = matrix; \ @@ -63,27 +63,24 @@ SelfAdjointEigenSolver >::compute(c } \ \ lda = internal::convert_index(m_eivec.outerStride()); \ - matrix_order=LAPACKE_COLROW; \ char jobz, uplo='L'/*, range='A'*/; \ jobz = computeEigenvectors ? 'V' : 'N'; \ \ - info = LAPACKE_##LAPACKE_NAME( matrix_order, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ + info = LAPACKE_##LAPACKE_NAME( LAPACK_COL_MAJOR, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ m_info = (info==0) ? Success : NoConvergence; \ m_isInitialized = true; \ m_eigenvectorsOk = computeEigenvectors; \ return *this; \ } +#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, ColMajor ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, RowMajor ) -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, ColMajor, LAPACK_COL_MAJOR) - -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev) +EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev) +EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev) +EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev) } // end namespace Eigen diff --git a/eigenlib/Eigen/src/Eigenvalues/Tridiagonalization.h b/eigenlib/Eigen/src/Eigenvalues/Tridiagonalization.h index 1d102c17..116f53e3 100644 --- a/eigenlib/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/eigenlib/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRIDIAGONALIZATION_H #define EIGEN_TRIDIAGONALIZATION_H diff --git a/eigenlib/Eigen/src/Geometry/AlignedBox.h b/eigenlib/Eigen/src/Geometry/AlignedBox.h index 066eae4f..e46fa872 100644 --- a/eigenlib/Eigen/src/Geometry/AlignedBox.h +++ b/eigenlib/Eigen/src/Geometry/AlignedBox.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ALIGNEDBOX_H #define EIGEN_ALIGNEDBOX_H diff --git a/eigenlib/Eigen/src/Geometry/AngleAxis.h b/eigenlib/Eigen/src/Geometry/AngleAxis.h index 0af3c1b0..1f92ba7e 100644 --- a/eigenlib/Eigen/src/Geometry/AngleAxis.h +++ b/eigenlib/Eigen/src/Geometry/AngleAxis.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ANGLEAXIS_H #define EIGEN_ANGLEAXIS_H @@ -178,7 +178,7 @@ EIGEN_DEVICE_FUNC AngleAxis& AngleAxis::operator=(const Quaterni if (n != Scalar(0)) { m_angle = Scalar(2)*atan2(n, abs(q.w())); - if(q.w() < 0) + if(q.w() < Scalar(0)) n = -n; m_axis = q.vec() / n; } diff --git a/eigenlib/Eigen/src/Geometry/EulerAngles.h b/eigenlib/Eigen/src/Geometry/EulerAngles.h index c633268a..26d782d8 100644 --- a/eigenlib/Eigen/src/Geometry/EulerAngles.h +++ b/eigenlib/Eigen/src/Geometry/EulerAngles.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_EULERANGLES_H #define EIGEN_EULERANGLES_H diff --git a/eigenlib/Eigen/src/Geometry/Homogeneous.h b/eigenlib/Eigen/src/Geometry/Homogeneous.h index 5f0da1a9..040a1973 100644 --- a/eigenlib/Eigen/src/Geometry/Homogeneous.h +++ b/eigenlib/Eigen/src/Geometry/Homogeneous.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HOMOGENEOUS_H #define EIGEN_HOMOGENEOUS_H diff --git a/eigenlib/Eigen/src/Geometry/Hyperplane.h b/eigenlib/Eigen/src/Geometry/Hyperplane.h index 05929b29..d46c6138 100644 --- a/eigenlib/Eigen/src/Geometry/Hyperplane.h +++ b/eigenlib/Eigen/src/Geometry/Hyperplane.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HYPERPLANE_H #define EIGEN_HYPERPLANE_H diff --git a/eigenlib/Eigen/src/Geometry/OrthoMethods.h b/eigenlib/Eigen/src/Geometry/OrthoMethods.h index a035e631..6ef33314 100644 --- a/eigenlib/Eigen/src/Geometry/OrthoMethods.h +++ b/eigenlib/Eigen/src/Geometry/OrthoMethods.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ORTHOMETHODS_H #define EIGEN_ORTHOMETHODS_H @@ -17,7 +17,7 @@ namespace Eigen { * * \returns the cross product of \c *this and \a other * - * Here is a very good explanation of cross-product: http://xkcd.com/199/ + * Here is a very good explanation of cross-product: xxxp://xkcd.com/199/ * * With complex numbers, the cross product is implemented as * \f$ (\mathbf{a}+i\mathbf{b}) \times (\mathbf{c}+i\mathbf{d}) = (\mathbf{a} \times \mathbf{c} - \mathbf{b} \times \mathbf{d}) - i(\mathbf{a} \times \mathbf{d} - \mathbf{b} \times \mathbf{c})\f$ diff --git a/eigenlib/Eigen/src/Geometry/ParametrizedLine.h b/eigenlib/Eigen/src/Geometry/ParametrizedLine.h index 1e985d8c..e7b20361 100644 --- a/eigenlib/Eigen/src/Geometry/ParametrizedLine.h +++ b/eigenlib/Eigen/src/Geometry/ParametrizedLine.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARAMETRIZEDLINE_H #define EIGEN_PARAMETRIZEDLINE_H diff --git a/eigenlib/Eigen/src/Geometry/Quaternion.h b/eigenlib/Eigen/src/Geometry/Quaternion.h index f6ef1bcf..503ed322 100644 --- a/eigenlib/Eigen/src/Geometry/Quaternion.h +++ b/eigenlib/Eigen/src/Geometry/Quaternion.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_QUATERNION_H #define EIGEN_QUATERNION_H @@ -43,6 +43,11 @@ class QuaternionBase : public RotationBase typedef typename internal::traits::Scalar Scalar; typedef typename NumTraits::Real RealScalar; typedef typename internal::traits::Coefficients Coefficients; + typedef typename Coefficients::CoeffReturnType CoeffReturnType; + typedef typename internal::conditional::Flags&LvalueBit), + Scalar&, CoeffReturnType>::type NonConstCoeffReturnType; + + enum { Flags = Eigen::internal::traits::Flags }; @@ -58,22 +63,22 @@ class QuaternionBase : public RotationBase /** \returns the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar x() const { return this->derived().coeffs().coeff(0); } + EIGEN_DEVICE_FUNC inline CoeffReturnType x() const { return this->derived().coeffs().coeff(0); } /** \returns the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar y() const { return this->derived().coeffs().coeff(1); } + EIGEN_DEVICE_FUNC inline CoeffReturnType y() const { return this->derived().coeffs().coeff(1); } /** \returns the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar z() const { return this->derived().coeffs().coeff(2); } + EIGEN_DEVICE_FUNC inline CoeffReturnType z() const { return this->derived().coeffs().coeff(2); } /** \returns the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar w() const { return this->derived().coeffs().coeff(3); } + EIGEN_DEVICE_FUNC inline CoeffReturnType w() const { return this->derived().coeffs().coeff(3); } - /** \returns a reference to the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& x() { return this->derived().coeffs().coeffRef(0); } - /** \returns a reference to the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& y() { return this->derived().coeffs().coeffRef(1); } - /** \returns a reference to the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& z() { return this->derived().coeffs().coeffRef(2); } - /** \returns a reference to the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& w() { return this->derived().coeffs().coeffRef(3); } + /** \returns a reference to the \c x coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType x() { return this->derived().coeffs().x(); } + /** \returns a reference to the \c y coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType y() { return this->derived().coeffs().y(); } + /** \returns a reference to the \c z coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType z() { return this->derived().coeffs().z(); } + /** \returns a reference to the \c w coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType w() { return this->derived().coeffs().w(); } /** \returns a read-only vector expression of the imaginary part (x,y,z) */ EIGEN_DEVICE_FUNC inline const VectorBlock vec() const { return coeffs().template head<3>(); } @@ -164,20 +169,38 @@ class QuaternionBase : public RotationBase /** return the result vector of \a v through the rotation*/ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const; + #ifdef EIGEN_PARSED_BY_DOXYGEN /** \returns \c *this with scalar type casted to \a NewScalarType * * Note that if \a NewScalarType is equal to the current scalar type of \c *this * then this function smartly returns a const reference to \c *this. */ template - EIGEN_DEVICE_FUNC inline typename internal::cast_return_type >::type cast() const + EIGEN_DEVICE_FUNC inline typename internal::cast_return_type >::type cast() const; + + #else + + template + EIGEN_DEVICE_FUNC inline + typename internal::enable_if::value,const Derived&>::type cast() const { - return typename internal::cast_return_type >::type(derived()); + return derived(); } + template + EIGEN_DEVICE_FUNC inline + typename internal::enable_if::value,Quaternion >::type cast() const + { + return Quaternion(coeffs().template cast()); + } + #endif + #ifdef EIGEN_QUATERNIONBASE_PLUGIN # include EIGEN_QUATERNIONBASE_PLUGIN #endif +protected: + EIGEN_DEFAULT_COPY_CONSTRUCTOR(QuaternionBase) + EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(QuaternionBase) }; /*************************************************************************** @@ -423,7 +446,7 @@ typedef Map, Aligned> QuaternionMapAlignedd; // Generic Quaternion * Quaternion product // This product can be specialized for a given architecture via the Arch template argument. namespace internal { -template struct quat_product +template struct quat_product { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& a, const QuaternionBase& b){ return Quaternion @@ -446,8 +469,7 @@ QuaternionBase::operator* (const QuaternionBase& other) c EIGEN_STATIC_ASSERT((internal::is_same::value), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) return internal::quat_product::Scalar, - EIGEN_PLAIN_ENUM_MIN(internal::traits::Alignment, internal::traits::Alignment)>::run(*this, other); + typename internal::traits::Scalar>::run(*this, other); } /** \sa operator*(Quaternion) */ @@ -613,7 +635,7 @@ EIGEN_DEVICE_FUNC inline Derived& QuaternionBase::setFromTwoVectors(con /** \returns a random unit quaternion following a uniform distribution law on SO(3) * - * \note The implementation is based on http://planning.cs.uiuc.edu/node198.html + * \note The implementation is based on xxxp://planning.cs.uiuc.edu/node198.html */ template EIGEN_DEVICE_FUNC Quaternion Quaternion::UnitRandom() @@ -672,7 +694,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> // Generic conjugate of a Quaternion namespace internal { -template struct quat_conj +template struct quat_conj { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& q){ return Quaternion(q.w(),-q.x(),-q.y(),-q.z()); @@ -691,8 +713,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> QuaternionBase::conjugate() const { return internal::quat_conj::Scalar, - internal::traits::Alignment>::run(*this); + typename internal::traits::Scalar>::run(*this); } @@ -715,7 +736,7 @@ QuaternionBase::angularDistance(const QuaternionBase& oth * \c *this and \a other at the parameter \a t in [0;1]. * * This represents an interpolation for a constant motion between \c *this and \a other, - * see also http://en.wikipedia.org/wiki/Slerp. + * see also xxxp://en.wikipedia.org/wiki/Slerp. */ template template diff --git a/eigenlib/Eigen/src/Geometry/Rotation2D.h b/eigenlib/Eigen/src/Geometry/Rotation2D.h index 884b7d0e..f62b0e74 100644 --- a/eigenlib/Eigen/src/Geometry/Rotation2D.h +++ b/eigenlib/Eigen/src/Geometry/Rotation2D.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ROTATION2D_H #define EIGEN_ROTATION2D_H diff --git a/eigenlib/Eigen/src/Geometry/RotationBase.h b/eigenlib/Eigen/src/Geometry/RotationBase.h index f0ee0bd0..f59d2ddc 100644 --- a/eigenlib/Eigen/src/Geometry/RotationBase.h +++ b/eigenlib/Eigen/src/Geometry/RotationBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ROTATIONBASE_H #define EIGEN_ROTATIONBASE_H diff --git a/eigenlib/Eigen/src/Geometry/Scaling.h b/eigenlib/Eigen/src/Geometry/Scaling.h old mode 100755 new mode 100644 index f58ca03d..3372508d --- a/eigenlib/Eigen/src/Geometry/Scaling.h +++ b/eigenlib/Eigen/src/Geometry/Scaling.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SCALING_H #define EIGEN_SCALING_H @@ -14,7 +14,7 @@ namespace Eigen { /** \geometry_module \ingroup Geometry_Module * - * \class Scaling + * \class UniformScaling * * \brief Represents a generic uniform scaling transformation * diff --git a/eigenlib/Eigen/src/Geometry/Transform.h b/eigenlib/Eigen/src/Geometry/Transform.h index 3f31ee45..45a71815 100644 --- a/eigenlib/Eigen/src/Geometry/Transform.h +++ b/eigenlib/Eigen/src/Geometry/Transform.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRANSFORM_H #define EIGEN_TRANSFORM_H @@ -252,11 +252,11 @@ protected: public: /** Default constructor without initialization of the meaningful coefficients. - * If Mode==Affine, then the last row is set to [0 ... 0 1] */ + * If Mode==Affine or Mode==Isometry, then the last row is set to [0 ... 0 1] */ EIGEN_DEVICE_FUNC inline Transform() { check_template_params(); - internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix); + internal::transform_make_affine<(int(Mode)==Affine || int(Mode)==Isometry) ? Affine : AffineCompact>::run(m_matrix); } EIGEN_DEVICE_FUNC inline Transform(const Transform& other) diff --git a/eigenlib/Eigen/src/Geometry/Translation.h b/eigenlib/Eigen/src/Geometry/Translation.h index 51d9a82e..c6cbb1d4 100644 --- a/eigenlib/Eigen/src/Geometry/Translation.h +++ b/eigenlib/Eigen/src/Geometry/Translation.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_TRANSLATION_H #define EIGEN_TRANSLATION_H @@ -138,12 +138,6 @@ public: /** \returns the inverse translation (opposite) */ Translation inverse() const { return Translation(-m_coeffs); } - Translation& operator=(const Translation& other) - { - m_coeffs = other.m_coeffs; - return *this; - } - static const Translation Identity() { return Translation(VectorType::Zero()); } /** \returns \c *this with scalar type casted to \a NewScalarType diff --git a/eigenlib/Eigen/src/Geometry/Umeyama.h b/eigenlib/Eigen/src/Geometry/Umeyama.h index 7e933fca..566b824c 100644 --- a/eigenlib/Eigen/src/Geometry/Umeyama.h +++ b/eigenlib/Eigen/src/Geometry/Umeyama.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_UMEYAMA_H #define EIGEN_UMEYAMA_H @@ -87,7 +87,7 @@ struct umeyama_transform_matrix_type * \f{align*} * T = \begin{bmatrix} c\mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix} * \f} -* minimizing the resudiual above. This transformation is always returned as an +* minimizing the residual above. This transformation is always returned as an * Eigen::Matrix. */ template diff --git a/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h b/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h index 1a86ff83..625ee0a0 100644 --- a/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/eigenlib/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_GEOMETRY_SSE_H #define EIGEN_GEOMETRY_SSE_H @@ -16,17 +16,23 @@ namespace Eigen { namespace internal { template -struct quat_product +struct quat_product { + enum { + AAlignment = traits::Alignment, + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { Quaternion res; const __m128 mask = _mm_setr_ps(0.f,0.f,0.f,-0.f); - __m128 a = _a.coeffs().template packet(0); - __m128 b = _b.coeffs().template packet(0); + __m128 a = _a.coeffs().template packet(0); + __m128 b = _b.coeffs().template packet(0); __m128 s1 = _mm_mul_ps(vec4f_swizzle1(a,1,2,0,2),vec4f_swizzle1(b,2,0,1,2)); __m128 s2 = _mm_mul_ps(vec4f_swizzle1(a,3,3,3,1),vec4f_swizzle1(b,0,1,2,1)); - pstore(&res.x(), + pstoret( + &res.x(), _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,vec4f_swizzle1(b,3,3,3,3)), _mm_mul_ps(vec4f_swizzle1(a,2,0,1,0), vec4f_swizzle1(b,1,2,0,0))), @@ -36,14 +42,17 @@ struct quat_product } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128 mask = _mm_setr_ps(-0.f,-0.f,-0.f,0.f); - pstore(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet(0))); + pstoret(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet::Alignment>(0))); return res; } }; @@ -52,6 +61,9 @@ struct quat_conj template struct cross3_impl { + enum { + ResAlignment = traits::type>::Alignment + }; static inline typename plain_matrix_type::type run(const VectorLhs& lhs, const VectorRhs& rhs) { @@ -60,7 +72,7 @@ struct cross3_impl __m128 mul1=_mm_mul_ps(vec4f_swizzle1(a,1,2,0,3),vec4f_swizzle1(b,2,0,1,3)); __m128 mul2=_mm_mul_ps(vec4f_swizzle1(a,2,0,1,3),vec4f_swizzle1(b,1,2,0,3)); typename plain_matrix_type::type res; - pstore(&res.x(),_mm_sub_ps(mul1,mul2)); + pstoret(&res.x(),_mm_sub_ps(mul1,mul2)); return res; } }; @@ -68,9 +80,14 @@ struct cross3_impl -template -struct quat_product +template +struct quat_product { + enum { + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; + static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); @@ -78,8 +95,8 @@ struct quat_product Quaternion res; const double* a = _a.coeffs().data(); - Packet2d b_xy = _b.coeffs().template packet(0); - Packet2d b_zw = _b.coeffs().template packet(2); + Packet2d b_xy = _b.coeffs().template packet(0); + Packet2d b_zw = _b.coeffs().template packet(2); Packet2d a_xx = pset1(a[0]); Packet2d a_yy = pset1(a[1]); Packet2d a_zz = pset1(a[2]); @@ -97,9 +114,9 @@ struct quat_product t2 = psub(pmul(a_zz, b_xy), pmul(a_xx, b_zw)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.x(), _mm_addsub_pd(t1, preverse(t2))); + pstoret(&res.x(), _mm_addsub_pd(t1, preverse(t2))); #else - pstore(&res.x(), padd(t1, pxor(mask,preverse(t2)))); + pstoret(&res.x(), padd(t1, pxor(mask,preverse(t2)))); #endif /* @@ -111,25 +128,28 @@ struct quat_product t2 = padd(pmul(a_zz, b_zw), pmul(a_xx, b_xy)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); + pstoret(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); #else - pstore(&res.z(), psub(t1, pxor(mask,preverse(t2)))); + pstoret(&res.z(), psub(t1, pxor(mask,preverse(t2)))); #endif return res; } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128d mask0 = _mm_setr_pd(-0.,-0.); const __m128d mask2 = _mm_setr_pd(-0.,0.); - pstore(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet(0))); - pstore(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet(2))); + pstoret(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet::Alignment>(0))); + pstoret(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet::Alignment>(2))); return res; } }; diff --git a/eigenlib/Eigen/src/Householder/BlockHouseholder.h b/eigenlib/Eigen/src/Householder/BlockHouseholder.h index 39bf8c83..17a661c5 100644 --- a/eigenlib/Eigen/src/Householder/BlockHouseholder.h +++ b/eigenlib/Eigen/src/Householder/BlockHouseholder.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BLOCK_HOUSEHOLDER_H #define EIGEN_BLOCK_HOUSEHOLDER_H @@ -87,7 +87,8 @@ void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vec const TriangularView V(vectors); // A -= V T V^* A - Matrix tmp = V.adjoint() * mat; // FIXME add .noalias() once the triangular product can work inplace if(forward) tmp = T.template triangularView() * tmp; diff --git a/eigenlib/Eigen/src/Householder/Householder.h b/eigenlib/Eigen/src/Householder/Householder.h index 80de2c30..c6133f6b 100644 --- a/eigenlib/Eigen/src/Householder/Householder.h +++ b/eigenlib/Eigen/src/Householder/Householder.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HOUSEHOLDER_H #define EIGEN_HOUSEHOLDER_H diff --git a/eigenlib/Eigen/src/Householder/HouseholderSequence.h b/eigenlib/Eigen/src/Householder/HouseholderSequence.h index 3ce0a693..bfd54244 100644 --- a/eigenlib/Eigen/src/Householder/HouseholderSequence.h +++ b/eigenlib/Eigen/src/Householder/HouseholderSequence.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H #define EIGEN_HOUSEHOLDER_SEQUENCE_H diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h index 358444af..835b5feb 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BASIC_PRECONDITIONERS_H #define EIGEN_BASIC_PRECONDITIONERS_H @@ -152,13 +152,28 @@ class LeastSquareDiagonalPreconditioner : public DiagonalPreconditioner<_Scalar> { // Compute the inverse squared-norm of each column of mat m_invdiag.resize(mat.cols()); - for(Index j=0; j0) - m_invdiag(j) = RealScalar(1)/sum; - else - m_invdiag(j) = RealScalar(1); + m_invdiag.setZero(); + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/numext::real(m_invdiag(j)); + } + else + { + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/sum; + else + m_invdiag(j) = RealScalar(1); + } } Base::m_isInitialized = true; return *this; diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/eigenlib/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h index 454f4681..dc8485f7 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BICGSTAB_H #define EIGEN_BICGSTAB_H diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h index 395daa8e..6d55f5cf 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CONJUGATE_GRADIENT_H #define EIGEN_CONJUGATE_GRADIENT_H @@ -50,7 +50,8 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, tol_error = 0; return; } - RealScalar threshold = tol*tol*rhsNorm2; + const RealScalar considerAsZero = (std::numeric_limits::min)(); + RealScalar threshold = numext::maxi(tol*tol*rhsNorm2,considerAsZero); RealScalar residualNorm2 = residual.squaredNorm(); if (residualNorm2 < threshold) { @@ -58,7 +59,7 @@ void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, tol_error = sqrt(residualNorm2 / rhsNorm2); return; } - + VectorType p(n); p = precond.solve(residual); // initial search direction diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h b/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h index e45c272b..57651e58 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_INCOMPLETE_CHOlESKY_H #define EIGEN_INCOMPLETE_CHOlESKY_H @@ -190,7 +190,7 @@ class IncompleteCholesky : public SparseSolverBase template void IncompleteCholesky::factorize(const _MatrixType& mat) diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h index 338e6f10..56aa1db4 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_INCOMPLETE_LUT_H #define EIGEN_INCOMPLETE_LUT_H @@ -88,12 +88,12 @@ Index QuickSplit(VectorV &row, VectorI &ind, Index ncut) * NOTE : The following implementation is derived from the ILUT implementation * in the SPARSKIT package, Copyright (C) 2005, the Regents of the University of Minnesota * released under the terms of the GNU LGPL: - * http://www-users.cs.umn.edu/~saad/software/SPARSKIT/README + * xxxp://www-users.cs.umn.edu/~saad/software/SPARSKIT/README * However, Yousef Saad gave us permission to relicense his ILUT code to MPL2. * See the Eigen mailing list archive, thread: ILUT, date: July 8, 2012: - * http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00064.html + * xxxp://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00064.html * alternatively, on GMANE: - * http://comments.gmane.org/gmane.comp.lib.eigen/3302 + * xxxp://comments.gmane.org/gmane.comp.lib.eigen/3302 */ template class IncompleteLUT : public SparseSolverBase > diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/eigenlib/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h index 7c2326eb..07a0a51d 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ITERATIVE_SOLVER_BASE_H #define EIGEN_ITERATIVE_SOLVER_BASE_H diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h b/eigenlib/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h index 0aea0e09..6062e8dc 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_LEAST_SQUARE_CONJUGATE_GRADIENT_H #define EIGEN_LEAST_SQUARE_CONJUGATE_GRADIENT_H diff --git a/eigenlib/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h b/eigenlib/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h index 0ace4517..6677f4fc 100644 --- a/eigenlib/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h +++ b/eigenlib/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SOLVEWITHGUESS_H #define EIGEN_SOLVEWITHGUESS_H diff --git a/eigenlib/Eigen/src/Jacobi/Jacobi.h b/eigenlib/Eigen/src/Jacobi/Jacobi.h index d25af8e9..2129b64b 100644 --- a/eigenlib/Eigen/src/Jacobi/Jacobi.h +++ b/eigenlib/Eigen/src/Jacobi/Jacobi.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_JACOBI_H #define EIGEN_JACOBI_H @@ -65,11 +65,11 @@ template class JacobiRotation bool makeJacobi(const MatrixBase&, Index p, Index q); bool makeJacobi(const RealScalar& x, const Scalar& y, const RealScalar& z); - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z=0); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r=0); protected: - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::true_type); - void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::false_type); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::true_type); + void makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type); Scalar m_c, m_s; }; @@ -84,7 +84,6 @@ bool JacobiRotation::makeJacobi(const RealScalar& x, const Scalar& y, co { using std::sqrt; using std::abs; - typedef typename NumTraits::Real RealScalar; RealScalar deno = RealScalar(2)*abs(y); if(deno < (std::numeric_limits::min)()) { @@ -133,7 +132,7 @@ inline bool JacobiRotation::makeJacobi(const MatrixBase& m, Ind * \f$ V = \left ( \begin{array}{c} p \\ q \end{array} \right )\f$ yields: * \f$ G^* V = \left ( \begin{array}{c} r \\ 0 \end{array} \right )\f$. * - * The value of \a z is returned if \a z is not null (the default is null). + * The value of \a r is returned if \a r is not null (the default is null). * Also note that G is built such that the cosine is always real. * * Example: \include Jacobi_makeGivens.cpp @@ -146,9 +145,9 @@ inline bool JacobiRotation::makeJacobi(const MatrixBase& m, Ind * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight() */ template -void JacobiRotation::makeGivens(const Scalar& p, const Scalar& q, Scalar* z) +void JacobiRotation::makeGivens(const Scalar& p, const Scalar& q, Scalar* r) { - makeGivens(p, q, z, typename internal::conditional::IsComplex, internal::true_type, internal::false_type>::type()); + makeGivens(p, q, r, typename internal::conditional::IsComplex, internal::true_type, internal::false_type>::type()); } @@ -298,12 +297,144 @@ inline void MatrixBase::applyOnTheRight(Index p, Index q, const JacobiR } namespace internal { + +template +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + for(Index i=0; i +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + enum { + PacketSize = packet_traits::size, + OtherPacketSize = packet_traits::size + }; + typedef typename packet_traits::type Packet; + typedef typename packet_traits::type OtherPacket; + + /*** dynamic-size vectorized paths ***/ + if(SizeAtCompileTime == Dynamic && ((incrx==1 && incry==1) || PacketSize == 1)) + { + // both vectors are sequentially stored in memory => vectorization + enum { Peeling = 2 }; + + Index alignedStart = internal::first_default_aligned(y, size); + Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; + + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + else + { + Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); + for(Index i=alignedStart; i(px); + Packet xi1 = ploadu(px+PacketSize); + Packet yi = pload (py); + Packet yi1 = pload (py+PacketSize); + pstoreu(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstoreu(px+PacketSize, padd(pm.pmul(pc,xi1),pcj.pmul(ps,yi1))); + pstore (py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pm.pmul(ps,xi1))); + px += Peeling*PacketSize; + py += Peeling*PacketSize; + } + if(alignedEnd!=peelingEnd) + { + Packet xi = ploadu(x+peelingEnd); + Packet yi = pload (y+peelingEnd); + pstoreu(x+peelingEnd, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + } + } + + for(Index i=alignedEnd; i0) // FIXME should be compared to the required alignment + { + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + Scalar* EIGEN_RESTRICT px = x; + Scalar* EIGEN_RESTRICT py = y; + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + + /*** non-vectorized path ***/ + else + { + apply_rotation_in_the_plane_selector::run(x,incrx,y,incry,size,c,s); + } + } +}; + template void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x, DenseBase& xpr_y, const JacobiRotation& j) { typedef typename VectorX::Scalar Scalar; - enum { PacketSize = packet_traits::size }; - typedef typename packet_traits::type Packet; + const bool Vectorizable = (VectorX::Flags & VectorY::Flags & PacketAccessBit) + && (int(packet_traits::size) == int(packet_traits::size)); + eigen_assert(xpr_x.size() == xpr_y.size()); Index size = xpr_x.size(); Index incrx = xpr_x.derived().innerStride(); @@ -317,113 +448,11 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x if (c==OtherScalar(1) && s==OtherScalar(0)) return; - /*** dynamic-size vectorized paths ***/ - - if(VectorX::SizeAtCompileTime == Dynamic && - (VectorX::Flags & VectorY::Flags & PacketAccessBit) && - ((incrx==1 && incry==1) || PacketSize == 1)) - { - // both vectors are sequentially stored in memory => vectorization - enum { Peeling = 2 }; - - Index alignedStart = internal::first_default_aligned(y, size); - Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; - - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - else - { - Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); - for(Index i=alignedStart; i(px); - Packet xi1 = ploadu(px+PacketSize); - Packet yi = pload (py); - Packet yi1 = pload (py+PacketSize); - pstoreu(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstoreu(px+PacketSize, padd(pmul(pc,xi1),pcj.pmul(ps,yi1))); - pstore (py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pmul(ps,xi1))); - px += Peeling*PacketSize; - py += Peeling*PacketSize; - } - if(alignedEnd!=peelingEnd) - { - Packet xi = ploadu(x+peelingEnd); - Packet yi = pload (y+peelingEnd); - pstoreu(x+peelingEnd, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - } - } - - for(Index i=alignedEnd; i::Alignment, evaluator::Alignment)>0)) // FIXME should be compared to the required alignment - { - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - Scalar* EIGEN_RESTRICT px = x; - Scalar* EIGEN_RESTRICT py = y; - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - - /*** non-vectorized path ***/ - else - { - for(Index i=0; i::Alignment, evaluator::Alignment), + Vectorizable>::run(x,incrx,y,incry,size,c,s); } } // end namespace internal diff --git a/eigenlib/Eigen/src/LU/Determinant.h b/eigenlib/Eigen/src/LU/Determinant.h index d6a3c1e5..516583b6 100644 --- a/eigenlib/Eigen/src/LU/Determinant.h +++ b/eigenlib/Eigen/src/LU/Determinant.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_DETERMINANT_H #define EIGEN_DETERMINANT_H diff --git a/eigenlib/Eigen/src/LU/FullPivLU.h b/eigenlib/Eigen/src/LU/FullPivLU.h index 03b6af70..69e7c249 100644 --- a/eigenlib/Eigen/src/LU/FullPivLU.h +++ b/eigenlib/Eigen/src/LU/FullPivLU.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_LU_H #define EIGEN_LU_H diff --git a/eigenlib/Eigen/src/LU/InverseImpl.h b/eigenlib/Eigen/src/LU/InverseImpl.h index 018f99b5..68166e85 100644 --- a/eigenlib/Eigen/src/LU/InverseImpl.h +++ b/eigenlib/Eigen/src/LU/InverseImpl.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_INVERSE_IMPL_H #define EIGEN_INVERSE_IMPL_H @@ -404,7 +404,7 @@ inline void MatrixBase::computeInverseWithCheck( const RealScalar& absDeterminantThreshold ) const { - RealScalar determinant; + Scalar determinant; // i'd love to put some static assertions there, but SFINAE means that they have no effect... eigen_assert(rows() == cols()); computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold); diff --git a/eigenlib/Eigen/src/LU/PartialPivLU.h b/eigenlib/Eigen/src/LU/PartialPivLU.h index d4396188..935adbcc 100644 --- a/eigenlib/Eigen/src/LU/PartialPivLU.h +++ b/eigenlib/Eigen/src/LU/PartialPivLU.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARTIALLU_H #define EIGEN_PARTIALLU_H @@ -519,7 +519,10 @@ void PartialPivLU::compute() // the row permutation is stored as int indices, so just to be sure: eigen_assert(m_lu.rows()::highest()); - m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff(); + if(m_lu.cols()>0) + m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff(); + else + m_l1_norm = RealScalar(0); eigen_assert(m_lu.rows() == m_lu.cols() && "PartialPivLU is only for square (and moreover invertible) matrices"); const Index size = m_lu.rows(); diff --git a/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h b/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h index ebb64a62..11f4018c 100644 --- a/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h +++ b/eigenlib/Eigen/src/LU/arch/Inverse_SSE.h @@ -7,11 +7,11 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // The SSE code for the 4x4 float and double matrix inverse in this file // comes from the following Intel's library: -// http://software.intel.com/en-us/articles/optimized-matrix-library-for-use-with-the-intel-pentiumr-4-processors-sse2-instructions/ +// xxxp://software.intel.com/en-us/articles/optimized-matrix-library-for-use-with-the-intel-pentiumr-4-processors-sse2-instructions/ // // Here is the respective copyright and license statement: // @@ -44,7 +44,7 @@ struct compute_inverse_size4 static void run(const MatrixType& mat, ResultType& result) { ActualMatrixType matrix(mat); - EIGEN_ALIGN16 const unsigned int _Sign_PNNP[4] = { 0x00000000, 0x80000000, 0x80000000, 0x00000000 }; + const Packet4f p4f_sign_PNNP = _mm_castsi128_ps(_mm_set_epi32(0x00000000, 0x80000000, 0x80000000, 0x00000000)); // Load the full matrix into registers __m128 _L1 = matrix.template packet( 0); @@ -139,7 +139,7 @@ struct compute_inverse_size4 iC = _mm_sub_ps(iC, _mm_mul_ps(_mm_shuffle_ps(A,A,0xB1), _mm_shuffle_ps(DC,DC,0x66))); rd = _mm_shuffle_ps(rd,rd,0); - rd = _mm_xor_ps(rd, _mm_load_ps((float*)_Sign_PNNP)); + rd = _mm_xor_ps(rd, p4f_sign_PNNP); // iB = C*|B| - D*B#*A iB = _mm_sub_ps(_mm_mul_ps(C,_mm_shuffle_ps(dB,dB,0)), iB); diff --git a/eigenlib/Eigen/src/MetisSupport/MetisSupport.h b/eigenlib/Eigen/src/MetisSupport/MetisSupport.h index 4c15304a..cbed964c 100644 --- a/eigenlib/Eigen/src/MetisSupport/MetisSupport.h +++ b/eigenlib/Eigen/src/MetisSupport/MetisSupport.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef METIS_SUPPORT_H #define METIS_SUPPORT_H diff --git a/eigenlib/Eigen/src/OrderingMethods/Amd.h b/eigenlib/Eigen/src/OrderingMethods/Amd.h index f91ecb24..208e8e5b 100644 --- a/eigenlib/Eigen/src/OrderingMethods/Amd.h +++ b/eigenlib/Eigen/src/OrderingMethods/Amd.h @@ -8,7 +8,7 @@ NOTE: this routine has been adapted from the CSparse library: Copyright (c) 2006, Timothy A. Davis. -http://www.suitesparse.com +xxxp://www.suitesparse.com CSparse is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h b/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h index 933cd564..50cd9dcc 100644 --- a/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h +++ b/eigenlib/Eigen/src/OrderingMethods/Eigen_Colamd.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // This file is modified from the colamd/symamd library. The copyright is below @@ -41,7 +41,7 @@ // // The colamd/symamd library is available at // -// http://www.suitesparse.com +// xxxp://www.suitesparse.com #ifndef EIGEN_COLAMD_H @@ -1004,7 +1004,7 @@ static IndexType find_ordering /* return the number of garbage collections */ COLAMD_ASSERT (head [min_score] >= COLAMD_EMPTY) ; /* get pivot column from head of minimum degree list */ - while (head [min_score] == COLAMD_EMPTY && min_score < n_col) + while (min_score < n_col && head [min_score] == COLAMD_EMPTY) { min_score++ ; } diff --git a/eigenlib/Eigen/src/OrderingMethods/Ordering.h b/eigenlib/Eigen/src/OrderingMethods/Ordering.h index 7ea9b14d..d3c74f77 100644 --- a/eigenlib/Eigen/src/OrderingMethods/Ordering.h +++ b/eigenlib/Eigen/src/OrderingMethods/Ordering.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_ORDERING_H #define EIGEN_ORDERING_H diff --git a/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h b/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h index d2ebfd7b..91df321d 100644 --- a/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h +++ b/eigenlib/Eigen/src/PaStiXSupport/PaStiXSupport.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PASTIXSUPPORT_H #define EIGEN_PASTIXSUPPORT_H @@ -64,28 +64,28 @@ namespace internal typedef typename _MatrixType::StorageIndex StorageIndex; }; - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} s_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} d_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast(vals), perm, invp, reinterpret_cast(x), nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} diff --git a/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h b/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h index 091c3970..98d0e3f2 100644 --- a/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h +++ b/eigenlib/Eigen/src/PardisoSupport/PardisoSupport.h @@ -192,7 +192,8 @@ class PardisoImpl : public SparseSolverBase void pardisoInit(int type) { m_type = type; - bool symmetric = std::abs(m_type) < 10; + EIGEN_USING_STD_MATH(abs); + bool symmetric = abs(m_type) < 10; m_iparm[0] = 1; // No solver default m_iparm[1] = 2; // use Metis for the ordering m_iparm[2] = 0; // Reserved. Set to zero. (??Numbers of processors, value of OMP_NUM_THREADS??) diff --git a/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h b/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h index 0e47c833..b6b39f36 100644 --- a/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h +++ b/eigenlib/Eigen/src/QR/ColPivHouseholderQR.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H #define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H @@ -506,8 +506,8 @@ void ColPivHouseholderQR::computeInPlace() m_colNormsUpdated.coeffRef(k) = m_colNormsDirect.coeffRef(k); } - RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); - RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); + RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); + RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case) m_maxpivot = RealScalar(0); @@ -550,15 +550,15 @@ void ColPivHouseholderQR::computeInPlace() // update our table of norms of the columns for (Index j = k + 1; j < cols; ++j) { // The following implements the stable norm downgrade step discussed in - // http://www.netlib.org/lapack/lawnspdf/lawn176.pdf + // xxxp://www.netlib.org/lapack/lawnspdf/lawn176.pdf // and used in LAPACK routines xGEQPF and xGEQP3. - // See lines 278-297 in http://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html - if (m_colNormsUpdated.coeffRef(j) != 0) { + // See lines 278-297 in xxxp://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html + if (m_colNormsUpdated.coeffRef(j) != RealScalar(0)) { RealScalar temp = abs(m_qr.coeffRef(k, j)) / m_colNormsUpdated.coeffRef(j); temp = (RealScalar(1) + temp) * (RealScalar(1) - temp); - temp = temp < 0 ? 0 : temp; - RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / - m_colNormsDirect.coeffRef(j)); + temp = temp < RealScalar(0) ? RealScalar(0) : temp; + RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / + m_colNormsDirect.coeffRef(j)); if (temp2 <= norm_downdate_threshold) { // The updated norm has become too inaccurate so re-compute the column // norm directly. diff --git a/eigenlib/Eigen/src/QR/CompleteOrthogonalDecomposition.h b/eigenlib/Eigen/src/QR/CompleteOrthogonalDecomposition.h index 34c637b7..13b260d7 100644 --- a/eigenlib/Eigen/src/QR/CompleteOrthogonalDecomposition.h +++ b/eigenlib/Eigen/src/QR/CompleteOrthogonalDecomposition.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H #define EIGEN_COMPLETEORTHOGONALDECOMPOSITION_H diff --git a/eigenlib/Eigen/src/QR/FullPivHouseholderQR.h b/eigenlib/Eigen/src/QR/FullPivHouseholderQR.h index e489bddc..a4437795 100644 --- a/eigenlib/Eigen/src/QR/FullPivHouseholderQR.h +++ b/eigenlib/Eigen/src/QR/FullPivHouseholderQR.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H #define EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H diff --git a/eigenlib/Eigen/src/QR/HouseholderQR.h b/eigenlib/Eigen/src/QR/HouseholderQR.h index 3513d995..e4e94280 100644 --- a/eigenlib/Eigen/src/QR/HouseholderQR.h +++ b/eigenlib/Eigen/src/QR/HouseholderQR.h @@ -7,7 +7,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_QR_H #define EIGEN_QR_H diff --git a/eigenlib/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h b/eigenlib/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h index 953d57c9..2237e0b3 100644 --- a/eigenlib/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h +++ b/eigenlib/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SUITESPARSEQRSUPPORT_H #define EIGEN_SUITESPARSEQRSUPPORT_H diff --git a/eigenlib/Eigen/src/SVD/BDCSVD.h b/eigenlib/Eigen/src/SVD/BDCSVD.h index 25fca6f4..d451f61f 100644 --- a/eigenlib/Eigen/src/SVD/BDCSVD.h +++ b/eigenlib/Eigen/src/SVD/BDCSVD.h @@ -11,11 +11,11 @@ // Copyright (C) 2013 Jean Ceccato // Copyright (C) 2013 Pierre Zoppitelli // Copyright (C) 2013 Jitse Niesen -// Copyright (C) 2014-2016 Gael Guennebaud +// Copyright (C) 2014-2017 Gael Guennebaud // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BDCSVD_H #define EIGEN_BDCSVD_H @@ -77,6 +77,7 @@ public: typedef _MatrixType MatrixType; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits::Real RealScalar; + typedef typename NumTraits::Literal Literal; enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, ColsAtCompileTime = MatrixType::ColsAtCompileTime, @@ -259,7 +260,7 @@ BDCSVD& BDCSVD::compute(const MatrixType& matrix, unsign //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows RealScalar scale = matrix.cwiseAbs().maxCoeff(); - if(scale==RealScalar(0)) scale = RealScalar(1); + if(scale==Literal(0)) scale = Literal(1); MatrixX copy; if (m_isTranspose) copy = matrix.adjoint()/scale; else copy = matrix/scale; @@ -351,13 +352,13 @@ void BDCSVD::structured_update(Block A, co Index k1=0, k2=0; for(Index j=0; j::divide (Index firstCol, Index lastCol, Index firstRowW, l = m_naiveU.row(1).segment(firstCol, k); f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1); } - if (m_compV) m_naiveV(firstRowW+k, firstColW) = 1; + if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1); if (r0::divide (Index firstCol, Index lastCol, Index firstRowW, // // TODO Opportunities for optimization: better root finding algo, better stopping criterion, better // handling of round-off errors, be consistent in ordering -// For instance, to solve the secular equation using FMM, see http://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf +// For instance, to solve the secular equation using FMM, see xxxp://www.stat.uchicago.edu/~lekheng/courses/302/classics/greengard-rokhlin.pdf template void BDCSVD::computeSVDofM(Index firstCol, Index n, MatrixXr& U, VectorType& singVals, MatrixXr& V) { @@ -574,7 +575,7 @@ void BDCSVD::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n); m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal(); ArrayRef diag = m_workspace.head(n); - diag(0) = 0; + diag(0) = Literal(0); // Allocate space for singular values and vectors singVals.resize(n); @@ -590,7 +591,7 @@ void BDCSVD::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec // but others are interleaved and we must ignore them at this stage. // To this end, let's compute a permutation skipping them: Index actual_n = n; - while(actual_n>1 && diag(actual_n-1)==0) --actual_n; + while(actual_n>1 && diag(actual_n-1)==Literal(0)) --actual_n; Index m = 0; // size of the deflated problem for(Index k=0;kconsiderZero) @@ -691,11 +692,13 @@ template typename BDCSVD::RealScalar BDCSVD::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift) { Index m = perm.size(); - RealScalar res = 1; + RealScalar res = Literal(1); for(Index i=0; i::computeSingVals(const ArrayRef& col0, const ArrayRef& d { using std::abs; using std::swap; + using std::sqrt; Index n = col0.size(); Index actual_n = n; - while(actual_n>1 && col0(actual_n-1)==0) --actual_n; + // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above + // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value. + while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n; for (Index k = 0; k < n; ++k) { - if (col0(k) == 0 || actual_n==1) + if (col0(k) == Literal(0) || actual_n==1) { // if col0(k) == 0, then entry is deflated, so singular value is on diagonal // if actual_n==1, then the deflated problem is already diagonalized singVals(k) = k==0 ? col0(0) : diag(k); - mus(k) = 0; + mus(k) = Literal(0); shifts(k) = k==0 ? col0(0) : diag(k); continue; } @@ -731,15 +737,17 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d right = (diag(actual_n-1) + col0.matrix().norm()); else { - // Skip deflated singular values + // Skip deflated singular values, + // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside. + // This should be equivalent to using perm[] Index l = k+1; - while(col0(l)==0) { ++l; eigen_internal_assert(l::computeSingVals(const ArrayRef& col0, const ArrayRef& d << " " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0) << " " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n"; #endif - RealScalar shift = (k == actual_n-1 || fMid > 0) ? left : right; + RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right; // measure everything relative to shift Map diagShifted(m_workspace.data()+4*n, n); diagShifted = diag - shift; + + if(k!=actual_n-1) + { + // check that after the shift, f(mid) is still negative: + RealScalar midShifted = (right - left) / RealScalar(2); + if(shift==right) + midShifted = -midShifted; + RealScalar fMidShifted = secularEq(midShifted, col0, diag, perm, diagShifted, shift); + if(fMidShifted>0) + { + // fMid was erroneous, fix it: + shift = fMidShifted > Literal(0) ? left : right; + diagShifted = diag - shift; + } + } // initial guess RealScalar muPrev, muCur; @@ -785,13 +808,13 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d // rational interpolation: fit a function of the form a / mu + b through the two previous // iterates and use its zero to compute the next iterate - bool useBisection = fPrev*fCur>0; - while (fCur!=0 && abs(muCur - muPrev) > 8 * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) + bool useBisection = fPrev*fCur>Literal(0); + while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) { ++m_numIters; // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples. - RealScalar a = (fCur - fPrev) / (1/muCur - 1/muPrev); + RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev); RealScalar b = fCur - a / muCur; // And find mu such that f(mu)==0: RealScalar muZero = -a/b; @@ -803,8 +826,8 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d fCur = fZero; - if (shift == left && (muCur < 0 || muCur > right - left)) useBisection = true; - if (shift == right && (muCur < -(right - left) || muCur > 0)) useBisection = true; + if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true; + if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true; if (abs(fCur)>abs(fPrev)) useBisection = true; } @@ -817,23 +840,33 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d RealScalar leftShifted, rightShifted; if (shift == left) { - leftShifted = (std::numeric_limits::min)(); + // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)), + // the factor 2 is to be more conservative + leftShifted = numext::maxi( (std::numeric_limits::min)(), Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits::max)()) ); + + // check that we did it right: + eigen_internal_assert( (numext::isfinite)( (col0(k)/leftShifted)*(col0(k)/(diag(k)+shift+leftShifted)) ) ); // I don't understand why the case k==0 would be special there: - // if (k == 0) rightShifted = right - left; else - rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.6)); // theoretically we can take 0.5, but let's be safe + // if (k == 0) rightShifted = right - left; else + rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe } else { - leftShifted = -(right - left) * RealScalar(0.6); - rightShifted = -(std::numeric_limits::min)(); + leftShifted = -(right - left) * RealScalar(0.51); + if(k+1( (std::numeric_limits::min)(), abs(col0(k+1)) / sqrt((std::numeric_limits::max)()) ); + else + rightShifted = -(std::numeric_limits::min)(); } RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift); + eigen_internal_assert(fLeft::computeSingVals(const ArrayRef& col0, const ArrayRef& d std::cout << k << " : " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; " << left << " - " << right << " -> " << leftShifted << " " << rightShifted << " shift=" << shift << "\n"; } #endif - eigen_internal_assert(fLeft * fRight < 0); - - while (rightShifted - leftShifted > 2 * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) - { - RealScalar midShifted = (leftShifted + rightShifted) / 2; - fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift); - if (fLeft * fMid < 0) - { - rightShifted = midShifted; - } - else - { - leftShifted = midShifted; - fLeft = fMid; - } - } + eigen_internal_assert(fLeft * fRight < Literal(0)); - muCur = (leftShifted + rightShifted) / 2; + if(fLeft Literal(2) * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) + { + RealScalar midShifted = (leftShifted + rightShifted) / Literal(2); + fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift); + eigen_internal_assert((numext::isfinite)(fMid)); + + if (fLeft * fMid < Literal(0)) + { + rightShifted = midShifted; + } + else + { + leftShifted = midShifted; + fLeft = fMid; + } + } + muCur = (leftShifted + rightShifted) / Literal(2); + } + else + { + // We have a problem as shifting on the left or right give either a positive or negative value + // at the middle of [left,right]... + // Instead fo abbording or entering an infinite loop, + // let's just use the middle as the estimated zero-crossing: + muCur = (right - left) * RealScalar(0.5); + if(shift == right) + muCur = -muCur; + } } singVals[k] = shift + muCur; @@ -892,8 +939,8 @@ void BDCSVD::perturbCol0 // The offset permits to skip deflated entries while computing zhat for (Index k = 0; k < n; ++k) { - if (col0(k) == 0) // deflated - zhat(k) = 0; + if (col0(k) == Literal(0)) // deflated + zhat(k) = Literal(0); else { // see equation (3.6) @@ -908,7 +955,7 @@ void BDCSVD::perturbCol0 Index j = i 0.9 ) + if(i!=k && numext::abs(((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) - 1) > 0.9 ) std::cout << " " << ((singVals(j)+dk)*(mus(j)+(shifts(j)-dk)))/((diag(i)+dk)*(diag(i)-dk)) << " == (" << (singVals(j)+dk) << " * " << (mus(j)+(shifts(j)-dk)) << ") / (" << (diag(i)+dk) << " * " << (diag(i)-dk) << ")\n"; #endif @@ -918,7 +965,7 @@ void BDCSVD::perturbCol0 std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n"; #endif RealScalar tmp = sqrt(prod); - zhat(k) = col0(k) > 0 ? tmp : -tmp; + zhat(k) = col0(k) > Literal(0) ? RealScalar(tmp) : RealScalar(-tmp); } } } @@ -934,7 +981,7 @@ void BDCSVD::computeSingVecs for (Index k = 0; k < n; ++k) { - if (zhat(k) == 0) + if (zhat(k) == Literal(0)) { U.col(k) = VectorType::Unit(n+1, k); if (m_compV) V.col(k) = VectorType::Unit(n, k); @@ -947,7 +994,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - U(n,k) = 0; + U(n,k) = Literal(0); U.col(k).normalize(); if (m_compV) @@ -958,7 +1005,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - V(0,k) = -1; + V(0,k) = Literal(-1); V.col(k).normalize(); } } @@ -979,15 +1026,15 @@ void BDCSVD::deflation43(Index firstCol, Index shift, Index i, Index Index start = firstCol + shift; RealScalar c = m_computed(start, start); RealScalar s = m_computed(start+i, start); - RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s)); - if (r == 0) + RealScalar r = numext::hypot(c,s); + if (r == Literal(0)) { - m_computed(start+i, start+i) = 0; + m_computed(start+i, start+i) = Literal(0); return; } m_computed(start,start) = r; - m_computed(start+i, start) = 0; - m_computed(start+i, start+i) = 0; + m_computed(start+i, start) = Literal(0); + m_computed(start+i, start+i) = Literal(0); JacobiRotation J(c/r,-s/r); if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J); @@ -1020,7 +1067,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi << m_computed(firstColm + i+1, firstColm+i+1) << " " << m_computed(firstColm + i+2, firstColm+i+2) << "\n"; #endif - if (r==0) + if (r==Literal(0)) { m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j); return; @@ -1029,7 +1076,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi s/=r; m_computed(firstColm + i, firstColm) = r; m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i); - m_computed(firstColm + j, firstColm) = 0; + m_computed(firstColm + j, firstColm) = Literal(0); JacobiRotation J(c,-s); if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J); @@ -1053,7 +1100,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index const RealScalar considerZero = (std::numeric_limits::min)(); RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff(); RealScalar epsilon_strict = numext::maxi(considerZero,NumTraits::epsilon() * maxDiag); - RealScalar epsilon_coarse = 8 * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); + RealScalar epsilon_coarse = Literal(8) * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); #ifdef EIGEN_BDCSVD_SANITY_CHECKS assert(m_naiveU.allFinite()); @@ -1081,7 +1128,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n"; #endif - col0(i) = 0; + col0(i) = Literal(0); } //condition 4.3 diff --git a/eigenlib/Eigen/src/SVD/JacobiSVD.h b/eigenlib/Eigen/src/SVD/JacobiSVD.h index e0cfb628..a36bd85e 100644 --- a/eigenlib/Eigen/src/SVD/JacobiSVD.h +++ b/eigenlib/Eigen/src/SVD/JacobiSVD.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_JACOBISVD_H #define EIGEN_JACOBISVD_H @@ -112,9 +112,11 @@ public: ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, - Options = MatrixType::Options + TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(RowMajor)) + : ColsAtCompileTime==1 ? (MatrixType::Options | RowMajor) + : MatrixType::Options }; - typedef Matrix + typedef Matrix TransposeTypeWithSameStorageOrder; void allocate(const JacobiSVD& svd) @@ -200,10 +202,12 @@ public: ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, - Options = MatrixType::Options + TrOptions = RowsAtCompileTime==1 ? (MatrixType::Options & ~(RowMajor)) + : ColsAtCompileTime==1 ? (MatrixType::Options | RowMajor) + : MatrixType::Options }; - typedef Matrix + typedef Matrix TransposeTypeWithSameStorageOrder; void allocate(const JacobiSVD& svd) diff --git a/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h b/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h index 50272154..ff0516f6 100644 --- a/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h +++ b/eigenlib/Eigen/src/SVD/JacobiSVD_LAPACKE.h @@ -61,9 +61,10 @@ JacobiSVD, ColPiv u = (LAPACKE_TYPE*)m_matrixU.data(); \ } else { ldu=1; u=&dummy; }\ MatrixType localV; \ - ldvt = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ + lapack_int vt_rows = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ if (computeV()) { \ - localV.resize(ldvt, m_cols); \ + localV.resize(vt_rows, m_cols); \ + ldvt = internal::convert_index(localV.outerStride()); \ vt = (LAPACKE_TYPE*)localV.data(); \ } else { ldvt=1; vt=&dummy; }\ Matrix superb; superb.resize(m_diagSize, 1); \ diff --git a/eigenlib/Eigen/src/SVD/SVDBase.h b/eigenlib/Eigen/src/SVD/SVDBase.h index cc90a3b7..9c6577c3 100644 --- a/eigenlib/Eigen/src/SVD/SVDBase.h +++ b/eigenlib/Eigen/src/SVD/SVDBase.h @@ -11,7 +11,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SVDBASE_H #define EIGEN_SVDBASE_H @@ -180,8 +180,10 @@ public: RealScalar threshold() const { eigen_assert(m_isInitialized || m_usePrescribedThreshold); + // this temporary is needed to workaround a MSVC issue + Index diagSize = (std::max)(1,m_diagSize); return m_usePrescribedThreshold ? m_prescribedThreshold - : (std::max)(1,m_diagSize)*NumTraits::epsilon(); + : RealScalar(diagSize)*NumTraits::epsilon(); } /** \returns true if \a U (full or thin) is asked for in this SVD decomposition */ diff --git a/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h b/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h index 0b146089..22c74c6d 100644 --- a/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h +++ b/eigenlib/Eigen/src/SVD/UpperBidiagonalization.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_BIDIAGONALIZATION_H #define EIGEN_BIDIAGONALIZATION_H @@ -159,6 +159,8 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, traits::Flags & RowMajorBit> > Y) { typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename NumTraits::Literal Literal; enum { StorageOrder = traits::Flags & RowMajorBit }; typedef InnerStride ColInnerStride; typedef InnerStride RowInnerStride; @@ -263,7 +265,7 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, SubMatType A10( A.block(bs,0, brows-bs,bs) ); SubMatType A01( A.block(0,bs, bs,bcols-bs) ); Scalar tmp = A01(bs-1,0); - A01(bs-1,0) = 1; + A01(bs-1,0) = Literal(1); A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint(); A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01; A01(bs-1,0) = tmp; diff --git a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h index 2907f652..60e7252e 100644 --- a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h +++ b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SIMPLICIAL_CHOLESKY_H #define EIGEN_SIMPLICIAL_CHOLESKY_H @@ -608,7 +608,7 @@ public: } if(Base::m_diag.size()>0) - dest = Base::m_diag.asDiagonal().inverse() * dest; + dest = Base::m_diag.real().asDiagonal().inverse() * dest; if (Base::m_matrix.nonZeros()>0) // otherwise I==I { diff --git a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h index 31e06995..7b6183d0 100644 --- a/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h +++ b/eigenlib/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h @@ -156,7 +156,7 @@ void SimplicialCholeskyBase::factorize_preordered(const CholMatrixType& /* the nonzero entry L(k,i) */ Scalar l_ki; if(DoLDLT) - l_ki = yi / m_diag[i]; + l_ki = yi / numext::real(m_diag[i]); else yi = l_ki = yi / Lx[Lp[i]]; diff --git a/eigenlib/Eigen/src/SparseCore/AmbiVector.h b/eigenlib/Eigen/src/SparseCore/AmbiVector.h index 1233e164..471c83be 100644 --- a/eigenlib/Eigen/src/SparseCore/AmbiVector.h +++ b/eigenlib/Eigen/src/SparseCore/AmbiVector.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_AMBIVECTOR_H #define EIGEN_AMBIVECTOR_H @@ -28,7 +28,7 @@ class AmbiVector typedef typename NumTraits::Real RealScalar; explicit AmbiVector(Index size) - : m_buffer(0), m_zero(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1) + : m_buffer(0), m_zero(0), m_size(0), m_end(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1) { resize(size); } @@ -94,7 +94,7 @@ class AmbiVector Index allocSize = m_allocatedElements * sizeof(ListEl); allocSize = (allocSize + sizeof(Scalar) - 1)/sizeof(Scalar); Scalar* newBuffer = new Scalar[allocSize]; - memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); + std::memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); delete[] m_buffer; m_buffer = newBuffer; } @@ -147,7 +147,8 @@ template void AmbiVector<_Scalar,_StorageIndex>::init(int mode) { m_mode = mode; - if (m_mode==IsSparse) + // This is only necessary in sparse mode, but we set these unconditionally to avoid some maybe-uninitialized warnings + // if (m_mode==IsSparse) { m_llSize = 0; m_llStart = -1; @@ -336,7 +337,7 @@ class AmbiVector<_Scalar,_StorageIndex>::Iterator { do { ++m_cachedIndex; - } while (m_cachedIndex::Iterator ListEl* EIGEN_RESTRICT llElements = reinterpret_cast(m_vector.m_buffer); do { m_currentEl = llElements[m_currentEl].next; - } while (m_currentEl>=0 && abs(llElements[m_currentEl].value)=0 && abs(llElements[m_currentEl].value)<=m_epsilon); if (m_currentEl<0) { m_cachedIndex = -1; @@ -363,9 +364,9 @@ class AmbiVector<_Scalar,_StorageIndex>::Iterator protected: const AmbiVector& m_vector; // the target vector - StorageIndex m_currentEl; // the current element in sparse/linked-list mode + StorageIndex m_currentEl; // the current element in sparse/linked-list mode RealScalar m_epsilon; // epsilon used to prune zero coefficients - StorageIndex m_cachedIndex; // current coordinate + StorageIndex m_cachedIndex; // current coordinate Scalar m_cachedValue; // current value bool m_isDense; // mode of the vector }; diff --git a/eigenlib/Eigen/src/SparseCore/CompressedStorage.h b/eigenlib/Eigen/src/SparseCore/CompressedStorage.h index d89fa0da..fbe1be96 100644 --- a/eigenlib/Eigen/src/SparseCore/CompressedStorage.h +++ b/eigenlib/Eigen/src/SparseCore/CompressedStorage.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_COMPRESSED_STORAGE_H #define EIGEN_COMPRESSED_STORAGE_H diff --git a/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h index 492eb0a2..a0ee6db2 100644 --- a/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +++ b/eigenlib/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H #define EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H @@ -17,7 +17,9 @@ namespace internal { template static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, bool sortedInsertion = false) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; // make sure to call innerSize/outerSize since we fake the storage order. Index rows = lhs.innerSize(); @@ -25,7 +27,7 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); ei_declare_aligned_stack_constructed_variable(bool, mask, rows, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, values, rows, 0); + ei_declare_aligned_stack_constructed_variable(ResScalar, values, rows, 0); ei_declare_aligned_stack_constructed_variable(Index, indices, rows, 0); std::memset(mask,0,sizeof(bool)*rows); @@ -51,12 +53,12 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r Index nnz = 0; for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); if(!mask[i]) { mask[i] = true; @@ -166,11 +168,12 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix rhsRow = rhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); - res = resRow; + typedef SparseMatrix RowMajorRhs; + typedef SparseMatrix RowMajorRes; + RowMajorRhs rhsRow = rhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); + res = resRow; } }; @@ -179,10 +182,11 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix lhsRow = lhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); + typedef SparseMatrix RowMajorLhs; + typedef SparseMatrix RowMajorRes; + RowMajorLhs lhsRow = lhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); res = resRow; } }; @@ -219,10 +223,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol = lhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); + typedef SparseMatrix ColMajorLhs; + typedef SparseMatrix ColMajorRes; + ColMajorLhs lhsCol = lhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); res = resCol; } }; @@ -232,10 +237,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol = rhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); + typedef SparseMatrix ColMajorRhs; + typedef SparseMatrix ColMajorRes; + ColMajorRhs rhsCol = rhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); res = resCol; } }; @@ -263,7 +269,8 @@ namespace internal { template static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; Index cols = rhs.outerSize(); eigen_assert(lhs.outerSize() == rhs.innerSize()); @@ -274,12 +281,12 @@ static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, { for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); res.coeffRef(i,j) += x * y; } } @@ -310,9 +317,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol(lhs); - internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); + typedef SparseMatrix ColMajorLhs; + ColMajorLhs lhsCol(lhs); + internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); } }; @@ -321,9 +328,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol(rhs); - internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); + typedef SparseMatrix ColMajorRhs; + ColMajorRhs rhsCol(rhs); + internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); } }; diff --git a/eigenlib/Eigen/src/SparseCore/MappedSparseMatrix.h b/eigenlib/Eigen/src/SparseCore/MappedSparseMatrix.h index 67718c85..c6a0f2af 100644 --- a/eigenlib/Eigen/src/SparseCore/MappedSparseMatrix.h +++ b/eigenlib/Eigen/src/SparseCore/MappedSparseMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MAPPED_SPARSEMATRIX_H #define EIGEN_MAPPED_SPARSEMATRIX_H @@ -19,7 +19,7 @@ namespace Eigen { * * \param _Scalar the scalar type, i.e. the type of the coefficients * - * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme. + * See xxxp://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme. * */ namespace internal { diff --git a/eigenlib/Eigen/src/SparseCore/SparseAssign.h b/eigenlib/Eigen/src/SparseCore/SparseAssign.h index 83776645..93fdbedf 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseAssign.h +++ b/eigenlib/Eigen/src/SparseCore/SparseAssign.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEASSIGN_H #define EIGEN_SPARSEASSIGN_H @@ -143,10 +143,7 @@ struct Assignment dst.setZero(); internal::evaluator srcEval(src); - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + resize_if_allowed(dst, src, func); internal::evaluator dstEval(dst); const Index outerEvaluationSize = (internal::evaluator::Flags&RowMajorBit) ? src.rows() : src.cols(); diff --git a/eigenlib/Eigen/src/SparseCore/SparseBlock.h b/eigenlib/Eigen/src/SparseCore/SparseBlock.h index 511e92b2..ee948927 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseBlock.h +++ b/eigenlib/Eigen/src/SparseCore/SparseBlock.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_BLOCK_H #define EIGEN_SPARSE_BLOCK_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseColEtree.h b/eigenlib/Eigen/src/SparseCore/SparseColEtree.h index ebe02d1a..caa95511 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseColEtree.h +++ b/eigenlib/Eigen/src/SparseCore/SparseColEtree.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h b/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h index e0850795..bf34f95c 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCompressedBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_COMPRESSED_BASE_H #define EIGEN_SPARSE_COMPRESSED_BASE_H @@ -279,11 +279,11 @@ struct evaluator > Flags = Derived::Flags }; - evaluator() : m_matrix(0) + evaluator() : m_matrix(0), m_zero(0) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } - explicit evaluator(const Derived &mat) : m_matrix(&mat) + explicit evaluator(const Derived &mat) : m_matrix(&mat), m_zero(0) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } @@ -296,26 +296,42 @@ struct evaluator > operator const Derived&() const { return *m_matrix; } typedef typename DenseCoeffsBase::CoeffReturnType CoeffReturnType; - Scalar coeff(Index row, Index col) const - { return m_matrix->coeff(row,col); } - + const Scalar& coeff(Index row, Index col) const + { + Index p = find(row,col); + + if(p==Dynamic) + return m_zero; + else + return m_matrix->const_cast_derived().valuePtr()[p]; + } + Scalar& coeffRef(Index row, Index col) + { + Index p = find(row,col); + eigen_assert(p!=Dynamic && "written coefficient does not exist"); + return m_matrix->const_cast_derived().valuePtr()[p]; + } + +protected: + + Index find(Index row, Index col) const { eigen_internal_assert(row>=0 && rowrows() && col>=0 && colcols()); - + const Index outer = Derived::IsRowMajor ? row : col; const Index inner = Derived::IsRowMajor ? col : row; Index start = m_matrix->outerIndexPtr()[outer]; Index end = m_matrix->isCompressed() ? m_matrix->outerIndexPtr()[outer+1] : m_matrix->outerIndexPtr()[outer] + m_matrix->innerNonZeroPtr()[outer]; - eigen_assert(end>start && "you are using a non finalized sparse matrix or written coefficient does not exist"); - const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner) - - m_matrix->innerIndexPtr(); - eigen_assert((pinnerIndexPtr()[p]==inner) && "written coefficient does not exist"); - return m_matrix->const_cast_derived().valuePtr()[p]; + eigen_assert(end>=start && "you are using a non finalized sparse matrix or written coefficient does not exist"); + const Index p = std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner) - m_matrix->innerIndexPtr(); + + return ((pinnerIndexPtr()[p]==inner)) ? p : Dynamic; } const Derived *m_matrix; + const Scalar m_zero; }; } diff --git a/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index 526c7121..10f24a3d 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H #define EIGEN_SPARSE_CWISE_BINARY_OP_H @@ -359,6 +359,16 @@ struct binary_evaluator, Lhs, Rhs>, Itera explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} }; +// "sparse ./ dense" +template +struct binary_evaluator, Lhs, Rhs>, IteratorBased, IndexBased> + : sparse_conjunction_evaluator, Lhs, Rhs> > +{ + typedef CwiseBinaryOp, Lhs, Rhs> XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; + // "sparse && sparse" template struct binary_evaluator, IteratorBased, IteratorBased> diff --git a/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h index ea797379..6dd1d872 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/eigenlib/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H #define EIGEN_SPARSE_CWISE_UNARY_OP_H @@ -49,6 +49,7 @@ template class unary_evaluator, IteratorBased>::InnerIterator : public unary_evaluator, IteratorBased>::EvalIterator { + protected: typedef typename XprType::Scalar Scalar; typedef typename unary_evaluator, IteratorBased>::EvalIterator Base; public: @@ -99,6 +100,7 @@ template class unary_evaluator, IteratorBased>::InnerIterator : public unary_evaluator, IteratorBased>::EvalIterator { + protected: typedef typename XprType::Scalar Scalar; typedef typename unary_evaluator, IteratorBased>::EvalIterator Base; public: diff --git a/eigenlib/Eigen/src/SparseCore/SparseDenseProduct.h b/eigenlib/Eigen/src/SparseCore/SparseDenseProduct.h index 0547db59..dc836bd6 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseDenseProduct.h +++ b/eigenlib/Eigen/src/SparseCore/SparseDenseProduct.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEDENSEPRODUCT_H #define EIGEN_SPARSEDENSEPRODUCT_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h b/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h index e4af49e0..192beba5 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h +++ b/eigenlib/Eigen/src/SparseCore/SparseDiagonalProduct.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H #define EIGEN_SPARSE_DIAGONAL_PRODUCT_H @@ -80,6 +80,8 @@ public: sparse_diagonal_product_evaluator(const SparseXprType &sparseXpr, const DiagonalCoeffType &diagCoeff) : m_sparseXprImpl(sparseXpr), m_diagCoeffImpl(diagCoeff) {} + + Index nonZerosEstimate() const { return m_sparseXprImpl.nonZerosEstimate(); } protected: evaluator m_sparseXprImpl; @@ -121,6 +123,8 @@ struct sparse_diagonal_product_evaluator m_sparseXprEval; diff --git a/eigenlib/Eigen/src/SparseCore/SparseDot.h b/eigenlib/Eigen/src/SparseCore/SparseDot.h index 38bc4aa9..72c05593 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseDot.h +++ b/eigenlib/Eigen/src/SparseCore/SparseDot.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_DOT_H #define EIGEN_SPARSE_DOT_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseFuzzy.h b/eigenlib/Eigen/src/SparseCore/SparseFuzzy.h index 7d47eb94..0d0c3eb7 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseFuzzy.h +++ b/eigenlib/Eigen/src/SparseCore/SparseFuzzy.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_FUZZY_H #define EIGEN_SPARSE_FUZZY_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseMap.h b/eigenlib/Eigen/src/SparseCore/SparseMap.h index f99be337..e199e262 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseMap.h +++ b/eigenlib/Eigen/src/SparseCore/SparseMap.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_MAP_H #define EIGEN_SPARSE_MAP_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseMatrix.h b/eigenlib/Eigen/src/SparseCore/SparseMatrix.h index 529c7a0a..0f590cc1 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseMatrix.h +++ b/eigenlib/Eigen/src/SparseCore/SparseMatrix.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEMATRIX_H #define EIGEN_SPARSEMATRIX_H @@ -327,7 +327,8 @@ class SparseMatrix m_outerIndex[j] = newOuterIndex[j]; m_innerNonZeros[j] = innerNNZ; } - m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1]; + if(m_outerSize>0) + m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1]; m_data.resize(m_outerIndex[m_outerSize]); } @@ -893,7 +894,7 @@ public: Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++; m_data.index(p) = convert_index(inner); - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } private: @@ -1274,7 +1275,7 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& m_innerNonZeros[outer]++; m_data.index(p) = inner; - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } template @@ -1301,11 +1302,11 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g., // the 2nd inner vector... bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) - && (size_t(m_outerIndex[outer+1]) == m_data.size()); + && (std::size_t(m_outerIndex[outer+1]) == m_data.size()); - size_t startId = m_outerIndex[outer]; - // FIXME let's make sure sizeof(long int) == sizeof(size_t) - size_t p = m_outerIndex[outer+1]; + std::size_t startId = m_outerIndex[outer]; + // FIXME let's make sure sizeof(long int) == sizeof(std::size_t) + std::size_t p = m_outerIndex[outer+1]; ++m_outerIndex[outer+1]; double reallocRatio = 1; @@ -1381,7 +1382,7 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_StorageIndex>::Scalar& } m_data.index(p) = inner; - return (m_data.value(p) = 0); + return (m_data.value(p) = Scalar(0)); } namespace internal { diff --git a/eigenlib/Eigen/src/SparseCore/SparseMatrixBase.h b/eigenlib/Eigen/src/SparseCore/SparseMatrixBase.h index c6b548f1..021cedc0 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseMatrixBase.h +++ b/eigenlib/Eigen/src/SparseCore/SparseMatrixBase.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEMATRIXBASE_H #define EIGEN_SPARSEMATRIXBASE_H diff --git a/eigenlib/Eigen/src/SparseCore/SparsePermutation.h b/eigenlib/Eigen/src/SparseCore/SparsePermutation.h index ef38357a..41df5bed 100644 --- a/eigenlib/Eigen/src/SparseCore/SparsePermutation.h +++ b/eigenlib/Eigen/src/SparseCore/SparsePermutation.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_PERMUTATION_H #define EIGEN_SPARSE_PERMUTATION_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseProduct.h b/eigenlib/Eigen/src/SparseCore/SparseProduct.h index 4cbf6878..73e042c9 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseProduct.h +++ b/eigenlib/Eigen/src/SparseCore/SparseProduct.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEPRODUCT_H #define EIGEN_SPARSEPRODUCT_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseRedux.h b/eigenlib/Eigen/src/SparseCore/SparseRedux.h index 45877496..6ea90b57 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseRedux.h +++ b/eigenlib/Eigen/src/SparseCore/SparseRedux.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEREDUX_H #define EIGEN_SPARSEREDUX_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseRef.h b/eigenlib/Eigen/src/SparseCore/SparseRef.h index d91f38f9..58388bfc 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseRef.h +++ b/eigenlib/Eigen/src/SparseCore/SparseRef.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_REF_H #define EIGEN_SPARSE_REF_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h b/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h index 9e39be73..70ed2f0b 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/eigenlib/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H #define EIGEN_SPARSE_SELFADJOINTVIEW_H @@ -47,6 +47,7 @@ template class SparseSelfAdjointView enum { Mode = _Mode, + TransposeMode = ((Mode & Upper) ? Lower : 0) | ((Mode & Lower) ? Upper : 0), RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime }; @@ -310,7 +311,7 @@ inline void sparse_selfadjoint_time_dense_product(const SparseLhsType& lhs, cons while (i && i.index() dstT(dst); - internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); + internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); } }; @@ -452,7 +453,7 @@ void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix::type::Scalar Scalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; typedef typename remove_all::type::StorageIndex StorageIndex; // make sure to call innerSize/outerSize since we fake the storage order. @@ -31,7 +32,7 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); // allocate a temporary buffer - AmbiVector tempVector(rows); + AmbiVector tempVector(rows); // mimics a resizeByInnerOuter: if(ResultType::IsRowMajor) @@ -63,14 +64,14 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r { // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index()) tempVector.restart(); - Scalar x = rhsIt.value(); + RhsScalar x = rhsIt.value(); for (typename evaluator::InnerIterator lhsIt(lhsEval, rhsIt.index()); lhsIt; ++lhsIt) { tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x; } } res.startVec(j); - for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) + for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) res.insertBackByOuterInner(j,it.index()) = it.value(); } res.finalize(); @@ -85,7 +86,6 @@ struct sparse_sparse_product_with_pruning_selector; template struct sparse_sparse_product_with_pruning_selector { - typedef typename traits::type>::Scalar Scalar; typedef typename ResultType::RealScalar RealScalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance) @@ -129,8 +129,8 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; - typedef SparseMatrix ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixLhs colLhs(lhs); ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, colRhs, res, tolerance); @@ -149,7 +149,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixLhs; + typedef SparseMatrix RowMajorMatrixLhs; RowMajorMatrixLhs rowLhs(lhs); sparse_sparse_product_with_pruning_selector(rowLhs,rhs,res,tolerance); } @@ -161,7 +161,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixRhs; + typedef SparseMatrix RowMajorMatrixRhs; RowMajorMatrixRhs rowRhs(rhs); sparse_sparse_product_with_pruning_selector(lhs,rowRhs,res,tolerance); } @@ -173,7 +173,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(lhs, colRhs, res, tolerance); } @@ -185,7 +185,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixLhs; ColMajorMatrixLhs colLhs(lhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, rhs, res, tolerance); } diff --git a/eigenlib/Eigen/src/SparseCore/SparseTranspose.h b/eigenlib/Eigen/src/SparseCore/SparseTranspose.h index 3757d4c6..3a3169a6 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseTranspose.h +++ b/eigenlib/Eigen/src/SparseCore/SparseTranspose.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSETRANSPOSE_H #define EIGEN_SPARSETRANSPOSE_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseTriangularView.h b/eigenlib/Eigen/src/SparseCore/SparseTriangularView.h index 9ac12026..84145809 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseTriangularView.h +++ b/eigenlib/Eigen/src/SparseCore/SparseTriangularView.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_TRIANGULARVIEW_H #define EIGEN_SPARSE_TRIANGULARVIEW_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseUtil.h b/eigenlib/Eigen/src/SparseCore/SparseUtil.h index 74df0d49..6daddd8f 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseUtil.h +++ b/eigenlib/Eigen/src/SparseCore/SparseUtil.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEUTIL_H #define EIGEN_SPARSEUTIL_H diff --git a/eigenlib/Eigen/src/SparseCore/SparseVector.h b/eigenlib/Eigen/src/SparseCore/SparseVector.h index 19b0fbc9..35c70092 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseVector.h +++ b/eigenlib/Eigen/src/SparseCore/SparseVector.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEVECTOR_H #define EIGEN_SPARSEVECTOR_H @@ -19,7 +19,7 @@ namespace Eigen { * * \tparam _Scalar the scalar type, i.e. the type of the coefficients * - * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme. + * See xxxp://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme. * * This class can be extended with the help of the plugin mechanism described on the page * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_SPARSEVECTOR_PLUGIN. diff --git a/eigenlib/Eigen/src/SparseCore/SparseView.h b/eigenlib/Eigen/src/SparseCore/SparseView.h index 7c4aea74..72cad92a 100644 --- a/eigenlib/Eigen/src/SparseCore/SparseView.h +++ b/eigenlib/Eigen/src/SparseCore/SparseView.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSEVIEW_H #define EIGEN_SPARSEVIEW_H @@ -90,6 +90,7 @@ struct unary_evaluator, IteratorBased> class InnerIterator : public EvalIterator { + protected: typedef typename XprType::Scalar Scalar; public: diff --git a/eigenlib/Eigen/src/SparseCore/TriangularSolver.h b/eigenlib/Eigen/src/SparseCore/TriangularSolver.h index f9c56ba7..5e5c20c7 100644 --- a/eigenlib/Eigen/src/SparseCore/TriangularSolver.h +++ b/eigenlib/Eigen/src/SparseCore/TriangularSolver.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSETRIANGULARSOLVER_H #define EIGEN_SPARSETRIANGULARSOLVER_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU.h b/eigenlib/Eigen/src/SparseLU/SparseLU.h index f883ab38..7b921fbd 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_LU_H @@ -25,7 +25,7 @@ template struct SparseLUMatrixURetu * * This class implements the supernodal LU factorization for general matrices. * It uses the main techniques from the sequential SuperLU package - * (http://crd-legacy.lbl.gov/~xiaoye/SuperLU/). It handles transparently real + * (xxxp://crd-legacy.lbl.gov/~xiaoye/SuperLU/). It handles transparently real * and complex arithmetics with single and double precision, depending on the * scalar type of your input matrix. * The code has been optimized to provide BLAS-3 operations during supernode-panel updates. @@ -43,8 +43,8 @@ template struct SparseLUMatrixURetu * Simple example with key steps * \code * VectorXd x(n), b(n); - * SparseMatrix A; - * SparseLU, COLAMDOrdering > solver; + * SparseMatrix A; + * SparseLU, COLAMDOrdering > solver; * // fill A and b; * // Compute the ordering permutation vector from the structural pattern of A * solver.analyzePattern(A); @@ -499,8 +499,6 @@ void SparseLU::factorize(const MatrixType& matrix) eigen_assert(m_analysisIsOk && "analyzePattern() should be called first"); eigen_assert((matrix.rows() == matrix.cols()) && "Only for squared matrices"); - typedef typename IndexVector::Scalar StorageIndex; - m_isInitialized = true; diff --git a/eigenlib/Eigen/src/SparseLU/SparseLUImpl.h b/eigenlib/Eigen/src/SparseLU/SparseLUImpl.h index fc0cfc4d..60360ee5 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLUImpl.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLUImpl.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef SPARSELU_IMPL_H #define SPARSELU_IMPL_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_Memory.h b/eigenlib/Eigen/src/SparseLU/SparseLU_Memory.h index 4dc42e87..b96d76f4 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_Memory.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_Memory.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_Structs.h b/eigenlib/Eigen/src/SparseLU/SparseLU_Structs.h index cf5ec449..11701629 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_Structs.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_Structs.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* * NOTE: This file comes from a partly modified version of files slu_[s,d,c,z]defs.h diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h b/eigenlib/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h index 721e1883..c3340fb4 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSELU_SUPERNODAL_MATRIX_H #define EIGEN_SPARSELU_SUPERNODAL_MATRIX_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_Utils.h b/eigenlib/Eigen/src/SparseLU/SparseLU_Utils.h index 9e3dab44..f06c903c 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_Utils.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_Utils.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSELU_UTILS_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_column_bmod.h b/eigenlib/Eigen/src/SparseLU/SparseLU_column_bmod.h index b57f0680..57f05ca5 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_column_bmod.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_column_bmod.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_column_dfs.h b/eigenlib/Eigen/src/SparseLU/SparseLU_column_dfs.h index c98b30e3..4f672baa 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_column_dfs.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_column_dfs.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h b/eigenlib/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h index c32d8d8b..fa54bd4a 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* * NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_gemm_kernel.h b/eigenlib/Eigen/src/SparseLU/SparseLU_gemm_kernel.h index 95ba7413..a521692f 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_gemm_kernel.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_gemm_kernel.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSELU_GEMM_KERNEL_H #define EIGEN_SPARSELU_GEMM_KERNEL_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h b/eigenlib/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h index 6f75d500..3c0fe279 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* This file is a modified version of heap_relax_snode.c file in SuperLU * -- SuperLU routine (version 3.0) -- diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_kernel_bmod.h b/eigenlib/Eigen/src/SparseLU/SparseLU_kernel_bmod.h index 8c1b3e8b..c7420989 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_kernel_bmod.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_kernel_bmod.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef SPARSELU_KERNEL_BMOD_H #define SPARSELU_KERNEL_BMOD_H diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_panel_bmod.h b/eigenlib/Eigen/src/SparseLU/SparseLU_panel_bmod.h index 822cf32c..934b5bb0 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_panel_bmod.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_panel_bmod.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_panel_dfs.h b/eigenlib/Eigen/src/SparseLU/SparseLU_panel_dfs.h index 155df733..bcb2aea6 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_panel_dfs.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_panel_dfs.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_pivotL.h b/eigenlib/Eigen/src/SparseLU/SparseLU_pivotL.h index a86dac93..08d5dbe7 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_pivotL.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_pivotL.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_pruneL.h b/eigenlib/Eigen/src/SparseLU/SparseLU_pruneL.h index ad32fed5..6506e3e4 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_pruneL.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_pruneL.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* diff --git a/eigenlib/Eigen/src/SparseLU/SparseLU_relax_snode.h b/eigenlib/Eigen/src/SparseLU/SparseLU_relax_snode.h index c408d01b..a5ca46bd 100644 --- a/eigenlib/Eigen/src/SparseLU/SparseLU_relax_snode.h +++ b/eigenlib/Eigen/src/SparseLU/SparseLU_relax_snode.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page /* This file is a modified version of heap_relax_snode.c file in SuperLU * -- SuperLU routine (version 3.0) -- diff --git a/eigenlib/Eigen/src/SparseQR/SparseQR.h b/eigenlib/Eigen/src/SparseQR/SparseQR.h index 2d4498b0..fce3ee5c 100644 --- a/eigenlib/Eigen/src/SparseQR/SparseQR.h +++ b/eigenlib/Eigen/src/SparseQR/SparseQR.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SPARSE_QR_H #define EIGEN_SPARSE_QR_H @@ -52,7 +52,7 @@ namespace internal { * rank-revealing permutations. Use colsPermutation() to get it. * * Q is the orthogonal matrix represented as products of Householder reflectors. - * Use matrixQ() to get an expression and matrixQ().transpose() to get the transpose. + * Use matrixQ() to get an expression and matrixQ().adjoint() to get the adjoint. * You can then apply it to a vector. * * R is the sparse triangular or trapezoidal matrix. The later occurs when A is rank-deficient. @@ -65,6 +65,7 @@ namespace internal { * \implsparsesolverconcept * * \warning The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()). + * \warning For complex matrices matrixQ().transpose() will actually return the adjoint matrix. * */ template @@ -196,9 +197,9 @@ class SparseQR : public SparseSolverBase > Index rank = this->rank(); - // Compute Q^T * b; + // Compute Q^* * b; typename Dest::PlainObject y, b; - y = this->matrixQ().transpose() * B; + y = this->matrixQ().adjoint() * B; b = y; // Solve with the triangular matrix R @@ -604,7 +605,7 @@ struct SparseQR_QProduct : ReturnByValue @@ -668,13 +672,14 @@ struct SparseQRMatrixQReturnType : public EigenBase(m_qr,other.derived(),false); } + // To use for operations with the adjoint of Q SparseQRMatrixQTransposeReturnType adjoint() const { return SparseQRMatrixQTransposeReturnType(m_qr); } inline Index rows() const { return m_qr.rows(); } - inline Index cols() const { return (std::min)(m_qr.rows(),m_qr.cols()); } - // To use for operations with the transpose of Q + inline Index cols() const { return m_qr.rows(); } + // To use for operations with the transpose of Q FIXME this is the same as adjoint at the moment SparseQRMatrixQTransposeReturnType transpose() const { return SparseQRMatrixQTransposeReturnType(m_qr); @@ -682,6 +687,7 @@ struct SparseQRMatrixQReturnType : public EigenBase struct SparseQRMatrixQTransposeReturnType { @@ -712,7 +718,7 @@ struct Assignment, internal: typedef typename DstXprType::StorageIndex StorageIndex; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { - typename DstXprType::PlainObject idMat(src.m_qr.rows(), src.m_qr.rows()); + typename DstXprType::PlainObject idMat(src.rows(), src.cols()); idMat.setIdentity(); // Sort the sparse householder reflectors if needed const_cast(&src.m_qr)->_sort_matrix_Q(); diff --git a/eigenlib/Eigen/src/StlSupport/StdDeque.h b/eigenlib/Eigen/src/StlSupport/StdDeque.h index cf1fedf9..563d0464 100644 --- a/eigenlib/Eigen/src/StlSupport/StdDeque.h +++ b/eigenlib/Eigen/src/StlSupport/StdDeque.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDDEQUE_H #define EIGEN_STDDEQUE_H @@ -98,8 +98,10 @@ namespace std { { return deque_base::insert(position,x); } void insert(const_iterator position, size_type new_size, const value_type& x) { deque_base::insert(position, new_size, x); } -#elif defined(_GLIBCXX_DEQUE) && EIGEN_GNUC_AT_LEAST(4,2) +#elif defined(_GLIBCXX_DEQUE) && EIGEN_GNUC_AT_LEAST(4,2) && !EIGEN_GNUC_AT_LEAST(10, 1) // workaround GCC std::deque implementation + // GCC 10.1 doesn't let us access _Deque_impl _M_impl anymore and we have to + // fall-back to the default case void resize(size_type new_size, const value_type& x) { if (new_size < deque_base::size()) @@ -108,7 +110,7 @@ namespace std { deque_base::insert(deque_base::end(), new_size - deque_base::size(), x); } #else - // either GCC 4.1 or non-GCC + // either non-GCC or GCC between 4.1 and 10.1 // default implementation which should always work. void resize(size_type new_size, const value_type& x) { diff --git a/eigenlib/Eigen/src/StlSupport/StdList.h b/eigenlib/Eigen/src/StlSupport/StdList.h index e1eba498..3fbc53f4 100644 --- a/eigenlib/Eigen/src/StlSupport/StdList.h +++ b/eigenlib/Eigen/src/StlSupport/StdList.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDLIST_H #define EIGEN_STDLIST_H diff --git a/eigenlib/Eigen/src/StlSupport/StdVector.h b/eigenlib/Eigen/src/StlSupport/StdVector.h index ec22821d..da36f8e0 100644 --- a/eigenlib/Eigen/src/StlSupport/StdVector.h +++ b/eigenlib/Eigen/src/StlSupport/StdVector.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STDVECTOR_H #define EIGEN_STDVECTOR_H diff --git a/eigenlib/Eigen/src/StlSupport/details.h b/eigenlib/Eigen/src/StlSupport/details.h index e42ec024..d60c28b8 100644 --- a/eigenlib/Eigen/src/StlSupport/details.h +++ b/eigenlib/Eigen/src/StlSupport/details.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_STL_DETAILS_H #define EIGEN_STL_DETAILS_H @@ -22,13 +22,13 @@ namespace Eigen { class aligned_allocator_indirection : public EIGEN_ALIGNED_ALLOCATOR { public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; template struct rebind diff --git a/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h b/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h index 50a69f30..38739c67 100644 --- a/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h +++ b/eigenlib/Eigen/src/SuperLUSupport/SuperLUSupport.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_SUPERLUSUPPORT_H #define EIGEN_SUPERLUSUPPORT_H @@ -297,8 +297,8 @@ SluMatrix asSluMatrix(MatrixType& mat) template MappedSparseMatrix map_superlu(SluMatrix& sluMat) { - eigen_assert((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR - || (Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC); + eigen_assert(((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR) + || ((Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC)); Index outerSize = (Flags&RowMajor)==RowMajor ? sluMat.ncol : sluMat.nrow; diff --git a/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h b/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h index dc74de93..25ace727 100644 --- a/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h +++ b/eigenlib/Eigen/src/UmfPackSupport/UmfPackSupport.h @@ -5,24 +5,42 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_UMFPACKSUPPORT_H #define EIGEN_UMFPACKSUPPORT_H -namespace Eigen { +namespace Eigen { /* TODO extract L, extract U, compute det, etc... */ // generic double/complex wrapper functions: -inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) { umfpack_di_defaults(control); } -inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) { umfpack_zi_defaults(control); } +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], double) +{ umfpack_di_report_info(control, info);} + +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], std::complex) +{ umfpack_zi_report_info(control, info);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, double) +{ umfpack_di_report_status(control, status);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, std::complex) +{ umfpack_zi_report_status(control, status);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], double) +{ umfpack_di_report_control(control);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], std::complex) +{ umfpack_zi_report_control(control);} + inline void umfpack_free_numeric(void **Numeric, double) { umfpack_di_free_numeric(Numeric); *Numeric = 0; } @@ -156,6 +174,7 @@ class UmfPackLU : public SparseSolverBase > public: typedef Array UmfpackControl; + typedef Array UmfpackInfo; UmfPackLU() : m_dummy(0,0), mp_matrix(m_dummy) @@ -215,7 +234,7 @@ class UmfPackLU : public SparseSolverBase > return m_q; } - /** Computes the sparse Cholesky decomposition of \a matrix + /** Computes the sparse Cholesky decomposition of \a matrix * Note that the matrix should be column-major, and in compressed format for best performance. * \sa SparseMatrix::makeCompressed(). */ @@ -240,7 +259,7 @@ class UmfPackLU : public SparseSolverBase > { if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar()); if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar()); - + grab(matrix.derived()); analyzePattern_impl(); @@ -267,7 +286,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Provides access to the control settings array used by UmfPack. * * If this array contains NaN's, the default values are used. @@ -278,7 +297,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Performs a numeric decomposition of \a matrix * * The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed. @@ -293,10 +312,38 @@ class UmfPackLU : public SparseSolverBase > umfpack_free_numeric(&m_numeric,Scalar()); grab(matrix.derived()); - + factorize_impl(); } + /** Prints the current UmfPack control settings. + * + * \sa umfpackControl() + */ + void umfpackReportControl() + { + umfpack_report_control(m_control.data(), Scalar()); + } + + /** Prints statistics collected by UmfPack. + * + * \sa analyzePattern(), compute() + */ + void umfpackReportInfo() + { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_info(m_control.data(), m_umfpackInfo.data(), Scalar()); + } + + /** Prints the status of the previous factorization operation performed by UmfPack (symbolic or numerical factorization). + * + * \sa analyzePattern(), compute() + */ + void umfpackReportStatus() { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_status(m_control.data(), m_fact_errorCode, Scalar()); + } + /** \internal */ template bool _solve_impl(const MatrixBase &b, MatrixBase &x) const; @@ -314,41 +361,42 @@ class UmfPackLU : public SparseSolverBase > m_numeric = 0; m_symbolic = 0; m_extractedDataAreDirty = true; + + umfpack_defaults(m_control.data(), Scalar()); } - + void analyzePattern_impl() { - umfpack_defaults(m_control.data(), Scalar()); - int errorCode = 0; - errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), - internal::convert_index(mp_matrix.cols()), - mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - &m_symbolic, m_control.data(), 0); + m_fact_errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), + internal::convert_index(mp_matrix.cols()), + mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), + &m_symbolic, m_control.data(), m_umfpackInfo.data()); m_isInitialized = true; - m_info = errorCode ? InvalidInput : Success; + m_info = m_fact_errorCode ? InvalidInput : Success; m_analysisIsOk = true; m_factorizationIsOk = false; m_extractedDataAreDirty = true; } - + void factorize_impl() { + m_fact_errorCode = umfpack_numeric(mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - m_symbolic, &m_numeric, m_control.data(), 0); + m_symbolic, &m_numeric, m_control.data(), m_umfpackInfo.data()); m_info = m_fact_errorCode == UMFPACK_OK ? Success : NumericalIssue; m_factorizationIsOk = true; m_extractedDataAreDirty = true; } - + template void grab(const EigenBase &A) { mp_matrix.~UmfpackMatrixRef(); ::new (&mp_matrix) UmfpackMatrixRef(A.derived()); } - + void grab(const UmfpackMatrixRef &A) { if(&(A.derived()) != &mp_matrix) @@ -357,19 +405,20 @@ class UmfPackLU : public SparseSolverBase > ::new (&mp_matrix) UmfpackMatrixRef(A); } } - + // cached data to reduce reallocation, etc. mutable LUMatrixType m_l; int m_fact_errorCode; UmfpackControl m_control; - + mutable UmfpackInfo m_umfpackInfo; + mutable LUMatrixType m_u; mutable IntColVectorType m_p; mutable IntRowVectorType m_q; UmfpackMatrixType m_dummy; UmfpackMatrixRef mp_matrix; - + void* m_numeric; void* m_symbolic; @@ -377,7 +426,7 @@ class UmfPackLU : public SparseSolverBase > int m_factorizationIsOk; int m_analysisIsOk; mutable bool m_extractedDataAreDirty; - + private: UmfPackLU(const UmfPackLU& ) { } }; @@ -427,7 +476,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas eigen_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major rhs yet"); eigen_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major result yet"); eigen_assert(b.derived().data() != x.derived().data() && " Umfpack does not support inplace solve"); - + int errorCode; Scalar* x_ptr = 0; Matrix x_tmp; @@ -442,7 +491,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas x_ptr = &x.col(j).coeffRef(0); errorCode = umfpack_solve(UMFPACK_A, mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), 0); + x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), m_umfpackInfo.data()); if(x.innerStride()!=1) x.col(j) = x_tmp; if (errorCode!=0) diff --git a/eigenlib/Eigen/src/misc/Image.h b/eigenlib/Eigen/src/misc/Image.h index b8b8a045..4d880a52 100644 --- a/eigenlib/Eigen/src/misc/Image.h +++ b/eigenlib/Eigen/src/misc/Image.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MISC_IMAGE_H #define EIGEN_MISC_IMAGE_H diff --git a/eigenlib/Eigen/src/misc/Kernel.h b/eigenlib/Eigen/src/misc/Kernel.h index bef5d6ff..054afc67 100644 --- a/eigenlib/Eigen/src/misc/Kernel.h +++ b/eigenlib/Eigen/src/misc/Kernel.h @@ -5,7 +5,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_MISC_KERNEL_H #define EIGEN_MISC_KERNEL_H diff --git a/eigenlib/Eigen/src/misc/RealSvd2x2.h b/eigenlib/Eigen/src/misc/RealSvd2x2.h index abb4d3c2..843fe479 100644 --- a/eigenlib/Eigen/src/misc/RealSvd2x2.h +++ b/eigenlib/Eigen/src/misc/RealSvd2x2.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_REALSVD2X2_H #define EIGEN_REALSVD2X2_H diff --git a/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h index 1f8a531a..05a7449b 100644 --- a/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h +++ b/eigenlib/Eigen/src/plugins/ArrayCwiseBinaryOps.h @@ -119,7 +119,7 @@ OP(const Scalar& s) const { \ return this->OP(Derived::PlainObject::Constant(rows(), cols(), s)); \ } \ EIGEN_DEVICE_FUNC friend EIGEN_STRONG_INLINE const RCmp ## COMPARATOR ## ReturnType \ -OP(const Scalar& s, const Derived& d) { \ +OP(const Scalar& s, const EIGEN_CURRENT_STORAGE_BASE_CLASS& d) { \ return Derived::PlainObject::Constant(d.rows(), d.cols(), s).OP(d); \ } diff --git a/eigenlib/Eigen/src/plugins/BlockMethods.h b/eigenlib/Eigen/src/plugins/BlockMethods.h index ac35a008..39055dc0 100644 --- a/eigenlib/Eigen/src/plugins/BlockMethods.h +++ b/eigenlib/Eigen/src/plugins/BlockMethods.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page #ifndef EIGEN_PARSED_BY_DOXYGEN diff --git a/eigenlib/Eigen/src/plugins/CommonCwiseBinaryOps.h b/eigenlib/Eigen/src/plugins/CommonCwiseBinaryOps.h index 8b6730ed..11084ec5 100644 --- a/eigenlib/Eigen/src/plugins/CommonCwiseBinaryOps.h +++ b/eigenlib/Eigen/src/plugins/CommonCwiseBinaryOps.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // This file is a base class plugin containing common coefficient wise functions. diff --git a/eigenlib/Eigen/src/plugins/CommonCwiseUnaryOps.h b/eigenlib/Eigen/src/plugins/CommonCwiseUnaryOps.h index 89f4faaa..a71c4bcf 100644 --- a/eigenlib/Eigen/src/plugins/CommonCwiseUnaryOps.h +++ b/eigenlib/Eigen/src/plugins/CommonCwiseUnaryOps.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // This file is a base class plugin containing common coefficient wise functions. diff --git a/eigenlib/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/eigenlib/Eigen/src/plugins/MatrixCwiseBinaryOps.h index f1084abe..f937d43d 100644 --- a/eigenlib/Eigen/src/plugins/MatrixCwiseBinaryOps.h +++ b/eigenlib/Eigen/src/plugins/MatrixCwiseBinaryOps.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // This file is a base class plugin containing matrix specifics coefficient wise functions. diff --git a/eigenlib/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/eigenlib/Eigen/src/plugins/MatrixCwiseUnaryOps.h index b1be3d56..fa75838d 100644 --- a/eigenlib/Eigen/src/plugins/MatrixCwiseUnaryOps.h +++ b/eigenlib/Eigen/src/plugins/MatrixCwiseUnaryOps.h @@ -6,7 +6,7 @@ // // 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/. +// with this file, You can obtain one at the mozilla.org home page // This file is included into the body of the base classes supporting matrix specific coefficient-wise functions. // This include MatrixBase and SparseMatrixBase. diff --git a/eigenlib/howto.txt b/eigenlib/howto.txt index 5f893409..d88199d5 100644 --- a/eigenlib/howto.txt +++ b/eigenlib/howto.txt @@ -3,11 +3,17 @@ Current Eigen Version 3.2.1 (26.02.2014) updated on 14/05/2014 Current Eigen Version 3.2.2 (04.08.2014) updated on 21/10/2014 Current Eigen Version 3.2.5 (16.06.2015) updated on 24/09/2015 Current Eigen Version 3.3.2 (18.01.2017) updated on 24/01/2017 +Current Eigen Version 3.3.9 (04.12.2020) updated on 15/06/2021 To update the lib: - download Eigen - unzip it somewhere -- delete (in the filesystem) the content of the folder eigenlib/Eigen - copy the folders 'Eigen' there +- delete (in the filesystem) the content of the folder eigenlib/Eigen - copy the folders 'Eigen' there +- execute the two following shell commands in the folder Eigen + + grep -RiIl 'http://mozilla.org/MPL/2.0/.' * | xargs sed -i 's/http:\/\/mozilla.org\/MPL\/2.0\/./the mozilla.org home page/g' + grep -RiIl 'http' * | xargs sed -i 's/http/xxxp/g' + - check the git status. - update this file - commit everything diff --git a/vcg/complex/algorithms/align_global.h b/vcg/complex/algorithms/align_global.h new file mode 100644 index 00000000..c695a623 --- /dev/null +++ b/vcg/complex/algorithms/align_global.h @@ -0,0 +1,700 @@ +#include +#include + +#include + +#ifndef MESHLAB_ALIGNGLOBAL_H +#define MESHLAB_ALIGNGLOBAL_H + +namespace vcg { + class AlignGlobal { + public: + + /** + * Forward declaration for the `VirtAlign` class. + */ + class Node; + + /** + * Allineamento virtuale tra due mesh (estratto da un alignresult). + * Nota Importante: la trasformazione e i punti qui memorizzati si intendono al netto delle trasf di base delle due mesh in gioco. + * Quindi se qualcuno sposta una mesh le pos dei punti sono ancora valide ma non la trasf da applicarvi. + */ + class VirtAlign + { + public: + + AlignGlobal::Node *Fix, *Mov; // allineamento tra i e j + std::vector FixP; // punti su Fix + std::vector MovP; // punti su Mov + std::vector FixN; // Normali su Fix + std::vector MovN; // Normali su Mov + vcg::Matrix44d M2F; //la matrice da applicare ai punti di Mov per ottenere quelli su Fix + vcg::Matrix44d F2M; //la matrice da applicare ai punti di Fix per ottenere quelli su Mov + /* + Nel caso semplificato che le mesh avessero come trasf di base l'identita' deve valere: + + N2A(N).Apply( P(N)) ~= AdjP(N) + A2N(N).Apply(AdjP(N)) ~= P(N) + + In generale un nodo N qualsiasi dell'VirtAlign vale che: + + N2A(N).Apply( N->M.Apply( P(N)) ) ~= AdjN(N)->M.Apply( AdjP(N) ); + A2M(N).Apply( AdjN(N)->M.Apply(AdjP(N)) ) ~= N->M.Apply( P(N) ); + + in cui il ~= significa uguale al netto dell'errore di allineamento. + + Per ottenere i virtualmate relativi ad un nodo n: + */ + + inline vcg::Matrix44d &N2A(AlignGlobal::Node *n) {if(n==Fix) return F2M; else return M2F;} + inline vcg::Matrix44d &A2N(AlignGlobal::Node *n) {if(n==Fix) return M2F; else return F2M;} + + inline std::vector &P(AlignGlobal::Node *n) {if(n==Fix) return FixP; else return MovP;} + inline std::vector &N(AlignGlobal::Node *n) {if(n==Fix) return FixN; else return MovN;} + + inline std::vector &AdjP(AlignGlobal::Node *n) {if(n==Fix) return MovP; else return FixP;} + inline std::vector &AdjN(AlignGlobal::Node *n) {if(n==Fix) return MovN; else return FixN;} + + AlignGlobal::Node *Adj(Node *n) const { + + assert(n == Fix || n == Mov); + if (n == Fix) return Mov; + + return Fix; + } + + bool Check() const { + + if (FixP.size() != MovP.size()) return false; + + Point3d mp, fp; + + double md = 0, fd = 0; + double md2 = 0, fd2 = 0; + + Matrix44d &MovTr=Mov->M; + Matrix44d &FixTr=Fix->M; + + for (std::size_t i = 0; i < FixP.size(); ++i) { + + mp = MovTr * MovP[i]; + fp = FixTr * FixP[i]; + + md += Distance(fp, M2F * mp); + md2 += SquaredDistance(fp, M2F * mp); + + fd += Distance(mp, F2M * fp); + fd2 += SquaredDistance(mp, F2M * fp); + } + + int nn = static_cast(MovP.size()); + + std::fprintf(stdout, "Arc %3i -> %3i : %i pt\n", Fix->id, Mov->id, nn); + std::fprintf(stdout, "SquaredSum Distance %7.3f %7.3f Avg %7.3f %7.3f\n", fd2, md2, fd2/nn, md2/nn); + std::fprintf(stdout, " Sum Distance %7.3f %7.3f Avg %7.3f %7.3f\n", fd , md , fd/nn, md/nn); + return true; + } + }; + + class Node { + public: + + int id; // id della mesh a cui corrisponde il nodo + int sid; // Subgraph id; + Matrix44d M; // La matrice che mette la mesh nella sua posizione di base; + std::list Adj; + + /*** + * True if the node is inside the active set + */ + bool Active; + + /*** + * False if it's dormant + */ + bool Queued; + bool Discarded; + + Node() : id{-1}, Active{false}, Discarded{false}, Queued{false} {} + + // Allinea un nodo con tutti i suoi vicini + double AlignWithActiveAdj(bool Rigid) { + + std::printf("--- AlignWithActiveAdj --- \nMoving node %i with respect to nodes:", id); + + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + if ((*li)->Adj(this)->Active) { + std::printf(" %i,", (*li)->Adj(this)->id); + } + } + + std::printf("\n"); + + //printf("Base Matrix of Node %i\n",id);print(M); + + // Step 1; Costruiamo le due liste di punti da allineare + std::vector FixP, MovP, FixN, MovN; + Box3d FixBox, MovBox; + FixBox.SetNull(); MovBox.SetNull(); + + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + + // scorro tutti i nodi adiacenti attivi + if ((*li)->Adj(this)->Active) { + //printf("Base Matrix of Node %i adj to %i\n",id,(*li)->Adj(this)->id); + //print((*li)->Adj(this)->M); + std::vector &AP=(*li)->AdjP(this); // Punti sul nodo adiacente corrente; + std::vector &AN=(*li)->AdjN(this); // Normali sul nodo adiacente corrente; + + //printf("Transf that bring points of %i onto %i\n",id,(*li)->Adj(this)->id); + //print((*li)->A2N(this)); + //printf("Transf that bring points of %i onto %i\n",(*li)->Adj(this)->id,id); + //print((*li)->N2A(this)); + vcg::Point3d pf, nf; + vcg::Point3d pm; + + for (std::size_t i = 0; i < AP.size(); ++i) { + + pf = (*li)->Adj(this)->M*AP[i]; // i punti fissi sono quelli sulla sup degli adiacenti messi nella loro pos corrente + FixP.push_back(pf); + FixBox.Add(pf); + nf=(*li)->Adj(this)->M*Point3d(AP[i]+AN[i])-pf; + nf.Normalize(); + FixN.push_back(nf); + + pm = (*li)->A2N(this)*pf; + MovP.push_back(pm); // i punti che si muovono sono quelli sul adj trasformati in modo tale da cascare sul nodo corr. + MovBox.Add(pm); + } + } + } + + vcg::Matrix44d out; + //if(Rigid) ret=ComputeRigidMatchMatrix(out,FixP,MovP); + //else ret=ComputeMatchMatrix2(out,FixP,FixN,MovP); + if (Rigid) { + ComputeRigidMatchMatrix(FixP,MovP,out); + } + else { + vcg::PointMatchingScale::computeRotoTranslationScalingMatchMatrix(out, FixP, MovP); + } + + Matrix44d outIn=vcg::Inverse(out); + //double maxdiff = MatrixNorm(out); + double maxdiff = MatrixBoxNorm(out,FixBox); + + // printf("Computed Transformation:\n"); print(out);printf("--\n"); + // printf("Collected %i points . Err = %f\n",FixP.size(),maxdiff); + + // La matrice out calcolata e' quella che applicata ai punti MovP li porta su FixP, quindi i punti della mesh corrente + // La nuova posizione di base della mesh diventa quindi + // M * out + // infatti se considero un punto della mesh originale applicarci la nuova matricie significa fare + // p * M * out + + // M=M*out; //--Orig + M = out * M; + + // come ultimo step occorre applicare la matrice trovata a tutti gli allineamenti in gioco. + // scorro tutti i nodi adiacenti attivi + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + //print((*li)->N2A(this)); + //print((*li)->A2N(this));printf("--\n"); + + (*li)->N2A(this)=(*li)->N2A(this)*outIn; + (*li)->A2N(this)=(*li)->A2N(this)*out ; + //print((*li)->N2A(this)); + //print((*li)->A2N(this));printf("--\n"); + } + + return maxdiff; + } + + double MatrixNorm(vcg::Matrix44d &NewM) const { + + double maxDiff = 0; + + vcg::Matrix44d diff; + diff.SetIdentity(); + diff = diff-NewM; + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + maxDiff += (diff[i][j] * diff[i][j]); + } + } + + return maxDiff; + } + + double MatrixBoxNorm(vcg::Matrix44d &NewM, vcg::Box3d &bb) const { + + double maxDiff = 0; + vcg::Point3d pt; + + pt = Point3d(bb.min[0], bb.min[1], bb.min[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.max[0], bb.min[1], bb.min[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.min[0], bb.max[1], bb.min[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.max[0], bb.max[1], bb.min[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.min[0], bb.min[1], bb.max[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.max[0], bb.min[1], bb.max[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.min[0], bb.max[1], bb.max[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + pt = Point3d(bb.max[0], bb.max[1], bb.max[2]); maxDiff = std::max(maxDiff, Distance(pt, NewM * pt)); + + return maxDiff; + } + + int PushBackActiveAdj(std::queue &Q) { + + assert(Active); + + int count = 0; + AlignGlobal::Node *pt; + + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + + pt = (*li)->Adj(this); + + if (pt->Active && !pt->Queued) { + ++count; + pt->Queued=true; + Q.push(pt); + } + } + return count; + } + + int DormantAdjNum() { + + int count = 0; + + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + if (!(*li)->Adj(this)->Active) ++count; + } + + return count; + } + + int ActiveAdjNum() { + + int count = 0; + + for (auto li = std::begin(Adj); li != std::end(Adj); ++li) { + if ((*li)->Adj(this)->Active) ++count; + } + + return count; + } + }; + + class SubGraphInfo { + public: + int sid; + int size; + Node *root; + }; + + std::list N; + std::list A; + + /** + * Descrittori delle componenti connesse, riempito dalla ComputeConnectedComponents + */ + std::list CC; + + static inline void LOG( FILE *fp, const char * f, ... ) { + + if (fp == 0) return; + + va_list marker; + va_start(marker, f); + std::vfprintf(fp, f, marker); + va_end(marker); + std::fflush(fp); + } + + inline int DormantNum() const { + + int count = 0; + + for (auto li = std::begin(N); li != std::end(N); ++li) { + if (!(*li).Active) ++count; + } + + return count; + } + + inline int ActiveNum() const { + + int count = 0; + + for (auto li = std::begin(N); li != std::end(N); ++li) { + if ((*li).Active) ++count; + } + + return count; + } + + bool CheckGraph() { + + std::vector Visited(N.size(), false); + std::stack st; + + st.push(&(*N.begin())); + while (!st.empty()) { + + AlignGlobal::Node *cur=st.top(); + st.pop(); + // std::printf("Visiting node %i\n",cur->id); + + for (auto li = std::begin(cur->Adj); li != std::end(cur->Adj); ++li) { + if (!Visited[(*li)->Adj(cur)->id]) { + Visited[(*li)->Adj(cur)->id] = true; + st.push((*li)->Adj(cur)); + } + } + } + + size_t cnt = std::count(std::begin(Visited), std::end(Visited), true); + std::printf("Nodes that can be reached from root %zu on %zu \n", cnt, N.size()); + + return (cnt == N.size()); + } + + void Dump(FILE *fp) const { + std::fprintf(fp, "Alignment Graph of %lu nodes and %lu arcs\n", N.size(), A.size()); + // list::iterator li; + // for(li=A.begin();li!=A.end();++li) + // printf("Arc : %3i ->%3i\n",(*li)->Fix->id,(*li)->Mov->id); + } + + int ComputeConnectedComponents() { + + std::printf("Building Connected Components on a graph with %lu nodes and %lu arcs\n", N.size(), A.size()); + + CC.clear(); + + std::stack ToReach; // nodi ancora da visitare + std::stack st; // nodi che si stanno visitando + + for (auto li = std::begin(N); li != std::end(N); ++li) { + (*li).sid = -1; + ToReach.push(&*li); + } + + int cnt = 0; + + while (!ToReach.empty()) { + + SubGraphInfo sg; + st.push(&*ToReach.top()); + ToReach.pop(); + + assert(st.top()->sid==-1); + + sg.root=st.top(); + sg.sid=cnt; + sg.size=0; + st.top()->sid=cnt; + + while (!st.empty()) { + + AlignGlobal::Node *cur=st.top(); + st.pop(); + ++sg.size; + + assert(cur->sid==cnt); + // std::printf("Visiting node %2i %2i\n",cur->id,cur->sid); + + for (auto li = std::begin(cur->Adj); li != std::end(cur->Adj); ++li) { + + if ((*li)->Adj(cur)->sid == -1) { + (*li)->Adj(cur)->sid=cnt; + st.push((*li)->Adj(cur)); + } + else { + assert((*li)->Adj(cur)->sid == cnt); + } + } + + } + + cnt++; + CC.push_back(sg); + + while (!ToReach.empty() && ToReach.top()->sid != -1) ToReach.pop(); + } + + return cnt; + } + + void Clear() { + + for (auto li = std::begin(A); li != std::end(A); ++li) { + delete (*li); + } + + N.clear(); + A.clear(); + } + + void MakeAllDormant() { + for (auto li = std::begin(N); li != std::end(N); ++li) { + (*li).Active=false; + } + } + + bool GlobalAlign(const std::map &Names, const double epsilon, int maxiter, bool Rigid, FILE *elfp, vcg::CallBackPos* cb) { + + double change; + int step = 0, localmaxiter; + + if (cb != NULL) cb(0, "Global Alignment..."); + AlignGlobal::LOG(elfp,"----------------\n----------------\nGlobalAlignment (target eps %7.3f)\n", epsilon); + + std::queue Q; + MakeAllDormant(); + AlignGlobal::Node *curr = ChooseDormantWithMostDormantLink(); + curr->Active = true; + + int cursid = curr->sid; + AlignGlobal::LOG(elfp, "Root node %i '%s' with %i dormant link\n", curr->id, Names.find(curr->id)->second.c_str(), curr->DormantAdjNum()); + + while (DormantNum() > 0) { + + AlignGlobal::LOG(elfp,"---------\nGlobalAlignment loop DormantNum = %i\n", DormantNum()); + + curr = ChooseDormantWithMostActiveLink(); + if (!curr) { + // la componente connessa e' finita e si passa alla successiva cercando un dormant con tutti dormant. + AlignGlobal::LOG(elfp,"\nCompleted Connected Component %i\n", cursid); + AlignGlobal::LOG(elfp,"\nDormant Num: %i\n", DormantNum()); + + curr = ChooseDormantWithMostDormantLink(); + if (curr == nullptr) { + AlignGlobal::LOG(elfp,"\nFailed ChooseDormantWithMostDormantLink, chosen id:%i\n" ,0); + break; // non ci sono piu' componenti connesse composte da piu' di una singola mesh. + } + else { + AlignGlobal::LOG(elfp,"\nCompleted ChooseDormantWithMostDormantLink, chosen id:%i\n" ,curr->id); + } + + curr->Active = true; + cursid = curr->sid; + curr = ChooseDormantWithMostActiveLink (); + if (curr == nullptr) { + AlignGlobal::LOG(elfp, "\nFailed ChooseDormantWithMostActiveLink, chosen id:%i\n", 0); + } + else { + AlignGlobal::LOG(elfp, "\nCompleted ChooseDormantWithMostActiveLink, chosen id:%i\n", curr->id); + } + } + + AlignGlobal::LOG(elfp,"\nAdded node %i '%s' with %i/%i Active link\n",curr->id,Names.find(curr->id)->second.c_str(),curr->ActiveAdjNum(),curr->Adj.size()); + curr->Active=true; + curr->Queued=true; + + // Si suppone, ad occhio, che per risistemare un insieme di n mesh servano al piu' 10n passi; + localmaxiter = ActiveNum() * 10; + Q.push(curr); + step = 0; + + // Ciclo interno di allineamento + while (!Q.empty()) { + + curr = Q.front(); + Q.pop(); + + curr->Queued=false; + change = curr->AlignWithActiveAdj(Rigid); + step++; + + AlignGlobal::LOG(elfp, " Step %5i Queue size %5i Moved %4i err %10.4f\n", step, Q.size(), curr->id, change); + + if (change > epsilon) { + + curr->PushBackActiveAdj(Q); + AlignGlobal::LOG(elfp," Large Change pushing back active nodes adj to %i to Q (new size %i)\n",curr->id,Q.size()); + + if (change > epsilon * 1000) { + std::printf("Large Change Warning\n\n"); + } + } + if (step > localmaxiter) return false; + if (step > maxiter) return false; + } + } + + if (!curr) { + + AlignGlobal::LOG(elfp,"Alignment failed for %i meshes:\n",DormantNum()); + for (auto li = std::begin(N); li != std::end(N); ++li){ + if (!(*li).Active) { + //(*li).M.SetIdentity(); + (*li).Discarded=true; + AlignGlobal::LOG(elfp, "%5i\n", (*li).id); + } + } + } + + AlignGlobal::LOG(elfp,"Completed Alignment in %i steps with error %f\n",step,epsilon); + return true; + } + + AlignGlobal::Node* ChooseDormantWithMostDormantLink() { + + int MaxAdjNum = 0; + AlignGlobal::Node *BestNode = nullptr; + + for (auto li = std::begin(N); li != std::end(N); ++li) { + if (!(*li).Active) { + int AdjNum = (*li).DormantAdjNum(); + if (AdjNum > MaxAdjNum) { + MaxAdjNum = AdjNum; + BestNode = &(*li); + } + } + } + + if (!BestNode){ + std::printf("Warning! Unable to find a Node with at least a dormant link!!\n"); + return nullptr; + } + + assert(BestNode); + assert(!BestNode->Queued); + assert(!BestNode->Active); + + return BestNode; + } + + AlignGlobal::Node* ChooseDormantWithMostActiveLink() { + + int MaxAdjNum = 0; + AlignGlobal::Node* BestNode = nullptr; + + for (auto li = std::begin(N); li != std::end(N); ++li) { + if (!(*li).Active) { + int AdjNum = (*li).ActiveAdjNum(); + if (AdjNum > MaxAdjNum) { + MaxAdjNum = AdjNum; + BestNode = &(*li); + } + } + } + + if (!BestNode){ + // Abbiamo finito di sistemare questa componente connessa. + std::printf("Warning! Unable to find a Node with at least an active link!!\n"); + return nullptr; + } + + assert(BestNode); + assert(!BestNode->Queued); + assert(!BestNode->Active); + + return BestNode; + } + + void BuildGraph(std::vector &Res, std::vector &Tr, std::vector &Id) { + + Clear(); + // si suppone che la matrice Tr[i] sia relativa ad un nodo con id Id[i]; + int mn = static_cast(Tr.size()); + + // printf("building graph\n"); + AlignGlobal::Node rgn; + rgn.Active = false; + rgn.Queued = false; + rgn.Discarded = false; + + std::map Id2N; + std::map Id2I; + + for (int i = 0; i < mn; ++i) { + rgn.id = Id[i]; + rgn.M = Tr[i]; + N.push_back(rgn); + Id2N[rgn.id] = &(N.back()); + Id2I[rgn.id] = i; + } + + std::printf("building %zu graph arcs\n",Res.size()); + AlignGlobal::VirtAlign *tv; + + // Ciclo principale in cui si costruiscono i vari archi + // Si assume che i result siano fatti nel sistema di riferimento della matrici fix. + + for (auto rii = std::begin(Res); rii != std::end(Res); ++rii) { + + AlignPair::Result *ri = *rii; + tv = new VirtAlign(); + tv->Fix = Id2N[(*ri).FixName]; + tv->Mov = Id2N[(*ri).MovName]; + tv->Fix->Adj.push_back(tv); + tv->Mov->Adj.push_back(tv); + tv->FixP = (*ri).Pfix; + tv->MovP = (*ri).Pmov; + tv->FixN = (*ri).Nfix; + tv->MovN = (*ri).Nmov; + + /* + + Siano: + Pf e Pm i punti sulle mesh fix e mov nei sist di rif originali + Pft e Pmt i punti sulle mesh fix e mov dopo le trasf correnti; + Mf e Mm le trasf che portano le mesh fix e mov nelle posizioni correnti; + If e Im le trasf inverse di cui sopra + Vale: + Pft = Mf*Pf e Pmt = Mm*Pm + Pf = If*Pft e Pm = Im*Pmt + + Res * Pm = Pf; + Res * Im * Pmt = If * Pft + Mf * Res * Im * Pmt = Mf * If * Pft + (Mf * Res * Im) * Pmt = Pft + + */ + Matrix44d Mm = Tr[Id2I[(*ri).MovName]]; + Matrix44d Mf = Tr[Id2I[(*ri).FixName]]; + Matrix44d Im = Inverse(Mm); + Matrix44d If = Inverse(Mf); + + Matrix44d NewTr = Mf * (*ri).Tr * Im; // --- orig + + tv->M2F = NewTr; + tv->F2M = Inverse(NewTr); + + assert(tv->Check()); + A.push_back(tv); + } + + ComputeConnectedComponents(); + } + + bool GetMatrixVector(std::vector &Tr, std::vector &Id) { + + std::map Id2N; + + Tr.clear(); + + for (auto li = std::begin(N); li != std::end(N); ++li) { + Id2N[(*li).id] = &*li; + } + + Tr.resize(Id.size()); + + for (std::size_t i = 0; i < Id.size(); ++i) { + + if (Id2N[Id[i]] == 0) return false; + Tr[i] = Id2N[Id[i]]->M; + } + + return false; + } + + }; +} + +#endif //MESHLAB_ALIGNGLOBAL_H diff --git a/vcg/complex/algorithms/align_pair.h b/vcg/complex/algorithms/align_pair.h index 284e5ac0..6b71a235 100644 --- a/vcg/complex/algorithms/align_pair.h +++ b/vcg/complex/algorithms/align_pair.h @@ -128,22 +128,21 @@ public: public: IterInfo() { - memset ( (void *) this, 0, sizeof(IterInfo)); } - double MinDistAbs; - int DistanceDiscarded; - int AngleDiscarded; - int BorderDiscarded; - int SampleTested; // how many points have been tested - int SampleUsed; // how many points have been actually used to compute the transformation - double pcl50; - double pclhi; - double AVG; - double RMS; - double StdDev; - int Time; // Ending time of this iteration - + double MinDistAbs = 0; + int DistanceDiscarded = 0; + int AngleDiscarded = 0; + int BorderDiscarded = 0; + int SampleTested = 0; // how many points have been tested + // how many points have been actually used to compute the transformation + int SampleUsed = 0; + double pcl50 = 0; + double pclhi = 0; + double AVG = 0; + double RMS = 0; + double StdDev = 0; + int Time = 0; // Ending time of this iteration }; std::vector I; diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index cbed0df5..ce4151fc 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -689,6 +689,9 @@ public: tmpMesh.vert.EnableVFAdjacency(); tmpMesh.face.EnableVFAdjacency(); + if (m.face.IsWedgeTexCoordEnabled()) + tmpMesh.face.EnableWedgeTexCoord(); + size_t selCnt=0; for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) diff --git a/vcg/complex/algorithms/create/marching_cubes.h b/vcg/complex/algorithms/create/marching_cubes.h index 830e0e1d..cbc8f5dd 100644 --- a/vcg/complex/algorithms/create/marching_cubes.h +++ b/vcg/complex/algorithms/create/marching_cubes.h @@ -26,6 +26,7 @@ #define __VCG_MARCHING_CUBES #include "mc_lookup_table.h" +#include namespace vcg { @@ -665,14 +666,14 @@ namespace vcg VertexPointer vp = NULL; size_t face_idx = _mesh->face.size(); size_t v12_idx = -1; - size_t vertices_idx[3]; + std::array vertices_idx; if (v12 != NULL) v12_idx = v12 - &_mesh->vert[0]; AllocatorType::AddFaces(*_mesh, (int) n); for (int trig=0; trig<3*n; face_idx++ ) { vp = NULL; - memset(vertices_idx, -1, 3*sizeof(size_t)); + vertices_idx.fill(-1); for (int vert=0; vert<3; vert++, trig++) //ok { diff --git a/vcg/complex/algorithms/create/mc_trivial_walker.h b/vcg/complex/algorithms/create/mc_trivial_walker.h index 8a745560..ac670fe7 100644 --- a/vcg/complex/algorithms/create/mc_trivial_walker.h +++ b/vcg/complex/algorithms/create/mc_trivial_walker.h @@ -166,12 +166,11 @@ private: { _bbox = subbox; _slice_dimension = _bbox.DimX()*_bbox.DimZ(); - - _x_cs = new VertexIndex[ _slice_dimension ]; - _y_cs = new VertexIndex[ _slice_dimension ]; - _z_cs = new VertexIndex[ _slice_dimension ]; - _x_ns = new VertexIndex[ _slice_dimension ]; - _z_ns = new VertexIndex[ _slice_dimension ]; + _x_cs.resize(_slice_dimension); + _y_cs.resize(_slice_dimension); + _z_cs.resize(_slice_dimension); + _x_ns.resize(_slice_dimension); + _z_ns.resize(_slice_dimension); } TrivialWalker() @@ -321,23 +320,22 @@ protected: int _slice_dimension; int _current_slice; - - VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente - VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente - VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente - VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta - VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta + + std::vector _x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente + std::vector _y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente + std::vector _z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente + std::vector _x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta + std::vector _z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta MeshType *_mesh; VolumeType *_volume; - - float _thr; + + float _thr; void NextYSlice() { - memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex)); - + std::fill(_x_cs.begin(),_x_cs.end(),-1); + std::fill(_y_cs.begin(),_y_cs.end(),-1); + std::fill(_z_cs.begin(),_z_cs.end(),-1); std::swap(_x_cs, _x_ns); std::swap(_z_cs, _z_ns); @@ -347,13 +345,11 @@ protected: void Begin() { _current_slice = _bbox.min.Y(); - - memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex)); - memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex)); - + std::fill(_x_cs.begin(),_x_cs.end(),-1); + std::fill(_y_cs.begin(),_y_cs.end(),-1); + std::fill(_z_cs.begin(),_z_cs.end(),-1); + std::fill(_x_ns.begin(),_x_ns.end(),-1); + std::fill(_z_ns.begin(),_z_ns.end(),-1); } }; } // end namespace tri diff --git a/vcg/complex/algorithms/create/platonic.h b/vcg/complex/algorithms/create/platonic.h index 8b4d906e..386bcff1 100644 --- a/vcg/complex/algorithms/create/platonic.h +++ b/vcg/complex/algorithms/create/platonic.h @@ -639,11 +639,11 @@ void Torus(MeshType &m, float hRingRadius, float vRingRadius, int hRingDiv=24, i template static ScalarType _SQfnC(ScalarType a, ScalarType b){ return math::Sgn(cos(a))*pow(fabs(cos(a)),b); -}; +} template static ScalarType _SQfnS(ScalarType a, ScalarType b){ return math::Sgn(sin(a))*pow(fabs(sin(a)),b); -}; +} /** diff --git a/vcg/complex/algorithms/create/plymc/plymc.h b/vcg/complex/algorithms/create/plymc/plymc.h index d01ed870..c90f233d 100644 --- a/vcg/complex/algorithms/create/plymc/plymc.h +++ b/vcg/complex/algorithms/create/plymc/plymc.h @@ -173,7 +173,7 @@ public: MeshProvider MP; Parameter p; Volume VV; - char errorMessage[1024]; + std::string errorMessage; /// PLYMC Methods @@ -193,7 +193,7 @@ public: { if(m.FN()==0) { - sprintf(errorMessage,"%sError: mesh has not per vertex normals\n",errorMessage); + errorMessage = "Error: mesh has not per vertex normals\n"; return false; } else @@ -214,7 +214,7 @@ public: tri::Allocator::CompactEveryVector(m); if(badNormalCnt > m.VN()/10) { - sprintf(errorMessage,"%sError: mesh has null normals\n",errorMessage); + errorMessage = "Error: mesh has null normals\n"; return false; } @@ -340,7 +340,7 @@ public: bool Process(vcg::CallBackPos *cb=0) { - sprintf(errorMessage,"%s", ""); + errorMessage = ""; printf("bbox scanning...\n"); fflush(stdout); Matrix44f Id; Id.SetIdentity(); MP.InitBBox(); @@ -419,7 +419,7 @@ bool Process(vcg::CallBackPos *cb=0) res = InitMesh(*sm,MP.MeshName(i).c_str(),MP.Tr(i)); if(!res) { - sprintf(errorMessage,"%sFailed Init of mesh %s\n",errorMessage,MP.MeshName(i).c_str()); + errorMessage = "Failed Init of mesh " +MP.MeshName(i); return false ; } } @@ -597,7 +597,6 @@ int MCSimplify( MeshType &m, float absoluteError, bool preserveBB, vcg::CallBack //qDebug("Simplifying at absoluteError=%f",absoluteError); float TargetError = absoluteError; - char buf[1024]; DeciSession.template Init< MyColl > (); pp.areaThr=TargetError*TargetError; @@ -605,8 +604,9 @@ int MCSimplify( MeshType &m, float absoluteError, bool preserveBB, vcg::CallBack if(TargetError < std::numeric_limits::max() ) DeciSession.SetTargetMetric(TargetError); while(DeciSession.DoOptimization() && DeciSession.currMetric < TargetError) { - sprintf(buf,"Simplyfing %7i err %9g \r",m.fn,DeciSession.currMetric); - if (cb) cb(int(100.0f*DeciSession.currMetric/TargetError),buf); + std::string buf = "Simplyfing " + std::to_string(m.fn) + " err " + std::to_string(DeciSession.currMetric) + " \r"; + if (cb) + cb(int(100.0f*DeciSession.currMetric/TargetError),buf.c_str()); } return 1; //success diff --git a/vcg/complex/algorithms/create/plymc/volume.h b/vcg/complex/algorithms/create/plymc/volume.h index 0a9ba7fc..8f654ee9 100644 --- a/vcg/complex/algorithms/create/plymc/volume.h +++ b/vcg/complex/algorithms/create/plymc/volume.h @@ -42,7 +42,7 @@ const char *SFormat( const char * f, ... ) static char buf[4096]; va_list marker; va_start( marker, f ); - vsprintf(buf,f,marker); + vsnprintf(buf,4096,f,marker); va_end( marker ); return buf; } @@ -301,9 +301,9 @@ public: void GetSubVolumeTag(std::string &subtag) { char buf[32]; - if (div[0]<= 10 && div[1]<= 10 && div[2]<= 10 ) sprintf(buf,"_%01d%01d%01d",pos[0],pos[1],pos[2]); - else if(div[0]<= 100 && div[1]<= 100 && div[2]<= 100 ) sprintf(buf,"_%02d%02d%02d",pos[0],pos[1],pos[2]); - else sprintf(buf,"_%03d%03d%03d",pos[0],pos[1],pos[2]); + if (div[0]<= 10 && div[1]<= 10 && div[2]<= 10 ) snprintf(buf,32,"_%01d%01d%01d",pos[0],pos[1],pos[2]); + else if(div[0]<= 100 && div[1]<= 100 && div[2]<= 100 ) snprintf(buf,32,"_%02d%02d%02d",pos[0],pos[1],pos[2]); + else snprintf(buf,32,"_%03d%03d%03d",pos[0],pos[1],pos[2]); subtag=buf; } diff --git a/vcg/complex/algorithms/create/resampler.h b/vcg/complex/algorithms/create/resampler.h index edf9eae5..94a484ec 100644 --- a/vcg/complex/algorithms/create/resampler.h +++ b/vcg/complex/algorithms/create/resampler.h @@ -74,19 +74,22 @@ class Resampler : public BasicGrid //typedef tri::FaceTmark MarkerFace; typedef vcg::tri::EmptyTMark MarkerFace; MarkerFace markerFunctor; - - VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente - VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente - VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente - VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta - VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta + + std::vector _x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente + std::vector _y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente + std::vector _z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente + std::vector _x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta + std::vector _z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta //float *_v_cs;///values of distance fields for each direction in current slice //float *_v_ns;///values of distance fields for each direction in next slice typedef typename std::pair field_value; - field_value* _v_cs; - field_value* _v_ns; + std::vector _v_cs; + std::vector _v_ns; + +// field_value* _v_cs; +// field_value* _v_ns; NewMeshType *_newM; OldMeshType *_oldM; @@ -110,15 +113,22 @@ class Resampler : public BasicGrid DiscretizeFlag=false; MultiSampleFlag=false; AbsDistFlag=false; - - _x_cs = new VertexIndex[ SliceSize ]; - _y_cs = new VertexIndex[ SliceSize ]; - _z_cs = new VertexIndex[ SliceSize ]; - _x_ns = new VertexIndex[ SliceSize ]; - _z_ns = new VertexIndex[ SliceSize ]; - - _v_cs= new field_value[(this->siz.X()+1)*(this->siz.Z()+1)]; - _v_ns= new field_value[(this->siz.X()+1)*(this->siz.Z()+1)]; + + _x_cs.resize(SliceSize); + _y_cs.resize(SliceSize); + _z_cs.resize(SliceSize); + _x_ns.resize(SliceSize); + _z_ns.resize(SliceSize); +// _x_cs = new VertexIndex[ SliceSize ]; +// _y_cs = new VertexIndex[ SliceSize ]; +// _z_cs = new VertexIndex[ SliceSize ]; +// _x_ns = new VertexIndex[ SliceSize ]; +// _z_ns = new VertexIndex[ SliceSize ]; + + _v_cs.resize((this->siz.X()+1)*(this->siz.Z()+1)); + _v_ns.resize((this->siz.X()+1)*(this->siz.Z()+1)); +// _v_cs= new field_value[(this->siz.X()+1)*(this->siz.Z()+1)]; +// _v_ns= new field_value[(this->siz.X()+1)*(this->siz.Z()+1)]; }; @@ -232,7 +242,7 @@ class Resampler : public BasicGrid /// compute the values if an entire slice (per y) distances>dig of a cell are signed with double of /// the distance of the bb - void ComputeSliceValues(int slice,field_value *slice_values) + void ComputeSliceValues(int slice,std::vector &slice_values) { #pragma omp parallel for schedule(dynamic, 10) for (int i=0; i<=this->siz.X(); i++) @@ -252,7 +262,7 @@ class Resampler : public BasicGrid For some reasons it can happens that the sign of the computed distance could not correct. this function tries to correct these issues by flipping the isolated voxels with discordant sign */ - void ComputeConsensus(int /*slice*/, field_value *slice_values) + void ComputeConsensus(int /*slice*/, std::vector &slice_values) { float max_dist = min(min(this->voxel[0],this->voxel[1]),this->voxel[2]); int flippedCnt=0; @@ -363,10 +373,13 @@ class Resampler : public BasicGrid //swap slices , the initial value of distance fields ids set as double of bbox of space void NextSlice() { - - memset(_x_cs, -1, SliceSize*sizeof(VertexIndex)); - memset(_y_cs, -1, SliceSize*sizeof(VertexIndex)); - memset(_z_cs, -1, SliceSize*sizeof(VertexIndex)); + + std::fill(_x_cs.begin(),_x_cs.end(),-1); + std::fill(_y_cs.begin(),_y_cs.end(),-1); + std::fill(_z_cs.begin(),_z_cs.end(),-1); +// memset(_x_cs, -1, SliceSize*sizeof(VertexIndex)); +// memset(_y_cs, -1, SliceSize*sizeof(VertexIndex)); +// memset(_z_cs, -1, SliceSize*sizeof(VertexIndex)); std::swap(_x_cs, _x_ns); @@ -384,12 +397,18 @@ class Resampler : public BasicGrid { CurrentSlice = 0; - - memset(_x_cs, -1, SliceSize*sizeof(VertexIndex)); - memset(_y_cs, -1, SliceSize*sizeof(VertexIndex)); - memset(_z_cs, -1, SliceSize*sizeof(VertexIndex)); - memset(_x_ns, -1, SliceSize*sizeof(VertexIndex)); - memset(_z_ns, -1, SliceSize*sizeof(VertexIndex)); + + std::fill(_x_cs.begin(),_x_cs.end(),-1); + std::fill(_y_cs.begin(),_y_cs.end(),-1); + std::fill(_z_cs.begin(),_z_cs.end(),-1); + std::fill(_x_ns.begin(),_x_ns.end(),-1); + std::fill(_z_ns.begin(),_z_ns.end(),-1); + +// memset(_x_cs, -1, SliceSize*sizeof(VertexIndex)); +// memset(_y_cs, -1, SliceSize*sizeof(VertexIndex)); +// memset(_z_cs, -1, SliceSize*sizeof(VertexIndex)); +// memset(_x_ns, -1, SliceSize*sizeof(VertexIndex)); +// memset(_z_ns, -1, SliceSize*sizeof(VertexIndex)); ComputeSliceValues(CurrentSlice,_v_cs); ComputeSliceValues(CurrentSlice+1,_v_ns); diff --git a/vcg/complex/algorithms/curve_on_manifold.h b/vcg/complex/algorithms/curve_on_manifold.h index 2c8e4abe..e03e1f5f 100644 --- a/vcg/complex/algorithms/curve_on_manifold.h +++ b/vcg/complex/algorithms/curve_on_manifold.h @@ -1141,7 +1141,7 @@ public: } }; -struct EdgePointSplit : public std::unary_function , CoordType> +struct EdgePointSplit { public: std::map, VertexPointer> &edgeToPolyVertMap; diff --git a/vcg/complex/algorithms/hole.h b/vcg/complex/algorithms/hole.h index ecb2256b..70e6aae7 100644 --- a/vcg/complex/algorithms/hole.h +++ b/vcg/complex/algorithms/hole.h @@ -291,8 +291,8 @@ public: typename MESH::ScalarType aspectRatio; const char * Dump() { static char buf[200]; - if(this->IsConcave()) sprintf(buf,"Dihedral -(deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); - else sprintf(buf,"Dihedral (deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); + if(this->IsConcave()) snprintf(buf,200,"Dihedral -(deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); + else snprintf(buf,200,"Dihedral (deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); return buf; } diff --git a/vcg/complex/algorithms/intersection.h b/vcg/complex/algorithms/intersection.h index b0c8cab9..3277ee5a 100644 --- a/vcg/complex/algorithms/intersection.h +++ b/vcg/complex/algorithms/intersection.h @@ -195,6 +195,26 @@ bool IntersectionPlaneMesh(TriMeshType & m, } tri::Allocator :: template DeletePerVertexAttribute < ScalarType >(m,qH); + //Clean-up: Remove duplicate vertex + tri::Clean::RemoveDuplicateVertex(em); + + //Clean-up: Sort edges ensuring orientation coherence + for(size_t j=1; j < em.edge.size(); j++) + { + auto &n=em.edge[j-1].V(1); + for(size_t i=j; i< em.edge.size(); i++) + { + auto & ei=em.edge[i]; + if (ei.V(1) == n) + std::swap(ei.V(0), ei.V(1)); + if (ei.V(0) == n) + { + std::swap(em.edge[j], em.edge[i]); + break; + } + } + } + return true; } diff --git a/vcg/complex/algorithms/local_optimization/quad_diag_collapse.h b/vcg/complex/algorithms/local_optimization/quad_diag_collapse.h index 94d65353..f2dea23a 100755 --- a/vcg/complex/algorithms/local_optimization/quad_diag_collapse.h +++ b/vcg/complex/algorithms/local_optimization/quad_diag_collapse.h @@ -358,9 +358,12 @@ namespace vcg{ virtual const char *Info(MeshType &m) { - static char buf[60]; - sprintf(buf,"(%d - %d) %g\n", hp->HVp()-&m.vert[0], hp->HNp()->HNp()->HVp()-&m.vert[0], -_priority); - return buf; + static std::string msg; + msg = + "(" + std::to_string(hp->HVp()-&m.vert[0]) + + " - " + std::to_string(hp->HNp()->HNp()->HVp()-&m.vert[0]) + + ") " + std::to_string(-_priority) + "\n"; + return msg.c_str(); } /*! diff --git a/vcg/complex/algorithms/local_optimization/tri_edge_collapse.h b/vcg/complex/algorithms/local_optimization/tri_edge_collapse.h index 309210da..0a4a8693 100644 --- a/vcg/complex/algorithms/local_optimization/tri_edge_collapse.h +++ b/vcg/complex/algorithms/local_optimization/tri_edge_collapse.h @@ -115,9 +115,12 @@ public: virtual const char *Info(TriMeshType &m) { mt = &m; - static char buf[60]; - sprintf(buf,"%i -> %i %g\n", int(pos.V(0)-&m.vert[0]), int(pos.V(1)-&m.vert[0]),-_priority); - return buf; + static std::string msg; + msg = + std::to_string(int(pos.V(0)-&m.vert[0])) + " -> " + + std::to_string(int(pos.V(1)-&m.vert[0])) + + " " + std::to_string(-_priority) + "\n"; + return msg.c_str(); } inline void Execute(TriMeshType &m, BaseParameterClass *) diff --git a/vcg/complex/algorithms/local_optimization/tri_edge_flip.h b/vcg/complex/algorithms/local_optimization/tri_edge_flip.h index 29f26b5f..2ad4d64e 100644 --- a/vcg/complex/algorithms/local_optimization/tri_edge_flip.h +++ b/vcg/complex/algorithms/local_optimization/tri_edge_flip.h @@ -283,9 +283,12 @@ public: */ const char* Info(TRIMESH_TYPE &m) { - static char dump[60]; - sprintf(dump,"%zu -> %zu %g\n", tri::Index(m,_pos.F()->V(0)), tri::Index(m,_pos.F()->V(1)),-_priority); - return dump; + static std::string msg; + msg = + std::to_string(tri::Index(m,_pos.F()->V(0))) + " -> " + + std::to_string(tri::Index(m,_pos.F()->V(1))) + + " " + std::to_string(-_priority) + "\n"; + return msg.c_str(); } /*! diff --git a/vcg/complex/algorithms/mesh_to_matrix.h b/vcg/complex/algorithms/mesh_to_matrix.h index c85edf8b..89ac2afd 100644 --- a/vcg/complex/algorithms/mesh_to_matrix.h +++ b/vcg/complex/algorithms/mesh_to_matrix.h @@ -278,7 +278,7 @@ public: } ScalarType maxA=0; for(int i=0;i +#include +#include + +#ifdef _OPENMP +#include +#endif + +namespace vcg { + + template + class MeshTree { + + public: + + class MeshNode { + + public: + bool glued; + MeshType *m; + + explicit MeshNode(MeshType *_m) : m{_m}, glued{false} {} + + vcg::Matrix44 &tr() { + return m->cm.Tr; + } + + const vcg::Box3 &bbox() const { + return m->cm.bbox; + } + + int Id() { + return m->id(); + } + }; + + class Param { + public: + int OGSize = 50000; + float arcThreshold = 0.3f; + float recalcThreshold = 0.1f; + }; + + std::map nodeMap; + std::vector resultList; + + vcg::OccupancyGrid OG{}; + vcg::CallBackPos* cb = vcg::DummyCallBackPos; + + MeshTree() = default; + + ~MeshTree() { clear(); } + + MeshType *MM(unsigned int i) { + return nodeMap[i]->m; + } + + void clear() { + + for (auto& ni : nodeMap) { + delete ni.second; + } + + nodeMap.clear(); + resultList.clear(); + } + + void deleteResult(MeshTree::MeshNode *mp) { + + auto li = std::begin(resultList); + while (li != resultList.end()) { + + if (li->MovName == mp->Id() || li->FixName == mp->Id()) { + li = resultList.erase(li); + } + else { + ++li; + } + } + } + + vcg::AlignPair::Result* findResult(int id1, int id2) { + + for (auto& li : resultList) { + if ((li.MovName == id1 && li.FixName == id2) || (li.MovName == id2 && li.FixName == id1) ) { + return &li; + } + } + + return nullptr; + } + + MeshTree::MeshNode *find(int id) { + + MeshTree::MeshNode *mp = nodeMap[id]; + + if (mp == nullptr || mp->Id() != id) { + assert("You are trying to find a non existent mesh" == nullptr); + } + + return mp; + } + + MeshTree::MeshNode *find(MeshType *m) { + + for (auto& ni : nodeMap) { + if (ni.second->m == m) return ni.second; + } + + assert("You are trying to find a non existent mesh" == nullptr); + return nullptr; + } + + int gluedNum() { + + int count = 0; + + for (auto& ni : nodeMap) { + if (ni.second->glued) ++count; + } + + return count; + } + + void Process(vcg::AlignPair::Param& ap, MeshTree::Param& mtp) + { + std::array buf; + std::snprintf( + buf.data(), + 1024, + "Starting Processing of %i glued meshes out of %zu meshes\n", + gluedNum(), + nodeMap.size()); + cb(0, buf.data()); + + /******* Occupancy Grid Computation *************/ + buf.fill('\0'); + std::snprintf(buf.data(), 1024, "Computing Overlaps %i glued meshes...\n", gluedNum()); + cb(0, buf.data()); + + OG.Init( + static_cast(nodeMap.size()), + vcg::Box3::Construct(gluedBBox()), + mtp.OGSize); + + for (auto& ni : nodeMap) { + MeshTree::MeshNode* mn = ni.second; + if (mn->glued) { + OG.AddMesh(mn->m->cm, vcg::Matrix44::Construct(mn->tr()), mn->Id()); + } + } + + OG.Compute(); + OG.Dump(stdout); + // Note: the s and t of the OG translate into fix and mov, respectively. + + /*************** The long loop of arc computing **************/ + + // count existing arcs within current error threshold + float percentileThr = 0; + if (!resultList.empty()) { + vcg::Distribution H; + for (auto& li : resultList) { + H.Add(li.err); + } + + percentileThr = H.Percentile(1.0f - mtp.recalcThreshold); + } + + std::size_t totalArcNum = 0; + int preservedArcNum = 0, recalcArcNum = 0; + + while (totalArcNum < OG.SVA.size() && + OG.SVA[totalArcNum].norm_area > mtp.arcThreshold) { + AlignPair::Result* curResult = + findResult(OG.SVA[totalArcNum].s, OG.SVA[totalArcNum].t); + if (curResult) { + if (curResult->err < percentileThr) { + ++preservedArcNum; + } + else { + ++recalcArcNum; + } + } + else { + resultList.push_back(AlignPair::Result()); + resultList.back().FixName = OG.SVA[totalArcNum].s; + resultList.back().MovName = OG.SVA[totalArcNum].t; + resultList.back().err = std::numeric_limits::max(); + } + ++totalArcNum; + } + + // if there are no arcs at all complain and return + if (totalArcNum == 0) { + buf.fill('\0'); + std::snprintf( + buf.data(), + 1024, + "\n Failure. There are no overlapping meshes?\n No candidate alignment arcs. " + "Nothing Done.\n"); + cb(0, buf.data()); + return; + } + + int num_max_thread = 1; +#ifdef _OPENMP + if (totalArcNum > 32) + num_max_thread = omp_get_max_threads(); +#endif + buf.fill('\0'); + std::snprintf( + buf.data(), 1024,"Arc with good overlap %6zu (on %6zu)\n", totalArcNum, OG.SVA.size()); + cb(0, buf.data()); + + buf.fill('\0'); + std::snprintf(buf.data(), 1024," %6i preserved %i Recalc \n", preservedArcNum, recalcArcNum); + cb(0, buf.data()); + + bool hasValidAlign = false; + +#pragma omp parallel for schedule(dynamic, 1) num_threads(num_max_thread) + + // on windows, omp does not support unsigned types for indices on cycles + for (int i = 0; i < static_cast(totalArcNum); ++i) { + std::fprintf( + stdout, + "%4i -> %4i Area:%5i NormArea:%5.3f\n", + OG.SVA[i].s, + OG.SVA[i].t, + OG.SVA[i].area, + OG.SVA[i].norm_area); + AlignPair::Result* curResult = findResult(OG.SVA[i].s, OG.SVA[i].t); + + // // missing arc and arc with great error must be recomputed. + if (curResult->err >= percentileThr) { + ProcessArc(OG.SVA[i].s, OG.SVA[i].t, *curResult, ap); + curResult->area = OG.SVA[i].norm_area; + + if (curResult->isValid()) { + hasValidAlign = true; + std::pair dd = curResult->computeAvgErr(); +#pragma omp critical + + buf.fill('\0'); + std::snprintf( + buf.data(), + 1024, + "(%3i/%3zu) %2i -> %2i Aligned AvgErr dd=%f -> dd=%f \n", + i + 1, + totalArcNum, + OG.SVA[i].s, + OG.SVA[i].t, + dd.first, + dd.second); + cb(0, buf.data()); + } + else { +#pragma omp critical + buf.fill('\0'); + std::snprintf( + buf.data(), + 1024, + "(%3i/%3zu) %2i -> %2i Failed Alignment of one arc %s\n", + i + 1, + totalArcNum, + OG.SVA[i].s, + OG.SVA[i].t, + vcg::AlignPair::errorMsg(curResult->status)); + cb(0, buf.data()); + } + } + } + + // if there are no valid arcs complain and return + if (!hasValidAlign) { + buf.fill('\0'); + std::snprintf( + buf.data(), + 1024, + "\n Failure. No successful arc among candidate Alignment arcs. Nothing " + "Done.\n"); + cb(0, buf.data()); + return; + } + + vcg::Distribution H; // stat for printing + for (auto& li : resultList) { + if (li.isValid()) + H.Add(li.err); + } + + buf.fill('\0'); + std::snprintf( + buf.data(), + 1024, + "Completed Mesh-Mesh Alignment: Avg Err %5.3f; Median %5.3f; 90%% %5.3f\n", + H.Avg(), + H.Percentile(0.5f), + H.Percentile(0.9f)); + cb(0, buf.data()); + + ProcessGlobal(ap); + } + + void ProcessGlobal(vcg::AlignPair::Param& ap) + { + /************** Preparing Matrices for global alignment *************/ + std::vector GluedIdVec; + std::vector GluedTrVec; + + std::map names; + + for (auto& ni : nodeMap) { + MeshTree::MeshNode* mn = ni.second; + if (mn->glued) { + GluedIdVec.push_back(mn->Id()); + GluedTrVec.push_back(vcg::Matrix44d::Construct(mn->tr())); + names[mn->Id()] = qUtf8Printable(mn->m->label()); + } + } + + vcg::AlignGlobal AG; + std::vector ResVecPtr; + for (auto& li : resultList) { + if (li.isValid()) { + ResVecPtr.push_back(&li); + } + } + + AG.BuildGraph(ResVecPtr, GluedTrVec, GluedIdVec); + + float StartGlobErr = 0.001f; + while (!AG.GlobalAlign( + names, + StartGlobErr, + 100, + ap.MatchMode == vcg::AlignPair::Param::MMRigid, + stdout, + cb)) { + StartGlobErr *= 2; + AG.BuildGraph(ResVecPtr, GluedTrVec, GluedIdVec); + } + + std::vector GluedTrVecOut(GluedTrVec.size()); + AG.GetMatrixVector(GluedTrVecOut, GluedIdVec); + + // Now get back the results! + for (std::size_t ii = 0; ii < GluedTrVecOut.size(); ++ii) { + MM(GluedIdVec[ii])->cm.Tr.Import(GluedTrVecOut[ii]); + } + std::string str = + "Completed Global Alignment (error bound " + std::to_string(StartGlobErr) + ")\n"; + cb(0, str.c_str()); + } + + void ProcessArc(int fixId, int movId, vcg::AlignPair::Result &result, vcg::AlignPair::Param ap) { + + // l'allineatore globale cambia le varie matrici di posizione di base delle mesh + // per questo motivo si aspetta i punti nel sistema di riferimento locale della mesh fix + // Si fanno tutti i conti rispetto al sistema di riferimento locale della mesh fix + vcg::Matrix44d FixM = vcg::Matrix44d::Construct(find(fixId)->tr()); + vcg::Matrix44d MovM = vcg::Matrix44d::Construct(find(movId)->tr()); + vcg::Matrix44d MovToFix = Inverse(FixM) * MovM; + + ProcessArc(fixId, movId, MovToFix, result, ap); + } + + void ProcessArc(int fixId, int movId, vcg::Matrix44d &MovM, vcg::AlignPair::Result &result, vcg::AlignPair::Param ap) { + + vcg::AlignPair::A2Mesh Fix; + vcg::AlignPair aa; + + // 1) Convert fixed mesh and put it into the grid. + MM(fixId)->updateDataMask(MeshType::MeshModel::MM_FACEMARK); + aa.convertMesh(MM(fixId)->cm,Fix); + + vcg::AlignPair::A2Grid UG; + vcg::AlignPair::A2GridVert VG; + + if (MM(fixId)->cm.fn==0 || ap.UseVertexOnly) { + Fix.initVert(vcg::Matrix44d::Identity()); + vcg::AlignPair::InitFixVert(&Fix,ap,VG); + } + else { + Fix.init(vcg::Matrix44d::Identity()); + vcg::AlignPair::initFix(&Fix, ap, UG); + } + + // 2) Convert the second mesh and sample a points on it. + MM(movId)->updateDataMask(MeshType::MeshModel::MM_FACEMARK); + std::vector tmpmv; + aa.convertVertex(MM(movId)->cm.vert,tmpmv); + aa.sampleMovVert(tmpmv, ap.SampleNum, ap.SampleMode); + + aa.mov=&tmpmv; + aa.fix=&Fix; + aa.ap = ap; + + // Perform the ICP algorithm + aa.align(MovM,UG,VG,result); + + result.FixName=fixId; + result.MovName=movId; + } + + inline vcg::Box3 bbox() { + + vcg::Box3 FullBBox; + for (auto& ni : nodeMap) { + FullBBox.Add(vcg::Matrix44d::Construct(ni.second->tr()), ni.second->bbox()); + } + + return FullBBox; + } + + inline vcg::Box3 gluedBBox() { + + vcg::Box3 FullBBox; + + for (auto& ni : nodeMap) { + if (ni.second->glued) { + FullBBox.Add(vcg::Matrix44::Construct(ni.second->tr()), ni.second->bbox()); + } + } + + return FullBBox; + } + + }; + +} + +#endif //VCGLIB_MESHTREE_H diff --git a/vcg/complex/algorithms/occupancy_grid.h b/vcg/complex/algorithms/occupancy_grid.h new file mode 100644 index 00000000..e4603119 --- /dev/null +++ b/vcg/complex/algorithms/occupancy_grid.h @@ -0,0 +1,429 @@ +#include + +// #include +#include + +#include +#include + +#ifndef VCGLIB_OCCUPANCY_GRID_H +#define VCGLIB_OCCUPANCY_GRID_H + +#define OG_MAX_MCB_SIZE 2048 +#define OG_MESH_INFO_MAX_STAT 64 + +namespace vcg { + template + class OccupancyGrid { + + public: + + /** + * Class to keep for each voxel the id of the mesh passing through it. + * based on bitset + */ + class MeshCounter { + + private: + std::bitset cnt; + + public: + + static constexpr int MaxVal() { + return OG_MAX_MCB_SIZE; + } + + bool Empty() const { + return cnt.none(); + } + + void Clear() { + cnt.reset(); + } + + bool IsSet(size_t i) const { + return cnt.test(i); + } + + void Set(size_t i) { + cnt.set(i); + } + + void UnSet(size_t i) { + cnt.reset(i); + } + + size_t Count() const { + return cnt.count(); + } + + /** + * Return a vector with all the id of the meshes + */ + void Pack(std::vector &v) const { + + v.clear(); + + for (size_t i = 0; i < MeshCounter::MaxVal(); ++i) { + if (cnt.test(i)) { + v.push_back(i); + } + } + } + + bool operator < (const MeshCounter &c) const { + + if (cnt == c.cnt) return false; + + std::size_t ii = 0; + + while (ii < MeshCounter::MaxVal()){ + if (cnt[ii] != c.cnt[ii]) { + return cnt[ii] < c.cnt[ii]; + } + ++ii; + } + return false; + } + }; + + /** + * Class for collecting cumulative information about each mesh in the OG. + * This info are collected in the Compute() by scanning the OG after we filled it with all the meshes. + */ + class OGMeshInfo { + + public: + + int id {-1}; // the id of the mesh + int area {0}; // number of voxels in the OG touched by this mesh + int coverage {0}; // quanto e' ricoperta da altre mesh eccetto se stessa (eg: se ho due mesh di 1000 con overlap al 30% la covrg e' 300) + + bool used = false; + + std::vector densityDistribution; // Distribution of the of the density of the voxels touched by this mesh: + // densityDistribution[i] says how many voxel (among the ones coverd by this mesh) + // are covered by othermeshes. Sum(densityDistribution) == area; + // if densityDistribution[1] > 0 means that this mesh is the unique to cover some portion of the space. + + void Init(int _id) { + id=_id; + } + + bool operator < (OGMeshInfo &o) const { + return area < o.area; + } + + static constexpr int MaxStat() { + return OG_MESH_INFO_MAX_STAT; + } + }; + + /** + * Classe con informazioni su un arco plausibile + */ + class OGArcInfo { + public: + + enum sort { + AREA, + NORM_AREA, + DEGREE + }; + + int s, t; // source and target (come indici nel gruppo corrente) + int area; // + float norm_area; + + OGArcInfo(int _s, int _t, int _area, float _n) : s{_s}, t{_t}, area{_area}, norm_area{_n} {} + OGArcInfo(int _s, int _t, int _area) : s{_s}, t{_t}, area{_area} {} + + bool operator < (const OGArcInfo &p) const { + return norm_area < p.norm_area; + } + }; + + GridStaticObj G; + + int mn; + int TotalArea; + /** + * Maximum number of meshes that cross a cell + */ + int MaxCount; + + /** + * SortedVisual Arcs + */ + std::vector SVA; // SortedVirtual Arcs; + /** + * High level information for each mesh. Mapped by mesh id + */ + std::map VM; + + bool Init(int _mn, Box3 bb, int size) { + + // the number of meshes (including all the unused ones; eg it is the range of the possible id) + mn = _mn; + if (mn > MeshCounter::MaxVal()) return false; + + MeshCounter MC; + + MC.Clear(); + G.Create(bb,size,MC); + VM.clear(); + + return true; + } + + void Add(const char *MeshName, Matrix44 &Tr, int id) { + + AlignPair::A2Mesh M; + + vcg::tri::io::Importer::Open(M, MeshName); + vcg::tri::Clean::RemoveUnreferencedVertex(M); + + AddMesh(M,Tr,id); + } + + void AddMeshes(std::vector &names, std::vector> &trv,int size) { + + Box3 bb, totalbb; + + bb.SetNull(); + totalbb.SetNull(); + + std::fprintf(stdout, "OG::AddMesh:Scanning BBoxes\n"); + + for (std::size_t i = 0; i < names.size(); ++i) { + // vcg::ply::ScanBBox(names[i].c_str(), bb, true); + totalbb.Add(trv[i], bb); + } + + Init(names.size(),totalbb,size); + + for (std::size_t i = 0; i < names.size(); ++i) { + std::fprintf(stdout, "OG::AddMesh:Adding Mesh %i '%s'\n", i, names[i].c_str()); + Add(names[i].c_str(), trv[i], i); + } + } + + void AddMesh(MeshType &mesh, const Matrix44 &Tr, int ind) { + + Matrix44f Trf; + Trf.Import(Tr); + + for (auto vi = std::begin(mesh.vert); vi != std::end(mesh.vert); ++vi) { + + if (!(*vi).IsD()) { + G.Grid(Trf * Point3f::Construct((*vi).P())).Set(ind); + } + } + + VM[ind].Init(ind); + VM[ind].used = true; + } + + void RemoveMesh(int id) { + + MeshCounter *GridEnd = G.grid + G.size(); + + for (MeshCounter* ig = G.grid; ig != GridEnd; ++ig) { + ig->UnSet(id); + } + } + + /** + * This function is called after we have all the mesh to the OG + * to collect the information about the interferences between the various meshes. + */ + void Compute() { + + // Analisi della griglia + // Si deve trovare l'insieme degli archi piu'plausibili + // un arco ha "senso" in una cella se entrambe le mesh compaiono in quell'arco + // Si considera tutti gli archi possibili e si conta in quante celle ha senso un arco + + std::vector VA; // virtual arcs + VA.resize(mn * mn, 0); + + std::map, int> VAMap; + + // First Loop: + // Scan the grid and update possible arc count + for (int i = 0; i < G.siz[0]; ++i) { + + for (int j = 0; j < G.siz[1]; ++j) { + + for (int k = 0; k < G.siz[2]; ++k) { + + std::vector vv; + G.Grid(i, j, k).Pack(vv); + std::size_t meshInCell = vv.size(); + + for (std::size_t ii = 0; ii < vv.size(); ++ii) { + + OccupancyGrid::OGMeshInfo &omi_ii = VM[vv[ii]]; + + ++omi_ii.area; // compute mesh area + if (meshInCell > omi_ii.densityDistribution.size()) { + omi_ii.densityDistribution.resize(meshInCell); + } + + ++(omi_ii.densityDistribution[meshInCell - 1]); + } + + for (std::size_t ii = 0; ii < vv.size(); ++ii) { + for (std::size_t jj = ii + 1; jj < vv.size(); ++jj) { + // count intersections of all mesh pairs + ++VAMap[std::make_pair(vv[ii], vv[jj])]; + } + } + } + } + } + + // Find all the arcs, e.g. all the pair of meshes + SVA.clear(); + for (auto vi = std::begin(VAMap); vi != std::end(VAMap); ++vi) { + if (vi->second > 0) { + int m_s = vi->first.first; + int m_t = vi->first.second; + int area = vi->second; + SVA.push_back( OGArcInfo (m_s,m_t,area,float(area)/float(std::min(VM[m_s].area,VM[m_t].area)) )); + } + } + + // Compute Mesh Coverage + for (std::size_t i = 0; i < SVA.size(); ++i) { + VM[SVA[i].s].coverage += SVA[i].area; + VM[SVA[i].t].coverage += SVA[i].area; + } + + std::sort(std::begin(SVA), std::end(SVA)); + std::reverse(std::begin(SVA), std::end(SVA)); + } + + void ComputeUsefulMesh(FILE *elfp) { + + int mcnt = 0; + std::vector UpdArea(mn); + std::vector UpdCovg(mn); + + for (std::size_t m = 0; m < mn; ++m) { + + if (VM[m].used && VM[m].area > 0) { + mcnt++; + UpdCovg[m]=VM[m].coverage; + UpdArea[m]=VM[m].area; + } + } + + int sz = G.size(); + if (elfp) { + std::fprintf(elfp, "\n\nComputing Usefulness of Meshes of %i(on %i) meshes\n Og with %i / %i fill ratio %i max mesh per cell\n\n", mcnt, mn, TotalArea, sz, MaxCount); + std::fprintf(elfp, "\n"); + } + + int CumArea = 0; + + for (std::size_t m = 0; m < mn-1; ++m) { + + int best = max_element(std::begin(UpdArea), std::end(UpdArea)) - std::begin(UpdArea); + + CumArea += UpdArea[best]; + if (UpdCovg[best] < 0) break; + + // se era una mesh fuori del working group si salta tutto. + if (VM[best].area == 0) continue; + + if (elfp) { + fprintf(elfp, "%3i %3i %7i (%7i) %7i %5.2f %7i(%7i)\n", + m, best, UpdArea[best], VM[best].area, TotalArea - CumArea, + 100.0 - 100 * float(CumArea) / TotalArea, UpdCovg[best], VM[best].coverage); + } + + UpdArea[best] = -1; + UpdCovg[best] = -1; + + for (std::size_t i = 0; i < sz; ++i) { + + MeshCounter &mc = G.grid[i]; + + if (mc.IsSet(best)) { + + mc.UnSet(best); + + for (std::size_t j = 0; j < mn; ++j) { + if (mc.IsSet(j)) { + --UpdArea[j]; + UpdCovg[j]-=mc.Count(); + } + } + + mc.Clear(); + } + } + } + } + + void Dump(FILE *fp) { + + std::fprintf(fp, "Occupancy Grid\n"); + std::fprintf(fp, "grid of ~%i kcells: %d x %d x %d\n", G.size(), G.siz[0], G.siz[1], G.siz[2]); + std::fprintf(fp, "grid voxel size of %f %f %f\n", G.voxel[0], G.voxel[1], G.voxel[2]); + + std::fprintf(fp,"Computed %lu arcs for %i meshes\n", SVA.size(), mn); + + for (std::size_t i=0;i(8), VM[i].densityDistribution.size()); ++j) { + std::fprintf(fp," %3i ", VM[i].densityDistribution[j]); + } + + std::fprintf(fp,"\n"); + } + else { + std::fprintf(fp, "mesh %3lu ---- UNUSED\n", i); + } + } + + std::fprintf(fp, "Computed %lu Arcs :\n", SVA.size()); + + for (std::size_t i = 0; i < SVA.size() && SVA[i].norm_area > .1; ++i) { + std::fprintf(fp, "%4i -> %4i Area:%5i NormArea:%5.3f\n", SVA[i].s, SVA[i].t, SVA[i].area, SVA[i].norm_area); + } + + std::fprintf(fp, "End OG Dump\n"); + } + + void ComputeTotalArea() { + + using uint = unsigned int; + + int ccnt = 0; + MaxCount = 0; + + int sz = G.size(); + + for (int i = 0; i < sz; ++i) + + if (!G.grid[i].Empty()) { + + ccnt++; + if (G.grid[i].Count() > static_cast(MaxCount)) { + MaxCount = G.grid[i].Count(); + } + } + + TotalArea = ccnt; + } + + }; +} + +#endif //VCGLIB_OCCUPANCY_GRID_H diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 4dfb3963..6e2d3087 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -624,7 +624,7 @@ public: do { std::vector new_queue; - for (int i=0; iIsD()); diff --git a/vcg/complex/algorithms/parametrization/uv_utils.h b/vcg/complex/algorithms/parametrization/uv_utils.h index e93bcedf..82b2e8ec 100644 --- a/vcg/complex/algorithms/parametrization/uv_utils.h +++ b/vcg/complex/algorithms/parametrization/uv_utils.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; 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. * @@ -21,8 +21,8 @@ * * ****************************************************************************/ -#ifndef VCG_UV_UTILS -#define VCG_UV_UTILS +#ifndef VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H +#define VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H #include #include @@ -30,7 +30,7 @@ #include namespace vcg { -namespace tri{ +namespace tri { template class UV_Utils { @@ -44,7 +44,7 @@ class UV_Utils public: - ///calculate the area in UV space + /// calculate the area in UV space static ScalarType PerVertUVArea(MeshType &m) { FaceIterator fi; @@ -242,6 +242,7 @@ public: } } }; -} //End Namespace Tri -} // End Namespace vcg -#endif + +} // end Namespace tri +} // end Namespace vcg +#endif // VCG_COMPLEX_ALGORITHMS_PARAMETRIZATION_UV_UTILS_H diff --git a/vcg/complex/algorithms/point_matching_scale.h b/vcg/complex/algorithms/point_matching_scale.h index 2acfb2a1..ca14fe38 100644 --- a/vcg/complex/algorithms/point_matching_scale.h +++ b/vcg/complex/algorithms/point_matching_scale.h @@ -93,7 +93,8 @@ public: // rtm = rototranslation RotoTranslation rt; vcg::Matrix44d rtm; - memcpy(&rt._v[0],&x[1],6*sizeof(double)); + for (unsigned int i = 0; i < 6; ++i) + rt._v[i] = x[i+1]; rt.toMatrix(rtm); // res= scaling w.r.t. barycenter @@ -122,7 +123,8 @@ public: RotoTranslation rt; vcg::Matrix44d m; - memcpy(&rt._v[0],&x[1],6*sizeof(double)); + for (unsigned int i = 0; i < 6; ++i) + rt._v[i] = x[i+1]; rt.toMatrix(m); for(; i != mov->end(); ++i,++ifix) { diff --git a/vcg/complex/algorithms/point_sampling.h b/vcg/complex/algorithms/point_sampling.h index d5e711f8..4bd163c0 100644 --- a/vcg/complex/algorithms/point_sampling.h +++ b/vcg/complex/algorithms/point_sampling.h @@ -502,6 +502,18 @@ static unsigned int RandomInt(unsigned int i) return (SamplingRandomGenerator().generate(i)); } +class MarsenneTwisterURBG +{ +public: + typedef unsigned int result_type; + MarsenneTwisterURBG(result_type max){_max = max;} + static constexpr result_type min() {return 0;} + static constexpr result_type max() {return std::numeric_limits::max();} + result_type operator()() {return SamplingRandomGenerator().generate(_max);} +private: + result_type _max; +}; + // Returns a random number in the [0,1) real interval using the improved Marsenne-Twister method. static double RandomDouble01() { @@ -714,8 +726,9 @@ static void FillAndShuffleFacePointerVector(MeshType & m, std::vector &vertVec) @@ -726,8 +739,9 @@ static void FillAndShuffleVertexPointerVector(MeshType & m, std::vector +#include +#include #include #include @@ -71,46 +74,63 @@ namespace tri { } } - /** - Import a trianglemesh from a polygon mesh - **/ - static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm) - { - tri::RequirePolygonalMesh(pm); - std::vector points; + /** + * @brief Import a trianglemesh from a polygon mesh + * @param tm: output triangle mesh + * @param pm: input polygonal mesh + * @param birthFaces: a mapping that tells, for each face of the triangle mesh, + * which one is its birth face in the polygonal mesh. + */ + static void ImportFromPolyMesh(TriMeshType& tm, PolyMeshType& pm, std::vector& birthFaces) + { + birthFaces.clear(); + birthFaces.reserve(pm.FN()); //at least the same face number of the polymesh + tri::RequirePolygonalMesh(pm); + std::vector points; - // the vertices are the same, simply import them - PolyVertexIterator vi; - TriVertexIterator tvi = Allocator::AddVertices(tm,pm.vert.size()); - int cnt = 0; - for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt) - if(!(*vi).IsD()) (*tvi).ImportData(*vi); else tri::Allocator::DeleteVertex(tm,(*tvi)); + // the vertices are the same, simply import them + PolyVertexIterator vi; + TriVertexIterator tvi = Allocator::AddVertices(tm,pm.vert.size()); + int cnt = 0; + for(tvi = tm.vert.begin(),vi = pm.vert.begin(); tvi != tm.vert.end(); ++tvi,++vi,++cnt) + if(!(*vi).IsD()) (*tvi).ImportData(*vi); else tri::Allocator::DeleteVertex(tm,(*tvi)); - for(PolyFaceIterator fi = pm.face.begin(); fi != pm.face.end(); ++fi) - { - if(!((*fi).IsD())){ - points.clear(); - for(int i = 0; i < (*fi).VN(); ++i) { - typename PolyMeshType::VertexType * v = (*fi).V(i); - points.push_back(v->P()); - } - std::vector faces; - TessellatePlanarPolygon3(points,faces); - for(size_t i = 0; i::AddFace(tm, - tri::Index(pm,(*fi).V( faces[i+0] )), - tri::Index(pm,(*fi).V( faces[i+1] )), - tri::Index(pm,(*fi).V( faces[i+2] )) ); + for(PolyFaceIterator fi = pm.face.begin(); fi != pm.face.end(); ++fi) + { + if(!((*fi).IsD())){ + points.clear(); + for(int i = 0; i < (*fi).VN(); ++i) { + typename PolyMeshType::VertexType * v = (*fi).V(i); + points.push_back(v->P()); + } + std::vector faces; + TessellatePlanarPolygon3(points,faces); - tfi->ImportData(*fi); - // set the F flags - if( (faces[i ]+1)%points.size() != size_t(faces[i+1])) (*tfi).SetF(0); - if( (faces[i+1]+1)%points.size() != size_t(faces[i+2])) (*tfi).SetF(1); - if( (faces[i+2]+1)%points.size() != size_t(faces[i ])) (*tfi).SetF(2); - } - } - } - } + //all the faces we add in tm have as a birth face fi + birthFaces.insert(birthFaces.end(), faces.size()/3, tri::Index(pm, *fi)); + + for(size_t i = 0; i::AddFace( + tm, + tri::Index(pm,(*fi).V( faces[i+0] )), + tri::Index(pm,(*fi).V( faces[i+1] )), + tri::Index(pm,(*fi).V( faces[i+2] )) ); + + tfi->ImportData(*fi); + // set the F flags + if( (faces[i ]+1)%points.size() != size_t(faces[i+1])) (*tfi).SetF(0); + if( (faces[i+1]+1)%points.size() != size_t(faces[i+2])) (*tfi).SetF(1); + if( (faces[i+2]+1)%points.size() != size_t(faces[i ])) (*tfi).SetF(2); + } + } + } + } + + static void ImportFromPolyMesh(TriMeshType & tm, PolyMeshType & pm) + { + std::vector dummyVector; + ImportFromPolyMesh(tm, pm, dummyVector); + } /** @@ -141,8 +161,8 @@ namespace tri { { std::vector vs;// vertices of the polygon ExtractPolygon(&*tfi,vs); - if (vs.size() > 3) - std::reverse(vs.begin(), vs.end()); + if (vs.size() > 3) + std::reverse(vs.begin(), vs.end()); //now vs contains all the vertices of the polygon (still in the trimesh) if (vs.size()==0)continue; typename PolyMeshType::FaceIterator pfi = tri::Allocator::AddFaces(pm,1); diff --git a/vcg/complex/algorithms/polygonal_algorithms.h b/vcg/complex/algorithms/polygonal_algorithms.h index 7154278c..6d1807de 100644 --- a/vcg/complex/algorithms/polygonal_algorithms.h +++ b/vcg/complex/algorithms/polygonal_algorithms.h @@ -23,8 +23,8 @@ #ifndef __VCGLIB_POLY_MESH_ALGORITHM #define __VCGLIB_POLY_MESH_ALGORITHM -#include #include +#include #include #include #include @@ -1181,6 +1181,14 @@ public: for (int j=0;j3)continue; + for (int j=0;j Box3Type; + typedef typename MeshType::EdgeType EdgeType; + typedef typename MeshType::EdgeIterator EdgeIterator; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename MeshType::FaceIterator FaceIterator; + typedef typename MeshType::ConstFaceIterator ConstFaceIterator; + typedef typename MeshType::FaceContainer FaceContainer; + typedef typename MeshType::TetraType TetraType; + typedef typename MeshType::TetraPointer TetraPointer; + typedef typename MeshType::TetraIterator TetraIterator; + typedef typename MeshType::TetraContainer TetraContainer; + typedef typename vcg::Box3 Box3Type; - static void ComputePerVertexQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV) + static void ComputePerVertexQualityMinMax(const MeshType & m, ScalarType &minV, ScalarType &maxV) { std::pair pp = ComputePerVertexQualityMinMax(m); minV=pp.first; maxV=pp.second; } - static std::pair ComputePerVertexQualityMinMax(MeshType & m) + static std::pair ComputePerVertexQualityMinMax(const MeshType & m) { // assert(0); tri::RequirePerVertexQuality(m); - typename MeshType::template PerMeshAttributeHandle < std::pair > mmqH; - mmqH = tri::Allocator::template GetPerMeshAttribute >(m,"minmaxQ"); + /** Please if you need to create an attribute called minmaxQ, implement an + explicit function that does it. This function should take a const Mesh. **/ + //typename MeshType::template PerMeshAttributeHandle < std::pair > mmqH; + //mmqH = tri::Allocator::template GetPerMeshAttribute >(m,"minmaxQ"); std::pair minmax = std::make_pair(std::numeric_limits::max(), -std::numeric_limits::max()); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) { if( (*vi).Q() < minmax.first) minmax.first = (*vi).Q(); if( (*vi).Q() > minmax.second) minmax.second = (*vi).Q(); } - mmqH() = minmax; + //mmqH() = minmax; return minmax; } - static void ComputePerFaceQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV) + static void ComputePerFaceQualityMinMax(const MeshType & m, ScalarType &minV, ScalarType &maxV) { std::pair pp = ComputePerFaceQualityMinMax(m); minV=pp.first; maxV=pp.second; } - static std::pair ComputePerFaceQualityMinMax( MeshType & m) + static std::pair ComputePerFaceQualityMinMax( const MeshType & m) { tri::RequirePerFaceQuality(m); std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); - FaceIterator fi; + ConstFaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { @@ -141,12 +144,12 @@ public: return avgQ /= (ScalarType) m.TN(); } - static ScalarType ComputePerFaceQualityAvg(MeshType & m) + static ScalarType ComputePerFaceQualityAvg(const MeshType & m) { tri::RequirePerFaceQuality(m); ScalarType AvgQ = 0; - FaceIterator fi; + ConstFaceIterator fi; size_t num=0; for(fi = m.face.begin(); fi != m.face.end(); ++fi) { @@ -221,11 +224,11 @@ public: Works for any triangulated model (no problem with open, nonmanifold selfintersecting models). Useful for computing the barycenter of 2D planar figures. */ - static Point3 ComputeShellBarycenter(MeshType & m) + static Point3 ComputeShellBarycenter(const MeshType & m) { Point3 barycenter(0,0,0); ScalarType areaSum=0; - FaceIterator fi; + ConstFaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { @@ -264,11 +267,11 @@ public: return area/ScalarType(2.0); } - static ScalarType ComputePolyMeshArea(MeshType & m) + static ScalarType ComputePolyMeshArea(const MeshType & m) { ScalarType area=0; - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) area += PolyArea(*fi); @@ -293,26 +296,32 @@ public: return sum; } - static void ComputePerVertexQualityDistribution(MeshType & m, Distribution & h, bool selectionOnly = false) // V1.0 + static void ComputePerVertexQualityDistribution(const MeshType & m, Distribution & h, bool selectionOnly = false) // V1.0 { tri::RequirePerVertexQuality(m); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + h.Clear(); + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { - assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*vi).Q()); + if(!math::IsNAN((*vi).Q())) + h.Add((*vi).Q()); + else + assert( "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); } } - static void ComputePerFaceQualityDistribution( MeshType & m, Distribution &h, + static void ComputePerFaceQualityDistribution( const MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 { tri::RequirePerFaceQuality(m); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + h.Clear(); + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ) { - assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*fi).Q()); + if(!math::IsNAN((*fi).Q())) + h.Add((*fi).Q()); + else + assert( "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); } } @@ -345,27 +354,27 @@ public: }); } - static void ComputePerFaceQualityHistogram( MeshType & m, Histogram &h, bool selectionOnly=false,int HistSize=10000 ) + static void ComputePerFaceQualityHistogram( const MeshType & m, Histogram &h, bool selectionOnly=false,int HistSize=10000 ) { tri::RequirePerFaceQuality(m); std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m); h.Clear(); h.SetRange( minmax.first,minmax.second, HistSize ); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + for(ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ){ assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); h.Add((*fi).Q()); } } - static void ComputePerVertexQualityHistogram( MeshType & m, Histogram &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 + static void ComputePerVertexQualityHistogram( const MeshType & m, Histogram &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 { tri::RequirePerVertexQuality(m); std::pair minmax = ComputePerVertexQualityMinMax(m); h.Clear(); h.SetRange( minmax.first,minmax.second, HistSize); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); @@ -381,7 +390,7 @@ public: { std::vector QV; QV.reserve(m.vn); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) QV.push_back((*vi).Q()); std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end()); @@ -391,7 +400,7 @@ public: h.Clear(); h.SetRange(newmin, newmax, HistSize*50); - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + for(ConstVertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) h.Add((*vi).Q()); } diff --git a/vcg/complex/algorithms/update/curvature.h b/vcg/complex/algorithms/update/curvature.h index 5b9a5364..e61e2ce8 100644 --- a/vcg/complex/algorithms/update/curvature.h +++ b/vcg/complex/algorithms/update/curvature.h @@ -400,7 +400,6 @@ For further details, please, refer to: \n static void MeanAndGaussian(MeshType & m) { tri::RequireFFAdjacency(m); - tri::RequirePerVertexCurvature(m); float area0, area1, area2, angle0, angle1, angle2; FaceIterator fi; @@ -411,13 +410,16 @@ static void MeanAndGaussian(MeshType & m) SimpleTempData TDContr(m.vert); vcg::tri::UpdateNormal::PerVertexNormalized(m); + auto KH = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KH")); + auto KG = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KG")); + //Compute AreaMix in H (vale anche per K) for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD()) { (TDAreaPtr)[*vi].A = 0.0; (TDContr)[*vi] =typename MeshType::CoordType(0.0,0.0,0.0); - (*vi).Kh() = 0.0; - (*vi).Kg() = (float)(2.0 * M_PI); + KH[*vi] = 0.0; + KG[*vi] = (ScalarType)(2.0 * M_PI); } for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD()) @@ -482,10 +484,10 @@ static void MeanAndGaussian(MeshType & m) TDContr[(*fi).V(0)] += ( e20v * (1.0/tan(angle1)) - e01v * (1.0/tan(angle2)) ) / 4.0; TDContr[(*fi).V(1)] += ( e01v * (1.0/tan(angle2)) - e12v * (1.0/tan(angle0)) ) / 4.0; TDContr[(*fi).V(2)] += ( e12v * (1.0/tan(angle0)) - e20v * (1.0/tan(angle1)) ) / 4.0; - - (*fi).V(0)->Kg() -= angle0; - (*fi).V(1)->Kg() -= angle1; - (*fi).V(2)->Kg() -= angle2; + + KG[(*fi).V(0)] -= angle0; + KG[(*fi).V(1)] -= angle1; + KG[(*fi).V(2)] -= angle2; for(int i=0;i<3;i++) @@ -501,7 +503,7 @@ static void MeanAndGaussian(MeshType & m) hp1.FlipV(); hp1.NextB(); e2=hp1.v->cP() - hp.v->cP(); - (*fi).V(i)->Kg() -= math::Abs(Angle(e1,e2)); + KG[(*fi).V(i)] -= math::Abs(Angle(e1,e2)); } } } @@ -510,13 +512,13 @@ static void MeanAndGaussian(MeshType & m) { if((TDAreaPtr)[*vi].A<=std::numeric_limits::epsilon()) { - (*vi).Kh() = 0; - (*vi).Kg() = 0; + KH[(*vi)] = 0; + KG[(*vi)] = 0; } else { - (*vi).Kh() = (((TDContr)[*vi].dot((*vi).cN())>0)?1.0:-1.0)*((TDContr)[*vi] / (TDAreaPtr) [*vi].A).Norm(); - (*vi).Kg() /= (TDAreaPtr)[*vi].A; + KH[(*vi)] = (((TDContr)[*vi].dot((*vi).cN())>0)?1.0:-1.0)*((TDContr)[*vi] / (TDAreaPtr) [*vi].A).Norm(); + KG[(*vi)] /= (TDAreaPtr)[*vi].A; } } } @@ -526,78 +528,86 @@ static void MeanAndGaussian(MeshType & m) /** The function uses the VF adiacency to walk around the vertex. - \return It will return the voronoi area around the vertex. If (norm == true) the mean and the gaussian curvature are normalized. - Based on the paper "Optimizing 3d triangulations using discrete curvature analysis" - */ - - static float ComputeSingleVertexCurvature(VertexPointer v, bool norm = true) + + Based on the paper + "Optimizing 3d triangulations using discrete curvature analysis" + it compute an approximation of the gaussian and of the absolute mean curvature + */ +static void PerVertexAbsoluteMeanAndGaussian(MeshType & m) +{ + tri::RequireVFAdjacency(m); + tri::RequireCompactness(m); + const bool areaNormalize = true; + const bool barycentricArea=false; + auto KH = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KH")); + auto KG = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KG")); + int faceCnt=0; + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) { + VertexPointer v=&*vi; VFIteratorType vfi(v); - float A = 0; + ScalarType A = 0; - v->Kh() = 0; - v->Kg() = 2 * M_PI; + KH[v] = 0; + ScalarType AngleDefect = (ScalarType)(2.0 * M_PI);; while (!vfi.End()) { - if (!vfi.F()->IsD()) { + faceCnt++; FacePointer f = vfi.F(); CoordType nf = TriangleNormal(*f); int i = vfi.I(); VertexPointer v0 = f->V0(i), v1 = f->V1(i), v2 = f->V2(i); + assert (v==v0); - float ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P() )); - float ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P() )); - float ang2 = M_PI - ang0 - ang1; + ScalarType ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P() )); + ScalarType ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P() )); + ScalarType ang2 = M_PI - ang0 - ang1; - float s01 = SquaredDistance(v1->P(), v0->P()); - float s02 = SquaredDistance(v2->P(), v0->P()); + ScalarType s01 = SquaredDistance(v1->P(), v0->P()); + ScalarType s02 = SquaredDistance(v2->P(), v0->P()); // voronoi cell of current vertex - if (ang0 >= M_PI/2) - A += (0.5f * DoubleArea(*f) - (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 ); - else if (ang1 >= M_PI/2) - A += (s01 * tan(ang0)) / 8.0; - else if (ang2 >= M_PI/2) - A += (s02 * tan(ang0)) / 8.0; - else // non obctuse triangle - A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0; - + if(barycentricArea) + A+=vcg::DoubleArea(*f)/6.0; + else + { + if (ang0 >= M_PI/2) + A += (0.5f * DoubleArea(*f) - (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 ); + else if (ang1 >= M_PI/2) + A += (s01 * tan(ang0)) / 8.0; + else if (ang2 >= M_PI/2) + A += (s02 * tan(ang0)) / 8.0; + else // non obctuse triangle + A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0; + } // gaussian curvature update - v->Kg() -= ang0; + AngleDefect -= ang0; // mean curvature update - ang1 = math::Abs(Angle(nf, v1->N())); - ang2 = math::Abs(Angle(nf, v2->N())); - v->Kh() += ( (math::Sqrt(s01) / 2.0) * ang1 + - (math::Sqrt(s02) / 2.0) * ang2 ); - } - + // Note that the standard abs mean curvature approximation would require + // to sum all the edges*diehedralAngle. Here with just VF adjacency + // we make a rough approximation that 1/2 of the edge len plus something + // that is half of the diedral angle + ang1 = math::Abs(Angle(nf, v1->N()+v0->N())); + ang2 = math::Abs(Angle(nf, v2->N()+v0->N())); + KH[v] += math::Sqrt(s01)*ang1 + math::Sqrt(s02)*ang2 ; ++vfi; } - v->Kh() /= 4.0f; + KH[v] /= 4.0; - if(norm) { + if(areaNormalize) { if(A <= std::numeric_limits::epsilon()) { - v->Kh() = 0; - v->Kg() = 0; + KH[v] = 0; + KG[v] = 0; } else { - v->Kh() /= A; - v->Kg() /= A; + KH[v] /= A; + KG[v] = AngleDefect / A; } } - - return A; - } - - static void PerVertex(MeshType & m) - { - tri::RequireVFAdjacency(m); - - for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) - ComputeSingleVertexCurvature(&*vi,false); } +} diff --git a/vcg/complex/algorithms/update/curvature_fitting.h b/vcg/complex/algorithms/update/curvature_fitting.h index 27e96182..332b3d36 100644 --- a/vcg/complex/algorithms/update/curvature_fitting.h +++ b/vcg/complex/algorithms/update/curvature_fitting.h @@ -372,8 +372,8 @@ class Quadric { assert(VV.size() >= 5); Eigen::MatrixXd A(VV.size(),5); - Eigen::MatrixXd b(VV.size(),1); - Eigen::MatrixXd sol(5,1); + Eigen::VectorXd b(VV.size()); + Eigen::VectorXd sol(5); for(unsigned int c=0; c < VV.size(); ++c) { @@ -580,12 +580,12 @@ class Quadric c_val = -c_val; CoordType v1, v2; - v1[0] = c_vec[0]; - v1[1] = c_vec[1]; + v1[0] = c_vec(0); + v1[1] = c_vec(1); v1[2] = d * v1[0] + e * v1[1]; - v2[0] = c_vec[2]; - v2[1] = c_vec[3]; + v2[0] = c_vec(2); + v2[1] = c_vec(3); v2[2] = d * v2[0] + e * v2[1]; v1 = v1.Normalize(); @@ -619,9 +619,8 @@ class Quadric - static void updateCurvatureLocal (MeshType & mesh, float radiusSphere) + static void updateCurvatureLocal (MeshType & mesh, float radiusSphere, vcg::CallBackPos * cb = NULL) { - bool verbose = false; bool projectionPlaneCheck = true; int vertexesPerFit = 0; @@ -631,24 +630,15 @@ class Quadric { std::vector vv; std::vector vvtmp; - - int count; - if (verbose && !((count = (vi - mesh.vert.begin())) % 1000)) - printf ("vertex %d of %d\n",count,mesh.vert.size()); - - // if (kRing != 0) - // expandRing (&*vi, kRing, 5, &vv); - // else + if (cb && ((i%1024)==00)) { + (*cb)(int(100.0f * (float)i / (float)mesh.vn),"Vertices Analysis"); + } expandSphereLocal (mesh, &*vi, radiusSphere, 5, &vv); assert (vv.size() >= 5); CoordType ppn; - // if (averageNormalMode) - // //ppn = (*vi).N(); getAverageNormal (&*vi, vv, &ppn); - // else - // getProjPlaneNormal (&*vi, vv, &ppn); if (projectionPlaneCheck) { @@ -659,33 +649,12 @@ class Quadric } vvtmp.clear(); - - // if (montecarloMaxVertexNum) - // { - // //printf ("P: %d\n", vv.size()); - // vvtmp.reserve (vv.size ()); - // //printf ("TP: %d\n", vvtmp.size()); - // applyMontecarlo (montecarloMaxVertexNum, vv, &vvtmp); - // //printf ("TD: %d\n", vvtmp.size()); - // vv = vvtmp; - // //printf ("D: %d\n", vv.size()); - // //printf ("\n"); - // } - assert (vv.size() >= 5); std::vector ref; computeReferenceFramesLocal (&*vi, ppn, &ref); - /* - printf ("%lf %lf %lf - %lf %lf %lf - %lf %lf %lf\n", - ref[0][0], ref[0][1], ref[0][2], - ref[1][0], ref[1][1], ref[1][2], - ref[2][0], ref[2][1], ref[2][2]); - */ - vertexesPerFit += vv.size(); - //printf ("size: %d\n", vv.size()); QuadricLocal q; fitQuadricLocal (&*vi, ref, vv, &q); @@ -694,9 +663,7 @@ class Quadric } - //if (verbose) - //printf ("average vertex num in each fit: %f, total %d, vn %d\n", ((float) vertexesPerFit) / mesh.vn, vertexesPerFit, mesh.vn); - if (verbose) + if (cb) printf ("average vertex num in each fit: %f\n", ((float) vertexesPerFit) / mesh.vn); } diff --git a/vcg/complex/algorithms/update/quality.h b/vcg/complex/algorithms/update/quality.h index 728c6e5f..51e8237b 100644 --- a/vcg/complex/algorithms/update/quality.h +++ b/vcg/complex/algorithms/update/quality.h @@ -224,6 +224,15 @@ static void VertexFromAttributeHandle(MeshType &m, typename MeshType::template P (*vi).Q()=VertexQualityType(h[vi]); } +static void VertexFromAttributeName(MeshType &m, const std::string &AttrName) +{ + tri::RequirePerVertexQuality(m); + auto KH = tri::Allocator:: template FindPerVertexAttribute (m, AttrName); + if(!tri::Allocator::template IsValidHandle(m, KH)) throw vcg::MissingPreconditionException("Required Attribute is non existent"); + for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) + (*vi).Q() = KH[vi]; +} + template static void FaceFromAttributeHandle(MeshType &m, typename MeshType::template PerFaceAttributeHandle &h) { @@ -232,6 +241,15 @@ static void FaceFromAttributeHandle(MeshType &m, typename MeshType::template Per (*fi).Q() =FaceQualityType(h[fi]); } +static void FaceFromAttributeName(MeshType &m, const std::string &AttrName) +{ + tri::RequirePerFaceQuality(m); + auto KH = tri::Allocator:: template FindPerFaceAttribute (m, AttrName); + if(!tri::Allocator::template IsValidHandle(m, KH)) throw vcg::MissingPreconditionException("Required Attribute is non existent"); + for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) + (*fi).Q() =FaceQualityType(KH[fi]); +} + static void FaceFromVertex( MeshType &m) { tri::RequirePerFaceQuality(m); @@ -252,23 +270,7 @@ static void VertexFromPlane(MeshType &m, const Plane3 &pl) (*vi).Q() =SignedDistancePlanePoint(pl,(*vi).cP()); } -static void VertexFromGaussianCurvatureHG(MeshType &m) -{ - tri::RequirePerVertexQuality(m); - tri::RequirePerVertexCurvature(m); - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) - (*vi).Q() = (*vi).Kg(); -} - -static void VertexFromMeanCurvatureHG(MeshType &m) -{ - tri::RequirePerVertexQuality(m); - tri::RequirePerVertexCurvature(m); - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) - (*vi).Q() = (*vi).Kh(); -} - -static void VertexFromGaussianCurvatureDir(MeshType &m) +static void VertexGaussianFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); @@ -276,21 +278,21 @@ static void VertexFromGaussianCurvatureDir(MeshType &m) (*vi).Q() = (*vi).K1()*(*vi).K2(); } -static void VertexFromMeanCurvatureDir(MeshType &m) +static void VertexMeanFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q() = ((*vi).K1()+(*vi).K2())/2.0f; } -static void VertexFromMinCurvatureDir(MeshType &m) +static void VertexMinCurvFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q() = (*vi).K1(); } -static void VertexFromMaxCurvatureDir(MeshType &m) +static void VertexMaxCurvFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); @@ -299,7 +301,7 @@ static void VertexFromMaxCurvatureDir(MeshType &m) } /** - * @brief VertexFromShapeIndexCurvatureDir + * @brief VertexShapeIndexFromCurvatureDir * Compute from the current Curvature Direction the Shape Index S as defined by [Koenderink 1992] * and store it in the per-vertex Quality. * S = 2/pi atan(k1+k2/k1-k2) @@ -309,7 +311,7 @@ static void VertexFromMaxCurvatureDir(MeshType &m) * Image and vision computing, 10(8):557–565, 1992. */ -static void VertexFromShapeIndexCurvatureDir(MeshType &m) +static void VertexShapeIndexFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); @@ -322,7 +324,7 @@ static void VertexFromShapeIndexCurvatureDir(MeshType &m) } } /** - * @brief VertexFromCurvednessCurvatureDir + * @brief VertexCurvednessFromCurvatureDir * Compute from the current Curvature Direction the Curvedness as defined by [Koenderink 1992] * and store it in the per-vertex Quality. * C = Sqrt((k1*k1+k2*k2)/2.0) @@ -331,7 +333,7 @@ static void VertexFromShapeIndexCurvatureDir(MeshType &m) * Surface shape and curvature scales. * Image and vision computing, 10(8):557–565, 1992. */ -static void VertexFromCurvednessCurvatureDir(MeshType &m) +static void VertexCurvednessFromCurvatureDir(MeshType &m) { tri::RequirePerVertexQuality(m); tri::RequirePerVertexCurvatureDir(m); @@ -361,17 +363,17 @@ static void VertexFromCurvednessCurvatureDir(MeshType &m) * N Dyn, K Hormann, SJ Kim, D Levin - Mathematical Methods for Curves and Surfaces: Oslo, 2000 */ -static void VertexFromAbsoluteCurvature(MeshType &m) +static void VertexAbsoluteCurvatureFromHGAttribute(MeshType &m) { tri::RequirePerVertexQuality(m); - tri::RequirePerVertexCurvature(m); - VertexIterator vi; - for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) + auto KH = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KH")); + auto KG = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KG")); + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { - if((*vi).Kg() >= 0) - (*vi).Q() = math::Abs( 2*(*vi).Kh() ); + if(KG[vi] >= 0) + (*vi).Q() = math::Abs( 2.0*KH[vi] ); else - (*vi).Q() = 2*math::Sqrt(math::Abs( (*vi).Kh()*(*vi).Kh() - (*vi).Kg())); + (*vi).Q() = 2*math::Sqrt(math::Abs( KH[vi]*KH[vi] - KG[vi])); } } @@ -382,13 +384,13 @@ static void VertexFromAbsoluteCurvature(MeshType &m) * Improved curvature estimation for watershed segmentation of 3-dimensional meshes * S Pulla, A Razdan, G Farin - Arizona State University, Tech. Rep, 2001 */ -static void VertexFromRMSCurvature(MeshType &m) +static void VertexRMSCurvatureFromHGAttribute(MeshType &m) { tri::RequirePerVertexQuality(m); - tri::RequirePerVertexCurvature(m); - VertexIterator vi; - for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) - (*vi).Q() = math::Sqrt(math::Abs( 4*(*vi).Kh()*(*vi).Kh() - 2*(*vi).Kg())); + auto KH = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KH")); + auto KG = vcg::tri::Allocator:: template GetPerVertexAttribute (m, std::string("KG")); + for(auto vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) + (*vi).Q() = math::Sqrt(math::Abs( 4*KH[vi]*KH[vi] - 2*KG[vi])); } /* diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index b4b337d6..ee96b2c9 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -2267,8 +2267,10 @@ public: for(size_t i = 0; i < m.vert.size(); ++i){ ATTR_TYPE * dest = &(*_handle)[i]; char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + ATTR_TYPE* attrptr = (ATTR_TYPE*)ptr; + *dest = attrptr[i * pa._sizeof ]; + //memcpy((void*)dest , + //(void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); } // remove the padded container @@ -2294,8 +2296,10 @@ public: for(size_t i = 0; i < m.edge.size(); ++i){ ATTR_TYPE * dest = &(*_handle)[i]; char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + ATTR_TYPE* attrptr = (ATTR_TYPE*)ptr; + *dest = attrptr[i * pa._sizeof ]; + //memcpy((void*)dest , + //(void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); } // remove the padded container @@ -2322,8 +2326,10 @@ public: for(size_t i = 0; i < m.face.size(); ++i){ ATTR_TYPE * dest = &(*_handle)[i]; char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + ATTR_TYPE* attrptr = (ATTR_TYPE*)ptr; + *dest = attrptr[i * pa._sizeof ]; + //memcpy((void*)dest , + // (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); } // remove the padded container @@ -2352,8 +2358,10 @@ public: { ATTR_TYPE *dest = &(*_handle)[i]; char *ptr = (char *)(((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void *)dest, - (void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); + ATTR_TYPE* attrptr = (ATTR_TYPE*)ptr; + *dest = attrptr[i * pa._sizeof ]; + //memcpy((void *)dest, + //(void *)&(ptr[i * pa._sizeof]), sizeof(ATTR_TYPE)); } // remove the padded container @@ -2376,8 +2384,11 @@ public: Attribute * _handle = new Attribute(); // copy the padded container in the new one - char * ptr = (char*)( ((Attribute *)pa._handle)->DataBegin()); - memcpy((void*)_handle->DataBegin() ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); + ATTR_TYPE* dest = (ATTR_TYPE*)_handle->DataBegin(); + char* ptr = (char*)( ((Attribute *)pa._handle)->DataBegin()); + ATTR_TYPE* attrptr = (ATTR_TYPE*)ptr; + *dest = *attrptr; + //memcpy((void*)dest ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); // remove the padded container delete ( (Attribute *) pa._handle); diff --git a/vcg/complex/append.h b/vcg/complex/append.h index c2db7433..ae040b78 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -264,215 +264,7 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, tri::UpdateSelection::VertexFromFaceLoose(mr,true); } - // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr - // and build the remapping for all - - Remap remap; - - // vertex - remap.vert.resize(mr.vert.size(), Remap::InvalidIndex()); - VertexIteratorLeft vp; - size_t svn = UpdateSelection::VertexCount(mr); - if(selected) - vp=Allocator::AddVertices(ml,int(svn)); - else - vp=Allocator::AddVertices(ml,mr.vn); - - for(VertexIteratorRight vi=mr.vert.begin(); vi!=mr.vert.end(); ++vi) - { - if(!(*vi).IsD() && (!selected || (*vi).IsS())) - { - size_t ind=Index(mr,*vi); - remap.vert[ind]=int(Index(ml,*vp)); - ++vp; - } - } - // edge - remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); - EdgeIteratorLeft ep; - size_t sen = UpdateSelection::EdgeCount(mr); - if(selected) ep=Allocator::AddEdges(ml,sen); - else ep=Allocator::AddEdges(ml,mr.en); - - for(EdgeIteratorRight ei=mr.edge.begin(); ei!=mr.edge.end(); ++ei) - if(!(*ei).IsD() && (!selected || (*ei).IsS())){ - size_t ind=Index(mr,*ei); - remap.edge[ind]=int(Index(ml,*ep)); - ++ep; - } - - // face - remap.face.resize(mr.face.size(), Remap::InvalidIndex()); - FaceIteratorLeft fp; - size_t sfn = UpdateSelection::FaceCount(mr); - if(selected) fp=Allocator::AddFaces(ml,sfn); - else fp=Allocator::AddFaces(ml,mr.fn); - - for(FaceIteratorRight fi=mr.face.begin(); fi!=mr.face.end(); ++fi) - if(!(*fi).IsD() && (!selected || (*fi).IsS())){ - size_t ind=Index(mr,*fi); - remap.face[ind]=int(Index(ml,*fp)); - ++fp; - } - - // hedge - remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); - for(HEdgeIteratorRight hi=mr.hedge.begin(); hi!=mr.hedge.end(); ++hi) - if(!(*hi).IsD() && (!selected || (*hi).IsS())){ - size_t ind=Index(mr,*hi); - assert(remap.hedge[ind]==Remap::InvalidIndex()); - HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); - (*hp).ImportData(*(hi)); - remap.hedge[ind]=Index(ml,*hp); - } - - remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); - for (TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if (!(*ti).IsD() && (!selected || (*ti).IsS())) { - size_t idx = Index(mr, *ti); - assert (remap.tetra[idx] == Remap::InvalidIndex()); - TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); - (*tp).ImportData(*ti); - remap.tetra[idx] = Index(ml, *tp); - } - - // phase 2. - // copy data from mr to its corresponding elements in ml and adjacencies - - // vertex - for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi) - if( !(*vi).IsD() && (!selected || (*vi).IsS())){ - ml.vert[remap.vert[Index(mr,*vi)]].ImportData(*vi); - if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,*vi)]],*vi,remap); - } - - // edge - for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei) - if(!(*ei).IsD() && (!selected || (*ei).IsS())){ - ml.edge[remap.edge[Index(mr,*ei)]].ImportData(*ei); - // Edge to Vertex Adj - EdgeLeft &el = ml.edge[remap.edge[Index(mr,*ei)]]; - if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ - el.V(0) = &ml.vert[remap.vert[Index(mr,ei->cV(0))]]; - el.V(1) = &ml.vert[remap.vert[Index(mr,ei->cV(1))]]; - } - if(adjFlag) ImportEdgeAdj(ml,mr,el,*ei,remap); - } - - // face - const size_t textureOffset = ml.textures.size(); - bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); - for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi) - if(!(*fi).IsD() && (!selected || (*fi).IsS())) - { - FaceLeft &fl = ml.face[remap.face[Index(mr,*fi)]]; - fl.Alloc(fi->VN()); - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < fl.VN(); ++i) - fl.V(i) = &ml.vert[remap.vert[Index(mr,fi->cV(i))]]; - } - fl.ImportData(*fi); - if(WTFlag) - for(int i = 0; i < fl.VN(); ++i) - fl.WT(i).n() += short(textureOffset); - if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,*fi)]],*fi,remap); - - } - - // hedge - for(HEdgeIteratorRight hi=mr.hedge.begin();hi!=mr.hedge.end();++hi) - if(!(*hi).IsD() && (!selected || (*hi).IsS())){ - ml.hedge[remap.hedge[Index(mr,*hi)]].ImportData(*hi); - ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected); - } - - //tetra - for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti) - if(!(*ti).IsD() && (!selected || (*ti).IsS())) - { - TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,*ti)]]; - - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < 4; ++i) - tl.V(i) = &ml.vert[remap.vert[Index(mr,ti->cV(i))]]; - } - tl.ImportData(*ti); - if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,*ti)]], *ti, remap); - - } - - // phase 3. - // take care of other per mesh data: textures, attributes - - // At the end concatenate the vector with texture names. - ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); - - // Attributes. Copy only those attributes that are present in both meshes - // Two attributes in different meshes are considered the same if they have the same - // name and the same type. This may be deceiving because they could in fact have - // different semantic, but this is up to the developer. - // If the left mesh has attributes that are not in the right mesh, their values for the elements - // of the right mesh will be uninitialized - - unsigned int id_r; - typename std::set< PointerToAttribute >::iterator al, ar; - - // per vertex attributes - for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.vert_attr.find(*al); - if(ar!= mr.vert_attr.end()){ - id_r = 0; - for(VertexIteratorRight vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) - if( !(*vi).IsD() && (!selected || (*vi).IsS())) - (*al)._handle->CopyValue(remap.vert[Index(mr,*vi)], id_r, (*ar)._handle); - } - } - - // per edge attributes - for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.edge_attr.find(*al); - if(ar!= mr.edge_attr.end()){ - id_r = 0; - for(EdgeIteratorRight ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) - if( !(*ei).IsD() && (!selected || (*ei).IsS())) - (*al)._handle->CopyValue(remap.edge[Index(mr,*ei)], id_r, (*ar)._handle); - } - } - - // per face attributes - for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.face_attr.find(*al); - if(ar!= mr.face_attr.end()){ - id_r = 0; - for(FaceIteratorRight fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) - if( !(*fi).IsD() && (!selected || (*fi).IsS())) - (*al)._handle->CopyValue(remap.face[Index(mr,*fi)], id_r, (*ar)._handle); - } - } - - // per tetra attributes - for(al = ml.tetra_attr.begin(); al != ml.tetra_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.tetra_attr.find(*al); - if(ar!= mr.tetra_attr.end()){ - id_r = 0; - for(TetraIteratorRight ti = mr.tetra.begin(); ti != mr.tetra.end(); ++ti, ++id_r) - if( !(*ti).IsD() && (!selected || (*ti).IsS())) - (*al)._handle->CopyValue(remap.tetra[Index(mr, *ti)], id_r, (*ar)._handle); - } - } - // per mesh attributes - // if both ml and mr have an attribute with the same name, no action is done - // if mr has an attribute that is NOT present in ml, the attribute is added to ml - //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar) - // if(!(*ar)._name.empty()){ - // al = ml.mesh_attr.find(*ar); - // if(al== ml.mesh_attr.end()) - // //... - // } + MeshAppendConst(ml, mr, selected, adjFlag); } static void Mesh(MeshLeft &ml, @@ -722,180 +514,231 @@ static void Mesh(MeshLeft &ml, * or, use the Mesh function that takes a non-const Right Mesh argument. */ static void MeshAppendConst( - MeshLeft& ml, - const ConstMeshRight& mr, - const bool selected = false, - const bool adjFlag = false) + MeshLeft& ml, + const ConstMeshRight& mr, + const bool selected = false, + const bool adjFlag = false) { - // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr - // and build the remapping for all + // phase 1. allocate on ml vert,edge,face, hedge to accomodat those of mr + // and build the remapping for all - Remap remap; + Remap remap; - // vertex - remap.vert.resize(mr.vert.size(), Remap::InvalidIndex()); - VertexIteratorLeft vp; - size_t svn = UpdateSelection::VertexCount(mr); - if(selected) - vp=Allocator::AddVertices(ml,int(svn)); - else - vp=Allocator::AddVertices(ml,mr.vn); - - ForEachVertex(mr, [&](const VertexRight& v) - { - if(!selected || v.IsS()) - { - size_t ind=Index(mr,v); - remap.vert[ind]=int(Index(ml,*vp)); - ++vp; + // vertex + remap.vert.resize(mr.vert.size(), Remap::InvalidIndex()); + VertexIteratorLeft vp; + if(selected){ + size_t svn = UpdateSelection::VertexCount(mr); + vp=Allocator::AddVertices(ml,int(svn)); } - }); - // edge - remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); - EdgeIteratorLeft ep; - size_t sen = UpdateSelection::EdgeCount(mr); - if(selected) ep=Allocator::AddEdges(ml,sen); - else ep=Allocator::AddEdges(ml,mr.en); + else + vp=Allocator::AddVertices(ml,mr.vn); - ForEachEdge(mr, [&](const EdgeRight& e) - { - if(!selected || e.IsS()){ - size_t ind=Index(mr,e); - remap.edge[ind]=int(Index(ml,*ep)); - ++ep; + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()) + { + size_t ind=Index(mr,v); + remap.vert[ind]=int(Index(ml,*vp)); + ++vp; + } + }); + // edge + remap.edge.resize(mr.edge.size(), Remap::InvalidIndex()); + EdgeIteratorLeft ep; + if(selected) { + size_t sen = UpdateSelection::EdgeCount(mr); + ep=Allocator::AddEdges(ml,sen); } - }); + else ep=Allocator::AddEdges(ml,mr.en); - // face - remap.face.resize(mr.face.size(), Remap::InvalidIndex()); - FaceIteratorLeft fp; - size_t sfn = UpdateSelection::FaceCount(mr); - if(selected) fp=Allocator::AddFaces(ml,sfn); - else fp=Allocator::AddFaces(ml,mr.fn); + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + size_t ind=Index(mr,e); + remap.edge[ind]=int(Index(ml,*ep)); + ++ep; + } + }); - ForEachFace(mr, [&](const FaceRight& f) - { - if(!selected || f.IsS()){ - size_t ind=Index(mr,f); - remap.face[ind]=int(Index(ml,*fp)); - ++fp; + // face + remap.face.resize(mr.face.size(), Remap::InvalidIndex()); + FaceIteratorLeft fp; + if(selected) { + size_t sfn = UpdateSelection::FaceCount(mr); + fp=Allocator::AddFaces(ml,sfn); } - }); + else fp=Allocator::AddFaces(ml,mr.fn); - // hedge - remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()){ + size_t ind=Index(mr,f); + remap.face[ind]=int(Index(ml,*fp)); + ++fp; + } + }); - ForEachHEdge(mr, [&](const HEdgeRight& he) - { - if(!selected || he.IsS()){ - size_t ind=Index(mr,he); - assert(remap.hedge[ind]==Remap::InvalidIndex()); - HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); - (*hp).ImportData(he); - remap.hedge[ind]=Index(ml,*hp); - } - }); + // hedge + remap.hedge.resize(mr.hedge.size(),Remap::InvalidIndex()); - remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + size_t ind=Index(mr,he); + assert(remap.hedge[ind]==Remap::InvalidIndex()); + HEdgeIteratorLeft hp = Allocator::AddHEdges(ml,1); + (*hp).ImportData(he); + remap.hedge[ind]=Index(ml,*hp); + } + }); - ForEachTetra(mr, [&](const TetraRight& t) - { - if (!selected || t.IsS()) { - size_t idx = Index(mr, t); - assert (remap.tetra[idx] == Remap::InvalidIndex()); - TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); - (*tp).ImportData(t); - remap.tetra[idx] = Index(ml, *tp); - } - }); + remap.tetra.resize(mr.tetra.size(), Remap::InvalidIndex()); - // phase 2. - // copy data from mr to its corresponding elements in ml and adjacencies + ForEachTetra(mr, [&](const TetraRight& t) + { + if (!selected || t.IsS()) { + size_t idx = Index(mr, t); + assert (remap.tetra[idx] == Remap::InvalidIndex()); + TetraIteratorLeft tp = Allocator::AddTetras(ml, 1); + (*tp).ImportData(t); + remap.tetra[idx] = Index(ml, *tp); + } + }); - // vertex - ForEachVertex(mr, [&](const VertexRight& v) - { - if(!selected || v.IsS()){ - ml.vert[remap.vert[Index(mr,v)]].ImportData(v); - if(adjFlag) ImportVertexAdj(ml,mr,ml.vert[remap.vert[Index(mr,v)]],v,remap); - } - }); + // phase 1.5 + // manage textures, creating a new one only when necessary + // (not making unuseful duplicates on append) and save a mapping - // edge - ForEachEdge(mr, [&](const EdgeRight& e) - { - if(!selected || e.IsS()){ - ml.edge[remap.edge[Index(mr,e)]].ImportData(e); - // Edge to Vertex Adj - EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; - if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ - el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; - el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; - } - if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); - } - }); + // for each texture in the right mesh, it maps it to the texture index in the + // left mesh + std::vector mappingTextures(mr.textures.size()); - // face - const size_t textureOffset = ml.textures.size(); - bool WTFlag = HasPerWedgeTexCoord(mr) && (textureOffset>0); - ForEachFace(mr, [&](const FaceRight& f) - { - if(!selected || f.IsS()) - { - FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; - fl.Alloc(f.VN()); - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < fl.VN(); ++i) - fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; - } - fl.ImportData(f); - if(WTFlag) - for(int i = 0; i < fl.VN(); ++i) - fl.WT(i).n() += short(textureOffset); - if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); + unsigned int baseMlT = ml.textures.size(); + for (unsigned int i = 0; i < mr.textures.size(); ++i) { + auto it = std::find(ml.textures.begin(), ml.textures.end(), mr.textures[i]); + //if the right texture does not exists in the left mesh + if (it == ml.textures.end()) { + //add the texture in the left mesh and create the mapping + mappingTextures[i] = baseMlT++; + ml.textures.push_back(mr.textures[i]); + } + else { + //the ith right texture will map in the texture found in the left mesh + mappingTextures[i] = it - ml.textures.begin(); + } + } + //ml.textures.insert(ml.textures.end(), mr.textures.begin(),mr.textures.end()); - } - }); + // phase 2. + // copy data from mr to its corresponding elements in ml and adjacencies - // hedge - ForEachHEdge(mr, [&](const HEdgeRight& he) - { - if(!selected || he.IsS()){ - ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); - ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); - } - }); + //vtexcoords - can copy only if they are enabled both on l and r + bool vertTexFlag = HasPerVertexTexCoord(ml) && HasPerVertexTexCoord(mr); - //tetra - ForEachTetra(mr, [&](const TetraRight& t) - { - if(!selected || t.IsS()) - { - TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; + // vertex + ForEachVertex(mr, [&](const VertexRight& v) + { + if(!selected || v.IsS()){ + VertexLeft &vl = ml.vert[remap.vert[Index(mr,v)]]; + vl.ImportData(v); + if(adjFlag) + ImportVertexAdj(ml,mr,vl,v,remap); + if (vertTexFlag){ + if (size_t(v.T().n()) < mappingTextures.size()) { + //standard case: the texture is contained in the mesh + vl.T().n() = mappingTextures[v.T().n()]; + } + else { + //the mesh has tex coords, but not the texture... + vl.T().n() = v.T().n(); + } + } + } + }); - if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ - for(int i = 0; i < 4; ++i) - tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; - } - tl.ImportData(t); - if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); + // edge + ForEachEdge(mr, [&](const EdgeRight& e) + { + if(!selected || e.IsS()){ + ml.edge[remap.edge[Index(mr,e)]].ImportData(e); + // Edge to Vertex Adj + EdgeLeft &el = ml.edge[remap.edge[Index(mr,e)]]; + if(HasEVAdjacency(ml) && HasEVAdjacency(mr)){ + el.V(0) = &ml.vert[remap.vert[Index(mr,e.cV(0))]]; + el.V(1) = &ml.vert[remap.vert[Index(mr,e.cV(1))]]; + } + if(adjFlag) ImportEdgeAdj(ml,mr,el,e,remap); + } + }); - } - }); + //ftexcoords - can copy only if they are enabled both on l and r + bool wedgeTexFlag = HasPerWedgeTexCoord(ml) && HasPerWedgeTexCoord(mr); - // phase 3. - // take care of other per mesh data: textures, attributes + // face + ForEachFace(mr, [&](const FaceRight& f) + { + if(!selected || f.IsS()) + { + FaceLeft &fl = ml.face[remap.face[Index(mr,f)]]; + fl.Alloc(f.VN()); + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < fl.VN(); ++i) + fl.V(i) = &ml.vert[remap.vert[Index(mr,f.cV(i))]]; + } + fl.ImportData(f); + if(wedgeTexFlag) { + for(int i = 0; i < 3; ++i){ + if (size_t(f.WT(i).n()) < mappingTextures.size()){ + //standard case: the texture is contained in the mesh + fl.WT(i).n() = mappingTextures[f.WT(i).n()]; + } + else { + //the mesh has tex coords, but not the texture... + fl.WT(i).n() = f.WT(i).n(); + } + } + } + if(adjFlag) ImportFaceAdj(ml,mr,ml.face[remap.face[Index(mr,f)]],f,remap); - // At the end concatenate the vector with texture names. - ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); + } + }); - // Attributes. Copy only those attributes that are present in both meshes - // Two attributes in different meshes are considered the same if they have the same - // name and the same type. This may be deceiving because they could in fact have - // different semantic, but this is up to the developer. - // If the left mesh has attributes that are not in the right mesh, their values for the elements - // of the right mesh will be uninitialized + // hedge + ForEachHEdge(mr, [&](const HEdgeRight& he) + { + if(!selected || he.IsS()){ + ml.hedge[remap.hedge[Index(mr,he)]].ImportData(he); + ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,he)]],he,remap,selected); + } + }); + + //tetra + ForEachTetra(mr, [&](const TetraRight& t) + { + if(!selected || t.IsS()) + { + TetraLeft &tl = ml.tetra[remap.tetra[Index(mr,t)]]; + + if(HasFVAdjacency(ml) && HasFVAdjacency(mr)){ + for(int i = 0; i < 4; ++i) + tl.V(i) = &ml.vert[remap.vert[Index(mr,t.cV(i))]]; + } + tl.ImportData(t); + if(adjFlag) ImportTetraAdj(ml, mr, ml.tetra[remap.tetra[Index(mr,t)]], t, remap); + + } + }); + + // phase 3. + // take care of other per mesh data: attributes + + // Attributes. Copy only those attributes that are present in both meshes + // Two attributes in different meshes are considered the same if they have the same + // name and the same type. This may be deceiving because they could in fact have + // different semantic, but this is up to the developer. + // If the left mesh has attributes that are not in the right mesh, their values for the elements + // of the right mesh will be uninitialized unsigned int id_r; typename std::set< PointerToAttribute >::iterator al, ar; @@ -968,40 +811,42 @@ static void MeshAppendConst( } } - // per mesh attributes - // if both ml and mr have an attribute with the same name, no action is done - // if mr has an attribute that is NOT present in ml, the attribute is added to ml - //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar) - // if(!(*ar)._name.empty()){ - // al = ml.mesh_attr.find(*ar); - // if(al== ml.mesh_attr.end()) - // //... - // } + // per mesh attributes + // if both ml and mr have an attribute with the same name, no action is done + // if mr has an attribute that is NOT present in ml, the attribute is added to ml + //for(ar = mr.mesh_attr.begin(); ar != mr.mesh_attr.end(); ++ar) + // if(!(*ar)._name.empty()){ + // al = ml.mesh_attr.find(*ar); + // if(al== ml.mesh_attr.end()) + // //... + // } } -/*! \brief Copy the second mesh over the first one. - The first mesh is destroyed. If requested only the selected elements are copied. -*/ +/** + * \brief Copy the second mesh over the first one. + * The first mesh is destroyed. If requested only the selected elements are copied. + */ static void MeshCopy(MeshLeft& ml, ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) { - ml.Clear(); - Mesh(ml,mr,selected,adjFlag); - ml.bbox.Import(mr.bbox); + ml.Clear(); + Mesh(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); } static void MeshCopyConst(MeshLeft& ml, const ConstMeshRight& mr, bool selected=false, const bool adjFlag = false) { - ml.Clear(); - MeshAppendConst(ml,mr,selected,adjFlag); - ml.bbox.Import(mr.bbox); + ml.Clear(); + MeshAppendConst(ml,mr,selected,adjFlag); + ml.bbox.Import(mr.bbox); } -/*! \brief %Append only the selected elements of second mesh to the first one. - - It is just a wrap of the main Append::Mesh() - */ +/** + * \brief %Append only the selected elements of second mesh to the first one. + * + * It is just a wrap of the main Append::Mesh() + */ static void Selected(MeshLeft& ml, ConstMeshRight& mr) { - Mesh(ml,mr,true); + Mesh(ml,mr,true); } }; // end of class Append diff --git a/vcg/complex/base.h b/vcg/complex/base.h index 88de7028..b59e26e6 100644 --- a/vcg/complex/base.h +++ b/vcg/complex/base.h @@ -29,6 +29,7 @@ #include +#include "exception.h" #include "used_types.h" namespace vcg { @@ -443,7 +444,7 @@ public: } /// destructor - ~TriMesh() + virtual ~TriMesh() { // ClearAttributes(); Clear(); @@ -481,13 +482,14 @@ public: face.clear(); edge.clear(); tetra.clear(); - // textures.clear(); - // normalmaps.clear(); + textures.clear(); + normalmaps.clear(); vn = 0; en = 0; fn = 0; hn = 0; tn = 0; + attrn = 0; imark = 0; C()=Color4b::Gray; } @@ -664,7 +666,6 @@ template < class VertexType> bool VertexVectorHasPerVertexColor (const std template < class VertexType> bool VertexVectorHasPerVertexMark (const std::vector &) { return VertexType::HasMark (); } template < class VertexType> bool VertexVectorHasPerVertexFlags (const std::vector &) { return VertexType::HasFlags (); } template < class VertexType> bool VertexVectorHasPerVertexRadius (const std::vector &) { return VertexType::HasRadius (); } -template < class VertexType> bool VertexVectorHasPerVertexCurvature (const std::vector &) { return VertexType::HasCurvature (); } template < class VertexType> bool VertexVectorHasPerVertexCurvatureDir(const std::vector &) { return VertexType::HasCurvatureDir(); } template < class VertexType> bool VertexVectorHasPerVertexTexCoord (const std::vector &) { return VertexType::HasTexCoord (); } @@ -674,7 +675,6 @@ template < class TriMeshType> bool HasPerVertexColor (const TriMeshType &m template < class TriMeshType> bool HasPerVertexMark (const TriMeshType &m) { return tri::VertexVectorHasPerVertexMark (m.vert); } template < class TriMeshType> bool HasPerVertexFlags (const TriMeshType &m) { return tri::VertexVectorHasPerVertexFlags (m.vert); } template < class TriMeshType> bool HasPerVertexRadius (const TriMeshType &m) { return tri::VertexVectorHasPerVertexRadius (m.vert); } -template < class TriMeshType> bool HasPerVertexCurvature (const TriMeshType &m) { return tri::VertexVectorHasPerVertexCurvature (m.vert); } template < class TriMeshType> bool HasPerVertexCurvatureDir(const TriMeshType &m) { return tri::VertexVectorHasPerVertexCurvatureDir(m.vert); } template < class TriMeshType> bool HasPerVertexTexCoord (const TriMeshType &m) { return tri::VertexVectorHasPerVertexTexCoord (m.vert); } @@ -875,7 +875,6 @@ template void RequirePerVertexColor (const MeshType &m) { template void RequirePerVertexMark (const MeshType &m) { if(!tri::HasPerVertexMark (m)) throw vcg::MissingComponentException("PerVertexMark "); } template void RequirePerVertexFlags (const MeshType &m) { if(!tri::HasPerVertexFlags (m)) throw vcg::MissingComponentException("PerVertexFlags "); } template void RequirePerVertexRadius (const MeshType &m) { if(!tri::HasPerVertexRadius (m)) throw vcg::MissingComponentException("PerVertexRadius "); } -template void RequirePerVertexCurvature (const MeshType &m) { if(!tri::HasPerVertexCurvature (m)) throw vcg::MissingComponentException("PerVertexCurvature "); } template void RequirePerVertexCurvatureDir(const MeshType &m) { if(!tri::HasPerVertexCurvatureDir(m)) throw vcg::MissingComponentException("PerVertexCurvatureDir"); } template void RequirePerVertexTexCoord (const MeshType &m) { if(!tri::HasPerVertexTexCoord (m)) throw vcg::MissingComponentException("PerVertexTexCoord "); } diff --git a/vcg/complex/used_types.h b/vcg/complex/used_types.h index 570dd1ce..61060a2b 100755 --- a/vcg/complex/used_types.h +++ b/vcg/complex/used_types.h @@ -119,6 +119,6 @@ struct _Face : public Face<_UsedTypes>{}; struct _Tetra : public TetraSimp<_UsedTypes>{}; struct _HEdge : public HEdge<_UsedTypes>{}; -}; +} #endif // USED_TYPES_H diff --git a/vcg/container/simple_temporary_data.h b/vcg/container/simple_temporary_data.h index 4e91c195..8fd50011 100644 --- a/vcg/container/simple_temporary_data.h +++ b/vcg/container/simple_temporary_data.h @@ -66,30 +66,34 @@ public: delete[] booldata; } - void reserve(size_t sz) - { - if (sz <= datareserve) - return; - bool *newdataLoc = new bool[sz]; - if (datasize != 0) - memcpy(newdataLoc, booldata, sizeof(bool) * sizeof(datasize)); - std::swap(booldata, newdataLoc); - if (newdataLoc != 0) - delete[] newdataLoc; - datareserve = sz; - } + void reserve(size_t sz) + { + if (sz <= datareserve) + return; + bool* newdataLoc = new bool[sz]; + if (datasize != 0) { + std::copy(booldata, booldata+datasize, newdataLoc); + // memcpy(newdataLoc, booldata, sizeof(bool) * sizeof(datasize)); + } - void resize(size_t sz) - { - int oldDatasize = datasize; - if (sz <= oldDatasize) - return; - if (sz > datareserve) - reserve(sz); - datasize = sz; - memset(&booldata[oldDatasize], 0, datasize - oldDatasize); - } - void push_back(const bool &v) + std::swap(booldata, newdataLoc); + if (newdataLoc != 0) + delete[] newdataLoc; + datareserve = sz; + } + + void resize(size_t sz) + { + int oldDatasize = datasize; + if ((int) sz <= oldDatasize) + return; + if (sz > datareserve) + reserve(sz); + datasize = sz; + for (unsigned int i = oldDatasize; i < datasize; ++i) + booldata[i] = false; + } + void push_back(const bool &v) { resize(datasize + 1); booldata[datasize] = v; diff --git a/vcg/math/matrix33.h b/vcg/math/matrix33.h index 356a10db..c896afca 100644 --- a/vcg/math/matrix33.h +++ b/vcg/math/matrix33.h @@ -523,7 +523,7 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t } S dot=(v0*v1); ///control if there is no rotation - if (dot>((S)1-epsilon)) + if (dot>(S(1)-epsilon)) { rotM.SetIdentity(); return rotM; @@ -535,13 +535,13 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t //if dot = -1 rotating to opposite vertex //the problem is underdefined, so choose axis such that division is more stable //alternative solution at http://cs.brown.edu/research/pubs/pdfs/1999/Moller-1999-EBA.pdf - if (dot < (S)-1 + epsilon) + if (dot < S(-1) + epsilon) { - S max = std::numeric_limits::min(); + S max = std::numeric_limits::lowest(); int maxInd = 0; for (int i = 0; i < 3; ++i) { - if (v0[i] > max) + if (std::abs(v0[i]) > max) { max = v0[i]; maxInd = i; @@ -552,7 +552,7 @@ Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=t axis[(maxInd+1) % 3] = 0; axis[(maxInd+2) % 3] = 1; - dot = (S)-1; + dot = S(-1); } else { diff --git a/vcg/math/matrix44.h b/vcg/math/matrix44.h index 11d228d9..9bcc0e30 100644 --- a/vcg/math/matrix44.h +++ b/vcg/math/matrix44.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -73,7 +74,7 @@ for 'column' vectors. */ template class Matrix44 { protected: - T _a[16]; + std::array _a; public: typedef T ScalarType; @@ -258,7 +259,9 @@ typedef Matrix44 Matrix44d; //} template Matrix44::Matrix44(const T v[]) { - memcpy((T *)_a, v, 16 * sizeof(T)); +// memcpy((T *)_a, v, 16 * sizeof(T)); + for (unsigned int i = 0; i < 16; ++i) + _a[i] = v[i]; } template T &Matrix44::ElementAt(const int row, const int col) { @@ -284,15 +287,15 @@ template T Matrix44::ElementAt(const int row, const int col) const //} template T *Matrix44::operator[](const int i) { assert(i >= 0 && i < 4); - return _a+i*4; + return &_a[i*4]; } template const T *Matrix44::operator[](const int i) const { assert(i >= 0 && i < 4); - return _a+i*4; + return &_a[i*4]; } -template T *Matrix44::V() { return _a;} -template const T *Matrix44::V() const { return _a;} +template T *Matrix44::V() { return _a.data();} +template const T *Matrix44::V() const { return _a.data();} template Matrix44 Matrix44::operator+(const Matrix44 &m) const { @@ -421,7 +424,7 @@ void Matrix44::FromEulerAngles(T alpha, T beta, T gamma) } template void Matrix44::SetZero() { - memset((T *)_a, 0, 16 * sizeof(T)); + _a.fill(0); } template void Matrix44::SetIdentity() { diff --git a/vcg/math/old_deprecated_matrix.h b/vcg/math/old_deprecated_matrix.h deleted file mode 100644 index b0f232e1..00000000 --- a/vcg/math/old_deprecated_matrix.h +++ /dev/null @@ -1,786 +0,0 @@ -/**************************************************************************** -* VCGLib o o * -* Visual and Computer Graphics Library o o * -* _ O _ * -* Copyright(C) 2004-2016 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; 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. * -* * -* 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ -/*************************************************************************** -$Log: not supported by cvs2svn $ -Revision 1.9 2006/09/11 16:11:39 marfr960 -Added const to declarations of the overloaded (operators *). -Otherwise the * operator would always attempt to convert any type of data passed as an argument to Point3 - -Revision 1.8 2006/08/23 15:24:45 marfr960 -Copy constructor : faster memcpy instead of slow 'for' cycle -empty constructor - -Revision 1.7 2006/04/29 10:26:04 fiorin -Added some utility methods (swapping of columns and rows, matrix-vector multiplication) - -Revision 1.6 2006/04/11 08:09:35 zifnab1974 -changes necessary for gcc 3.4.5 on linux 64bit. Please take note of case-sensitivity of filenames - -Revision 1.5 2005/12/12 11:25:00 ganovelli -added diagonal matrix, outer produce and namespace - -***************************************************************************/ - -#ifndef MATRIX_VCGLIB -#define MATRIX_VCGLIB - -#include -#include -#include -#include -#include -#include - -namespace vcg{ - namespace ndim{ - - /** \addtogroup math */ - /* @{ */ - - /*! - * This class represent a diagonal mm matrix. - */ - - class MatrixDiagBase{public: - virtual const int & Dimension()const =0; - virtual float operator[](const int & i)const = 0; - }; - template - class MatrixDiag: public Point, public MatrixDiagBase{ - public: - const int & Dimension() const {return N;} - MatrixDiag(const Point&p):Point(p){} - }; - -/*! - * This class represent a generic mn matrix. The class is templated over the scalar type field. - * @param TYPE (Templete Parameter) Specifies the ScalarType field. - */ - template - class Matrix - { - - public: - typedef TYPE ScalarType; - - /*! - * Default constructor - * All the elements are initialized to zero. - * \param m the number of matrix rows - * \param n the number of matrix columns - */ - Matrix(unsigned int m, unsigned int n) - { - _rows = m; - _columns = n; - _data = new ScalarType[m*n]; - memset(_data, 0, m*n*sizeof(ScalarType)); - }; - - /*! - * Constructor - * The matrix elements are initialized with the values of the elements in \i values. - * \param m the number of matrix rows - * \param n the number of matrix columns - * \param values the values of the matrix elements - */ - Matrix(unsigned int m, unsigned int n, TYPE *values) - { - _rows = m; - _columns = n; - unsigned int dim = m*n; - _data = new ScalarType[dim]; - memcpy(_data, values, dim*sizeof(ScalarType)); - //unsigned int i; - //for (i=0; i<_rows*_columns; i++) - // _data[i] = values[i]; - }; - - /*! - * Empty constructor - * Just create the object - */ - Matrix() - { - _rows = 0; - _columns = 0; - _data = NULL; - }; - - /*! - * Copy constructor - * The matrix elements are initialized with the value of the corresponding element in \i m - * \param m the matrix to be copied - */ - Matrix(const Matrix &m) - { - _rows = m._rows; - _columns = m._columns; - _data = new ScalarType[_rows*_columns]; - - unsigned int dim = _rows * _columns; - memcpy(_data, m._data, dim * sizeof(ScalarType)); - -// for (unsigned int i=0; i<_rows*_columns; i++) -// _data[i] = m._data[i]; - }; - - /*! - * Default destructor - */ - ~Matrix() - { - delete []_data; - }; - - /*! - * Number of columns - */ - inline unsigned int ColumnsNumber() const - { - return _columns; - }; - - - /*! - * Number of rows - */ - inline unsigned int RowsNumber() const - { - return _rows; - }; - - /*! - * Equality operator. - * \param m - * \return true iff the matrices have same size and its elements have same values. - */ - bool operator==(const Matrix &m) const - { - if (_rows==m._rows && _columns==m._columns) - { - bool result = true; - for (unsigned int i=0; i<_rows*_columns && result; i++) - result = (_data[i]==m._data[i]); - return result; - } - return false; - }; - - /*! - * Inequality operator - * \param m - * \return true iff the matrices have different size or if their elements have different values. - */ - bool operator!=(const Matrix &m) const - { - if (_rows==m._rows && _columns==m._columns) - { - bool result = false; - for (unsigned int i=0; i<_rows*_columns && !result; i++) - result = (_data[i]!=m._data[i]); - return result; - } - return true; - }; - - /*! - * Return the element stored in the i-th rows at the j-th column - * \param i the row index - * \param j the column index - * \return the element - */ - inline TYPE ElementAt(unsigned int i, unsigned int j) - { - assert(i>=0 && i<_rows); - assert(j>=0 && j<_columns); - return _data[i*_columns+j]; - }; - - /*! - * Calculate and return the matrix determinant (Laplace) - * \return the matrix determinant - */ - TYPE Determinant() const - { - assert(_rows == _columns); - switch (_rows) - { - case 2: - { - return _data[0]*_data[3]-_data[1]*_data[2]; - break; - }; - case 3: - { - return _data[0]*(_data[4]*_data[8]-_data[5]*_data[7]) - - _data[1]*(_data[3]*_data[8]-_data[5]*_data[6]) + - _data[2]*(_data[3]*_data[7]-_data[4]*_data[6]) ; - break; - }; - default: - { - // da migliorare: si puo' cercare la riga/colonna con maggior numero di zeri - ScalarType det = 0; - for (unsigned int j=0; j<_columns; j++) - if (_data[j]!=0) - det += _data[j]*this->Cofactor(0, j); - - return det; - } - }; - }; - - /*! - * Return the cofactor Ai,j of the ai,j element - * \return ... - */ - TYPE Cofactor(unsigned int i, unsigned int j) const - { - assert(_rows == _columns); - assert(_rows>2); - TYPE *values = new TYPE[(_rows-1)*(_columns-1)]; - unsigned int u, v, p, q, s, t; - for (u=0, p=0, s=0, t=0; u<_rows; u++, t+=_rows) - { - if (i==u) - continue; - - for (v=0, q=0; v<_columns; v++) - { - if (j==v) - continue; - values[s+q] = _data[t+v]; - q++; - } - p++; - s+=(_rows-1); - } - Matrix temp(_rows-1, _columns-1, values); - return (pow(TYPE(-1.0), TYPE(i+j))*temp.Determinant()); - }; - - /*! - * Subscript operator: - * \param i the index of the row - * \return a reference to the i-th matrix row - */ - inline TYPE* operator[](const unsigned int i) - { - assert(i<_rows); - return _data + i*_columns; - }; - - /*! - * Const subscript operator - * \param i the index of the row - * \return a reference to the i-th matrix row - */ - inline const TYPE* operator[](const unsigned int i) const - { - assert(i<_rows); - return _data + i*_columns; - }; - - /*! - * Get the j-th column on the matrix. - * \param j the column index. - * \return the reference to the column elements. This pointer must be deallocated by the caller. - */ - TYPE* GetColumn(const unsigned int j) - { - assert(j>=0 && j<_columns); - ScalarType *v = new ScalarType[_columns]; - unsigned int i, p; - for (i=0, p=j; i<_rows; i++, p+=_columns) - v[i] = _data[p]; - return v; - }; - - /*! - * Get the i-th row on the matrix. - * \param i the column index. - * \return the reference to the row elements. This pointer must be deallocated by the caller. - */ - TYPE* GetRow(const unsigned int i) - { - assert(i>=0 && i<_rows); - ScalarType *v = new ScalarType[_rows]; - unsigned int j, p; - for (j=0, p=i*_columns; j<_columns; j++, p++) - v[j] = _data[p]; - return v; - }; - - /*! - * Swaps the values of the elements between the i-th and the j-th column. - * \param i the index of the first column - * \param j the index of the second column - */ - void SwapColumns(const unsigned int i, const unsigned int j) - { - assert(0<=i && i<_columns); - assert(0<=j && j<_columns); - if (i==j) - return; - - unsigned int r, e0, e1; - for (r=0, e0=i, e1=j; r<_rows; r++, e0+=_columns, e1+=_columns) - std::swap(_data[e0], _data[e1]); - }; - - /*! - * Swaps the values of the elements between the i-th and the j-th row. - * \param i the index of the first row - * \param j the index of the second row - */ - void SwapRows(const unsigned int i, const unsigned int j) - { - assert(0<=i && i<_rows); - assert(0<=j && j<_rows); - if (i==j) - return; - - unsigned int r, e0, e1; - for (r=0, e0=i*_columns, e1=j*_columns; r<_columns; r++, e0++, e1++) - std::swap(_data[e0], _data[e1]); - }; - - /*! - * Assignment operator - * \param m ... - */ - Matrix& operator=(const Matrix &m) - { - if (this != &m) - { - assert(_rows == m._rows); - assert(_columns == m._columns); - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] = m._data[i]; - } - return *this; - }; - - /*! - * Adds a matrix m to this matrix. - * \param m reference to matrix to add to this - * \return the matrix sum. - */ - Matrix& operator+=(const Matrix &m) - { - assert(_rows == m._rows); - assert(_columns == m._columns); - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] += m._data[i]; - return *this; - }; - - /*! - * Subtracts a matrix m to this matrix. - * \param m reference to matrix to subtract - * \return the matrix difference. - */ - Matrix& operator-=(const Matrix &m) - { - assert(_rows == m._rows); - assert(_columns == m._columns); - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] -= m._data[i]; - return *this; - }; - - /*! - * (Modifier) Add to each element of this matrix the scalar constant k. - * \param k the scalar constant - * \return the modified matrix - */ - Matrix& operator+=(const TYPE k) - { - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] += k; - return *this; - }; - - /*! - * (Modifier) Subtract from each element of this matrix the scalar constant k. - * \param k the scalar constant - * \return the modified matrix - */ - Matrix& operator-=(const TYPE k) - { - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] -= k; - return *this; - }; - - /*! - * (Modifier) Multiplies each element of this matrix by the scalar constant k. - * \param k the scalar constant - * \return the modified matrix - */ - Matrix& operator*=(const TYPE k) - { - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] *= k; - return *this; - }; - - /*! - * (Modifier) Divides each element of this matrix by the scalar constant k. - * \param k the scalar constant - * \return the modified matrix - */ - Matrix& operator/=(const TYPE k) - { - assert(k!=0); - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] /= k; - return *this; - }; - - /*! - * Matrix multiplication: calculates the cross product. - * \param m reference to the matrix to multiply by - * \return the matrix product - */ - Matrix operator*(const Matrix &m) const - { - assert(_columns == m._rows); - Matrix result(_rows, m._columns); - unsigned int i, j, k, p, q, r; - for (i=0, p=0, r=0; i - void DotProduct(Point &m,Point &result) - { - unsigned int i, j, p, r; - for (i=0, p=0, r=0; i operator*(const MatrixDiagBase &m) const - { - assert(_columns == _rows); - assert(_columns == m.Dimension()); - int i,j; - Matrix result(_rows, _columns); - - for (i=0; i - void OuterProduct(const Point a, const Point< M,TYPE> b) - { - assert(N == _rows); - assert(M == _columns); - Matrix result(_rows,_columns); - unsigned int i, j; - - for (i=0; i operator*(Point3 &p) const - { - assert(_columns==3 && _rows==3); - vcg::Point3 result; - result[0] = _data[0]*p[0]+_data[1]*p[1]+_data[2]*p[2]; - result[1] = _data[3]*p[0]+_data[4]*p[1]+_data[5]*p[2]; - result[2] = _data[6]*p[0]+_data[7]*p[1]+_data[8]*p[2]; - return result; - }; - - - /*! - * Scalar sum. - * \param k - * \return the resultant matrix - */ - Matrix operator+(const TYPE k) - { - Matrix result(_rows, _columns); - for (unsigned int i=0; i<_rows*_columns; i++) - result._data[i] = _data[i]+k; - return result; - }; - - /*! - * Scalar difference. - * \param k - * \return the resultant matrix - */ - Matrix operator-(const TYPE k) - { - Matrix result(_rows, _columns); - for (unsigned int i=0; i<_rows*_columns; i++) - result._data[i] = _data[i]-k; - return result; - }; - - /*! - * Negate all matrix elements - * \return the modified matrix - */ - Matrix operator-() const - { - Matrix result(_rows, _columns, _data); - for (unsigned int i=0; i<_columns*_rows; i++) - result._data[i] = -1*_data[i]; - return result; - }; - - /*! - * Scalar multiplication. - * \param k value to multiply every member by - * \return the resultant matrix - */ - Matrix operator*(const TYPE k) const - { - Matrix result(_rows, _columns); - for (unsigned int i=0; i<_rows*_columns; i++) - result._data[i] = _data[i]*k; - return result; - }; - - /*! - * Scalar division. - * \param k value to divide every member by - * \return the resultant matrix - */ - Matrix operator/(const TYPE k) - { - Matrix result(_rows, _columns); - for (unsigned int i=0; i<_rows*_columns; i++) - result._data[i] = _data[i]/k; - return result; - }; - - - /*! - * Set all the matrix elements to zero. - */ - void SetZero() - { - for (unsigned int i=0; i<_rows*_columns; i++) - _data[i] = ScalarType(0.0); - }; - - /*! - * Set the matrix to identity. - */ - void SetIdentity() - { - assert(_rows==_columns); - for (unsigned int i=0; i<_rows; i++) - for (unsigned int j=0; j<_columns; j++) - _data[i] = (i==j) ? ScalarType(1.0) : ScalarType(0.0f); - }; - - /*! - * Set the values of j-th column to v[j] - * \param j the column index - * \param v ... - */ - void SetColumn(const unsigned int j, TYPE* v) - { - assert(j>=0 && j<_columns); - unsigned int i, p; - for (i=0, p=j; i<_rows; i++, p+=_columns) - _data[p] = v[i]; - }; - - /*! - * Set the elements of the i-th row to v[j] - * \param i the row index - * \param v ... - */ - void SetRow(const unsigned int i, TYPE* v) - { - assert(i>=0 && i<_rows); - unsigned int j, p; - for (j=0, p=i*_rows; j<_columns; j++, p++) - _data[p] = v[j]; - }; - - /*! - * Set the diagonal elements vi,i to v[i] - * \param v - */ - void SetDiagonal(TYPE *v) - { - assert(_rows == _columns); - for (unsigned int i=0, p=0; i<_rows; i++, p+=_rows) - _data[p+i] = v[i]; - }; - - /*! - * Resize the current matrix. - * \param m the number of matrix rows. - * \param n the number of matrix columns. - */ - void Resize(const unsigned int m, const unsigned int n) - { - assert(m>=2); - assert(n>=2); - _rows = m; - _columns = n; - delete []_data; - _data = new ScalarType[m*n]; - for (unsigned int i=0; i MatrixMNd; - typedef vcg::ndim::Matrix MatrixMNf; - - /*! @} */ - -// template -// void Invert(MatrixType & m){ -// typedef typename MatrixType::ScalarType X; -// X *diag; -// diag = new X [m.ColumnsNumber()]; - -// MatrixType res(m.RowsNumber(),m.ColumnsNumber()); -// vcg::SingularValueDecomposition (m,&diag[0],res,LeaveUnsorted,50 ); -// m.Transpose(); -// // prodotto per la diagonale -// unsigned int i,j; -// for (i=0; i -#include -#include -#ifndef _YES_I_WANT_TO_USE_DANGEROUS_STUFF -#error "Please do not never user this file. Use EIGEN!!!!" -#endif -namespace vcg -{ - /** \addtogroup math */ - /* @{ */ - - /*! - * - */ - template< typename MATRIX_TYPE > - static void JacobiRotate(MATRIX_TYPE &A, typename MATRIX_TYPE::ScalarType s, typename MATRIX_TYPE::ScalarType tau, int i,int j,int k,int l) - { - typename MATRIX_TYPE::ScalarType g=A[i][j]; - typename MATRIX_TYPE::ScalarType h=A[k][l]; - A[i][j]=g-s*(h+g*tau); - A[k][l]=h+s*(g-h*tau); - }; - - /*! - * Computes all eigenvalues and eigenvectors of a real symmetric matrix . - * On output, elements of the input matrix above the diagonal are destroyed. - * \param d returns the eigenvalues of a. - * \param v is a matrix whose columns contain, the normalized eigenvectors - * \param nrot returns the number of Jacobi rotations that were required. - */ - template - static void Jacobi(MATRIX_TYPE &w, POINT_TYPE &d, MATRIX_TYPE &v, int &nrot) - { - typedef typename MATRIX_TYPE::ScalarType ScalarType; - assert(w.RowsNumber()==w.ColumnsNumber()); - int dimension = w.RowsNumber(); - - int j,iq,ip,i; - //assert(w.IsSymmetric()); - typename MATRIX_TYPE::ScalarType tresh, theta, tau, t, sm, s, h, g, c; - POINT_TYPE b, z; - - v.SetIdentity(); - - for (ip=0;ip4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip]) && (float)(fabs(d[iq])+g) == (float)fabs(d[iq])) - w[ip][iq]=ScalarType(0.0); - else if (fabs(w[ip][iq]) > tresh) - { - h=d[iq]-d[ip]; - if ((float)(fabs(h)+g) == (float)fabs(h)) - t=(w[ip][iq])/h; //t =1/(2#) - else - { - theta=ScalarType(0.5)*h/(w[ip][iq]); //Equation (11.1.10). - t=ScalarType(1.0)/(fabs(theta)+sqrt(ScalarType(1.0)+theta*theta)); - if (theta < ScalarType(0.0)) t = -t; - } - c=ScalarType(1.0)/sqrt(ScalarType(1.0)+t*t); - s=t*c; - tau=s/(ScalarType(1.0)+c); - h=t*w[ip][iq]; - z[ip] -= h; - z[iq] += h; - d[ip] -= h; - d[iq] += h; - w[ip][iq]=ScalarType(0.0); - for (j=0;j<=ip-1;j++) { //Case of rotations 1 <= j < p. - JacobiRotate(w,s,tau,j,ip,j,iq) ; - } - for (j=ip+1;j<=iq-1;j++) { //Case of rotations p < j < q. - JacobiRotate(w,s,tau,ip,j,j,iq); - } - for (j=iq+1;j(w,s,tau,ip,j,iq,j); - } - for (j=0;j(v,s,tau,j,ip,j,iq); - } - ++nrot; - } - } - } - for (ip=0;ip - void SortEigenvaluesAndEigenvectors(POINT_TYPE &eigenvalues, MATRIX_TYPE &eigenvectors, bool absComparison = false) - { - assert(eigenvectors.ColumnsNumber()==eigenvectors.RowsNumber()); - int dimension = eigenvectors.ColumnsNumber(); - int i, j, k; - float p,q; - for (i=0; i= p) - { - p = q; - k = j; - } - p = eigenvalues[k]; - } - else - { - p = eigenvalues[ k=i ]; - for (j=i+1; j= p) - p = eigenvalues[ k=j ]; - } - - if (k != i) - { - eigenvalues[k] = eigenvalues[i]; // i.e. - eigenvalues[i] = p; // swaps the value of the elements i-th and k-th - - for (j=0; j - inline static TYPE sqr(TYPE a) - { - TYPE sqr_arg = a; - return (sqr_arg == 0 ? 0 : sqr_arg*sqr_arg); - } - - // Computes (a^2 + b^2)^(1/2) without destructive underflow or overflow. - template - inline static TYPE pythagora(TYPE a, TYPE b) - { - TYPE abs_a = fabs(a); - TYPE abs_b = fabs(b); - if (abs_a > abs_b) - return abs_a*sqrt((TYPE)1.0+sqr(abs_b/abs_a)); - else - return (abs_b == (TYPE)0.0 ? (TYPE)0.0 : abs_b*sqrt((TYPE)1.0+sqr(abs_a/abs_b))); - } - - template - inline static TYPE sign(TYPE a, TYPE b) - { - return (b >= 0.0 ? fabs(a) : -fabs(a)); - } - - /*! - * - */ - enum SortingStrategy {LeaveUnsorted=0, SortAscending=1, SortDescending=2}; - template< typename MATRIX_TYPE > - void Sort(MATRIX_TYPE &U, typename MATRIX_TYPE::ScalarType W[], MATRIX_TYPE &V, const SortingStrategy sorting) ; - - - /*! - * Given a matrix Amxn, this routine computes its singular value decomposition, - * i.e. A=UxWxVT. The matrix A will be destroyed! - * (This is the implementation described in Numerical Recipies). - * \param A the matrix to be decomposed - * \param W the diagonal matrix of singular values W, stored as a vector W[1...N] - * \param V the matrix V (not the transpose VT) - * \param max_iters max iteration number (default = 30). - * \return - */ - template - static bool SingularValueDecomposition(MATRIX_TYPE &A, typename MATRIX_TYPE::ScalarType *W, MATRIX_TYPE &V, const SortingStrategy sorting=LeaveUnsorted, const int max_iters=30) - { - typedef typename MATRIX_TYPE::ScalarType ScalarType; - int m = (int) A.RowsNumber(); - int n = (int) A.ColumnsNumber(); - int flag,i,its,j,jj,k,l,nm; - ScalarType anorm, c, f, g, h, s, scale, x, y, z, *rv1; - bool convergence = true; - - rv1 = new ScalarType[n]; - g = scale = anorm = 0; - // Householder reduction to bidiagonal form. - for (i=0; i( sqrt(s), f ); - h = f*g - s; - A[i][i]=f-g; - for (j=l; j(sqrt(s),f); - h = f*g - s; - A[i][l] = f-g; - for (k=l; k=0; i--) - { - //Accumulation of right-hand transformations. - if (i < (n-1)) - { - if (g) - { - for (j=l; j=0; i--) - { - l = i+1; - g = W[i]; - for (j=l; j=0; k--) - { - for (its=1; its<=max_iters; its++) - { - flag=1; - for (l=k; l>=0; l--) - { - // Test for splitting. - nm=l-1; - // Note that rv1[1] is always zero. - if ((double)(fabs(rv1[l])+anorm) == anorm) - { - flag=0; - break; - } - if ((double)(fabs(W[nm])+anorm) == anorm) - break; - } - if (flag) - { - c=0.0; //Cancellation of rv1[l], if l > 1. - s=1.0; - for (i=l ;i<=k; i++) - { - f = s*rv1[i]; - rv1[i] = c*rv1[i]; - if ((double)(fabs(f)+anorm) == anorm) - break; - g = W[i]; - h = pythagora(f,g); - W[i] = h; - h = (ScalarType)1.0/h; - c = g*h; - s = -f*h; - for (j=0; j(f,1.0); - f=((x-z)*(x+z) + h*((y/(f+sign(g,f)))-h))/x; - c=s=1.0; - //Next QR transformation: - for (j=l; j<= nm;j++) - { - i = j+1; - g = rv1[i]; - y = W[i]; - h = s*g; - g = c*g; - z = pythagora(f,h); - rv1[j] = z; - c = f/z; - s = h/z; - f = x*c + g*s; - g = g*c - x*s; - h = y*s; - y *= c; - for (jj=0; jj(f,h); - W[j] = z; - // Rotation can be arbitrary if z = 0. - if (z) - { - z = (ScalarType)1.0/z; - c = f*z; - s = h*z; - } - f = c*g + s*y; - x = c*y - s*g; - for (jj=0; jj(A, W, V, sorting); - - return convergence; - }; - - - /*! - * Sort the singular values computed by the SingularValueDecomposition procedure and - * modify the matrices U and V accordingly. - */ - // TODO modify the last parameter type - template< typename MATRIX_TYPE > - void Sort(MATRIX_TYPE &U, typename MATRIX_TYPE::ScalarType W[], MATRIX_TYPE &V, const SortingStrategy sorting) - { - typedef typename MATRIX_TYPE::ScalarType ScalarType; - - assert(U.ColumnsNumber()==V.ColumnsNumber()); - - int mu = U.RowsNumber(); - int mv = V.RowsNumber(); - int n = U.ColumnsNumber(); - - //ScalarType* u = &U[0][0]; - //ScalarType* v = &V[0][0]; - - for (int i=0; i p) - { - k = j; - p = W[j]; - } - } - break; - } - case LeaveUnsorted: break; // nothing to do. - } - if (k != i) - { - W[k] = W[i]; // i.e. - W[i] = p; // swaps the i-th and the k-th elements - - int j = mu; - //ScalarType* uji = u + i; // uji = &U[0][i] - //ScalarType* ujk = u + k; // ujk = &U[0][k] - //ScalarType* vji = v + i; // vji = &V[0][i] - //ScalarType* vjk = v + k; // vjk = &V[0][k] - //if (j) - //{ - // for(;;) for( ; j!=0; --j, uji+=n, ujk+=n) - // { { - // p = *uji; p = *uji; // i.e. - // *uji = *ujk; *uji = *ujk; // swap( U[s][i], U[s][k] ) - // *ujk = p; *ujk = p; // - // if (!(--j)) } - // break; - // uji += n; - // ujk += n; - // } - //} - for(int s=0; j!=0; ++s, --j) - std::swap(U[s][i], U[s][k]); - - j = mv; - //if (j!=0) - //{ - // for(;;) for ( ; j!=0; --j, vji+=n, ujk+=n) - // { { - // p = *vji; p = *vji; // i.e. - // *vji = *vjk; *vji = *vjk; // swap( V[s][i], V[s][k] ) - // *vjk = p; *vjk = p; // - // if (!(--j)) } - // break; - // vji += n; - // vjk += n; - // } - //} - for (int s=0; j!=0; ++s, --j) - std::swap(V[s][i], V[s][k]); - } - } - } - - - /*! - * Solves AxX = B for a vector X, where A is specified by the matrices Umxn, - * Wnx1 and Vnxn as returned by SingularValueDecomposition. - * No input quantities are destroyed, so the routine may be called sequentially with different bxs. - * \param x is the output solution vector (xnx1) - * \param b is the input right-hand side (bnx1) - */ - template - static void SingularValueBacksubstitution(const MATRIX_TYPE &U, - const typename MATRIX_TYPE::ScalarType *W, - const MATRIX_TYPE &V, - typename MATRIX_TYPE::ScalarType *x, - const typename MATRIX_TYPE::ScalarType *b) - { - typedef typename MATRIX_TYPE::ScalarType ScalarType; - unsigned int jj, j, i; - unsigned int columns_number = U.ColumnsNumber(); - unsigned int rows_number = U.RowsNumber(); - ScalarType s; - ScalarType *tmp = new ScalarType[columns_number]; - for (j=0; j - -namespace vcg{ -namespace ndim{ -template class Matrix; -} -} - -namespace Eigen{ -template -struct ei_traits > : ei_traits > {}; -template struct ei_to_vcgtype -{ typedef vcg::ndim::Matrix type; }; -} - -namespace vcg{ -namespace ndim{ - -/** \addtogroup math */ -/* @{ */ - -/*! - * \deprecated use Matrix or Matrix or any typedef - * This class represent a generic mn matrix. The class is templated over the scalar type field. - * @param Scalar (Templete Parameter) Specifies the ScalarType field. - */ -template -class Matrix : public Eigen::Matrix<_Scalar,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> // FIXME col or row major ? -{ - typedef Eigen::Matrix<_Scalar,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> _Base; - -public: - - _EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix,_Base); - typedef _Scalar ScalarType; - VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix) - - /*! - * Default constructor - * All the elements are initialized to zero. - * \param m the number of matrix rows - * \param n the number of matrix columns - */ - Matrix(int m, int n) - : Base(m,n) - { - memset(Base::data(), 0, m*n*sizeof(Scalar)); - } - - /*! - * Constructor - * The matrix elements are initialized with the values of the elements in \i values. - * \param m the number of matrix rows - * \param n the number of matrix columns - * \param values the values of the matrix elements - */ - Matrix(int m, int n, Scalar *values) - : Base(m,n) - { - *this = Eigen::Map >(values, m , n); - } - - /*! - * Empty constructor - * Just create the object - */ - Matrix() : Base() {} - - /*! - * Copy constructor - * The matrix elements are initialized with the value of the corresponding element in \i m - * \param m the matrix to be copied - */ - Matrix(const Matrix &m) : Base(m) {} - - template - Matrix(const Eigen::MatrixBase &m) : Base(m) {} - - /*! - * Default destructor - */ - ~Matrix() {} - - /*! - * \deprecated use *this.row(i) - * Subscript operator: - * \param i the index of the row - * \return a reference to the i-th matrix row - */ - inline typename Base::RowXpr operator[](const unsigned int i) - { return Base::row(i); } - - /*! - * \deprecated use *this.row(i) - * Const subscript operator - * \param i the index of the row - * \return a reference to the i-th matrix row - */ - inline const typename Base::RowXpr operator[](const unsigned int i) const - { return Base::row(i); } - - - /*! - * Matrix multiplication: calculates the cross product. - * \param reference to the matrix to multiply by - * \return the matrix product - */ - // FIXME what the hell is that ! - /*template - void DotProduct(Point &m,Point &result) - { - unsigned int i, j, p, r; - for (i=0, p=0, r=0; i=2); - assert(n>=2); - Base::resize(m,n); - memset(Base::data(), 0, m*n*sizeof(Scalar)); - }; -}; - -typedef vcg::ndim::Matrix MatrixMNd; -typedef vcg::ndim::Matrix MatrixMNf; - -/*! @} */ - -template -void Invert(MatrixType & m) -{ - m = m.inverse(); -} - -} -} // end of namespace - -#endif - -#endif - diff --git a/vcg/math/old_matrix33.h b/vcg/math/old_matrix33.h deleted file mode 100644 index 0aebd8b0..00000000 --- a/vcg/math/old_matrix33.h +++ /dev/null @@ -1,298 +0,0 @@ -/**************************************************************************** -* VCGLib o o * -* Visual and Computer Graphics Library o o * -* _ O _ * -* Copyright(C) 2004-2016 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; 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. * -* * -* 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef VCG_USE_EIGEN -#include "deprecated_matrix33.h" -#else - -#ifndef __VCGLIB_MATRIX33_H -#define __VCGLIB_MATRIX33_H - -#include "eigen.h" -#include "matrix44.h" - -namespace vcg{ -template class Matrix33; -} - -namespace Eigen{ -template -struct ei_traits > : ei_traits > {}; -template struct ei_to_vcgtype -{ typedef vcg::Matrix33 type; }; -} - -namespace vcg { - -/** \deprecated use Matrix - @name Matrix33 - Class Matrix33. - This is the class for definition of a matrix 3x3. - @param S (Templete Parameter) Specifies the ScalarType field. -*/ -template -class Matrix33 : public Eigen::Matrix<_Scalar,3,3,Eigen::RowMajor> // FIXME col or row major ? -{ - - typedef Eigen::Matrix<_Scalar,3,3,Eigen::RowMajor> _Base; -public: - - using _Base::coeff; - using _Base::coeffRef; - using _Base::setZero; - - _EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix33,_Base); - typedef _Scalar ScalarType; - - VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix33) - - /// Default constructor - inline Matrix33() : Base() {} - - /// Copy constructor - Matrix33(const Matrix33& m ) : Base(m) {} - - /// create from a \b row-major array - Matrix33(const Scalar * v ) : Base(Eigen::Map >(v)) {} - - /// create from Matrix44 excluding row and column k - Matrix33(const Matrix44 & m, const int & k) : Base(m.minor(k,k)) {} - - template - Matrix33(const Eigen::MatrixBase& other) : Base(other) {} - - /*! \deprecated use *this.row(i) */ - inline typename Base::RowXpr operator[](const unsigned int i) - { return Base::row(i); } - - /*! \deprecated use *this.row(i) */ - inline const typename Base::RowXpr operator[](const unsigned int i) const - { return Base::row(i); } - - /** \deprecated */ - Matrix33 & SetRotateRad(Scalar angle, const Point3 & axis ) - { - *this = Eigen::AngleAxis(angle,axis).toRotationMatrix(); - return (*this); - } - /** \deprecated */ - Matrix33 & SetRotateDeg(Scalar angle, const Point3 & axis ){ - return SetRotateRad(math::ToRad(angle),axis); - } - - // Warning, this Inversion code can be HIGHLY NUMERICALLY UNSTABLE! - // In most case you are advised to use the Invert() method based on SVD decomposition. - /** \deprecated */ - Matrix33 & FastInvert() { return *this = Base::inverse(); } - - void show(FILE * fp) - { - for(int i=0;i<3;++i) - printf("| %g \t%g \t%g |\n",coeff(i,0),coeff(i,1),coeff(i,2)); - } - - /** \deprecated use a * b.transpose() - compute the matrix generated by the product of a * b^T - */ - // hm.... this is the outer product - void ExternalProduct(const Point3 &a, const Point3 &b) { *this = a * b.transpose(); } - - /** Compute the Frobenius Norm of the Matrix */ - Scalar Norm() { return Base::cwise().abs2().sum(); } - - /** Computes the covariance matrix of a set of 3d points. Returns the barycenter. - */ - // FIXME should be outside Matrix - - - /** - It computes the cross covariance matrix of two set of 3d points P and X; - it returns also the barycenters of P and X. - fonte: - - Besl, McKay - A method for registration o f 3d Shapes - IEEE TPAMI Vol 14, No 2 1992 - - */ - // FIXME should be outside Matrix - template - void CrossCovariance(const STLPOINTCONTAINER &P, const STLPOINTCONTAINER &X, - Point3 &bp, Point3 &bx) - { - setZero(); - assert(P.size()==X.size()); - bx.setZero(); - bp.setZero(); - Matrix33 tmp; - typename std::vector >::const_iterator pi,xi; - for(pi=P.begin(),xi=X.begin();pi!=P.end();++pi,++xi){ - bp+=*pi; - bx+=*xi; - tmp.ExternalProduct(*pi,*xi); - (*this)+=tmp; - } - bp/=P.size(); - bx/=X.size(); - (*this)/=P.size(); - tmp.ExternalProduct(bp,bx); - (*this)-=tmp; - } - - template - void WeightedCrossCovariance(const STLREALCONTAINER & weights, - const STLPOINTCONTAINER &P, - const STLPOINTCONTAINER &X, - Point3 &bp, - Point3 &bx) - { - setZero(); - assert(P.size()==X.size()); - bx.SetZero(); - bp.SetZero(); - Matrix33 tmp; - typename std::vector >::const_iterator pi,xi; - typename STLREALCONTAINER::const_iterator pw; - - for(pi=P.begin(),xi=X.begin();pi!=P.end();++pi,++xi){ - bp+=(*pi); - bx+=(*xi); - } - bp/=P.size(); - bx/=X.size(); - - for(pi=P.begin(),xi=X.begin(),pw = weights.begin();pi!=P.end();++pi,++xi,++pw){ - - tmp.ExternalProduct(((*pi)-(bp)),((*xi)-(bp))); - - (*this)+=tmp*(*pw); - } - } -}; - -template -void Invert(Matrix33 &m) { m = m.lu().inverse(); } - -template -Matrix33 Inverse(const Matrix33&m) { return m.lu().inverse(); } - -///given 2 vector centered into origin calculate the rotation matrix from first to the second -template -Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=true) - { - typedef typename vcg::Point3 CoordType; - Matrix33 rotM; - const S epsilon=0.00001; - if (!normalized) - { - v0.Normalize(); - v1.Normalize(); - } - S dot=v0.dot(v1); - ///control if there is no rotation - if (dot>((S)1-epsilon)) - { - rotM.SetIdentity(); - return rotM; - } - - ///find the axis of rotation - CoordType axis; - axis=v0^v1; - axis.Normalize(); - - ///construct rotation matrix - S u=axis.X(); - S v=axis.Y(); - S w=axis.Z(); - S phi=acos(dot); - S rcos = cos(phi); - S rsin = sin(phi); - - rotM[0][0] = rcos + u*u*(1-rcos); - rotM[1][0] = w * rsin + v*u*(1-rcos); - rotM[2][0] = -v * rsin + w*u*(1-rcos); - rotM[0][1] = -w * rsin + u*v*(1-rcos); - rotM[1][1] = rcos + v*v*(1-rcos); - rotM[2][1] = u * rsin + w*v*(1-rcos); - rotM[0][2] = v * rsin + u*w*(1-rcos); - rotM[1][2] = -u * rsin + v*w*(1-rcos); - rotM[2][2] = rcos + w*w*(1-rcos); - - return rotM; - } - -///return the rotation matrix along axis -template -Matrix33 RotationMatrix(const vcg::Point3 &axis, - const float &angleRad) - { - vcg::Matrix44 matr44; - vcg::Matrix33 matr33; - matr44.SetRotate(angleRad,axis); - for (int i=0;i<3;i++) - for (int j=0;j<3;j++) - matr33[i][j]=matr44[i][j]; - return matr33; - } - -/// return a random rotation matrix, from the paper: -/// Fast Random Rotation Matrices, James Arvo -/// Graphics Gems III pp. 117-120 -template - Matrix33 RandomRotation(){ - S x1,x2,x3; - Matrix33 R,H,M,vv; - Point3 v; - R.SetIdentity(); - H.SetIdentity(); - x1 = rand()/S(RAND_MAX); - x2 = rand()/S(RAND_MAX); - x3 = rand()/S(RAND_MAX); - - R[0][0] = cos(S(2)*M_PI*x1); - R[0][1] = sin(S(2)*M_PI*x1); - R[1][0] = - R[0][1]; - R[1][1] = R[0][0]; - - v[0] = cos(2.0 * M_PI * x2)*sqrt(x3); - v[1] = sin(2.0 * M_PI * x2)*sqrt(x3); - v[2] = sqrt(1-x3); - - vv.OuterProduct(v,v); - H -= vv*S(2); - M = H*R*S(-1); - return M; -} - -/// -typedef Matrix33 Matrix33s; -typedef Matrix33 Matrix33i; -typedef Matrix33 Matrix33f; -typedef Matrix33 Matrix33d; - -} // end of namespace - -#endif - -#endif diff --git a/vcg/math/old_matrix44.h b/vcg/math/old_matrix44.h deleted file mode 100644 index d4a7ae9a..00000000 --- a/vcg/math/old_matrix44.h +++ /dev/null @@ -1,493 +0,0 @@ -/**************************************************************************** -* VCGLib o o * -* Visual and Computer Graphics Library o o * -* _ O _ * -* Copyright(C) 2004-2016 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; 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. * -* * -* 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef VCG_USE_EIGEN -#include "deprecated_matrix44.h" -#else - -#ifndef __VCGLIB_MATRIX44 -#define __VCGLIB_MATRIX44 - -#include "eigen.h" -#include -#include -#include -#include - -namespace vcg{ -template class Matrix44; -} - -namespace Eigen{ -template -struct ei_traits > : ei_traits > {}; -template struct ei_to_vcgtype -{ typedef vcg::Matrix44 type; }; -} - -namespace vcg { - - /* - Annotations: -Opengl stores matrix in column-major order. That is, the matrix is stored as: - - a0 a4 a8 a12 - a1 a5 a9 a13 - a2 a6 a10 a14 - a3 a7 a11 a15 - - Usually in opengl (see opengl specs) vectors are 'column' vectors - so usually matrix are PRE-multiplied for a vector. - So the command glTranslate generate a matrix that - is ready to be premultipled for a vector: - - 1 0 0 tx - 0 1 0 ty - 0 0 1 tz - 0 0 0 1 - -Matrix44 stores matrix in row-major order i.e. - - a0 a1 a2 a3 - a4 a5 a6 a7 - a8 a9 a10 a11 - a12 a13 a14 a15 - -So for the use of that matrix in opengl with their supposed meaning you have to transpose them before feeding to glMultMatrix. -This mechanism is hidden by the templated function defined in wrap/gl/math.h; -If your machine has the ARB_transpose_matrix extension it will use the appropriate; -The various gl-like command SetRotate, SetTranslate assume that you are making matrix -for 'column' vectors. - -*/ - -// Note that we have to pass Dim and HDim because it is not allowed to use a template -// parameter to define a template specialization. To be more precise, in the following -// specializations, it is not allowed to use Dim+1 instead of HDim. -template< typename Other, - int OtherRows=Eigen::ei_traits::RowsAtCompileTime, - int OtherCols=Eigen::ei_traits::ColsAtCompileTime> -struct ei_matrix44_product_impl; - -/** \deprecated use Eigen::Matrix (or the typedef) you want a real 4x4 matrix, or use Eigen::Transform if you want a transformation matrix for a 3D space (a Eigen::Transform is internally a 4x4 col-major matrix) - * - * This class represents a 4x4 matrix. T is the kind of element in the matrix. - */ -template -class Matrix44 : public Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor> // FIXME col or row major ! -{ - - typedef Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor> _Base; -public: - - using _Base::coeff; - using _Base::coeffRef; - using _Base::ElementAt; - using _Base::setZero; - - _EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix44,_Base); - typedef _Scalar ScalarType; - VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix44) - - Matrix44() : Base() {} - ~Matrix44() {} - Matrix44(const Matrix44 &m) : Base(m) {} - Matrix44(const Scalar * v ) : Base(Eigen::Map >(v)) {} - template - Matrix44(const Eigen::MatrixBase& other) : Base(other) {} - - const typename Base::RowXpr operator[](int i) const { return Base::row(i); } - typename Base::RowXpr operator[](int i) { return Base::row(i); } - - typename Base::ColXpr GetColumn4(const int& i) const { return Base::col(i); } - const Eigen::Block GetColumn3(const int& i) const { return this->template block<3,1>(0,i); } - - typename Base::RowXpr GetRow4(const int& i) const { return Base::row(i); } - Eigen::Block GetRow3(const int& i) const { return this->template block<1,3>(i,0); } - - template - void ToMatrix(Matrix44Type & m) const { m = (*this).template cast(); } - - void ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma); - - template - void FromMatrix(const Matrix44Type & m) { for(int i = 0; i < 16; i++) Base::data()[i] = m.data()[i]; } - - void FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma); - void SetDiagonal(const Scalar k); - Matrix44 &SetScale(const Scalar sx, const Scalar sy, const Scalar sz); - Matrix44 &SetScale(const Point3 &t); - Matrix44 &SetTranslate(const Point3 &t); - Matrix44 &SetTranslate(const Scalar sx, const Scalar sy, const Scalar sz); - Matrix44 &SetShearXY(const Scalar sz); - Matrix44 &SetShearXZ(const Scalar sy); - Matrix44 &SetShearYZ(const Scalar sx); - - ///use radiants for angle. - Matrix44 &SetRotateDeg(Scalar AngleDeg, const Point3 & axis); - Matrix44 &SetRotateRad(Scalar AngleRad, const Point3 & axis); - - /** taken from Eigen::Transform - * \returns the product between the transform \c *this and a matrix expression \a other - * - * The right hand side \a other might be either: - * \li a matrix expression with 4 rows - * \li a 3D vector/point - */ - template - inline const typename ei_matrix44_product_impl::ResultType - operator * (const Eigen::MatrixBase &other) const - { return ei_matrix44_product_impl::run(*this,other.derived()); } - - void print() {std::cout << *this << "\n\n";} - -}; - -//return NULL matrix if not invertible -template Matrix44 &Invert(Matrix44 &m); -template Matrix44 Inverse(const Matrix44 &m); - -typedef Matrix44 Matrix44s; -typedef Matrix44 Matrix44i; -typedef Matrix44 Matrix44f; -typedef Matrix44 Matrix44d; - -template < class PointType , class T > void operator*=( std::vector &vert, const Matrix44 & m ) { - typename std::vector::iterator ii; - for(ii=vert.begin();ii!=vert.end();++ii) - (*ii).P()=m * (*ii).P(); -} - -template -void Matrix44::ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma) -{ - alpha = atan2(coeff(1,2), coeff(2,2)); - beta = asin(-coeff(0,2)); - gamma = atan2(coeff(0,1), coeff(1,1)); -} - -template -void Matrix44::FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma) -{ - this->SetZero(); - - T cosalpha = cos(alpha); - T cosbeta = cos(beta); - T cosgamma = cos(gamma); - T sinalpha = sin(alpha); - T sinbeta = sin(beta); - T singamma = sin(gamma); - - ElementAt(0,0) = cosbeta * cosgamma; - ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma; - ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma; - - ElementAt(0,1) = cosbeta * singamma; - ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma; - ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma; - - ElementAt(0,2) = -sinbeta; - ElementAt(1,2) = sinalpha * cosbeta; - ElementAt(2,2) = cosalpha * cosbeta; - - ElementAt(3,3) = 1; -} - -template void Matrix44::SetDiagonal(const Scalar k) { - setZero(); - ElementAt(0, 0) = k; - ElementAt(1, 1) = k; - ElementAt(2, 2) = k; - ElementAt(3, 3) = 1; -} - -template Matrix44 &Matrix44::SetScale(const Point3 &t) { - SetScale(t[0], t[1], t[2]); - return *this; -} -template Matrix44 &Matrix44::SetScale(const Scalar sx, const Scalar sy, const Scalar sz) { - setZero(); - ElementAt(0, 0) = sx; - ElementAt(1, 1) = sy; - ElementAt(2, 2) = sz; - ElementAt(3, 3) = 1; - return *this; -} - -template Matrix44 &Matrix44::SetTranslate(const Point3 &t) { - SetTranslate(t[0], t[1], t[2]); - return *this; -} -template Matrix44 &Matrix44::SetTranslate(const Scalar tx, const Scalar ty, const Scalar tz) { - Base::setIdentity(); - ElementAt(0, 3) = tx; - ElementAt(1, 3) = ty; - ElementAt(2, 3) = tz; - return *this; -} - -template Matrix44 &Matrix44::SetRotateDeg(Scalar AngleDeg, const Point3 & axis) { - return SetRotateRad(math::ToRad(AngleDeg),axis); -} - -template Matrix44 &Matrix44::SetRotateRad(Scalar AngleRad, const Point3 & axis) { - //angle = angle*(T)3.14159265358979323846/180; e' in radianti! - T c = math::Cos(AngleRad); - T s = math::Sin(AngleRad); - T q = 1-c; - Point3 t = axis; - t.Normalize(); - ElementAt(0,0) = t[0]*t[0]*q + c; - ElementAt(0,1) = t[0]*t[1]*q - t[2]*s; - ElementAt(0,2) = t[0]*t[2]*q + t[1]*s; - ElementAt(0,3) = 0; - ElementAt(1,0) = t[1]*t[0]*q + t[2]*s; - ElementAt(1,1) = t[1]*t[1]*q + c; - ElementAt(1,2) = t[1]*t[2]*q - t[0]*s; - ElementAt(1,3) = 0; - ElementAt(2,0) = t[2]*t[0]*q -t[1]*s; - ElementAt(2,1) = t[2]*t[1]*q +t[0]*s; - ElementAt(2,2) = t[2]*t[2]*q +c; - ElementAt(2,3) = 0; - ElementAt(3,0) = 0; - ElementAt(3,1) = 0; - ElementAt(3,2) = 0; - ElementAt(3,3) = 1; - return *this; -} - -/* Shear Matrixes -XY -1 k 0 0 x x+ky -0 1 0 0 y y -0 0 1 0 z z -0 0 0 1 1 1 - -1 0 k 0 x x+kz -0 1 0 0 y y -0 0 1 0 z z -0 0 0 1 1 1 - -1 1 0 0 x x -0 1 k 0 y y+kz -0 0 1 0 z z -0 0 0 1 1 1 - -*/ - - template Matrix44 & Matrix44::SetShearXY( const Scalar sh) {// shear the X coordinate as the Y coordinate change - Base::setIdentity(); - ElementAt(0,1) = sh; - return *this; - } - - template Matrix44 & Matrix44::SetShearXZ( const Scalar sh) {// shear the X coordinate as the Z coordinate change - Base::setIdentity(); - ElementAt(0,2) = sh; - return *this; - } - - template Matrix44 &Matrix44::SetShearYZ( const Scalar sh) {// shear the Y coordinate as the Z coordinate change - Base::setIdentity(); - ElementAt(1,2) = sh; - return *this; - } - - -/* -Given a non singular, non projective matrix (e.g. with the last row equal to [0,0,0,1] ) -This procedure decompose it in a sequence of - Scale,Shear,Rotation e Translation - -- ScaleV and Tranv are obiviously scaling and translation. -- ShearV contains three scalars with, respectively - ShearXY, ShearXZ e ShearYZ -- RotateV contains the rotations (in degree!) around the x,y,z axis - The input matrix is modified leaving inside it a simple roto translation. - - To obtain the original matrix the above transformation have to be applied in the strict following way: - - OriginalMatrix = Trn * Rtx*Rty*Rtz * ShearYZ*ShearXZ*ShearXY * Scl - -Example Code: -double srv() { return (double(rand()%40)-20)/2.0; } // small random value - - srand(time(0)); - Point3d ScV(10+srv(),10+srv(),10+srv()),ScVOut(-1,-1,-1); - Point3d ShV(srv(),srv(),srv()),ShVOut(-1,-1,-1); - Point3d RtV(10+srv(),srv(),srv()),RtVOut(-1,-1,-1); - Point3d TrV(srv(),srv(),srv()),TrVOut(-1,-1,-1); - - Matrix44d Scl; Scl.SetScale(ScV); - Matrix44d Sxy; Sxy.SetShearXY(ShV[0]); - Matrix44d Sxz; Sxz.SetShearXZ(ShV[1]); - Matrix44d Syz; Syz.SetShearYZ(ShV[2]); - Matrix44d Rtx; Rtx.SetRotate(math::ToRad(RtV[0]),Point3d(1,0,0)); - Matrix44d Rty; Rty.SetRotate(math::ToRad(RtV[1]),Point3d(0,1,0)); - Matrix44d Rtz; Rtz.SetRotate(math::ToRad(RtV[2]),Point3d(0,0,1)); - Matrix44d Trn; Trn.SetTranslate(TrV); - - Matrix44d StartM = Trn * Rtx*Rty*Rtz * Syz*Sxz*Sxy *Scl; - Matrix44d ResultM=StartM; - Decompose(ResultM,ScVOut,ShVOut,RtVOut,TrVOut); - - Scl.SetScale(ScVOut); - Sxy.SetShearXY(ShVOut[0]); - Sxz.SetShearXZ(ShVOut[1]); - Syz.SetShearYZ(ShVOut[2]); - Rtx.SetRotate(math::ToRad(RtVOut[0]),Point3d(1,0,0)); - Rty.SetRotate(math::ToRad(RtVOut[1]),Point3d(0,1,0)); - Rtz.SetRotate(math::ToRad(RtVOut[2]),Point3d(0,0,1)); - Trn.SetTranslate(TrVOut); - - // Now Rebuild is equal to StartM - Matrix44d RebuildM = Trn * Rtx*Rty*Rtz * Syz*Sxz*Sxy * Scl ; -*/ -template -bool Decompose(Matrix44 &M, Point3 &ScaleV, Point3 &ShearV, Point3 &RotV,Point3 &TranV) -{ - if(!(M(3,0)==0 && M(3,1)==0 && M(3,2)==0 && M(3,3)==1) ) // the matrix is projective - return false; - if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible... - - // First Step recover the traslation - TranV=M.GetColumn3(3); - - // Second Step Recover Scale and Shearing interleaved - ScaleV[0]=Norm(M.GetColumn3(0)); - Point3 R[3]; - R[0]=M.GetColumn3(0); - R[0].Normalize(); - - ShearV[0]=R[0].dot(M.GetColumn3(1)); // xy shearing - R[1]= M.GetColumn3(1)-R[0]*ShearV[0]; - assert(math::Abs(R[1].dot(R[0]))<1e-10); - ScaleV[1]=Norm(R[1]); // y scaling - R[1]=R[1]/ScaleV[1]; - ShearV[0]=ShearV[0]/ScaleV[1]; - - ShearV[1]=R[0].dot(M.GetColumn3(2)); // xz shearing - R[2]= M.GetColumn3(2)-R[0]*ShearV[1]; - assert(math::Abs(R[2].dot(R[0]))<1e-10); - - R[2] = R[2]-R[1]*(R[2].dot(R[1])); - assert(math::Abs(R[2].dot(R[1]))<1e-10); - assert(math::Abs(R[2].dot(R[0]))<1e-10); - - ScaleV[2]=Norm(R[2]); - ShearV[1]=ShearV[1]/ScaleV[2]; - R[2]=R[2]/ScaleV[2]; - assert(math::Abs(R[2].dot(R[1]))<1e-10); - assert(math::Abs(R[2].dot(R[0]))<1e-10); - - ShearV[2]=R[1].dot(M.GetColumn3(2)); // yz shearing - ShearV[2]=ShearV[2]/ScaleV[2]; - int i,j; - for(i=0;i<3;++i) - for(j=0;j<3;++j) - M(i,j)=R[j][i]; - - // Third and last step: Recover the rotation - //now the matrix should be a pure rotation matrix so its determinant is +-1 - double det=M.Determinant(); - if(math::Abs(det)<1e-10) return false; // matrix should be at least invertible... - assert(math::Abs(math::Abs(det)-1.0)<1e-10); // it should be +-1... - if(det<0) { - ScaleV *= -1; - M *= -1; - } - - double alpha,beta,gamma; // rotations around the x,y and z axis - beta=asin( M(0,2)); - double cosbeta=cos(beta); - if(math::Abs(cosbeta) > 1e-5) - { - alpha=asin(-M(1,2)/cosbeta); - if((M(2,2)/cosbeta) < 0 ) alpha=M_PI-alpha; - gamma=asin(-M(0,1)/cosbeta); - if((M(0,0)/cosbeta)<0) gamma = M_PI-gamma; - } - else - { - alpha=asin(-M(1,0)); - if(M(1,1)<0) alpha=M_PI-alpha; - gamma=0; - } - - RotV[0]=math::ToDeg(alpha); - RotV[1]=math::ToDeg(beta); - RotV[2]=math::ToDeg(gamma); - - return true; -} - -/* -To invert a matrix you can -either invert the matrix inplace calling - -vcg::Invert(yourMatrix); - -or get the inverse matrix of a given matrix without touching it: - -invertedMatrix = vcg::Inverse(untouchedMatrix); - -*/ -template Matrix44 & Invert(Matrix44 &m) { - return m = m.lu().inverse(); -} - -template Matrix44 Inverse(const Matrix44 &m) { - return m.lu().inverse(); -} - -template -struct ei_matrix44_product_impl -{ - typedef typename Other::Scalar Scalar; - typedef typename Eigen::ProductReturnType::Base,Other>::Type ResultType; - static ResultType run(const Matrix44& tr, const Other& other) - { return (static_cast::Base&>(tr)) * other; } -}; - -template -struct ei_matrix44_product_impl -{ - typedef typename Other::Scalar Scalar; - typedef Eigen::Matrix ResultType; - static ResultType run(const Matrix44& tr, const Other& p) - { - Scalar w; - Eigen::Matrix s; - s[0] = tr.ElementAt(0, 0)*p[0] + tr.ElementAt(0, 1)*p[1] + tr.ElementAt(0, 2)*p[2] + tr.ElementAt(0, 3); - s[1] = tr.ElementAt(1, 0)*p[0] + tr.ElementAt(1, 1)*p[1] + tr.ElementAt(1, 2)*p[2] + tr.ElementAt(1, 3); - s[2] = tr.ElementAt(2, 0)*p[0] + tr.ElementAt(2, 1)*p[1] + tr.ElementAt(2, 2)*p[2] + tr.ElementAt(2, 3); - w = tr.ElementAt(3, 0)*p[0] + tr.ElementAt(3, 1)*p[1] + tr.ElementAt(3, 2)*p[2] + tr.ElementAt(3, 3); - if(w!= 0) s /= w; - return s; - } -}; - -} //namespace -#endif - -#endif diff --git a/vcg/math/shot.h b/vcg/math/shot.h index 0eeda9cf..6ab6def0 100644 --- a/vcg/math/shot.h +++ b/vcg/math/shot.h @@ -127,7 +127,7 @@ public: void SetViewPoint(const vcg::Point3 & viewpoint); /// GET fov from focal - float GetFovFromFocal(); + float GetFovFromFocal() const; /// look at (point+up) void LookAt(const vcg::Point3 & point,const vcg::Point3 & up); @@ -256,7 +256,7 @@ void Shot::SetViewPoint(const vcg::Point3 & viewpoint) /// GET fov from focal template -float Shot::GetFovFromFocal() +float Shot::GetFovFromFocal() const { double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1]; return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm)))); diff --git a/vcg/simplex/edge/component.h b/vcg/simplex/edge/component.h index 4e922ae3..8c27bcec 100644 --- a/vcg/simplex/edge/component.h +++ b/vcg/simplex/edge/component.h @@ -128,9 +128,10 @@ public: inline typename T::VertexType * const & V( const int j ) const { assert(j>=0 && j<2); return v[j]; } inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && j<2); return v[j]; } - // Shortcut per accedere ai punti delle facce - inline CoordType & P( const int j ) { assert(j>=0 && j<2); return v[j]->P(); } - inline const CoordType &cP( const int j ) const { assert(j>=0 && j<2); return v[j]->P(); } + /// Shortcuts to access points + inline CoordType & P( const int j ) { assert(j>=0 && j<2); return v[j]->P();} + inline const CoordType & P( const int j ) const { assert(j>=0 && j<2); return v[j]->P();} + inline const CoordType & cP( const int j ) const { assert(j>=0 && j<2); return v[j]->P();} /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. @@ -142,7 +143,7 @@ public: inline const typename T::VertexType * const & cV0( const int j ) const { return cV(j);} inline const typename T::VertexType * const & cV1( const int j ) const { return cV((j+1)%2);} - /// Shortcut per accedere ai punti delle facce + /// Shortcuts to access points inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%2)->P();} inline const CoordType & P0( const int j ) const { return V(j)->P();} diff --git a/vcg/simplex/face/base.h b/vcg/simplex/face/base.h index 967c7dbc..639d0753 100644 --- a/vcg/simplex/face/base.h +++ b/vcg/simplex/face/base.h @@ -156,7 +156,7 @@ public: /// deletes the Face from the mesh void SetD() {this->Flags() |=DELETED;} - /// un-delete a Face + /// undelete the Face void ClearD() {this->Flags() &=(~DELETED);} /// marks the Face as readable void SetR() {this->Flags() &=(~NOTREAD);} @@ -168,14 +168,14 @@ public: void ClearW() {this->Flags() |=NOTWRITE;} /// select the Face void SetS() {this->Flags() |=SELECTED;} - /// Un-select a Face + /// unselect the Face void ClearS() {this->Flags() &= ~SELECTED;} - /// select the Face + /// set as visited the Face void SetV() {this->Flags() |=VISITED;} - /// Un-select a Face + /// set as unvisited the Face void ClearV() {this->Flags() &= ~VISITED;} - /// This function checks if the face is selected + /// This function checks if the face is border bool IsB(int i) const {return (this->cFlags() & (BORDER0<Flags() |=(BORDER0<=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } - inline typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline typename T::VertexType * & V( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]; } + inline const typename T::VertexType * V( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } + inline const typename T::VertexType * cV( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]; } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @@ -90,11 +90,15 @@ public: inline const VertexType * cV2( const int j ) const { return cV((j+2)%this->VN());} inline CoordType &P( const int j ) { assert(j>=0 && jVN()); return _vpoly[j]->P(); } + inline CoordType P( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]->cP(); } inline CoordType cP( const int j ) const { assert(j>=0 && jVN()); return _vpoly[j]->cP(); } inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%this->VN())->P();} inline CoordType & P2( const int j ) { return V((j+2)%this->VN())->P();} + inline CoordType P0( const int j ) const { return cV(j)->P();} + inline CoordType P1( const int j ) const { return cV((j+1)%this->VN())->P();} + inline CoordType P2( const int j ) const { return cV((j+2)%this->VN())->P();} inline CoordType cP0( const int j ) const { return cV(j)->P();} inline CoordType cP1( const int j ) const { return cV((j+1)%this->VN())->P();} inline CoordType cP2( const int j ) const { return cV((j+2)%this->VN())->P();} @@ -139,8 +143,9 @@ public: typename T::FacePointer &VFp(const int j) { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const VFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && jVN()); return _vfpP[j]; } - char &VFi(const int j) {return _vfiP[j]; } - char VFi(const int j) const {return _vfiP[j]; } + char & VFi(const int j) { return _vfiP[j]; } + char VFi(const int j) const { return _vfiP[j]; } + char cVFi(const int j) const { return _vfiP[j]; } template void ImportData(const LeftF & leftF){T::ImportData(leftF);} inline void Alloc(const int & ns) { diff --git a/vcg/simplex/vertex/component.h b/vcg/simplex/vertex/component.h index dab25640..37f27f93 100644 --- a/vcg/simplex/vertex/component.h +++ b/vcg/simplex/vertex/component.h @@ -158,15 +158,8 @@ public: static bool HasVHAdjacency() { return false; } typedef float CurScalarType; - typedef float ScalarTypeCur; typedef Point3f CurVecType; typedef Point2f CurvatureType; - float &Kh() { static float dummy = 0.f; assert(0);return dummy;} - float &Kg() { static float dummy = 0.f; assert(0);return dummy;} - float Kh() const { static float dummy = 0.f; assert(0); return dummy;} - float Kg() const { static float dummy = 0.f; assert(0); return dummy;} - float cKh() const { static float dummy = 0.f; assert(0); return dummy;} - float cKg() const { static float dummy = 0.f; assert(0); return dummy;} typedef CurvatureDirBaseType CurvatureDirType; CurVecType &PD1() {static CurVecType v(0,0,0); assert(0);return v;} @@ -183,9 +176,7 @@ public: CurScalarType cK1() const {static ScalarType v = 0.0;assert(0);return v;} CurScalarType cK2() const {static ScalarType v = 0.0;assert(0);return v;} - static bool HasCurvature() { return false; } static bool HasCurvatureDir() { return false; } - inline bool IsCurvatureEnabled() const { return TT::VertexType::HasCurvature();} inline bool IsCurvatureDirEnabled() const { return TT::VertexType::HasCurvatureDir();} template < class RightValueType> @@ -428,46 +419,6 @@ template class Qualityd: public Quality { public: static void Name(std::vector & name){name.push_back(std::string("Qualityd"));TT::Name(name);} }; - /*-------------------------- Curvature ----------------------------------*/ - - /*! \brief \em Component: Per vertex basic \b curvature - This component keeps the mean an gaussian curvature for a vertex. Used by some of the algorithms of vcg::tri::UpdateCurvature to store the computed curvatures. - */ - template class Curvature: public TT { - public: - typedef Point2 CurvatureType; - typedef typename CurvatureType::ScalarType ScalarTypeCur; - const ScalarTypeCur &Kh() const { return _hk[0]; } - const ScalarTypeCur &Kg() const { return _hk[1]; } - ScalarTypeCur &Kh() { return _hk[0]; } - ScalarTypeCur &Kg() { return _hk[1]; } - ScalarTypeCur cKh() const { return _hk[0]; } - ScalarTypeCur cKg() const { return _hk[1]; } - - template < class RightValueType> - void ImportData(const RightValueType & rVert ) { - if(rVert.IsCurvatureEnabled()) { - Kh() = rVert.cKh(); - Kg() = rVert.cKg(); - } - TT::ImportData( rVert); - } - - static bool HasCurvature() { return true; } - static void Name(std::vector & name){name.push_back(std::string("Curvature"));TT::Name(name);} - - private: - Point2 _hk; - }; - - - template class Curvaturef: public Curvature< float, T> { - public: static void Name(std::vector & name){name.push_back(std::string("Curvaturef"));T::Name(name);} - }; - template class Curvatured: public Curvature { - public: static void Name(std::vector & name){name.push_back(std::string("Curvatured"));T::Name(name);} - }; - /*-------------------------- Curvature Direction ----------------------------------*/ /*! \brief \em Component: Per vertex \b curvature \b directions diff --git a/vcg/simplex/vertex/component_ocf.h b/vcg/simplex/vertex/component_ocf.h index c063308c..4ad90edb 100644 --- a/vcg/simplex/vertex/component_ocf.h +++ b/vcg/simplex/vertex/component_ocf.h @@ -432,50 +432,6 @@ public: }; -///*-------------------------- CURVATURE ----------------------------------*/ - -template class CurvatureOcf: public TT { -public: - typedef Point2 CurvatureType; - typedef typename CurvatureType::ScalarType ScalarTypeCur; - - ScalarTypeCur &Kh(){ assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][0]; } - ScalarTypeCur &Kg(){ assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][1]; } - ScalarTypeCur cKh() const - { - assert((*this).Base().CurvatureEnabled); - return (*this).Base().CuV[(*this).Index()][0]; - } - - ScalarTypeCur cKg() const - { - assert((*this).Base().CurvatureEnabled); - return (*this).Base().CuV[(*this).Index()][1]; - } - - template - void ImportData(const RightVertexType & rightV){ - if((*this).IsCurvatureEnabled() && rightV.IsCurvatureEnabled()) - { - (*this).Base().CuV[(*this).Index()][0] = rightV.cKh(); - (*this).Base().CuV[(*this).Index()][1] = rightV.cKg(); - } - TT::ImportData(rightV); - } - - inline bool IsCurvatureEnabled( ) const - { - return this->Base().IsCurvatureEnabled(); - } - - static bool HasCurvature() { return true; } - static bool HasCurvatureOcf() { return true; } -}; - -template class CurvaturefOcf: public CurvatureOcf {public: static void Name(std::vector & name){name.push_back(std::string("CurvaturefOcf"));T::Name(name);} }; -template class CurvaturedOcf: public CurvatureOcf {public: static void Name(std::vector & name){name.push_back(std::string("CurvaturedOcf"));T::Name(name);} }; - - ///*-------------------------- CURVATURE DIR ----------------------------------*/ template @@ -494,13 +450,17 @@ public: typedef typename CurvatureDirType::CurVecType CurVecType; typedef typename CurvatureDirType::CurScalarType CurScalarType; - CurVecType &PD1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} - CurVecType &PD2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].min_dir;} - CurVecType cPD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} - CurVecType cPD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].min_dir;} + CurVecType& PD1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} + CurVecType& PD2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].min_dir;} + const CurVecType& cPD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} + const CurVecType& cPD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].min_dir;} + const CurVecType& PD1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} + const CurVecType& PD2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].min_dir;} - CurScalarType &K1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} - CurScalarType &K2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} + CurScalarType& K1() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} + CurScalarType& K2() { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} + CurScalarType K1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} + CurScalarType K2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} CurScalarType cK1() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} CurScalarType cK2() const { assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} diff --git a/vcg/space/color4.h b/vcg/space/color4.h index d97e7480..8d7c71c3 100644 --- a/vcg/space/color4.h +++ b/vcg/space/color4.h @@ -261,6 +261,7 @@ inline static Color4 ColorRamp(const float &minf,const float &maxf ,float v ) inline static unsigned short ToUnsignedB5G5R5(const Color4 &) { return 0;} inline static unsigned short ToUnsignedR5G5B5(const Color4 &) { return 0;} +inline static unsigned int ToUnsignedA8R8G8B8(const Color4 &) { return 0;} inline static Color4 FromUnsignedB5G5R5(unsigned short) { @@ -439,6 +440,17 @@ inline unsigned short Color4::ToUnsignedR5G5B5(const Color4 +inline unsigned int Color4::ToUnsignedA8R8G8B8(const Color4 &cc) +{ + unsigned int r = cc[0]; + unsigned int g = cc[1]; + unsigned int b = cc[2]; + unsigned int a = cc[3]; + unsigned int res = (r << 16) | (g << 8) | (b) | (a << 24); + return res; +} + template<> inline Color4 Color4::FromUnsignedR5G5B5(unsigned short val) diff --git a/vcg/space/deprecated_point2.h b/vcg/space/deprecated_point2.h index 6241e78d..5db300a3 100644 --- a/vcg/space/deprecated_point2.h +++ b/vcg/space/deprecated_point2.h @@ -193,12 +193,19 @@ public: _v[1] *= s; return *this; } + inline Point2 & operator /= ( const ScalarType s ) { _v[0] /= s; _v[1] /= s; return *this; } + + inline Point2 operator - (void) const + { + return Point2(-_v[0], -_v[1]); + } + //@} /// returns the norm (Euclidian) inline ScalarType Norm( void ) const @@ -216,7 +223,8 @@ public: _v[1] *= sy; return * this; } - /// normalizes, and returns itself as result + + /// normalizes, and returns itself as result (nonsense) inline Point2 & Normalize( void ) { ScalarType n = math::Sqrt(_v[0]*_v[0] + _v[1]*_v[1]); @@ -225,6 +233,19 @@ public: } return *this; } + + inline void normalize(void) + { + this->Normalize(); + } + + inline Point2 normalized(void) const + { + Point2 p = *this; + p.normalize(); + return p; + } + /// points equality inline bool operator == ( const Point2 & p ) const { @@ -374,42 +395,50 @@ inline T Angle( Point2 const & p0, Point2 const & p1 ) } template -inline Point2 operator - ( Point2 const & p ){ - return Point2( -p[0], -p[1] ); -} - -template -inline Point2 operator * ( const T s, Point2 const & p ){ +inline Point2 operator * ( const T s, Point2 const & p ) +{ return Point2( p[0] * s, p[1] * s ); } template -inline T Norm( Point2 const & p ){ +inline T Norm( Point2 const & p ) +{ return p.Norm(); } template -inline T SquaredNorm( Point2 const & p ){ +inline T SquaredNorm( Point2 const & p ) +{ return p.SquaredNorm(); } template -inline Point2 & Normalize( Point2 & p ){ +inline Point2 & Normalize( Point2 & p ) +{ return p.Normalize(); } +template +inline Point2 Normalized(const Point2 & p ) +{ + return p.normalized(); +} + template -inline T Distance( Point2 const & p1,Point2 const & p2 ){ +inline T Distance( Point2 const & p1,Point2 const & p2 ) +{ return Norm(p1-p2); } template -inline T SquaredDistance( Point2 const & p1,Point2 const & p2 ){ +inline T SquaredDistance( Point2 const & p1,Point2 const & p2 ) +{ return SquaredNorm(p1-p2); } template -inline Point2 Abs(const Point2 & p) { +inline Point2 Abs(const Point2 & p) +{ return (Point2(math::Abs(p[0]), math::Abs(p[1]))); } diff --git a/vcg/space/deprecated_point3.h b/vcg/space/deprecated_point3.h index a5e75494..81e67862 100644 --- a/vcg/space/deprecated_point3.h +++ b/vcg/space/deprecated_point3.h @@ -277,12 +277,9 @@ public: assert(i>=0 && i<3); return _v[i]; } -//@} -//@{ - /** @name Classical overloading of operators - Note - **/ + /** @name Classical overloading of operators + **/ inline Point3 operator + ( Point3 const & p) const { @@ -306,7 +303,7 @@ public: return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2] ); } inline P3ScalarType dot( const Point3 & p ) const { return (*this) * p; } - /// Cross product + /// Cross product inline Point3 operator ^ ( Point3 const & p ) const { return Point3 @@ -345,7 +342,8 @@ public: _v[2] /= s; return *this; } - // Norme + + // Norms inline P3ScalarType Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] ); @@ -370,62 +368,69 @@ public: return *this; } - // Normalizzazione - inline Point3 & Normalize() - { - P3ScalarType n = P3ScalarType(math::Sqrt(_v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2])); - if (n > P3ScalarType(0)) { _v[0] /= n; _v[1] /= n; _v[2] /= n; } - return *this; - } + // Normalization + inline Point3 & Normalize() + { + P3ScalarType n = P3ScalarType(math::Sqrt(_v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2])); + if (n > P3ScalarType(0)) { _v[0] /= n; _v[1] /= n; _v[2] /= n; } + return *this; + } - // for compatibility with eigen port - inline Point3 & normalized() { return Normalize(); } + inline void normalize(void) + { + this->Normalize(); + } - /** - * Convert to polar coordinates from cartesian coordinates. - * - * Theta is the azimuth angle and ranges between [0, 2PI) degrees. - * Phi is the elevation angle (not the polar angle) and ranges between [-PI/2, PI/2] degrees. - * - * /note Note that instead of the classical polar angle, which ranges between - * 0 and PI degrees we opt for the elevation angle to obtain a more - * intuitive spherical coordinate system. - */ - void ToPolarRad(P3ScalarType &ro, P3ScalarType &theta, P3ScalarType &phi) const - { - ro = Norm(); - theta = (P3ScalarType)atan2(_v[2], _v[0]); - phi = (P3ScalarType)asin(_v[1]/ro); - } + inline Point3 normalized(void) const + { + Point3 p = *this; + p.normalize(); + return p; + } - /** - * Convert from polar coordinates to cartesian coordinates. - * - * Theta is the azimuth angle and ranges between [0, 2PI) radians. - * Phi is the elevation angle (not the polar angle) and ranges between [-PI/2, PI/2] radians. - * - * \note Note that instead of the classical polar angle, which ranges between - * 0 and PI degrees, we opt for the elevation angle to obtain a more - * intuitive spherical coordinate system. - */ - void FromPolarRad(const P3ScalarType &ro, const P3ScalarType &theta, const P3ScalarType &phi) - { - _v[0]= ro*cos(theta)*cos(phi); - _v[1]= ro*sin(phi); - _v[2]= ro*sin(theta)*cos(phi); - } + /** + * Convert to polar coordinates from cartesian coordinates. + * + * Theta is the azimuth angle and ranges between [0, 2PI) degrees. + * Phi is the elevation angle (not the polar angle) and ranges between [-PI/2, PI/2] degrees. + * + * /note Note that instead of the classical polar angle, which ranges between + * 0 and PI degrees we opt for the elevation angle to obtain a more + * intuitive spherical coordinate system. + */ + void ToPolarRad(P3ScalarType &ro, P3ScalarType &theta, P3ScalarType &phi) const + { + ro = Norm(); + theta = (P3ScalarType)atan2(_v[2], _v[0]); + phi = (P3ScalarType)asin(_v[1]/ro); + } - Box3 GetBBox(Box3 &bb) const; -//@} -//@{ + /** + * Convert from polar coordinates to cartesian coordinates. + * + * Theta is the azimuth angle and ranges between [0, 2PI) radians. + * Phi is the elevation angle (not the polar angle) and ranges between [-PI/2, PI/2] radians. + * + * \note Note that instead of the classical polar angle, which ranges between + * 0 and PI degrees, we opt for the elevation angle to obtain a more + * intuitive spherical coordinate system. + */ + void FromPolarRad(const P3ScalarType &ro, const P3ScalarType &theta, const P3ScalarType &phi) + { + _v[0]= ro*cos(theta)*cos(phi); + _v[1]= ro*sin(phi); + _v[2]= ro*sin(theta)*cos(phi); + } - size_t MaxCoeffId() const - { - if (_v[0]>_v[1]) - return _v[0]>_v[2] ? 0 : 2; - else - return _v[1]>_v[2] ? 1 : 2; - } + Box3 GetBBox(Box3 &bb) const; + + size_t MaxCoeffId() const + { + if (_v[0]>_v[1]) + return _v[0]>_v[2] ? 0 : 2; + else + return _v[1]>_v[2] ? 1 : 2; + } /** @name Comparison Operators. Note that the reverse z prioritized ordering, useful in many situations. **/ @@ -463,8 +468,7 @@ inline bool operator == ( Point3 const & p ) const (_v[0]>=p._v[0]); } - - inline Point3 operator - () const + inline Point3 operator - (void) const { return Point3 ( -_v[0], -_v[1], -_v[2] ); } @@ -500,32 +504,37 @@ inline P3ScalarType AngleN( Point3 const & p1, Point3 inline P3ScalarType Norm( Point3 const & p ) { - return p.Norm(); + return p.Norm(); } template inline P3ScalarType SquaredNorm( Point3 const & p ) { - return p.SquaredNorm(); + return p.SquaredNorm(); } template inline Point3 & Normalize( Point3 & p ) { - p.Normalize(); - return p; + return p.Normalize(); +} + +template +inline Point3 Normalized(const Point3 & p) +{ + return p.normalized(); } template inline P3ScalarType Distance( Point3 const & p1,Point3 const & p2 ) { - return (p1-p2).Norm(); + return (p1-p2).Norm(); } template inline P3ScalarType SquaredDistance( Point3 const & p1,Point3 const & p2 ) { - return (p1-p2).SquaredNorm(); + return (p1-p2).SquaredNorm(); } template @@ -627,6 +636,12 @@ inline Point3 LowClampToZero(const Point3 & p) { return (Point3(std::max(p[0], (SCALARTYPE)0), std::max(p[1], (SCALARTYPE)0), std::max(p[2], (SCALARTYPE)0))); } +template +inline Point3 operator*(const Scalar s, const Point3 & p) +{ + return (p * s); +} + typedef Point3 Point3s; typedef Point3 Point3i; typedef Point3 Point3f; diff --git a/vcg/space/deprecated_point4.h b/vcg/space/deprecated_point4.h index 39b5d135..2b1b0410 100644 --- a/vcg/space/deprecated_point4.h +++ b/vcg/space/deprecated_point4.h @@ -274,21 +274,44 @@ public: return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3]; } /// Euclidian normalization - inline Point4 & Normalize() + inline Point4 & Normalize() { T n = sqrt(_v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] ); if(n>0.0) { _v[0] /= n; _v[1] /= n; _v[2] /= n; _v[3] /= n; } return *this; } - /// Homogeneous normalization (division by W) - inline Point4 & HomoNormalize(){ - if (_v[3]!=0.0) { _v[0] /= _v[3]; _v[1] /= _v[3]; _v[2] /= _v[3]; _v[3]=1.0; } - return *this; - }; -//@} + inline void normalize(void) + { + this->Normalize(); + } + + inline Point4 normalized(void) const + { + Point4 p = *this; + p.normalize(); + return p; + } + + /// Homogeneous normalization (division by W) + inline Point4 & HomoNormalize() + { + if (_v[3]!=0.0) { _v[0] /= _v[3]; _v[1] /= _v[3]; _v[2] /= _v[3]; _v[3]=1.0; } + return *this; + }; + + inline void homoNormalize(void) + { + this->HomoNormalize(); + }; + + inline Point4 homoNormalized(void) const + { + Point4 p = *this; + p.homoNormalize(); + return p; + } -//@{ /** @name Comparison operators (lexicographical order) **/ inline bool operator == ( const Point4& p ) const @@ -409,6 +432,12 @@ double StableDot ( Point4 const & p0, Point4 const & p1 ) return p0.StableDot(p1); } +template +inline Point4 operator*(const Scalar s, const Point4 & p) +{ + return (p * s); +} + typedef Point4 Point4s; typedef Point4 Point4i; typedef Point4 Point4f; diff --git a/vcg/space/index/octree.h b/vcg/space/index/octree.h index 25df7310..076f0eab 100644 --- a/vcg/space/index/octree.h +++ b/vcg/space/index/octree.h @@ -25,6 +25,7 @@ #define VCG_SPACE_INDEX_OCTREE_H #include +#include #ifdef __glut_h__ #include @@ -212,11 +213,11 @@ namespace vcg public: Octree() { - marks=0; + //marks=0; } ~Octree() { - if(marks) delete []marks; + //if(marks) delete []marks; int node_count = TemplatedOctree::NodeCount(); for (int i=0; i()); std::vector< NodePointer > filled_leaves(placeholder_count); @@ -537,7 +538,7 @@ OBJECT_RETRIEVER: /*! * Markers used to avoid duplication of the same result during a query */ - unsigned char *marks; + std::vector marks; unsigned char global_mark; /*! @@ -561,7 +562,7 @@ OBJECT_RETRIEVER: global_mark = (global_mark+1)%255; if (global_mark == 0) { - memset(&marks[0], 0, sizeof(unsigned char)*int(sorted_dataset.size())); + std::fill(marks.begin(), marks.begin() + sorted_dataset.size(), 0); global_mark++; } };//end of IncrementMark diff --git a/vcg/space/index/octree_template.h b/vcg/space/index/octree_template.h index 7a2f1d71..96aca827 100644 --- a/vcg/space/index/octree_template.h +++ b/vcg/space/index/octree_template.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include namespace vcg @@ -111,7 +113,7 @@ protected: InnerNode() : Node() {} InnerNode(NodePointer parent, int level) : Node(parent, level) { - memset(&sons[0], 0, 8*sizeof(Node*)); + sons.fill(nullptr); } inline NodePointer &Son(int sonIndex) @@ -125,7 +127,7 @@ protected: return false; } - NodePointer sons[8]; + std::array sons; }; /* @@ -598,7 +600,8 @@ public: assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() ); assert( boundingBox.min.Z()<=p.Z() && p.Z()<=boundingBox.max.Z() ); - memset(route, NULL, maximumDepth*sizeof(NodePointer)); + for (unsigned int i = 0; i < maximumDepth; ++i) + route[i] = nullptr; CenterType path = CenterType::Construct(Interize(p)); int shift = maximumDepth-1; diff --git a/vcg/space/index/perfect_spatial_hashing.h b/vcg/space/index/perfect_spatial_hashing.h index bbcbdef9..cf253bc0 100644 --- a/vcg/space/index/perfect_spatial_hashing.h +++ b/vcg/space/index/perfect_spatial_hashing.h @@ -1462,7 +1462,7 @@ namespace vcg m_OffsetTable.GetPreImageSortedPerCardinality(preimage_slots); char msg[128]; - sprintf(msg, "Building offset table of resolution %d", m_OffsetTable.GetSize()); + snprintf(msg, 128, "Building offset table of resolution %d", m_OffsetTable.GetSize()); int step = int(preimage_slots.size())/100; int number_of_slots = int(preimage_slots.size()); int perc = 0; diff --git a/vcg/space/intersection3.h b/vcg/space/intersection3.h index e6cc96ae..e0fcadd2 100644 --- a/vcg/space/intersection3.h +++ b/vcg/space/intersection3.h @@ -121,7 +121,7 @@ namespace vcg { solution_count++; } return solution_count; - }; // end of IntersectionSegmentSphere + } // end of IntersectionSegmentSphere /*! @@ -214,7 +214,7 @@ namespace vcg { penetration_detected = (witness.SquaredNorm() <= (radius*radius)); witness += center; return penetration_detected; - }; //end of IntersectionSphereTriangle + } //end of IntersectionSphereTriangle /// intersection between line and plane template diff --git a/vcg/space/outline2_packer.h b/vcg/space/outline2_packer.h index 5343ad0b..384bfda6 100644 --- a/vcg/space/outline2_packer.h +++ b/vcg/space/outline2_packer.h @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * @@ -24,6 +24,7 @@ #define __VCG_OUTLINE2_PACKER_H__ #include +#include #include #include #include @@ -212,26 +213,24 @@ static bool WritePolyVec(const std::vector< std::vector > &polyVec, con static bool ReadPolyVec(std::vector< std::vector > &polyVec, const char *filename) { - FILE *fp=fopen(filename,"r"); - if(!fp) return false; - int sz; - fscanf(fp,"%i\n",&sz); - polyVec.clear(); - polyVec.resize(sz); - for(size_t i=0;i> sz; + polyVec.resize(sz); + for (std::size_t i = 0; i < sz; ++i){ + int isz; + ifs >> isz; + polyVec[i].resize(isz); + for (std::size_t j = 0; j < isz; ++j){ + float x, y; + ifs >> x >> y; + polyVec[i][j].X() = x; + polyVec[i][j].Y() = y; + } + } + ifs.close(); + return true; } diff --git a/vcg/space/tetra3.h b/vcg/space/tetra3.h index cd702b31..4f07b145 100644 --- a/vcg/space/tetra3.h +++ b/vcg/space/tetra3.h @@ -379,7 +379,7 @@ class Tetra CoordType n1 = ((p2 - p0) ^ (p1 - p0)).normalized(); return M_PI - double(acos(n0 * n1)); - }; + } template static typename TetraType::ScalarType SolidAngle(const TetraType &t, const size_t vidx) @@ -390,7 +390,7 @@ class Tetra ScalarType a2 = DihedralAngle(t, Tetra::EofV(vidx, 2)); return (a0 + a1 + a2) - M_PI; - }; + } template static typename TetraType::ScalarType AspectRatio(const TetraType &t) diff --git a/wrap/gl/camera.h b/wrap/gl/camera.h index a72d15d4..b6a8dc77 100644 --- a/wrap/gl/camera.h +++ b/wrap/gl/camera.h @@ -79,9 +79,6 @@ creation // VCG #include -// opengl -#include - template struct GlCamera{ @@ -139,35 +136,35 @@ static void SetGLIsometricProj(float x1, float x2, float y1, float y2, float z1, } /// get OpenGL-like frustum from a vcg camera (intrinsics) -static void GetFrustum(vcg::Camera & intrinsics, S & sx,S & dx,S & bt,S & tp,S & f) +static void GetFrustum(const vcg::Camera & intrinsics, S & sx,S & dx,S & bt,S & tp,S & f) { intrinsics.GetFrustum(sx,dx,bt,tp,f); } /// set the OpenGL PROJECTION matrix to match the camera (intrinsics). requires near and far plane -static void TransformGL(vcg::Camera & camera, S nearDist, S farDist ) +static void TransformGL(const vcg::Camera & camera, S nearDist, S farDist ) { S sx,dx,bt,tp,nr; camera.GetFrustum(sx,dx,bt,tp,nr); - if(camera.cameraType == CameraType::PERSPECTIVE) { - S ratio = nearDist/nr; - sx *= ratio; - dx *= ratio; - bt *= ratio; - tp *= ratio; - } + if(camera.cameraType == CameraType::PERSPECTIVE) { + S ratio = nearDist/nr; + sx *= ratio; + dx *= ratio; + bt *= ratio; + tp *= ratio; + } assert(glGetError()==0); - switch(camera.cameraType) + switch(camera.cameraType) { - case CameraType::PERSPECTIVE: glFrustum(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::ORTHO: glOrtho(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::ISOMETRIC: SetGLIsometricProj(sx,dx,bt,tp,nearDist,farDist); break; - case CameraType::CAVALIERI: SetGLCavalieriProj(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::PERSPECTIVE: glFrustum(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::ORTHO: glOrtho(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::ISOMETRIC: SetGLIsometricProj(sx,dx,bt,tp,nearDist,farDist); break; + case CameraType::CAVALIERI: SetGLCavalieriProj(sx,dx,bt,tp,nearDist,farDist); break; } - + assert(glGetError()==0); }; diff --git a/wrap/gl/deprecated_space.h b/wrap/gl/deprecated_space.h index 563032cc..7478b859 100644 --- a/wrap/gl/deprecated_space.h +++ b/wrap/gl/deprecated_space.h @@ -152,7 +152,7 @@ namespace vcg { glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); glEnd(); glPopAttrib(); -}; +} template /// Funzione di utilita' per la visualizzazione in OpenGL (flat shaded) inline void glBoxFlat(Box3 const & b) @@ -190,7 +190,7 @@ inline void glBoxFlat(Box3 const & b) glVertex3f(b.min[0], b.min[1], b.max[2]); glEnd(); glPopAttrib(); -}; +} template @@ -228,7 +228,7 @@ inline void glBoxClip(const Box3 & b) glEnd(); glPopAttrib(); -}; +} template inline void glPlane3( Plane3 p, Point3 c, T size ) { Point3 w = p.Direction(); diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 30feb0ef..e0fd053e 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include @@ -1158,25 +1158,27 @@ namespace vcg triangles += cit->second - cit->first + 1; } - if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) - { - for (typename std::vector::iterator it = _edge.begin(); it != _edge.end(); ++it) - { - it->_v[0] = vpatlas[it->_v[0]]; - it->_v[1] = vpatlas[it->_v[1]]; - } - - GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - if (attributestobeupdated[INT_ATT_NAMES::ATT_WEDGETEXTURE] || attributestobeupdated[INT_ATT_NAMES::ATT_VERTTEXTURE]) _texindnumtriangles[t] = std::make_pair(mit->first, triangles); ++t; } + if ((attributestobeupdated[INT_ATT_NAMES::ATT_EDGEINDICES]) && (_edge.size() > 0)) + { + unsigned int i = 0; + for (EdgeVertInd& e : _edge) + { + e._v[0] = vpatlas[e._v[0]]; + e._v[1] = vpatlas[e._v[1]]; + ++i; + } + + GLBufferObject* buffobj = _bo[INT_ATT_NAMES::ATT_EDGEINDICES]; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffobj->_bohandle); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, buffobj->_components * buffobj->getSizeOfGLType() * _edge.size(), &_edge[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + //return (k != tn) // throw MeshLabException("Mesh has not been properly partitioned"); return true; diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index bb4ea942..4d327d14 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -24,403 +24,220 @@ #ifndef __PICK______H #define __PICK______H +// Assumes OpenGL already included + #include #include -#include "gl_type_name.h" +#include namespace vcg{ template class GLPickTri { - typedef typename MESH_TYPE::ScalarType ScalarType; - typedef typename MESH_TYPE::CoordType CoordType; - typedef typename MESH_TYPE::FaceIterator FaceIterator; - typedef typename MESH_TYPE::VertexIterator VertexIterator; - typedef typename MESH_TYPE::FacePointer FacePointer; - typedef typename MESH_TYPE::VertexPointer VertexPointer; - typedef typename MESH_TYPE::VertexType VertexType; - public: - static CoordType glProject(const Eigen::Matrix &M, const ScalarType * viewport, const CoordType &p) - { - const ScalarType vx=viewport[0]; - const ScalarType vy=viewport[1]; - const ScalarType vw2=viewport[2]/ScalarType(2.0); - const ScalarType vh2=viewport[3]/ScalarType(2.0); - Eigen::Matrix vp(p[0],p[1],p[2],ScalarType(1.0)); - Eigen::Matrix vpp = M*vp; - Eigen::Matrix ndc = vpp/vpp[3]; + typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::VertexIterator VertexIterator; + typedef typename MESH_TYPE::FacePointer FacePointer; + typedef typename MESH_TYPE::VertexPointer VertexPointer; + typedef typename MESH_TYPE::VertexType VertexType; - CoordType sc( - vw2*ndc[0] + vx+vw2, - vh2*ndc[1] + vy+vh2, - ndc[2] - ); + static CoordType glProject(const Eigen::Matrix &M, const ScalarType * viewport, const CoordType &p) + { + const ScalarType vx=viewport[0]; + const ScalarType vy=viewport[1]; + const ScalarType vw2=viewport[2]/ScalarType(2.0); + const ScalarType vh2=viewport[3]/ScalarType(2.0); + Eigen::Matrix vp(p[0],p[1],p[2],ScalarType(1.0)); + Eigen::Matrix vpp = M*vp; + Eigen::Matrix ndc = vpp/vpp[3]; - return sc; - } + CoordType sc(vw2*ndc[0] + vx+vw2, + vh2*ndc[1] + vy+vh2, + ndc[2]); - static void FillProjectedVector(MESH_TYPE &m, std::vector &pVec, const Eigen::Matrix &M, const ScalarType * viewportF) - { - pVec.resize(m.vert.size()); - for(size_t i=0;i::glProject(M, viewportF,CoordType::Construct(m.vert[i].P())); - } - } + return sc; + } - static void glGetMatrixAndViewport(Eigen::Matrix &M, ScalarType *viewportF) - { - Eigen::Matrix4d mp,mm; + static void FillProjectedVector(MESH_TYPE &m, std::vector &pVec, const Eigen::Matrix &M, const ScalarType * viewportF) + { + pVec.resize(m.vert.size()); + for(size_t i=0;i::glProject(M, viewportF,CoordType::Construct(m.vert[i].P())); + } + } - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - for(int i=0;i<4;++i) viewportF[i]=viewport[i]; + static void glGetMatrixAndViewport(Eigen::Matrix &M, ScalarType *viewportF) + { + Eigen::Matrix4d mp,mm; - glGetDoublev(GL_PROJECTION_MATRIX, mp.data()); - glGetDoublev(GL_MODELVIEW_MATRIX, mm.data()); + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + for(int i=0;i<4;++i) viewportF[i]=viewport[i]; - M = (mp*mm).cast(); - } + glGetDoublev(GL_PROJECTION_MATRIX, mp.data()); + glGetDoublev(GL_MODELVIEW_MATRIX, mm.data()); - // compute a bbox in Device Coordinate (with the z without the near far normalization and ranged in -1 1) - static Box3 ComputeDCBox(int x, int y, int width, int height) - { - Box3 bb; - bb.SetNull(); - bb.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0))); - bb.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0), ScalarType(1.0))); - return bb; - } + M = (mp*mm).cast(); + } -public: + // compute a bbox in Device Coordinate (with the z without the near far normalization and ranged in -1 1) + static Box3 ComputeDCBox(int x, int y, int width, int height) + { + Box3 bb; + bb.SetNull(); + bb.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0))); + bb.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0), ScalarType(1.0))); + return bb; + } - static bool PickClosestFace(int x, int y, MESH_TYPE &m, FacePointer &fp,int width=4, int height=4) - { - Eigen::Matrix M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); - Box3 reg=ComputeDCBox(x,y,width,height); + static bool PickClosestFace(int x, int y, MESH_TYPE &m, FacePointer &fp,int width=4, int height=4) + { + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); + Box3 reg=ComputeDCBox(x,y,width,height); - ScalarType bzmin = std::numeric_limits::max(); - fp=0; - for(size_t i=0;i::max(); + fp=0; + for(size_t i=0;i M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); - ScalarType bzmin = std::numeric_limits::max(); - vp=0; + static bool PickClosestVert(int x, int y, MESH_TYPE &m, VertexPointer &vp,int width=4, int height=4) + { + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); + ScalarType bzmin = std::numeric_limits::max(); + vp=0; - Box3 reg=ComputeDCBox(x,y,width,height); + Box3 reg=ComputeDCBox(x,y,width,height); - for(size_t i=0;i &result, int width=4, int height=4) - { - result.clear(); - static Eigen::Matrix lastM; - static MESH_TYPE *lastm=0; - static std::vector pVec; + static int PickVert(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4) + { + result.clear(); + static Eigen::Matrix lastM; + static MESH_TYPE *lastm=0; + static std::vector pVec; - Eigen::Matrix M; - ScalarType viewportF[4]; - glGetMatrixAndViewport(M,viewportF); + Eigen::Matrix M; + ScalarType viewportF[4]; + glGetMatrixAndViewport(M,viewportF); - Box3 reg =ComputeDCBox(x,y,width,height); + Box3 reg =ComputeDCBox(x,y,width,height); - if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) - { - FillProjectedVector(m,pVec,M,viewportF); - lastM = M; - lastm = &m; - } + if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) + { + FillProjectedVector(m,pVec,M,viewportF); + lastM = M; + lastm = &m; + } - for(size_t i=0;i &result, int width = 4, int height = 4) - { - static Eigen::Matrix lastM; - static MESH_TYPE *lastm = 0; - static std::vector pVec; + static int PickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width = 4, int height = 4) + { + static Eigen::Matrix lastM; + static MESH_TYPE *lastm = 0; + static std::vector pVec; - ScalarType viewportF[4]; - Eigen::Matrix M; - glGetMatrixAndViewport(M, viewportF); - result.clear(); - Box3 reg; - reg.Add(CoordType(x - width / ScalarType(2.0), y - height / ScalarType(2.0), ScalarType(-1.0))); - reg.Add(CoordType(x + width / ScalarType(2.0), y + height / ScalarType(2.0), ScalarType(1.0))); + ScalarType viewportF[4]; + Eigen::Matrix M; + glGetMatrixAndViewport(M, viewportF); + result.clear(); + Box3 reg; + reg.Add(CoordType(x - width / ScalarType(2.0), y - height / ScalarType(2.0), ScalarType(-1.0))); + reg.Add(CoordType(x + width / ScalarType(2.0), y + height / ScalarType(2.0), ScalarType(1.0))); - - if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) - { - FillProjectedVector(m, pVec, M, viewportF); - lastM = M; - lastm = &m; - } + if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) + { + FillProjectedVector(m, pVec, M, viewportF); + lastM = M; + lastm = &m; + } - for (size_t i = 0; i < m.face.size(); ++i) - { - if (!m.face[i].IsD()) - { - const CoordType &p0 = pVec[tri::Index(m, m.face[i].V(0))]; - const CoordType &p1 = pVec[tri::Index(m, m.face[i].V(1))]; - const CoordType &p2 = pVec[tri::Index(m, m.face[i].V(2))]; + for (size_t i = 0; i < m.face.size(); ++i) + { + if (!m.face[i].IsD()) + { + const CoordType &p0 = pVec[tri::Index(m, m.face[i].V(0))]; + const CoordType &p1 = pVec[tri::Index(m, m.face[i].V(1))]; + const CoordType &p2 = pVec[tri::Index(m, m.face[i].V(2))]; - if (!(abs(p0[2]) > 1 || abs(p1[2]) > 1 || abs(p2[2]) > 1) && IntersectionTriangleBox(reg, p0, p1, p2)) - result.push_back(&m.face[i]); - } - } - return result.size(); - } + if (!(abs(p0[2]) > 1 || abs(p1[2]) > 1 || abs(p2[2]) > 1) && IntersectionTriangleBox(reg, p0, p1, p2)) + result.push_back(&m.face[i]); + } + } + return result.size(); + } - // Same of above but it also assumes that you want only visible faces. - // Visibility is computed according to the current depth buffer. - static int PickVisibleFace(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4) - { - ScalarType vp[4]; - Eigen::Matrix M; - glGetMatrixAndViewport(M,vp); + // Same of above but it also assumes that you want only visible faces. + // Visibility is computed according to the current depth buffer. + static int PickVisibleFace(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4) + { + ScalarType vp[4]; + Eigen::Matrix M; + glGetMatrixAndViewport(M,vp); - int screenW = (int)(vp[2]-vp[0]); - int screenH = (int)(vp[3]-vp[1]); + int screenW = (int)(vp[2]-vp[0]); + int screenH = (int)(vp[3]-vp[1]); - GL_TYPE_NM::ScalarType *buffer = new GL_TYPE_NM::ScalarType[screenW*screenH]; + GLfloat *buffer = new GLfloat[screenW*screenH]; - //I'm not sure glReadPixels can accept GL_DOUBLE tag - //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM::SCALAR(),buffer); - //err = glGetError(); - std::vector result; - PickFace(x,y,m,result,width,height); - ScalarType LocalEpsilon(ScalarType(0.001)); - for(size_t i =0;i=0 && p[0]=0 && p[1]= ScalarType(p[2]+1.0)/2.0) - resultZ.push_back(result[i]); - } - } + //glReadPixels does NOT accept GL_DOUBLE + //GLenum err = glGetError(); + glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_FLOAT,buffer); + //err = glGetError(); + std::vector result; + PickFace(x,y,m,result,width,height); + ScalarType LocalEpsilon(ScalarType(0.001)); + for(size_t i =0;i=0 && p[0]=0 && p[1]= ScalarType(p[2]+1.0)/2.0) + resultZ.push_back(result[i]); + } + } - delete [] buffer; - return resultZ.size(); - } - - -#ifdef _I_REALLY_NEED_OLD_GL_PICK_ - // Same of above but it also assumes that you want only visible faces. - // Visibility is computed according to the current depth buffer. - static int OldPickFaceVisible(int x, int y, MESH_TYPE &m, std::vector &resultZ, int width=4, int height=4, bool sorted=true) - { - // First step - - double mm[16]; - double mp[16]; - GLint vp[4]; - glGetIntegerv(GL_VIEWPORT,vp); - glGetDoublev(GL_MODELVIEW_MATRIX ,mm); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - int screenW = vp[2]-vp[0]; - int screenH = vp[3]-vp[1]; - - - GL_TYPE_NM::ScalarType *buffer = new GL_TYPE_NM::ScalarType[screenW*screenH]; - - //I'm not sure glReadPixels can accept GL_DOUBLE tag - //GLenum err = glGetError(); - glReadPixels(vp[0],vp[1],vp[2],vp[3],GL_DEPTH_COMPONENT,GL_TYPE_NM::SCALAR(),buffer); - //err = glGetError(); - - std::vector result; - OldPickFace(x,y,m,result,width,height,sorted); - ScalarType LocalEpsilon(0.001); - for(size_t i =0;i=0 && tx=0 && ty= tz) - resultZ.push_back(result[i]); - } - } - - delete [] buffer; - return resultZ.size(); - } - - static int OldPickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) - { - result.clear(); - if(width==0 ||height==0) return 0; - long hits; - int sz=m.face.size()*5; - GLuint *selectBuf =new GLuint[sz]; - // static unsigned int selectBuf[16384]; - glSelectBuffer(sz, selectBuf); - glRenderMode(GL_SELECT); - glInitNames(); - - /* Because LoadName() won't work with no names on the stack */ - glPushName(-1); - double mp[16]; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); - glLoadIdentity(); - //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); - gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - int fcnt=0; - FaceIterator fi; - for(fi=m.face.begin();fi!=m.face.end();++fi) - { - if(!(*fi).IsD()) - { - glLoadName(fcnt); - glBegin(GL_TRIANGLES); - glVertex( (*fi).V(0)->P() ); - glVertex( (*fi).V(1)->P() ); - glVertex( (*fi).V(2)->P() ); - glEnd(); - } - fcnt++; // the counter should advance even for deleted faces! - } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - hits = glRenderMode(GL_RENDER); - //xstring buf; - //if (hits <= 0) return 0; - std::vector< std::pair > H; - for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - if(sorted) - std::sort(H.begin(),H.end()); - // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); - result.resize(H.size()); - for(long ii=0;ii &result, int width=4, int height=4,bool sorted=true) - { - result.clear(); - if(width==0 ||height==0) return 0; - long hits; - int sz=m.vert.size()*5; - GLuint *selectBuf =new GLuint[sz]; - glSelectBuffer(sz, selectBuf); - glRenderMode(GL_SELECT); - glInitNames(); - - /* Because LoadName() won't work with no names on the stack */ - glPushName(-1); - double mp[16]; - - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - glMatrixMode(GL_PROJECTION); - glGetDoublev(GL_PROJECTION_MATRIX ,mp); - glPushMatrix(); - glLoadIdentity(); - gluPickMatrix(x, y, width, height, viewport); - glMultMatrixd(mp); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - int vcnt=0; - VertexIterator vi; - for(vi=m.vert.begin();vi!=m.vert.end();++vi) - { - if(!(*vi).IsD()) - { - glLoadName(vcnt); - glBegin(GL_POINTS); - glVertex( (*vi).P() ); - glEnd(); - } - vcnt++; // the counter should advance even for deleted faces! - } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - hits = glRenderMode(GL_RENDER); - std::vector< std::pair > H; - for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); - } - if(sorted) - std::sort(H.begin(),H.end()); - result.resize(H.size()); - for(long ii=0;ii GlCameraType; /// returns the OpenGL 4x4 MODELVIEW matrix that describes the shot position and orientation (extrinsics) -static void MatrixGL(ShotType & shot,vcg::Matrix44 & m) +static void MatrixGL(const ShotType & shot,vcg::Matrix44 & m) { m = shot.GetWorldToExtrinsicsMatrix(); } /// set the OpenGL MODELVIEW matrix to match the shot (extrinsics) -static void TransformGL(vcg::Shot & shot) +static void TransformGL(const vcg::Shot & shot) { vcg::Matrix44 m; MatrixGL(shot,m); @@ -109,7 +109,7 @@ static void TransformGL(vcg::Shot & shot) } /// set the OpenGL PROJECTION and MODELVIEW matrix to match camera+shot. requires near and far plane -static void SetView(vcg::Shot & shot, ScalarType nearDist, ScalarType farDist) +static void SetView(const vcg::Shot & shot, ScalarType nearDist, ScalarType farDist) { assert(glGetError() == 0); glMatrixMode(GL_PROJECTION); @@ -170,7 +170,7 @@ static ScalarType GetFarPlane(vcg::Shot & shot, vcg::Box3 & shot, vcg::Box3 bbox, ScalarType &nr, ScalarType &fr) +static void GetNearFarPlanes(const vcg::Shot & shot, vcg::Box3 bbox, ScalarType &nr, ScalarType &fr) { vcg::Point3 zaxis = shot.Axis(2); ScalarType offset = zaxis * shot.GetViewPoint(); diff --git a/wrap/igl/smooth_field.h b/wrap/igl/smooth_field.h index bc3ad19f..9629a883 100644 --- a/wrap/igl/smooth_field.h +++ b/wrap/igl/smooth_field.h @@ -264,6 +264,14 @@ class FieldSmoother mesh.face[i].PD2()=dir2*Norm2; } #else + (void)mesh; + (void)HardI; + (void)HardD; + (void)SoftI; + (void)SoftD; + (void)SoftW; + (void)alpha_soft; + (void)Ndir; assert(0); #endif } diff --git a/wrap/io_trimesh/alnParser.h b/wrap/io_trimesh/alnParser.h index 1e7fd4a4..1e18593a 100644 --- a/wrap/io_trimesh/alnParser.h +++ b/wrap/io_trimesh/alnParser.h @@ -2,7 +2,7 @@ * MeshLab o o * * An extendible mesh processor o o * * _ O _ * -* Copyright(C) 2005, 2009 \/)\/ * +* Copyright(C) 2005, 2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -30,126 +30,124 @@ struct RangeMap { - RangeMap() - { - quality = 1.0f; - } + RangeMap() : quality(1.0f) {} - std::string filename; - Matrix44m transformation; - float quality; + std::string filename; + vcg::Matrix44d transformation; + float quality; }; class ALNParser { public: - enum ALNParserCodes {NoError, CantOpen, UnexpectedEOF, ExpectingComment}; + enum ALNParserCodes {NoError, CantOpen, UnexpectedEOF, ExpectingComment}; - static const char* ErrorMsg(int message_code) - { - static const char* error_msg[4] = {"No errors", "Can't open file", "Premature End of file", "I was expecting a comment"}; + static const char* ErrorMsg(int message_code) + { + static const char* error_msg[4] = {"No errors", "Can't open file", "Premature End of file", "I was expecting a comment"}; - if(message_code>3 || message_code<0) - return "Unknown error"; - else - return error_msg[message_code]; - }; + if(message_code>3 || message_code<0) + return "Unknown error"; + else + return error_msg[message_code]; + }; - static int BuildALN(std::vector &rangemaps, std::vector< std::string > &files) - { - rangemaps.clear(); - rangemaps.resize( files.size() ); - std::vector< RangeMap >::iterator rm = rangemaps.begin(); - std::vector< std::string >::iterator it = files.begin(); - std::vector< std::string >::iterator end = files.end(); - for ( ; it!=end; it++, rm++) - { - (*rm).filename = (*it); - (*rm).quality = 1.0f; - (*rm).transformation.SetIdentity(); - } - files.clear(); - return NoError; - }; + static int BuildALN(std::vector &rangemaps, std::vector< std::string > &files) + { + rangemaps.clear(); + rangemaps.resize( files.size() ); + std::vector< RangeMap >::iterator rm = rangemaps.begin(); + std::vector< std::string >::iterator it = files.begin(); + std::vector< std::string >::iterator end = files.end(); + for ( ; it!=end; it++, rm++) + { + (*rm).filename = (*it); + (*rm).quality = 1.0f; + (*rm).transformation.SetIdentity(); + } + files.clear(); + return NoError; + }; - static int ParseALN(std::vector &rangemaps, const char *ALNname) - { - rangemaps.clear(); + static int ParseALN(std::vector &rangemaps, const char *ALNname) + { + rangemaps.clear(); - FILE *stream=fopen(ALNname, "rt"); - if(stream==NULL) - return CantOpen; + FILE *stream=fopen(ALNname, "rt"); + if(stream==NULL) + return CantOpen; - int mesh_number; - fscanf(stream, "%i\n", &mesh_number); + int mesh_number; + fscanf(stream, "%i\n", &mesh_number); - char buffer[1024]; - for (int m=0; m0); + char *occurrence = strchr(buffer, 'W'); + if(occurrence!=NULL && occurrence[1]==':') + rm.quality = (float) atof(occurrence+2); + assert(rm.quality>0); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[0][0]),&(rm.transformation[0][1]),&(rm.transformation[0][2]),&(rm.transformation[0][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[1][0]),&(rm.transformation[1][1]),&(rm.transformation[1][2]),&(rm.transformation[1][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[2][0]),&(rm.transformation[2][1]),&(rm.transformation[2][2]),&(rm.transformation[2][3])); - fscanf(stream,"%f %f %f %f \n",&(rm.transformation[3][0]),&(rm.transformation[3][1]),&(rm.transformation[3][2]),&(rm.transformation[3][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[0][0]),&(rm.transformation[0][1]),&(rm.transformation[0][2]),&(rm.transformation[0][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[1][0]),&(rm.transformation[1][1]),&(rm.transformation[1][2]),&(rm.transformation[1][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[2][0]),&(rm.transformation[2][1]),&(rm.transformation[2][2]),&(rm.transformation[2][3])); + fscanf(stream,"%lf %lf %lf %lf \n",&(rm.transformation[3][0]),&(rm.transformation[3][1]),&(rm.transformation[3][2]),&(rm.transformation[3][3])); - rangemaps.push_back(rm); - } - fclose(stream); - return NoError; - } // end of ParseALN + rangemaps.push_back(rm); + } + fclose(stream); + return NoError; + } // end of ParseALN -static bool SaveALN(const char *alnfile, std::vector &names) -{ - std::vector Tr(names.size()); - for(int i=0; i < static_cast(Tr.size()); ++i) Tr[i].SetIdentity(); - return SaveALN(alnfile,names, Tr); -} -template -static bool SaveALN(const char *alnfile, std::vector &names, std::vector > &Tr) -{ - // printf("Saving aln file %s\n",alnfile); - FILE *fp=fopen(alnfile,"w"); - if(!fp) - { - printf("unable to open file %s\n",alnfile); - return false; - } + static bool SaveALN(const char *alnfile, std::vector &names) + { + std::vector Tr(names.size()); + for(int i=0; i < static_cast(Tr.size()); ++i) Tr[i].SetIdentity(); + return SaveALN(alnfile,names, Tr); + } - fprintf(fp,"%i\n",(int)names.size()); - for(int i=0;i < static_cast(names.size());++i) - { - fprintf(fp,"%s\n",names[i].c_str()); + template + static bool SaveALN(const char *alnfile, std::vector &names, std::vector > &Tr) + { + // printf("Saving aln file %s\n",alnfile); + FILE *fp=fopen(alnfile,"w"); + if(!fp) + { + printf("unable to open file %s\n",alnfile); + return false; + } - fprintf(fp,"#\n"); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][0][0]),(Tr[i][0][1]),(Tr[i][0][2]),(Tr[i][0][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][1][0]),(Tr[i][1][1]),(Tr[i][1][2]),(Tr[i][1][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][2][0]),(Tr[i][2][1]),(Tr[i][2][2]),(Tr[i][2][3])); - fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][3][0]),(Tr[i][3][1]),(Tr[i][3][2]),(Tr[i][3][3])); - } - fprintf(fp,"0\n"); + fprintf(fp,"%i\n",(int)names.size()); + for(int i=0;i < static_cast(names.size());++i) + { + fprintf(fp,"%s\n",names[i].c_str()); - fclose(fp); - return true; -} + fprintf(fp,"#\n"); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][0][0]),(Tr[i][0][1]),(Tr[i][0][2]),(Tr[i][0][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][1][0]),(Tr[i][1][1]),(Tr[i][1][2]),(Tr[i][1][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][2][0]),(Tr[i][2][1]),(Tr[i][2][2]),(Tr[i][2][3])); + fprintf(fp,"%lf %lf %lf %lf \n",(Tr[i][3][0]),(Tr[i][3][1]),(Tr[i][3][2]),(Tr[i][3][3])); + } + fprintf(fp,"0\n"); + + fclose(fp); + return true; + } }; diff --git a/wrap/io_trimesh/export_idtf.h b/wrap/io_trimesh/export_idtf.h index ac393c40..e711ee61 100644 --- a/wrap/io_trimesh/export_idtf.h +++ b/wrap/io_trimesh/export_idtf.h @@ -159,7 +159,8 @@ public: tga.colourmaptype = 0; tga.imagetype = 2; - memset(tga.colormapspecs,0,5); + for (unsigned int i = 0; i < 5; ++i) + tga.colormapspecs[i] = '\0'; tga.xstart = (short) im.offset().x(); tga.ystart = (short) im.offset().y(); tga.height = (short) im.height(); @@ -180,10 +181,10 @@ public: //is a 8-digits binary number code // always 0 0 | mirroring | bits //(future uses)| image | for alpha-channel - //-------------------------------------------- - // 7 6 | 5 4 | 3 2 1 0 //-------------------------------------------- - // 0 0 | 1 0 | 1 0 0 0 + // 7 6 | 5 4 | 3 2 1 0 + //-------------------------------------------- + // 0 0 | 1 0 | 1 0 0 0 tga.descriptor = (char) 40; tga.bits = (char) 32; } diff --git a/wrap/io_trimesh/export_off.h b/wrap/io_trimesh/export_off.h index 3a9fec97..d4b8435b 100644 --- a/wrap/io_trimesh/export_off.h +++ b/wrap/io_trimesh/export_off.h @@ -104,10 +104,17 @@ public: tri::UpdateFlags::FaceClearV(m); for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if (!fi->IsD()) if (!fi->IsV()) { vcg::tri::PolygonSupport::ExtractPolygon(&*fi,polygon); + //not sure why this std::reverse is needed. ExtractPolygon is used in + //many other functions, and nobody complained. however, this list is + //clockwise wrt fi normal. + std::reverse(polygon.begin(), polygon.end()); if(!polygon.empty()) { fprintf(fpout,"%d ", int(polygon.size()) ); - for (size_t i=0; iFlags() ); + for (size_t i=0; iC()[0],fi->C()[1],fi->C()[2] ); fprintf(fpout,"\n"); } } diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index d2c9d3cf..c69106b2 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -34,827 +34,936 @@ #include #include #include - +#include #include namespace vcg { - namespace tri { - namespace io { +namespace tri { +namespace io { - template - class ExporterPLY - { - // Si occupa di convertire da un tipo all'altro. - // usata nella saveply per matchare i tipi tra stotype e memtype. - // Ad es se in memoria c'e' un int e voglio salvare un float - // src sara in effetti un puntatore a int il cui valore deve - // essere convertito al tipo di ritorno desiderato (stotype) +template +class ExporterPLY +{ + // Si occupa di convertire da un tipo all'altro. + // usata nella saveply per matchare i tipi tra stotype e memtype. + // Ad es se in memoria c'e' un int e voglio salvare un float + // src sara in effetti un puntatore a int il cui valore deve + // essere convertito al tipo di ritorno desiderato (stotype) - template - static void PlyConv(int mem_type, void *src, StoType &dest) - { - switch (mem_type){ - case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; - case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; - case ply::T_INT : dest = (StoType) (* ((int *) src)); break; - case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; - case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; - case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; - default : assert(0); - } - } + template + static void PlyConv(int mem_type, void *src, StoType &dest) + { + switch (mem_type){ + case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; + case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; + case ply::T_INT : dest = (StoType) (* ((int *) src)); break; + case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; + case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; + case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; + default : assert(0); + } + } - public: - typedef ::vcg::ply::PropDescriptor PropDescriptor ; - typedef typename SaveMeshType::ConstVertexPointer VertexPointer; - typedef typename SaveMeshType::ScalarType ScalarType; - typedef typename SaveMeshType::VertexType VertexType; - typedef typename SaveMeshType::FaceType FaceType; - typedef typename SaveMeshType::ConstFacePointer FacePointer; - typedef typename SaveMeshType::ConstVertexIterator VertexIterator; - typedef typename SaveMeshType::ConstFaceIterator FaceIterator; - typedef typename SaveMeshType::ConstEdgeIterator EdgeIterator; - typedef typename vcg::Shot::ScalarType ShotScalarType; +public: + typedef ::vcg::ply::PropDescriptor PropDescriptor ; + typedef typename SaveMeshType::ConstVertexPointer VertexPointer; + typedef typename SaveMeshType::ScalarType ScalarType; + typedef typename SaveMeshType::VertexType VertexType; + typedef typename SaveMeshType::FaceType FaceType; + typedef typename SaveMeshType::ConstFacePointer FacePointer; + typedef typename SaveMeshType::ConstVertexIterator VertexIterator; + typedef typename SaveMeshType::ConstFaceIterator FaceIterator; + typedef typename SaveMeshType::ConstEdgeIterator EdgeIterator; + typedef typename vcg::Shot::ScalarType ShotScalarType; - static int Save(const SaveMeshType &m, const char * filename, bool binary=true) - { - PlyInfo pi; - return Save(m,filename,binary,pi); - } + static int Save(const SaveMeshType &m, const char * filename, bool binary=true) + { + PlyInfo pi; + return Save(m,filename,binary,pi); + } - static int Save(const SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) - { - PlyInfo pi; - pi.mask=savemask; - return Save(m,filename,binary,pi,cb); - } + static int Save(const SaveMeshType &m, const char * filename, int savemask, bool binary = true, CallBackPos *cb=0 ) + { + PlyInfo pi; + pi.mask=savemask; + return Save(m,filename,binary,pi,cb); + } - static int Save(const SaveMeshType &m, const char * filename, bool binary, const PlyInfo &pi, CallBackPos *cb=0) // V1.0 - { - FILE * fpout; - const char * hbin = "binary_little_endian"; - const char * hasc = "ascii"; - const char * h; - //Coord ScalarType - const int DGT = vcg::tri::io::Precision::digits(); - const int DGTS = vcg::tri::io::Precision::digits(); - const int DGTVQ = vcg::tri::io::Precision::digits(); - const int DGTVR = vcg::tri::io::Precision::digits(); - const int DGTFQ = vcg::tri::io::Precision::digits(); - bool saveTexIndexFlag = false; + static int Save(const SaveMeshType &m, const char * filename, bool binary, const PlyInfo &pi, CallBackPos *cb=0) // V1.0 + { + FILE * fpout; + const char * hbin = "binary_little_endian"; + const char * hasc = "ascii"; + const char * h; + //Coord ScalarType + const int DGT = vcg::tri::io::Precision::digits(); + const int DGTS = vcg::tri::io::Precision::digits(); + const int DGTVQ = vcg::tri::io::Precision::digits(); + const int DGTVR = vcg::tri::io::Precision::digits(); + const int DGTVT = vcg::tri::io::Precision::digits(); + const int DGTFQ = vcg::tri::io::Precision::digits(); + const int DGTFT = vcg::tri::io::Precision::digits(); + bool saveTexIndexFlag = false; - if(binary) h=hbin; - else h=hasc; + if(binary) h=hbin; + else h=hasc; - fpout = fopen(filename,"wb"); - if(fpout==NULL) { - //pi.status=::vcg::ply::E_CANTOPEN; - return ::vcg::ply::E_CANTOPEN; - } - fprintf(fpout, - "ply\n" - "format %s 1.0\n" - "comment VCGLIB generated\n" - ,h - ); + fpout = fopen(filename,"wb"); + if(fpout==NULL) { + //pi.status=::vcg::ply::E_CANTOPEN; + return ::vcg::ply::E_CANTOPEN; + } + fprintf(fpout, + "ply\n" + "format %s 1.0\n" + "comment VCGLIB generated\n" , + h); - if (((pi.mask & Mask::IOM_WEDGTEXCOORD) != 0) || ((pi.mask & Mask::IOM_VERTTEXCOORD) != 0)) - { - const char * TFILE = "TextureFile"; + if (((pi.mask & Mask::IOM_WEDGTEXCOORD) != 0) || ((pi.mask & Mask::IOM_VERTTEXCOORD) != 0)) + { + const char * TFILE = "TextureFile"; - for(size_t i=0; i < m.textures.size(); ++i) - fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) ); + for(size_t i=0; i < m.textures.size(); ++i) + fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) ); - if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) saveTexIndexFlag = true; - } + if(m.textures.size()>1 && (HasPerWedgeTexCoord(m) || HasPerVertexTexCoord(m))) saveTexIndexFlag = true; + } - if((pi.mask & Mask::IOM_CAMERA)) - { - const char* cmtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"element camera 1\n"); - fprintf(fpout,"property %s view_px\n",cmtp); - fprintf(fpout,"property %s view_py\n",cmtp); - fprintf(fpout,"property %s view_pz\n",cmtp); - fprintf(fpout,"property %s x_axisx\n",cmtp); - fprintf(fpout,"property %s x_axisy\n",cmtp); - fprintf(fpout,"property %s x_axisz\n",cmtp); - fprintf(fpout,"property %s y_axisx\n",cmtp); - fprintf(fpout,"property %s y_axisy\n",cmtp); - fprintf(fpout,"property %s y_axisz\n",cmtp); - fprintf(fpout,"property %s z_axisx\n",cmtp); - fprintf(fpout,"property %s z_axisy\n",cmtp); - fprintf(fpout,"property %s z_axisz\n",cmtp); - fprintf(fpout,"property %s focal\n",cmtp); - fprintf(fpout,"property %s scalex\n",cmtp); - fprintf(fpout,"property %s scaley\n",cmtp); - fprintf(fpout,"property %s centerx\n",cmtp); - fprintf(fpout,"property %s centery\n",cmtp); - fprintf(fpout,"property int viewportx\n"); - fprintf(fpout,"property int viewporty\n"); - fprintf(fpout,"property %s k1\n",cmtp); - fprintf(fpout,"property %s k2\n",cmtp); - fprintf(fpout,"property %s k3\n",cmtp); - fprintf(fpout,"property %s k4\n",cmtp); - } + if((pi.mask & Mask::IOM_CAMERA)) + { + const char* cmtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"element camera 1\n"); + fprintf(fpout,"property %s view_px\n",cmtp); + fprintf(fpout,"property %s view_py\n",cmtp); + fprintf(fpout,"property %s view_pz\n",cmtp); + fprintf(fpout,"property %s x_axisx\n",cmtp); + fprintf(fpout,"property %s x_axisy\n",cmtp); + fprintf(fpout,"property %s x_axisz\n",cmtp); + fprintf(fpout,"property %s y_axisx\n",cmtp); + fprintf(fpout,"property %s y_axisy\n",cmtp); + fprintf(fpout,"property %s y_axisz\n",cmtp); + fprintf(fpout,"property %s z_axisx\n",cmtp); + fprintf(fpout,"property %s z_axisy\n",cmtp); + fprintf(fpout,"property %s z_axisz\n",cmtp); + fprintf(fpout,"property %s focal\n",cmtp); + fprintf(fpout,"property %s scalex\n",cmtp); + fprintf(fpout,"property %s scaley\n",cmtp); + fprintf(fpout,"property %s centerx\n",cmtp); + fprintf(fpout,"property %s centery\n",cmtp); + fprintf(fpout,"property int viewportx\n"); + fprintf(fpout,"property int viewporty\n"); + fprintf(fpout,"property %s k1\n",cmtp); + fprintf(fpout,"property %s k2\n",cmtp); + fprintf(fpout,"property %s k3\n",cmtp); + fprintf(fpout,"property %s k4\n",cmtp); + } - const char* vttp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"element vertex %d\n",m.vn); - fprintf(fpout,"property %s x\n",vttp); - fprintf(fpout,"property %s y\n",vttp); - fprintf(fpout,"property %s z\n",vttp); + const char* vttp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"element vertex %d\n",m.vn); + fprintf(fpout,"property %s x\n",vttp); + fprintf(fpout,"property %s y\n",vttp); + fprintf(fpout,"property %s z\n",vttp); - if( HasPerVertexNormal(m) &&( pi.mask & Mask::IOM_VERTNORMAL) ) - { - fprintf(fpout,"property %s nx\n",vttp); - fprintf(fpout,"property %s ny\n",vttp); - fprintf(fpout,"property %s nz\n",vttp); - } + if( HasPerVertexNormal(m) &&( pi.mask & Mask::IOM_VERTNORMAL) ) + { + fprintf(fpout,"property %s nx\n",vttp); + fprintf(fpout,"property %s ny\n",vttp); + fprintf(fpout,"property %s nz\n",vttp); + } - if( HasPerVertexFlags(m) &&( pi.mask & Mask::IOM_VERTFLAGS) ) - { - fprintf(fpout, - "property int flags\n" - ); - } + if( HasPerVertexFlags(m) &&( pi.mask & Mask::IOM_VERTFLAGS) ) + { + fprintf(fpout, + "property int flags\n"); + } - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) - { - fprintf(fpout, - "property uchar red\n" - "property uchar green\n" - "property uchar blue\n" - "property uchar alpha\n" - ); - } + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) + { + fprintf(fpout, + "property uchar red\n" + "property uchar green\n" + "property uchar blue\n" + "property uchar alpha\n"); + } - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) - { - const char* vqtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s quality\n",vqtp); - } + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) + { + const char* vqtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"property %s quality\n",vqtp); + } - if( tri::HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) - { - const char* rdtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s radius\n",rdtp); - } - if( ( HasPerVertexTexCoord(m) && pi.mask & Mask::IOM_VERTTEXCOORD ) ) - { - fprintf(fpout, - "property float texture_u\n" - "property float texture_v\n" - ); - } - for(size_t i=0;i::typeName(); + fprintf(fpout,"property %s radius\n",rdtp); + } + if( ( HasPerVertexTexCoord(m) && pi.mask & Mask::IOM_VERTTEXCOORD ) ) + { + const char* rdtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout, + "property %s texture_u\n" + "property %s texture_v\n", + rdtp, rdtp); + } + for(size_t i=0;i::typeName(); + fprintf(fpout, + "property list uchar %s texcoord\n", rdtp ); + } + // The texture index information has to be saved for each face (if necessary) both for PerVert and PerWedg + if( saveTexIndexFlag && + ( ( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) || + ( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) || + ( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) + ) + ) + { + fprintf(fpout, + "property int texnumber\n"); + } - if ( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) - { - fprintf(fpout, - "property list uchar float color\n" - ); - } + if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) + { + fprintf( + fpout, + "property uchar red\n" + "property uchar green\n" + "property uchar blue\n" + "property uchar alpha\n"); + } - if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) + if ( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) + { + fprintf( + fpout, + "property list uchar float color\n"); + } + + if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) + { + const char* fntp = vcg::tri::io::Precision::typeName(); + fprintf(fpout, "property %s nx\n", fntp); + fprintf(fpout, "property %s ny\n", fntp); + fprintf(fpout, "property %s nz\n", fntp); + } + + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + { + const char* fqtp = vcg::tri::io::Precision::typeName(); + fprintf(fpout,"property %s quality\n",fqtp); + } + + for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) + fprintf( + fpout, + "element edge %d\n" "property int vertex1\n""property int vertex2\n",m.en); + fprintf(fpout, "end_header\n" ); + + // Salvataggio camera + if((pi.mask & Mask::IOM_CAMERA)) + { + if(binary) + { + ShotScalarType t[17]; + + t[ 0] = (ShotScalarType)m.shot.Extrinsics.Tra()[0]; + t[ 1] = (ShotScalarType)m.shot.Extrinsics.Tra()[1]; + t[ 2] = (ShotScalarType)m.shot.Extrinsics.Tra()[2]; + t[ 3] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][0]; + t[ 4] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][1]; + t[ 5] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][2]; + t[ 6] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][0]; + t[ 7] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][1]; + t[ 8] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][2]; + t[ 9] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][0]; + t[10] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][1]; + t[11] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][2]; + t[12] = (ShotScalarType)m.shot.Intrinsics.FocalMm; + t[13] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[0]; + t[14] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[1]; + t[15] = (ShotScalarType)m.shot.Intrinsics.CenterPx[0]; + t[16] = (ShotScalarType)m.shot.Intrinsics.CenterPx[1]; + fwrite(t,sizeof(ShotScalarType),17,fpout); + + fwrite( &m.shot.Intrinsics.ViewportPx[0],sizeof(int),2,fpout ); + + t[ 0] = (ShotScalarType)m.shot.Intrinsics.k[0]; + t[ 1] = (ShotScalarType)m.shot.Intrinsics.k[1]; + t[ 2] = (ShotScalarType)m.shot.Intrinsics.k[2]; + t[ 3] = (ShotScalarType)m.shot.Intrinsics.k[3]; + fwrite(t,sizeof(ShotScalarType),4,fpout); + } + else + { + fprintf(fpout,"%.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %d %d %.*g %.*g %.*g %.*g\n" + ,DGTS,-m.shot.Extrinsics.Tra()[0] + ,DGTS,-m.shot.Extrinsics.Tra()[1] + ,DGTS,-m.shot.Extrinsics.Tra()[2] + ,DGTS,m.shot.Extrinsics.Rot()[0][0] + ,DGTS,m.shot.Extrinsics.Rot()[0][1] + ,DGTS,m.shot.Extrinsics.Rot()[0][2] + ,DGTS,m.shot.Extrinsics.Rot()[1][0] + ,DGTS,m.shot.Extrinsics.Rot()[1][1] + ,DGTS,m.shot.Extrinsics.Rot()[1][2] + ,DGTS,m.shot.Extrinsics.Rot()[2][0] + ,DGTS,m.shot.Extrinsics.Rot()[2][1] + ,DGTS,m.shot.Extrinsics.Rot()[2][2] + ,DGTS,m.shot.Intrinsics.FocalMm + ,DGTS,m.shot.Intrinsics.PixelSizeMm[0] + ,DGTS,m.shot.Intrinsics.PixelSizeMm[1] + ,DGTS,m.shot.Intrinsics.CenterPx[0] + ,DGTS,m.shot.Intrinsics.CenterPx[1] + ,m.shot.Intrinsics.ViewportPx[0] + ,m.shot.Intrinsics.ViewportPx[1] + ,DGTS,m.shot.Intrinsics.k[0] + ,DGTS,m.shot.Intrinsics.k[1] + ,DGTS,m.shot.Intrinsics.k[2] + ,DGTS,m.shot.Intrinsics.k[3] + ); + } + } + + + int j; + std::vector FlagV; + VertexPointer vp; + VertexIterator vi; + SimpleTempData indices(m.vert); + + std::vector > thfv(pi.VertDescriptorVec.size()); + std::vector > thdv(pi.VertDescriptorVec.size()); + std::vector > thiv(pi.VertDescriptorVec.size()); + std::vector > thsv(pi.VertDescriptorVec.size()); + std::vector > thcv(pi.VertDescriptorVec.size()); + std::vector > thuv(pi.VertDescriptorVec.size()); + std::vector > thp3fv(pi.VertDescriptorVec.size()); + std::vector > thp3dv(pi.VertDescriptorVec.size()); + + for(size_t i=0;i::typeName(); - fprintf(fpout, "property %s nx\n", fntp); - fprintf(fpout, "property %s ny\n", fntp); - fprintf(fpout, "property %s nz\n", fntp); + case ply::T_FLOAT : thfv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + default : assert(0); + } + } + else { + switch (pi.VertDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : thp3fv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + case ply::T_DOUBLE : thp3dv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; + default : assert(0); + } + } + } + } + std::vector > thff(pi.FaceDescriptorVec.size()); + std::vector > thdf(pi.FaceDescriptorVec.size()); + std::vector > thif(pi.FaceDescriptorVec.size()); + std::vector > thsf(pi.FaceDescriptorVec.size()); + std::vector > thcf(pi.FaceDescriptorVec.size()); + std::vector > thuf(pi.FaceDescriptorVec.size()); + std::vector > thp3ff(pi.FaceDescriptorVec.size()); + std::vector > thp3df(pi.FaceDescriptorVec.size()); + + for(size_t i=0;i::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + default : assert(0); + } + } + else { + switch (pi.FaceDescriptorVec[i].stotype1) + { + case ply::T_FLOAT : thp3ff[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + case ply::T_DOUBLE : thp3df[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; + default : assert(0); + } + } + } + } + + for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){ + vp=&(*vi); + indices[vi] = j; + //((m.vn+m.fn) != 0) all vertices and faces have been marked as deleted but the are still in the vert/face vectors + if(cb && ((j%1000)==0) && ((m.vn+m.fn) != 0) )(*cb)( (100*j)/(m.vn+m.fn), "Saving Vertices"); + + if( !HasPerVertexFlags(m) || !vp->IsD() ) + { + if(binary) + { + ScalarType t; + + t = ScalarType(vp->P()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->P()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->P()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + + if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) + { + t = ScalarType(vp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(vp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + } + if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) ) + fwrite(&(vp->Flags()),sizeof(int),1,fpout); + + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ){ + auto c = vp->C(); + fwrite(&c,sizeof(char),4,fpout); } - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - { - const char* fqtp = vcg::tri::io::Precision::typeName(); - fprintf(fpout,"property %s quality\n",fqtp); - } + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ){ + auto q = vp->Q(); + fwrite(&q, sizeof(typename VertexType::QualityType),1,fpout); + } - for(size_t i=0;i0 && (pi.mask & Mask::IOM_EDGEINDEX) ) - fprintf(fpout, - "element edge %d\n" - "property int vertex1\n" - "property int vertex2\n" - ,m.en - ); - fprintf(fpout, "end_header\n" ); + if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ){ + auto r = vp->R(); + fwrite(&r,sizeof(typename VertexType::RadiusType),1,fpout); + } - // Salvataggio camera - if((pi.mask & Mask::IOM_CAMERA)) - { - if(binary) - { - ShotScalarType t[17]; + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ){ + typename VertexType::TexCoordType::ScalarType t; + t = ScalarType(vp->T().u()); fwrite(&t,sizeof(typename VertexType::TexCoordType::ScalarType),1,fpout); + t = ScalarType(vp->T().v()); fwrite(&t,sizeof(typename VertexType::TexCoordType::ScalarType),1,fpout); + } - t[ 0] = (ShotScalarType)m.shot.Extrinsics.Tra()[0]; - t[ 1] = (ShotScalarType)m.shot.Extrinsics.Tra()[1]; - t[ 2] = (ShotScalarType)m.shot.Extrinsics.Tra()[2]; - t[ 3] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][0]; - t[ 4] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][1]; - t[ 5] = (ShotScalarType)m.shot.Extrinsics.Rot()[0][2]; - t[ 6] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][0]; - t[ 7] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][1]; - t[ 8] = (ShotScalarType)m.shot.Extrinsics.Rot()[1][2]; - t[ 9] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][0]; - t[10] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][1]; - t[11] = (ShotScalarType)m.shot.Extrinsics.Rot()[2][2]; - t[12] = (ShotScalarType)m.shot.Intrinsics.FocalMm; - t[13] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[0]; - t[14] = (ShotScalarType)m.shot.Intrinsics.PixelSizeMm[1]; - t[15] = (ShotScalarType)m.shot.Intrinsics.CenterPx[0]; - t[16] = (ShotScalarType)m.shot.Intrinsics.CenterPx[1]; - fwrite(t,sizeof(ShotScalarType),17,fpout); - - fwrite( &m.shot.Intrinsics.ViewportPx[0],sizeof(int),2,fpout ); - - t[ 0] = (ShotScalarType)m.shot.Intrinsics.k[0]; - t[ 1] = (ShotScalarType)m.shot.Intrinsics.k[1]; - t[ 2] = (ShotScalarType)m.shot.Intrinsics.k[2]; - t[ 3] = (ShotScalarType)m.shot.Intrinsics.k[3]; - fwrite(t,sizeof(ShotScalarType),4,fpout); - } - else - { - fprintf(fpout,"%.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %.*g %d %d %.*g %.*g %.*g %.*g\n" - ,DGTS,-m.shot.Extrinsics.Tra()[0] - ,DGTS,-m.shot.Extrinsics.Tra()[1] - ,DGTS,-m.shot.Extrinsics.Tra()[2] - ,DGTS,m.shot.Extrinsics.Rot()[0][0] - ,DGTS,m.shot.Extrinsics.Rot()[0][1] - ,DGTS,m.shot.Extrinsics.Rot()[0][2] - ,DGTS,m.shot.Extrinsics.Rot()[1][0] - ,DGTS,m.shot.Extrinsics.Rot()[1][1] - ,DGTS,m.shot.Extrinsics.Rot()[1][2] - ,DGTS,m.shot.Extrinsics.Rot()[2][0] - ,DGTS,m.shot.Extrinsics.Rot()[2][1] - ,DGTS,m.shot.Extrinsics.Rot()[2][2] - ,DGTS,m.shot.Intrinsics.FocalMm - ,DGTS,m.shot.Intrinsics.PixelSizeMm[0] - ,DGTS,m.shot.Intrinsics.PixelSizeMm[1] - ,DGTS,m.shot.Intrinsics.CenterPx[0] - ,DGTS,m.shot.Intrinsics.CenterPx[1] - ,m.shot.Intrinsics.ViewportPx[0] - ,m.shot.Intrinsics.ViewportPx[1] - ,DGTS,m.shot.Intrinsics.k[0] - ,DGTS,m.shot.Intrinsics.k[1] - ,DGTS,m.shot.Intrinsics.k[2] - ,DGTS,m.shot.Intrinsics.k[3] - ); - } - } - - - int j; - std::vector FlagV; - VertexPointer vp; - VertexIterator vi; - SimpleTempData indices(m.vert); - - std::vector > thfv(pi.VertDescriptorVec.size()); - std::vector > thdv(pi.VertDescriptorVec.size()); - std::vector > thiv(pi.VertDescriptorVec.size()); - std::vector > thsv(pi.VertDescriptorVec.size()); - std::vector > thcv(pi.VertDescriptorVec.size()); - std::vector > thuv(pi.VertDescriptorVec.size()); - - for(size_t i=0;i::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_DOUBLE : thdv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_INT : thiv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_SHORT : thsv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_CHAR : thcv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - case ply::T_UCHAR : thuv[i] = vcg::tri::Allocator::template FindPerVertexAttribute(m,pi.VertAttrNameVec[i]); break; - default : assert(0); - } - } - } - std::vector > thff(pi.FaceDescriptorVec.size()); - std::vector > thdf(pi.FaceDescriptorVec.size()); - std::vector > thif(pi.FaceDescriptorVec.size()); - std::vector > thsf(pi.FaceDescriptorVec.size()); - std::vector > thcf(pi.FaceDescriptorVec.size()); - std::vector > thuf(pi.FaceDescriptorVec.size()); - - for(size_t i=0;i::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_DOUBLE : thdf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_INT : thif[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_SHORT : thsf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_CHAR : thcf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - case ply::T_UCHAR : thuf[i] = vcg::tri::Allocator::template FindPerFaceAttribute(m,pi.FaceAttrNameVec[i]); break; - default : assert(0); - } - } - } - - - - - for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){ - vp=&(*vi); - indices[vi] = j; - //((m.vn+m.fn) != 0) all vertices and faces have been marked as deleted but the are still in the vert/face vectors - if(cb && ((j%1000)==0) && ((m.vn+m.fn) != 0) )(*cb)( (100*j)/(m.vn+m.fn), "Saving Vertices"); - - if( !HasPerVertexFlags(m) || !vp->IsD() ) - { - if(binary) - { - ScalarType t; - - t = ScalarType(vp->P()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->P()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->P()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); - - if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - { - t = ScalarType(vp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); - } - if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) ) - fwrite(&(vp->Flags()),sizeof(int),1,fpout); - - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ){ - auto c = vp->C(); - fwrite(&c,sizeof(char),4,fpout); - } - - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ){ - auto q = vp->Q(); - fwrite(&q, sizeof(typename VertexType::QualityType),1,fpout); - } - - if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ){ - auto r = vp->R(); - fwrite(&r,sizeof(typename VertexType::RadiusType),1,fpout); - } - - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) - { - t = ScalarType(vp->T().u()); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(vp->T().v()); fwrite(&t,sizeof(ScalarType),1,fpout); - } - - for(size_t i=0;iP()[0],DGT,vp->P()[1],DGT,vp->P()[2]); - - if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); - - if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) - fprintf(fpout,"%d ",vp->Flags()); - - if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) - fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); - - if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) - fprintf(fpout,"%.*g ",DGTVQ,vp->Q()); - - if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) - fprintf(fpout,"%.*g ",DGTVR,vp->R()); - - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) - fprintf(fpout,"%f %f",vp->T().u(),vp->T().v()); - - for(size_t i=0;iIsD() ) - { fcnt++; - if(binary) - { - vv[0]=indices[fp->cV(0)]; - vv[1]=indices[fp->cV(1)]; - vv[2]=indices[fp->cV(2)]; - fwrite(&b3char,sizeof(char),1,fpout); - fwrite(vv,sizeof(int),3,fpout); - - if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ){ - auto fl = fp->Flags(); - fwrite(&fl,sizeof(int),1,fpout); - } - - if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it... - { - fwrite(&b6char,sizeof(char),1,fpout); - float t[6]; - for(int k=0;k<3;++k) - { - t[k*2+0] = fp->V(k)->T().u(); - t[k*2+1] = fp->V(k)->T().v(); - } - fwrite(t,sizeof(float),6,fpout); - } - else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) - { - fwrite(&b6char,sizeof(char),1,fpout); - float t[6]; - for(int k=0;k<3;++k) - { - t[k*2+0] = fp->WT(k).u(); - t[k*2+1] = fp->WT(k).v(); - } - fwrite(t,sizeof(float),6,fpout); - } - - if(saveTexIndexFlag) - { - int t = fp->WT(0).n(); - fwrite(&t,sizeof(int),1,fpout); - } - - if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) - fwrite(&( fp->C() ),sizeof(char),4,fpout); - - - if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) - { - fwrite(&b9char,sizeof(char),1,fpout); - float t[3]; - for(int z=0;z<3;++z) - { - t[0] = float(fp->WC(z)[0])/255; - t[1] = float(fp->WC(z)[1])/255; - t[2] = float(fp->WC(z)[2])/255; - fwrite( t,sizeof(float),3,fpout); - } - } - - if( HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL) ) - { - ScalarType t; - t = ScalarType(fp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(fp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); - t = ScalarType(fp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + for(size_t i=0;iP()[0],DGT,vp->P()[1],DGT,vp->P()[2]); - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout); + if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) + fprintf(fpout,"%.*g %.*g %.*g " ,DGT,ScalarType(vp->N()[0]),DGT,ScalarType(vp->N()[1]),DGT,ScalarType(vp->N()[2])); + + if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) + fprintf(fpout,"%d ",vp->Flags()); + + if( HasPerVertexColor(m) && (pi.mask & Mask::IOM_VERTCOLOR) ) + fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); + + if( HasPerVertexQuality(m) && (pi.mask & Mask::IOM_VERTQUALITY) ) + fprintf(fpout,"%.*g ",DGTVQ,vp->Q()); + + if( HasPerVertexRadius(m) && (pi.mask & Mask::IOM_VERTRADIUS) ) + fprintf(fpout,"%.*g ",DGTVR,vp->R()); + + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_VERTTEXCOORD) ) + fprintf(fpout,"%.*g %.*g",DGTVT,vp->T().u(),DGTVT,vp->T().v()); + + for(size_t i=0;iIsD() ) + { fcnt++; + if(binary) + { + vv[0]=indices[fp->cV(0)]; + vv[1]=indices[fp->cV(1)]; + vv[2]=indices[fp->cV(2)]; + fwrite(&b3char,sizeof(char),1,fpout); + fwrite(vv,sizeof(int),3,fpout); + + if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS) ){ + auto fl = fp->Flags(); + fwrite(&fl,sizeof(int),1,fpout); + } + + if( HasPerVertexTexCoord(m) && (!HasPerWedgeTexCoord(m)) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // Note that you can save VT as WT if you really want it... + { + fwrite(&b6char,sizeof(char),1,fpout); + typename FaceType::TexCoordType::ScalarType t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->V(k)->T().u(); + t[k*2+1] = fp->V(k)->T().v(); + } + fwrite(t,sizeof(typename FaceType::TexCoordType::ScalarType),6,fpout); + } + else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) + { + fwrite(&b6char,sizeof(char),1,fpout); + typename FaceType::TexCoordType::ScalarType t[6]; + for(int k=0;k<3;++k) + { + t[k*2+0] = fp->WT(k).u(); + t[k*2+1] = fp->WT(k).v(); + } + fwrite(t,sizeof(typename FaceType::TexCoordType::ScalarType),6,fpout); + } + + if(saveTexIndexFlag) + { + int t = fp->WT(0).n(); + fwrite(&t,sizeof(int),1,fpout); + } + + if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) + fwrite(&( fp->C() ),sizeof(char),4,fpout); - for(size_t i=0;iVN()); - for(int k=0;kVN();++k) - fprintf(fpout,"%d ",indices[fp->cV(k)]); + if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) + { + fwrite(&b9char,sizeof(char),1,fpout); + float t[3]; + for(int z=0;z<3;++z) + { + t[0] = float(fp->WC(z)[0])/255; + t[1] = float(fp->WC(z)[1])/255; + t[2] = float(fp->WC(z)[2])/255; + fwrite( t,sizeof(float),3,fpout); + } + } - if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS )) - fprintf(fpout,"%d ",fp->Flags()); + if( HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL) ) + { + ScalarType t; + t = ScalarType(fp->N()[0]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(fp->N()[1]); fwrite(&t,sizeof(ScalarType),1,fpout); + t = ScalarType(fp->N()[2]); fwrite(&t,sizeof(ScalarType),1,fpout); + } - if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // you can save VT as WT if you really want it... - { - fprintf(fpout,"%d ",fp->VN()*2); - for(int k=0;kVN();++k) - fprintf(fpout,"%f %f " - ,fp->V(k)->T().u() - ,fp->V(k)->T().v() - ); - } - else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) - { - fprintf(fpout,"%d ",fp->VN()*2); - for(int k=0;kVN();++k) - fprintf(fpout,"%f %f " - ,fp->WT(k).u() - ,fp->WT(k).v() - ); - } - - if(saveTexIndexFlag) - { - fprintf(fpout,"%d ",fp->WT(0).n()); - } - - if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) - { - fprintf(fpout, "%u %u %u %u ", fp->C()[0], fp->C()[1], fp->C()[2], fp->C()[3]); - } - else if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) - { - fprintf(fpout,"9 "); - for(int z=0;z<3;++z) - fprintf(fpout,"%g %g %g " - ,double(fp->WC(z)[0])/255 - ,double(fp->WC(z)[1])/255 - ,double(fp->WC(z)[2])/255 - ); - } - - if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT, ScalarType(fp->N()[0]),DGT,ScalarType(fp->N()[1]),DGT,ScalarType(fp->N()[2])); - - if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) - fprintf(fpout,"%.*g ",DGTFQ,fp->Q()); - - for(size_t i=0;iIsD() ) - { - ++ecnt; - if(binary) - { - eauxvv[0]=indices[ei->cV(0)]; - eauxvv[1]=indices[ei->cV(1)]; - fwrite(eauxvv,sizeof(int),2,fpout); - } - else // ***** ASCII ***** - fprintf(fpout,"%d %d \n", indices[ei->cV(0)], indices[ei->cV(1)]); - } - } - assert(ecnt==m.en); - } - int result = 0; - if (ferror(fpout)) result = ply::E_STREAMERROR; - fclose(fpout); - return result; - } - - static const char *ErrorMsg(int error) - { - static std::vector ply_error_msg; - if(ply_error_msg.empty()) - { - ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); - ply_error_msg[ply::E_NOERROR ]="No errors"; - ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; - ply_error_msg[ply::E_NOTHEADER ]="Header not found"; - ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; - ply_error_msg[ply::E_NOFORMAT ]="Format not found"; - ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; - ply_error_msg[ply::E_PROPOUTOFELEMENT ]="Property without element"; - ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; - ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; - ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; - ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; - ply_error_msg[ply::E_INCOMPATIBLETYPE ]="Incompatible type"; - ply_error_msg[ply::E_BADCAST ]="Bad cast"; - - ply_error_msg[ply::E_STREAMERROR ] = "Output Stream Error"; - - ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; - ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; - ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; - ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; - ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; - ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; - ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; - } - - if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; - else return ply_error_msg[error].c_str(); - }; - - static int GetExportMaskCapability() - { - int capability = 0; - capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; - capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; - capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; - capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; - capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; - capability |= vcg::tri::io::Mask::IOM_VERTRADIUS ; - capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; - capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; - capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; - capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; - capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; - // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; - capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; - capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; - capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; - capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; - capability |= vcg::tri::io::Mask::IOM_CAMERA ; - capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; - return capability; - } + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + fwrite( &(fp->Q()),sizeof(typename FaceType::ScalarType),1,fpout); - }; // end class + for(size_t i=0;iVN()); + for(int k=0;kVN();++k) + fprintf(fpout,"%d ",indices[fp->cV(k)]); + + if(HasPerFaceFlags(m)&&( pi.mask & Mask::IOM_FACEFLAGS )) + fprintf(fpout,"%d ",fp->Flags()); + + if( HasPerVertexTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) // you can save VT as WT if you really want it... + { + fprintf(fpout,"%d ",fp->VN()*2); + for(int k=0;kVN();++k) + fprintf(fpout,"%.*g %.*g " + ,DGTFT,fp->V(k)->T().u() + ,DGTFT,fp->V(k)->T().v() + ); + } + else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) + { + fprintf(fpout,"%d ",fp->VN()*2); + for(int k=0;kVN();++k) + fprintf(fpout,"%f %f " + ,fp->WT(k).u() + ,fp->WT(k).v() + ); + } + + if(saveTexIndexFlag) + { + fprintf(fpout,"%d ",fp->WT(0).n()); + } + + if( HasPerFaceColor(m) && (pi.mask & Mask::IOM_FACECOLOR) ) + { + fprintf(fpout, "%u %u %u %u ", fp->C()[0], fp->C()[1], fp->C()[2], fp->C()[3]); + } + else if( HasPerWedgeColor(m) && (pi.mask & Mask::IOM_WEDGCOLOR) ) + { + fprintf(fpout,"9 "); + for(int z=0;z<3;++z) + fprintf(fpout,"%g %g %g " + ,double(fp->WC(z)[0])/255 + ,double(fp->WC(z)[1])/255 + ,double(fp->WC(z)[2])/255 + ); + } + + if (HasPerFaceNormal(m) && (pi.mask & Mask::IOM_FACENORMAL)) + fprintf(fpout,"%.*g %.*g %.*g " ,DGT, ScalarType(fp->N()[0]),DGT,ScalarType(fp->N()[1]),DGT,ScalarType(fp->N()[2])); + + if( HasPerFaceQuality(m) && (pi.mask & Mask::IOM_FACEQUALITY) ) + fprintf(fpout,"%.*g ",DGTFQ,fp->Q()); + + for(size_t i=0;iIsD() ) + { + ++ecnt; + if(binary) + { + eauxvv[0]=indices[ei->cV(0)]; + eauxvv[1]=indices[ei->cV(1)]; + fwrite(eauxvv,sizeof(int),2,fpout); + } + else // ***** ASCII ***** + fprintf(fpout,"%d %d \n", indices[ei->cV(0)], indices[ei->cV(1)]); + } + } + assert(ecnt==m.en); + } + int result = 0; + if (ferror(fpout)) result = ply::E_STREAMERROR; + fclose(fpout); + return result; + } + + static const char *ErrorMsg(int error) + { + static std::vector ply_error_msg; + if(ply_error_msg.empty()) + { + ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); + ply_error_msg[ply::E_NOERROR ]="No errors"; + ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; + ply_error_msg[ply::E_NOTHEADER ]="Header not found"; + ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; + ply_error_msg[ply::E_NOFORMAT ]="Format not found"; + ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; + ply_error_msg[ply::E_PROPOUTOFELEMENT ]="Property without element"; + ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; + ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; + ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; + ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; + ply_error_msg[ply::E_INCOMPATIBLETYPE ]="Incompatible type"; + ply_error_msg[ply::E_BADCAST ]="Bad cast"; + + ply_error_msg[ply::E_STREAMERROR ] = "Output Stream Error"; + + ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; + ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; + ply_error_msg[PlyInfo::E_SHORTFILE ]="Unexpected EOF"; + ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; + ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; + ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; + ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; + } + + if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; + else return ply_error_msg[error].c_str(); + }; + + static int GetExportMaskCapability() + { + int capability = 0; + capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; + capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; + capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; + capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; + capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; + capability |= vcg::tri::io::Mask::IOM_VERTRADIUS ; + capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; + capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; + capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; + capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; + capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; + // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; + capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; + capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; + capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; + capability |= vcg::tri::io::Mask::IOM_CAMERA ; + //capability |= vcg::tri::io::Mask::IOM_BITPOLYGONAL; + return capability; + } + + +}; // end class - } // end namespace tri - } // end namespace io +} // end namespace tri +} // end namespace io } // end namespace vcg //@} #endif diff --git a/wrap/io_trimesh/import_dae.h b/wrap/io_trimesh/import_dae.h index b4e0e09b..0dcaaa6f 100644 --- a/wrap/io_trimesh/import_dae.h +++ b/wrap/io_trimesh/import_dae.h @@ -397,14 +397,33 @@ namespace io { } // ind_txt = indexTextureByImgNode(*(info.doc),txt_node); } - int faceAttributeNum = triNodeList.at(tript).toElement().elementsByTagName("input").size(); + int triangleNumber = triNodeList.at(tript).toElement().attribute("count").toInt(); + + // A triangle can have multiple inputs that share a common offset. Therefore it's + // not sufficient to take the number of input to derive the stride from triangle to + // triangle. Instead, this heuristic uses the maximal offset found among inputs. + QDomNodeList attributes = triNodeList.at(tript).toElement().elementsByTagName("input"); + int numTriangleAttributeIndices = 0; + for (int i = 0; i < attributes.size(); ++i) { + QDomNode attr = attributes.at(i); + int offset = attr.toElement().attribute("offset", "-1").toInt(); + numTriangleAttributeIndices = std::max(numTriangleAttributeIndices, offset+1); + } QStringList face; valueStringList(face,triNodeList.at(tript),"p"); + + // Ensure that the

array size is consistent with the number of triangles and the + // exprected stride. + if (face.size() != 3 * triangleNumber * numTriangleAttributeIndices) { + QDEBUG("********* ERROR triangle count is inconsistent with input offsets and face index list"); + return E_INCOMPATIBLECOLLADA141FORMAT; + } + int offsetface = (int)m.face.size(); if (face.size() != 0) { - vcg::tri::Allocator::AddFaces(m,face.size() / (faceAttributeNum * 3)); + vcg::tri::Allocator::AddFaces(m, triangleNumber); WedgeAttribute wa; FindStandardWedgeAttributes(wa,triNodeList.at(tript),*(info.doc)); @@ -430,7 +449,7 @@ namespace io { WedgeTextureAttribute(m,face,ind_txt,wa.wt,wa.wtsrc,ff,jj + wa.offtx,tt,wa.stridetx); } - jj += faceAttributeNum; + jj += numTriangleAttributeIndices; } if( ! ( (m.face[ff].V(0) != m.face[ff].V(1)) && (m.face[ff].V(0) != m.face[ff].V(2)) && @@ -589,8 +608,13 @@ namespace io { } } - if (isTri && tripatch.isEmpty()) + if (isTri && tripatch.isEmpty()) { tripatch=polylist; + // Clear the polylist. Otherwise faces are loaded twice, once by + // LoadTriangularMesh and another time by LoadPolygonalListMesh. + polylist = QDomNodeList(); + } + if (tripatch.isEmpty() && polypatch.isEmpty() && polylist.isEmpty()) return E_NOPOLYGONALMESH; diff --git a/wrap/io_trimesh/import_nvm.h b/wrap/io_trimesh/import_nvm.h index 06f70ac5..8991855a 100644 --- a/wrap/io_trimesh/import_nvm.h +++ b/wrap/io_trimesh/import_nvm.h @@ -166,17 +166,17 @@ static int Open( OpenMeshType &m, std::vector > & shots, float x,y,z; unsigned int r,g,b,i_cam, key_sift,n_corr; uint readValues = fscanf(fp,"%f %f %f ",&x,&y,&z); - if (readValues < 3) qDebug() << "Point " << i << ": only " << readValues << " coordinates read!"; + if (readValues < 3) std::cerr << "Point " << i << ": only " << readValues << " coordinates read!"; (*vi).P() = vcg::Point3(x,y,z); readValues = fscanf(fp,"%d %d %d ",&r,&g,&b); - if (readValues < 3) qDebug() << "Point " << i << ": only " << readValues << " color values read!"; + if (readValues < 3) std::cerr << "Point " << i << ": only " << readValues << " color values read!"; (*vi).C() = vcg::Color4b(r,g,b,255); readValues = fscanf(fp,"%d ",&n_corr); - if (readValues < 1) qDebug() << "Point " << i << ": no n correspondences read!"; + if (readValues < 1) std::cerr << "Point " << i << ": no n correspondences read!"; for(uint j = 0; j < n_corr; ++j){ readValues = fscanf(fp,"%d %d %f %f ",&i_cam,&key_sift,&x,&y); - if (readValues != 3) qDebug() << "Point " << i << "; Corresp: " << j << ": only " << readValues << " values read!"; + if (readValues != 3) std::cerr << "Point " << i << "; Corresp: " << j << ": only " << readValues << " values read!"; Correspondence corr(i_cam,key_sift,x,y); ch[i].push_back(corr); } diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 9f9fa909..5b8ab94d 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -25,6 +25,8 @@ #ifndef __VCGLIB_IMPORT_OBJ #define __VCGLIB_IMPORT_OBJ +#include + #include #include #include @@ -958,136 +960,124 @@ public: return ret; } - static bool LoadMaterials(const char * filename, std::vector &materials, std::vector &textures) - { - // assumes we are in the right directory - - std::ifstream stream(filename); - if (stream.fail()) - return false; - - std::vector< std::string > tokens; - std::string line; - std::string header; - - materials.clear(); - Material currentMaterial; - - // Fill in some default values for the material - currentMaterial.index = (unsigned int)(-1); - currentMaterial.Ka = Point3f(0.2, 0.2, 0.2); - currentMaterial.Kd = Point3f(1, 1, 1); - currentMaterial.Ks = Point3f(1, 1, 1); - currentMaterial.Tr = 1; - currentMaterial.Ns = 0; - currentMaterial.illum = 2; - - bool first = true; - while (!stream.eof()) - { - tokens.clear(); - TokenizeNextLine(stream, tokens, line, 0); - - if (tokens.size() > 0) - { - header.clear(); - header = tokens[0]; - - if (header.compare("newmtl")==0) - { - if (!first) - { - materials.push_back(currentMaterial); - currentMaterial = Material(); - currentMaterial.index = (unsigned int)(-1); - } - else - first = false; - //strcpy(currentMaterial.name, tokens[1].c_str()); - if(tokens.size() < 2) - return false; - else if (tokens.size() == 2) - currentMaterial.materialName = tokens[1]; //play it safe - else - currentMaterial.materialName = line.substr(7); //space in the name, get everything after "newmtl " - } - else if (header.compare("Ka")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Ka = Point3fFrom3Tokens(tokens,1); - } - else if (header.compare("Kd")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Kd = Point3fFrom3Tokens(tokens,1); - } - else if (header.compare("Ks")==0) - { - if (tokens.size() < 4) return false; - currentMaterial.Ks = Point3fFrom3Tokens(tokens,1); - } - else if ( (header.compare("d")==0) || - (header.compare("Tr")==0) ) // alpha - { - if (tokens.size() < 2) return false; - currentMaterial.Tr = (float) atof(tokens[1].c_str()); - } - else if (header.compare("Ns")==0) // shininess - { - if (tokens.size() < 2) return false; - currentMaterial.Ns = float(atoi(tokens[1].c_str())); - } - else if (header.compare("illum")==0) // specular illumination on/off - { - if (tokens.size() < 2) return false; - currentMaterial.illum = atoi(tokens[1].c_str());; - } - else if(header.compare("map_Kd")==0) // texture name - { - std::string textureName; - if (tokens.size() < 2) - return false; - else if (tokens.size() == 2) - textureName = tokens[1]; //play it safe - else - textureName = line.substr(7); //get everything after "map_Kd " - - currentMaterial.map_Kd=textureName; - - // adding texture name into textures vector (if not already present) - // avoid adding the same name twice - auto it = std::find(textures.begin(), textures.end(), textureName); - if(it==textures.end()) { - currentMaterial.index = textures.size(); - textures.push_back(textureName); - } else { - currentMaterial.index = std::distance(textures.begin(),it); - } - } - // we simply ignore other situations - } - } - materials.push_back(currentMaterial); // add last read material - - stream.close(); - // Sometimes some materials have texture and no texture - // in this case for sake of uniformity we just use the first texture. - if(!textures.empty()) - { - for(size_t i=0;i &materials, std::vector &textures) + { + // assumes we are in the right directory + + std::ifstream stream(filename); + if (stream.fail()) + return false; + + std::vector< std::string > tokens; + std::string line; + std::string header; + + materials.clear(); + Material currentMaterial; + + // Fill in some default values for the material + currentMaterial.index = (unsigned int)(-1); + currentMaterial.Ka = Point3f(0.2, 0.2, 0.2); + currentMaterial.Kd = Point3f(1, 1, 1); + currentMaterial.Ks = Point3f(1, 1, 1); + currentMaterial.Tr = 1; + currentMaterial.Ns = 0; + currentMaterial.illum = 2; + + bool first = true; + while (!stream.eof()) { + tokens.clear(); + TokenizeNextLine(stream, tokens, line, 0); + + if (tokens.size() > 0) { + header.clear(); + header = tokens[0]; + + if (header.compare("newmtl")==0) { + if (!first) { + materials.push_back(currentMaterial); + currentMaterial = Material(); + currentMaterial.index = (unsigned int)(-1); + } + else + first = false; + //strcpy(currentMaterial.name, tokens[1].c_str()); + if(tokens.size() < 2) + return false; + else if (tokens.size() == 2) + currentMaterial.materialName = tokens[1]; //play it safe + else + currentMaterial.materialName = line.substr(7); //space in the name, get everything after "newmtl " + } + else if (header.compare("Ka")==0) { + if (tokens.size() < 4) { + currentMaterial.Ka = Point3fFrom3Tokens(tokens,1); + } + } + else if (header.compare("Kd")==0) { + if (tokens.size() < 4) { + currentMaterial.Kd = Point3fFrom3Tokens(tokens,1); + } + } + else if (header.compare("Ks")==0) { + if (tokens.size() < 4) { + currentMaterial.Ks = Point3fFrom3Tokens(tokens,1); + } + } + else if ((header.compare("d")==0) || (header.compare("Tr")==0)) { // alpha + if (tokens.size() < 2) { + currentMaterial.Tr = (float) atof(tokens[1].c_str()); + } + } + else if (header.compare("Ns")==0) { // shininess + if (tokens.size() < 2) { + currentMaterial.Ns = float(atoi(tokens[1].c_str())); + } + } + else if (header.compare("illum")==0) { // specular illumination on/off + if (tokens.size() < 2) { + currentMaterial.illum = atoi(tokens[1].c_str()); + } + } + else if(header.compare("map_Kd")==0) { // texture name + std::string textureName; + if (tokens.size() == 2) { + //the tex name is the last one (after any option) + textureName = tokens[tokens.size()-1]; + } + + currentMaterial.map_Kd=textureName; + + // adding texture name into textures vector (if not already present) + // avoid adding the same name twice + auto it = std::find(textures.begin(), textures.end(), textureName); + if(it==textures.end()) { + currentMaterial.index = textures.size(); + textures.push_back(textureName); + } else { + currentMaterial.index = std::distance(textures.begin(),it); + } + } + // we simply ignore other situations + } + } + materials.push_back(currentMaterial); // add last read material + + stream.close(); + // Sometimes some materials have texture and no texture + // in this case for sake of uniformity we just use the first texture. + if(!textures.empty()) { + for(size_t i=0;i + /** @name Load and Save in Ply format */ @@ -64,37 +66,123 @@ This class can be passed to the ImporterPLY::Open() function for class PlyInfo { public: - typedef ::vcg::ply::PropDescriptor PropDescriptor ; + typedef ::vcg::ply::PropDescriptor PropDescriptor ; - void AddPerElemFloatAttribute(int elemType, const char *attrName, const char * propName=0) - { - static const char *elemStr[2]={"vertex","face"}; - std::vector *elemDescVec[2]={&(this->VertDescriptorVec), &(this->FaceDescriptorVec)}; - std::vector *elemNameVec[2]={&(this->VertAttrNameVec), &(this->FaceAttrNameVec)}; + void addPerElemScalarAttribute(int elemType, vcg::ply::PlyTypes propertyType, const std::string& attrName, std::string propName="") + { + if(propName=="") + propName=attrName; - if(propName==0) propName=attrName; - elemDescVec[elemType]->push_back(PropDescriptor()); - elemNameVec[elemType]->push_back(attrName); - elemDescVec[elemType]->back().elemname=elemStr[elemType]; - elemDescVec[elemType]->back().propname=strdup(propName); - elemDescVec[elemType]->back().stotype1 = vcg::ply::T_FLOAT; - elemDescVec[elemType]->back().memtype1 = vcg::ply::T_FLOAT; - } + PropDescriptor p; + p.propname=propName; + p.islist = false; + p.stotype1 = propertyType; + p.memtype1 = propertyType; - void AddPerVertexFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(0,attrName,propName); - } - void AddPerFaceFloatAttribute(const char *attrName, const char *propName=0) { - AddPerElemFloatAttribute(1,attrName,propName); - } + if (elemType == 0){ //vertex + VertAttrNameVec.push_back(attrName); + p.elemname="vertex"; + VertDescriptorVec.push_back(p); + } + else if (elemType == 1){ //face + FaceAttrNameVec.push_back(attrName); + p.elemname="face"; + FaceDescriptorVec.push_back(p); + } + } + void AddPerElemFloatAttribute(int elemType, const std::string& attrName, std::string propName="") + { + addPerElemScalarAttribute(elemType, vcg::ply::T_FLOAT, attrName, propName); + } + + void AddPerElemDoubleAttribute(int elemType, const std::string& attrName, std::string propName="") + { + addPerElemScalarAttribute(elemType, vcg::ply::T_DOUBLE, attrName, propName); + } + + void addPerVertexScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemScalarAttribute(0,attrType, attrName,propName); + } + + void AddPerVertexFloatAttribute(const std::string& attrName, std::string propName="") + { + AddPerElemFloatAttribute(0,attrName,propName); + } + + void addPerFaceScalarAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemScalarAttribute(1,attrType, attrName,propName); + } + + void AddPerFaceFloatAttribute(const std::string& attrName, std::string propName="") + { + AddPerElemFloatAttribute(1,attrName,propName); + } + + void addPerElemPointAttribute(int elemType, vcg::ply::PlyTypes propertyType, const std::string& attrName, std::string propName="") + { + if(propName=="") + propName=attrName; + + PropDescriptor p; + p.propname=propName; + p.stotype1 = propertyType; + p.memtype1 = propertyType; + p.islist = true; + p.memtype2 = vcg::ply::PlyTypes::T_UCHAR; + p.stotype2 = vcg::ply::PlyTypes::T_UCHAR; + + if (elemType == 0){ //vertex + VertAttrNameVec.push_back(attrName); + p.elemname="vertex"; + VertDescriptorVec.push_back(p); + } + else if (elemType == 1){ //face + FaceAttrNameVec.push_back(attrName); + p.elemname="face"; + FaceDescriptorVec.push_back(p); + } + } + + void addPerVertexPoint3mAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemPointAttribute(0,attrType, attrName,propName); + } + + void addPerVertexPoint3fAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(0,vcg::ply::PlyTypes::T_FLOAT, attrName,propName); + } + + void addPerVertexPoint3dAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(0,vcg::ply::PlyTypes::T_DOUBLE, attrName,propName); + } + + void addPerFacePoint3mAttribute(const std::string& attrName, vcg::ply::PlyTypes attrType, std::string propName="") + { + addPerElemPointAttribute(1,attrType, attrName,propName); + } + + void addPerFacePoint3fAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(1,vcg::ply::PlyTypes::T_FLOAT, attrName,propName); + } + + void addPerFacePoint3dAttribute(const std::string& attrName, std::string propName="") + { + addPerElemPointAttribute(1,vcg::ply::PlyTypes::T_DOUBLE, attrName,propName); + } /* Note that saving a per vertex point3 attribute is a mess. * Actually require to allocate 3 float attribute and save them. And they are never deallocated... */ template - void AddPerVertexPoint3fAttribute(MeshType &m, const char *attrName, const char *propName="") + void AddPerVertexPoint3fAttribute(MeshType &m, const std::string& attrName, std::string propName="") { - if(propName==0) propName=attrName; + if(propName=="") + propName=attrName; const char *attrxyz[3] = { strdup((std::string(attrName)+std::string("_x")).c_str()), @@ -151,7 +239,7 @@ public: enum Error { - // Funzioni superiori + // Funzioni superiori E_NO_VERTEX = ply::E_MAXPLYERRORS+1, // 15 E_NO_FACE = ply::E_MAXPLYERRORS+2, // 16 E_SHORTFILE = ply::E_MAXPLYERRORS+3, // 17 diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 5a213560..e4110928 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -104,8 +104,8 @@ namespace nanoply NNP_BITFLAG = 0x00040000, /**< Bit flags. */ NNP_K1 = 0x00080000, /**< Main curvaure value k1. */ NNP_K2 = 0x00100000, /**< Main curvaure value k2. */ - NNP_KG = 0x00200000, /**< Gaussian curvature value. */ - NNP_KH = 0x00400000, /**< Mean curvature value. */ +// NNP_KG = 0x00200000, /**< Gaussian curvature value. */ +// NNP_KH = 0x00400000, /**< Mean curvature value. */ NNP_K1DIR = 0x00800000, /**< Curvature direction k1. */ NNP_K2DIR = 0x01000000, /**< Curvature direction k2. */ NNP_EDGE_V1 = 0x02000000, /**< Index of the first vertex of the edge. */ @@ -242,8 +242,8 @@ namespace nanoply { PlyEntity::NNP_BITFLAG, NameVector({ "flags" }) }, { PlyEntity::NNP_K1, NameVector({ "k1" }) }, { PlyEntity::NNP_K2, NameVector({ "k2" }) }, - { PlyEntity::NNP_KG, NameVector({ "k" }) }, - { PlyEntity::NNP_KH, NameVector({ "h" }) }, +// { PlyEntity::NNP_KG, NameVector({ "k" }) }, +// { PlyEntity::NNP_KH, NameVector({ "h" }) }, { PlyEntity::NNP_K1DIR, NameVector({ "k1dir" }) }, { PlyEntity::NNP_K2DIR, NameVector({ "k2dir" }) }, { PlyEntity::NNP_EDGE_V1, NameVector({ "vertex1", "v1" }) }, @@ -738,8 +738,8 @@ namespace nanoply case NNP_BITFLAG: return "NNP_BITFLAG "; case NNP_K1: return "NNP_K1 "; case NNP_K2: return "NNP_K2 "; - case NNP_KG: return "NNP_K "; - case NNP_KH: return "NNP_H "; +// case NNP_KG: return "NNP_K "; +// case NNP_KH: return "NNP_H "; case NNP_K1DIR: return "NNP_K1DIR "; case NNP_K2DIR: return "NNP_K2DIR "; case NNP_EDGE_V1: return "NNP_EDGE_V1 "; diff --git a/wrap/nanoply/include/nanoplyWrapper.hpp b/wrap/nanoply/include/nanoplyWrapper.hpp index abab3417..800b3427 100644 --- a/wrap/nanoply/include/nanoplyWrapper.hpp +++ b/wrap/nanoply/include/nanoplyWrapper.hpp @@ -856,8 +856,8 @@ namespace nanoply case NNP_DENSITY: mask |= BitMask::IO_VERTRADIUS; break; case NNP_TEXTURE2D: case NNP_TEXTURE3D: mask |= BitMask::IO_VERTTEXCOORD; break; - case NNP_KH: - case NNP_KG: mask |= BitMask::IO_VERTCURV; break; +// case NNP_KH: +// case NNP_KG: mask |= BitMask::IO_VERTCURV; break; case NNP_K1: case NNP_K2: case NNP_K1DIR: @@ -1012,21 +1012,21 @@ namespace nanoply else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); } - if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) - { - if (ocfVertexMask & BitMask::IO_VERTCURV) - { - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); - } - else - { - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); - vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); - } - } - if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) - { +// if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) +// { +// if (ocfVertexMask & BitMask::IO_VERTCURV) +// { +// vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); +// vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); +// } +// else +// { +// vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); +// vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); +// } +// } + if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) + { if (ocfVertexMask & BitMask::IO_VERTCURVDIR) { vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); @@ -1380,19 +1380,19 @@ namespace nanoply else PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); } - if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) - { - if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) - { - PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); - PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); - } - else - { - PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); - PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); - } - } +// if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) +// { +// if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) +// { +// PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); +// PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); +// } +// else +// { +// PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); +// PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); +// } +// } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCURVDIR) diff --git a/wrap/openfbx/.clang-format b/wrap/openfbx/.clang-format deleted file mode 100755 index 2950cfd3..00000000 --- a/wrap/openfbx/.clang-format +++ /dev/null @@ -1,42 +0,0 @@ -BasedOnStyle: LLVM - -AlignAfterOpenBracket : false -AlignEscapedNewlinesLeft : true -AlignConsecutiveAssignments : false -AllowAllParametersOfDeclarationOnNextLine : false -AccessModifierOffset : -4 -AllowShortCaseLabelsOnASingleLine : true -AllowShortFunctionsOnASingleLine : Inline -AllowShortIfStatementsOnASingleLine : true -AllowShortLoopsOnASingleLine : true -AlwaysBreakAfterDefinitionReturnType : None -BinPackArguments : false -BinPackParameters : false -BreakBeforeBraces : Allman -BreakConstructorInitializersBeforeComma : true -ColumnLimit : 120 -ConstructorInitializerIndentWidth : 4 -ConstructorInitializerAllOnOneLineOrOnePerLine : false -ContinuationIndentWidth : 4 -IndentCaseLabels : true -IndentWidth : 4 -KeepEmptyLinesAtTheStartOfBlocks : true -MaxEmptyLinesToKeep : 2 -NamespaceIndentation : None -PenaltyBreakBeforeFirstCallParameter : 0 -PenaltyReturnTypeOnItsOwnLine : 1000 -PointerAlignment : Left -SpaceAfterCStyleCast : false -SpaceBeforeAssignmentOperators : true -SpaceBeforeParens : true -SpaceInEmptyParentheses : false -SpacesBeforeTrailingComments : 1 -SpacesInAngles : false -SpacesInCStyleCastParentheses : false -SpacesInParentheses : false -SpacesInSquareBrackets : false -Standard : Cpp11 -TabWidth : 4 -UseTab : true - - diff --git a/wrap/ply/plylib.cpp b/wrap/ply/plylib.cpp index 8530349f..78bb2ccd 100644 --- a/wrap/ply/plylib.cpp +++ b/wrap/ply/plylib.cpp @@ -143,8 +143,12 @@ static int TypeSize[] = { size_t PropDescriptor::memtypesize() const {return TypeSize[memtype1];} size_t PropDescriptor::stotypesize() const {return TypeSize[stotype1];} +size_t PropDescriptor::memtype2size() const {return TypeSize[memtype2];} +size_t PropDescriptor::stotype2size() const {return TypeSize[stotype2];} const char *PropDescriptor::memtypename() const {return PlyFile::typenames[memtype1];} const char *PropDescriptor::stotypename() const {return PlyFile::typenames[stotype1];} +const char *PropDescriptor::memtype2name() const {return PlyFile::typenames[memtype2];} +const char *PropDescriptor::stotype2name() const {return PlyFile::typenames[stotype2];} static char CrossType[9][9]= { @@ -3691,6 +3695,6 @@ void interpret_texture_name(const char*a, const char*fn, char*output){ output[io++]=a[ia++]; }; output[io]=0; -}; +} } } diff --git a/wrap/ply/plylib.h b/wrap/ply/plylib.h index 59e5eddd..a068ac4c 100644 --- a/wrap/ply/plylib.h +++ b/wrap/ply/plylib.h @@ -112,33 +112,57 @@ typedef FILE * GZFILE; #endif - // Messaggio di errore -//extern const char * ply_error_msg[]; - - // TIPO FILE - - -// Descrittore esterno di propieta' +// Ply Property descriptor class PropDescriptor { public: - const char * elemname; // Nome dell'elemento - const char * propname; // Nome della propieta' - int stotype1; // Tipo dell'elemento su file (se lista tipo degli elementi della lista) - int memtype1; // Tipo dell'elemento in memoria (se lista tipo degli elementi della lista) - size_t offset1; // Offset del valore in memoria - int islist; // 1 se lista, 0 altrimenti - int alloclist; // 1 se alloca lista, 0 se preallocata - int stotype2; // Tipo del numero di elementi della lista su file - int memtype2; // Tipo del numero di elementi della lista in memoria - size_t offset2; // Offset valore memoria + PropDescriptor() {} + PropDescriptor + (std::string elemname, + std::string propname, + int stotype1, + int memtype1, + size_t offset1, + bool islist, + bool alloclist, + int stotype2, + int memtype2, + size_t offset2, + int format) : + elemname(elemname), + propname(propname), + stotype1(stotype1), + memtype1(memtype1), + offset1(offset1), + islist(islist), + alloclist(alloclist), + stotype2(stotype2), + memtype2(memtype2), + offset2(offset2), + format(format) + { + } + std::string elemname; // name of the element (e.g. vertex) + std::string propname; // name of the property (e.g. x, y, red...) + int stotype1 = -1; // Type of the property in the file + int memtype1 = -1; // Type of the property in memory + size_t offset1 = 0; // Offset in memory + bool islist = false; // true if the property is a list + bool alloclist = false; // 1 se alloca lista, 0 se preallocata + int stotype2 = -1; // Type of the number of elements of the list in the file + int memtype2 = -1; // Type of the number of elements of the list in memory + size_t offset2 = 0; // Offset valore memoria - int format; // duplicazione del formato + int format = -1; // duplicazione del formato - size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file - size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria - const char *memtypename() const; - const char *stotypename() const; + size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file + size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria + const char* memtypename() const; + const char* stotypename() const; + size_t stotype2size() const; // per sapere quanto e'grande un dato descrittore sul file + size_t memtype2size() const; // per sapere quanto e'grande un dato descrittore in memoria + const char* memtype2name() const; + const char* stotype2name() const; }; // Reading Callback (used to copy a data prop) @@ -178,7 +202,7 @@ public: int bestored; // 1 se va storata PropDescriptor desc; // Descrittore di memorizzazione - readelemcb cb; // Callback di lettura + readelemcb cb = nullptr; // Callback di lettura }; @@ -231,7 +255,7 @@ public: std::string name; // Nome dell'elemento int number; // Numero di elementi di questo tipo - std::vector props; // Vettore dinamico delle property + std::vector props; // Vettore dinamico delle property }; @@ -273,7 +297,7 @@ public: // Come sopra ma con descrittore inline int AddToRead( const PropDescriptor & p ) { - return AddToRead(p.elemname,p.propname,p.stotype1, + return AddToRead(p.elemname.c_str(),p.propname.c_str(),p.stotype1, p.memtype1,p.offset1,p.islist,p.alloclist,p.stotype2, p.memtype2,p.offset2 ); diff --git a/wrap/qt/shot_qt.h b/wrap/qt/shot_qt.h index e2dc32e4..e9ca0a6c 100644 --- a/wrap/qt/shot_qt.h +++ b/wrap/qt/shot_qt.h @@ -1,6 +1,10 @@ #ifndef SHOT_QT_H #define SHOT_QT_H +#include +#include + +#include /** This function read a shot from a parsed XML node. diff --git a/wrap/system/memory_info.h b/wrap/system/memory_info.h index 517f49e7..884ccc31 100644 --- a/wrap/system/memory_info.h +++ b/wrap/system/memory_info.h @@ -112,6 +112,6 @@ namespace vcg return (_currentfreememory >= mem); } }; -}; +} -#endif \ No newline at end of file +#endif