Skip to content

Commit f22ae80

Browse files
authored
Merge pull request #87 from t-kalinowski/la-updates
Linear algebra support + stricter name/arg validation
2 parents fa7ada1 + 9e017d9 commit f22ae80

62 files changed

Lines changed: 5405 additions & 345 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This project is an R package that transpiles R functions to Fortran.
66
R -q -e 'devtools::test()'
77
```
88

9-
- To run the full `R CMD check` locally:
9+
- To run the full `R CMD check` locally (this takes a long time):
1010
```sh
1111
R -q -e 'rcmdcheck::rcmdcheck(error_on = "warning")'
1212
```
@@ -16,6 +16,17 @@ R -q -e 'rcmdcheck::rcmdcheck(error_on = "warning")'
1616
R -q -e 'devtools::test_active_file("tests/testthat/test-dims2f.R")'
1717
```
1818

19+
- To run a subset of test files:
20+
```sh
21+
R -q -e 'devtools::test(filter = "regex")'
22+
```
23+
filter arg behavior: If not `NULL`, only tests with file names matching this regular expression will be executed. Matching is performed on the file name after it's stripped of "test-" and ".R".
24+
25+
- To run full coverage and save zero-coverage JSON output:
26+
```sh
27+
R -q -e 'covr::package_coverage() -> cov; saveRDS(cov, "cov.rds"); z <- covr::zero_coverage(cov); jsonlite::toJSON(z, pretty = TRUE)'
28+
```
29+
1930
- To see the generated C and Fortran code for an R function, use `r2f()`:
2031
```sh
2132
R --no-save -q <<'EOF'
@@ -33,10 +44,13 @@ EOF
3344

3445
- Never disable or skip tests.
3546

36-
- When adding tests, prefer user-facing API tests (e.g. `expect_quick_identical()`); avoid asserting on generated Fortran/C translation strings.
47+
- When adding tests, strongly prefer tests that only excercise the public API (e.g. `expect_quick_identical()`); avoid asserting on generated Fortran/C translation strings unless explicitly asked. Avoid testing internal functions unless explicitly.
48+
49+
- When writing tests, make sure that we test both C/Fortran code generation (typically reported accuratly by covr), as well as calling the generated function (not covered by covr). Our tests must excercise the actual generated function.
50+
51+
- While troubleshooting and iterating towards a solution, you can run targeted single-file tests; After large refactors, always run the full test suite.
3752

38-
- While troubleshooting and iterating towards a solution, you can run targeted single-file tests; before committing/pushing, always run the full test suite and `rcmdcheck`.
39-
- Before finishing a task, always run the full test suite and `rcmdcheck`.
53+
- Before opening a PR, always run `rcmdcheck`.
4054

4155
- Prefer extending S7 classes with explicit properties over attaching arbitrary unchecked attributes.
4256

NEWS.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@
33
- Added initial matrix/linear algebra handler support from base R, using the
44
same BLAS/LAPACK as R: `%*%`, `t()`, `crossprod()`, `tcrossprod()`,
55
`outer()` (with `FUN="*"`), `%o%`, `forwardsolve()`, `backsolve()`, `diag()`,
6-
`t()`, `chol()`, `chol2inv()`, `solve()`, and `qr.solve()`.
6+
`t()`, `chol()`, `chol2inv()`, `solve()`, and `qr.solve()`. This includes
7+
support for:
8+
9+
- `drop()` for rank 0-2 inputs (including singleton matrices).
10+
- `svd()` results via `$d`, `$u`, and `$v` (either from `s <- svd(x)` or
11+
directly from `svd(x)$d`/`$u`/`$v`).
12+
- `.Machine$double.eps`.
13+
- `qr.solve()` using the LINPACK QR path (for better compatibility with
14+
base R behavior).
715

816
The plan is to add more functions in the future (#77, #79 @mns-nordicals)
917

@@ -79,6 +87,27 @@
7987
- Fixed a crash when compiling chained / fall-through assignments like
8088
`a <- b <- 1` (#60).
8189
90+
- `quick()` now supports dotted symbols (e.g. `foo.bar`) for arguments, locals,
91+
and loop variables. Conflicting names that map to the same Fortran symbol now
92+
error (Fortran is case-insensitive).
93+
94+
- Fixed C bridge size checks for dotted argument names used in
95+
`declare(type(...))` size expressions (e.g. `type(x = double(foo.bar))`).
96+
97+
- `quick()` now gives a helpful error message when a function argument is used
98+
without being declared
99+
(i.e. missing `declare(type(arg = ...))`).
100+
101+
- Fixed an error in invalid subscript arity reporting, e.g. `x[1, 2, 3]` on a
102+
matrix now errors cleanly instead of failing while formatting the message.
103+
104+
- Vector-matrix recycling in arithmetic is now restricted to recycling
105+
along the first axes only.
106+
107+
- Local closures now support optional arguments with `NULL` defaults, with
108+
validation to ensure optional arguments are initialized (via `is.null()`)
109+
before use.
110+
82111
# quickr 0.2.1
83112
84113
- Added support for `!` and unary `-` and `+` (#49, @mns-nordicals)

R/aaa-utils.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,42 @@ NULL
66

77
`%||%` <- function(x, y) if (is.null(x)) y else x
88

9+
fortranize_name <- function(name, prefix = "v_") {
10+
stopifnot(is_string(name), is_string(prefix), nzchar(prefix))
11+
out <- gsub("[^A-Za-z0-9_]", "_", name)
12+
if (!nzchar(out) || !grepl("^[A-Za-z]", out)) {
13+
out <- paste0(prefix, out)
14+
}
15+
out
16+
}
17+
18+
fortranize_expr_symbols <- function(expr) {
19+
if (!is.symbol(expr) && !is.call(expr)) {
20+
return(expr)
21+
}
22+
syms <- all.vars(expr)
23+
if (!length(syms)) {
24+
return(expr)
25+
}
26+
replacements <- setNames(
27+
lapply(syms, \(sym) as.symbol(fortranize_name(sym))),
28+
syms
29+
)
30+
substitute_(expr, list2env(replacements, parent = emptyenv()))
31+
}
32+
33+
scope_fortran_symbol <- function(sym, scope) {
34+
stopifnot(is.symbol(sym))
35+
if (is.null(scope)) {
36+
return(sym)
37+
}
38+
var <- get0(as.character(sym), scope)
39+
if (inherits(var, Variable) && !is.null(var@name)) {
40+
return(as.symbol(var@name))
41+
}
42+
sym
43+
}
44+
945
quickr_r_cmd <- function(
1046
os_type = .Platform$OS.type,
1147
r_home = R.home,

0 commit comments

Comments
 (0)