C++ Integration
PRISME supports C++ implementations of statistical methods for performance-critical computations through MATLAB mex.
Current C++ implementations include TFCE, Cluster Size, and cNBS methods.
File Organization
statistical_methods/
├── mex_scripts/ # C++ source files (.cpp)
│ ├── apply_tfce_cpp.cpp
│ ├── size_pval_cpp.cpp
│ ├── constrained_pval_cpp.cpp
│ └── ...
└── mex_binaries/ # Compiled MEX files (generated)
├── apply_tfce_cpp.mexa64
└── ...
Compilation
Compile all C++ methods by running:
compile_mex()
This script:
1. Cleans existing MEX binaries
2. Compiles all C++ files from mex_scripts/
3. Stores compiled binaries in mex_binaries/
4. Adds the binary directory to MATLAB path
Compilation is platform-specific - the script will generate the appropriate binary format for your system (.mexa64 for Linux, .mexmaci64 for macOS, .mexw64 for Windows).
Naming Convention
C++ implementations use the _cpp suffix:
- MATLAB version: Fast_TFCE.m
- C++ version: Fast_TFCE_cpp.m (wrapper) + apply_tfce_cpp.cpp (implementation)
The MATLAB wrapper class calls the compiled MEX function.
Adding a C++ Method
Step 1: Write the C++ Function
Create your C++ file in statistical_methods/mex_scripts/:
// my_method_cpp.cpp
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
// Get input data
double *data = mxGetPr(prhs[0]);
mwSize n = mxGetM(prhs[0]);
// Allocate output
plhs[0] = mxCreateDoubleMatrix(n, 1, mxREAL);
double *output = mxGetPr(plhs[0]);
// Your computation here
for (mwSize i = 0; i < n; i++) {
output[i] = data[i] * 2.0; // Example
}
}
Step 2: Register in compile_mex
Add your file to the source_files list in compile_mex.m:
source_files = {
'statistical_methods/mex_scripts/apply_tfce_cpp.cpp', ...
'statistical_methods/mex_scripts/my_method_cpp.cpp', ... % Add here
% ... other files
};
Step 3: Create MATLAB Wrapper
Create a MATLAB class that calls your C++ function:
classdef My_Method_cpp
properties
level = 'variable';
permutation_based = true;
end
methods
function pvals = run_method(obj, varargin)
params = struct(varargin{:});
edge_stats = params.edge_stats;
perm_data = params.permuted_edge_data;
% Call compiled C++ function
pvals = my_method_cpp(edge_stats, perm_data);
end
end
end
Step 4: Compile and Test
% Compile
compile_mex();
% Test with developer mode
Params = setparams();
Params.all_cluster_stat_types = {'My_Method_cpp'};
Params.testing = true;
repetition_calculator();
Memory Compatibility
Critical: Ensure all MATLAB variables are cast to double before passing to C++ functions:
% Correct
pvals = my_cpp_function(double(edge_stats));
% Incorrect - may cause memory errors
pvals = my_cpp_function(edge_stats); % If edge_stats is single precision
C++ MEX functions expect double precision by default. Type mismatches can cause crashes or incorrect results.
Validation
When replacing a MATLAB method with C++:
- Keep both versions initially
- Run both on test data
- Verify identical outputs
- Benchmark performance improvement
PRISME's permutation recycling ensures both versions receive identical input, making validation straightforward.
Computational Time Performance Benchmarking
Statistical methods are timed during PRISME calculation execution. Use this feature to benchmark the C++ implementation and see if it is the best for your statistical inference method.