---
title: "Operations"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
number-sections: true
vignette: >
  %\VignetteIndexEntry{Operations}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include=FALSE}
old_options <- options(
  max.print = 10, # Set the maximum number of rows to display
  width = 80 # Set the maximum number of columns to display
)
```

## Introduction

This vignette introduces the generic functions and operations supported by `dbMatrix`. 

## Loading library

```{r, message=F}
library(dbMatrix)
library(Matrix)
```

## dbMatrix generics

The table below lists the matrix operations `dbMatrix` supports. If you need
one that is missing, please open an issue on
[GitHub](https://github.com/dbverse-org/dbmatrix-r/issues).

✅ - supported
❌ - not supported

|                                   | dbSparseMatrix | dbDenseMatrix |
|-----------------------------------|----------------|---------------|
| `colSums`, `rowSums`              | ✅             | ✅            |
| `colMeans`, `rowMeans`            | ✅             | ✅            |
| `colVars`, `rowVars`              | ✅             | ✅            |
| `colSds`, `rowSds`                | ✅             | ✅            |
| `sum`, `mean`, `max`, `min`       | ✅             | ✅            |
| `range`                           | ❌             | ❌            |
| `t`                               | ✅             | ✅            |
| `[` (subsetting)                  | ✅             | ✅            |
| `head`, `tail`                    | ✅             | ✅            |
| `is.na`                           | ✅             | ✅            |
| `dim`, `nrow`, `ncol`, `dimnames` | ✅             | ✅            |
| `rownames`, `colnames`            | ✅             | ✅            |
| `writeMM`                         | ✅             | ✅            |
| `db_svd`                          | ✅             | ❌            |

Arithmetic and math functions are covered in `vignette("arithmetic")`.

`dbMatrix` skips missing values (`NA`) in all of these summaries, as if
`na.rm = TRUE`.

## dbSparse Matrix Operations

### Create test data
Let's create a sparse matrix for demonstration:

```{r}
set.seed(42)
dgc <- Matrix::rsparsematrix(100, 50, density = 0.1, rand.x = function(n) rpois(n, 5) + 1)
rownames(dgc) <- paste0("gene_", seq_len(100))
colnames(dgc) <- paste0("cell_", seq_len(50))

dplyr::glimpse(dgc)
```

```{r}
# create dbSparseMatrix from the same dgc
con <- DBI::dbConnect(duckdb::duckdb(), ":memory:")

sparse <- dbMatrix(
  value = dgc,
  con = con,
  name = "test_matrix",
  class = "dbSparseMatrix",
  overwrite = TRUE
)

# preview
# show function aims to emulate the show method for dgCMatrix
head(sparse)
```

### transpose
```{r}
dbMatrix::t(sparse)
```

### colMeans
```{r}
dbMatrix::colMeans(sparse)
```


### colSums
```{r}
dbMatrix::colSums(sparse)
```

### rowMeans
```{r}
dbMatrix::rowMeans(sparse)
```

### rowSums
```{r}
dbMatrix::rowSums(sparse)
```

### dim
```{r}
dim(sparse)

dim(dgc)
```

### Check results are equivalent
<details>
  <summary>Click to expand </summary>
  
  ```{r}
all.equal(dbMatrix::colMeans(sparse), Matrix::colMeans(dgc))

all.equal(dbMatrix::colSums(sparse), Matrix::colSums(dgc))

all.equal(dbMatrix::rowMeans(sparse), Matrix::rowMeans(dgc))

all.equal(dbMatrix::rowSums(sparse), Matrix::rowSums(dgc))
  ```
</details>


## dbDenseMatrix Operations

```{r, eval=TRUE, message=FALSE, warning=FALSE}
# Create a dense matrix directly
set.seed(42)
mat <- matrix(rnorm(100), nrow = 10, ncol = 10)
rownames(mat) <- paste0("row_", 1:10)
colnames(mat) <- paste0("col_", 1:10)

# Create dbDenseMatrix
con2 <- DBI::dbConnect(duckdb::duckdb(), ":memory:")
dense <- dbMatrix(
  value = mat,
  con = con2,
  name = "dense_matrix",
  class = "dbDenseMatrix",
  overwrite = TRUE
)

# preview
dense
```

### transpose
```{r}
dbMatrix::t(dense)
```

### colMeans
```{r}
dbMatrix::colMeans(dense)
```

### colSums
```{r}
dbMatrix::colSums(dense)
```

### rowMeans
```{r}
dbMatrix::rowMeans(dense)
```

### rowSums
```{r}
dbMatrix::rowSums(dense)
```

### mean
```{r}
dbMatrix::mean(dense)
```

### dim
```{r}
dim(dense)
```

## Cleanup
```{r}
DBI::dbDisconnect(con, shutdown = TRUE)
DBI::dbDisconnect(con2, shutdown = TRUE)
options(old_options)
```

## Session Info
```{r eval=TRUE, message=FALSE}
sessionInfo()
```
