Skip to content

Commit f6654f4

Browse files
authored
Merge pull request t-kalinowski#85 from mns-nordicals/split-r2f.R
Split r2f.R into domain-specific handler and helper files
2 parents 7df1780 + b9d4068 commit f6654f4

19 files changed

Lines changed: 2178 additions & 2070 deletions

R/r2f-aab-core.R

Lines changed: 411 additions & 0 deletions
Large diffs are not rendered by default.

R/r2f-arithmetic.R

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# r2f-arithmetic.R
2+
# Handlers for arithmetic operators: +, -, *, /, ^, %%, %/%
3+
4+
# --- Handlers ---
5+
6+
r2f_handlers[["+"]] <- function(args, scope, ...) {
7+
# Support both binary and unary plus
8+
if (length(args) == 1L) {
9+
x <- r2f(args[[1L]], scope, ...)
10+
Fortran(glue("(+{x})"), Variable(x@value@mode, x@value@dims))
11+
} else {
12+
.[left, right] <- lapply(args, r2f, scope, ...)
13+
reshaped <- maybe_reshape_vector_matrix(left, right)
14+
left <- reshaped$left
15+
right <- reshaped$right
16+
Fortran(glue("({left} + {right})"), conform(left@value, right@value))
17+
}
18+
}
19+
20+
r2f_handlers[["-"]] <- function(args, scope, ...) {
21+
# Support both binary and unary minus
22+
if (length(args) == 1L) {
23+
x <- r2f(args[[1L]], scope, ...)
24+
Fortran(glue("(-{x})"), Variable(x@value@mode, x@value@dims))
25+
} else {
26+
.[left, right] <- lapply(args, r2f, scope, ...)
27+
reshaped <- maybe_reshape_vector_matrix(left, right)
28+
left <- reshaped$left
29+
right <- reshaped$right
30+
Fortran(glue("({left} - {right})"), conform(left@value, right@value))
31+
}
32+
}
33+
34+
r2f_handlers[["*"]] <- function(args, scope = NULL, ...) {
35+
.[left, right] <- lapply(args, r2f, scope, ...)
36+
reshaped <- maybe_reshape_vector_matrix(left, right)
37+
left <- reshaped$left
38+
right <- reshaped$right
39+
Fortran(glue("({left} * {right})"), conform(left@value, right@value))
40+
}
41+
42+
r2f_handlers[["/"]] <- function(args, scope = NULL, ...) {
43+
.[left, right] <- lapply(args, r2f, scope, ...)
44+
left <- maybe_cast_double(left)
45+
right <- maybe_cast_double(right)
46+
reshaped <- maybe_reshape_vector_matrix(left, right)
47+
left <- reshaped$left
48+
right <- reshaped$right
49+
Fortran(glue("({left} / {right})"), conform(left@value, right@value))
50+
}
51+
52+
r2f_handlers[["^"]] <- function(args, scope, ...) {
53+
.[left, right] <- lapply(args, r2f, scope, ...)
54+
reshaped <- maybe_reshape_vector_matrix(left, right)
55+
left <- reshaped$left
56+
right <- reshaped$right
57+
Fortran(glue("({left} ** {right})"), conform(left@value, right@value))
58+
}
59+
60+
61+
# ---- remainder (%%) and integer division (%/%) ----
62+
#
63+
# R semantics:
64+
# x %% y == r where r has the sign of y (divisor)
65+
# x %/% y == q where q = floor(x / y)
66+
# and x == r + y * q (within rounding error)
67+
#
68+
# Fortran intrinsics:
69+
# - MODULO(a,p) : remainder with sign(p)
70+
# - FLOOR(x) : greatest integer <= x (real)
71+
# - AINT(x) : truncation toward 0 (real)
72+
73+
r2f_handlers[["%%"]] <- function(args, scope, ...) {
74+
.[left, right] <- lapply(args, r2f, scope, ...)
75+
out_val <- conform(left@value, right@value)
76+
# MODULO gives result with sign(right) - matches R %% behaviour
77+
Fortran(glue("modulo({left}, {right})"), out_val)
78+
}
79+
80+
r2f_handlers[["%/%"]] <- function(args, scope, ...) {
81+
.[left, right] <- lapply(args, r2f, scope, ...)
82+
out_val <- conform(left@value, right@value)
83+
84+
expr <- switch(
85+
out_val@mode,
86+
integer = glue("int(floor(real({left}) / real({right})))"),
87+
double = glue("floor({left} / {right})"),
88+
stop("%/% only implemented for numeric types")
89+
)
90+
91+
Fortran(expr, out_val)
92+
}

R/r2f-coercions.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# r2f-coercions.R
2+
# Handlers for type coercions: as.double
3+
4+
# --- Handlers ---
5+
6+
r2f_handlers[["as.double"]] <- function(args, scope = NULL, ...) {
7+
stopifnot(length(args) == 1L)
8+
maybe_cast_double(r2f(args[[1]], scope, ...))
9+
}

R/r2f-conditionals.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# r2f-conditionals.R
2+
# Handlers for vectorized conditionals: ifelse
3+
4+
# --- Handlers ---
5+
6+
r2f_handlers[["ifelse"]] <- function(args, scope, ...) {
7+
.[mask, tsource, fsource] <- lapply(args, r2f, scope, ...)
8+
# (tsource, fsource, mask)
9+
mode <- tsource@value@mode
10+
dims <- conform(mask@value, tsource@value, fsource@value)@dims
11+
Fortran(glue("merge({tsource}, {fsource}, {mask})"), Variable(mode, dims))
12+
}

R/r2f-constructors.R

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# r2f-constructors.R
2+
# Handlers for value constructors: c, logical, integer, double, numeric,
3+
# character, raw, matrix, array
4+
5+
# --- Handlers ---
6+
7+
r2f_handlers[["c"]] <- function(args, scope = NULL, ...) {
8+
ff <- lapply(args, r2f, scope, ...)
9+
s <- glue("[ {str_flatten_commas(ff)} ]")
10+
lens <- lapply(ff[order(map_int(ff, \(f) f@value@rank))], function(e) {
11+
rank <- e@value@rank
12+
if (rank == 0) {
13+
1L
14+
} else if (rank == 1) {
15+
e@value@dims[[1]]
16+
} else {
17+
stop("all args passed to c() must be scalars or 1-d arrays")
18+
}
19+
})
20+
mode <- reduce_promoted_mode(ff)
21+
len <- Reduce(
22+
\(l1, l2) {
23+
if (is_scalar_na(l1) || is_scalar_na(l2)) {
24+
NA
25+
} else if (is_wholenumber(l1) && is_wholenumber(l2)) {
26+
l1 + l2
27+
} else {
28+
call("+", l1, l2)
29+
}
30+
},
31+
lens
32+
)
33+
Fortran(s, Variable(mode, list(len)))
34+
}
35+
36+
37+
register_r2f_handler(
38+
"logical",
39+
function(args, scope, ...) {
40+
Fortran(".false.", Variable(mode = "logical", dims = r2dims(args, scope)))
41+
},
42+
match_fun = FALSE
43+
)
44+
45+
register_r2f_handler(
46+
"integer",
47+
function(args, scope, ...) {
48+
Fortran("0", Variable(mode = "integer", dims = r2dims(args, scope)))
49+
},
50+
match_fun = FALSE
51+
)
52+
53+
register_r2f_handler(
54+
c("double", "numeric"),
55+
function(args, scope, ...) {
56+
Fortran("0", Variable(mode = "double", dims = r2dims(args, scope)))
57+
},
58+
match_fun = FALSE
59+
)
60+
61+
62+
r2f_handlers[["character"]] <- r2f_handlers[["raw"]] <-
63+
.r2f_handler_not_implemented_yet
64+
65+
66+
r2f_handlers[["matrix"]] <- function(args, scope = NULL, ...) {
67+
args$data %||% stop("matrix(data=) must be provided, cannot be NA")
68+
out <- r2f(args$data, scope, ...)
69+
out@value <- Variable(
70+
mode = out@value@mode,
71+
dims = r2dims(list(args$nrow, args$ncol), scope)
72+
)
73+
out
74+
75+
# TODO: reshape() if !passes_as_scalar(out)
76+
}
77+
78+
r2f_handlers[["array"]] <- function(args, scope = NULL, ...) {
79+
args$data %||% stop("array(data=) must be provided, cannot be NA")
80+
if (is.null(args$dim)) {
81+
stop("array(dim=) must be provided, cannot be NA")
82+
}
83+
if (!is.null(args$dimnames)) {
84+
stop("array(dimnames=) not supported")
85+
}
86+
87+
out <- r2f(args$data, scope, ...)
88+
if (!passes_as_scalar(out@value)) {
89+
stop("array(data=) must be a scalar for now")
90+
}
91+
92+
out@value <- Variable(
93+
mode = out@value@mode,
94+
dims = r2dims(args$dim, scope)
95+
)
96+
out
97+
}

0 commit comments

Comments
 (0)