Functions for materializing R values as arrays and promoting inputs.
Most commonly used via the .promote argument of as_anvl_arrays().
promotion_common() brings every input to their common data type
(common_dtype()).
R values always yield within the type category (such as float) and otherwise
contribute their default data type.
promotion_like() brings the inputs to the data type of a selected input.
If the selected input is an R value, its default data type is used.
promotion_dtype() brings the inputs to the specified data type.
promotion_rdata_common() brings the R values to the common data type, as
long as it is within their category (a double can e.g. not become an
integer).
AnvlArray inputs are left as they are and the function throws an error
if not all of them have exactly the same data type.
This rule is commonly used in primitives expecting homogenous inputs
for one or more argument subsets.
promotion_grouped() applies several rules to disjoint subsets.
promotion_rule() creates a new promotion rule.
It takes in arrayish values and outputs a list of data types, with NULL indicating
no conversion.
Usage
promotion_common(on = NULL, fallback = NULL)
promotion_like(arg, on = NULL, coerce = FALSE)
promotion_dtype(dtype, on = NULL, coerce = FALSE)
promotion_rdata_common(on = NULL)
promotion_grouped(...)
promotion_rule(fn, kind, on = NULL, ...)Arguments
- on
(
NULL|character()|numeric())
Subset of arguments to apply a rule to. Indicated either via position or argument name.- fallback
(
NULL|tengen::DataType|character(1))
The data type to settle on when every input is a bare R value, in place of the default those would materialize at on their own.NULL(default) leaves them their default.- arg
(
character(1)|numeric(1))
Which input to take the data type from: its name in theas_anvl_arrays()call, or its position. Naming it needs the call's arguments to be named.- coerce
(
logical(1))
Bring an input to the target even where that is not a promotion, instead of raising an error. Two things are refused without it: a float reaching an integer data type, which no category crosses to on its own (an R double ati32, or anf32array ati32), and narrowing a value the target cannot hold (anf64array atf32). The default isFALSE.- dtype
(
tengen::DataType|character(1))
The data type to bring the inputs to.- ...
(
PromotionRule)
The rules to apply to disjoint argument subsets.- fn
(
function)
The rule.- kind
(
character(1))
What the rule is, for printing: it shows as<{kind}>, so give it the name of the function that builds it.
Value
(function(args) -> list())
A function returning data types for those inputs to be converted and NULL for those
to be left unchanged.
Examples
promotion_common()(list(pi, nv_scalar(2L, "i64")))
#> [[1]]
#> <f32>
#>
#> [[2]]
#> <f32>
#>
promotion_common(fallback = "f64")(list(1, 2))
#> [[1]]
#> <f64>
#>
#> [[2]]
#> <f64>
#>
promotion_common(c(1, 2))(list(-3, 4, 1))
#> [[1]]
#> <f32>
#>
#> [[2]]
#> <f32>
#>
#> [[3]]
#> NULL
#>
promotion_like("x", coerce = TRUE)(list(x = nv_scalar(1, "f32"), nv_scalar(1, "f64")))
#> [[1]]
#> <f32>
#>
#> [[2]]
#> <f32>
#>
# without `coerce`, a target the input cannot hold is refused
try(promotion_like("x")(list(x = nv_scalar(1, "f32"), nv_scalar(1, "f64"))))
#> Error : Cannot bring argument 2 to data type "f32".
#> ✖ "f64" is not promotable to "f32".
#> ℹ Convert it explicitly with `nv_convert()`.
# every input at the widest float in the call, and never below f32.
widest_float <- promotion_rule(
function(args) {
widths <- vapply(args, function(a) {
dt <- peek_dtype(to_abstract(a))
if (tengen::is_dtype_float(dt)) tengen::dtype_width(dt) else 0L
}, integer(1))
rep(list(as_dtype(paste0("f", max(c(32L, widths))))), length(args))
},
"widest_float"
)
widest_float
#> <widest_float>
as_anvl_arrays(nv_array(1L), 2.5, nv_array(1, dtype = "f64"), .promote = widest_float)
#> [[1]]
#> AnvlArray
#> 1
#> [ CPUf64{1} ]
#>
#> [[2]]
#> AnvlArray
#> 2.5000
#> [ CPUf64{} ]
#>
#> [[3]]
#> AnvlArray
#> 1
#> [ CPUf64{1} ]
#>