|
1 | | -# quickr (development version) |
| 1 | +# quickr 0.3.0 |
2 | 2 |
|
3 | | -- Added support for `as.integer()` coercion from `double`, `logical`, and |
4 | | - `integer` values (with `double` truncating towards 0). |
| 3 | +This release adds major new support for linear algebra, local functions, |
| 4 | +`sapply()`, and OpenMP parallelism, along with a broad round of reliability, |
| 5 | +compatibility, and compiler/runtime improvements. |
5 | 6 |
|
6 | | -- Added initial matrix/linear algebra handler support from base R, using the |
7 | | - same BLAS/LAPACK as R: `%*%`, `t()`, `crossprod()`, `tcrossprod()`, |
8 | | - `outer()` (with `FUN="*"`), `%o%`, `forwardsolve()`, `backsolve()`, `diag()`, |
9 | | - `t()`, `chol()`, `chol2inv()`, `solve()`, and `qr.solve()`. This includes |
10 | | - support for: |
| 7 | +## Major new features |
11 | 8 |
|
12 | | - - `drop()` for rank 0-2 inputs (including singleton matrices). |
13 | | - - `svd()` results via `$d`, `$u`, and `$v` (either from `s <- svd(x)` or |
14 | | - directly from `svd(x)$d`/`$u`/`$v`). |
15 | | - - `.Machine$double.eps`. |
16 | | - - `qr.solve()` using the LINPACK QR path (for better compatibility with |
17 | | - base R behavior). |
18 | | - |
19 | | - The plan is to add more functions in the future (#77, #79 @mns-nordicals) |
20 | | - |
21 | | -- Added support for `cbind()` and `rbind()` for rank-0/1/2 inputs, with scalar |
22 | | - recycling only and strict length checks for non-scalar inputs. |
23 | | - |
24 | | -- On macOS, quickr will use LLVM flang (`flang-new`) for compilation when |
25 | | - available (e.g. `brew install flang`). This is optional and can be disabled |
26 | | - with `options(quickr.prefer_flang = FALSE)`. |
| 9 | +### Matrix and linear algebra support |
27 | 10 |
|
28 | | -- Added OpenMP parallelization via `declare(parallel())`/`declare(omp())` for |
29 | | - `for` loops and `sapply()` calls. |
| 11 | +- Added initial matrix / linear algebra support from base R, using the same |
| 12 | + BLAS/LAPACK as R. Supported operations now include `%*%`, `t()`, |
| 13 | + `crossprod()`, `tcrossprod()`, `outer()` with `FUN = "*"`, `%o%`, |
| 14 | + `forwardsolve()`, `backsolve()`, `diag()`, `chol()`, `chol2inv()`, |
| 15 | + `solve()`, and `qr.solve()`. (#77, #79, @mns-nordicals) |
30 | 16 |
|
31 | | -- Added support for throwing errors with `stop()`. (#86) |
| 17 | +- This also adds support for: |
32 | 18 |
|
33 | | -- Added support for `abs()` in size expressions used by `declare(type(...))` |
34 | | - (e.g. `declare(type(x = integer(abs(end - start) + 1L)))`). |
35 | | - |
36 | | -- Improved `for (... in <iterable>)` lowering, including value iteration |
37 | | - (`for (v in x)`) and support for `rev()` wrappers on supported iterables. |
38 | | - |
39 | | -- Added support for `tanh()` as a unary intrinsic and `rev()` for reversing |
40 | | - rank-0/1 vectors (including bind(c) logicals, preserving `NA` storage where |
41 | | - possible). |
42 | | - |
43 | | -- Added nested compilation scopes with local declaration emission, enabling |
44 | | - block-scoped temporaries (Fortran 2008 `block ... end block`) and local |
45 | | - closures (lowered to internal procedures under `contains`), including `sapply()` |
46 | | - lowering with host association for captures and support for `simplify = "array"` for |
47 | | - higher-rank outputs. Examples: |
| 19 | + - `drop()` for rank 0-2 inputs, including singleton matrices. |
| 20 | + - `svd()` results via `$d`, `$u`, and `$v`, whether accessed from |
| 21 | + `s <- svd(x)` or directly as `svd(x)$d`, `svd(x)$u`, or `svd(x)$v`. |
| 22 | + - `.Machine$double.eps`. |
48 | 23 |
|
49 | | - - Block-scoped temporary for expression subscripting: |
| 24 | +### Local closures and `sapply()` |
50 | 25 |
|
51 | | - ```r |
52 | | - out[1] <- ifelse((x > 0.0)[2, 3], 1.0, 0.0) |
53 | | - ``` |
| 26 | +- Added support for local closures inside compiled functions, including |
| 27 | + `sapply()` lowering with host association for captures and support for |
| 28 | + `simplify = "array"` for higher-rank outputs. |
54 | 29 |
|
55 | | - - Local closure + `sapply()` lowering: |
| 30 | +- Example: |
56 | 31 |
|
57 | | - ```r |
58 | | - f <- function(i) x[i] + 1.0 |
59 | | - out <- sapply(seq_along(out), f) |
60 | | - ``` |
| 32 | + ```r |
| 33 | + f <- function(i) x[i] + 1.0 |
| 34 | + out <- sapply(seq_along(out), f) |
| 35 | + ``` |
61 | 36 |
|
62 | | - This lowering matches R’s “copy-on-modify" semantics: modifications to the variables from the parent scope trigger a copy in the local closure scope. |
| 37 | +* This lowering matches R’s copy-on-modify semantics: modifying variables from |
| 38 | + the parent scope triggers a copy in the local closure scope. |
63 | 39 |
|
64 | | -- Added support for superassignment (`<<-`) inside local closures (lowered to internal procedures) to explicitly mutate variables in the enclosing quick function scope, including `x[i] <<- ...` subset targets. Example: |
| 40 | +* Added support for superassignment (`<<-`) inside local closures, including |
| 41 | + subset targets such as `x[i] <<- ...`, to explicitly mutate variables in the |
| 42 | + enclosing quick function scope. For example: |
65 | 43 |
|
66 | 44 | ```r |
67 | 45 | apply_boundary_conditions <- function() { |
|
74 | 52 | apply_boundary_conditions() |
75 | 53 | ``` |
76 | 54 |
|
77 | | -- Added support for `array(data=..., dim=...)` for shape construction in |
78 | | - user code and tests. |
| 55 | +* Local closures also support optional arguments with `NULL` defaults, |
| 56 | + with validation to ensure optional arguments are initialized via `is.null()` |
| 57 | + before use. |
79 | 58 |
|
80 | | -- Added extensive tests + snapshots for local closures, `sapply()`, |
81 | | - block-scoped temporaries, and package compilation behavior (internal procedure |
82 | | - name collisions). |
| 59 | +### Parallel execution |
83 | 60 |
|
84 | | -- Lowered the minimum supported R version to 4.3.0 and added a backport of |
85 | | - `declare()` for R < 4.4.0 (#67). |
| 61 | +* Added OpenMP parallelization via `declare(parallel())` / `declare(omp())` |
| 62 | + for supported `for` loops and `sapply()` calls. |
86 | 63 |
|
87 | | -- Fixed `[` subsetting scalars with both `drop=TRUE` and `drop=FALSE`, simplifying |
88 | | - to Fortran scalars so subsetted scalars in reductions (e.g., `min(m[1, 1], m[2, 1])`) |
89 | | - no longer emit `minval` on scalars (#64). |
| 64 | +### Binding and iteration |
90 | 65 |
|
91 | | -- Fixed nested scalar `min()`/`max()` in reductions, so clamp-style expressions |
92 | | - like `min(max(x[i], lo), hi)` work reliably. |
| 66 | +* Added support for `cbind()` and `rbind()` for rank-0/1/2 inputs, with scalar |
| 67 | + recycling only and strict length checks for non-scalar inputs. |
93 | 68 |
|
94 | | -- Fixed an issue where subsetting logical arrays could fail when compiling quick |
95 | | - functions, e.g. `(x > 0)[2, 3]` (#68). |
| 69 | +* Improved lowering for `for (... in <iterable>)`, including value iteration |
| 70 | + such as `for (v in x)`, and support for `rev()` wrappers on supported |
| 71 | + iterables. |
96 | 72 |
|
97 | | -- Fixed a crash when compiling chained / fall-through assignments like |
98 | | - `a <- b <- 1` (#60). |
| 73 | +## Language and runtime additions |
99 | 74 |
|
100 | | -- `quick()` now supports dotted symbols (e.g. `foo.bar`) for arguments, locals, |
101 | | - and loop variables. Conflicting names that map to the same Fortran symbol now |
102 | | - error (Fortran is case-insensitive). |
| 75 | +* Added support for throwing errors with `stop()`. (#86) |
103 | 76 |
|
104 | | -- Fixed C bridge size checks for dotted argument names used in |
105 | | - `declare(type(...))` size expressions (e.g. `type(x = double(foo.bar))`). |
| 77 | +* Added support for `as.integer()` coercion from `double`, `logical`, and |
| 78 | + `integer` values. `double` inputs are truncated toward 0. |
106 | 79 |
|
107 | | -- `quick()` now gives a helpful error message when a function argument is used |
108 | | - without being declared |
109 | | - (i.e. missing `declare(type(arg = ...))`). |
| 80 | +* Added support for `tanh()` as a unary intrinsic. |
110 | 81 |
|
111 | | -- Fixed an error in invalid subscript arity reporting, e.g. `x[1, 2, 3]` on a |
112 | | - matrix now errors cleanly instead of failing while formatting the message. |
| 82 | +* Added support for `rev()` for reversing rank-0/1 vectors, including bind(c) |
| 83 | + logicals, preserving `NA` storage where possible. |
113 | 84 |
|
114 | | -- Vector-matrix recycling in arithmetic is now restricted to recycling |
115 | | - along the first axes only. |
| 85 | +* Added support for `abs()` in size expressions used by `declare(type(...))`, |
| 86 | + for example: |
| 87 | + `declare(type(x = integer(abs(end - start) + 1L)))`. |
116 | 88 |
|
117 | | -- Local closures now support optional arguments with `NULL` defaults, with |
118 | | - validation to ensure optional arguments are initialized (via `is.null()`) |
119 | | - before use. |
| 89 | +* Improved support for `array(data = ..., dim = ...)` for shape construction in |
| 90 | + user code. |
| 91 | + |
| 92 | +## Compiler and lowering improvements |
| 93 | + |
| 94 | +- quickr now supports nested compilation scopes with local declaration |
| 95 | + emission, enabling block-scoped temporaries and local closures lowered to |
| 96 | + internal procedures under `contains`. |
| 97 | + |
| 98 | + - This helps in two ways. First, in large compiled functions, declared intermediate |
| 99 | + results no longer need to stay live for the full duration of the function, |
| 100 | + which can reduce peak memory use. |
| 101 | + |
| 102 | + - Second, it improves handling of large temporaries across compilers. In |
| 103 | + particular, LLVM flang may place temporary arrays on the stack by default, |
| 104 | + which can cause problems when those temporaries are large. This work also |
| 105 | + led to better control over when temporaries need to be emitted as |
| 106 | + heap allocatable. |
| 107 | + |
| 108 | +* Example of a block-scoped temporary used for expression subscripting: |
| 109 | + |
| 110 | + ```r |
| 111 | + out[1] <- ifelse((x > 0.0)[2, 3], 1.0, 0.0) |
| 112 | + ``` |
| 113 | + |
| 114 | +## Reliability, compatibility, and diagnostics |
| 115 | + |
| 116 | +* Added extensive tests and snapshots covering local closures, `sapply()`, |
| 117 | + block-scoped temporaries, and package compilation behavior, including |
| 118 | + internal procedure name collisions. |
| 119 | + |
| 120 | +* Fixed `[` subsetting on scalars with both `drop = TRUE` and `drop = FALSE`, |
| 121 | + simplifying to Fortran scalars so subsetted scalars in reductions such as |
| 122 | + `min(m[1, 1], m[2, 1])` no longer emit `minval` on scalars. (#64) |
| 123 | + |
| 124 | +* Fixed nested scalar `min()` / `max()` in reductions, so clamp-style |
| 125 | + expressions like `min(max(x[i], lo), hi)` work reliably. |
| 126 | + |
| 127 | +* Fixed an issue where subsetting logical arrays could fail when compiling |
| 128 | + quick functions, for example `(x > 0)[2, 3]`. (#68) |
| 129 | + |
| 130 | +* Fixed a crash when compiling chained or fall-through assignments such as |
| 131 | + `a <- b <- 1`. (#60) |
| 132 | + |
| 133 | +* `quick()` now supports dotted symbols such as `foo.bar` for arguments, |
| 134 | + locals, and loop variables. Conflicting names that map to the same Fortran |
| 135 | + symbol now error, since Fortran is case-insensitive. |
| 136 | + |
| 137 | +* Fixed C bridge size checks for dotted argument names used in |
| 138 | + `declare(type(...))` size expressions, for example |
| 139 | + `type(x = double(foo.bar))`. |
| 140 | + |
| 141 | +* `quick()` now gives a helpful error when a function argument is used without |
| 142 | + being declared through `declare(type(arg = ...))`. |
| 143 | + |
| 144 | +* Fixed an error in invalid subscript arity reporting, for example |
| 145 | + `x[1, 2, 3]` on a matrix now errors cleanly instead of failing while |
| 146 | + formatting the message. |
| 147 | + |
| 148 | +## Breaking changes |
| 149 | + |
| 150 | +* Vector-matrix recycling in arithmetic is now restricted to recycling along |
| 151 | + the first axes only. |
| 152 | + |
| 153 | +## Platform and toolchain |
| 154 | + |
| 155 | +* Lowered the minimum supported R version to 4.3.0 and added a backport of |
| 156 | + `declare()` for R < 4.4.0. (#67) |
| 157 | + |
| 158 | +* On macOS, quickr will use LLVM flang (`flang-new`) for compilation when |
| 159 | + available, for example after `brew install flang`. This is optional and can |
| 160 | + be disabled with `options(quickr.prefer_flang = FALSE)`. |
120 | 161 |
|
121 | 162 | # quickr 0.2.1 |
122 | 163 |
|
|
156 | 197 | - Added workaround for cases where the compiler error message might not |
157 | 198 | display correctly in RStudio. |
158 | 199 |
|
159 | | -- Improved error message when using case-sensitive variable names (#18, #36, #39) |
| 200 | +- Improved error message when using case-sensitive variable names |
| 201 | + (#18, #36, #39) |
160 | 202 |
|
161 | | -- Added `AGENTS.md` and `scripts/setup_codex.sh` to enable the ChatGPT/Codex agent |
162 | | - to run tests in a docker container configured without internet access. |
| 203 | +- Added `AGENTS.md` and `scripts/setup_codex.sh` to enable the ChatGPT/Codex |
| 204 | + agent to run tests in a docker container configured without internet access. |
163 | 205 |
|
164 | 206 |
|
165 | 207 | # quickr 0.1.0 |
|
0 commit comments