Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ target_include_directories(OpenABF
$<BUILD_INTERFACE:${OPENABF_LINK_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_features(OpenABF INTERFACE cxx_std_17)
target_compile_features(OpenABF INTERFACE cxx_std_20)
set_target_properties(OpenABF
PROPERTIES
PUBLIC_HEADER "${public_hdrs}"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The templated interface is designed for simple out-of-the-box use, and
integration with existing geometric processing pipelines is quick and easy.

## Dependencies
- C++17 compiler
- C++20 compiler
- [Eigen 3.3+](http://eigen.tuxfamily.org/)
- CMake 3.15+ (optional)

Expand Down Expand Up @@ -161,7 +161,7 @@ path. As OpenABF depends upon the Eigen library, you will also need to add the
Eigen headers to your include path:

```shell
g++ -I /path/to/eigen/ -std=c++17 -DNDEBUG -O3 main.cpp -o main
g++ -I /path/to/eigen/ -std=c++20 -DNDEBUG -O3 main.cpp -o main
```

> [!IMPORTANT]
Expand All @@ -175,8 +175,8 @@ automatically conformant with the C++ standard in all cases. This may lead to
the following issues when compiling against OpenABF.

> [!NOTE]
> As this project only supports C++17 and up, you should always compile
with at least `/std:c++17`.
> As this project only supports C++20 and up, you should always compile
with at least `/std:c++20`.

#### Undeclared identifier errors

Expand Down
2 changes: 1 addition & 1 deletion conductor/code_styleguides/cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Setters on instance configuration follow the instance-method rule: `set_<thing>(
Pre-2026 code in several places uses `camelCase` for instance methods and `detail::` free functions (e.g., `setLevelRatio`, `detail::lscm::buildSystem`, `DecimationMesh::tryCollapse`). These are tracked for rename in issue #94. New code must follow the table above.

## C++ Standards
- **Standard**: C++17 required; do not use C++20 features in public headers without a guard
- **Standard**: C++20 required
- **Headers**: All public headers must be self-contained (include what they use)
- **`#pragma once`**: Preferred over include guards in project headers
- **RAII**: Prefer RAII over manual resource management
Expand Down
2 changes: 1 addition & 1 deletion conductor/setup_state.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"key_goals": "Zero-to-low dependency header-only integration; multiple algorithms (ABF, ABF++, LSCM); multi-chart flattening and packing; high numerical accuracy; production-efficient implementations.",
"voice_tone": "Concise and direct",
"design_principles": "Simplicity over features, Performance first, Developer experience focused",
"languages": "C++17, Python 3.x (scripts)",
"languages": "C++20, Python 3.x (scripts)",
"frontend": "None",
"backend": "None",
"database": "None",
Expand Down
2 changes: 1 addition & 1 deletion conductor/tech-stack.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Tech Stack

## Primary Language
- **C++17** — all library code; required standard for consumers
- **C++20** — all library code; required standard for consumers
- **Python 3.x** — utility/build scripts (e.g. `thirdparty/amalgamate/amalgamate.py` for single-header generation); Python bindings (pybind11) are a future consideration

## Build System
Expand Down
8 changes: 4 additions & 4 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ file(s) into your include directory. This page outlines the various installation
options.

## Dependencies
- C++17 compiler
- C++20 compiler
- [Eigen 3.3+](http://eigen.tuxfamily.org/)
- CMake 3.15+ (optional)

Expand Down Expand Up @@ -74,7 +74,7 @@ path. As %OpenABF depends upon the Eigen library, you will also need to add the
Eigen headers to your include path:

```{.sh}
g++ -I /path/to/eigen/ -std=c++17 -DNDEBUG -O3 main.cpp -o main
g++ -I /path/to/eigen/ -std=c++20 -DNDEBUG -O3 main.cpp -o main
```

**Note:** For best performance, compile your application with the `-DNDEBUG -03`
Expand All @@ -86,8 +86,8 @@ For many legacy reasons, the Microsoft Visual C++ compiler (MSVC) is not
automatically conformant with the C++ standard in all cases. This may lead to
the following issues when compiling against OpenABF.

**Note:** As this project only supports C++17 and up, you should always compile
with at least `/std:c++17`.
**Note:** As this project only supports C++20 and up, you should always compile
with at least `/std:c++20`.

### Undeclared identifier errors

Expand Down
19 changes: 9 additions & 10 deletions include/OpenABF/ABF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cassert>
#include <cmath>
#include <concepts>
#include <limits>
#include <vector>

Expand Down Expand Up @@ -84,7 +85,7 @@ void InitializeAnglesAndWeights(MeshPtr& m)
}

/** @brief Compute ∇CTri w.r.t LambdaTri == CTri */
template <typename T, class FacePtr, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class FacePtr>
auto TriGrad(const FacePtr& f) -> T
{
T g = -PI<T>;
Expand All @@ -95,7 +96,7 @@ auto TriGrad(const FacePtr& f) -> T
}

/** @brief Compute ∇CPlan w.r.t LambdaPlan == CPlan */
template <typename T, class VertPtr, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class VertPtr>
auto PlanGrad(const VertPtr& v) -> T
{
T g = -2 * PI<T>;
Expand All @@ -106,7 +107,7 @@ auto PlanGrad(const VertPtr& v) -> T
}

/** @brief Compute ∇CLen w.r.t LambdaLen == CLen */
template <typename T, class VertPtr, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class VertPtr>
auto LenGrad(const VertPtr& vertex) -> T
{
T p1{1};
Expand All @@ -119,8 +120,7 @@ auto LenGrad(const VertPtr& vertex) -> T
}

/** @brief Compute ∇CLen w.r.t edge->alpha */
template <typename T, class VertPtr, class EdgePtr,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class VertPtr, class EdgePtr>
auto LenGrad(const VertPtr& vertex, const EdgePtr& edge) -> T
{
T p1{1};
Expand All @@ -146,7 +146,7 @@ auto LenGrad(const VertPtr& vertex, const EdgePtr& edge) -> T
}

/** @brief Compute ∇F w.r.t an edge's alpha */
template <typename T, class EdgePtr, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class EdgePtr>
auto AlphaGrad(const EdgePtr& edge) -> T
{
// δE/δα
Expand All @@ -172,7 +172,7 @@ auto AlphaGrad(const EdgePtr& edge) -> T
}

/** @brief Compute ∇F w.r.t all parameters */
template <typename T, class MeshPtr, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class MeshPtr>
auto Gradient(const MeshPtr& mesh) -> T
{
T g{0};
Expand Down Expand Up @@ -225,9 +225,8 @@ auto Gradient(const MeshPtr& mesh) -> T
* concept](https://eigen.tuxfamily.org/dox-devel/group__TopicSparseSystems.html)
* and templated on Eigen::SparseMatrix<T>
*/
template <typename T, class MeshType = detail::ABF::Mesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class MeshType = detail::ABF::Mesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>>
class ABF
{
public:
Expand Down
6 changes: 3 additions & 3 deletions include/OpenABF/ABFPlusPlus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cassert>
#include <cmath>
#include <concepts>
#include <limits>
#include <vector>

Expand Down Expand Up @@ -38,9 +39,8 @@ namespace OpenABF
* concept](https://eigen.tuxfamily.org/dox-devel/group__TopicSparseSystems.html)
* and templated on Eigen::SparseMatrix<T>
*/
template <typename T, class MeshType = detail::ABF::Mesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class MeshType = detail::ABF::Mesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>>
class ABFPlusPlus
{
public:
Expand Down
16 changes: 7 additions & 9 deletions include/OpenABF/AngleBasedLSCM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <algorithm>
#include <cmath>
#include <concepts>
#include <cstddef>
#include <iterator>
#include <optional>
Expand Down Expand Up @@ -32,9 +33,8 @@ template <template <class...> class U, class... Vs>
constexpr bool is_instance_of_v<U<Vs...>, U> = std::true_type{};

/** Solve least squares using A'Ab */
template <
class SparseMatrix, class DenseMatrix, class Solver,
std::enable_if_t<!is_instance_of_v<Solver, Eigen::LeastSquaresConjugateGradient>, bool> = false>
template <class SparseMatrix, class DenseMatrix, class Solver>
requires(!is_instance_of_v<Solver, Eigen::LeastSquaresConjugateGradient>)
auto SolveLeastSquares(SparseMatrix A, SparseMatrix b) -> DenseMatrix
{
// Setup AtA and solver
Expand All @@ -56,9 +56,8 @@ auto SolveLeastSquares(SparseMatrix A, SparseMatrix b) -> DenseMatrix
}

/** Solve least squares with LeastSquaresConjugateGradient */
template <
class SparseMatrix, class DenseMatrix, class Solver,
std::enable_if_t<is_instance_of_v<Solver, Eigen::LeastSquaresConjugateGradient>, bool> = true>
template <class SparseMatrix, class DenseMatrix, class Solver>
requires(is_instance_of_v<Solver, Eigen::LeastSquaresConjugateGradient>)
auto SolveLeastSquares(SparseMatrix A, SparseMatrix b) -> DenseMatrix
{
// Solve
Expand Down Expand Up @@ -118,9 +117,8 @@ auto SolveLeastSquares(SparseMatrix A, SparseMatrix b) -> DenseMatrix
* at the mesh sizes we target. Use IC only if you have profiled it favorably
* against Diagonal for your specific mesh class.
*/
template <typename T, class MeshType = HalfEdgeMesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T, class MeshType = HalfEdgeMesh<T>,
class Solver = Eigen::SparseLU<Eigen::SparseMatrix<T>, Eigen::COLAMDOrdering<int>>>
class AngleBasedLSCM
{
public:
Expand Down
18 changes: 12 additions & 6 deletions include/OpenABF/HalfEdgeMesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,14 +430,16 @@ class HalfEdgeMesh

/** Dereference operator */
template <bool Const_ = Const>
std::enable_if_t<Const_, reference> operator*() const
requires(Const_)
reference operator*() const
{
return current_;
}

/** Dereference operator */
template <bool Const_ = Const>
std::enable_if_t<not Const_, reference> operator*()
requires(not Const_)
reference operator*()
{
return current_;
}
Expand Down Expand Up @@ -507,13 +509,15 @@ class HalfEdgeMesh

/** Dereference (const overload) */
template <bool C = Const>
auto operator*() const -> std::enable_if_t<C, reference>
requires(C)
auto operator*() const -> reference
{
return current_;
}
/** Dereference (non-const overload) */
template <bool C = Const>
auto operator*() -> std::enable_if_t<!C, reference>
requires(!C)
auto operator*() -> reference
{
return current_;
}
Expand Down Expand Up @@ -598,13 +602,15 @@ class HalfEdgeMesh

/** Dereference (const overload) */
template <bool C = Const>
auto operator*() const -> std::enable_if_t<C, reference>
requires(C)
auto operator*() const -> reference
{
return *edgeIt_;
}
/** Dereference (non-const overload) */
template <bool C = Const>
auto operator*() -> std::enable_if_t<!C, reference>
requires(!C)
auto operator*() -> reference
{
return *edgeIt_;
}
Expand Down
6 changes: 3 additions & 3 deletions include/OpenABF/HierarchicalLSCM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <algorithm>
#include <array>
#include <cmath>
#include <concepts>
#include <limits>
#include <numeric>
#include <optional>
Expand Down Expand Up @@ -969,10 +970,9 @@ auto SolveLSCMLevel(const typename HalfEdgeMesh<T>::Pointer& levelMesh,
* The result is numerically equivalent but may differ in convergence
* behavior from a plain AngleBasedLSCM call.
*/
template <typename T, class MeshType = HalfEdgeMesh<T>,
template <std::floating_point T, class MeshType = HalfEdgeMesh<T>,
class Solver =
Eigen::ConjugateGradient<Eigen::SparseMatrix<T>, Eigen::Lower | Eigen::Upper>,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
Eigen::ConjugateGradient<Eigen::SparseMatrix<T>, Eigen::Lower | Eigen::Upper>>
class HierarchicalLSCM
{
public:
Expand Down
7 changes: 3 additions & 4 deletions include/OpenABF/Math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <algorithm>
#include <cmath>
#include <concepts>
#include <limits>
#include <numeric>

Expand Down Expand Up @@ -80,16 +81,14 @@ auto interior_angle(const Vector1& a, const Vector2& b)
}

/** @brief Convert degrees to radians */
template <typename T = float, typename T2,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T = float, typename T2>
constexpr auto to_radians(T2 deg) -> T
{
return deg * PI<T> / T(180);
}

/** @brief Convert radians to degrees */
template <typename T = float, typename T2,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
template <std::floating_point T = float, typename T2>
constexpr auto to_degrees(T2 rad) -> T
{
return rad * T(180) / PI<T>;
Expand Down
18 changes: 12 additions & 6 deletions include/OpenABF/Vec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace OpenABF
* @tparam T Element type
* @tparam Dims Number of elements
*/
template <typename T, std::size_t Dims, std::enable_if_t<std::is_arithmetic<T>::value, bool> = true>
template <typename T, std::size_t Dims>
requires(std::is_arithmetic_v<T>)
class Vec
{
/** Underlying element storage */
Expand Down Expand Up @@ -203,7 +204,8 @@ class Vec
}

/** @brief Multiplication assignment operator */
template <typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, bool> = true>
template <typename T2>
requires(std::is_arithmetic_v<T2>)
Vec& operator*=(const T2& b)
{
for (auto& v : val_) {
Expand All @@ -213,15 +215,17 @@ class Vec
}

/** @brief Multiplication operator */
template <typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, bool> = true>
template <typename T2>
requires(std::is_arithmetic_v<T2>)
friend Vec operator*(Vec lhs, const T2& rhs)
{
lhs *= rhs;
return lhs;
}

/** @brief Division assignment operator */
template <typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, bool> = true>
template <typename T2>
requires(std::is_arithmetic_v<T2>)
Vec& operator/=(const T2& b)
{
for (auto& v : val_) {
Expand All @@ -231,7 +235,8 @@ class Vec
}

/** @brief Division operator */
template <typename T2, std::enable_if_t<std::is_arithmetic<T2>::value, bool> = true>
template <typename T2>
requires(std::is_arithmetic_v<T2>)
friend Vec operator/(Vec lhs, const T2& rhs)
{
lhs /= rhs;
Expand All @@ -247,7 +252,8 @@ class Vec

/** @brief Compute the vector cross product */
template <class Vector, std::size_t D = Dims>
std::enable_if_t<D == 3, Vec> cross(const Vector& v)
requires(D == 3)
Vec cross(const Vector& v)
{
return OpenABF::cross(*this, v);
}
Expand Down
Loading