---
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

`dbMatrix` objects currently support several statistical matrix operations listed below with support for more coming soon.

✅  - implemented
🟧 - not yet implemented

|          | dbSparseMatrix | dbDenseMatrix |
|----------|----------------|---------------|
| colSums  | ✅             | ✅            |
| rowSums  | ✅             | ✅            |
| colMeans | ✅             | ✅            |
| rowMeans | ✅             | ✅            |
| colSds   | 🟧             | ✅            |
| rowSds   | 🟧             | ✅            |
| t        | ✅             | ✅            |
| mean     | ✅             | ✅            |
| nrow     | ✅             | ✅            |
| ncol     | ✅             | ✅            |
| dims     | ✅             | ✅            |
| head     | ✅             | ✅            |
| tail     | ✅             | ✅            |
| ...      |                |               |

## 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, memory = TRUE, names = TRUE), Matrix::colMeans(dgc))

all.equal(dbMatrix::colSums(sparse, memory = TRUE, names = TRUE), Matrix::colSums(dgc))

all.equal(dbMatrix::rowMeans(sparse, memory = TRUE, names = TRUE), Matrix::rowMeans(dgc))

all.equal(dbMatrix::rowSums(sparse, memory = TRUE, names = TRUE), 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()
```
