literal.hpp 2.49 KB
Newer Older
Paul's avatar
Paul committed
1
2
3
4
#ifndef GUARD_RTGLIB_LITERAL_HPP
#define GUARD_RTGLIB_LITERAL_HPP

#include <rtg/shape.hpp>
Paul's avatar
Paul committed
5
#include <rtg/argument.hpp>
Paul's avatar
Paul committed
6
#include <rtg/tensor_view.hpp>
Paul's avatar
Paul committed
7
8
9
10
11

namespace rtg {

struct literal 
{
Paul's avatar
Paul committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    literal()
    : buffer(), shape_()
    {}

    template<class T>
    literal(T x) 
    : buffer(sizeof(T), 0), shape_(shape::get_type<T>{})
    {
        static_assert(std::is_trivial<T>{}, "Literals can only be trivial types");
        *(reinterpret_cast<T*>(buffer.data())) = x;
    }

    template<class T>
    literal(shape s, const std::vector<T>& x) 
    : buffer(s.bytes(), 0), shape_(s)
    {
        static_assert(std::is_trivial<T>{}, "Literals can only be trivial types");
        std::copy(x.begin(), x.end(), reinterpret_cast<T*>(buffer.data()));
    }
Paul's avatar
Paul committed
31
32
33
34
    
    literal(shape s, const char* x)
    : buffer(x, x+s.bytes()), shape_(s)
    {}
Paul's avatar
Paul committed
35
36
37
38
39
40

    friend bool operator==(const literal& x, const literal& y)
    {
        bool result = x.buffer.empty() && y.buffer.empty();
        if(not result && x.shape_ == y.shape_ and x.buffer.size() == y.buffer.size())
        {
Paul's avatar
Paul committed
41
            // TODO: Dont use tensor view for single values
Paul's avatar
Paul committed
42
            x.shape_.visit_type([&](auto as) {
Paul's avatar
Paul committed
43
44
45
                auto xview = make_view(x.shape_, as.from(x.buffer.data()));
                auto yview = make_view(y.shape_, as.from(y.buffer.data()));
                result = xview == yview;
Paul's avatar
Paul committed
46
47
48
49
50
51
52
53
54
55
56
            });
        }
        return result;
    }

    friend bool operator!=(const literal& x, const literal& y)
    {
        return !(x == y);
    }

    template<class Visitor>
Paul's avatar
Paul committed
57
58
59
60
61
62
63
64
65
    void visit_at(Visitor v, std::size_t n=0) const
    {
        shape_.visit_type([&](auto as) {
            v(*(as.from(this->buffer.data())+shape_.index(n)));
        });
    }

    template<class Visitor>
    void visit(Visitor v) const
Paul's avatar
Paul committed
66
67
    {
        shape_.visit_type([&](auto as) {
Paul's avatar
Paul committed
68
            v(make_view(this->shape_, as.from(this->buffer.data())));
Paul's avatar
Paul committed
69
70
71
72
73
74
75
76
        });
    }

    bool empty() const
    {
        return this->buffer.empty();
    }

Paul's avatar
Paul committed
77
78
79
80
81
    bool single() const
    {
        return this->shape_.elements() == 1;
    }

Paul's avatar
Paul committed
82
83
84
85
    template<class T>
    T at(std::size_t n=0) const
    {
        T result;
Paul's avatar
Paul committed
86
        this->visit_at([&](auto x) {
Paul's avatar
Paul committed
87
88
89
90
91
92
93
94
95
96
            result = x;
        });
        return result;
    }

    const shape& get_shape() const
    {
        return this->shape_;
    }

Paul's avatar
Paul committed
97
98
99
    argument get_argument() const
    {
        auto b = buffer;
Paul's avatar
Paul committed
100
        return {shape_, [b]() mutable { return b.data(); }};
Paul's avatar
Paul committed
101
102
    }

Paul's avatar
Paul committed
103
private:
Paul's avatar
Paul committed
104
105
106
107
108
109
110
    std::vector<char> buffer;
    shape shape_;
};

}

#endif