C Integration¶
Use gp4c directly in C/C++ projects.
Installation¶
Install as system library:
# System-wide (requires sudo)
./install_library.sh
# User install (no sudo)
./install_library.sh --user
Or with CMake:
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --parallel
sudo cmake --install .
Basic Usage¶
Header¶
Include the header in your C code:
Sampling f and g¶
#include "gp4c.h"
#include <stdlib.h>
int main() {
// Setup
int n = 100;
double x[100];
for (int i = 0; i < n; i++) {
x[i] = i * 0.05; // Grid from 0 to 4.95
}
// Parameters
double sigma2 = 1.0;
double ell = 0.5;
int n_samples = 5;
// Allocate output
double *f_samples = malloc(n_samples * n * sizeof(double));
double *g_samples = malloc(n_samples * n * sizeof(double));
// Sample
int status = draw_joint_gp_samples(
x, n, // x_f grid
x, n, // x_g grid
sigma2, ell,
KERNEL_RBF, // kernel type
n_samples,
42, // random seed
f_samples,
g_samples,
NULL // zero mean
);
if (status != 0) {
fprintf(stderr, "Sampling failed\n");
return 1;
}
// Use samples...
free(f_samples);
free(g_samples);
return 0;
}
Compilation¶
Or manually:
Advanced Usage¶
Custom Grids¶
Use different grids for f and g:
double x_f[100]; // Dense grid for function
double x_g[20]; // Coarse grid for integral
// Initialize grids...
int status = draw_joint_gp_samples(
x_f, 100,
x_g, 20,
sigma2, ell,
KERNEL_RBF,
n_samples, 42,
f_samples,
g_samples,
NULL
);
Flexible Sampling (f, g, and h)¶
Sample any combination of function, integral, and derivative:
GPSamplingSpec spec;
spec.x_f = x;
spec.n_f = n;
spec.x_g = x;
spec.n_g = n;
spec.x_h = x;
spec.n_h = n;
spec.flags = GP_SAMPLE_F | GP_SAMPLE_G | GP_SAMPLE_H;
double *f_samples = malloc(n_samples * n * sizeof(double));
double *g_samples = malloc(n_samples * n * sizeof(double));
double *h_samples = malloc(n_samples * n * sizeof(double));
int status = draw_gp_samples_flexible(
&spec,
sigma2, ell,
KERNEL_RBF,
n_samples, 42,
f_samples, g_samples, h_samples,
NULL // zero mean
);
Posterior Sampling¶
Condition on observations:
// Observations
double x_obs[] = {0.0, 1.0, 2.0, 3.0, 4.0};
double y_obs[] = {0.0, 0.84, 0.91, 0.14, -0.76}; // sin(x)
double noise = 0.01;
GPObservations obs;
obs.x_f = x_obs;
obs.y_f = y_obs;
obs.n_f = 5;
obs.x_g = NULL;
obs.y_g = NULL;
obs.n_g = 0;
obs.x_h = NULL;
obs.y_h = NULL;
obs.n_h = 0;
obs.noise_f_cov = &noise;
obs.noise_f_type = NOISE_SCALAR;
obs.noise_g_cov = NULL;
obs.noise_g_type = NOISE_SCALAR;
obs.noise_h_cov = NULL;
obs.noise_h_type = NOISE_SCALAR;
// Prediction points
GPSamplingSpec pred;
pred.x_f = x_test;
pred.n_f = n_test;
pred.x_g = NULL;
pred.n_g = 0;
pred.x_h = NULL;
pred.n_h = 0;
pred.flags = GP_SAMPLE_F;
// Output arrays
double *f_samples = malloc(n_samples * n_test * sizeof(double));
double *f_mean = malloc(n_test * sizeof(double));
double *f_std = malloc(n_test * sizeof(double));
int status = draw_gp_posterior_samples(
&obs, &pred,
sigma2, ell,
KERNEL_RBF,
n_samples, 42,
f_samples, NULL, NULL, // samples (f, g, h)
f_mean, NULL, NULL, // means
f_std, NULL, NULL, // stds
NULL // zero mean
);
Memory Management¶
Preallocate output arrays:
int n_f = 100;
int n_g = 50;
int n_samples = 10;
double *f_samples = malloc(n_samples * n_f * sizeof(double));
double *g_samples = malloc(n_samples * n_g * sizeof(double));
// Sample...
free(f_samples);
free(g_samples);
API Reference¶
draw_joint_gp_samples¶
int draw_joint_gp_samples(
const double *x_f, int n_f,
const double *x_g, int n_g,
double sigma2, double ell,
KernelType kernel,
int n_samples, unsigned long seed,
double *f_samples,
double *g_samples,
const GPMeanSpec *mean
);
Parameters:
x_f, n_f: Function evaluation grid and sizex_g, n_g: Integral evaluation grid and sizesigma2: Kernel varianceell: Kernel length scalekernel: Kernel type (KERNEL_RBF, KERNEL_MATERN52, KERNEL_MATERN32)n_samples: Number of samples to drawseed: Random seed for reproducibilityf_samples: Output array (n_samples × n_f)g_samples: Output array (n_samples × n_g)mean: Mean specification (NULL for zero mean)
Returns:
0on success- Non-zero on error
draw_gp_samples_flexible¶
int draw_gp_samples_flexible(
const GPSamplingSpec *spec,
double sigma2, double ell,
KernelType kernel,
int n_samples, unsigned long seed,
double *f_samples, double *g_samples, double *h_samples,
const GPMeanSpec *mean
);
draw_gp_posterior_samples¶
int draw_gp_posterior_samples(
const GPObservations *obs,
const GPSamplingSpec *pred,
double sigma2, double ell,
KernelType kernel,
int n_samples, unsigned long seed,
double *f_samples, double *g_samples, double *h_samples,
double *f_mean, double *g_mean, double *h_mean,
double *f_std, double *g_std, double *h_std,
const GPMeanSpec *mean
);
Kernel Types¶
typedef enum {
KERNEL_RBF = 0, // RBF/Squared Exponential
KERNEL_MATERN52 = 1, // Matérn 5/2
KERNEL_MATERN32 = 2 // Matérn 3/2 (once mean-square differentiable)
} KernelType;
Noise Types¶
typedef enum {
NOISE_SCALAR = 0, // Single variance for all observations
NOISE_DIAGONAL = 1, // Per-observation variances
NOISE_FULL = 2 // Full covariance matrix
} NoiseType;
CMake Integration¶
Use gp4c in your CMake project:
cmake_minimum_required(VERSION 3.12)
project(my_project)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GP4C REQUIRED gp4c)
add_executable(my_program my_program.c)
target_include_directories(my_program PRIVATE ${GP4C_INCLUDE_DIRS})
target_link_libraries(my_program ${GP4C_LIBRARIES})
Or using find_package:
find_package(gp4c REQUIRED)
add_executable(my_program my_program.c)
target_link_libraries(my_program gp4c::gp4c)
Full Example¶
See examples/C_INTEGRATION.md in the repository for complete working examples.
Next Steps¶
- Python Examples - Python API usage
- CLASS Integration - Using gp4c in CLASS
- API Reference - Python interface