#ifndef HALIDE_BOUNDARY_CONDITIONS_H
#define HALIDE_BOUNDARY_CONDITIONS_H
#include <utility>
#include <vector>
#include "Func.h"
#include "IR.h"
#include "Util.h"
namespace Halide {
namespace BoundaryConditions {
namespace Internal {
inline const Func &func_like_to_func(const Func &func) {
return func;
}
template <typename T>
inline NO_INLINE Func func_like_to_func(const T &func_like) {
return lambda(_, func_like(_));
}
}
EXPORT Func constant_exterior(const Func &source, Tuple value,
const std::vector<std::pair<Expr, Expr>> &bounds);
EXPORT Func constant_exterior(const Func &source, Expr value,
const std::vector<std::pair<Expr, Expr>> &bounds);
template <typename T>
inline NO_INLINE Func constant_exterior(const T &func_like, Tuple value) {
std::vector<std::pair<Expr, Expr>> object_bounds;
for (int i = 0; i < func_like.dimensions(); i++) {
object_bounds.push_back({ Expr(func_like.dim(i).min()), Expr(func_like.dim(i).extent()) });
}
return constant_exterior(Internal::func_like_to_func(func_like), value, object_bounds);
}
template <typename T>
inline NO_INLINE Func constant_exterior(const T &func_like, Expr value) {
return constant_exterior(func_like, Tuple(value));
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func constant_exterior(const T &func_like, Tuple value,
Bounds&&... bounds) {
std::vector<std::pair<Expr, Expr>> collected_bounds;
::Halide::Internal::collect_paired_args(collected_bounds, std::forward<Bounds>(bounds)...);
return constant_exterior(Internal::func_like_to_func(func_like), value, collected_bounds);
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func constant_exterior(const T &func_like, Expr value,
Bounds&&... bounds) {
return constant_exterior(func_like, Tuple(value), std::forward<Bounds>(bounds)...);
}
EXPORT Func repeat_edge(const Func &source,
const std::vector<std::pair<Expr, Expr>> &bounds);
template <typename T>
inline NO_INLINE Func repeat_edge(const T &func_like) {
std::vector<std::pair<Expr, Expr>> object_bounds;
for (int i = 0; i < func_like.dimensions(); i++) {
object_bounds.push_back({ Expr(func_like.dim(i).min()), Expr(func_like.dim(i).extent()) });
}
return repeat_edge(Internal::func_like_to_func(func_like), object_bounds);
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func repeat_edge(const T &func_like, Bounds&&... bounds) {
std::vector<std::pair<Expr, Expr>> collected_bounds;
::Halide::Internal::collect_paired_args(collected_bounds, std::forward<Bounds>(bounds)...);
return repeat_edge(Internal::func_like_to_func(func_like), collected_bounds);
}
EXPORT Func repeat_image(const Func &source,
const std::vector<std::pair<Expr, Expr>> &bounds);
template <typename T>
inline NO_INLINE Func repeat_image(const T &func_like) {
std::vector<std::pair<Expr, Expr>> object_bounds;
for (int i = 0; i < func_like.dimensions(); i++) {
object_bounds.push_back({ Expr(func_like.dim(i).min()), Expr(func_like.dim(i).extent()) });
}
return repeat_image(Internal::func_like_to_func(func_like), object_bounds);
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func repeat_image(const T &func_like, Bounds&&... bounds) {
std::vector<std::pair<Expr, Expr>> collected_bounds;
::Halide::Internal::collect_paired_args(collected_bounds, std::forward<Bounds>(bounds)...);
return repeat_image(Internal::func_like_to_func(func_like), collected_bounds);
}
EXPORT Func mirror_image(const Func &source,
const std::vector<std::pair<Expr, Expr>> &bounds);
template <typename T>
inline NO_INLINE Func mirror_image(const T &func_like) {
std::vector<std::pair<Expr, Expr>> object_bounds;
for (int i = 0; i < func_like.dimensions(); i++) {
object_bounds.push_back({ Expr(func_like.dim(i).min()), Expr(func_like.dim(i).extent()) });
}
return mirror_image(Internal::func_like_to_func(func_like), object_bounds);
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func mirror_image(const T &func_like, Bounds&&... bounds) {
std::vector<std::pair<Expr, Expr>> collected_bounds;
::Halide::Internal::collect_paired_args(collected_bounds, std::forward<Bounds>(bounds)...);
return mirror_image(Internal::func_like_to_func(func_like), collected_bounds);
}
EXPORT Func mirror_interior(const Func &source,
const std::vector<std::pair<Expr, Expr>> &bounds);
template <typename T>
inline NO_INLINE Func mirror_interior(const T &func_like) {
std::vector<std::pair<Expr, Expr>> object_bounds;
for (int i = 0; i < func_like.dimensions(); i++) {
object_bounds.push_back({ Expr(func_like.dim(i).min()), Expr(func_like.dim(i).extent()) });
}
return mirror_interior(Internal::func_like_to_func(func_like), object_bounds);
}
template <typename T, typename ...Bounds,
typename std::enable_if<Halide::Internal::all_are_convertible<Expr, Bounds...>::value>::type* = nullptr>
inline NO_INLINE Func mirror_interior(const T &func_like, Bounds&&... bounds) {
std::vector<std::pair<Expr, Expr>> collected_bounds;
::Halide::Internal::collect_paired_args(collected_bounds, std::forward<Bounds>(bounds)...);
return mirror_interior(Internal::func_like_to_func(func_like), collected_bounds);
}
}
}
#endif