Repository: BSplineX/BSplineX
Pull request #30: Refactor/avoid unused included header
Author: login: SebastianoTaddei
Labels: name: task
description: A task that needed to be done
Created: 2025-04-19T15:22:23Z | Merged: 2025-04-21T14:28:59Z

Fixes #10 

Unfortunately the syntax

```cpp
using new_func = foo::old_func;
```

is not possible, especially with templates and overloads. Had to resort to plain

```cpp
using foo::old_func;
```

which works but doesn't allow renaming.

I also did a little cleanup.

Linked issue #10: Clang-tidy warning: "Included header bsplinex.hpp is not used directly"
When the BSplineX single-header is included as
```cpp 
#include "BSplineX/bsplinex.hpp"
```
(as shown in the examples), clang-tidy gives the following warning:
```
Included header bsplinex.hpp is not used directly [unused-includes]
```

This seems to happen because the single header only includes other headers, without defining any symbols directly.

I'm not sure how this should be addressed, but it would be nice to avoid this warning.
Linked issue comments: user: login: SebastianoTaddei
created_at: 2025-04-19T13:52:28Z
body: After some googling perhaps what we should do is the following. Modify `bsplinex.hpp` to only include actual useful files and reduce grouping. That would be

```cpp
#ifndef BSPLINEX_BSPLINEX_HPP
#define BSPLINEX_BSPLINEX_HPP

#include "BSplineX/bspline/bspline_types.hpp"
#include "BSplineX/bspline/bspline_factory_clamped.hpp"
#include "BSplineX/bspline/bspline_factory_open.hpp"
#include "BSplineX/bspline/bspline_factory_periodic.hpp"

#endif
```

Then, flatten the internal namespaces since the user likely doesn't care. That would be something like

```cpp
...

namespace bsplinex
{

using OpenUniform = types::OpenUniform;
using open_uniform = factory::open_uniform;
...

}

...
```

We could even go as far as changing `bsplinex` to `bsplinex_internal` for all files except this main one, but I don't know if I like it all that much.

Thoughts @masinag?
author_association: COLLABORATOR
user: login: masinag
created_at: 2025-04-19T14:16:29Z
body: It seems reasonable. Maybe we can consider renaming factory functions to something like `make_open_uniform` if we drop the `factory::` namespace.


author_association: COLLABORATOR
user: login: masinag
created_at: 2025-04-19T14:24:59Z
body: > We could even go as far as changing `bsplinex` to `bsplinex_internal` for all files except this main one, but I don't know if I like it all that much.

I don't think it's necessary, but I don't have a strong opinion. If we don't have good reasons, I would leave it as it is now.
author_association: COLLABORATOR
user: login: SebastianoTaddei
created_at: 2025-04-19T14:36:13Z
body: I agree with both comments, implementing them now.
author_association: COLLABORATOR

Diff:
diff --git a/.github/workflows/test_python_bindings_creation.yml b/.github/workflows/test_python_bindings_creation.yml
new file mode 100644
index 0000000..ff36ca3
--- /dev/null
+++ b/.github/workflows/test_python_bindings_creation.yml
@@ -0,0 +1,40 @@
+name: Test Python Bindings Creation
+
+on:
+  push:
+    branches: ["main"]
+  pull_request:
+    branches: ["main"]
+jobs:
+  test:
+    name: Test Python bindings creation on ${{ matrix.os }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest, macos-latest, macos-13, windows-latest]
+
+    steps:
+      - name: "Setup: checkout Python bindings repo"
+        uses: actions/checkout@v4
+        with:
+          repository: BSplineX/BSplineX-python
+
+      - name: "Setup: checkout repo"
+        uses: actions/checkout@v4
+        with:
+          path: BSplineX
+
+      - name: "Setup: get CMake"
+        uses: lukka/get-cmake@latest
+        with:
+          cmakeVersion: latestrc
+
+      - name: "Setup: get Python"
+        uses: actions/setup-python@v5
+        with:
+          python-version: "3.12"
+
+      - name: "Test: generate Python bindings"
+        run: |
+          pip install . -U
+        shell: bash
diff --git a/README.md b/README.md
index 360cea4..34651da 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # BSplineX
 
-The B-Spline library you have always dreamed of where performance and easy-to-use interfaces live in harmony.
+The B-Spline library you have always dreamed of where performance and
+easy-to-use interfaces live in harmony.
 
 ## Features
 
@@ -16,7 +17,10 @@ This is a non-exhaustive list of the currently supported features.
 
 ### Quick and dirty
 
-`BSplineX` is a header-only library that depends only on `Eigen`, so the quick and dirty way of installing it is by simply copying the `include` directory to your project and make sure to have `Eigen` available however you see fit. Alternatively, you can do things properly and use `CMake`.
+`BSplineX` is a header-only library that depends only on `Eigen`, so the quick
+and dirty way of installing it is by simply copying the `include` directory to
+your project and make sure to have `Eigen` available however you see fit.
+Alternatively, you can do things properly and use `CMake`.
 
 ### CMake
 
@@ -43,7 +47,8 @@ fetchcontent_makeavailable(BSplineX)
 target_link_libraries(your_target PRIVATE BSplineX::BSplineX)
 ```
 
-If you already have `BSplineX` somewhere on your system, you can use `find_pacakge` directly.
+If you already have `BSplineX` somewhere on your system, you can use
+`find_package` directly.
 
 ```cmake
 # Optionally specify a custom path to find content from
@@ -57,7 +62,8 @@ find_package(
 target_link_libraries(your_target PRIVATE BSplineX::BSplineX)
 ```
 
-Since we are nice people, we also show you how to conditionally use `FetchContent` based if you already have the library or not.
+Since we are nice people, we also show you how to conditionally use
+`FetchContent` based if you already have the library or not.
 
 ```cmake
 # Optionally specify a custom path to find content from
@@ -87,7 +93,8 @@ target_link_libraries(your_target PRIVATE BSplineX::BSplineX)
 
 ## Usage
 
-`BSplineX` is extremely easy to use, everything that is complex about B-Splines is hidden behind the curtain. Hereafter some quick examples.
+`BSplineX` is extremely easy to use, everything that is complex about B-Splines
+is hidden behind the curtain. Hereafter some quick examples.
 
 ### Creating a 1D B-Spline
 
@@ -106,7 +113,7 @@ int main()
   constexpr double max_knot{10.0};
   std::vector<double> ctrl_points{1.0, 0.3, 0.6, 0.9, 0.28, 9.32};
 
-  auto bspline = bsplinex::factory::clamped_uniform_constant(
+  auto bspline = bsplinex::make_clamped_uniform_constant(
     degree, min_knot, max_knot, num_knots, ctrl_points
   );
 
@@ -118,19 +125,28 @@ int main()
 }
 ```
 
-If you want to make it periodic or open, just change the template parameter, easy. Want to pass in a non-uniform knot sequence? Piece of cake, just set the `Curve` template parameter to `Curve::NON_UNIFORM` and pass in your knots vector. Boom, done, simple.
+If you want to make it periodic or open, just change the template parameter,
+easy. Want to pass in a non-uniform knot sequence? Piece of cake, just set the
+`Curve` template parameter to `Curve::NON_UNIFORM` and pass in your knots
+vector. Boom, done, simple.
 
-Now I know what you are thinking: "Dude, cool, but how on earth do I know which control points to use?". Fear not, and follow along ;).
+Now I know what you are thinking: "Dude, cool, but how on earth do I know which
+control points to use?". Fear not, and follow along ;).
 
 ### Fitting a 1D B-Spline
 
-In the previous example, the knots are easy to understand: they are you discretisation grid, so you just have to choose how you want to discretise along that dimension. Control points on the other hand are not easily graspable. Fortunately you don't really need to know them a priori, you can just interpolate (coming soon!) or fit some data points. Let's see how, assuming we start from the previous example.
+In the previous example, the knots are easy to understand: they are you
+discretisation grid, so you just have to choose how you want to discretise
+along that dimension. Control points on the other hand are not easily
+graspable. Fortunately you don't really need to know them a priori, you can
+just interpolate (coming soon!) or fit some data points. Let's see how,
+assuming we start from the previous example.
 
 ```cpp
 ...
 
   // Create the B-Spline without specifying the control points
-  auto bspline = bsplinex::factory::clamped_uniform_constant(
+  auto bspline = bsplinex::make_clamped_uniform_constant(
     degree, min_knot, max_knot, num_knots
   );
 
@@ -151,4 +167,9 @@ See the [examples](examples) folder for some more examples on how to use the lib
 
 ## Performance
 
-`BSplineX` is all about performance. In fact, aside from being a cool and useful project, it is our playground to understand modern code optimisation techniques. Our goal is to be as fast as humanly possible (albeit without having to re-write the library by hand in assembly). Hereafter a non-exhaustive quick table with some performance results. If you want to can run the benchmarks on your own PC.
+`BSplineX` is all about performance. In fact, aside from being a cool and
+useful project, it is our playground to understand modern code optimisation
+techniques. Our goal is to be as fast as humanly possible (albeit without
+having to re-write the library by hand in assembly). Hereafter a non-exhaustive
+quick table with some performance results. If you want to can run the
+benchmarks on your own PC.
diff --git a/bindings/BSplineX.i b/bindings/BSplineX.i
index 3125dec..9fa57b4 100644
--- a/bindings/BSplineX.i
+++ b/bindings/BSplineX.i
@@ -2,11 +2,11 @@
 
 // Injected C++ code
 %{
+#include "BSplineX/bsplinex.hpp"
 #include "BSplineX/defines.hpp"
 #include "BSplineX/types.hpp"
 #include "BSplineX/bspline/bspline.hpp"
 #include "BSplineX/bspline/bspline_types.hpp"
-#include "BSplineX/bspline/bspline_factory.hpp"
 #include "BSplineX/bspline/bspline_factory_open.hpp"
 #include "BSplineX/bspline/bspline_factory_clamped.hpp"
 #include "BSplineX/bspline/bspline_factory_periodic.hpp"
@@ -19,15 +19,15 @@ using namespace bsplinex;
 %template() std::pair<double, double>;
 %template() std::vector<double>;
 
+%include "BSplineX/bsplinex.hpp"
 %include "BSplineX/defines.hpp"
 %include "BSplineX/types.hpp"
 %include "BSplineX/bspline/bspline.hpp"
-%include "BSplineX/bspline/bspline_factory.hpp"
+%include "BSplineX/bspline/bspline_types.hpp"
 %include "BSplineX/bspline/bspline_factory_open.hpp"
 %include "BSplineX/bspline/bspline_factory_clamped.hpp"
 %include "BSplineX/bspline/bspline_factory_periodic.hpp"
 %include "BSplineX/bspline/bspline_lsq.hpp"
-%include "BSplineX/bspline/bspline_types.hpp"
 %include "exception.i"
 using namespace bsplinex;
 
@@ -39,66 +39,45 @@ using namespace bsplinex;
   }
 }
 
-%template(Condition) lsq::Condition<double>;
-%template() std::vector<lsq::Condition<double>>;
-
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
+%template(Condition) InterpolantCondition<double>;
+%template() std::vector<InterpolantCondition<double>>;
 
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
-%template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template() OpenUniform<double>;
+%template(open_uniform) make_open_uniform<double>;
 
 %template(OpenUniformConstant) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::CONSTANT>;
-%template() types::OpenUniformConstant<double>;
-%template(open_uniform_constant) factory::open_uniform_constant<double>;
+%template() OpenUniformConstant<double>;
+%template(open_uniform_constant) make_open_uniform_constant<double>;
 
 %template(OpenNonUniform) bspline::BSpline<double, Curve::NON_UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
-%template() types::OpenNonUniform<double>;
-%template(open_nonuniform) factory::open_nonuniform<double>;
+%template() OpenNonUniform<double>;
+%template(open_nonuniform) make_open_nonuniform<double>;
 
 %template(OpenNonUniformConstant) bspline::BSpline<double, Curve::NON_UNIFORM, BoundaryCondition::OPEN, Extrapolation::CONSTANT>;
-%template() types::OpenNonUniformConstant<double>;
-%template(open_nonuniform_constant) factory::open_nonuniform_constant<double>;
-
-//  ██████╗██╗      █████╗ ███╗   ███╗██████╗ ███████╗██████╗
-// ██╔════╝██║     ██╔══██╗████╗ ████║██╔══██╗██╔════╝██╔══██╗
-// ██║     ██║     ███████║██╔████╔██║██████╔╝█████╗  ██║  ██║
-// ██║     ██║     ██╔══██║██║╚██╔╝██║██╔═══╝ ██╔══╝  ██║  ██║
-// ╚██████╗███████╗██║  ██║██║ ╚═╝ ██║██║     ███████╗██████╔╝
-// ╚═════╝╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝╚═╝     ╚══════╝╚═════╝
+%template() OpenNonUniformConstant<double>;
+%template(open_nonuniform_constant) make_open_nonuniform_constant<double>;
 
 %template(ClampedUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::CLAMPED, Extrapolation::NONE>;
-%template() types::ClampedUniform<double>;
-%template(clamped_uniform) factory::clamped_uniform<double>;
+%template() ClampedUniform<double>;
+%template(clamped_uniform) make_clamped_uniform<double>;
 
 %template(ClampedUniformConstant) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::CLAMPED, Extrapolation::CONSTANT>;
-%template() types::ClampedUniformConstant<double>;
-%template(clamped_uniform_constant) factory::clamped_uniform_constant<double>;
+%template() ClampedUniformConstant<double>;
+%template(clamped_uniform_constant) make_clamped_uniform_constant<double>;
 
 %template(ClampedNonUniform) bspline::BSpline<double, Curve::NON_UNIFORM, BoundaryCondition::CLAMPED, Extrapolation::NONE>;
-%template() types::ClampedNonUniform<double>;
-%template(clamped_nonuniform) factory::clamped_nonuniform<double>;
+%template() ClampedNonUniform<double>;
+%template(clamped_nonuniform) make_clamped_nonuniform<double>;
 
 %template(ClampedNonUniformConstant) bspline::BSpline<double, Curve::NON_UNIFORM, BoundaryCondition::CLAMPED, Extrapolation::CONSTANT>;
-%template() types::ClampedNonUniformConstant<double>;
-%template(clamped_nonuniform_constant) factory::clamped_nonuniform_constant<double>;
-
-// ██████╗ ███████╗██████╗ ██╗ ██████╗ ██████╗ ██╗ ██████╗
-// ██╔══██╗██╔════╝██╔══██╗██║██╔═══██╗██╔══██╗██║██╔════╝
-// ██████╔╝█████╗  ██████╔╝██║██║   ██║██║  ██║██║██║
-// ██╔═══╝ ██╔══╝  ██╔══██╗██║██║   ██║██║  ██║██║██║
-// ██║     ███████╗██║  ██║██║╚██████╔╝██████╔╝██║╚██████╗
-// ╚═╝     ╚══════╝╚═╝  ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝
+%template() ClampedNonUniformConstant<double>;
+%template(clamped_nonuniform_constant) make_clamped_nonuniform_constant<double>;
 
 %template(PeriodicUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::PERIODIC, Extrapolation::PERIODIC>;
-%template() types::PeriodicUniform<double>;
-%template(periodic_uniform) factory::periodic_uniform<double>;
+%template() PeriodicUniform<double>;
+%template(periodic_uniform) make_periodic_uniform<double>;
 
 %template(PeriodicNonUniform) bspline::BSpline<double, Curve::NON_UNIFORM, BoundaryCondition::PERIODIC, Extrapolation::PERIODIC>;
-%template() types::PeriodicNonUniform<double>;
-%template(periodic_nonuniform) factory::periodic_nonuniform<double>;
+%template() PeriodicNonUniform<double>;
+%template(periodic_nonuniform) make_periodic_nonuniform<double>;
diff --git a/cmake/test_cmake_inclusion/test.cpp b/cmake/test_cmake_inclusion/test.cpp
index d0b89e5..cfdc561 100644
--- a/cmake/test_cmake_inclusion/test.cpp
+++ b/cmake/test_cmake_inclusion/test.cpp
@@ -3,9 +3,10 @@
 
 int main()
 {
-  auto bspline = bsplinex::factory::periodic_nonuniform(3, {0, 1, 2, 3, 4});
+  auto bspline = bsplinex::make_periodic_nonuniform(3, {0, 1, 2, 3, 4});
 
-  std::cout << bspline.evaluate(3.0) << std::endl;
+  constexpr double x{3.0};
+  std::cout << bspline.evaluate(x) << "\n";
 
   return 0;
 }
diff --git a/examples/ex_evaluate.cpp b/examples/ex_evaluate.cpp
index 6df5ee7..b4514db 100644
--- a/examples/ex_evaluate.cpp
+++ b/examples/ex_evaluate.cpp
@@ -10,7 +10,7 @@ int main()
   std::vector<double> const knots{0.1, 1.3, 2.2, 2.2, 4.9, 6.3, 6.3, 6.3, 13.2};
   std::vector<double> const control_points{0.1, 1.3, 2.2, 4.9, 13.2};
 
-  auto bspline = bsplinex::factory::open_nonuniform(degree, knots, control_points);
+  auto bspline = bsplinex::make_open_nonuniform(degree, knots, control_points);
 
   // evaluate the curve at some points
   std::vector<double> const eval_x{3.0, 3.4, 5.1, 6.2};
diff --git a/examples/ex_fit.cpp b/examples/ex_fit.cpp
index 17a5987..400cd6a 100644
--- a/examples/ex_fit.cpp
+++ b/examples/ex_fit.cpp
@@ -16,7 +16,7 @@ int main()
   constexpr double knots_end{12.0};
   constexpr size_t num_knots{12};
 
-  auto bspline = bsplinex::factory::periodic_uniform(degree, knots_begin, knots_end, num_knots);
+  auto bspline = bsplinex::make_periodic_uniform(degree, knots_begin, knots_end, num_knots);
 
   // fit the curve to the points
   bspline.fit(x_fit, y_fit);
diff --git a/examples/ex_interpolate.cpp b/examples/ex_interpolate.cpp
index 9660ca7..fbef186 100644
--- a/examples/ex_interpolate.cpp
+++ b/examples/ex_interpolate.cpp
@@ -16,7 +16,7 @@ int main()
 
   constexpr size_t degree{2};
 
-  auto bspline = bsplinex::factory::open_nonuniform(degree);
+  auto bspline = bsplinex::make_open_nonuniform(degree);
 
   // interpolate the curve to the points
   bspline.interpolate(x_interp, y_interp, {{cond_x, cond_y, cond_d}});
diff --git a/include/BSplineX/bspline/bspline.hpp b/include/BSplineX/bspline/bspline.hpp
index ed84c23..320bba4 100644
--- a/include/BSplineX/bspline/bspline.hpp
+++ b/include/BSplineX/bspline/bspline.hpp
@@ -286,7 +286,7 @@ class BSpline
   void interpolate(
       std::vector<T> const &x,
       std::vector<T> const &y,
-      std::vector<lsq::Condition<T>> const &additional_conditions
+      std::vector<lsq::InterpolantCondition<T>> const &additional_conditions
   )
   {
     releaseassert(x.size() == y.size(), "x and y must have the same size");
@@ -345,7 +345,8 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<decltype(BC)>::value,
+          "Unknown boundary condition, you should never get here!"
       );
     }
 
diff --git a/include/BSplineX/bspline/bspline_factory.hpp b/include/BSplineX/bspline/bspline_factory.hpp
deleted file mode 100644
index dcef298..0000000
--- a/include/BSplineX/bspline/bspline_factory.hpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef BSPLINEX_BSPLINE_BSPLINE_FACTORY_HPP
-#define BSPLINEX_BSPLINE_BSPLINE_FACTORY_HPP
-
-// BSplineX
-#include "BSplineX/bspline/bspline_factory_clamped.hpp"
-#include "BSplineX/bspline/bspline_factory_open.hpp"
-#include "BSplineX/bspline/bspline_factory_periodic.hpp"
-
-#endif
diff --git a/include/BSplineX/bspline/bspline_factory_clamped.hpp b/include/BSplineX/bspline/bspline_factory_clamped.hpp
index 6df29b8..b86a141 100644
--- a/include/BSplineX/bspline/bspline_factory_clamped.hpp
+++ b/include/BSplineX/bspline/bspline_factory_clamped.hpp
@@ -32,8 +32,9 @@ using namespace constants;
  * @return A clamped uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniform<T>
-clamped_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points)
+types::ClampedUniform<T> make_clamped_uniform(
+    size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points
+)
 {
   return types::ClampedUniform<T>{
       knots::Data<T, types::ClampedUniform<T>::curve_type>{begin, end, num_elems},
@@ -57,9 +58,11 @@ clamped_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T>
  * @return A clamped uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniform<T> clamped_uniform(size_t degree, T begin, T end, size_t num_elems)
+types::ClampedUniform<T> make_clamped_uniform(size_t degree, T begin, T end, size_t num_elems)
 {
-  return clamped_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1));
+  return make_clamped_uniform<T>(
+      degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1)
+  );
 }
 
 /**
@@ -73,12 +76,14 @@ inline types::ClampedUniform<T> clamped_uniform(size_t degree, T begin, T end, s
  * @return A clamped uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniform<T> clamped_uniform(size_t degree)
+types::ClampedUniform<T> make_clamped_uniform(size_t degree)
 {
   constexpr T begin{ZERO<T>};
   constexpr T end{ONE<T>};
   constexpr size_t num_elems{2};
-  return clamped_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1));
+  return make_clamped_uniform<T>(
+      degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1)
+  );
 }
 
 /**
@@ -98,7 +103,7 @@ inline types::ClampedUniform<T> clamped_uniform(size_t degree)
  * @return A clamped uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniformConstant<T> clamped_uniform_constant(
+types::ClampedUniformConstant<T> make_clamped_uniform_constant(
     size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points
 )
 {
@@ -124,10 +129,10 @@ inline types::ClampedUniformConstant<T> clamped_uniform_constant(
  * @return A clamped uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniformConstant<T>
-clamped_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
+types::ClampedUniformConstant<T>
+make_clamped_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
 {
-  return clamped_uniform_constant<T>(
+  return make_clamped_uniform_constant<T>(
       degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1)
   );
 }
@@ -143,12 +148,12 @@ clamped_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
  * @return A clamped uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedUniformConstant<T> clamped_uniform_constant(size_t degree)
+types::ClampedUniformConstant<T> make_clamped_uniform_constant(size_t degree)
 {
   constexpr T begin{ZERO<T>};
   constexpr T end{ONE<T>};
   constexpr size_t num_elems{2};
-  return clamped_uniform_constant<T>(
+  return make_clamped_uniform_constant<T>(
       degree, begin, end, num_elems, std::vector<T>(num_elems + degree - 1)
   );
 }
@@ -168,8 +173,9 @@ inline types::ClampedUniformConstant<T> clamped_uniform_constant(size_t degree)
  * @return A clamped non-uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniform<T>
-clamped_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points)
+types::ClampedNonUniform<T> make_clamped_nonuniform(
+    size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points
+)
 {
   return types::ClampedNonUniform<T>{
       knots::Data<T, types::ClampedNonUniform<T>::curve_type>{knots},
@@ -191,9 +197,9 @@ clamped_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> co
  * @return A clamped non-uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniform<T> clamped_nonuniform(size_t degree, std::vector<T> const &knots)
+types::ClampedNonUniform<T> make_clamped_nonuniform(size_t degree, std::vector<T> const &knots)
 {
-  return clamped_nonuniform<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
+  return make_clamped_nonuniform<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
 }
 
 /**
@@ -207,10 +213,10 @@ inline types::ClampedNonUniform<T> clamped_nonuniform(size_t degree, std::vector
  * @return A clamped non-uniform BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniform<T> clamped_nonuniform(size_t degree)
+types::ClampedNonUniform<T> make_clamped_nonuniform(size_t degree)
 {
   std::vector<T> const knots(2);
-  return clamped_nonuniform<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
+  return make_clamped_nonuniform<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
 }
 
 /**
@@ -228,7 +234,7 @@ inline types::ClampedNonUniform<T> clamped_nonuniform(size_t degree)
  * @return A clamped non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniformConstant<T> clamped_nonuniform_constant(
+types::ClampedNonUniformConstant<T> make_clamped_nonuniform_constant(
     size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points
 )
 {
@@ -252,10 +258,12 @@ inline types::ClampedNonUniformConstant<T> clamped_nonuniform_constant(
  * @return A clamped non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniformConstant<T>
-clamped_nonuniform_constant(size_t degree, std::vector<T> const &knots)
+types::ClampedNonUniformConstant<T>
+make_clamped_nonuniform_constant(size_t degree, std::vector<T> const &knots)
 {
-  return clamped_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
+  return make_clamped_nonuniform_constant<T>(
+      degree, knots, std::vector<T>(knots.size() + degree - 1)
+  );
 }
 
 /**
@@ -269,10 +277,12 @@ clamped_nonuniform_constant(size_t degree, std::vector<T> const &knots)
  * @return A clamped non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::ClampedNonUniformConstant<T> clamped_nonuniform_constant(size_t degree)
+types::ClampedNonUniformConstant<T> make_clamped_nonuniform_constant(size_t degree)
 {
   std::vector<T> const knots(2);
-  return clamped_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() + degree - 1));
+  return make_clamped_nonuniform_constant<T>(
+      degree, knots, std::vector<T>(knots.size() + degree - 1)
+  );
 }
 
 } // namespace bsplinex::factory
diff --git a/include/BSplineX/bspline/bspline_factory_open.hpp b/include/BSplineX/bspline/bspline_factory_open.hpp
index 6d675a5..54e2f42 100644
--- a/include/BSplineX/bspline/bspline_factory_open.hpp
+++ b/include/BSplineX/bspline/bspline_factory_open.hpp
@@ -33,8 +33,9 @@ using namespace constants;
  * @return A open uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenUniform<T>
-open_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points)
+types::OpenUniform<T> make_open_uniform(
+    size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points
+)
 {
   return types::OpenUniform<T>{
       knots::Data<T, types::OpenUniform<T>::curve_type>{begin, end, num_elems},
@@ -59,9 +60,11 @@ open_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T> con
  * @return A open uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenUniform<T> open_uniform(size_t degree, T begin, T end, size_t num_elems)
+types::OpenUniform<T> make_open_uniform(size_t degree, T begin, T end, size_t num_elems)
 {
-  return open_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1));
+  return make_open_uniform<T>(
+      degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1)
+  );
 }
 
 /**
@@ -75,12 +78,14 @@ inline types::OpenUniform<T> open_uniform(size_t degree, T begin, T end, size_t
  * @return A open uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenUniform<T> open_uniform(size_t degree)
+types::OpenUniform<T> make_open_uniform(size_t degree)
 {
   constexpr T begin{ZERO<T>};
   constexpr T end{ONE<T>};
-  size_t const num_elems{1 + 2 * degree};
-  return open_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1));
+  size_t const num_elems{1 + (2 * degree)};
+  return make_open_uniform<T>(
+      degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1)
+  );
 }
 
 /**
@@ -101,7 +106,7 @@ inline types::OpenUniform<T> open_uniform(size_t degree)
  * @return A open uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenUniformConstant<T> open_uniform_constant(
+types::OpenUniformConstant<T> make_open_uniform_constant(
     size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points
 )
 {
@@ -128,10 +133,10 @@ inline types::OpenUniformConstant<T> open_uniform_constant(
  * @return A open uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenUniformConstant<T>
-open_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
+types::OpenUniformConstant<T>
+make_open_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
 {
-  return open_uniform_constant<T>(
+  return make_open_uniform_constant<T>(
       degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1)
   );
 }
@@ -147,12 +152,12 @@ open_uniform_constant(size_t degree, T begin, T end, size_t num_elems)
  * @return A open uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenUniformConstant<T> open_uniform_constant(size_t degree)
+types::OpenUniformConstant<T> make_open_uniform_constant(size_t degree)
 {
   constexpr T begin{ZERO<T>};
   constexpr T end{ONE<T>};
-  size_t const num_elems{1 + 2 * degree};
-  return open_uniform_constant<T>(
+  size_t const num_elems{1 + (2 * degree)};
+  return make_open_uniform_constant<T>(
       degree, begin, end, num_elems, std::vector<T>(num_elems - degree - 1)
   );
 }
@@ -172,8 +177,8 @@ inline types::OpenUniformConstant<T> open_uniform_constant(size_t degree)
  * @return A open non-uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniform<T>
-open_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points)
+types::OpenNonUniform<T>
+make_open_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points)
 {
   return types::OpenNonUniform<T>{
       knots::Data<T, types::OpenNonUniform<T>::curve_type>{knots},
@@ -195,9 +200,9 @@ open_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> const
  * @return A open non-uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniform<T> open_nonuniform(size_t degree, std::vector<T> const &knots)
+types::OpenNonUniform<T> make_open_nonuniform(size_t degree, std::vector<T> const &knots)
 {
-  return open_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
+  return make_open_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
 }
 
 /**
@@ -211,10 +216,10 @@ inline types::OpenNonUniform<T> open_nonuniform(size_t degree, std::vector<T> co
  * @return A open non-uniform BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniform<T> open_nonuniform(size_t degree)
+types::OpenNonUniform<T> make_open_nonuniform(size_t degree)
 {
-  std::vector<T> const knots(1 + 2 * degree);
-  return open_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
+  std::vector<T> const knots(1 + (2 * degree));
+  return make_open_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
 }
 
 /**
@@ -232,7 +237,7 @@ inline types::OpenNonUniform<T> open_nonuniform(size_t degree)
  * @return A open non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniformConstant<T> open_nonuniform_constant(
+types::OpenNonUniformConstant<T> make_open_nonuniform_constant(
     size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points
 )
 {
@@ -256,10 +261,10 @@ inline types::OpenNonUniformConstant<T> open_nonuniform_constant(
  * @return A open non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniformConstant<T>
-open_nonuniform_constant(size_t degree, std::vector<T> const &knots)
+types::OpenNonUniformConstant<T>
+make_open_nonuniform_constant(size_t degree, std::vector<T> const &knots)
 {
-  return open_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
+  return make_open_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
 }
 
 /**
@@ -273,10 +278,10 @@ open_nonuniform_constant(size_t degree, std::vector<T> const &knots)
  * @return A open non-uniform constant BSpline.
  */
 template <typename T = double>
-inline types::OpenNonUniformConstant<T> open_nonuniform_constant(size_t degree)
+types::OpenNonUniformConstant<T> make_open_nonuniform_constant(size_t degree)
 {
-  std::vector<T> const knots(1 + 2 * degree);
-  return open_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
+  std::vector<T> const knots(1 + (2 * degree));
+  return make_open_nonuniform_constant<T>(degree, knots, std::vector<T>(knots.size() - degree - 1));
 }
 
 } // namespace bsplinex::factory
diff --git a/include/BSplineX/bspline/bspline_factory_periodic.hpp b/include/BSplineX/bspline/bspline_factory_periodic.hpp
index e7e0c1e..827a9b2 100644
--- a/include/BSplineX/bspline/bspline_factory_periodic.hpp
+++ b/include/BSplineX/bspline/bspline_factory_periodic.hpp
@@ -33,8 +33,9 @@ using namespace constants;
  * @return A periodic uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicUniform<T>
-periodic_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points)
+types::PeriodicUniform<T> make_periodic_uniform(
+    size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points
+)
 {
   return types::PeriodicUniform<T>{
       knots::Data<T, types::PeriodicUniform<T>::curve_type>{begin, end, num_elems},
@@ -58,9 +59,9 @@ periodic_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T>
  * @return A periodic uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicUniform<T> periodic_uniform(size_t degree, T begin, T end, size_t num_elems)
+types::PeriodicUniform<T> make_periodic_uniform(size_t degree, T begin, T end, size_t num_elems)
 {
-  return periodic_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - 1));
+  return make_periodic_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - 1));
 }
 
 /**
@@ -74,12 +75,12 @@ inline types::PeriodicUniform<T> periodic_uniform(size_t degree, T begin, T end,
  * @return A periodic uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicUniform<T> periodic_uniform(size_t degree)
+types::PeriodicUniform<T> make_periodic_uniform(size_t degree)
 {
   constexpr T begin{ZERO<T>};
   constexpr T end{ONE<T>};
   size_t const num_elems{2 * degree};
-  return periodic_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - 1));
+  return make_periodic_uniform<T>(degree, begin, end, num_elems, std::vector<T>(num_elems - 1));
 }
 
 /**
@@ -98,8 +99,9 @@ inline types::PeriodicUniform<T> periodic_uniform(size_t degree)
  * @return A periodic non-uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicNonUniform<T>
-periodic_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points)
+types::PeriodicNonUniform<T> make_periodic_nonuniform(
+    size_t degree, std::vector<T> const &knots, std::vector<T> const &ctrl_points
+)
 {
   return types::PeriodicNonUniform<T>{
       knots::Data<T, types::PeriodicNonUniform<T>::curve_type>{knots},
@@ -121,9 +123,9 @@ periodic_nonuniform(size_t degree, std::vector<T> const &knots, std::vector<T> c
  * @return A periodic non-uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicNonUniform<T> periodic_nonuniform(size_t degree, std::vector<T> const &knots)
+types::PeriodicNonUniform<T> make_periodic_nonuniform(size_t degree, std::vector<T> const &knots)
 {
-  return periodic_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - 1));
+  return make_periodic_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - 1));
 }
 
 /**
@@ -137,10 +139,10 @@ inline types::PeriodicNonUniform<T> periodic_nonuniform(size_t degree, std::vect
  * @return A periodic non-uniform BSpline.
  */
 template <typename T = double>
-inline types::PeriodicNonUniform<T> periodic_nonuniform(size_t degree)
+types::PeriodicNonUniform<T> make_periodic_nonuniform(size_t degree)
 {
   std::vector<T> const knots(2 * degree);
-  return periodic_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - 1));
+  return make_periodic_nonuniform<T>(degree, knots, std::vector<T>(knots.size() - 1));
 }
 
 } // namespace bsplinex::factory
diff --git a/include/BSplineX/bspline/bspline_lsq.hpp b/include/BSplineX/bspline/bspline_lsq.hpp
index 724f926..647c4a3 100644
--- a/include/BSplineX/bspline/bspline_lsq.hpp
+++ b/include/BSplineX/bspline/bspline_lsq.hpp
@@ -159,28 +159,28 @@ class LSQMatrix<T, Eigen::SparseMatrix<T>>
 };
 
 template <typename T>
-struct Condition
+struct InterpolantCondition
 {
   T x_value;
   T y_value;
   size_t derivative_order;
 
-  Condition(T x_value, T y_value, size_t derivative_order)
+  InterpolantCondition(T x_value, T y_value, size_t derivative_order)
       : x_value{x_value}, y_value{y_value}, derivative_order{derivative_order}
   {
   }
 };
 
 template <typename T, class Iter>
-std::vector<Condition<T>> create_sorted_conditions(
+std::vector<InterpolantCondition<T>> create_sorted_conditions(
     views::ArrayView<Iter> x,
     views::ArrayView<Iter> y,
-    std::vector<Condition<T>> const &additional_conditions
+    std::vector<InterpolantCondition<T>> const &additional_conditions
 )
 {
   debugassert(x.size() == y.size(), "x and y must have the same size.");
 
-  std::vector<Condition<T>> conditions;
+  std::vector<InterpolantCondition<T>> conditions;
   conditions.reserve(x.size() + additional_conditions.size());
 
   for (size_t k{0}; k < x.size(); k++)
@@ -192,7 +192,8 @@ std::vector<Condition<T>> create_sorted_conditions(
   std::sort(
       conditions.begin(),
       conditions.end(),
-      [&](Condition<T> const &a, Condition<T> const &b) { return a.x_value < b.x_value; }
+      [&](InterpolantCondition<T> const &a, InterpolantCondition<T> const &b)
+      { return a.x_value < b.x_value; }
   );
 
   return conditions;
@@ -206,7 +207,7 @@ void fill(
     std::function<size_t(T, size_t, std::vector<T> &)> nnz_basis,
     views::ArrayView<Iter> const &x,
     views::ArrayView<Iter> const &y,
-    std::vector<Condition<T>> const &additional_conditions
+    std::vector<InterpolantCondition<T>> const &additional_conditions
 )
 {
   debugassert(x.size() == y.size(), "x and y must have the same size.");
@@ -218,12 +219,13 @@ void fill(
   size_t const num_rows = A.num_rows();
   size_t const num_cols = A.num_cols();
 
-  std::vector<Condition<T>> conditions = create_sorted_conditions(x, y, additional_conditions);
+  std::vector<InterpolantCondition<T>> conditions =
+      create_sorted_conditions(x, y, additional_conditions);
 
   std::vector<T> nnz(degree + 1, ZERO<T>);
   for (size_t i{0}; i < num_rows; i++)
   {
-    Condition<T> const &condition = conditions.at(i);
+    InterpolantCondition<T> const &condition = conditions.at(i);
 
     size_t const index = nnz_basis(condition.x_value, condition.derivative_order, nnz);
     for (size_t j{0}; j <= degree; j++)
@@ -254,7 +256,7 @@ lsq(size_t const degree,
     std::function<size_t(T, size_t, std::vector<T> &)> nnz_basis,
     views::ArrayView<Iter> const &x,
     views::ArrayView<Iter> const &y,
-    std::vector<Condition<T>> const &additional_conditions)
+    std::vector<InterpolantCondition<T>> const &additional_conditions)
 {
   debugassert(x.size() == y.size(), "x and y must have the same size.");
 
diff --git a/include/BSplineX/bsplinex.hpp b/include/BSplineX/bsplinex.hpp
index 60e87fa..e182235 100644
--- a/include/BSplineX/bsplinex.hpp
+++ b/include/BSplineX/bsplinex.hpp
@@ -1,8 +1,43 @@
 #ifndef BSPLINEX_BSPLINEX_HPP
 #define BSPLINEX_BSPLINEX_HPP
 
-#include "BSplineX/bspline/bspline.hpp"
-#include "BSplineX/bspline/bspline_factory.hpp"
+#include "BSplineX/bspline/bspline_factory_clamped.hpp"
+#include "BSplineX/bspline/bspline_factory_open.hpp"
+#include "BSplineX/bspline/bspline_factory_periodic.hpp"
+#include "BSplineX/bspline/bspline_lsq.hpp"
 #include "BSplineX/bspline/bspline_types.hpp"
 
+namespace bsplinex
+{
+
+using types::OpenNonUniform;
+using types::OpenNonUniformConstant;
+using types::OpenUniform;
+using types::OpenUniformConstant;
+
+using factory::make_open_nonuniform;
+using factory::make_open_nonuniform_constant;
+using factory::make_open_uniform;
+using factory::make_open_uniform_constant;
+
+using types::ClampedNonUniform;
+using types::ClampedNonUniformConstant;
+using types::ClampedUniform;
+using types::ClampedUniformConstant;
+
+using factory::make_clamped_nonuniform;
+using factory::make_clamped_nonuniform_constant;
+using factory::make_clamped_uniform;
+using factory::make_clamped_uniform_constant;
+
+using types::PeriodicNonUniform;
+using types::PeriodicUniform;
+
+using factory::make_periodic_nonuniform;
+using factory::make_periodic_uniform;
+
+using lsq::InterpolantCondition;
+
+} // namespace bsplinex
+
 #endif
diff --git a/include/BSplineX/defines.hpp b/include/BSplineX/defines.hpp
index 613c3e8..4aaaf9c 100644
--- a/include/BSplineX/defines.hpp
+++ b/include/BSplineX/defines.hpp
@@ -29,7 +29,7 @@
 
 // some compilers complain about static_assert(false, ...)
 // Use a false_type dependent from a template argument to silence them.
-template <auto>
+template <typename T>
 struct dependent_false : std::false_type
 {
 };
diff --git a/tests/bspline/test_bspline_with_data.cpp b/tests/bspline/test_bspline_with_data.cpp
index fb542b0..9f05f58 100644
--- a/tests/bspline/test_bspline_with_data.cpp
+++ b/tests/bspline/test_bspline_with_data.cpp
@@ -375,7 +375,7 @@ TEMPLATE_TEST_CASE("BSpline", "[bspline][template][product]", BSPLINE_TEST_TYPES
                                                    .get<std::pair<
                                                        std::vector<std::pair<size_t, real_t>>,
                                                        std::vector<std::pair<size_t, real_t>>>>();
-        std::vector<lsq::Condition<real_t>> additional_conditions{};
+        std::vector<lsq::InterpolantCondition<real_t>> additional_conditions{};
         additional_conditions.reserve(conds_left.size() + conds_right.size());
         for (auto const &[derivative_order, value] : conds_left)
         {


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors header inclusions and updates the public interface by removing unused header files and deprecating the alias syntax, resulting in a cleaner, more consistent API.  
- Removed unused header inclusion from bsplinex.hpp  
- Refactored inline function definitions and removed the internal factory namespace  
- Updated examples, tests, and README to reflect the new interface

### Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.

<details>
<summary>Show a summary per file</summary>

| File                                               | Description                                  |
| -------------------------------------------------- | -------------------------------------------- |
| include/BSplineX/bsplinex.hpp                      | Updated header inclusions and using directives |
| include/BSplineX/bspline/bspline_factory_*.hpp     | Removed inline specifiers from function templates |
| include/BSplineX/bspline/bspline_factory.hpp       | Removed as it became unused after refactoring |
| examples/ex_interpolate.cpp, ex_fit.cpp, ex_evaluate.cpp | Updated function calls to use the new namespace |
| cmake/test_cmake_inclusion/test.cpp                | Adjusted namespace calls and minor formatting changes |
| README.md                                          | Reformatted text and updated installation instructions |
</details>


<details>
<summary>Files not reviewed (1)</summary>

* **bindings/BSplineX.i**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**README.md:50**
* Typo detected: 'find_pacakge' should be corrected to 'find_package'.
```
If you already have `BSplineX` somewhere on your system, you can use `find_pacakge` directly.
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T15:22:44Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors how header files are included and functions are exposed in BSplineX, removing an unnecessary header and standardizing the naming of factory functions. Key changes include:
- Removal of the generic bspline_factory.hpp header in favor of more targeted factory headers.
- Renaming factory function calls from the old naming (e.g. open_nonuniform, periodic_uniform) to a clearer "make_" prefix.
- Updating example usages and README documentation to reflect the new function naming and include structure.

### Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                                            | Description                                                    |
|-------------------------------------------------|----------------------------------------------------------------|
| include/BSplineX/bsplinex.hpp                   | Updated includes and using declarations for factory functions. |
| bspline_factory_periodic.hpp, open.hpp, clamped.hpp | Renamed factory functions to use the "make_" prefix consistently. |
| bspline_factory.hpp                             | Removed obsolete header file.                                  |
| examples/*.cpp                                  | Updated example usages to call the new functions.              |
| cmake/test_cmake_inclusion/test.cpp             | Removed the factory namespace usage on periodic functions.     |
| README.md                                       | Adjusted documentation layout and retained minor text changes.   |
</details>


<details>
<summary>Files not reviewed (1)</summary>

* **bindings/BSplineX.i**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**cmake/test_cmake_inclusion/test.cpp:6**
* The function call still uses 'periodic_nonuniform' instead of the updated 'make_periodic_nonuniform'. Consider updating the call to align with the new naming convention.
```
auto bspline = bsplinex::periodic_nonuniform(3, {0, 1, 2, 3, 4});
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-20T14:42:08Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-20T20:01:02Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:12:30Z
user: login: SebastianoTaddei
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:18:38Z
user: login: SebastianoTaddei
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:19:22Z
user: login: SebastianoTaddei
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:20:33Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:32:37Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:44:09Z
user: login: SebastianoTaddei
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T13:46:16Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T14:00:15Z
user: login: masinag
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T14:02:02Z
user: login: SebastianoTaddei
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-21T14:03:00Z
user: login: masinag
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-21T14:05:10Z
user: login: masinag
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-21T14:06:36Z

Review comments:
diff_hunk: @@ -43,7 +47,8 @@ fetchcontent_makeavailable(BSplineX)
 target_link_libraries(your_target PRIVATE BSplineX::BSplineX)
 ```
 
-If you already have `BSplineX` somewhere on your system, you can use `find_pacakge` directly.
+If you already have `BSplineX` somewhere on your system, you can use
+`find_pacakge` directly.
path: README.md
user: login: Copilot
body: The term 'find_pacakge' appears to be misspelled; it should be 'find_package'.
```suggestion
`find_package` directly.
```
created_at: 2025-04-20T14:42:07Z
author_association: CONTRIBUTOR
path: bindings/BSplineX.i
user: login: masinag
body: Here we have to change the functions and the types in the template instantiations for the bindings too.
created_at: 2025-04-20T19:51:17Z
author_association: COLLABORATOR
path: bindings/BSplineX.i
user: login: masinag
body: Moreover, I noticed that the bindings don't compile because (my version of) SWIG doesn't support  `template<auto>` used in `defines.hpp`. I think we can change it to `template <typename T>`
created_at: 2025-04-20T19:53:37Z
author_association: COLLABORATOR
diff_hunk: @@ -42,63 +40,42 @@ using namespace bsplinex;
 %template(Condition) lsq::Condition<double>;
 %template() std::vector<lsq::Condition<double>>;
 
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
-
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
 %template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template(open_uniform) factory::make_open_uniform<double>;
path: bindings/BSplineX.i
user: login: masinag
body: Here and elsewere I would use
```swig
%template() bsplinex::OpenUniform<double>;
%template(open_uniform) bsplinex::make_open_uniform<double>;
```
or even without `bsplinex::` since we are already `using namespace bsplines;`.
created_at: 2025-04-21T12:55:53Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: masinag
body: My understanding here is that we want a `false_type` dependent from `BC` because the `if constexpr` is on the value of `BC`.
Probably this works anyway, but using `BC` seems more semantically correct to me.
created_at: 2025-04-21T12:58:43Z
author_association: COLLABORATOR
diff_hunk: @@ -42,63 +40,42 @@ using namespace bsplinex;
 %template(Condition) lsq::Condition<double>;
 %template() std::vector<lsq::Condition<double>>;
 
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
-
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
 %template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template(open_uniform) factory::make_open_uniform<double>;
path: bindings/BSplineX.i
user: login: masinag
body: Also, probably we can just include the header "BSplinex/bsplinex.hpp" (not sure)
created_at: 2025-04-21T13:03:37Z
author_association: COLLABORATOR
path: include/BSplineX/bsplinex.hpp
user: login: masinag
body: Should we add
```cpp
using bsplinex::lsq::Condition;
```
? If so, we should consider renaming it maybe.

created_at: 2025-04-21T13:04:20Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: SebastianoTaddei
body: Unfortunately we cannot use `BC` directly as that gives an error like `template argument must be a type`. However, if you prefer we can use `decltype(BC)` as that works.
created_at: 2025-04-21T13:18:38Z
author_association: COLLABORATOR
diff_hunk: @@ -42,63 +40,42 @@ using namespace bsplinex;
 %template(Condition) lsq::Condition<double>;
 %template() std::vector<lsq::Condition<double>>;
 
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
-
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
 %template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template(open_uniform) factory::make_open_uniform<double>;
path: bindings/BSplineX.i
user: login: SebastianoTaddei
body: You are right, implementing now (I will see if we can reduce the includes).
created_at: 2025-04-21T13:19:22Z
author_association: COLLABORATOR
path: include/BSplineX/bsplinex.hpp
user: login: SebastianoTaddei
body: That is indeed part of the public API, I will add it and consider an alternative name
created_at: 2025-04-21T13:20:33Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: masinag
body: Ah I see, we can just use
```suggestion
          dependent_false<BoundaryCondition>::value, "Unknown boundary condition, you should never get here!"
```
created_at: 2025-04-21T13:32:37Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: masinag
body: Ok, apparently this doesn't work :smile: 
I think it has to depend on the actual value of `BC` to work. Not sure that `decltype(BC)` works, but we can try.
created_at: 2025-04-21T13:44:09Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: SebastianoTaddei
body: Let's see, otherwise we go back to <T> unfortunately
created_at: 2025-04-21T13:46:16Z
author_association: COLLABORATOR
diff_hunk: @@ -341,7 +341,7 @@ class BSpline
     else
     {
       static_assert(
-          dependent_false<BC>::value, "Unknown boundary condition, you should never get here!"
+          dependent_false<T>::value, "Unknown boundary condition, you should never get here!"
path: include/BSplineX/bspline/bspline.hpp
user: login: masinag
body: It does :rocket: 
created_at: 2025-04-21T14:00:15Z
author_association: COLLABORATOR
diff_hunk: @@ -42,63 +40,42 @@ using namespace bsplinex;
 %template(Condition) lsq::Condition<double>;
 %template() std::vector<lsq::Condition<double>>;
 
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
-
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
 %template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template(open_uniform) factory::make_open_uniform<double>;
path: bindings/BSplineX.i
user: login: masinag
body: Have you checked if we can remove some of the includes?
created_at: 2025-04-21T14:02:02Z
author_association: COLLABORATOR
diff_hunk: @@ -42,63 +40,42 @@ using namespace bsplinex;
 %template(Condition) lsq::Condition<double>;
 %template() std::vector<lsq::Condition<double>>;
 
-//  ██████╗ ██████╗ ███████╗███╗   ██╗
-// ██╔═══██╗██╔══██╗██╔════╝████╗  ██║
-// ██║   ██║██████╔╝█████╗  ██╔██╗ ██║
-// ██║   ██║██╔═══╝ ██╔══╝  ██║╚██╗██║
-// ╚██████╔╝██║     ███████╗██║ ╚████║
-//  ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═══╝
-
 %template(OpenUniform) bspline::BSpline<double, Curve::UNIFORM, BoundaryCondition::OPEN, Extrapolation::NONE>;
 %template() types::OpenUniform<double>;
-%template(open_uniform) factory::open_uniform<double>;
+%template(open_uniform) factory::make_open_uniform<double>;
path: bindings/BSplineX.i
user: login: SebastianoTaddei
body: Yup, and it breaks every time
created_at: 2025-04-21T14:03:00Z
author_association: COLLABORATOR

PR comments:
user: login: masinag
created_at: 2025-04-19T15:37:29Z
body: I think we have some options:
1. leave it as it is now
2. rename factory methods like `factory::open_uniform` to `factory::make_open_uniform`.
3. Use the following syntax, keeping in mind that [this is not really a function alias, even though it is very likely to be so with compiler optimizations ](https://stackoverflow.com/a/49819511).
```cpp
template <typename T>
auto constexpr make_open_uniform = factory::open_uniform<T>;
```



author_association: COLLABORATOR
user: login: masinag
created_at: 2025-04-19T15:39:35Z
body: I would prefer options 2 or 3 to avoid confusion between the type (class name) and the factory function.
author_association: COLLABORATOR
user: login: SebastianoTaddei
created_at: 2025-04-19T16:09:03Z
body: I would go with option 2 as unfortunately option 3 (my preferred method) does not work with overload (not tested but in the answer it states as much). If you can test to see if option 3 does work with overloads, if it does then we are golden, otherwise I think option 2 works best as it allows us to not have all the clang-tidy warnings
author_association: COLLABORATOR
user: login: masinag
created_at: 2025-04-19T18:14:43Z
body: Oh I missed that part, I confirm it doesn't work with overloaded functions.

Another option would be to wrap the functions like
```cpp
template <typename T>
inline OpenUniform<T> 
make_open_uniform(size_t degree, T begin, T end, size_t num_elems, std::vector<T> const &ctrl_points) {
    return factory::open_uniform<T>(degree, begin, end, num_elems, ctrl_points);
}
```
but probably option 2 is still the cleanest.
author_association: COLLABORATOR
user: login: SebastianoTaddei
created_at: 2025-04-19T20:56:18Z
body: Yes exactly but that is error prone and if the user goes to the function definition it won't immediately go/understand where the commented function is. I'll update with option 2 tomorrow
author_association: COLLABORATOR
user: login: SebastianoTaddei
created_at: 2025-04-21T12:56:30Z
body: Given that I pushed broken bindings, I have added an action that tests their creation to make sure that they at least compile
author_association: COLLABORATOR