# Rational record class from the S3 vector vignette new_rational <- function(n = integer(), d = integer()) { if (!is_integer(n)) { abort("`n` must be an integer.") } if (!is_integer(d)) { abort("`d` must be an integer.") } new_rcrd(list(n = n, d = d), class = "vctrs_rational") } rational <- function(n, d) { args <- vec_cast_common(n, d, .to = integer()) args <- vec_recycle_common(!!! args) new_rational(args[[1L]], args[[2L]]) } format.vctrs_rational <- function(x, ...) { n <- field(x, "n") d <- field(x, "d") out <- paste0(n, "/", d) out[is.na(n) | is.na(d)] <- NA out } vec_proxy_equal.vctrs_rational <- function(x) { n <- field(x, "n") d <- field(x, "d") gcd <- gcd(n, d) data.frame(n = n / gcd, d = d / gcd) } gcd <- function(x, y) { r <- x %% y ifelse(r, gcd(y, r), y) } vec_proxy_compare.vctrs_rational <- function(x, ...) { field(x, "n") / field(x, "d") } rational_methods <- list( vec_ptype_abbr.vctrs_rational = function(x, ...) "rtnl", vec_ptype_full.vctrs_rational = function(x, ...) "rational", vec_ptype2.vctrs_rational = function(x, y, ...) UseMethod("vec_ptype2.vctrs_rational"), vec_ptype2.vctrs_rational.vctrs_rational = function(x, y, ...) new_rational(), vec_ptype2.vctrs_rational.integer = function(x, y, ...) new_rational(), vec_ptype2.integer.vctrs_rational = function(x, y, ...) new_rational(), vec_cast.vctrs_rational = function(x, to, ...) UseMethod("vec_cast.vctrs_rational"), vec_cast.vctrs_rational.vctrs_rational = function(x, to, ...) x, vec_cast.double.vctrs_rational = function(x, to, ...) field(x, "n") / field(x, "d"), vec_cast.vctrs_rational.integer = function(x, to, ...) rational(x, 1), vec_proxy_equal.vctrs_rational = vec_proxy_equal.vctrs_rational, vec_proxy_compare.vctrs_rational = vec_proxy_compare.vctrs_rational ) local_rational_class <- function(frame = caller_env()) { local_methods(.frame = frame, !!!rational_methods) }