-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.qmd
102 lines (80 loc) · 3.78 KB
/
README.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
---
title: "Including multiple files in a single Rcpp chunk"
format: gfm
---
## Issues and workarounds
### First issue
If you have a habit of separating function declaration in a header file with
`.h` extension and function implementation in the eponymous `.cpp` file, then
including the `cpp` file or the `.h` file in a Rcpp code chunk will result in
failure to compile. This is because Rcpp code chunks make use of
`Rcpp::sourceCpp()` function, which only accepts a single `.cpp` file by design.
**Solution.** You should convert every pair of file (`myfile.h`, `myfile.cpp`)
into a single file (`myfile.hpp`) and then include the `.hpp` file in the Rcpp
code chunk.
### Second issue
If you have multiple files to include in a single Rcpp code chunk, then you
cannot include them directly in the Rcpp code chunk. This is because, behind the
scene, `Rcpp::sourceCpp()` creates a -- possibly temporary -- cache directory
into which it copies only the single input file provided in the `file` argument.
**Solution.** You can manually copy all the files you want to include in the
Rcpp code chunk to the cache directory created by `Rcpp::sourceCpp()`. This can
be done by setting the `cacheDir` argument of the `Rcpp::sourceCpp()` function
to the desired cache directory via the `cacheDir` optional argument. Behind the
scene, `Rcpp::sourceCpp()` subsequently creates a sub-directory in that
directory whose name is platform-dependent and retrieved via
`Rcpp:::.sourceCppPlatformCacheDir()`. We can therefore decide beforehand of the
location of that cache directory, create it and copy the files we want to
include in the Rcpp code chunk to that directory.
### Do not copy header files!
If you have header files to include in the Rcpp code chunk, you should not copy
as per the first issue above. Instead, you should convert them to `.hpp` files
and include them in the Rcpp code chunk.
## Live example
The following code assumes that all your source files are in the `src`
directory into the directory where your `.qmd` file is located. The code
demonstrates how to include multiple files in a single Rcpp code chunk.
The first and last code chunks are the ones handling the copying of the files to
the cache directory and the deletion of the cache directory. They can be hidden
in the final document by setting the code chunk option `include` to `false`.
First, we create the cache directory and copy the header file
`hausdorff_utils.hpp` to it.
```{r}
cache_dir_base <- "."
cache_dir <- Rcpp:::.sourceCppPlatformCacheDir(cache_dir_base)
fs::dir_create(cache_dir)
fs::file_copy(
path = list.files("src", pattern = "*.hpp", full.names = TRUE),
new_path = cache_dir,
overwrite = TRUE
)
```
Then we can compile a `.cpp` file which depends on a `.hpp` file that has been
copied to the cache directory by setting the `cacheDir` argument of the
`Rcpp::sourceCpp()` function to the cache directory that we curated before.
```
# ```{Rcpp, engine.opts = list(cacheDir = ".")}
# #| file: src/hausdorff_parallel.cpp
# ```
```
```{Rcpp, engine.opts = list(cacheDir = ".")}
#| file: src/hausdorff_parallel.cpp
```
The code above implements the function `dist_parallel()` which performs pairwise
Hausdorff distance computations within a functional data set, possibly in
parallel. The function expects as input a list of size $N$ containing the $N$
$L$-dimensional curves observed on a given grid of size $M$ of their common
domain. Each entry of the input list must be a matrix of shape $L \times M$. The
simulated data stored in `data/dat.rds` is formatted in such a way. We can
therefore check that we can use the exported function `dist_parallel()` as
follows.
```{r}
dat <- readRDS("data/dat.rds")
dat <- dat[1:21]
D <- dist_parallel(dat, dimension = 3L)
head(D)
```
Finally, we can clean up the cache directory.
```{r}
fs::dir_delete(cache_dir)
```