diff --git a/.github/workflows/test_windows_tpls.yml b/.github/workflows/test_windows_tpls.yml index b38b2aed0e..4ac42495d9 100644 --- a/.github/workflows/test_windows_tpls.yml +++ b/.github/workflows/test_windows_tpls.yml @@ -29,21 +29,21 @@ jobs: steps: - name: Checkout repo w/ submodules - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive - name: Set up python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: - python-version: '3.7' + python-version: '3.10' - name: List path and files run: ls - name: Run uberenv (${{ matrix.triplet }}) run: python3 ./scripts/uberenv/uberenv.py --triplet ${{ matrix.triplet }} - name: Save Uberenv logs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ always() }} with: name: uberenv_artifacts_${{ matrix.triplet }}_${{ matrix.cfg }}.zip @@ -73,7 +73,7 @@ jobs: ls ctest -C ${{ matrix.cfg }} --no-compress-output -T Test - name: Save CTest logs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ always() }} with: name: ctest_artifacts_${{ matrix.triplet }}_${{ matrix.cfg }}.zip diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index ebb02c070f..602f2e1f41 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -84,6 +84,9 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/ - Removes caching of `{PACKAGE}_FOUND` variables in `SetupAxomThirdParty.cmake` - We no longer test Axom with the XL compiler. So users should consider XL unsupported. +### Fixed +- `numerics::eigen_solve()` has been corrected to avoid an early return with error state. + ## [Version 0.9.0] - Release date 2024-03-19 ### Added diff --git a/src/axom/core/MDMapping.hpp b/src/axom/core/MDMapping.hpp index 78492a190e..872ad9996e 100644 --- a/src/axom/core/MDMapping.hpp +++ b/src/axom/core/MDMapping.hpp @@ -324,22 +324,16 @@ class MDMapping const axom::StackArray& v) const { // v is a permutation if all its values are unique and in [0, DIM). - axom::StackArray found; - for(int d = 0; d < DIM; ++d) - { - found[d] = false; - } - for(int d = 0; d < DIM; ++d) + axom::StackArray values_sorted = v; + + // After sorting, the values should be the sequence {0, 1, ... DIM - 1}. + axom::utilities::insertionSort(&values_sorted[0], DIM); + for(int d = 0; d < DIM; d++) { - if(v[d] < 0 || v[d] >= DIM) - { - return false; // Out of range. - } - if(found[v[d]] == true) + if(values_sorted[d] != d) { - return false; // Repeated index. + return false; } - found[v[d]] = true; } return true; } diff --git a/src/axom/core/numerics/eigen_solve.hpp b/src/axom/core/numerics/eigen_solve.hpp index 81fa50667b..04ebe3e1d6 100644 --- a/src/axom/core/numerics/eigen_solve.hpp +++ b/src/axom/core/numerics/eigen_solve.hpp @@ -38,7 +38,7 @@ namespace numerics * \param [in] A a square input matrix * \param [in] k number of eigenvalue-eigenvectors to find * \param [out] u pointer to k eigenvectors in order by magnitude of eigenvalue - * \param [out] lambdas pointer to k eigenvales in order by size + * \param [out] lambdas pointer to k eigenvalues in order by size * \param [in] numIterations optional number of iterations for the power method * \note if k <= 0, the solve is declared successful * \return rc return value, nonzero if the solve is successful. @@ -119,9 +119,12 @@ int eigen_solve(Matrix& A, int k, T* u, T* lambdas, int numIterations) bool res = normalize(vec, N); - if(!res) // something went wrong + // something went wrong, likely because `vec` is (numerically) + // in the span of the previous eigenvectors. Try again! + if(!res) { - return 0; + i--; + continue; } // 3: run depth iterations of power method; note that a loop invariant diff --git a/src/axom/primal/tests/primal_orientedboundingbox.cpp b/src/axom/primal/tests/primal_orientedboundingbox.cpp index 01f57dfe14..a9415f570c 100644 --- a/src/axom/primal/tests/primal_orientedboundingbox.cpp +++ b/src/axom/primal/tests/primal_orientedboundingbox.cpp @@ -121,6 +121,81 @@ TEST(primal_OBBox, obb_ctor_from_data) EXPECT_TRUE(obbox1.getExtents() == e); } +//------------------------------------------------------------------------------ +TEST(primal_OBBox, obb_ctor_from_point_array) +{ + constexpr int DIM = 3; + using CoordType = double; + using QPoint = primal::Point; + using QOBBox = primal::OrientedBoundingBox; + + QPoint pt1; // origin + QPoint pt2({1.0, 0.0, 0.0}); + QPoint pt3({0.0, 1.0, 0.0}); + QPoint pt4({0.0, 0.0, 1.0}); + QPoint pt5({1.0, 1.0, 0.0}); + QPoint pt6({1.0, 0.0, 1.0}); + QPoint pt7({0.0, 1.0, 1.0}); + QPoint pt8({1.0, 1.0, 1.0}); + + /* -1D OBB */ + QPoint* pts_00 = nullptr; + QOBBox obbox00(pts_00, 0); + + EXPECT_FALSE(obbox00.isValid()); + + /* 0D OBB */ + QPoint pts_0d[] = {pt1}; + QOBBox obbox0(pts_0d, 1); + + EXPECT_TRUE(obbox0.isValid()); + EXPECT_TRUE(obbox0.contains(pt1)); + + EXPECT_NEAR(obbox0.getCentroid()[0], 0.0, 1e-6); + EXPECT_NEAR(obbox0.getCentroid()[1], 0.0, 1e-6); + EXPECT_NEAR(obbox0.getCentroid()[2], 0.0, 1e-6); + + /* 1D OBB */ + QPoint pts_1d[] = {pt1, pt2}; + QOBBox obbox1(pts_1d, 2); + + EXPECT_TRUE(obbox1.isValid()); + EXPECT_TRUE(obbox1.contains(pt1)); + EXPECT_TRUE(obbox1.contains(pt2)); + + EXPECT_NEAR(obbox1.getCentroid()[0], 0.5, 1e-6); + EXPECT_NEAR(obbox1.getCentroid()[1], 0.0, 1e-6); + EXPECT_NEAR(obbox1.getCentroid()[2], 0.0, 1e-6); + + /* 2D OBB */ + QPoint pts_2d[] = {pt1, pt2, pt3, pt5}; + QOBBox obbox2(pts_2d, 4); + + EXPECT_TRUE(obbox2.isValid()); + EXPECT_TRUE(obbox2.contains(pt1)); + EXPECT_TRUE(obbox2.contains(pt2)); + EXPECT_TRUE(obbox2.contains(pt3)); + EXPECT_TRUE(obbox2.contains(pt5)); + + EXPECT_NEAR(obbox2.getCentroid()[0], 0.5, 1e-6); + EXPECT_NEAR(obbox2.getCentroid()[1], 0.5, 1e-6); + EXPECT_NEAR(obbox2.getCentroid()[2], 0.0, 1e-6); + + /* 3D OBB */ + QPoint pts_3d[] = {pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8}; + QOBBox obbox3(pts_3d, 8); + + // check containments + EXPECT_TRUE(obbox3.isValid()); + for(int i = 0; i < 8; i++) + { + EXPECT_TRUE(obbox3.contains(pts_3d[i])); + } + + // check settings + EXPECT_TRUE(obbox3.getCentroid() == QPoint(0.5)); +} + //------------------------------------------------------------------------------ TEST(primal_OBBox, obb_test_clear) { diff --git a/src/axom/slam/BivariateMap.hpp b/src/axom/slam/BivariateMap.hpp index c2859d0206..eb33188c7e 100644 --- a/src/axom/slam/BivariateMap.hpp +++ b/src/axom/slam/BivariateMap.hpp @@ -802,7 +802,7 @@ class BivariateMap::RangeIterator * index. Same as operator() */ template - DataRefType value(ComponentIndex... comp) const + AXOM_HOST_DEVICE DataRefType value(ComponentIndex... comp) const { return m_mapIterator(comp...); }