1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | |
20 | /*! |
21 | * \file unary.cc |
22 | * \brief Unary operators. |
23 | */ |
24 | #include <tvm/relay/attrs/transform.h> |
25 | #include <tvm/relay/expr.h> |
26 | #include <tvm/relay/op.h> |
27 | #include <tvm/topi/elemwise.h> |
28 | #include <tvm/topi/transform.h> |
29 | |
30 | #include "../make_op.h" |
31 | #include "../op_common.h" |
32 | #include "../type_relations.h" |
33 | |
34 | namespace tvm { |
35 | namespace relay { |
36 | |
37 | #define RELAY_UNARY_COMPUTE(FTOPI) \ |
38 | [](const Attrs& attrs, const Array<te::Tensor>& inputs, \ |
39 | const Type& out_type) -> Array<te::Tensor> { return {FTOPI(inputs[0])}; } |
40 | |
41 | RELAY_REGISTER_UNARY_OP("log" ) |
42 | .describe(R"code(Returns the log input array, computed element-wise. |
43 | |
44 | .. math:: |
45 | log(x) |
46 | |
47 | )code" TVM_ADD_FILELINE) |
48 | .set_support_level(1) |
49 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::log)); |
50 | |
51 | RELAY_REGISTER_UNARY_OP("log2" ) |
52 | .describe(R"code(Returns the log to base 2 of input array, computed element-wise. |
53 | |
54 | .. math:: |
55 | log2(x) |
56 | |
57 | )code" TVM_ADD_FILELINE) |
58 | .set_support_level(1) |
59 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::log2)); |
60 | |
61 | RELAY_REGISTER_UNARY_OP("log10" ) |
62 | .describe(R"code(Returns the log to base 10 of input array, computed element-wise. |
63 | |
64 | .. math:: |
65 | log10(x) |
66 | |
67 | )code" TVM_ADD_FILELINE) |
68 | .set_support_level(1) |
69 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::log10)); |
70 | |
71 | RELAY_REGISTER_UNARY_OP("tan" ) |
72 | .describe(R"code(Returns the tan of input array, computed element-wise. |
73 | |
74 | .. math:: |
75 | Y = tan(X) |
76 | |
77 | )code" TVM_ADD_FILELINE) |
78 | .set_support_level(1) |
79 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::tan)); |
80 | |
81 | RELAY_REGISTER_UNARY_OP("cos" ) |
82 | .describe(R"code(Returns the cos of input array, computed element-wise. |
83 | |
84 | .. math:: |
85 | Y = cos(X) |
86 | |
87 | )code" TVM_ADD_FILELINE) |
88 | .set_support_level(1) |
89 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::cos)); |
90 | |
91 | RELAY_REGISTER_UNARY_OP("cosh" ) |
92 | .describe(R"code(Returns the cosh of input array, computed element-wise. |
93 | |
94 | .. math:: |
95 | Y = cosh(X) |
96 | |
97 | )code" TVM_ADD_FILELINE) |
98 | .set_support_level(1) |
99 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::cosh)); |
100 | |
101 | RELAY_REGISTER_UNARY_OP("sin" ) |
102 | .describe(R"code(Returns the sin of input array, computed element-wise. |
103 | |
104 | .. math:: |
105 | Y = sin(X) |
106 | |
107 | )code" TVM_ADD_FILELINE) |
108 | .set_support_level(1) |
109 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::sin)); |
110 | |
111 | RELAY_REGISTER_UNARY_OP("sinh" ) |
112 | .describe(R"code(Returns the sinh of input array, computed element-wise. |
113 | |
114 | .. math:: |
115 | Y = sinh(X) |
116 | |
117 | )code" TVM_ADD_FILELINE) |
118 | .set_support_level(1) |
119 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::sinh)); |
120 | |
121 | RELAY_REGISTER_UNARY_OP("acos" ) |
122 | .describe(R"code(Returns the acos of input array, computed element-wise. |
123 | |
124 | .. math:: |
125 | Y = acos(X) |
126 | |
127 | )code" TVM_ADD_FILELINE) |
128 | .set_support_level(1) |
129 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::acos)); |
130 | |
131 | RELAY_REGISTER_UNARY_OP("acosh" ) |
132 | .describe(R"code(Returns the acosh of input array, computed element-wise. |
133 | |
134 | .. math:: |
135 | Y = acosh(X) |
136 | |
137 | )code" TVM_ADD_FILELINE) |
138 | .set_support_level(1) |
139 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::acosh)); |
140 | |
141 | RELAY_REGISTER_UNARY_OP("asin" ) |
142 | .describe(R"code(Returns the asin of input array, computed element-wise. |
143 | |
144 | .. math:: |
145 | Y = asin(X) |
146 | |
147 | )code" TVM_ADD_FILELINE) |
148 | .set_support_level(1) |
149 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::asin)); |
150 | |
151 | RELAY_REGISTER_UNARY_OP("asinh" ) |
152 | .describe(R"code(Returns the asinh of input array, computed element-wise. |
153 | |
154 | .. math:: |
155 | Y = asinh(X) |
156 | |
157 | )code" TVM_ADD_FILELINE) |
158 | .set_support_level(1) |
159 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::asinh)); |
160 | |
161 | RELAY_REGISTER_UNARY_OP("atan" ) |
162 | .describe(R"code(Returns the atan of input array, computed element-wise. |
163 | |
164 | .. math:: |
165 | Y = atan(X) |
166 | |
167 | )code" TVM_ADD_FILELINE) |
168 | .set_support_level(1) |
169 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::atan)); |
170 | |
171 | RELAY_REGISTER_UNARY_OP("atanh" ) |
172 | .describe(R"code(Returns the atanh of input array, computed element-wise. |
173 | |
174 | .. math:: |
175 | Y = atanh(X) |
176 | |
177 | )code" TVM_ADD_FILELINE) |
178 | .set_support_level(1) |
179 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::atanh)); |
180 | |
181 | RELAY_REGISTER_UNARY_OP("exp" ) |
182 | .describe(R"code(Returns the exp input array, computed element-wise. |
183 | |
184 | .. math:: |
185 | \exp(x) |
186 | |
187 | )code" TVM_ADD_FILELINE) |
188 | .set_support_level(1) |
189 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::exp)); |
190 | |
191 | RELAY_REGISTER_UNARY_OP("fast_exp" ) |
192 | .describe(R"code(Returns the fast_exp input array, computed element-wise. |
193 | |
194 | .. math:: |
195 | \fast_exp(x) |
196 | |
197 | )code" TVM_ADD_FILELINE) |
198 | .set_support_level(1) |
199 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::fast_exp)); |
200 | |
201 | RELAY_REGISTER_UNARY_OP("erf" ) |
202 | .describe(R"code(Returns the error function value for input array, computed element-wise. |
203 | |
204 | .. math:: |
205 | \erf(x) |
206 | |
207 | )code" TVM_ADD_FILELINE) |
208 | .set_support_level(1) |
209 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::erf)); |
210 | |
211 | RELAY_REGISTER_UNARY_OP("fast_erf" ) |
212 | .describe(R"code(Returns the error function value for input array, computed element-wise. |
213 | |
214 | .. math:: |
215 | \fast_erf(x) |
216 | |
217 | )code" TVM_ADD_FILELINE) |
218 | .set_support_level(1) |
219 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::fast_erf)); |
220 | |
221 | RELAY_REGISTER_UNARY_OP("sqrt" ) |
222 | .describe(R"code(Returns the sqrt input array, computed element-wise. |
223 | |
224 | .. math:: |
225 | sqrt(x) |
226 | |
227 | )code" TVM_ADD_FILELINE) |
228 | .set_support_level(1) |
229 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::sqrt)); |
230 | |
231 | RELAY_REGISTER_UNARY_OP("rsqrt" ) |
232 | .describe(R"code(Returns the rsqrt input array, computed element-wise. |
233 | |
234 | .. math:: |
235 | 1/sqrt(x) |
236 | |
237 | )code" TVM_ADD_FILELINE) |
238 | .set_support_level(1) |
239 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::rsqrt)); |
240 | |
241 | RELAY_REGISTER_UNARY_OP("zeros_like" ) |
242 | .describe(R"code(Returns an array of zeros, with same type and shape as the input. |
243 | )code" TVM_ADD_FILELINE) |
244 | .set_support_level(4); |
245 | |
246 | RELAY_REGISTER_UNARY_OP("ones_like" ) |
247 | .describe(R"code(Returns an array of ones, with same type and shape as the input. |
248 | )code" TVM_ADD_FILELINE) |
249 | .set_support_level(4); |
250 | |
251 | RELAY_REGISTER_UNARY_OP("sigmoid" ) |
252 | .describe(R"code(Returns the sigmoid input array, computed element-wise. |
253 | |
254 | .. math:: |
255 | sigmoid(x) |
256 | |
257 | )code" TVM_ADD_FILELINE) |
258 | .set_support_level(1) |
259 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::sigmoid)); |
260 | |
261 | RELAY_REGISTER_UNARY_OP("copy" ) |
262 | .describe(R"code(Copy a tensor. |
263 | )code" TVM_ADD_FILELINE) |
264 | .set_support_level(3) |
265 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::identity)); |
266 | |
267 | // relay.clip |
268 | TVM_REGISTER_NODE_TYPE(ClipAttrs); |
269 | |
270 | Expr MakeClip(Expr a, double a_min, double a_max) { |
271 | auto attrs = make_object<ClipAttrs>(); |
272 | attrs->a_min = a_min; |
273 | attrs->a_max = a_max; |
274 | static const Op& op = Op::Get("clip" ); |
275 | return Call(op, {a}, Attrs(attrs), {}); |
276 | } |
277 | |
278 | TVM_REGISTER_GLOBAL("relay.op._make.clip" ).set_body_typed(MakeClip); |
279 | |
280 | RELAY_REGISTER_OP("clip" ) |
281 | .describe(R"code(Clip tensor values. |
282 | This function takes a tensor, a minimum value `a_min`, and a maximum value `a_max`, and returns a clipped tensor where all values below `a_min` are set to `a_min` and all values above `a_max` are set to `a_max`. `a_min` and `a_max` are cast to the tensor's dtype. |
283 | )code" TVM_ADD_FILELINE) |
284 | .set_num_inputs(1) |
285 | .add_argument("data" , "Tensor" , "The input tensor." ) |
286 | .add_type_rel("Identity" , IdentityRel) |
287 | .set_attr<TOpPattern>("TOpPattern" , kElemWise) |
288 | .set_attr<TOpIsStateful>("TOpIsStateful" , false) |
289 | .set_attr<FInferCorrectLayout>("FInferCorrectLayout" , ElemwiseArbitraryLayout) |
290 | .set_attrs_type<ClipAttrs>() |
291 | .set_support_level(3); |
292 | |
293 | // relay.fixed_point_multiply |
294 | TVM_REGISTER_NODE_TYPE(FixedPointMultiplyAttrs); |
295 | |
296 | TVM_REGISTER_GLOBAL("relay.op._make.fixed_point_multiply" ) |
297 | .set_body_typed([](Expr a, int32_t multiplier, int32_t shift) { |
298 | auto attrs = make_object<FixedPointMultiplyAttrs>(); |
299 | attrs->multiplier = multiplier; |
300 | attrs->shift = shift; |
301 | static const Op& op = Op::Get("fixed_point_multiply" ); |
302 | return Call(op, {a}, Attrs(attrs), {}); |
303 | }); |
304 | |
305 | RELAY_REGISTER_OP("fixed_point_multiply" ) |
306 | .describe(R"code(fixed point multiplication)code" TVM_ADD_FILELINE) |
307 | .set_num_inputs(1) |
308 | .add_argument("data" , "Tensor" , "The input tensor." ) |
309 | .add_type_rel("Identity" , IdentityRel) |
310 | .set_attr<TOpPattern>("TOpPattern" , kElemWise) |
311 | .set_attr<TOpIsStateful>("TOpIsStateful" , false) |
312 | .set_attr<FInferCorrectLayout>("FInferCorrectLayout" , ElemwiseArbitraryLayout) |
313 | .set_attrs_type<FixedPointMultiplyAttrs>() |
314 | .set_support_level(10); |
315 | |
316 | RELAY_REGISTER_UNARY_OP("floor" ) |
317 | .describe(R"code(Returns the floor of input array, computed element-wise. |
318 | )code" TVM_ADD_FILELINE) |
319 | .set_support_level(3) |
320 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::floor)); |
321 | |
322 | RELAY_REGISTER_UNARY_OP("ceil" ) |
323 | .describe(R"code(Returns the ceil of input array, computed element-wise. |
324 | |
325 | .. math:: |
326 | ceil(x) |
327 | |
328 | )code" TVM_ADD_FILELINE) |
329 | .set_support_level(3) |
330 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::ceil)); |
331 | |
332 | RELAY_REGISTER_UNARY_OP("trunc" ) |
333 | .describe(R"code(Returns the trunc of input array, computed element-wise. |
334 | |
335 | .. math:: |
336 | trunc(x) |
337 | |
338 | )code" TVM_ADD_FILELINE) |
339 | .set_support_level(3) |
340 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::trunc)); |
341 | |
342 | RELAY_REGISTER_UNARY_OP("round" ) |
343 | .describe(R"code(Returns the round of input array, computed element-wise. |
344 | |
345 | .. math:: |
346 | round(x) |
347 | |
348 | )code" TVM_ADD_FILELINE) |
349 | .set_support_level(3) |
350 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::round)); |
351 | |
352 | RELAY_REGISTER_UNARY_OP("sign" ) |
353 | .describe(R"code(Returns the sign of input array, computed element-wise. |
354 | |
355 | .. numpy:: |
356 | sign(x) |
357 | |
358 | )code" TVM_ADD_FILELINE) |
359 | .set_support_level(3) |
360 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::sign)); |
361 | |
362 | RELAY_REGISTER_UNARY_OP("abs" ) |
363 | .describe(R"code(Returns the abs of input array, computed element-wise. |
364 | |
365 | .. math:: |
366 | abs(x) |
367 | |
368 | )code" TVM_ADD_FILELINE) |
369 | .set_support_level(3) |
370 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::abs)); |
371 | |
372 | RELAY_REGISTER_UNARY_OP("tanh" ) |
373 | .describe(R"code(Returns the tanh of input array, computed element-wise. |
374 | |
375 | .. math:: |
376 | Y = sinh(X) / cosh(X) |
377 | |
378 | )code" TVM_ADD_FILELINE) |
379 | .set_support_level(1) |
380 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::tanh)); |
381 | |
382 | RELAY_REGISTER_UNARY_OP("fast_tanh" ) |
383 | .describe(R"code(Returns the fast_tanh of input array, computed element-wise. |
384 | |
385 | .. math:: |
386 | Y = sinh(X) / cosh(X) |
387 | |
388 | )code" TVM_ADD_FILELINE) |
389 | .set_support_level(1) |
390 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::fast_tanh)); |
391 | |
392 | RELAY_REGISTER_UNARY_OP("negative" ) |
393 | .describe(R"code(Returns the numeric negative of input array, computed element-wise. |
394 | |
395 | .. math:: |
396 | -(x) |
397 | |
398 | )code" TVM_ADD_FILELINE) |
399 | .set_support_level(3) |
400 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::negative)); |
401 | |
402 | RELAY_REGISTER_UNARY_OP("logical_not" ) |
403 | .describe(R"code(Returns the logical inverse of input array, computed element-wise. |
404 | |
405 | .. math:: |
406 | !(x) |
407 | |
408 | )code" TVM_ADD_FILELINE) |
409 | .set_support_level(4) |
410 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::logical_not)); |
411 | |
412 | RELAY_REGISTER_UNARY_OP("bitwise_not" ) |
413 | .describe(R"code(Returns the bitwise inverse of input array, computed element-wise. |
414 | |
415 | .. math:: |
416 | ~(x) |
417 | |
418 | )code" TVM_ADD_FILELINE) |
419 | .set_support_level(4) |
420 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::bitwise_not)); |
421 | |
422 | Array<te::Tensor> ShapeOfCompute(const Attrs& attrs, const Array<te::Tensor>& inputs, |
423 | const Type& out_type) { |
424 | ICHECK_EQ(inputs.size(), 1); |
425 | const auto* param = attrs.as<ShapeOfAttrs>(); |
426 | ICHECK(param != nullptr); |
427 | return {topi::shape(inputs[0], param->dtype)}; |
428 | } |
429 | |
430 | Expr MakeShapeOf(Expr data, DataType dtype) { |
431 | auto attrs = make_object<ShapeOfAttrs>(); |
432 | attrs->dtype = dtype; |
433 | static const Op& op = Op::Get("shape_of" ); |
434 | return Call(op, {data}, Attrs(attrs), {}); |
435 | } |
436 | |
437 | TVM_REGISTER_GLOBAL("relay.op._make.shape_of" ).set_body_typed(MakeShapeOf); |
438 | |
439 | RELAY_REGISTER_OP("shape_of" ) |
440 | .describe(R"code(Returns a tensor representing the shape of a tensor. |
441 | |
442 | )code" TVM_ADD_FILELINE) |
443 | .set_num_inputs(1) |
444 | .set_attrs_type<ShapeOfAttrs>() |
445 | .add_argument("data" , "Tensor" , "The input tensor." ) |
446 | .add_type_rel("ShapeOf" , ShapeOfRel) |
447 | .set_attr<TOpIsStateful>("TOpIsStateful" , false) |
448 | // Use kOpaque for shape_of op for now since it won't be performance critic, |
449 | // and it makes things easier for dynamic shape func |
450 | .set_attr<TOpPattern>("TOpPattern" , kOpaque) |
451 | .set_support_level(10) |
452 | .set_attr<FTVMCompute>("FTVMCompute" , ShapeOfCompute); |
453 | |
454 | TVM_REGISTER_NODE_TYPE(NdarraySizeAttrs); |
455 | |
456 | bool NdarraySizeRel(const Array<Type>& types, int num_inputs, const Attrs& attrs, |
457 | const TypeReporter& reporter) { |
458 | ICHECK_EQ(num_inputs, 1); |
459 | auto tt = types[0].as<TensorTypeNode>(); |
460 | |
461 | if (tt == nullptr) { |
462 | return false; |
463 | } |
464 | |
465 | const auto* param = attrs.as<NdarraySizeAttrs>(); |
466 | ICHECK(param != nullptr); |
467 | reporter->Assign(types[1], TensorType({}, param->dtype)); |
468 | return true; |
469 | } |
470 | |
471 | Array<te::Tensor> NdarraySizeCompute(const Attrs& attrs, const Array<te::Tensor>& inputs, |
472 | const Type& out_type) { |
473 | ICHECK_EQ(inputs.size(), 1); |
474 | const auto* param = attrs.as<NdarraySizeAttrs>(); |
475 | ICHECK(param != nullptr); |
476 | return Array<te::Tensor>{topi::ndarray_size(inputs[0], param->dtype)}; |
477 | } |
478 | |
479 | TVM_REGISTER_GLOBAL("relay.op._make.ndarray_size" ).set_body_typed([](Expr data, DataType dtype) { |
480 | auto attrs = make_object<NdarraySizeAttrs>(); |
481 | attrs->dtype = dtype; |
482 | static const Op& op = Op::Get("ndarray_size" ); |
483 | return Call(op, {data}, Attrs(attrs), {}); |
484 | }); |
485 | |
486 | RELAY_REGISTER_OP("ndarray_size" ) |
487 | .describe(R"code(Returns a tensor representing the number of elements of input tensor. |
488 | |
489 | )code" TVM_ADD_FILELINE) |
490 | .set_num_inputs(1) |
491 | .set_attrs_type<NdarraySizeAttrs>() |
492 | .add_argument("data" , "Tensor" , "The input tensor." ) |
493 | .add_type_rel("NdarraySize" , NdarraySizeRel) |
494 | .set_attr<TOpIsStateful>("TOpIsStateful" , false) |
495 | .set_attr<TOpPattern>("TOpPattern" , kInjective) |
496 | .set_attr<FInferCorrectLayout>("FInferCorrectLayout" , ElemwiseArbitraryLayout) |
497 | .set_support_level(10) |
498 | .set_attr<FTVMCompute>("FTVMCompute" , NdarraySizeCompute); |
499 | |
500 | RELAY_REGISTER_UNARY_OP("isnan" ) |
501 | .describe(R"code(Returns whether the input contains any NaN, computed element-wise. |
502 | .. math:: |
503 | isnan(x) |
504 | )code" TVM_ADD_FILELINE) |
505 | .set_support_level(3) |
506 | .add_type_rel("IdentityCompRel" , IdentityCompRel) |
507 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::isnan)); |
508 | |
509 | RELAY_REGISTER_UNARY_OP("isfinite" ) |
510 | .describe(R"code(Returns the finiteness of input, computed element-wise. |
511 | .. math:: |
512 | isfinite(x) |
513 | )code" TVM_ADD_FILELINE) |
514 | .set_support_level(3) |
515 | .add_type_rel("IdentityCompRel" , IdentityCompRel) |
516 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::isfinite)); |
517 | |
518 | RELAY_REGISTER_UNARY_OP("isinf" ) |
519 | .describe(R"code(Returns the infiniteness of input, computed element-wise. |
520 | .. math:: |
521 | isinf(x) |
522 | )code" TVM_ADD_FILELINE) |
523 | .set_support_level(3) |
524 | .add_type_rel("IdentityCompRel" , IdentityCompRel) |
525 | .set_attr<FTVMCompute>("FTVMCompute" , RELAY_UNARY_COMPUTE(topi::isinf)); |
526 | |
527 | } // namespace relay |
528 | } // namespace tvm |
529 | |