diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml index 45be7199..a766b0fe 100644 --- a/.github/workflows/continuous.yml +++ b/.github/workflows/continuous.yml @@ -23,24 +23,23 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + os: [ubuntu-latest, macos-latest] config: [Debug, Release] include: - os: macos-latest name: macOS - - os: ubuntu-18.04 - name: Linux - - os: ubuntu-20.04 + - os: ubuntu-latest name: Linux steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2.5.0 with: fetch-depth: 10 - name: Dependencies (Linux) if: runner.os == 'Linux' run: | + sudo apt-get update sudo apt-get install \ ccache \ xorg-dev \ @@ -83,54 +82,49 @@ jobs: Windows: runs-on: windows-latest - env: - CC: cl.exe - CXX: cl.exe strategy: fail-fast: false matrix: config: [Debug, Release] steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2.5.0 with: fetch-depth: 10 - - uses: seanmiddleditch/gha-setup-ninja@master - # https://github.com/actions/cache/issues/101 - - name: Set env + - name: Install Ninja + uses: seanmiddleditch/gha-setup-ninja@master + + - name: Set env variable for sccache run: | echo "appdata=$env:LOCALAPPDATA" >> ${env:GITHUB_ENV} - name: Cache build id: cache-build - uses: actions/cache@v1 + uses: actions/cache@v3.0.11 with: path: ${{ env.appdata }}\Mozilla\sccache key: ${{ runner.os }}-${{ matrix.config }}-cache - name: Prepare sccache run: | - Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') + iwr -useb 'https://raw.githubusercontent.com/scoopinstaller/install/master/install.ps1' -outfile 'install.ps1' + .\install.ps1 -RunAsAdmin scoop install sccache --global # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} - # We run configure + build in the same step, since they both need to call VsDevCmd - # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 - cmake --version + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 cmake -G Ninja ^ -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ^ -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DRIGID_IPC_WITH_UNIT_TESTS=ON ^ -B build ^ -S . - cd build - ninja -j4 + cmake --build build -j1 - name: Tests - run: cd build; ctest --verbose + run: cd build; ctest --verbose -j2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6eda1c58..17221442 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ option(RIGID_IPC_WITH_DERIVATIVE_CHECK "Check derivatives using finite diff # Set default minimum C++ standard if(RIGID_IPC_TOPLEVEL_PROJECT) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) endif() @@ -55,29 +55,15 @@ include(rigid_ipc_use_colors) include(rigid_ipc_autogen) -mark_as_advanced(CLEAR CMAKE_BUILD_TYPE) - ################################################################################ # External project settings ################################################################################ # libigl options -option(LIBIGL_USE_STATIC_LIBRARY "Use libigl as static library" OFF) -option(LIBIGL_WITH_PREDICATES "Use exact predicates" ON) -set(LIBIGL_WITH_OPENGL_GLFW_IMGUI ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Use OpenGL" FORCE) -set(LIBIGL_WITH_OPENGL_GLFW ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Use GLFW" FORCE) -set(LIBIGL_WITH_OPENGL ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Use IMGUI" FORCE) -set(LIBIGL_WITH_PNG ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Use PNG" FORCE) - -# PolySolve settings -option(POLYSOLVE_WITH_CHOLMOD "Enable Cholmod library" ON) -option(POLYSOLVE_WITH_UMFPACK "Enable UmfPack library" OFF) -option(POLYSOLVE_WITH_SUPERLU "Enable SuperLU library" OFF) -option(POLYSOLVE_WITH_MKL "Enable MKL library" OFF) -option(POLYSOLVE_WITH_PARDISO "Enable Pardiso library" OFF) -option(POLYSOLVE_WITH_HYPRE "Enable hypre" OFF) -option(POLYSOLVE_WITH_AMGCL "Use AMGCL" OFF) -option(POLYSOLVE_WITH_SPECTRA "Enable computing spectrum" OFF) +set(LIBIGL_GLFW ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Build target igl::glfw" FORCE) +set(LIBIGL_IMGUI ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Build target igl::imgui" FORCE) +set(LIBIGL_OPENGL ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Build target igl::opengl" FORCE) +set(LIBIGL_PNG ${RIGID_IPC_WITH_OPENGL} CACHE BOOL "Build target igl::png" FORCE) set(TIGHT_INCLUSION_WITH_NO_ZERO_TOI OFF CACHE BOOL "Enable refinement if CCD produces a zero ToI" FORCE) @@ -88,13 +74,14 @@ set(TIGHT_INCLUSION_WITH_NO_ZERO_TOI OFF CACHE BOOL "Enable refinement if CCD pr add_library(ipc_rigid src/autodiff/autodiff.cpp + src/utils/sinc.cpp src/ccd/impact.cpp src/ccd/ccd.cpp src/ccd/linear/broad_phase.cpp src/ccd/piecewise_linear/time_of_impact.cpp - src/interval/filib_rounding.cpp + src/interval/interval.cpp src/interval/interval_root_finder.cpp src/ccd/rigid/broad_phase.cpp src/ccd/rigid/rigid_body_hash_grid.cpp @@ -199,7 +186,7 @@ target_link_libraries(ipc_rigid PUBLIC # JSON Parser include(json) -target_link_libraries(ipc_rigid PUBLIC nlohmann::json) +target_link_libraries(ipc_rigid PUBLIC nlohmann_json::nlohmann_json) # Logger include(spdlog) @@ -209,10 +196,6 @@ target_link_libraries(ipc_rigid PUBLIC spdlog::spdlog) include(finite_diff) target_link_libraries(ipc_rigid PUBLIC finitediff::finitediff) -# Boost -include(boost) -target_link_libraries(ipc_rigid PUBLIC Boost::boost) - # TBB include(tbb) target_link_libraries(ipc_rigid PUBLIC TBB::tbb) @@ -221,10 +204,6 @@ target_link_libraries(ipc_rigid PUBLIC TBB::tbb) include(tight_inclusion) target_link_libraries(ipc_rigid PUBLIC tight_inclusion::tight_inclusion) -# PolySolve for wrapping linear solvers -include(polysolve) -target_link_libraries(ipc_rigid PUBLIC PolyFEM::polysolve) - # IPC Toolkit include(ipc_toolkit) target_link_libraries(ipc_rigid PUBLIC ipc::toolkit) @@ -241,10 +220,6 @@ target_link_libraries(ipc_rigid PUBLIC simple_bvh::simple_bvh) include(tinygltf) target_link_libraries(ipc_rigid PUBLIC tinygltf::tinygltf) -# Filesystem -include(filesystem) -target_link_libraries(ipc_rigid PUBLIC ghc::filesystem) - ################################################################################ # Compiler options ################################################################################ @@ -296,9 +271,8 @@ target_link_libraries(rigid_ipc_sim PUBLIC CLI11::CLI11) if(RIGID_IPC_WITH_OPENGL) target_compile_definitions(rigid_ipc_sim PUBLIC RIGID_IPC_WITH_OPENGL) - include(libigl) target_link_libraries(rigid_ipc_sim PUBLIC - igl::opengl igl::opengl_glfw igl::opengl_glfw_imgui igl::png) + igl::opengl igl::glfw igl::imgui igl::png) # Charlie Tangora's gif-h library include(gif_h) diff --git a/cmake/recipes/boost.cmake b/cmake/recipes/boost.cmake deleted file mode 100644 index b46102de..00000000 --- a/cmake/recipes/boost.cmake +++ /dev/null @@ -1,29 +0,0 @@ -if(TARGET Boost::boost) - return() -endif() - -message(STATUS "Third-party: creating targets 'Boost::boost'") - -include(FetchContent) -FetchContent_Declare( - boost-cmake - GIT_REPOSITORY https://github.com/Orphis/boost-cmake.git - GIT_TAG 7f97a08b64bd5d2e53e932ddf80c40544cf45edf -) - -set(PREVIOUS_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -set(OLD_CMAKE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE}) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -# This guy will download boost using FetchContent -FetchContent_GetProperties(boost-cmake) -if(NOT boost-cmake_POPULATED) - FetchContent_Populate(boost-cmake) - # File lcid.cpp from Boost_locale.cpp doesn't compile on MSVC, so we exclude them from the default - # targets being built by the project (only targets explicitly used by other targets will be built). - add_subdirectory(${boost-cmake_SOURCE_DIR} ${boost-cmake_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() - -set(CMAKE_POSITION_INDEPENDENT_CODE ${OLD_CMAKE_POSITION_INDEPENDENT_CODE}) -set(CMAKE_CXX_FLAGS "${PREVIOUS_CMAKE_CXX_FLAGS}") diff --git a/cmake/recipes/eigen.cmake b/cmake/recipes/eigen.cmake index 8e33f247..d066f64f 100644 --- a/cmake/recipes/eigen.cmake +++ b/cmake/recipes/eigen.cmake @@ -13,7 +13,7 @@ if(TARGET Eigen3::Eigen) return() endif() -option(EIGEN_WITH_MKL "Use Eigen with MKL" OFF) +# option(EIGEN_WITH_MKL "Use Eigen with MKL" OFF) if(EIGEN_ROOT) message(STATUS "Third-party: creating target 'Eigen3::Eigen' for external path: ${EIGEN_ROOT}") @@ -25,7 +25,7 @@ else() FetchContent_Declare( eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG tags/3.3.7 + GIT_TAG tags/3.4.0 GIT_SHALLOW TRUE ) FetchContent_GetProperties(eigen) @@ -49,16 +49,16 @@ target_include_directories(Eigen3_Eigen SYSTEM INTERFACE ) # target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_MPL2_ONLY) -if(EIGEN_WITH_MKL) - # TODO: Checks that, on 64bits systems, `mkl::mkl` is using the LP64 interface - # (by looking at the compile definition of the target) - include(mkl) - target_link_libraries(Eigen3_Eigen INTERFACE mkl::mkl) - target_compile_definitions(Eigen3_Eigen INTERFACE - EIGEN_USE_MKL_ALL - EIGEN_USE_LAPACKE_STRICT - ) -endif() +# if(EIGEN_WITH_MKL) +# # TODO: Checks that, on 64bits systems, `mkl::mkl` is using the LP64 interface +# # (by looking at the compile definition of the target) +# include(mkl) +# target_link_libraries(Eigen3_Eigen INTERFACE mkl::mkl) +# target_compile_definitions(Eigen3_Eigen INTERFACE +# EIGEN_USE_MKL_ALL +# EIGEN_USE_LAPACKE_STRICT +# ) +# endif() # On Windows, enable natvis files to improve debugging experience if(WIN32 AND eigen_SOURCE_DIR) diff --git a/cmake/recipes/filesystem.cmake b/cmake/recipes/filesystem.cmake deleted file mode 100644 index 97fd4898..00000000 --- a/cmake/recipes/filesystem.cmake +++ /dev/null @@ -1,63 +0,0 @@ -if(TARGET ghc::filesystem) - return() -endif() - -message(STATUS "Third-party: creating target 'ghc::filesystem'") - -include(FetchContent) -FetchContent_Declare( - filesystem - GIT_REPOSITORY https://github.com/gulrak/filesystem.git - GIT_TAG v1.5.8 - GIT_SHALLOW TRUE -) -FetchContent_MakeAvailable(filesystem) -add_library(ghc::filesystem ALIAS ghc_filesystem) - -# Check if we need to link against any special libraries (e.g., stdc++fs for GCC < 9) -set(SAVED_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES}) -set(SAVED_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - -set(GHC_FILESYSTEM_TEST_CODE [[ - #include - int main() { - auto cwd = fs::current_path(); - return static_cast(cwd.string().size()); - } - ]]) - - -# Try to compile a simple filesystem program without any linker flags -list(APPEND CMAKE_REQUIRED_INCLUDES "${filesystem_SOURCE_DIR}/include") -check_cxx_source_compiles("${GHC_FILESYSTEM_TEST_CODE}" GHC_FILESYSTEM_NO_LINK_NEEDED) - -if(NOT GHC_FILESYSTEM_NO_LINK_NEEDED) - # Add the libstdc++ flag - set(CMAKE_REQUIRED_LIBRARIES ${SAVED_CMAKE_REQUIRED_LIBRARIES} -lstdc++fs) - check_cxx_source_compiles("${GHC_FILESYSTEM_TEST_CODE}" GHC_FILESYSTEM_STDCPPFS_NEEDED) - - if(NOT GHC_FILESYSTEM_STDCPPFS_NEEDED) - # Try the libc++ flag - set(CMAKE_REQUIRED_LIBRARIES ${SAVED_CMAKE_REQUIRED_LIBRARIES} -lc++fs) - check_cxx_source_compiles("${GHC_FILESYSTEM_TEST_CODE}" GHC_FILESYSTEM_CPPFS_NEEDED) - endif() -endif() - -if(GHC_FILESYSTEM_NO_LINK_NEEDED) - # on certain linux distros we have a version of libstdc++ which has the final code for c++17 fs in the - # libstdc++.so.*. BUT when compiling with g++ < 9, we MUST still link with libstdc++fs.a - # libc++ should not suffer from this issue, so, in theory we should be fine with only checking for - # GCC's libstdc++ - if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")) - target_link_libraries(ghc_filesystem INTERFACE -lstdc++fs) - endif() -elseif(GHC_FILESYSTEM_STDCPPFS_NEEDED) - target_link_libraries(ghc_filesystem INTERFACE -lstdc++fs) -elseif(GHC_FILESYSTEM_CPPFS_NEEDED) - target_link_libraries(ghc_filesystem INTERFACE -lc++fs) -else() - message(FATAL_ERROR "Unable to determine correct linking options to compile GHC filesystem!") -endif() - -set(CMAKE_REQUIRED_INCLUDES ${SAVED_CMAKE_REQUIRED_INCLUDES}) -set(CMAKE_REQUIRED_LIBRARIES ${SAVED_CMAKE_REQUIRED_LIBRARIES}) diff --git a/cmake/recipes/json.cmake b/cmake/recipes/json.cmake index 1a4c9dca..38c76199 100644 --- a/cmake/recipes/json.cmake +++ b/cmake/recipes/json.cmake @@ -9,11 +9,13 @@ # OF ANY KIND, either express or implied. See the License for the specific language # governing permissions and limitations under the License. # -if(TARGET nlohmann::json) + +# JSON MIT +if(TARGET nlohmann_json::nlohmann_json) return() endif() -message(STATUS "Third-party: creating target 'nlohmann::json'") +message(STATUS "Third-party: creating target 'nlohmann_json::nlohmann_json'") # nlohmann_json is a big repo for a single header, so we just download the release archive set(NLOHMANNJSON_VERSION "v3.10.2") @@ -27,7 +29,7 @@ FetchContent_Declare( FetchContent_MakeAvailable(nlohmann_json) add_library(nlohmann_json INTERFACE) -add_library(nlohmann::json ALIAS nlohmann_json) +add_library(nlohmann_json::nlohmann_json ALIAS nlohmann_json) include(GNUInstallDirs) target_include_directories(nlohmann_json INTERFACE diff --git a/cmake/recipes/libigl.cmake b/cmake/recipes/libigl.cmake index 04b54564..cd7a42a6 100644 --- a/cmake/recipes/libigl.cmake +++ b/cmake/recipes/libigl.cmake @@ -15,29 +15,15 @@ endif() message(STATUS "Third-party: creating target 'igl::core'") +set(LIBIGL_PREDICATES ON CACHE BOOL "Use exact predicates" FORCE) + +include(eigen) + include(FetchContent) FetchContent_Declare( libigl GIT_REPOSITORY https://github.com/libigl/libigl.git - GIT_TAG v2.3.0 + GIT_TAG v2.4.0 GIT_SHALLOW TRUE ) -FetchContent_GetProperties(libigl) -if(libigl_POPULATED) - return() -endif() -FetchContent_Populate(libigl) - -include(eigen) - -set(LIBIGL_WITH_PREDICATES ON CACHE BOOL "Use exact predicates" FORCE) - -list(APPEND CMAKE_MODULE_PATH ${libigl_SOURCE_DIR}/cmake) -include(${libigl_SOURCE_DIR}/cmake/libigl.cmake ${libigl_BINARY_DIR}) - -# Install rules -set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME libigl) -set_target_properties(igl PROPERTIES EXPORT_NAME core) -install(DIRECTORY ${libigl_SOURCE_DIR}/include/igl DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(TARGETS igl igl_common EXPORT Libigl_Targets) -install(EXPORT Libigl_Targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/igl NAMESPACE igl::) +FetchContent_MakeAvailable(libigl) diff --git a/cmake/recipes/polysolve.cmake b/cmake/recipes/polysolve.cmake deleted file mode 100644 index 73e8a9ec..00000000 --- a/cmake/recipes/polysolve.cmake +++ /dev/null @@ -1,16 +0,0 @@ -if(TARGET PolyFEM::polysolve) - return() -endif() - -message(STATUS "Third-party: creating target 'PolyFEM::polysolve'") - -include(FetchContent) -FetchContent_Declare( - polysolve - GIT_REPOSITORY https://github.com/polyfem/polysolve.git - GIT_TAG 72e5eaca17b1ae975fa5a7149627a17e6b13cf80 - GIT_SHALLOW FALSE -) -FetchContent_MakeAvailable(polysolve) - -add_library(PolyFEM::polysolve ALIAS polysolve) diff --git a/cmake/recipes/software_renderer.cmake b/cmake/recipes/software_renderer.cmake index 0d8127c9..a4107906 100644 --- a/cmake/recipes/software_renderer.cmake +++ b/cmake/recipes/software_renderer.cmake @@ -8,7 +8,7 @@ include(FetchContent) FetchContent_Declare( software_renderer GIT_REPOSITORY https://github.com/zfergus/software-renderer.git - GIT_TAG cdfb409d02a1b3b55e916c549aedbff7e5bdb5e7 + GIT_TAG 2453b2b05b42e95ff38d1b6f91c9857390087a69 GIT_SHALLOW FALSE ) FetchContent_MakeAvailable(software_renderer) diff --git a/src/SimState.cpp b/src/SimState.cpp index f2d8c75f..79c9c7aa 100644 --- a/src/SimState.cpp +++ b/src/SimState.cpp @@ -6,7 +6,6 @@ #include #include -#include // filesystem #include #include #include @@ -24,6 +23,9 @@ #include #include +#include +namespace fs = std::filesystem; + namespace ipc::rigid { SimState::SimState() @@ -151,14 +153,7 @@ bool SimState::init(const nlohmann::json& args_in) "energy_conv_tol": null, "velocity_conv_tol": null, "is_velocity_conv_tol_abs": false, - "line_search_lower_bound": null, - "linear_solver": { - "name": "Eigen::SimplicialLDLT", - "max_iter": 1000, - "tolerance": 1e-10, - "pre_max_iter": 1, - "mtype": 2 - } + "line_search_lower_bound": null }, "ipc_solver": { "dhat_epsilon": 1e-9, diff --git a/src/ccd/rigid/broad_phase.hpp b/src/ccd/rigid/broad_phase.hpp index f9d3ee05..5cbd83a8 100644 --- a/src/ccd/rigid/broad_phase.hpp +++ b/src/ccd/rigid/broad_phase.hpp @@ -90,8 +90,7 @@ void detect_intersection_candidates_rigid_bvh( // Helper functions /////////////////////////////////////////////////////////////////////////////// -typedef tbb::enumerable_thread_specific - ThreadSpecificCandidates; +typedef tbb::enumerable_thread_specific ThreadSpecificCandidates; void merge_local_candidates( const ThreadSpecificCandidates& storages, Candidates& candidates); diff --git a/src/ccd/rigid/rigid_body_bvh.cpp b/src/ccd/rigid/rigid_body_bvh.cpp index c537d052..a9636a80 100644 --- a/src/ccd/rigid/rigid_body_bvh.cpp +++ b/src/ccd/rigid/rigid_body_bvh.cpp @@ -114,7 +114,7 @@ void detect_body_pair_collision_candidates_from_aabbs( size_t vb_id = EB(eb_id, vi); if (selectorB.vertex_to_edge(vb_id) == eb_id && AABB::are_overlapping( - fa_aabb, bodyB_vertex_aabbs[vb_id])) { + fa_aabb, bodyB_vertex_aabbs[vb_id])) { add_fv(fa_id, vb_id); } } diff --git a/src/ccd/rigid/rigid_body_bvh.hpp b/src/ccd/rigid/rigid_body_bvh.hpp index 7a78e084..8810ea72 100644 --- a/src/ccd/rigid/rigid_body_bvh.hpp +++ b/src/ccd/rigid/rigid_body_bvh.hpp @@ -30,7 +30,7 @@ inline AABB vertex_aabb(const VectorMax3I& v, double inflation_radius = 0) VectorMax3d min(v.size()); VectorMax3d max(v.size()); for (int i = 0; i < v.size(); i++) { - if (empty(v(i))) { + if (v(i).is_empty()) { throw "interval is empty"; } min(i) = (v(i) - inflation_radius).lower(); diff --git a/src/ccd/rigid/rigid_body_hash_grid.cpp b/src/ccd/rigid/rigid_body_hash_grid.cpp index 7ab07e6d..328fecd1 100644 --- a/src/ccd/rigid/rigid_body_hash_grid.cpp +++ b/src/ccd/rigid/rigid_body_hash_grid.cpp @@ -221,7 +221,7 @@ int RigidBodyHashGrid::compute_vertices_intervals( // If the vertices' intervals are outside the scene bbox, then split t in // hopes that a smaller interval will be more accurate. - std::pair t_halves = bisect(t); + std::pair t_halves = t.bisect(); MatrixXI V_first, V_second; int n_subs0 = compute_vertices_intervals( body, pose_t0, pose_t1, V_first, inflation_radius, t_halves.first, @@ -236,7 +236,7 @@ int RigidBodyHashGrid::compute_vertices_intervals( // Take the hull of the two halves of the vertices' trajectories for (int i = 0; i < vertices.rows(); i++) { for (int j = 0; j < vertices.cols(); j++) { - vertices(i, j) = hull(V_first(i, j), V_second(i, j)); + vertices(i, j) = V_first(i, j) | V_second(i, j); assert(vertices(i, j).lower() - inflation_radius >= m_domainMin(j)); assert(vertices(i, j).upper() + inflation_radius <= m_domainMax(j)); } @@ -253,7 +253,7 @@ intervals_to_AABB(const Eigen::MatrixBase& x, double inflation_radius) VectorMax3d min(x.size()); VectorMax3d max(x.size()); for (int i = 0; i < x.size(); i++) { - if (empty(x(i))) { + if (x(i).is_empty()) { throw "interval is empty"; } min(i) = x(i).lower() - inflation_radius; diff --git a/src/ccd/rigid/time_of_impact.cpp b/src/ccd/rigid/time_of_impact.cpp index 8b4d5572..4a63b470 100644 --- a/src/ccd/rigid/time_of_impact.cpp +++ b/src/ccd/rigid/time_of_impact.cpp @@ -276,7 +276,7 @@ bool compute_face_vertex_time_of_impact( const auto is_domain_valid = [&](const VectorMax3I& params) { const Interval &t = params[0], &u = params[1], &v = params[2]; // 0 ≤ t, u, v ≤ 1 is satisfied by the initial domain of the solve - return overlap(u + v, Interval(0, 1)); + return (u + v).overlaps(Interval(0, 1)); }; Eigen::Vector3d tol = compute_face_vertex_tolerance( diff --git a/src/geometry/intersection.cpp b/src/geometry/intersection.cpp index b540c783..b6be3c9f 100644 --- a/src/geometry/intersection.cpp +++ b/src/geometry/intersection.cpp @@ -16,10 +16,10 @@ bool is_point_along_edge( Interval alpha = point_edge_closest_point(p, e0, e1); // Check this in case empty intervals are not allowed - if (!overlap(alpha, Interval(0, 1))) { + if (!alpha.overlaps(Interval(0, 1))) { return false; } - Interval valid_alpha = boost::numeric::intersect(alpha, Interval(0, 1)); + Interval valid_alpha = alpha & Interval(0, 1); // Check the distance to the closest point is small VectorMax3I edge_to_point = e0 + valid_alpha * e - p; diff --git a/src/interval/filib_rounding.cpp b/src/interval/filib_rounding.cpp deleted file mode 100644 index a18fb355..00000000 --- a/src/interval/filib_rounding.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include "filib_rounding.hpp" - -#include - -#include -#undef local - -#include - -namespace ipc::rigid { - -double FILibRounding::add_down(double x, double y) -{ - return x == -y ? 0 : q_pred(x + y); -} - -double FILibRounding::add_up(double x, double y) -{ - return x == -y ? 0 : q_succ(x + y); -} - -double FILibRounding::sub_down(double x, double y) -{ - return x == y ? 0 : q_pred(x - y); -} - -double FILibRounding::sub_up(double x, double y) -{ - return x == y ? 0 : q_succ(x - y); -} - -double FILibRounding::mul_down(double x, double y) -{ - return (x == 0 || y == 0) ? 0 : q_pred(x * y); -} - -double FILibRounding::mul_up(double x, double y) -{ - return (x == 0 || y == 0) ? 0 : q_succ(x * y); -} - -double FILibRounding::div_down(double x, double y) -{ - return x == 0 ? 0 : q_pred(x / y); -} - -double FILibRounding::div_up(double x, double y) -{ - return x == 0 ? 0 : q_succ(x / y); -} - -double FILibRounding::sqrt_down(double x) -{ - return x == 0 ? 0 : r_pred(q_sqrt(x)); -} - -double FILibRounding::sqrt_up(double x) -{ - return x == 0 ? 0 : r_succ(q_sqrt(x)); -} - -double FILibRounding::exp_down(double x) -{ - double r = x == 0 ? 1.0 : (x <= q_mine ? 0 : (q_exp(x) * q_exem)); - // Snap negative r values to 0 - if (r < 0) { - r = 0; - } - // Snap negative r values to 1 if x is positive - if (x >= 0 && r < 1.0) { - r = 1; - } - return r; -} - -double FILibRounding::exp_up(double x) -{ - double r = x == 0 ? 1.0 : (x <= q_mine ? q_minr : (q_exp(x) * q_exep)); - // Snap negative r values to 0 - if (r < 0) { - r = 0; - } - // Snap negative r values to 1 if x is positive - if (x >= 0 && r < 1.0) { - r = 1; - } - return r; -} - -// double FILibRounding::log_down(double x) -// { -// assert(false); -// throw NotImplementedError(""); -// } - -// double FILibRounding::log_up(double x) -// { -// assert(false); -// throw NotImplementedError(""); -// } - -double FILibRounding::cos_down(double x) -{ - double r; - if (x < -q_sint[2] || x > q_sint[2]) { - r = -1.0; - } else { - r = q_cos(x); - r *= r < 0 ? q_cosp : q_cosm; - } - if (r < -1.0) { - r = -1; - } - if (r > 1.0) { - r = 1; - } - return r; -} - -double FILibRounding::cos_up(double x) -{ - double r; - if (x < -q_sint[2] || x > q_sint[2]) { - r = 1.0; - } else { - r = q_cos(x); - r *= r < 0 ? q_cosm : q_cosp; - } - if (r < -1.0) { - r = -1; - } - if (r > 1.0) { - r = 1; - } - return r; -} - -// double FILibRounding::tan_down(double x) -// { -// assert(false); -// throw NotImplementedError("tan_down is not implemented!"); -// } - -// double FILibRounding::tan_up(double x) -// { -// assert(false); -// throw NotImplementedError("tan_up is not implemented!"); -// } - -// double FILibRounding::asin_down(double x) -// { -// assert(false); -// throw NotImplementedError("asin_down is not implemented!"); -// } - -// double FILibRounding::asin_up(double x) -// { -// assert(false); -// throw NotImplementedError("asin_up is not implemented!"); -// } - -// double FILibRounding::acos_down(double x) -// { -// assert(false); -// throw NotImplementedError("acos_down is not implemented!"); -// } - -// double FILibRounding::acos_up(double x) -// { -// assert(false); -// throw NotImplementedError("acos_up is not implemented!"); -// } - -// double FILibRounding::atan_down(double x) -// { -// assert(false); -// throw NotImplementedError("atan_down is not implemented!"); -// } - -// double FILibRounding::atan_up(double x) -// { -// assert(false); -// throw NotImplementedError("atan_up is not implemented!"); -// } - -// double FILibRounding::sinh_down(double x) -// { -// assert(false); -// throw NotImplementedError("sinh_down is not implemented!"); -// } - -// double FILibRounding::sinh_up(double x) -// { -// assert(false); -// throw NotImplementedError("sinh_up is not implemented!"); -// } - -// double FILibRounding::cosh_down(double x) -// { -// assert(false); -// throw NotImplementedError("cosh_down is not implemented!"); -// } - -// double FILibRounding::cosh_up(double x) -// { -// assert(false); -// throw NotImplementedError("cosh_up is not implemented!"); -// } - -// double FILibRounding::tanh_down(double x) -// { -// assert(false); -// throw NotImplementedError("tanh_down is not implemented!"); -// } - -// double FILibRounding::tanh_up(double x) -// { -// assert(false); -// throw NotImplementedError("tanh_up is not implemented!"); -// } - -// double FILibRounding::asinh_down(double x) -// { -// assert(false); -// throw NotImplementedError("asinh_down is not implemented!"); -// } - -// double FILibRounding::asinh_up(double x) -// { -// assert(false); -// throw NotImplementedError("asinh_up is not implemented!"); -// } - -// double FILibRounding::acosh_down(double x) -// { -// assert(false); -// throw NotImplementedError("acosh_down is not implemented!"); -// } - -// double FILibRounding::acosh_up(double x) -// { -// assert(false); -// throw NotImplementedError("acosh_up is not implemented!"); -// } - -// double FILibRounding::atanh_down(double x) -// { -// assert(false); -// throw NotImplementedError("atanh_down is not implemented!"); -// } - -// double FILibRounding::atanh_up(double x) -// { -// assert(false); -// throw NotImplementedError("atanh_up is not implemented!"); -// } - -double FILibRounding::median(double x, double y) -{ - this->to_nearest(); - return this->force_rounding(q_mid({ x, y })); -} - -double FILibRounding::int_down(double x) -{ - this->downward(); - return this->to_int(x); -} - -double FILibRounding::int_up(double x) -{ - this->upward(); - return this->to_int(x); -} - -} // namespace ipc::rigid diff --git a/src/interval/filib_rounding.hpp b/src/interval/filib_rounding.hpp deleted file mode 100644 index e43d2e30..00000000 --- a/src/interval/filib_rounding.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include - -namespace ipc::rigid { - -// A wrapper for filibs rounding -struct FILibRounding : boost::numeric::interval_lib::rounding_control { - // default constructor, destructor - // FILibRounding() {} - // ~FILibRounding() {} - void init() {} - // mathematical operations - double add_down(double x, double y); // [-∞;+∞][-∞;+∞] - double add_up(double x, double y); // [-∞;+∞][-∞;+∞] - double sub_down(double x, double y); // [-∞;+∞][-∞;+∞] - double sub_up(double x, double y); // [-∞;+∞][-∞;+∞] - double mul_down(double x, double y); // [-∞;+∞][-∞;+∞] - double mul_up(double x, double y); // [-∞;+∞][-∞;+∞] - double div_down(double x, double y); // [-∞;+∞]([-∞;+∞]-{0}) - double div_up(double x, double y); // [-∞;+∞]([-∞;+∞]-{0}) - double sqrt_down(double x); // ]0;+∞] - double sqrt_up(double x); // ]0;+∞] - double exp_down(double x); // [-∞;+∞] - double exp_up(double x); // [-∞;+∞] - // double log_down(double x); // ]0;+∞] - // double log_up(double x); // ]0;+∞] - double cos_down(double x); // [0;2π] - double cos_up(double x); // [0;2π] - // double tan_down(double x); // ]-π/2;π/2[ - // double tan_up(double x); // ]-π/2;π/2[ - // double asin_down(double x); // [-1;1] - // double asin_up(double x); // [-1;1] - // double acos_down(double x); // [-1;1] - // double acos_up(double x); // [-1;1] - // double atan_down(double x); // [-∞;+∞] - // double atan_up(double x); // [-∞;+∞] - // double sinh_down(double x); // [-∞;+∞] - // double sinh_up(double x); // [-∞;+∞] - // double cosh_down(double x); // [-∞;+∞] - // double cosh_up(double x); // [-∞;+∞] - // double tanh_down(double x); // [-∞;+∞] - // double tanh_up(double x); // [-∞;+∞] - // double asinh_down(double x); // [-∞;+∞] - // double asinh_up(double x); // [-∞;+∞] - // double acosh_down(double x); // [1;+∞] - // double acosh_up(double x); // [1;+∞] - // double atanh_down(double x); // [-1;1] - // double atanh_up(double x); // [-1;1] - - /// @brief median of two numbers rounded to closest number - double median(double x, double y); // [-∞;+∞][-∞;+∞] - - /// @brief round down to integer - double int_down(double x); // [-∞;+∞] - /// @brief round up to integer - double int_up(double x); // [-∞;+∞] - - /// @brief convert to the closest double (rounding down) - template double conv_down(const T& x) - { - this->downward(); - return this->force_rounding(x); - } - /// @brief convert to the closest double (rounding up) - template double conv_up(const T& x) - { - this->upward(); - return this->force_rounding(x); - } -}; - -} // namespace ipc::rigid diff --git a/src/interval/interval.cpp b/src/interval/interval.cpp new file mode 100644 index 00000000..ea55d8fd --- /dev/null +++ b/src/interval/interval.cpp @@ -0,0 +1,353 @@ +#include "interval.hpp" + +#include +#include +#include + +namespace ipc::rigid { + +Interval::Interval() { *this = empty(); } + +Interval::Interval(double x) +{ + INF = x; + SUP = x; +} + +Interval::Interval(double x, double y) +{ + INF = x; + SUP = y; +} + +Interval Interval::empty() +{ + return Interval( + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()); +} + +/* ------------------------------------------------------------------- */ +/* --- IO (input/output) --- */ +/* ------------------------------------------------------------------- */ + +std::istream& operator>>(std::istream& is, Interval& a) +{ + double help, ioconst; + + ioconst = (1e17 - 1) * 1e27; + + is >> help; + if ((help < -ioconst) || (help > ioconst)) + a.INF = q_pred(q_pred(help)); + else + a.INF = q_pred(help); + + is >> help; + if ((help < -ioconst) || (help > ioconst)) + a.SUP = q_succ(q_succ(help)); + else + a.SUP = q_succ(help); + + return is; +} + +std::ostream& operator<<(std::ostream& os, const Interval& a) +{ + Interval help; + + help.INF = q_pred(q_pred(a.INF)); + help.SUP = q_succ(q_succ(a.SUP)); + + std::ios_base::fmtflags aktform = std::cout.flags(); + os << "[" << std::setprecision(15) << std::setw(23) + << std::setiosflags(std::ios::scientific); + os << help.INF; + std::cout.flags(aktform); + os << "," << std::setprecision(15) << std::setw(23) + << std::setiosflags(std::ios::scientific); + os << help.SUP; + std::cout.flags(aktform); + os << " ]"; + + return os; +} + +/* ------------------------------------------------------------------- */ +/* --- interval arithmetic (basic operations) --- */ +/* ------------------------------------------------------------------- */ + +Interval operator+(const Interval& a, const Interval& b) +{ + return add_ii(a, b); +} + +Interval operator+(const Interval& a, double b) { return add_id(a, b); } + +Interval operator+(double a, const Interval& b) { return add_di(a, b); } + +Interval operator+(const Interval& a) { return a; } + +Interval& Interval::operator+=(const Interval& rhs) +{ + *this = add_ii(*this, rhs); + return *this; +} + +Interval& Interval::operator+=(const double& rhs) +{ + *this = add_id(*this, rhs); + return *this; +} + +Interval operator-(const Interval& a, const Interval& b) +{ + return sub_ii(a, b); +} + +Interval operator-(const Interval& a, double b) { return sub_id(a, b); } + +Interval operator-(double a, const Interval& b) { return sub_di(a, b); } + +Interval operator-(const Interval& a) { return Interval(-a.SUP, -a.INF); } + +Interval& Interval::operator-=(const Interval& rhs) +{ + *this = sub_ii(*this, rhs); + return *this; +} + +Interval& Interval::operator-=(const double rhs) +{ + *this = sub_id(*this, rhs); + return *this; +} + +Interval operator*(const Interval& a, const Interval& b) +{ + return mul_ii(a, b); +} + +Interval operator*(const Interval& a, double b) { return mul_id(a, b); } + +Interval operator*(double a, const Interval& b) { return mul_di(a, b); } + +Interval& Interval::operator*=(const Interval& rhs) +{ + *this = mul_ii(*this, rhs); + return *this; +} + +Interval& Interval::operator*=(const double rhs) +{ + *this = mul_id(*this, rhs); + return *this; +} + +Interval operator/(const Interval& a, const Interval& b) +{ + return div_ii(a, b); +} + +Interval operator/(const Interval& a, double b) { return div_id(a, b); } + +Interval operator/(double a, const Interval& b) { return div_di(a, b); } + +Interval& Interval::operator/=(const Interval& rhs) +{ + *this = div_ii(*this, rhs); + return *this; +} + +Interval& Interval::operator/=(const double& rhs) +{ + *this = div_id(*this, rhs); + return *this; +} + +/* ------------------------------------------------------------------- */ +/* --- Interval arithmetic (logical operations) --- */ +/* ------------------------------------------------------------------- */ + +bool operator==(const Interval& a, const Interval& b) { return ieq_ii(a, b); } + +bool operator==(const Interval& a, double b) { return ieq_ii(a, Interval(b)); } + +bool operator!=(const Interval& a, const Interval& b) +{ + return !(a.INF == b.INF && a.SUP == b.SUP); +} + +bool operator<(const Interval& a, const Interval& b) { return in_ii(a, b); } + +bool operator<(const double a, const Interval& b) +{ + return b.INF < a && a < b.SUP; +} + +bool operator<=(const Interval& a, const Interval& b) +{ + return b.INF <= a.INF && a.SUP <= b.SUP; +} + +bool operator<=(double a, const Interval& b) { return in_di(a, b); } + +bool operator>(const Interval& a, const Interval& b) +{ + return b.INF > a.INF && a.SUP > b.SUP; +} +bool operator>(const Interval& a, double b) { return a.INF < b && b < a.SUP; } + +bool operator>=(const Interval& a, const Interval& b) +{ + return b.INF >= a.INF && a.SUP >= b.SUP; +} + +bool operator>=(const Interval& a, double b) +{ + return a.INF <= b && b <= a.SUP; +} + +Interval operator|(const Interval& a, const Interval& b) { return hull(a, b); } +Interval& Interval::operator|=(const Interval& b) +{ + *this = *this | b; + return *this; +} + +Interval operator&(const Interval& a, const Interval& b) +{ + return intsec(a, b); +} +Interval& Interval::operator&=(const Interval& b) +{ + *this = *this & b; + return *this; +} + +bool in(double a, const Interval& b) { return in_di(a, b); } + +bool in(const Interval& a, const Interval& b) { return in_ii(a, b); } + +bool Interval::is_empty() const { return this->INF > this->SUP; } + +bool Interval::zero_in() const { return this->INF <= 0 && this->SUP >= 0; } + +bool Interval::overlaps(const Interval& b) const +{ + return (this->INF <= b.SUP) && (b.INF <= this->SUP); +} + +/* ------------------------------------------------------------------- */ +/* --- utilities, mid, diam, ... --- */ +/* ------------------------------------------------------------------- */ + +double Interval::mid() const { return q_mid(*this); } + +std::pair Interval::bisect() const +{ + double mid = this->mid(); + return std::make_pair(Interval(this->INF, mid), Interval(mid, this->SUP)); +} + +bool disjoint(const Interval& a, const Interval& b) { return dis_ii(a, b); } + +double Interval::diam() const { return q_diam(*this); } + +double Interval::drel() const +{ + if ((SUP <= -q_minr) || (q_minr <= INF)) { + if (INF > 0) + return diam() / INF; + else + return diam() / (-SUP); + } else { + return diam(); + } +} + +Interval Interval::blow(double eps) const +{ + Interval y; + y = (1.0 + eps) * (*this) - eps * (*this); + return (Interval(q_pred(y.INF), q_succ(y.SUP))); +} + +// min max function, same as what BOOST does +Interval max(const Interval& x, const Interval& y) +{ + return Interval(std::max(x.INF, y.INF), std::max(x.SUP, y.SUP)); +} +Interval max(const Interval& x, double y) +{ + return Interval(std::max(x.INF, y), std::max(x.SUP, y)); +} + +Interval max(double x, const Interval& y) +{ + return Interval(std::max(x, y.INF), std::max(x, y.SUP)); +} + +Interval min(const Interval& x, const Interval& y) +{ + return Interval(std::min(x.INF, y.INF), std::min(x.SUP, y.SUP)); +} +Interval min(const Interval& x, double y) +{ + return Interval(std::min(x.INF, y), std::min(x.SUP, y)); +} + +Interval min(double x, const Interval& y) +{ + return Interval(std::min(x, y.INF), std::min(x, y.SUP)); +} + +/* ------------------------------------------------------------------- */ +/* --- Interval arithmetic (elementary functions) --- */ +/* ------------------------------------------------------------------- */ + +Interval exp(const Interval& a) { return j_exp(a); } +Interval expm(const Interval& a) { return j_expm(a); } +Interval sinh(const Interval& a) { return j_sinh(a); } +Interval cosh(const Interval& a) { return j_cosh(a); } +Interval coth(const Interval& a) { return j_coth(a); } +Interval tanh(const Interval& a) { return j_tanh(a); } +Interval log(const Interval& a) { return j_log(a); } +Interval ln(const Interval& a) { return j_log(a); } +Interval lg1p(const Interval& a) { return j_lg1p(a); } +Interval sqrt(const Interval& a) { return j_sqrt(a); } +Interval sqr(const Interval& a) { return j_sqr(a); } +Interval asnh(const Interval& a) { return j_asnh(a); } +Interval asinh(const Interval& a) { return j_asnh(a); } +Interval acsh(const Interval& a) { return j_acsh(a); } +Interval acosh(const Interval& a) { return j_acsh(a); } +Interval acth(const Interval& a) { return j_acth(a); } +Interval acoth(const Interval& a) { return j_acth(a); } +Interval atnh(const Interval& a) { return j_atnh(a); } +Interval atanh(const Interval& a) { return j_atnh(a); } +Interval asin(const Interval& a) { return j_asin(a); } +Interval acos(const Interval& a) { return j_acos(a); } +Interval acot(const Interval& a) { return j_acot(a); } +Interval atan(const Interval& a) { return j_atan(a); } +Interval sin(const Interval& a) { return j_sin(a); } +Interval cos(const Interval& a) { return j_cos(a); } +Interval cot(const Interval& a) { return j_cot(a); } +Interval tan(const Interval& a) { return j_tan(a); } +Interval exp2(const Interval& a) { return j_exp2(a); } +Interval ex10(const Interval& a) { return j_ex10(a); } +Interval log2(const Interval& a) { return j_log2(a); } +Interval lg10(const Interval& a) { return j_lg10(a); } +Interval erf(const Interval& a) { return j_erf(a); } +Interval erfc(const Interval& a) { return j_erfc(a); } + +Interval abs(const Interval& a) +{ + if (a.INF >= 0) + return a; + else if (a.SUP <= 0) + return -a; + else + return Interval(0, std::max(-a.INF, a.SUP)); +} + +} // namespace ipc::rigid \ No newline at end of file diff --git a/src/interval/interval.hpp b/src/interval/interval.hpp index 2134c7b8..9462a11e 100644 --- a/src/interval/interval.hpp +++ b/src/interval/interval.hpp @@ -1,66 +1,183 @@ // An interval object. #pragma once +#include + +#include + #include -#include +namespace ipc::rigid { -#define USE_FILIB_INTERVALS -#ifdef USE_FILIB_INTERVALS -#include -#endif +class Interval { +public: + Interval(); + Interval(double x); + Interval(double x, double y); -#include + static Interval empty(); -namespace ipc::rigid { + /* ------------------------------------------------------------------- */ + /* --- IO (input/output) --- */ + /* ------------------------------------------------------------------- */ -namespace interval_options { - typedef boost::numeric::interval_lib::checking_catch_nan - CheckingPolicy; -} // namespace interval_options - -#ifdef USE_FILIB_INTERVALS - -// Use filib rounding arithmetic -typedef boost::numeric::interval< - double, - boost::numeric::interval_lib::policies< - boost::numeric::interval_lib::save_state, - interval_options::CheckingPolicy>> - Interval; - -#elif defined(__APPLE__) - -// clang-format off -#warning "Rounding modes seem to be broken with trigonometric functions on macOS, unable to compute exact interval arithmetic!" -// clang-format on -typedef boost::numeric::interval< - double, - boost::numeric::interval_lib::policies< - boost::numeric::interval_lib::save_state< - boost::numeric::interval_lib::rounded_transc_exact>, - interval_options::CheckingPolicy>> - Interval; - -#else - -// Use proper rounding arithmetic -typedef boost::numeric::interval< - double, - boost::numeric::interval_lib::policies< - boost::numeric::interval_lib::save_state< - boost::numeric::interval_lib::rounded_transc_std>, - interval_options::CheckingPolicy>> - Interval; - -#endif // USE_FILIB_INTERVALS + friend std::istream& operator>>(std::istream& is, Interval& a); + friend std::ostream& operator<<(std::ostream& os, const Interval& a); + + /* ------------------------------------------------------------------- */ + /* --- interval arithmetic (basic operations) --- */ + /* ------------------------------------------------------------------- */ + + friend Interval operator+(const Interval& a, const Interval& b); + friend Interval operator+(const Interval& a, const double b); + friend Interval operator+(const double a, const Interval& b); + friend Interval operator+(const Interval& a); + + Interval& operator+=(const Interval& rhs); + Interval& operator+=(const double& rhs); + + friend Interval operator-(const Interval& a, const Interval& b); + friend Interval operator-(const Interval& a, const double b); + friend Interval operator-(const double a, const Interval& b); + friend Interval operator-(const Interval& a); + + Interval& operator-=(const Interval& rhs); + Interval& operator-=(const double rhs); + + friend Interval operator*(const Interval& a, const Interval& b); + friend Interval operator*(const Interval& a, double b); + friend Interval operator*(double a, const Interval& b); + + Interval& operator*=(const Interval& rhs); + Interval& operator*=(const double rhs); + + friend Interval operator/(const Interval& a, const Interval& b); + friend Interval operator/(const Interval& a, const double b); + friend Interval operator/(const double a, const Interval& b); + + Interval& operator/=(const Interval& rhs); + Interval& operator/=(const double& rhs); + + /* ------------------------------------------------------------------- */ + /* --- Interval arithmetic (logical operations) --- */ + /* ------------------------------------------------------------------- */ + + friend bool operator==(const Interval& a, const Interval& b); + friend bool operator==(const Interval& a, const double b); + + friend bool operator!=(const Interval& a, const Interval& b); + + friend bool operator<(const Interval& a, const Interval& b); + friend bool operator<(const double a, const Interval& b); + friend bool operator<=(const Interval& a, const Interval& b); + friend bool operator<=(const double a, const Interval& b); + + friend bool operator>(const Interval& a, const Interval& b); + friend bool operator>(const Interval& a, const double b); + friend bool operator>=(const Interval& a, const Interval& b); + friend bool operator>=(const Interval& a, const double b); + + friend Interval operator|(const Interval& a, const Interval& b); + friend Interval operator&(const Interval& a, const Interval& b); + + Interval& operator|=(const Interval& b); + Interval& operator&=(const Interval& b); + + friend bool in(double a, const Interval& b); + friend bool in(const Interval& a, const Interval& b); + + bool is_empty() const; + bool zero_in() const; + + bool overlaps(const Interval& b) const; + + /* ------------------------------------------------------------------- */ + /* --- utilities, mid, diam, ... --- */ + /* ------------------------------------------------------------------- */ + + double mid() const; + std::pair bisect() const; + friend bool disjoint(const Interval& a, const Interval& b); + double diam() const; + double drel() const; + double width() const { return diam(); } + Interval blow(double eps) const; + + // min max function, same as what BOOST does + friend Interval max(const Interval& x, const Interval& y); + friend Interval max(const Interval& x, double y); + friend Interval max(double x, const Interval& y); + + friend Interval min(const Interval& x, const Interval& y); + friend Interval min(const Interval& x, double y); + friend Interval min(double x, const Interval& y); + + /* ------------------------------------------------------------------- */ + /* --- Interval arithmetic (elementary functions) --- */ + /* ------------------------------------------------------------------- */ + + friend Interval exp(const Interval& a); + friend Interval expm(const Interval& a); + friend Interval sinh(const Interval& a); + friend Interval cosh(const Interval& a); + friend Interval coth(const Interval& a); + friend Interval tanh(const Interval& a); + friend Interval log(const Interval& a); + friend Interval ln(const Interval& a); + friend Interval lg1p(const Interval& a); + friend Interval sqrt(const Interval& a); + friend Interval sqr(const Interval& a); + friend Interval asnh(const Interval& a); + friend Interval asinh(const Interval& a); + friend Interval acsh(const Interval& a); + friend Interval acosh(const Interval& a); + friend Interval acth(const Interval& a); + friend Interval acoth(const Interval& a); + friend Interval atnh(const Interval& a); + friend Interval atanh(const Interval& a); + friend Interval asin(const Interval& a); + friend Interval acos(const Interval& a); + friend Interval acot(const Interval& a); + friend Interval atan(const Interval& a); + friend Interval sin(const Interval& a); + friend Interval cos(const Interval& a); + friend Interval cot(const Interval& a); + friend Interval tan(const Interval& a); + friend Interval exp2(const Interval& a); + friend Interval ex10(const Interval& a); + friend Interval log2(const Interval& a); + friend Interval lg10(const Interval& a); + friend Interval erf(const Interval& a); + friend Interval erfc(const Interval& a); + + friend Interval abs(const Interval& a); + + const double& lower() const { return INF; } + const double& upper() const { return SUP; } + + double& lower() { return INF; } + double& upper() { return SUP; } + +protected: + // Helper functions to convert from pure FILib interval to my Interval + Interval(interval i) + { + INF = i.INF; + SUP = i.SUP; + } + + // Helper functions to convert from my Interval to pure FILib interval + operator interval() const { return { INF, SUP }; } + + double INF, SUP; +}; template inline Eigen::VectorXd width(const Eigen::MatrixBase& x) { Eigen::VectorXd w(x.size()); for (int i = 0; i < x.size(); i++) { - w(i) = width(x(i)); + w(i) = x(i).width(); } return w; } @@ -81,7 +198,7 @@ inline bool zero_in(const Eigen::MatrixBase& x) { // Check if the origin is in the n-dimensional interval for (int i = 0; i < x.size(); i++) { - if (!boost::numeric::zero_in(x(i))) { + if (!x(i).zero_in()) { return false; } } @@ -115,19 +232,19 @@ struct ScalarBinaryOpTraits { typedef ipc::rigid::Interval ReturnType; }; -#if EIGEN_MAJOR_VERSION >= 3 -namespace internal { - template - struct is_convertible> { - enum { value = is_convertible::value }; - }; - - template - struct is_convertible< - boost::numeric::interval, - boost::numeric::interval> { - enum { value = true }; - }; -} // namespace internal -#endif +// #if EIGEN_MAJOR_VERSION >= 3 +// namespace internal { +// template +// struct is_convertible> { +// enum { value = is_convertible::value }; +// }; + +// template +// struct is_convertible< +// boost::numeric::interval, +// boost::numeric::interval> { +// enum { value = true }; +// }; +// } // namespace internal +// #endif } // namespace Eigen diff --git a/src/interval/interval_root_finder.cpp b/src/interval/interval_root_finder.cpp index d0d67c1e..c1f082b4 100644 --- a/src/interval/interval_root_finder.cpp +++ b/src/interval/interval_root_finder.cpp @@ -81,11 +81,11 @@ void log_octree( return; } - std::pair t_split = bisect(x0(0)); + std::pair t_split = x0(0).bisect(); for (Interval t : { t_split.first, t_split.second }) { - std::pair alpha_split = bisect(x0(1)); + std::pair alpha_split = x0(1).bisect(); for (Interval alpha : { alpha_split.first, alpha_split.second }) { - std::pair beta_split = bisect(x0(2)); + std::pair beta_split = x0(2).bisect(); for (Interval beta : { beta_split.first, beta_split.second }) { Vector3I x(t, alpha, beta); log_octree(f, x, levels - 1); @@ -178,26 +178,13 @@ bool interval_root_finder( } assert(split_i >= 0 && split_i <= x.size()); - std::pair halves = bisect(x(split_i)); + std::pair halves = x(split_i).bisect(); // Push the second half on first so it is examined after the first half x(split_i) = halves.second; xs.push(x); x(split_i) = halves.first; xs.push(x); } - // TODO: This is needs to be updated when max_iterations is renabled - // if (!xs.empty()) { - // // Return the earliest possible time of impact - // x = xs.top().first; - // xs.pop(); - // while (!xs.empty()) { - // if (xs.top().first[0].lower() < x[0].lower()) { - // x = xs.top().first; - // } - // xs.pop(); - // } - // return true; // A conservative answer - // } x = earliest_root; return found_root; } diff --git a/src/io/read_rb_scene.cpp b/src/io/read_rb_scene.cpp index 31e8ef4d..29bb065e 100644 --- a/src/io/read_rb_scene.cpp +++ b/src/io/read_rb_scene.cpp @@ -3,7 +3,6 @@ #include #include -#include // filesystem #include #include #include @@ -16,6 +15,9 @@ #include #include +#include +namespace fs = std::filesystem; + namespace ipc::rigid { template diff --git a/src/io/write_obj.cpp b/src/io/write_obj.cpp index 6d537730..f8cc2137 100644 --- a/src/io/write_obj.cpp +++ b/src/io/write_obj.cpp @@ -15,11 +15,12 @@ #include #include -#include // filesystem - #include #include +#include +namespace fs = std::filesystem; + namespace ipc::rigid { static const Eigen::IOFormat vertices_format( diff --git a/src/main.cpp b/src/main.cpp index 9a9bd0db..486bfd42 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,8 +6,6 @@ #include #include -#include // filesystem - #include #ifdef RIGID_IPC_WITH_OPENGL #include @@ -15,6 +13,9 @@ #include #include +#include +namespace fs = std::filesystem; + int main(int argc, char* argv[]) { using namespace ipc::rigid; diff --git a/src/opt/distance_barrier_constraint.hpp b/src/opt/distance_barrier_constraint.hpp index 84d2c2e4..ce400985 100644 --- a/src/opt/distance_barrier_constraint.hpp +++ b/src/opt/distance_barrier_constraint.hpp @@ -70,8 +70,7 @@ class DistanceBarrierConstraint : public CollisionConstraint { } double compute_minimum_distance( - const RigidBodyAssembler& bodies, - const PosesD& poses) const; + const RigidBodyAssembler& bodies, const PosesD& poses) const; // Settings // ---------- diff --git a/src/physics/rigid_body_assembler.hpp b/src/physics/rigid_body_assembler.hpp index a2dda51f..baa195ba 100644 --- a/src/physics/rigid_body_assembler.hpp +++ b/src/physics/rigid_body_assembler.hpp @@ -13,8 +13,8 @@ namespace ipc::rigid { class RigidBodyAssembler { public: - RigidBodyAssembler() {} - ~RigidBodyAssembler() {} + RigidBodyAssembler() { } + ~RigidBodyAssembler() { } /// @brief inits assembler to use this set of rigid-bodies void init(const std::vector& rbs); diff --git a/src/problems/distance_barrier_rb_problem.cpp b/src/problems/distance_barrier_rb_problem.cpp index 72469c18..8e475a77 100644 --- a/src/problems/distance_barrier_rb_problem.cpp +++ b/src/problems/distance_barrier_rb_problem.cpp @@ -603,8 +603,8 @@ bool DistanceBarrierRBProblem::take_step(const Eigen::VectorXd& x) * (Qdot_prev + h / 4.0 * ( - // Tau * Jinv + - rb.Qddot)); + // Tau * Jinv + + rb.Qddot)); rb.Qddot = 4 * (Q - Q_tilde) / (h * h); //+ Tau * Jinv; break; } @@ -1248,7 +1248,7 @@ void apply_chain_rule( } struct PotentialStorage { - PotentialStorage() {} + PotentialStorage() { } PotentialStorage(size_t nvars) { gradient.setZero(nvars); } double potential = 0; Eigen::VectorXd gradient; diff --git a/src/problems/rigid_body_collision_constraint.cpp b/src/problems/rigid_body_collision_constraint.cpp index 1263cca9..60ddf5aa 100644 --- a/src/problems/rigid_body_collision_constraint.cpp +++ b/src/problems/rigid_body_collision_constraint.cpp @@ -49,9 +49,7 @@ RigidBodyEdgeEdgeConstraint::RigidBodyEdgeEdgeConstraint( } RigidBodyFaceVertexConstraint::RigidBodyFaceVertexConstraint( - const RigidBodyAssembler& bodies, - long face_index, - long vertex_index) + const RigidBodyAssembler& bodies, long face_index, long vertex_index) { const auto& face = bodies.m_faces.row(face_index); bodies.global_to_local_vertex( diff --git a/src/problems/rigid_body_collision_constraint.hpp b/src/problems/rigid_body_collision_constraint.hpp index f891eca1..16333581 100644 --- a/src/problems/rigid_body_collision_constraint.hpp +++ b/src/problems/rigid_body_collision_constraint.hpp @@ -26,20 +26,20 @@ struct RigidBodyVertexVertexConstraint { const RigidBodyAssembler& bodies, const VertexVertexConstraint& vv_constraint) : RigidBodyVertexVertexConstraint( - bodies, - vv_constraint.vertex0_index, - vv_constraint.vertex1_index, - vv_constraint.multiplicity) + bodies, + vv_constraint.vertex0_index, + vv_constraint.vertex1_index, + vv_constraint.multiplicity) { } RigidBodyVertexVertexConstraint( const RigidBodyAssembler& bodies, const VertexVertexFrictionConstraint& vv_constraint) : RigidBodyVertexVertexConstraint( - bodies, - vv_constraint.vertex0_index, - vv_constraint.vertex1_index, - vv_constraint.multiplicity) + bodies, + vv_constraint.vertex0_index, + vv_constraint.vertex1_index, + vv_constraint.multiplicity) { } @@ -69,20 +69,20 @@ struct RigidBodyEdgeVertexConstraint { const RigidBodyAssembler& bodies, const EdgeVertexConstraint& ev_constraint) : RigidBodyEdgeVertexConstraint( - bodies, - ev_constraint.edge_index, - ev_constraint.vertex_index, - ev_constraint.multiplicity) + bodies, + ev_constraint.edge_index, + ev_constraint.vertex_index, + ev_constraint.multiplicity) { } RigidBodyEdgeVertexConstraint( const RigidBodyAssembler& bodies, const EdgeVertexFrictionConstraint& ev_constraint) : RigidBodyEdgeVertexConstraint( - bodies, - ev_constraint.edge_index, - ev_constraint.vertex_index, - ev_constraint.multiplicity) + bodies, + ev_constraint.edge_index, + ev_constraint.vertex_index, + ev_constraint.multiplicity) { } @@ -118,17 +118,17 @@ struct RigidBodyEdgeEdgeConstraint { const RigidBodyAssembler& bodies, const EdgeEdgeConstraint& ee_constraint) : RigidBodyEdgeEdgeConstraint( - bodies, - ee_constraint.edge0_index, - ee_constraint.edge1_index, - ee_constraint.eps_x) + bodies, + ee_constraint.edge0_index, + ee_constraint.edge1_index, + ee_constraint.eps_x) { } RigidBodyEdgeEdgeConstraint( const RigidBodyAssembler& bodies, const EdgeEdgeFrictionConstraint& ee_constraint) : RigidBodyEdgeEdgeConstraint( - bodies, ee_constraint.edge0_index, ee_constraint.edge1_index, -1) + bodies, ee_constraint.edge0_index, ee_constraint.edge1_index, -1) { } @@ -154,21 +154,19 @@ struct RigidBodyFaceVertexConstraint { const long multiplicity = 1; RigidBodyFaceVertexConstraint( - const RigidBodyAssembler& bodies, - long face_index, - long vertex_index); + const RigidBodyAssembler& bodies, long face_index, long vertex_index); RigidBodyFaceVertexConstraint( const RigidBodyAssembler& bodies, const FaceVertexConstraint& fv_constraint) : RigidBodyFaceVertexConstraint( - bodies, fv_constraint.face_index, fv_constraint.vertex_index) + bodies, fv_constraint.face_index, fv_constraint.vertex_index) { } RigidBodyFaceVertexConstraint( const RigidBodyAssembler& bodies, const FaceVertexFrictionConstraint& fv_constraint) : RigidBodyFaceVertexConstraint( - bodies, fv_constraint.face_index, fv_constraint.vertex_index) + bodies, fv_constraint.face_index, fv_constraint.vertex_index) { } @@ -208,9 +206,7 @@ vertex_local_body_ids(const Constraints& constraints, size_t ci) template std::array body_ids( - const RigidBodyAssembler& bodies, - const Constraints& constraints, - size_t ci) + const RigidBodyAssembler& bodies, const Constraints& constraints, size_t ci) { if (ci < constraints.vv_constraints.size()) { return RigidBodyVertexVertexConstraint( diff --git a/src/profiler.cpp b/src/profiler.cpp index 1ecba203..821d6c17 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1,9 +1,11 @@ -#include // filesystem #include #include #include #include +#include +namespace fs = std::filesystem; + #ifdef RIGID_IPC_PROFILE_FUNCTIONS namespace ipc::rigid { diff --git a/src/solvers/newton_solver.cpp b/src/solvers/newton_solver.cpp index 046cfc37..d92648d7 100644 --- a/src/solvers/newton_solver.cpp +++ b/src/solvers/newton_solver.cpp @@ -23,7 +23,6 @@ NewtonSolver::NewtonSolver() , is_velocity_conv_tol_abs(false) , is_energy_converged(false) { - linear_solver = polysolve::LinearSolver::create("", ""); } void NewtonSolver::settings(const nlohmann::json& json) @@ -34,19 +33,6 @@ void NewtonSolver::settings(const nlohmann::json& json) velocity_conv_tol = json["velocity_conv_tol"]; is_velocity_conv_tol_abs = json["is_velocity_conv_tol_abs"]; m_line_search_lower_bound = json["line_search_lower_bound"]; - - linear_solver_settings = json["linear_solver"]; - try { - linear_solver = - polysolve::LinearSolver::create(linear_solver_settings["name"], ""); - } catch (const std::runtime_error& err) { - spdlog::error("{}! Using Eigen::SimplicialLDLT instead.", err.what()); - linear_solver_settings["name"] = "Eigen::SimplicialLDLT"; - linear_solver = - polysolve::LinearSolver::create(linear_solver_settings["name"], ""); - } - linear_solver->setParameters(linear_solver_settings); - reset_stats(); } @@ -55,7 +41,6 @@ nlohmann::json NewtonSolver::settings() const nlohmann::json settings; settings["max_iterations"] = max_iterations; settings["convergence_criteria"] = convergence_criteria; - settings["linear_solver"] = linear_solver_settings; settings["energy_conv_tol"] = energy_conv_tol; settings["velocity_conv_tol"] = velocity_conv_tol; settings["is_velocity_conv_tol_abs"] = is_velocity_conv_tol_abs; @@ -517,18 +502,14 @@ bool NewtonSolver::compute_direction( // direction = dense_hessian.ldlt().solve(-gradient); // solve_success = true; // } else { - linear_solver->analyzePattern(hessian, hessian.rows()); - linear_solver->factorize(hessian); - nlohmann::json info; - linear_solver->getInfo(info); - // TODO: This check only works for direct Eigen solvers - if (!info.contains("solver_info") || info["solver_info"] == "Success") { - // TODO: Do we have a better initial guess for iterative - // solvers? + Eigen::SimplicialLDLT> linear_solver; + linear_solver.analyzePattern(hessian); + linear_solver.factorize(hessian); + + if (linear_solver.info() == Eigen::Success) { direction = Eigen::VectorXd::Zero(gradient.size()); - linear_solver->solve(-gradient, direction); - linear_solver->getInfo(info); - if (!info.contains("solver_info") || info["solver_info"] == "Success") { + direction = linear_solver.solve(-gradient); + if (linear_solver.info() == Eigen::Success) { solve_success = true; } else { spdlog::warn( diff --git a/src/solvers/newton_solver.hpp b/src/solvers/newton_solver.hpp index 2e6d11c1..5c109d58 100644 --- a/src/solvers/newton_solver.hpp +++ b/src/solvers/newton_solver.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include @@ -130,10 +129,6 @@ class NewtonSolver : public virtual OptimizationSolver { Eigen::VectorXd grad_direction; ///< Gradient with fixed DoF set to zero Eigen::SparseMatrix hessian, hessian_free; - // Linear solver pointer - std::unique_ptr linear_solver; - nlohmann::json linear_solver_settings; - private: void reset_stats(); diff --git a/src/tools/generate_bullet_results.cpp b/src/tools/generate_bullet_results.cpp index b1ee3634..254552f7 100644 --- a/src/tools/generate_bullet_results.cpp +++ b/src/tools/generate_bullet_results.cpp @@ -1,10 +1,12 @@ #include -#include // filesystem #include #include #include +#include +namespace fs = std::filesystem; + int generate_bullet_results( const std::string& json_path, const std::string& bullet_result_file_path) { @@ -21,8 +23,8 @@ int generate_bullet_results( int lastSlash = bullet_result_file_path.find_last_of('/'); std::string folderPath = "output/" + bullet_result_file_path.substr( - lastSlash, - bullet_result_file_path.find_last_of('.') - lastSlash) + lastSlash, + bullet_result_file_path.find_last_of('.') - lastSlash) + "/"; fs::create_directories(fs::path(folderPath)); diff --git a/src/tools/obj_sequence.cpp b/src/tools/obj_sequence.cpp index 99765a83..9d09c31a 100644 --- a/src/tools/obj_sequence.cpp +++ b/src/tools/obj_sequence.cpp @@ -1,9 +1,11 @@ #include -#include // filesystem #include #include +#include +namespace fs = std::filesystem; + int main(int argc, char* argv[]) { using namespace ipc::rigid; diff --git a/src/tools/renderer/main.cpp b/src/tools/renderer/main.cpp index 9c944633..9e03ed62 100644 --- a/src/tools/renderer/main.cpp +++ b/src/tools/renderer/main.cpp @@ -1,7 +1,6 @@ #include #include -#include // filesystem #include #include #include @@ -16,6 +15,9 @@ #include "render_mesh.hpp" +#include +namespace fs = std::filesystem; + using namespace swr; struct SimRenderArgs { diff --git a/src/tools/sim_to_gltf.cpp b/src/tools/sim_to_gltf.cpp index be452771..97801c2a 100644 --- a/src/tools/sim_to_gltf.cpp +++ b/src/tools/sim_to_gltf.cpp @@ -1,9 +1,11 @@ #include -#include // filesystem #include #include +#include +namespace fs = std::filesystem; + int main(int argc, char* argv[]) { using namespace ipc::rigid; @@ -22,8 +24,8 @@ int main(int argc, char* argv[]) spdlog::level::level_enum loglevel = spdlog::level::warn; app.add_option("--log,--loglevel", loglevel, "log level") ->default_val(loglevel) - ->transform( - CLI::CheckedTransformer(SPDLOG_LEVEL_NAMES_TO_LEVELS, CLI::ignore_case)); + ->transform(CLI::CheckedTransformer( + SPDLOG_LEVEL_NAMES_TO_LEVELS, CLI::ignore_case)); try { app.parse(argc, argv); diff --git a/src/tools/time_ccd.cpp b/src/tools/time_ccd.cpp index 98496dbc..b9d6cd2d 100644 --- a/src/tools/time_ccd.cpp +++ b/src/tools/time_ccd.cpp @@ -1,6 +1,5 @@ #include -#include // filesystem #include #include @@ -10,6 +9,9 @@ #include #include +#include +namespace fs = std::filesystem; + using namespace ipc; using namespace ipc::rigid; diff --git a/src/utils/clamp.hpp b/src/utils/clamp.hpp index 1a080f46..d12ebc6d 100644 --- a/src/utils/clamp.hpp +++ b/src/utils/clamp.hpp @@ -11,7 +11,7 @@ template inline T clamp_to_01(const T& x) template <> inline Interval clamp_to_01(const Interval& x) { - return boost::numeric::intersect(x, Interval(0, 1)); + return x & Interval(0, 1); } } // namespace ipc::rigid diff --git a/src/utils/is_zero.hpp b/src/utils/is_zero.hpp index d0bc906e..99ab675e 100644 --- a/src/utils/is_zero.hpp +++ b/src/utils/is_zero.hpp @@ -7,13 +7,10 @@ namespace ipc::rigid { template inline bool is_zero(T x) { return x == 0.0; } -template <> inline bool is_zero(Interval x) -{ - return boost::numeric::zero_in(x); -} +template <> inline bool is_zero(Interval x) { return x.zero_in(); } template -inline bool is_zero(Vector X) +inline bool is_zero(const Vector& X) { // Check that all components contain zero // WARNING: This is conservative, but no exact diff --git a/src/utils/sinc.cpp b/src/utils/sinc.cpp index 0ad4e6c3..a2453e79 100644 --- a/src/utils/sinc.cpp +++ b/src/utils/sinc.cpp @@ -79,22 +79,19 @@ Interval sinc(const Interval& x) } // sinc is monotonically decreasing, so flip a and b. // TODO: Set rounding modes here to avoid round off error. - y = hull( - y, - Interval( - // https://www.wolframalpha.com/input/?i=min+sin%28x%29%2Fx+between+4+and+5 - std::max( - _sinc_interval_taylor(x_monotonic.upper()).lower(), - -0.271724), // <-- A conservative lower bound for sinc(x) - std::min( - _sinc_interval_taylor(x_monotonic.lower()).upper(), 1.0))); + y |= Interval( + // https://www.wolframalpha.com/input/?i=min+sin%28x%29%2Fx+between+4+and+5 + std::max( + _sinc_interval_taylor(x_monotonic.upper()).lower(), + -0.271724), // <-- A conservative lower bound for sinc(x) + std::min(_sinc_interval_taylor(x_monotonic.lower()).upper(), 1.0)); } // Case 2 (Not necessarily monotonic): - if (!empty(x_gt_monotonic)) { + if (!x_gt_monotonic.is_empty()) { // x_gt_monotonic is larger than one, so the division should be well // behaved. - y = hull(y, sin(x_gt_monotonic) / x_gt_monotonic); + y |= sin(x_gt_monotonic) / x_gt_monotonic; } return y; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 45a298c2..343aa310 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,10 +66,4 @@ target_compile_definitions(rigid_ipc_tests PUBLIC CATCH_CONFIG_ENABLE_BENCHMARKI # Register tests set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON) -catch_discover_tests(rigid_ipc_tests) - -################################################################################ - -add_executable(test_rounding rounding_test.cpp) -target_link_libraries(test_rounding PUBLIC Boost::boost) -target_compile_options(test_rounding PUBLIC -msse2) +catch_discover_tests(rigid_ipc_tests) \ No newline at end of file