1.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht 2 3 Distributed under the terms of the BSD 3-Clause License. 4 5 The full license is in the file LICENSE, distributed with this software. 6 7Common pitfalls 8=============== 9 10xarray initialization 11--------------------- 12 13.. code:: 14 15 xt::xarray<double> a({1, 3, 4, 2}); 16 17does not initialize a 4D-array, but a 1D-array containing the values ``1``, ``3``, 18``4``, and ``2``. 19It is strictly equivalent to 20 21.. code:: 22 23 xt::xarray<double> a = {1, 3, 4, 2}; 24 25To initialize a 4D-array with the given shape, use the ``from_shape`` static method: 26 27.. code:: 28 29 auto a = xt::xarray<double>::from_shape({1, 3, 4, 2}); 30 31The confusion often comes from the way ``xtensor`` can be initialized: 32 33.. code:: 34 35 xt::xtensor<double, 4> a = {1, 3, 4, 2}; 36 37In this case, a 4D-tensor with shape ``(1, 3, 4, 2)`` is initialized. 38 39Intermediate result 40------------------- 41 42Consider the following function: 43 44.. code:: 45 46 template <class C> 47 auto func(const C& c) 48 { 49 return (1 - func_tmp(c)) / (1 + func_tmp(c)); 50 } 51 52where ``func_tmp`` is another unary function accepting an xtensor expression. You may 53be tempted to simplify it a bit: 54 55.. code:: 56 57 template <class C> 58 auto func(const C& c) 59 { 60 auto tmp = func_tmp(c); 61 return (1 - tmp) / (1 + tmp); 62 } 63 64Unfortunately, you introduced a bug; indeed, expressions in ``xtensor`` are not evaluated 65immediately, they capture their arguments by reference or copy depending on their nature, 66for future evaluation. Since ``tmp`` is an lvalue, it is captured by reference in the last 67statement; when the function returns, ``tmp`` is destroyed, leading to a dangling reference 68in the returned expression. 69 70Replacing ``auto tmp`` with ``xt::xarray<double> tmp`` does not change anything, ``tmp`` 71is still an lvalue and thus captured by reference. 72 73Random numbers not consistent 74----------------------------- 75 76Using a random number function from xtensor actually returns a lazy 77generator. That means, accessing the same element of a random number 78generator does not give the same random number if called twice. 79 80.. code:: 81 82 auto gen = xt::random::rand<double>({10, 10}); 83 auto a0 = gen(0, 0); 84 auto a1 = gen(0, 0); 85 86 // a0 != a1 !!! 87 88You need to explicitly assign or eval a random number generator, 89like so: 90 91.. code:: 92 93 xt::xarray<double> xr = xt::random::rand<double>({10, 10}); 94 auto xr2 = eval(xt::random::rand<double>({10, 10})); 95 96 // now xr(0, 0) == xr(0, 0) is true. 97 98variance arguments 99------------------ 100 101When ``variance`` is passed an expression and an integer parameter, this latter 102is not the axis along which the variance must be computed, but the degree of freedom: 103 104.. code:: 105 106 xt::xtensor<double, 2> a = {{1., 2., 3.}, {4., 5., 6.}}; 107 std::cout << xt::variance(a, 1) << std::endl; 108 // Outputs 3.5 109 110If you want to specify an axis, you need to pass an initializer list: 111 112.. code:: 113 114 xt::xtensor<double, 2> a = {{1., 2., 3.}, {4., 5., 6.}}; 115 std::cout << xt::variance(a, {1}) << std::endl; 116 .. Outputs { 0.666667, 0.666667 } 117 118fixed_shape on Windows 119---------------------- 120 121Builder functions such as ``empty`` or ``ones`` accept an initializer list 122as argument. If the elements of this list do not have the same type, a 123curious compilation error may occur on Windows: 124 125.. code:: 126 127 size_t N = 10ull; 128 xt::xarray<int> ages = xt::empty<int>({N, 4ul}); 129 130 // error: cannot convert argument 1 from 'initializer list' 131 // to 'const xt::fixed_shape<> &' 132 133To avoid this compiler bug (for which we don't have a workaround), ensure 134all the elements in the initializer list have the same type. 135 136Alignment of fixed-size members 137------------------------------- 138 139.. note:: 140 141 If you are using ``C++ >= 17`` you should not have to worry about this. 142 143When building with ``xsimd`` (see :ref:`external-dependencies`), if you define a structure 144having members of fixed-size xtensor types, you must ensure that the buffers properly 145aligned. For this you can use the macro ``XTENSOR_FIXED_ALIGN`` available in 146``xtensor/xtensor_config.hpp``. 147Consider the following example: 148 149.. code-block:: cpp 150 151 template <typename T> 152 class alignas(XTENSOR_FIXED_ALIGN) Foo 153 { 154 public: 155 156 using allocator_type = std::conditional_t<XTENSOR_FIXED_ALIGN != 0, 157 xt_simd::aligned_allocator<T, XTENSOR_FIXED_ALIGN>, 158 std::allocator<T>>; 159 160 Foo(T fac) : m_fac(fac) 161 { 162 m_bar.fill(fac); 163 } 164 165 auto get() const 166 { 167 return m_bar; 168 } 169 170 private: 171 172 xt::xtensor_fixed<T, xt::xshape<10, 10>> m_bar; 173 T m_fac; 174 }; 175 176Whereby it is important to store the fixed-sized xtensor type (in this case ``xt::xtensor_fixed<T, xt::xshape<10, 10>>``) as first member. 177