Skip to content

Commit 5cbad69

Browse files
committed
Updated new and readme
1 parent 4dfa4a2 commit 5cbad69

8 files changed

Lines changed: 793 additions & 29 deletions

NEWS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
- Added initial matrix/linear algebra handler support from base R, using the
44
same BLAS/LAPACK as R: `%*%`, `t()`, `crossprod()`, `tcrossprod()`,
5-
`outer()` (with `FUN="*"`), `%o%`, `forwardsolve()`, and `backsolve()`.
5+
`outer()` (with `FUN="*"`), `%o%`, `forwardsolve()`, `backsolve()`, `diag()`, `t()`, `chol()`, `chol2inv()` and `solve()`
66

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

99
- Added support for `cbind()` and `rbind()` for rank-0/1/2 inputs, with scalar
1010
recycling only and strict length checks for non-scalar inputs.

README.Rmd

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,90 @@ For example:
447447
my_fun <- quick(name = "my_fun", function(x) ....)
448448
```
449449

450+
## Basic support for matrix operations
451+
We have implemented a subset of matrix operations from base R. When you do a matrix multiplication like `A %*% B`, R calls BLAS/LAPACK functions linked to your R build. `quickr` is linked to the same BLAS/LAPACK implementation, so you can expect the same results and slightly faster computation due to lower overhead. There are multiple BLAS/LAPACK implementations, and performance therefore depends on what you have installed.
452+
453+
To illustrate the performance of matrix operations, we do a linear regression using the normal equation, which is fast but not the most numerically stable method. We compare with `RcppArmadillo`, which is a popular library for matrix operations. The `RcppArmadillo` implementation aims to match our R implementation.
454+
455+
```{r}
456+
lm <- function(X, y) {
457+
declare(
458+
type(X = double(n, k)),
459+
type(y = double(n))
460+
)
461+
462+
df <- nrow(X) - ncol(X)
463+
464+
XtX <- crossprod(X)
465+
Xty <- crossprod(X, y)
466+
coef <- solve(XtX, Xty)
467+
fit_val <- X %*% coef
468+
resid <- y - fit_val
469+
s2 <- crossprod(resid)[1]
470+
s2 <- s2 / df
471+
472+
U <- chol(XtX)
473+
XtX_inv <- chol2inv(U)
474+
std_err <- sqrt(diag(XtX_inv) * s2)
475+
476+
list(
477+
coefficients = coef,
478+
stderr = std_err,
479+
df.residual = df,
480+
fitted_values = fit_val,
481+
residuals = resid
482+
)
483+
}
484+
485+
qlm <- quick(lm)
486+
487+
Rcpp::sourceCpp(
488+
code = '#include <RcppArmadillo.h>
489+
// [[Rcpp::depends(RcppArmadillo)]]
490+
491+
// [[Rcpp::export]]
492+
Rcpp::List RcppLm(const arma::mat& X, const arma::colvec& y) {
493+
int n = X.n_rows;
494+
int k = X.n_cols;
495+
int df = n - k;
496+
497+
arma::mat XtX = arma::trans(X) * X;
498+
arma::colvec Xty = arma::trans(X) * y;
499+
arma::colvec coef = arma::solve(XtX, Xty);
500+
arma::colvec fit_val = X * coef;
501+
arma::colvec resid = y - fit_val;
502+
double s2 = arma::dot(resid, resid);
503+
s2 = s2 / df;
504+
505+
arma::mat U = arma::chol(XtX);
506+
arma::mat XtX_inv = arma::inv(arma::trimatu(U)) * arma::trans(arma::inv(arma::trimatu(U)));
507+
arma::colvec std_err = arma::sqrt(arma::diagvec(XtX_inv) * s2);
508+
509+
return Rcpp::List::create(
510+
Rcpp::Named("coefficients") = coef,
511+
Rcpp::Named("stderr") = std_err,
512+
Rcpp::Named("df.residual") = df,
513+
Rcpp::Named("fitted_values") = fit_val,
514+
Rcpp::Named("residuals") = resid
515+
);
516+
}'
517+
)
518+
519+
beta <- c(0.5, 1.0, -2.0, 10, 5)
520+
X <- cbind(1, matrix(rnorm(3 * 10^6), ncol = 4))
521+
y <- as.vector(X %*% beta + rnorm(nrow(X), sd = 2))
522+
523+
timings <- bench::mark(
524+
r = lm(X, y),
525+
quickr = qlm(X, y),
526+
RcppArmadillo = RcppLm(X, y),
527+
check = FALSE, # stderr is a vector in R and matrix in RcppArmadillo
528+
min_iterations = 30
529+
)
530+
timings
531+
532+
```
533+
450534
## Installation
451535

452536
You can install quickr from CRAN with:

0 commit comments

Comments
 (0)