Sylvain Corlay
2017-03-17 13:18:30 UTC
Hi All,
On behalf of the xtensor development team, I am pleased to announce the
releases of
- xtensor 0.7.1 https://github.com/QuantStack/xtensor/
- xtensor-python 0.6.0 https://github.com/QuantStack/xtensor-python/
*What is xtensor?*
xtensor is a C++ library meant for numerical analysis with
multi-dimensional array expressions.
xtensor provides
- an extensible expression system enabling* lazy broadcasting.*
- an API following the idioms of the *C++ standard library*.
- an increasing support of numpy features which you can see in the *NumPy
to xtensor cheat sheet*.
- tools to manipulate array expressions and build upon xtensor.
- *numpy bindings* enabling the inplace use of numpy arrays as xtensor
expressions in C++ extensions.
*What is new in this release?*
In this release, we have added the reducers functionality and the real and
imaginary views for complex arrays. We have increased the performance of
xtensor universal functions.
*Where can I learn more about xtensor?*
Check out the extensive documentation:
http://xtensor.readthedocs.io/en/latest/
Or the numpy to xtensor cheat sheet:
http://xtensor.readthedocs.io/en/latest/numpy.html
Or join us in the chat room:
https://gitter.im/QuantStack/Lobby
Thanks!
Sylvain
From NumPy to xtensor
Containers
Two container types are provided. xarray (dynamic number of dimensions) and
xtensor (static number of dimensions).
Python 3 - numpyC++ 14 - xtensor
np.array([[3, 4], [5, 6]])
xt::xarray<double>({{3, 4}, {5, 6}})
xt::xtensor<double, 2>({{3, 4}, {5, 6}})
arr.reshape([3, 4]) arr.reshape{{3, 4})
Initializers
Lazy helper functions return tensor expressions. Return types donât hold
any value and are evaluated upon access or assignment. They can be assigned
to a container or directly used in expressions.
Python 3 - numpyC++ 14 - xtensor
np.linspace(1.0, 10.0, 100) xt::linspace<double>(1.0, 10.0, 100)
np.logspace(2.0, 3.0, 4) xt::logspace<double>(2.0, 3.0, 4)
np.arange(3, 7) xt::arange(3, 7)
np.eye(4) xt::eye(4)
np.zeros([3, 4]) xt::zeros<double>({3, 4})
np.ones([3, 4]) xt::ones<double>({3, 4})
np.meshgrid(x0, x1, x2, indexing='ij') xt::meshgrid(x0, x1, x2)
xtensorâs meshgrid implementation corresponds to numpyâs 'ij' indexing
order.
Broadcasting
xtensor offers lazy numpy-style broadcasting, and universal functions.
Unlike numpy, no copy or temporary variables are created.
Python 3 - numpyC++ 14 - xtensor
a[:, np.newaxis]
a[:5, 1:]
a[5:1:-1, :]
xt::view(a, xt::all(), xt::newaxis())
xt::view(a, xt::range(_, 5), xt::range(1, _))
xt::view(a, xt::range(5, 1, -1), xt::all())
np.broadcast(a, [4, 5, 7]) xt::broadcast(a, {4, 5, 7})
np.vectorize(f) xt::vectorize(f)
a[a > 5] xt::filter(a, a > 5)
a[[0, 1], [0, 0]] xt::index_view(a, {{0, 0}, {1, 0}})
Random
The random module provides simple ways to create random tensor expressions,
lazily.
Python 3 - numpyC++ 14 - xtensor
np.random.randn(10, 10) xt::random::randn<double>({10, 10})
np.random.randint(10, 10) xt::random::randint<int>({10, 10})
np.random.rand(3, 4) xt::random::rand<double>({3, 4})
Concatenation
Concatenating expressions does not allocate memory, it returns a tensor
expression holding closures on the specified arguments.
Python 3 - numpyC++ 14 - xtensor
np.stack([a, b, c], axis=1) xt::stack(xtuple(a, b, c), 1)
np.concatenate([a, b, c], axis=1) xt::concatenate(xtuple(a, b, c), 1)
Diagonal, triangular and flip
In the same spirit as concatenation, the following operations do not
allocate any memory and do not modify the underlying xexpression.
Python 3 - numpyC++ 14 - xtensor
np.diag(a) xt::diag(a)
np.diagonal(a) xt::diagonal(a)
np.triu(a) xt::triu(a)
np.tril(a, k=1) xt::tril(a, 1)
np.flip(a, axis=3) xt::flip(a, 3)
np.flipud(a) xt::flip(a, 0)
np.fliplr(a) xt::flip(a, 1)
Iteration
xtensor follows the idioms of the C++ STL providing iterator pairs to
iterate on arrays in different fashions.
Python 3 - numpyC++ 14 - xtensor
for x in np.nditer(a):
for(auto it=a.xbegin(); it!=a.xend(); ++it)
Iterating with a prescribed broadcasting shape
for(auto it=a.xbegin({3, 4});
it!=a.xend({3, 4}); ++it)
Logical
Logical universal functions are truly lazy. xt::where(condition, a, b) does
not evaluate a where condition is falsy, and it does not evaluate b where
condition is truthy.
Python 3 - numpyC++ 14 - xtensor
np.where(a > 5, a, b) xt::where(a > 5, a, b)
np.where(a > 5) xt::where(a > 5)
np.any(a) xt::any(a)
np.all(a) xt::all(a)
np.logical_and(a, b) a && b
np.logical_or(a, b) a || b
Comparisons
Python 3 - numpyC++ 14 - xtensor
np.equal(a, b) xt::equal(a, b)
np.not_equal(a) xt::not_equal(a)
np.nonzero(a) xt::nonzero(a)
Complex numbers
Functions xt::real and xt::imag respectively return views on the real and
imaginary part of a complex expression. The returned value is an expression
holding a closure on the passed argument.
Python 3 - numpyC++ 14 - xtensor
np.real(a) xt::real(a)
np.imag(a) xt::imag(a)
- The constness and value category (rvalue / lvalue) of real(a) is the
same as that of a. Hence, if a is a non-const lvalue, real(a) is an
non-const lvalue reference, to which one can assign a real expression.
- If a has complex values, the same holds for imag(a). The constness and
value category ofimag(a) is the same as that of a.
- If a has real values, imag(a) returns zeros(a.shape()).
Reducers
Reducers accumulate values of tensor expressions along specified axes. When
no axis is specified, values are accumulated along all axes. Reducers are
lazy, meaning that returned expressons donât hold any values and are
computed upon access or assigmnent.
Python 3 - numpyC++ 14 - xtensor
np.sum(a, axis=[0, 1]) xt::sum(a, {0, 1})
np.sum(a) xt::sum(a)
np.prod(a, axis=1) xt::prod(a, {1})
np.prod(a) xt::prod(a)
np.mean(a, axis=1) xt::mean(a, {1})
np.mean(a) xt::mean(a)
More generally, one can use the xt::reduce(function, input, axes) which
allows the specification of an arbitrary binary function for the reduction.
The binary function must be cummutative and associative up to rounding
errors.
Mathematical functions
xtensor universal functions are provided for a large set number of
mathematical functions.
*Basic functions:*
Python 3 - numpyC++ 14 - xtensor
np.isnan(a) xt::isnan(a)
np.absolute(a) xt::abs(a)
np.sign(a) xt::sign(a)
np.remainder(a, b) xt::remainder(a, b)
np.clip(a, min, max) xt::clip(a, min, max)
xt::fma(a, b, c)
*Exponential functions:*
Python 3 - numpyC++ 14 - xtensor
np.exp(a) xt::exp(a)
np.expm1(a) xt::expm1(a)
np.log(a) xt::log(a)
np.log1p(a) xt::log1p(a)
*Power functions:*
Python 3 - numpyC++ 14 - xtensor
np.power(a, p) xt::pow(a, b)
np.sqrt(a) xt::sqrt(a)
np.cbrt(a) xt::cbrt(a)
*Trigonometric functions:*
Python 3 - numpyC++ 14 - xtensor
np.sin(a) xt::sin(a)
np.cos(a) xt::cos(a)
np.tan(a) xt::tan(a)
*Hyperbolic functions:*
Python 3 - numpyC++ 14 - xtensor
np.sinh(a) xt::sinh(a)
np.cosh(a) xt::cosh(a)
np.tang(a) xt::tanh(a)
*Error and gamma functions:*
Python 3 - numpyC++ 14 - xtensor
scipy.special.erf(a) xt::erf(a)
scipy.special.gamma(a) xt::tgamma(a)
scipy.special.gammaln(a) xt::lgamma(a)
On behalf of the xtensor development team, I am pleased to announce the
releases of
- xtensor 0.7.1 https://github.com/QuantStack/xtensor/
- xtensor-python 0.6.0 https://github.com/QuantStack/xtensor-python/
*What is xtensor?*
xtensor is a C++ library meant for numerical analysis with
multi-dimensional array expressions.
xtensor provides
- an extensible expression system enabling* lazy broadcasting.*
- an API following the idioms of the *C++ standard library*.
- an increasing support of numpy features which you can see in the *NumPy
to xtensor cheat sheet*.
- tools to manipulate array expressions and build upon xtensor.
- *numpy bindings* enabling the inplace use of numpy arrays as xtensor
expressions in C++ extensions.
*What is new in this release?*
In this release, we have added the reducers functionality and the real and
imaginary views for complex arrays. We have increased the performance of
xtensor universal functions.
*Where can I learn more about xtensor?*
Check out the extensive documentation:
http://xtensor.readthedocs.io/en/latest/
Or the numpy to xtensor cheat sheet:
http://xtensor.readthedocs.io/en/latest/numpy.html
Or join us in the chat room:
https://gitter.im/QuantStack/Lobby
Thanks!
Sylvain
From NumPy to xtensor
Containers
Two container types are provided. xarray (dynamic number of dimensions) and
xtensor (static number of dimensions).
Python 3 - numpyC++ 14 - xtensor
np.array([[3, 4], [5, 6]])
xt::xarray<double>({{3, 4}, {5, 6}})
xt::xtensor<double, 2>({{3, 4}, {5, 6}})
arr.reshape([3, 4]) arr.reshape{{3, 4})
Initializers
Lazy helper functions return tensor expressions. Return types donât hold
any value and are evaluated upon access or assignment. They can be assigned
to a container or directly used in expressions.
Python 3 - numpyC++ 14 - xtensor
np.linspace(1.0, 10.0, 100) xt::linspace<double>(1.0, 10.0, 100)
np.logspace(2.0, 3.0, 4) xt::logspace<double>(2.0, 3.0, 4)
np.arange(3, 7) xt::arange(3, 7)
np.eye(4) xt::eye(4)
np.zeros([3, 4]) xt::zeros<double>({3, 4})
np.ones([3, 4]) xt::ones<double>({3, 4})
np.meshgrid(x0, x1, x2, indexing='ij') xt::meshgrid(x0, x1, x2)
xtensorâs meshgrid implementation corresponds to numpyâs 'ij' indexing
order.
Broadcasting
xtensor offers lazy numpy-style broadcasting, and universal functions.
Unlike numpy, no copy or temporary variables are created.
Python 3 - numpyC++ 14 - xtensor
a[:, np.newaxis]
a[:5, 1:]
a[5:1:-1, :]
xt::view(a, xt::all(), xt::newaxis())
xt::view(a, xt::range(_, 5), xt::range(1, _))
xt::view(a, xt::range(5, 1, -1), xt::all())
np.broadcast(a, [4, 5, 7]) xt::broadcast(a, {4, 5, 7})
np.vectorize(f) xt::vectorize(f)
a[a > 5] xt::filter(a, a > 5)
a[[0, 1], [0, 0]] xt::index_view(a, {{0, 0}, {1, 0}})
Random
The random module provides simple ways to create random tensor expressions,
lazily.
Python 3 - numpyC++ 14 - xtensor
np.random.randn(10, 10) xt::random::randn<double>({10, 10})
np.random.randint(10, 10) xt::random::randint<int>({10, 10})
np.random.rand(3, 4) xt::random::rand<double>({3, 4})
Concatenation
Concatenating expressions does not allocate memory, it returns a tensor
expression holding closures on the specified arguments.
Python 3 - numpyC++ 14 - xtensor
np.stack([a, b, c], axis=1) xt::stack(xtuple(a, b, c), 1)
np.concatenate([a, b, c], axis=1) xt::concatenate(xtuple(a, b, c), 1)
Diagonal, triangular and flip
In the same spirit as concatenation, the following operations do not
allocate any memory and do not modify the underlying xexpression.
Python 3 - numpyC++ 14 - xtensor
np.diag(a) xt::diag(a)
np.diagonal(a) xt::diagonal(a)
np.triu(a) xt::triu(a)
np.tril(a, k=1) xt::tril(a, 1)
np.flip(a, axis=3) xt::flip(a, 3)
np.flipud(a) xt::flip(a, 0)
np.fliplr(a) xt::flip(a, 1)
Iteration
xtensor follows the idioms of the C++ STL providing iterator pairs to
iterate on arrays in different fashions.
Python 3 - numpyC++ 14 - xtensor
for x in np.nditer(a):
for(auto it=a.xbegin(); it!=a.xend(); ++it)
Iterating with a prescribed broadcasting shape
for(auto it=a.xbegin({3, 4});
it!=a.xend({3, 4}); ++it)
Logical
Logical universal functions are truly lazy. xt::where(condition, a, b) does
not evaluate a where condition is falsy, and it does not evaluate b where
condition is truthy.
Python 3 - numpyC++ 14 - xtensor
np.where(a > 5, a, b) xt::where(a > 5, a, b)
np.where(a > 5) xt::where(a > 5)
np.any(a) xt::any(a)
np.all(a) xt::all(a)
np.logical_and(a, b) a && b
np.logical_or(a, b) a || b
Comparisons
Python 3 - numpyC++ 14 - xtensor
np.equal(a, b) xt::equal(a, b)
np.not_equal(a) xt::not_equal(a)
np.nonzero(a) xt::nonzero(a)
Complex numbers
Functions xt::real and xt::imag respectively return views on the real and
imaginary part of a complex expression. The returned value is an expression
holding a closure on the passed argument.
Python 3 - numpyC++ 14 - xtensor
np.real(a) xt::real(a)
np.imag(a) xt::imag(a)
- The constness and value category (rvalue / lvalue) of real(a) is the
same as that of a. Hence, if a is a non-const lvalue, real(a) is an
non-const lvalue reference, to which one can assign a real expression.
- If a has complex values, the same holds for imag(a). The constness and
value category ofimag(a) is the same as that of a.
- If a has real values, imag(a) returns zeros(a.shape()).
Reducers
Reducers accumulate values of tensor expressions along specified axes. When
no axis is specified, values are accumulated along all axes. Reducers are
lazy, meaning that returned expressons donât hold any values and are
computed upon access or assigmnent.
Python 3 - numpyC++ 14 - xtensor
np.sum(a, axis=[0, 1]) xt::sum(a, {0, 1})
np.sum(a) xt::sum(a)
np.prod(a, axis=1) xt::prod(a, {1})
np.prod(a) xt::prod(a)
np.mean(a, axis=1) xt::mean(a, {1})
np.mean(a) xt::mean(a)
More generally, one can use the xt::reduce(function, input, axes) which
allows the specification of an arbitrary binary function for the reduction.
The binary function must be cummutative and associative up to rounding
errors.
Mathematical functions
xtensor universal functions are provided for a large set number of
mathematical functions.
*Basic functions:*
Python 3 - numpyC++ 14 - xtensor
np.isnan(a) xt::isnan(a)
np.absolute(a) xt::abs(a)
np.sign(a) xt::sign(a)
np.remainder(a, b) xt::remainder(a, b)
np.clip(a, min, max) xt::clip(a, min, max)
xt::fma(a, b, c)
*Exponential functions:*
Python 3 - numpyC++ 14 - xtensor
np.exp(a) xt::exp(a)
np.expm1(a) xt::expm1(a)
np.log(a) xt::log(a)
np.log1p(a) xt::log1p(a)
*Power functions:*
Python 3 - numpyC++ 14 - xtensor
np.power(a, p) xt::pow(a, b)
np.sqrt(a) xt::sqrt(a)
np.cbrt(a) xt::cbrt(a)
*Trigonometric functions:*
Python 3 - numpyC++ 14 - xtensor
np.sin(a) xt::sin(a)
np.cos(a) xt::cos(a)
np.tan(a) xt::tan(a)
*Hyperbolic functions:*
Python 3 - numpyC++ 14 - xtensor
np.sinh(a) xt::sinh(a)
np.cosh(a) xt::cosh(a)
np.tang(a) xt::tanh(a)
*Error and gamma functions:*
Python 3 - numpyC++ 14 - xtensor
scipy.special.erf(a) xt::erf(a)
scipy.special.gamma(a) xt::tgamma(a)
scipy.special.gammaln(a) xt::lgamma(a)