Arrays
Important
#include "higra/structure/array.hpp
The preferred way to represent homogeneous tabular data in higra is through the use of xtensor multi-dimentional arrays. Xtensor aims at providing numpy like arrays in C++: take a look at the numpy->xtensor cheat sheet .
Higra defines some commodity types (aliases) that map to particular xtensor types. There are 3 categories of types:
points, ie. 1 dimensional arrays of fixed size: they do not require heap allocated memory and benefit from a lot of compile time optimization;
fixed dimension arrays of variable size: they require heap allocated memory but, thanks to their fixed dimension, they also benefit from compile time optimization;
variable dimension arrays of variable size: they require heap allocated memory.
Therefore, using the most specific type compatible with your needs will provide better performances.
Typename |
Template |
Description |
Base type |
---|---|---|---|
|
|
An n dimensional point |
|
|
A two dimentional point with real coordinates ( |
|
|
|
A two dimentional point with integral coordinates ( |
|
|
|
A three dimentional point with real coordinates ( |
|
|
|
A three dimentional point with integral coordinates ( |
|
|
|
A four dimentional point with real coordinates ( |
|
|
|
A four dimentional point with integral coordinates ( |
|
|
|
|
A one dimentional array |
|
|
|
A two dimentional array |
|
|
|
A three dimentional array |
|
|
|
A four dimentional array |
|
|
|
A n-dimentional array (n being defined at runtime) |
|
Quick start
Creating arrays
From scratch:
1// explicit initialization
2array_2d<int> a1 {{1, 2, 3},
3 {4, 5, 6}};
4
5// empty (non initialized) array of given shape
6array_2d<int> a2 = array_1d<int>::from_shape({2, 3});
7
8// array of given shapes initialized with given value
9array_2d<int> a3({2, 3}, 5);
10
11// array of given shapes initialized with 0
12array_2d<int> a4 = xt::zeros<int>({2, 3});
13
14// array of given shapes initialized with 1
15array_2d<int> a5 = xt::ones<int>({2, 3});
From an existing array:
1array_2d<int> a1 {{1, 2, 3},
2 {4, 5, 6}};
3
4// same shape and value type, non-initialized
5auto a2 = xt::empty_like(a1);
6
7// same shape and value type, initialized to 0
8auto a3 = xt::zeros_like(a1);
9
10// same shape and value type, initialized to 1
11auto a4 = xt::ones_like(a1);
12
13// same shape and value type, initialized to given value
14auto a5 = xt::full_like(a1, 5);
Properties
1array_2d<int> a1 {{1, 2, 3},
2 {4, 5, 6}};
3
4// dimension
5auto d = a1.dimension(); // 2
6
7// size
8auto s = a1.size(); // 6
9
10// shape
11auto sh = a1.shape();
12sh[0]; // 2
13sh[1]; // 3
Element access
1array_2d<int> a1 {{1, 2, 3},
2 {4, 5, 6}};
3
4// modify and read element at line 1, column 2
5a1(1, 2) = 7;
6int v = a1(1, 2);
7
8// Same thing with the [] operator
9a1[{1, 2}] = 7;
10int v = a1[{1, 2}];
Display
1#include <iostream>
2#include <xtensor/xio.hpp>
3using namespace std;
4
5array_2d<int> a1 {{1, 2, 3},
6 {4, 5, 6}};
7
8cout << a1 << "\n";
Lazy Evaluation
Most xtensor operations are lazily evaluated. In the following situation:
1array_1d<int> a1{1, 2, 3};
2array_1d<int> a2{4, 5, 6};
3
4auto r = a2 * (a1 + a2);
r does only store the expression, i.e. the symbolic operation, but no actual results. The result will be computed when elements are accessed:
1auto v = r(1); // performs 5 * (2 + 5)
If an expression is evaluated several times at the same position, the same result will be computed several times.
An expression can be fully evaluated by assigning it to an actual array or by using the eval function:
1array_1d<int> ar1 = r; // evaluates the expression r and assigns the result to ar1
2auto ar2 = xt::eval(r); // evaluates r and assigns it to an array called ar2
Attention
Returning a non evaluated expression that refers to local variable will lead to undefined behaviors:
1auto function(){
2 array_1d<int> a1{1, 2, 3};
3 array_1d<int> a2{4, 5, 6};
4 //return a1 + a2; => ERROR depends of local variables that are destructed at the end of the function
5 return xt::eval(a1 + a2); // OK
6}