--- title: "Matrix Wrapper Helpers" author: "Frédéric Bertrand" date: "`r format(Sys.Date())`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Matrix Wrapper Helpers} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(bigalgebra) ``` ## Overview Beyond its Level 1 vector helpers, `bigalgebra` includes wrappers around the Level 3 BLAS routines and related utilities for manipulating matrices stored in memory or as [`bigmemory::big.matrix`] objects. This vignette demonstrates the core workflows for the symmetric matrix-matrix multiply `dsymm()`, the general matrix multiply `dgemm()` and the AXPY-style updater `daxpy()`. ## Symmetric matrix products with `dsymm()` `dsymm()` mirrors the BLAS symmetric matrix-matrix multiplication kernel. It can multiply from the left or right and accepts optional leading-dimension arguments when working with non-standard strides. ```{r} A_sym <- matrix(c(2, 1, 1, 3), 2, 2) B_rhs <- diag(2) C_out <- matrix(0, 2, 2) dsymm(A = A_sym, B = B_rhs, C = C_out, SIDE = "L", UPLO = "U") C_out ``` When either input is a `big.matrix`, the wrapper performs the computation in place without materialising an intermediate R matrix. ```{r} library(bigmemory) dir.create(tmp_sym <- tempfile()) A_bm <- filebacked.big.matrix(2, 2, type = "double", backingpath = tmp_sym, backingfile = "A.bin", descriptorfile = "A.desc") A_bm[,] <- A_sym B_bm <- filebacked.big.matrix(2, 2, type = "double", backingpath = tmp_sym, backingfile = "B.bin", descriptorfile = "B.desc") B_bm[,] <- B_rhs C_bm <- filebacked.big.matrix(2, 2, type = "double", backingpath = tmp_sym, backingfile = "C.bin", descriptorfile = "C.desc") dsymm(A = A_bm, B = B_bm, C = C_bm) C_bm[] ``` ## General matrix multiplication with `dgemm()` `dgemm()` exposes the workhorse Level 3 BLAS routine that computes `C := alpha * op(A) %*% op(B) + beta * C`. All matrices can be ordinary R matrices or `big.matrix` objects, and any missing output will be created automatically. When you construct native R matrices, coerce integer literals to doubles (for example with `as.numeric()`) so they satisfy the package's double-precision requirement. ```{r} A <- matrix(as.numeric(1:6), nrow = 2) B <- matrix(seq(2, 12, by = 2), nrow = 3) C <- matrix(0, nrow = 2, ncol = 4) dgemm(TRANSA = "N", TRANSB = "N", A = A, B = B, C = C, BETA = 0) C ``` Transposed operands are also supported via `TRANSA` and `TRANSB`: ```{r} C_t <- matrix(0, nrow = 3, ncol = 3) dgemm(TRANSA = "T", TRANSB = "N", A = A, B = B, C = C_t, BETA = 0) C_t ``` ## Updating matrices with `daxpy()` `daxpy()` provides a convenient wrapper for the AXPY operation `Y := alpha * X + Y`. The helper respects the package option `bigalgebra.mixed_arithmetic_returns_R_matrix` to decide when to return a native matrix versus a `big.matrix`. ```{r} X <- matrix(1, nrow = 2, ncol = 2) Y <- matrix(c(0, 1, 2, 3), nrow = 2) daxpy(A = 0.5, X = X, Y = Y) ``` When both operands are `big.matrix` objects, the result stays on disk: ```{r} dir.create(tmp_axpy <- tempfile()) X_bm <- filebacked.big.matrix(2, 2, type = "double", backingpath = tmp_axpy, backingfile = "X.bin", descriptorfile = "X.desc") X_bm[,] <- 1 daxpy(A = 3, X = X_bm) X_bm[] ``` ```{r} unlink(file.path(tmp_sym, c("A.bin", "A.desc", "B.bin", "B.desc", "C.bin", "C.desc"))) unlink(tmp_sym, recursive = TRUE) unlink(file.path(tmp_axpy, c("X.bin", "X.desc"))) unlink(tmp_axpy, recursive = TRUE) ```