Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/clover/util/factor.hpp
4572 views
1
//
2
// Copyright 2013 Francisco Jerez
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a
5
// copy of this software and associated documentation files (the "Software"),
6
// to deal in the Software without restriction, including without limitation
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
// and/or sell copies of the Software, and to permit persons to whom the
9
// Software is furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
// OTHER DEALINGS IN THE SOFTWARE.
21
//
22
23
#ifndef CLOVER_UTIL_FACTOR_HPP
24
#define CLOVER_UTIL_FACTOR_HPP
25
26
#include "util/range.hpp"
27
28
namespace clover {
29
namespace factor {
30
///
31
/// Calculate all prime integer factors of \p x.
32
///
33
/// If \p limit is non-zero, terminate early as soon as enough
34
/// factors have been collected to reach the product \p limit.
35
///
36
template<typename T>
37
std::vector<T>
38
find_integer_prime_factors(T x, T limit = 0)
39
{
40
const T max_d = (limit > 0 && limit < x ? limit : x);
41
const T min_x = x / max_d;
42
std::vector<T> factors;
43
44
for (T d = 2; d <= max_d && x > min_x; d++) {
45
if (x % d == 0) {
46
for (; x % d == 0; x /= d);
47
factors.push_back(d);
48
}
49
}
50
51
return factors;
52
}
53
54
namespace detail {
55
///
56
/// Walk the power set of prime factors of the n-dimensional
57
/// integer array \p grid subject to the constraints given by
58
/// \p limits.
59
///
60
template<typename T>
61
std::pair<T, std::vector<T>>
62
next_grid_factor(const std::pair<T, std::vector<T>> &limits,
63
const std::vector<T> &grid,
64
const std::vector<std::vector<T>> &factors,
65
std::pair<T, std::vector<T>> block,
66
unsigned d = 0, unsigned i = 0) {
67
if (d >= factors.size()) {
68
// We're done.
69
return {};
70
71
} else if (i >= factors[d].size()) {
72
// We're done with this grid dimension, try the next.
73
return next_grid_factor(limits, grid, factors,
74
std::move(block), d + 1, 0);
75
76
} else {
77
T f = factors[d][i];
78
79
// Try the next power of this factor.
80
block.first *= f;
81
block.second[d] *= f;
82
83
if (block.first <= limits.first &&
84
block.second[d] <= limits.second[d] &&
85
grid[d] % block.second[d] == 0) {
86
// We've found a valid grid divisor.
87
return block;
88
89
} else {
90
// Overflow, back off to the zeroth power,
91
while (block.second[d] % f == 0) {
92
block.second[d] /= f;
93
block.first /= f;
94
}
95
96
// ...and carry to the next factor.
97
return next_grid_factor(limits, grid, factors,
98
std::move(block), d, i + 1);
99
}
100
}
101
}
102
}
103
104
///
105
/// Find the divisor of the integer array \p grid that gives the
106
/// highest possible product not greater than \p product_limit
107
/// subject to the constraints given by \p coord_limit.
108
///
109
template<typename T>
110
std::vector<T>
111
find_grid_optimal_factor(T product_limit,
112
const std::vector<T> &coord_limit,
113
const std::vector<T> &grid) {
114
const std::vector<std::vector<T>> factors =
115
map(find_integer_prime_factors<T>, grid, coord_limit);
116
const auto limits = std::make_pair(product_limit, coord_limit);
117
auto best = std::make_pair(T(1), std::vector<T>(grid.size(), T(1)));
118
119
for (auto block = best;
120
block.first != 0 && best.first != product_limit;
121
block = detail::next_grid_factor(limits, grid, factors, block)) {
122
if (block.first > best.first)
123
best = block;
124
}
125
126
return best.second;
127
}
128
}
129
}
130
131
#endif
132
133