Halide
Param.h
Go to the documentation of this file.
1 #ifndef HALIDE_PARAM_H
2 #define HALIDE_PARAM_H
3 
4 #include <type_traits>
5 
6 #include "Argument.h"
7 #include "ExternFuncArgument.h"
8 #include "IR.h"
9 
10 /** \file
11  *
12  * Classes for declaring scalar parameters to halide pipelines
13  */
14 
15 namespace Halide {
16 
17 /** A scalar parameter to a halide pipeline. If you're jitting, this
18  * should be bound to an actual value of type T using the set method
19  * before you realize the function uses this. If you're statically
20  * compiling, this param should appear in the argument list. */
21 template<typename T = void>
22 class Param {
23  /** A reference-counted handle on the internal parameter object */
24  Internal::Parameter param;
25 
26  // This is a deliberately non-existent type that allows us to compile Param<>
27  // but provide less-confusing error messages if you attempt to call get<> or set<>
28  // without explicit types.
29  struct DynamicParamType;
30 
31  /** T unless T is (const) void, in which case pointer-to-useless-type.` */
32  using not_void_T = typename std::conditional<std::is_void<T>::value, DynamicParamType *, T>::type;
33 
34  void check_name() const {
35  user_assert(param.name() != "__user_context")
36  << "Param<void*>(\"__user_context\") "
37  << "is no longer used to control whether Halide functions take explicit "
38  << "user_context arguments. Use set_custom_user_context() when jitting, "
39  << "or add Target::UserContext to the Target feature set when compiling ahead of time.";
40  }
41 
42  // Must be constexpr to allow use in case clauses.
43  inline static constexpr int halide_type_code(halide_type_code_t code, int bits) {
44  return (((int)code) << 8) | bits;
45  }
46 
47  // Allow all Param<> variants friend access to each other
48  template<typename OTHER_TYPE>
49  friend class Param;
50 
51 public:
52  /** True if the Halide type is not void (or const void). */
53  static constexpr bool has_static_type = !std::is_void<T>::value;
54 
55  /** Get the Halide type of T. Callers should not use the result if
56  * has_static_halide_type is false. */
57  static Type static_type() {
59  return type_of<T>();
60  }
61 
62  /** Construct a scalar parameter of type T with a unique
63  * auto-generated name */
64  // @{
66  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
67  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
68  }
69  explicit Param(Type t)
70  : param(t, false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
71  static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
72  }
73  // @}
74 
75  /** Construct a scalar parameter of type T with the given name. */
76  // @{
77  explicit Param(const std::string &n)
78  : param(type_of<T>(), false, 0, n) {
79  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
80  check_name();
81  }
82  explicit Param(const char *n)
83  : param(type_of<T>(), false, 0, n) {
84  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
85  check_name();
86  }
87  Param(Type t, const std::string &n)
88  : param(t, false, 0, n) {
89  static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
90  check_name();
91  }
92  // @}
93 
94  /** Construct a scalar parameter of type T an initial value of
95  * 'val'. Only triggers for non-pointer types. */
96  template<typename T2 = T, typename std::enable_if<!std::is_pointer<T2>::value>::type * = nullptr>
97  explicit Param(not_void_T val)
98  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
99  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
100  set<not_void_T>(val);
101  }
102 
103  /** Construct a scalar parameter of type T with the given name
104  * and an initial value of 'val'. */
105  Param(const std::string &n, not_void_T val)
106  : param(type_of<T>(), false, 0, n) {
107  check_name();
108  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
109  set<not_void_T>(val);
110  }
111 
112  /** Construct a scalar parameter of type T with an initial value of 'val'
113  * and a given min and max. */
114  Param(not_void_T val, const Expr &min, const Expr &max)
115  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
116  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
117  set_range(min, max);
118  set<not_void_T>(val);
119  }
120 
121  /** Construct a scalar parameter of type T with the given name
122  * and an initial value of 'val' and a given min and max. */
123  Param(const std::string &n, not_void_T val, const Expr &min, const Expr &max)
124  : param(type_of<T>(), false, 0, n) {
125  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
126  check_name();
127  set_range(min, max);
128  set<not_void_T>(val);
129  }
130 
131  /** Construct a Param<void> from any other Param. */
132  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
133  Param(const Param<OTHER_TYPE> &other)
134  : param(other.param) {
135  // empty
136  }
137 
138  /** Construct a Param<non-void> from a Param with matching type.
139  * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
140  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
141  Param(const Param<OTHER_TYPE> &other)
142  : param(other.param) {
143  user_assert(other.type() == type_of<T>())
144  << "Param<" << type_of<T>() << "> cannot be constructed from a Param with type " << other.type();
145  }
146 
147  /** Copy a Param<void> from any other Param. */
148  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
150  param = other.param;
151  return *this;
152  }
153 
154  /** Copy a Param<non-void> from a Param with matching type.
155  * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
156  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
158  user_assert(other.type() == type_of<T>())
159  << "Param<" << type_of<T>() << "> cannot be copied from a Param with type " << other.type();
160  param = other.param;
161  return *this;
162  }
163 
164  /** Get the name of this parameter */
165  const std::string &name() const {
166  return param.name();
167  }
168 
169  /** Get the current value of this parameter. Only meaningful when jitting.
170  Asserts if type does not exactly match the Parameter's type. */
171  template<typename T2 = not_void_T>
173  return param.scalar<T2>();
174  }
175 
176  /** Set the current value of this parameter. Only meaningful when jitting.
177  Asserts if type is not losslessly-convertible to Parameter's type. */
178  // @{
179  template<typename SOME_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
180  HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val) {
182  << "The value " << val << " cannot be losslessly converted to type " << type();
183  param.set_scalar<T>(val);
184  }
185 
186  // Specialized version for when T = void (thus the type is only known at runtime,
187  // not compiletime). Note that this actually works fine for all Params; we specialize
188  // it just to reduce code size for the common case of T != void.
189  template<typename SOME_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
190  HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val) {
191 #define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE) \
192  case halide_type_code(CODE, BITS): \
193  user_assert(Internal::IsRoundtrippable<TYPE>::value(val)) \
194  << "The value " << val << " cannot be losslessly converted to type " << type; \
195  param.set_scalar<TYPE>(Internal::StaticCast<TYPE>::value(val)); \
196  break;
197 
198  const Type type = param.type();
199  switch (halide_type_code(type.code(), type.bits())) {
211  HALIDE_HANDLE_TYPE_DISPATCH(halide_type_handle, 64, uint64_t) // Handle types are always set via set_scalar<uint64_t>, not set_scalar<void*>
212  default:
213  internal_error << "Unsupported type in Param::set<" << type << ">\n";
214  }
215 
216 #undef HALIDE_HANDLE_TYPE_DISPATCH
217  }
218  // @}
219 
220  /** Get the halide type of the Param */
221  Type type() const {
222  return param.type();
223  }
224 
225  /** Get or set the possible range of this parameter. Use undefined
226  * Exprs to mean unbounded. */
227  // @{
228  void set_range(const Expr &min, const Expr &max) {
231  }
232 
234  if (min.defined() && min.type() != param.type()) {
235  min = Internal::Cast::make(param.type(), min);
236  }
237  param.set_min_value(min);
238  }
239 
241  if (max.defined() && max.type() != param.type()) {
242  max = Internal::Cast::make(param.type(), max);
243  }
244  param.set_max_value(max);
245  }
246 
247  Expr min_value() const {
248  return param.min_value();
249  }
250 
251  Expr max_value() const {
252  return param.max_value();
253  }
254  // @}
255 
256  template<typename SOME_TYPE>
257  void set_estimate(const SOME_TYPE &value) {
259  << "The value " << value << " cannot be losslessly converted to type " << type();
260  param.set_estimate(Expr(value));
261  }
262 
263  /** You can use this parameter as an expression in a halide
264  * function definition */
265  operator Expr() const {
266  return Internal::Variable::make(param.type(), name(), param);
267  }
268 
269  /** Using a param as the argument to an external stage treats it
270  * as an Expr */
271  operator ExternFuncArgument() const {
272  return Expr(*this);
273  }
274 
275  /** Construct the appropriate argument matching this parameter,
276  * for the purpose of generating the right type signature when
277  * statically compiling halide pipelines. */
278  operator Argument() const {
279  return Argument(name(), Argument::InputScalar, type(), 0,
280  param.get_argument_estimates());
281  }
282 
284  return param;
285  }
286 
288  return param;
289  }
290 };
291 
292 /** Returns an Expr corresponding to the user context passed to
293  * the function (if any). It is rare that this function is necessary
294  * (e.g. to pass the user context to an extern function written in C). */
296  return Internal::Variable::make(Handle(), "__user_context",
297  Internal::Parameter(Handle(), false, 0, "__user_context"));
298 }
299 
300 } // namespace Halide
301 
302 #endif
int32_t
signed __INT32_TYPE__ int32_t
Definition: runtime_internal.h:20
Halide::Internal::Cast::make
static Expr make(Type t, Expr v)
Halide::Internal::Parameter::set_scalar
HALIDE_NO_USER_CODE_INLINE void set_scalar(T val)
If the parameter is a scalar parameter, set its current value.
Definition: Parameter.h:90
Halide::Param::set
HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val)
Set the current value of this parameter.
Definition: Param.h:180
Halide::Param::has_static_type
static constexpr bool has_static_type
True if the Halide type is not void (or const void).
Definition: Param.h:53
Halide::Param::min_value
Expr min_value() const
Definition: Param.h:247
internal_assert
#define internal_assert(c)
Definition: Errors.h:19
Halide::Argument::InputScalar
@ InputScalar
Definition: Argument.h:53
halide_type_handle
@ halide_type_handle
opaque pointer type (void *)
Definition: HalideRuntime.h:407
Halide::Param::operator=
Param< T > & operator=(const Param< OTHER_TYPE > &other)
Copy a Param<void> from any other Param.
Definition: Param.h:149
Halide::Internal::Parameter::set_max_value
void set_max_value(const Expr &e)
uint8_t
unsigned __INT8_TYPE__ uint8_t
Definition: runtime_internal.h:25
Halide::Internal::Parameter::max_value
Expr max_value() const
uint16_t
unsigned __INT16_TYPE__ uint16_t
Definition: runtime_internal.h:23
Halide::Param::type
Type type() const
Get the halide type of the Param.
Definition: Param.h:221
Halide::Internal::Parameter
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:28
Halide::Internal::Parameter::min_value
Expr min_value() const
halide_type_float
@ halide_type_float
IEEE floating point numbers.
Definition: HalideRuntime.h:406
Halide::Param::name
const std::string & name() const
Get the name of this parameter.
Definition: Param.h:165
Halide::user_context_value
Expr user_context_value()
Returns an Expr corresponding to the user context passed to the function (if any).
Definition: Param.h:295
Halide::min
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:577
Halide::Internal::make_entity_name
std::string make_entity_name(void *stack_ptr, const std::string &type, char prefix)
Make a unique name for an object based on the name of the stack variable passed in.
int8_t
signed __INT8_TYPE__ int8_t
Definition: runtime_internal.h:24
Halide::Argument
A struct representing an argument to a halide-generated function.
Definition: Argument.h:37
Halide::Param::Param
Param()
Construct a scalar parameter of type T with a unique auto-generated name.
Definition: Param.h:65
Halide::Param::Param
Param(const std::string &n, not_void_T val)
Construct a scalar parameter of type T with the given name and an initial value of 'val'.
Definition: Param.h:105
IR.h
user_assert
#define user_assert(c)
Definition: Errors.h:15
Halide::Param::Param
Param(const char *n)
Definition: Param.h:82
Halide::Param::set_max_value
void set_max_value(Expr max)
Definition: Param.h:240
Halide::Param::get
HALIDE_NO_USER_CODE_INLINE T2 get() const
Get the current value of this parameter.
Definition: Param.h:172
Halide::Param::Param
Param(const std::string &n, not_void_T val, const Expr &min, const Expr &max)
Construct a scalar parameter of type T with the given name and an initial value of 'val' and a given ...
Definition: Param.h:123
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition: runtime_internal.h:19
Halide::Type
Types in the halide type system.
Definition: Type.h:269
Halide::Param::static_type
static Type static_type()
Get the Halide type of T.
Definition: Param.h:57
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AddAtomicMutex.h:21
Halide::Internal::Parameter::type
Type type() const
Get the type of this parameter.
Halide::ExternFuncArgument
An argument to an extern-defined Func.
Definition: ExternFuncArgument.h:17
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::Handle
Type Handle(int lanes=1, const halide_handle_cplusplus_type *handle_type=nullptr)
Construct a handle type.
Definition: Type.h:497
Argument.h
ExternFuncArgument.h
Halide::Internal::Parameter::set_estimate
void set_estimate(Expr e)
Halide::Param::parameter
const Internal::Parameter & parameter() const
Definition: Param.h:283
halide_type_code_t
halide_type_code_t
Types in the halide type system.
Definition: HalideRuntime.h:399
Halide::Expr::type
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
Definition: Expr.h:320
Halide::Type::bits
HALIDE_ALWAYS_INLINE int bits() const
Return the bit size of a single element of this type.
Definition: Type.h:331
Halide::Param::Param
Param(const Param< OTHER_TYPE > &other)
Construct a Param<void> from any other Param.
Definition: Param.h:133
Halide::Internal::Parameter::set_min_value
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
int64_t
signed __INT64_TYPE__ int64_t
Definition: runtime_internal.h:18
halide_type_uint
@ halide_type_uint
unsigned integers
Definition: HalideRuntime.h:405
Halide::Param::set_range
void set_range(const Expr &min, const Expr &max)
Get or set the possible range of this parameter.
Definition: Param.h:228
Halide::Param::set_min_value
void set_min_value(Expr min)
Definition: Param.h:233
HALIDE_NO_USER_CODE_INLINE
#define HALIDE_NO_USER_CODE_INLINE
Definition: Util.h:44
internal_error
#define internal_error
Definition: Errors.h:23
Halide::Param::Param
Param(not_void_T val)
Construct a scalar parameter of type T an initial value of 'val'.
Definition: Param.h:97
Halide::Internal::Parameter::get_argument_estimates
ArgumentEstimates get_argument_estimates() const
Get the ArgumentEstimates appropriate for this Parameter.
Halide::Param::Param
Param(Type t)
Definition: Param.h:69
Halide::Internal::Parameter::name
const std::string & name() const
Get the name of this parameter.
Halide::Param::set_estimate
void set_estimate(const SOME_TYPE &value)
Definition: Param.h:257
Halide::Internal::IntrusivePtr::defined
HALIDE_ALWAYS_INLINE bool defined() const
Definition: IntrusivePtr.h:156
Halide::Param::max_value
Expr max_value() const
Definition: Param.h:251
Halide::Param::Param
Param(not_void_T val, const Expr &min, const Expr &max)
Construct a scalar parameter of type T with an initial value of 'val' and a given min and max.
Definition: Param.h:114
Halide::type_of
Type type_of()
Construct the halide equivalent of a C type.
Definition: Type.h:503
Halide::Internal::IsRoundtrippable
Definition: Util.h:440
Halide::Internal::Parameter::scalar
HALIDE_NO_USER_CODE_INLINE T scalar() const
If the parameter is a scalar parameter, get its currently bound value.
Definition: Parameter.h:78
int16_t
signed __INT16_TYPE__ int16_t
Definition: runtime_internal.h:22
Halide::Expr
A fragment of Halide syntax.
Definition: Expr.h:256
Halide::Param::Param
Param(Type t, const std::string &n)
Definition: Param.h:87
halide_type_int
@ halide_type_int
signed integers
Definition: HalideRuntime.h:404
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:21
Halide::max
Expr max(const FuncRef &a, const FuncRef &b)
Definition: Func.h:580
Halide::Internal::Variable::make
static Expr make(Type type, const std::string &name)
Definition: IR.h:664
Halide::Param
A scalar parameter to a halide pipeline.
Definition: Param.h:22
Halide::Type::code
HALIDE_ALWAYS_INLINE halide_type_code_t code() const
Return the underlying data type of an element as an enum value.
Definition: Type.h:325
Halide::Param::parameter
Internal::Parameter & parameter()
Definition: Param.h:287
Halide::Param::Param
Param(const std::string &n)
Construct a scalar parameter of type T with the given name.
Definition: Param.h:77
HALIDE_HANDLE_TYPE_DISPATCH
#define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE)