Applies a promotion rule to the operands of a primitive, inside the primitive's own body.
A primitive promotes nothing on its own: an R value among its operands would
materialize at its own default, so whether a call worked would depend on
whether the array it met happened to be at that default. A primitive whose
operands must agree says so with this, on the same list it goes on to hand
graph_desc_add():
function(lhs, rhs) {
operands <- apply_promotion(list(lhs = lhs, rhs = rhs), promotion_rdata_common())
graph_desc_add(self, operands, infer_fn = infer_fn)[[1L]]
}promotion_rdata_common() is the rule for it: an operand that has a data type
keeps it, and an R value takes the one the others have, within its own category.
That is what makes prim_mul(x_f64, 2) work whatever x's data type is,
while keeping a primitive from widening the array it was handed – promotion
across categories is the nv_* layer's job.
Arguments
- operands
(
list())
The operands, named as the primitive'sgraph_desc_add()call names them.- promote
(
function)
The rule to apply; see promotion_rule.
Value
(list())operands, each materialized at the data type the rule named for it.
Details
Pass only the operands that must agree, and name them as the
graph_desc_add() call names them. prim_ifelse() promotes its two
branches and leaves pred a bool; prim_scatter() promotes x and
update and leaves the indices alone. A primitive with one arrayish operand,
or with deliberately heterogeneous ones (prim_sort()'s payload,
prim_while()'s loop state), calls this not at all.
Call it before the body uses the operands for anything else, so it sees
settled data types throughout: prim_reduce() reads dtype(init) to trace
its reductor and prim_scatter() builds its update computation's parameter
slots from peek_dtype(), both before recording a call.
It is idempotent: once every operand is at the data type the rule names, materializing them again changes nothing.
Examples
# an R value takes the data type of the operand it meets
operands <- apply_promotion(list(lhs = nv_scalar(1, "f64"), rhs = 2), promotion_rdata_common())
dtype(operands$rhs)
#> <f64>