fill.hpp 5.18 KB
Newer Older
Chao Liu's avatar
Chao Liu committed
1
// SPDX-License-Identifier: MIT
2
// Copyright (c) 2018-2024, Advanced Micro Devices, Inc. All rights reserved.
Chao Liu's avatar
Chao Liu committed
3

4
5
6
#pragma once

#include <algorithm>
7
#include <cmath>
8
#include <iterator>
9
#include <random>
10
11
#include <type_traits>
#include <utility>
12

Chao Liu's avatar
Chao Liu committed
13
#include "ck/utility/data_type.hpp"
14
15
16
17

namespace ck {
namespace utils {

18
19
20
21
22
template <typename T>
struct FillUniformDistribution
{
    float a_{-5.f};
    float b_{5.f};
23

24
25
26
27
28
29
30
    template <typename ForwardIter>
    void operator()(ForwardIter first, ForwardIter last) const
    {
        std::mt19937 gen(11939);
        std::uniform_real_distribution<float> dis(a_, b_);
        std::generate(first, last, [&dis, &gen]() { return ck::type_convert<T>(dis(gen)); });
    }
31
32

    template <typename ForwardRange>
33
34
35
36
    auto operator()(ForwardRange&& range) const
        -> std::void_t<decltype(std::declval<const FillUniformDistribution&>()(
            std::begin(std::forward<ForwardRange>(range)),
            std::end(std::forward<ForwardRange>(range))))>
37
38
39
40
    {
        (*this)(std::begin(std::forward<ForwardRange>(range)),
                std::end(std::forward<ForwardRange>(range)));
    }
41
};
42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Normally FillUniformDistributionIntegerValue should use std::uniform_int_distribution as below.
// However this produces segfaults in std::mt19937 which look like inifite loop.
//      template <typename T>
//      struct FillUniformDistributionIntegerValue
//      {
//          int a_{-5};
//          int b_{5};
//
//          template <typename ForwardIter>
//          void operator()(ForwardIter first, ForwardIter last) const
//          {
//              std::mt19937 gen(11939);
//              std::uniform_int_distribution<int> dis(a_, b_);
//              std::generate(
//                  first, last, [&dis, &gen]() { return ck::type_convert<T>(dis(gen)); });
//          }
//      };
60

61
// Workaround for uniform_int_distribution not working as expected. See note above.<
62
template <typename T>
63
struct FillUniformDistributionIntegerValue
64
{
65
66
    float a_{-5.f};
    float b_{5.f};
67
68
69
70

    template <typename ForwardIter>
    void operator()(ForwardIter first, ForwardIter last) const
    {
71
72
73
74
        std::mt19937 gen(11939);
        std::uniform_real_distribution<float> dis(a_, b_);
        std::generate(
            first, last, [&dis, &gen]() { return ck::type_convert<T>(std::round(dis(gen))); });
75
    }
76
77
78
79
80
81
82
83
84
85

    template <typename ForwardRange>
    auto operator()(ForwardRange&& range) const
        -> std::void_t<decltype(std::declval<const FillUniformDistributionIntegerValue&>()(
            std::begin(std::forward<ForwardRange>(range)),
            std::end(std::forward<ForwardRange>(range))))>
    {
        (*this)(std::begin(std::forward<ForwardRange>(range)),
                std::end(std::forward<ForwardRange>(range)));
    }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
};

template <typename T>
struct FillMonotonicSeq
{
    T init_value_{0};
    T step_{1};

    template <typename ForwardIter>
    void operator()(ForwardIter first, ForwardIter last) const
    {
        std::generate(first, last, [=, n = init_value_]() mutable {
            auto tmp = n;
            n += step_;
            return tmp;
        });
    }
103
104

    template <typename ForwardRange>
105
106
107
108
    auto operator()(ForwardRange&& range) const
        -> std::void_t<decltype(std::declval<const FillMonotonicSeq&>()(
            std::begin(std::forward<ForwardRange>(range)),
            std::end(std::forward<ForwardRange>(range))))>
109
110
111
112
    {
        (*this)(std::begin(std::forward<ForwardRange>(range)),
                std::end(std::forward<ForwardRange>(range)));
    }
113
114
115
116
117
118
119
120
121
122
123
124
};

template <typename T>
struct FillConstant
{
    T value_{0};

    template <typename ForwardIter>
    void operator()(ForwardIter first, ForwardIter last) const
    {
        std::fill(first, last, value_);
    }
125
126
127
128
129
130
131
132
133

    template <typename ForwardRange>
    auto operator()(ForwardRange&& range) const -> std::void_t<
        decltype(std::declval<const FillConstant&>()(std::begin(std::forward<ForwardRange>(range)),
                                                     std::end(std::forward<ForwardRange>(range))))>
    {
        (*this)(std::begin(std::forward<ForwardRange>(range)),
                std::end(std::forward<ForwardRange>(range)));
    }
134
135
};

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
template <typename T>
struct TransformIntoStructuralSparsity
{
    // clang-format off
    static constexpr T valid_sequences[] = {
        0, 0, 1, 1,
        0, 1, 0, 1,
        0, 1, 1, 0,
        1, 0, 0, 1,
        1, 0, 1, 0,
        1, 1, 0, 0,
    };
    // clang-format on

    template <typename ForwardIter>
    void operator()(ForwardIter first, ForwardIter last) const
    {
        std::for_each(first, last, [=, idx = 0](T& elem) mutable {
            auto tmp_idx = idx;
            idx += 1;
            return elem *= valid_sequences[tmp_idx % (sizeof(valid_sequences) / sizeof(T))];
        });
    }

    template <typename ForwardRange>
    auto operator()(ForwardRange&& range) const
        -> std::void_t<decltype(std::declval<const TransformIntoStructuralSparsity&>()(
            std::begin(std::forward<ForwardRange>(range)),
            std::end(std::forward<ForwardRange>(range))))>
    {
        (*this)(std::begin(std::forward<ForwardRange>(range)),
                std::end(std::forward<ForwardRange>(range)));
    }
};

171
172
} // namespace utils
} // namespace ck