GALAHAD RPD package#

purpose#

The rpd package reads and writes quadratic programming (and related) problem data to and from a QPLIB-format data file. Variables may be continuous, binary or integer.

Currently only the options and inform dictionaries are exposed; these are provided and used by other GALAHAD packages with Python interfaces. Please contact us if you would like full functionality!

See Section 4 of $GALAHAD/doc/rpd.pdf for additional details.

reference#

The QPBLIB format is defined in

F. Furini, E. Traversi, P. Belotti, A. Frangioni, A. Gleixner, N. Gould, L. Liberti, A. Lodi, R. Misener, H. Mittelmann, N. V. Sahinidis, S. Vigerske and A. Wiegele, ``QPLIB: a library of quadratic programming instances’’, Mathematical Programming Computation 11 (2019) 237-–265.

introduction to function calls#

To solve a given problem, functions from the rpd package must be called in the following order:

  • rpd_initialize - provide default control parameters and set up initial data structures

  • rpd_get_stats - read a given QPLIB file into internal data structures, and report vital statistics

  • (optionally, and in any order, where relevant)

    • rpd_get_g - get the objective gradient term \(g\)

    • rpd_get_f - get the objective constant term \(f\)

    • rpd_get_xlu - get the variable bounds \(x_l\) and \(x_u\)

    • rpd_get_xlu - get the constraint bounds \(c_l\) and \(c_u\)

    • rpd_get_h - get the objective Hessian term \(H\)

    • rpd_get_a - get the constrain Jacobian term \(A\)

    • rpd_get_h_c - get the constraint Hessian terms \(H_c\)

    • rpd_get_x_type - determine the type of each variable \(x\)

    • rpd_get_x - get initial value of the variable \(x\)

    • rpd_get_y - get initial value of Lagrange multipliers \(y\)

    • rpd_get_z - get initial value of the dual variables \(z\)

  • rpd_terminate - deallocate data structures

See the examples section for illustrations of use.

callable functions#

overview of functions provided#

// namespaces

namespace conf;

// typedefs

typedef float spc_;
typedef double rpc_;
typedef int ipc_;

// structs

struct rpd_control_type;
struct rpd_inform_type;

// global functions

void rpd_initialize(void **data, struct rpd_control_type* control, ipc_ *status);

void rpd_get_stats(
    char qplib_file[],
    ipc_ qplib_file_len,
    struct rpd_control_type* control,
    void **data,
    ipc_ *status,
    char p_type[4],
    ipc_ *n,
    ipc_ *m,
    ipc_ *h_ne,
    ipc_ *a_ne,
    ipc_ *h_c_ne
);

void rpd_get_g(void **data, ipc_ *status, ipc_ n, rpc_ g[]);
void rpd_get_f(void **data, ipc_ *status, rpc_* f);

void rpd_get_xlu(
    void **data,
    ipc_ *status,
    ipc_ n,
    rpc_ x_l[],
    rpc_ x_u[]
);

void rpd_get_clu(
    void **data,
    ipc_ *status,
    ipc_ m,
    rpc_ c_l[],
    rpc_ c_u[]
);

void rpd_get_h(
    void **data,
    ipc_ *status,
    ipc_ h_ne,
    ipc_ h_row[],
    ipc_ h_col[],
    rpc_ h_val[]
);

void rpd_get_a(
    void **data,
    ipc_ *status,
    ipc_ a_ne,
    ipc_ a_row[],
    ipc_ a_col[],
    rpc_ a_val[]
);

void rpd_get_h_c(
    void **data,
    ipc_ *status,
    ipc_ h_c_ne,
    ipc_ h_c_ptr[],
    ipc_ h_c_row[],
    ipc_ h_c_col[],
    rpc_ h_c_val[]
);

void rpd_get_x_type(void **data, ipc_ *status, ipc_ n, ipc_ x_type[]);
void rpd_get_x(void **data, ipc_ *status, ipc_ n, rpc_ x[]);
void rpd_get_y(void **data, ipc_ *status, ipc_ m, rpc_ y[]);
void rpd_get_z(void **data, ipc_ *status, ipc_ n, rpc_ z[]);
void rpd_information(void **data, struct rpd_inform_type* inform, ipc_ *status);

void rpd_terminate(
    void **data,
    struct rpd_control_type* control,
    struct rpd_inform_type* inform
);

typedefs#

typedef float spc_

spc_ is real single precision

typedef double rpc_

rpc_ is the real working precision used, but may be changed to float by defining the preprocessor variable SINGLE.

typedef int ipc_

ipc_ is the default integer word length used, but may be changed to int64_t by defining the preprocessor variable INTEGER_64.

function calls#

void rpd_initialize(void **data, struct rpd_control_type* control, ipc_ *status)

Set default control values and initialize private data

Parameters:

data

holds private internal data

control

is a struct containing control information (see rpd_control_type)

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are (currently):

  • 0

    The initialization was successful.

void rpd_get_stats(
    char qplib_file[],
    ipc_ qplib_file_len,
    struct rpd_control_type* control,
    void **data,
    ipc_ *status,
    char p_type[4],
    ipc_ *n,
    ipc_ *m,
    ipc_ *h_ne,
    ipc_ *a_ne,
    ipc_ *h_c_ne
)

Read the data from a specified QPLIB file into internal storage, and report the type of problem encoded, along with problem-specific dimensions.

Parameters:

qplib_file

is a one-dimensional array of type char that specifies the name of the QPLIB file that is to be read.

qplib_file_len

is a scalar variable of type ipc_, that gives the number of characters in the name encoded in qplib_file.

control

is a struct whose members provide control paramters for the remaining prcedures (see rpd_control_type)

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

p_type

is a one-dimensional array of size 4 and type char that specifies the type of quadratic programming problem encoded in the QPLIB file.

The first character indicates the type of objective function used. It will be one of the following:

  • L a linear objective function.

  • D a convex quadratic objective function whose Hessian is a diagonal matrix.

  • C a convex quadratic objective function.

  • Q a quadratic objective function whose Hessian may be indefinite.

The second character indicates the types of variables that are present. It will be one of the following:

  • C all the variables are continuous.

  • B all the variables are binary (0-1).

  • M the variables are a mix of continuous and binary.

  • I all the variables are integer.

  • G the variables are a mix of continuous, binary and integer.

The third character indicates the type of the (most extreme) constraint function used; other constraints may be of a lesser type. It will be one of the following:

  • N there are no constraints.

  • B some of the variables lie between lower and upper bounds (box constraint).

  • L the constraint functions are linear.

  • D the constraint functions are convex quadratics with diagonal Hessians.

  • C the constraint functions are convex quadratics.

  • Q the constraint functions are quadratics whose Hessians may be indefinite.

Thus for continuous problems, we would have

  • LCL a linear program.

  • LCC or LCQ a linear program with quadratic constraints.

  • CCB or QCB a bound-constrained quadratic program.

  • CCL or QCL a quadratic program.

  • CCC or CCQ or QCC or QCQ a quadratic program with quadratic constraints.

For integer problems, the second character would be I rather than C, and for mixed integer problems, the second character would by M or G.

n

is a scalar variable of type ipc_, that holds the number of variables.

m

is a scalar variable of type ipc_, that holds the number of general constraints.

h_ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of \(H\) stored in the sparse symmetric co-ordinate storage scheme.

a_ne

is a scalar variable of type ipc_, that holds the number of entries in \(A\) stored in the sparse co-ordinate storage scheme.

h_c_ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of \(H_c\) stored in the joint sparse co-ordinate storage scheme.

void rpd_get_g(void **data, ipc_ *status, ipc_ n, rpc_ g[])

Recover the linear term \(g\) from in objective function

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

n

is a scalar variable of type ipc_, that holds the number of variables.

g

is a one-dimensional array of size n and type rpc_, that gives the linear term \(g\) of the objective function. The j-th component of g, j = 0, … , n-1, contains \(g_j\).

void rpd_get_f(void **data, ipc_ *status, rpc_* f)

Recover the constant term \(f\) in the objective function.

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

f

is a scalar of type rpc_, that gives the constant term \(f\) from the objective function.

void rpd_get_xlu(
    void **data,
    ipc_ *status,
    ipc_ n,
    rpc_ x_l[],
    rpc_ x_u[]
)

Recover the variable lower and upper bounds \(x_l\) and \(x_u\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

n

is a scalar variable of type ipc_, that holds the number of variables.

x_l

is a one-dimensional array of size n and type rpc_, that gives the lower bounds \(x_l\) on the variables \(x\). The j-th component of x_l, j = 0, … , n-1, contains \((x_l)_j\).

x_u

is a one-dimensional array of size n and type rpc_, that gives the upper bounds \(x_u\) on the variables \(x\). The j-th component of x_u, j = 0, … , n-1, contains \((x_u)_j\).

void rpd_get_clu(
    void **data,
    ipc_ *status,
    ipc_ m,
    rpc_ c_l[],
    rpc_ c_u[]
)

Recover the constraint lower and upper bounds \(c_l\) and \(c_u\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

m

is a scalar variable of type ipc_, that holds the number of general constraints.

c_l

is a one-dimensional array of size m and type rpc_, that gives the lower bounds \(c_l\) on the constraints \(A x\). The i-th component of c_l, i = 0, … , m-1, contains \((c_l)_i\).

c_u

is a one-dimensional array of size m and type rpc_, that gives the upper bounds \(c_u\) on the constraints \(A x\). The i-th component of c_u, i = 0, … , m-1, contains \((c_u)_i\).

void rpd_get_h(
    void **data,
    ipc_ *status,
    ipc_ h_ne,
    ipc_ h_row[],
    ipc_ h_col[],
    rpc_ h_val[]
)

Recover the Hessian term \(H\) in the objective function.

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

h_ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of the Hessian matrix \(H\).

h_row

is a one-dimensional array of size h_ne and type ipc_, that gives the row indices of the lower triangular part of \(H\) in the sparse co-ordinate storage scheme.

h_col

is a one-dimensional array of size h_ne and type ipc_, that gives the column indices of the lower triangular part of \(H\) in the sparse co-ordinate storage scheme.

h_val

is a one-dimensional array of size h_ne and type rpc_, that holds the values of the entries of the lower triangular part of the Hessian matrix \(H\) in the sparse co-ordinate storage scheme.

void rpd_get_a(
    void **data,
    ipc_ *status,
    ipc_ a_ne,
    ipc_ a_row[],
    ipc_ a_col[],
    rpc_ a_val[]
)

Recover the Jacobian term \(A\) in the constraints.

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

a_ne

is a scalar variable of type ipc_, that holds the number of entries in the constraint Jacobian matrix \(A\).

a_row

is a one-dimensional array of size a_ne and type ipc_, that gives the row indices of \(A\) in the sparse co-ordinate storage scheme.

a_col

is a one-dimensional array of size a_ne and type ipc_, that gives the column indices of \(A\) in the sparse co-ordinate, storage scheme.

a_val

is a one-dimensional array of size a_ne and type rpc_, that gives the values of the entries of the constraint Jacobian matrix \(A\) in the sparse co-ordinate scheme.

void rpd_get_h_c(
    void **data,
    ipc_ *status,
    ipc_ h_c_ne,
    ipc_ h_c_ptr[],
    ipc_ h_c_row[],
    ipc_ h_c_col[],
    rpc_ h_c_val[]
)

Recover the Hessian terms \(H_c\) in the constraints.

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

h_c_ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of the Hessian matrix \(H\).

h_c_ptr

is a one-dimensional array of size h_c_ne and type ipc_, that gives the constraint indices of the lower triangular part of \(H_c\) in the joint sparse co-ordinate storage scheme.

h_c_row

is a one-dimensional array of size h_c_ne and type ipc_, that gives the row indices of the lower triangular part of \(H_c\) in the joint sparse co-ordinate storage scheme.

h_c_col

is a one-dimensional array of size h_c_ne and type ipc_, that gives the column indices of the lower triangular part of \(H_c\) in the sparse co-ordinate storage scheme.

h_c_val

is a one-dimensional array of size h_c_ne and type rpc_, that holds the values of the entries of the lower triangular part of the Hessian matrix \(H_c\) in the sparse co-ordinate storage scheme.

void rpd_get_x_type(void **data, ipc_ *status, ipc_ n, ipc_ x_type[])

Recover the types of the variables \(x\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

n

is a scalar variable of type ipc_, that holds the number of variables.

x_type

is a one-dimensional array of size n and type ipc_, that specifies the type of each variable \(x\). Specifically, for j = 0, … , n-1, x(j) =

  • 0 variable \(x_j\) is continuous,

  • 1 variable \(x_j\) is integer, and

  • 2 variable \(x_j\) is binary (0,1)

void rpd_get_x(void **data, ipc_ *status, ipc_ n, rpc_ x[])

Recover the initial values of the variables \(x\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

n

is a scalar variable of type ipc_, that holds the number of variables.

x

is a one-dimensional array of size n and type rpc_, that gives the initial values \(x\) of the optimization variables. The j-th component of x, j = 0, … , n-1, contains \(x_j\).

void rpd_get_y(void **data, ipc_ *status, ipc_ m, rpc_ y[])

Recover the initial values of the Lagrange multipliers \(y\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

m

is a scalar variable of type ipc_, that holds the number of general constraints.

y

is a one-dimensional array of size n and type rpc_, that gives the initial values \(y\) of the Lagrange multipliers for the general constraints. The j-th component of y, j = 0, … , n-1, contains \(y_j\).

void rpd_get_z(void **data, ipc_ *status, ipc_ n, rpc_ z[])

Recover the initial values of the dual variables \(z\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 0

    The statistics have been recovered successfully.

  • -93

    The QPLIB file did not contain the required data.

n

is a scalar variable of type ipc_, that holds the number of variables.

z

is a one-dimensional array of size n and type rpc_, that gives the initial values \(z\) of the dual variables. The j-th component of z, j = 0, … , n-1, contains \(z_j\).

void rpd_information(void **data, struct rpd_inform_type* inform, ipc_ *status)

Provides output information

Parameters:

data

holds private internal data

inform

is a struct containing output information (see rpd_inform_type)

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are (currently):

  • 0

    The values were recorded successfully

void rpd_terminate(
    void **data,
    struct rpd_control_type* control,
    struct rpd_inform_type* inform
)

Deallocate all internal private storage

Parameters:

data

holds private internal data

control

is a struct containing control information (see rpd_control_type)

inform

is a struct containing output information (see rpd_inform_type)

available structures#

rpd_control_type structure#

#include <galahad_rpd.h>

struct rpd_control_type {
    // fields

    bool f_indexing;
    ipc_ qplib;
    ipc_ error;
    ipc_ out;
    ipc_ print_level;
    bool space_critical;
    bool deallocate_error_fatal;
};

detailed documentation#

control derived type as a C struct

components#

bool f_indexing

use C or Fortran sparse matrix indexing

ipc_ qplib

QPLIB file input stream number.

ipc_ error

error and warning diagnostics occur on stream error

ipc_ out

general output occurs on stream out

ipc_ print_level

the level of output required is specified by print_level

  • \(\leq\) 0 gives no output,

  • \(\geq\) 1 gives increasingly verbose (debugging) output

bool space_critical

if .space_critical true, every effort will be made to use as little space as possible. This may result in longer computation time

bool deallocate_error_fatal

if .deallocate_error_fatal is true, any array/pointer deallocation error will terminate execution. Otherwise, computation will continue

rpd_inform_type structure#

#include <galahad_rpd.h>

struct rpd_inform_type {
    // fields

    ipc_ status;
    ipc_ alloc_status;
    char bad_alloc[81];
    ipc_ io_status;
    ipc_ line;
    char p_type[4];
};

detailed documentation#

inform derived type as a C struct

components#

ipc_ status

return status. Possible values are:

  • 0

    The call was successful.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -22

    An input/outpur error occurred.

  • -25

    The end of the input file was reached prematurely.

  • -29

    The problem type was not recognised.

ipc_ alloc_status

the status of the last attempted allocation or deallocation

char bad_alloc[81]

the name of the array for which an allocation or deallocation error occurred

ipc_ io_status

status from last read attempt

ipc_ line

number of last line read from i/o file

char p_type[4]

problem type

example calls#

This is an example of how to use the package to read and write a QP; the code is available in $GALAHAD/src/rpd/C/rpdt.c . A variety of supported Hessian and constraint matrix storage formats are shown.

Notice that C-style indexing is used, and that this is flagged by setting control.f_indexing to false. The floating-point type rpc_ is set in galahad_precision.h to double by default, but to float if the preprocessor variable SINGLE is defined. Similarly, the integer type ipc_ from galahad_precision.h is set to int by default, but to int64_t if the preprocessor variable INTEGER_64 is defined.

/* rpdt.c */
/* Full test for the RPD C interface using C sparse matrix indexing */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "galahad_precision.h"
#include "galahad_cfunctions.h"
#include "galahad_rpd.h"
#define BUFSIZE 1000

int main(void) {

    // Derived types
    void *data;
    struct rpd_control_type control;
    struct rpd_inform_type inform;

    char qplib_file[BUFSIZE];
    char *galahad = "GALAHAD";
    ipc_ qplib_file_len;

    // make sure the GALAHAD environment variable actually exists
    if(!getenv(galahad)){
      fprintf(stderr, " The environment variable %s was not found.\n", galahad);
      exit( 1 );
    }

    // make sure the buffer is large enough to hold the environment variable
    // value, and if so, copy it into qplib_file
    if( snprintf( qplib_file, BUFSIZE, "%s", getenv(galahad) ) >= BUFSIZE){
      fprintf (stderr, " BUFSIZE of %d was too small. Aborting\n", BUFSIZE );
      exit( 1 );
    }
    // extend the qplib_file string to include the actual position of the
    // provided ALLINIT.qplib example file provided as part GALAHAD
    char source[] = "/examples/ALLINIT.qplib";
    strcat( qplib_file, source );
    // compute the length of the string
    qplib_file_len = strlen( qplib_file );

    printf( " QPLIB file: %s\n", qplib_file );

    ipc_ status;
    ipc_ n;
    ipc_ m;
    ipc_ h_ne;
    ipc_ a_ne;
    ipc_ h_c_ne;
    char p_type[4];

    printf(" C sparse matrix indexing\n\n");

    printf(" basic tests of storage formats\n\n");

    // Initialize RPD */
    rpd_initialize( &data, &control, &status );

    // Set user-defined control options */
    control.f_indexing = false; // C sparse matrix indexing

    // Recover vital statistics from the QPLIB file
    rpd_get_stats( qplib_file, qplib_file_len, &control, &data, &status,
                   p_type, &n, &m, &h_ne, &a_ne, &h_c_ne );
    printf( " QPLIB file is of type %s\n", p_type );
    printf( " n = %" i_ipc_ ", m = %" i_ipc_ ", h_ne = %" i_ipc_
            ", a_ne = %" i_ipc_ ", h_c_ne = %" i_ipc_ "\n",
            n, m, h_ne, a_ne, h_c_ne );

    // Recover g
    rpc_ g[n];
    rpd_get_g( &data, &status, n, g );
    printf( " g = %.1f %.1f %.1f %.1f %.1f\n",g[0], g[1], g[2], g[3], g[4]);

    // Recover f
    rpc_ f;
    rpd_get_f( &data, &status, &f );
    printf( " f = %.1f\n", f );

    // Recover xlu
    rpc_ x_l[n];
    rpc_ x_u[n];
    rpd_get_xlu( &data, &status, n, x_l, x_u );
    printf( " x_l = %.1f %.1f %.1f %.1f %.1f\n", x_l[0], x_l[1], x_l[2],
             x_l[3], x_l[4]);
    printf( " x_u = %.1f %.1f %.1f %.1f %.1f\n", x_u[0], x_u[1], x_u[2],
             x_u[3], x_u[4]);

    // Recover clu
    rpc_ c_l[m];
    rpc_ c_u[m];
    rpd_get_clu( &data, &status, m, c_l, c_u );
    printf( " c_l = %.1f %.1f\n", c_l[0], c_l[1] );
    printf( " c_u = %.1f %.1f\n", c_u[0], c_u[1] );

    // Recover H
    ipc_ h_row[h_ne];
    ipc_ h_col[h_ne];
    rpc_ h_val[h_ne];
    rpd_get_h( &data, &status, h_ne, h_row, h_col, h_val );
    printf( " h_row, h_col, h_val =\n");
    for( ipc_ i = 0; i < h_ne; i++) printf("   %" i_ipc_ " %" i_ipc_ " %.1f\n",
         h_row[i], h_col[i], h_val[i]);

    // Recover A
    ipc_ a_row[a_ne];
    ipc_ a_col[a_ne];
    rpc_ a_val[a_ne];
    rpd_get_a( &data, &status, a_ne, a_row, a_col, a_val );
    printf( " a_row, a_col, a_val =\n");
    for( ipc_ i = 0; i < a_ne; i++) printf("   %" i_ipc_ " %" i_ipc_ " %.1f\n",
         a_row[i], a_col[i], a_val[i]);

    // Recover H_c
    ipc_ h_c_ptr[h_c_ne];
    ipc_ h_c_row[h_c_ne];
    ipc_ h_c_col[h_c_ne];
    rpc_ h_c_val[h_c_ne];
    rpd_get_h_c( &data, &status, h_c_ne, h_c_ptr, h_c_row, h_c_col, h_c_val );
    printf( " h_c_row, h_c_col, h_c_val =\n");
    for( ipc_ i = 0; i < h_c_ne; i++) printf("   %" i_ipc_ " %" i_ipc_
         " %" i_ipc_ " %.1f\n", h_c_ptr[i], h_c_row[i], h_c_col[i], h_c_val[i]);

    // Recover x_type
    ipc_ x_type[n];
    rpd_get_x_type( &data, &status, n, x_type );
    printf( " x_type = %" i_ipc_ " %" i_ipc_ " %" i_ipc_ " %" i_ipc_
            " %" i_ipc_ "\n", x_type[0], x_type[1], x_type[2],
            x_type[3], x_type[4] );

    // Recover x
    rpc_ x[n];
    rpd_get_x( &data, &status, n, x );
    printf( " x = %.1f %.1f %.1f %.1f %.1f\n",x[0], x[1], x[2], x[3], x[4]);

    // Recover y
    rpc_ y[m];
    rpd_get_y( &data, &status, m, y );
    printf( " y = %.1f %.1f\n",y[0], y[1]);

    // Recover z
    rpc_ z[n];
    rpd_get_z( &data, &status, n, z );
    printf( " z = %.1f %.1f %.1f %.1f %.1f\n",z[0], z[1], z[2], z[3], z[4]);

    // Delete internal workspace
    rpd_terminate( &data, &control, &inform );
}

This is the same example, but now fortran-style indexing is used; the code is available in $GALAHAD/src/rpd/C/rpdtf.c .

/* rpdtf.c */
/* Full test for the RPD C interface using Fortran sparse matrix indexing */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "galahad_precision.h"
#include "galahad_cfunctions.h"
#include "galahad_rpd.h"
#define BUFSIZE 1000

int main(void) {

    // Derived types
    void *data;
    struct rpd_control_type control;
    struct rpd_inform_type inform;

    char qplib_file[BUFSIZE];
    char *galahad = "GALAHAD";
    ipc_ qplib_file_len;

    // make sure the GALAHAD environment variable actually exists
    if(!getenv(galahad)){
      fprintf(stderr, " The environment variable %s was not found.\n", galahad);
      exit( 1 );
    }

    // make sure the buffer is large enough to hold the environment variable
    // value, and if so, copy it into qplib_file
    if( snprintf( qplib_file, BUFSIZE, "%s", getenv(galahad) ) >= BUFSIZE){
      fprintf (stderr, " BUFSIZE of %d was too small. Aborting\n", BUFSIZE );
      exit( 1 );
    }
    // extend the qplib_file string to include the actual position of the
    // provided ALLINIT.qplib example file provided as part GALAHAD
    char source[] = "/examples/ALLINIT.qplib";
    strcat( qplib_file, source );
    // compute the length of the string
    qplib_file_len = strlen( qplib_file );

    printf( " QPLIB file: %s\n", qplib_file );

    ipc_ status;
    ipc_ n;
    ipc_ m;
    ipc_ h_ne;
    ipc_ a_ne;
    ipc_ h_c_ne;
    char p_type[4];

    printf(" Fortran sparse matrix indexing\n\n");

    printf(" basic tests of storage formats\n\n");

    // Initialize RPD */
    rpd_initialize( &data, &control, &status );

    // Set user-defined control options */
    control.f_indexing = true; // fortran sparse matrix indexing

    // Recover vital statistics from the QPLIB file
    rpd_get_stats( qplib_file, qplib_file_len, &control, &data, &status,
                   p_type, &n, &m, &h_ne, &a_ne, &h_c_ne );
    printf( " QPLIB file is of type %s\n", p_type );
    printf( " n = %" i_ipc_ ", m = %" i_ipc_ ", h_ne = %" i_ipc_
            ", a_ne = %" i_ipc_ ", h_c_ne = %" i_ipc_ "\n",
            n, m, h_ne, a_ne, h_c_ne );

    // Recover g
    rpc_ g[n];
    rpd_get_g( &data, &status, n, g );
    printf( " g = %.1f %.1f %.1f %.1f %.1f\n",g[0], g[1], g[2], g[3], g[4]);

    // Recover f
    rpc_ f;
    rpd_get_f( &data, &status, &f );
    printf( " f = %.1f\n", f );

    // Recover xlu
    rpc_ x_l[n];
    rpc_ x_u[n];
    rpd_get_xlu( &data, &status, n, x_l, x_u );
    printf( " x_l = %.1f %.1f %.1f %.1f %.1f\n", x_l[0], x_l[1], x_l[2],
             x_l[3], x_l[4]);
    printf( " x_u = %.1f %.1f %.1f %.1f %.1f\n", x_u[0], x_u[1], x_u[2],
             x_u[3], x_u[4]);

    // Recover clu
    rpc_ c_l[m];
    rpc_ c_u[m];
    rpd_get_clu( &data, &status, m, c_l, c_u );
    printf( " c_l = %.1f %.1f\n", c_l[0], c_l[1] );
    printf( " c_u = %.1f %.1f\n", c_u[0], c_u[1] );

    // Recover H
    ipc_ h_row[h_ne];
    ipc_ h_col[h_ne];
    rpc_ h_val[h_ne];
    rpd_get_h( &data, &status, h_ne, h_row, h_col, h_val );
    printf( " h_row, h_col, h_val =\n");
    for( ipc_ i = 0; i < h_ne; i++) printf("   %" i_ipc_ " %" i_ipc_ " %.1f\n",
         h_row[i], h_col[i], h_val[i]);

    // Recover A
    ipc_ a_row[a_ne];
    ipc_ a_col[a_ne];
    rpc_ a_val[a_ne];
    rpd_get_a( &data, &status, a_ne, a_row, a_col, a_val );
    printf( " a_row, a_col, a_val =\n");
    for( ipc_ i = 0; i < a_ne; i++) printf("   %" i_ipc_ " %" i_ipc_ " %.1f\n",
         a_row[i], a_col[i], a_val[i]);

    // Recover H_c
    ipc_ h_c_ptr[h_c_ne];
    ipc_ h_c_row[h_c_ne];
    ipc_ h_c_col[h_c_ne];
    rpc_ h_c_val[h_c_ne];
    rpd_get_h_c( &data, &status, h_c_ne, h_c_ptr, h_c_row, h_c_col, h_c_val );
    printf( " h_c_row, h_c_col, h_c_val =\n");
    for( ipc_ i = 0; i < h_c_ne; i++) printf("   %" i_ipc_ " %" i_ipc_
         " %" i_ipc_ " %.1f\n", h_c_ptr[i], h_c_row[i], h_c_col[i], h_c_val[i]);

    // Recover x_type
    ipc_ x_type[n];
    rpd_get_x_type( &data, &status, n, x_type );
    printf( " x_type = %" i_ipc_ " %" i_ipc_ " %" i_ipc_ " %" i_ipc_
            " %" i_ipc_ "\n", x_type[0], x_type[1], x_type[2],
            x_type[3], x_type[4] );

    // Recover x
    rpc_ x[n];
    rpd_get_x( &data, &status, n, x );
    printf( " x = %.1f %.1f %.1f %.1f %.1f\n",x[0], x[1], x[2], x[3], x[4]);

    // Recover y
    rpc_ y[m];
    rpd_get_y( &data, &status, m, y );
    printf( " y = %.1f %.1f\n",y[0], y[1]);

    // Recover z
    rpc_ z[n];
    rpd_get_z( &data, &status, n, z );
    printf( " z = %.1f %.1f %.1f %.1f %.1f\n",z[0], z[1], z[2], z[3], z[4]);

    // Delete internal workspace
    rpd_terminate( &data, &control, &inform );
}