Skip to contents

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.

Usage

apply_promotion(operands, promote)

Arguments

operands

(list())
The operands, named as the primitive's graph_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>