Skip to content

Interfacing with C arrays and other external data

Roman edited this page Jun 11, 2020 · 6 revisions

Interfacing with C arrays and other external data

Interfacing with C arrays

You can wrap C arrays as Fastor tensors and operate on them just like you would on Fastor's tensors without making any copies, using the Fastor::TensorMap feature. For instance

double c_array[4] = {1,2,3,4};
TensorMap<double,4> tn1(c_array);

// You can now operate on tn1. This will also modify c_array
tn1 += 1;

// print c_array values now using println function
println<double,4>(c_array);

will give you

2 3 4 5

Interfacing with Eigen matrices and Eigen tensors

  1. If your Eigen matrices or Eigen tensors are row-major you can wrap them directly using Fastor::TensorMap and operate on them just like any other Fastor tensor.
Eigen::TensorFixedSize<double,Eigen::Sizes<2,3,4>, Eigen::RowMajor> ea;
std::iota(ea.data(),ea.data()+24,1.);
std::cout << "Eigen row-major tensor (ea)\n" << ea << std::endl;
TensorMap<double,2,3,4> fa(ea.data());
fa += 2;
std::cout << "Eigen row-major tensor modified by Fastor (ea+2) \n" << ea << std::endl;
Eigen row-major tensor (ea)
 1  2  3  4  5  6  7  8  9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24

Eigen row-major tensor modified by Fastor (ea+2)
 3  4  5  6  7  8  9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26

Note that Fastor::TensorMap just wraps around existing data and does not make any copies so changing fa in this case changes ea. You can use Fastor::TensorMap exactly like Fastor::Tensor. It has almost all of the functionality of a Fastor::Tensor.

  1. If your Eigen matrices/tensors are in column-major layout (Eigen's default), you have to construct a Fastor Tensor by specifying the layout to the constructor of the Tensor, for instance with Eigen matrices say
Eigen::Matrix<double,3,4> ea;
std::iota(ea.data(),ea.data()+12,1.);
std::cout << ea << std::endl;
 1  4  7 10
 2  5  8 11
 3  6  9 12

Which is of course column-major. Now, to construct a Fastor Tensor you do

Tensor<double,3,4> fa(ea.data(),Fastor::ColumnMajor);

You can perform computation on fa now

fa += 2;
std::cout << fa << std::endl;
[ 3,  6,  9, 12]
[ 4,  7, 10, 13]
[ 5,  8, 11, 14]

To change back to Eigen matrix, it is necessary to convert back to row-major first and then use Eigen::Map

Tensor<double,3,4> fb = torowmajor(fa);
Eigen::Map<Eigen::Matrix<double,3,4>> eb(fb.data());
std::cout << eb << std::endl;
 3  6  9 12
 4  7 10 13
 5  8 11 14

Otherwise Eigen will assume contiguity is in other axis and will swap the data for you. Note that all of these matrices are copies as Fastor internally treats everything as row-major, so changing fa will not change ea until you convert them back to Eigen matrices. This copy is really cheap though.

  1. There is also a free function tocolumnmajor that you can use after constructing a Fastor::Tensor
Tensor<double,3,4> fa(ea.data());
Tensor<double,3,4> fb = tocolumnmajor(fa);

Certainly you can wrap Eigen::Tensors in the same fashion.