void Clamp(std::vector<double>& input_image, double min_value, double max_value, int width, int height)
{
for (int j = 0; j < width; j++)
{
for (int i = 0; i < height; i++)
{
input_image[i*width + j] = std::min(std::max(input_image[i*width + j], min_value), max_value);
}
}
}
我正在尝试创建这种钳制功能。
有没有更好的方法来使用std::vector
?
我也可以使用C ++ 11
答案 0 :(得分:3)
C ++ 17有std::clamp
。此外,在这种情况下也不需要height
和width
参数。
void clamp_vec(std::vector<double>& input_image, double min_value, double max_value) {
std::transform(std::begin(input_image), std::end(input_image), std::begin(input_image),
[=] (auto i) { return std::clamp(i, min_value, max_value); });
}
只要定义了运算符<
,泛型类型的模板版本就会起作用:
template <typename T>
void clamp_vec(std::vector<T>& input_image, const T& min_value, const T& max_value) {
std::transform(std::begin(input_image), std::end(input_image), std::begin(input_image),
[&] (const T& v) { return std::clamp(v, min_value, max_value); });
}
如果std::clamp
不可用,您可以自己实现,直到C ++ 17出现,例如:
template <typename T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return clamp(v, lo, hi, std::less<>());
}
template <typename T, typename Compare>
constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp) {
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
}
答案 1 :(得分:2)
您可以使用std::transform,假设您将函数应用于每个元素,则不需要高度和宽度参数。分割最小和最大操作似乎更加SIMD友好,因此我建议:
void Clamp(std::vector<double>& input_image, double min_value, double max_value)
{
std::transform(std::begin(input_image), std::end(input_image), std::begin(input_image), [max_value] (double d) { return std::min(d, max_value); }
std::transform(std::begin(input_image), std::end(input_image), std::begin(input_image), [min_value] (double d) { return std::max(d, max_value); }
}
否则,C ++ 11方式可能是使用range-based for loop:
void Clamp(std::vector<double>& input_image, double min_value, double max_value) // removed hight and width
{
for (double& d : input_image)
{
d = std::min(std::max(d, min_value), max_value);
}
}
或更SIMD“友好”:
void Clamp(std::vector<double>& input_image, double min_value, double max_value) // removed height and width
{
for (double& d : input_image)
{
d = std::max(d, min_value);
}
for (double& d : input_image)
{
d = std::min(d, max_value);
}
}
答案 2 :(得分:2)
我想我只是在一次通过中让优化者完成它的工作。
void Clamp(std::vector<double>& input_image, double min_value, double max_value)
{
auto clamp = [min_value, max_value](double x) {
return std::min(std::max(x, min_value), max_value);
};
std::transform(input_image.begin(), input_image.end(),
input_image.begin(), clamp);
}
在godbolt上对此进行测试,gcc对其进行了矢量化,并完全消除了clamp
的冗余副本。
答案 3 :(得分:1)
你去吧。我做了两个转换只是为了给编译器提供更好的优化和向量化机会。如果您不同意,可以加入1 lambda。
{{1}}
始终记住,循环连续的内存元素要快得多。请参阅std::transform
reference以了解其工作原理。