File: rank.rst

package info (click to toggle)
xtensor 0.25.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,476 kB
  • sloc: cpp: 65,302; makefile: 202; python: 171; javascript: 8
file content (116 lines) | stat: -rw-r--r-- 3,235 bytes parent folder | download
1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht

   Distributed under the terms of the BSD 3-Clause License.

   The full license is in the file LICENSE, distributed with this software.

.. _rank:

Tensor Rank
===========

Rank overload
-------------

All *xtensor*'s classes have a member ``rank`` that can be used
to overload based on rank using *SFINAE*.
Consider the following example:

.. code-block:: cpp

    template <class E, std::enable_if_t<!xt::has_rank_t<E, 2>::value, int> = 0>
    inline E foo(E&& a)
    {
        ... // act on object of flexible rank, or fixed rank != 2
    }

    template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
    inline E foo(E&& a)
    {
        ... // act on object of fixed rank == 2
    }

    int main()
    {
        xt::xarray<size_t> a = {{9, 9}, {9, 9}};
        xt::xtensor<size_t, 1> b = {9, 9};
        xt::xtensor<size_t, 2> c = {{9, 9}, {9, 9}};

        foo(a); // flexible rank -> first overload
        foo(b); // fixed rank == 2 -> first overload
        foo(c); // fixed rank == 2 -> second overload

        return 0;
    }

.. note::

    If one wants to test for more than a single value for ``rank``,
    one can use the default value ``SIZE_MAX`` used for flexible rank objects.
    For example, one could have the following overloads:

    .. code-block:: cpp

        // flexible rank
        template <class E, std::enable_if_t<!xt::has_fixed_rank_t<E>::value, int> = 0>
        inline E foo(E&& a);

        // fixed rank == 1
        template <class E, std::enable_if_t<xt::has_rank_t<E, 1>::value, int> = 0>
        inline E foo(E&& a);

        // fixed rank == 2
        template <class E, std::enable_if_t<xt::has_rank_t<E, 2>::value, int> = 0>
        inline E foo(E&& a);

    Note that fixed ranks other than 1 and 2 will raise a compiler error.

    Of course, if one wants a more limited scope, one could also do the following:

    .. code-block:: cpp

        // flexible rank
        inline void foo(xt::xarray<double>& a);

        // fixed rank == 1
        inline void foo(xt::xtensor<double,1>& a);

        // fixed rank == 2
        inline void foo(xt::xtensor<double,2>& a);

Rank as member
--------------

If you want to use the rank as a member of your own class you can use
:cpp:type:`xt::get_rank\<E\> <xt::get_rank>`.
Consider the following example:

.. code-block:: cpp

    template <class T>
    struct Foo
    {
        static const size_t rank = xt::get_rank<T>::value;

        static size_t value()
        {
            return rank;
        }
    };

    int main()
    {
        xt::xtensor<double, 1> A = xt::zeros<double>({2});
        xt::xtensor<double, 2> B = xt::zeros<double>({2, 2});
        xt::xarray<double> C = xt::zeros<double>({2, 2});

        assert(Foo<decltype(A)>::value() == 1);
        assert(Foo<decltype(B)>::value() == 2);
        assert(Foo<decltype(C)>::value() == SIZE_MAX);

        return 0;
    }

``xt::get_rank`` 'returns' the rank of the *xtensor* object if its rank is fixed.
In all other cases it 'returns' ``SIZE_MAX``.
Indeed ``xt::get_rank<xt::array<double>>::value`` is equal to ``SIZE_MAX``, but equally so is ``xt::get_rank<double>::value``.