bezier
bezier copied to clipboard
Adding idiomatic C++ equivalents for each subroutine in `helpers.h`.
An example that hits on all parts of the xtensor
/ xarray
API we'll need:
#include "xtensor/xadapt.hpp"
#include "xtensor/xfixed.hpp"
#include "xtensor/xio.hpp"
#include "xtensor/xtensor.hpp"
#include <iostream>
int main(int argc, char* argv[])
{
// H/T: https://xtensor.readthedocs.io/en/latest/container.html
xt::xtensor<double, 2, xt::layout_type::column_major> arr1 {
{ 1.0, 2.0, 3.0 },
{ 4.0, 5.0, 6.0 },
{ 7.0, 8.0, 9.0 },
};
double* p1 = arr1.data();
for (std::size_t i = 0; i < arr1.size(); ++i) {
std::cout << p1[i] << " ";
}
std::cout << std::endl;
std::cout << "arr1.dimension(): " << arr1.dimension() << std::endl;
std::cout << "arr1.shape(0): " << arr1.shape(0) << std::endl;
std::cout << "arr1.shape(1): " << arr1.shape(1) << std::endl;
std::cout << "arr1.shape(2): " << arr1.shape(2) << std::endl;
std::cout << "arr1.shape(): " << xt::adapt(arr1.shape()) << std::endl;
std::cout << "========================================" << std::endl;
xt::xtensor<double, 2, xt::layout_type::row_major> arr2 {
{ 1.0, 2.0, 3.0 },
{ 4.0, 5.0, 6.0 },
{ 7.0, 8.0, 9.0 },
};
double* p2 = arr2.data();
for (std::size_t i = 0; i < arr2.size(); ++i) {
std::cout << p2[i] << " ";
}
std::cout << std::endl;
std::cout << "arr2.dimension(): " << arr2.dimension() << std::endl;
std::cout << "arr2.shape(0): " << arr2.shape(0) << std::endl;
std::cout << "arr2.shape(1): " << arr2.shape(1) << std::endl;
std::cout << "========================================" << std::endl;
xt::xtensor_fixed<double, xt::xshape<3, 2>, xt::layout_type::column_major>
arr3 {
{ 1.0, 2.0 },
{ 4.0, 5.0 },
{ 7.0, 8.0 },
};
double* p3 = arr3.data();
for (std::size_t i = 0; i < arr3.size(); ++i) {
std::cout << p3[i] << " ";
}
std::cout << std::endl;
std::cout << "arr3.dimension(): " << arr3.dimension() << std::endl;
std::cout << "arr3.shape(0): " << arr3.shape(0) << std::endl;
std::cout << "arr3.shape(1): " << arr3.shape(1) << std::endl;
std::cout << "========================================" << std::endl;
xt::xarray<double, xt::layout_type::column_major> arr4 {
{ 1.0, 2.0, 3.0 },
{ 4.0, 5.0, 6.0 },
{ 7.0, 8.0, 9.0 },
};
double* p4 = arr4.data();
for (std::size_t i = 0; i < arr4.size(); ++i) {
std::cout << p4[i] << " ";
}
std::cout << std::endl;
std::cout << "arr4.dimension(): " << arr4.dimension() << std::endl;
std::cout << "arr4.shape(): " << xt::adapt(arr4.shape()) << std::endl;
for (std::size_t i = 0; i < arr4.dimension(); ++i) {
std::cout << "arr4.shape(" << i << "): " << arr4.shape(i) << std::endl;
}
return 0;
}
Some things to take away from this:
- Any of
xarray
,xtensor
,xtensor_fixed
will work (though we should preferxtensor_fixed
) -
arr.shape(N) == 1
whenN
is too large (this avoid runtime "problems") - Fortran order need be specified in the type as
xt::layout_type::column_major
- We can get
rows = arr.shape(0)
andcols = arr.shape(1)
and if we want to do runtime type assertions (e.g. in the presence ofxarray
where number of dimensions isn't known at compile time) we can checkarr.dimension()
- A raw pointer exists are
arr.data()
(like avector<double>
) andarr.size()
returns the number of elements in this raw pointer (though we'll likely not need it to invokelibbezier
)
Possibly relevant for performance when building xtensor
: https://xtensor.readthedocs.io/en/latest/build-options.html#external-dependencies
-
XTENSOR_USE_XSIMD
-
XTENSOR_USE_TBB
-
XTENSOR_DISABLE_EXCEPTIONS
-
XTENSOR_USE_OPENMP
Another thing worth checking / requiring (if we allow generic types, e.g. views) is that the raw .data()
pointers are contiguous.