Skip to content

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

Include the header in your C code:

#include "gp4c.h"
#include <stdio.h>

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

gcc -o my_program my_program.c $(pkg-config --cflags --libs gp4c)

Or manually:

gcc -o my_program my_program.c -I/usr/local/include -L/usr/local/lib -lgp4c -lgsl -lgslcblas -lm

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 size
  • x_g, n_g : Integral evaluation grid and size
  • sigma2 : Kernel variance
  • ell : Kernel length scale
  • kernel : Kernel type (KERNEL_RBF, KERNEL_MATERN52, KERNEL_MATERN32)
  • n_samples : Number of samples to draw
  • seed : Random seed for reproducibility
  • f_samples : Output array (n_samples × n_f)
  • g_samples : Output array (n_samples × n_g)
  • mean : Mean specification (NULL for zero mean)

Returns:

  • 0 on 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