```/* nag_rand_bb_make_bridge_order (g05xec) Example Program.
*
* Copyright 2014 Numerical Algorithms Group.
*
* Mark 24, 2013.
*/
#include <stdio.h>
#include <math.h>
#include <nag.h>
#include <nag_stdlib.h>
#include <nagg05.h>
#include <nagf07.h>
int get_z(Nag_OrderType order, Integer ntimes, Integer d, Integer a,
Integer npaths, double * z, Integer pdz);
void display_results(Nag_OrderType order, Integer npaths, Integer ntimes,
Integer d, double *b, Integer pdb);

#define CHECK_FAIL(name,fail) if(fail.code != NE_NOERROR) { \
printf("Error calling %s\n%s\n",name,fail.message); exit_status=-1; goto END; }

int main(void)
{
Integer exit_status = 0;
NagError fail;
/*  Scalars */
double t0, tend;
Integer a, d, pdb, pdc, pdz, nmove, npaths, ntimes, i ;
Nag_OrderType order;
/*  Arrays */
double  *b = 0,  *c = 0,  *intime = 0,  *rcomm = 0,  *start = 0,
*term = 0,  *times = 0,  *z = 0;
Integer  *move = 0;
INIT_FAIL(fail);

/* Parameters which determine the bridge */
ntimes = 10;
t0 = 0.0;
npaths = 2;
a = 0;
nmove = 3; /* We modify the first 3 points in the construction order */
d = 3;
#ifdef NAG_COLUMN_MAJOR
order = Nag_ColMajor;
pdz = npaths;
pdb = npaths;
#else
order = Nag_RowMajor;
pdz = d*(ntimes+1-a);
pdb = d*(ntimes+1);
#endif
pdc = d;
#define C(I,J) c[(J-1)*pdc + I-1]
/* Allocate memory */
if (
!( intime = NAG_ALLOC((ntimes), double)) ||
!( times = NAG_ALLOC((ntimes), double)) ||
!( rcomm = NAG_ALLOC((12 * (ntimes + 1)), double)) ||
!( start = NAG_ALLOC(d, double))  ||
!( term = NAG_ALLOC(d, double))  ||
!( c = NAG_ALLOC(pdc * d, double)) ||
!( z = NAG_ALLOC(d*(ntimes+1-a) * npaths, double)) ||
!( b = NAG_ALLOC(d*(ntimes+1) * npaths, double)) ||
!( move = NAG_ALLOC(nmove, Integer))
)
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}

/* Fix the time points at which the bridge is required */
for ( i=0; i<ntimes; i++) {
intime[i] =  t0 + 1.71*(double)(i+1);
}
tend =  t0 + 1.71*(double)(ntimes + 1);
/* We will use the bridge construction order Nag_RLRoundDown. However
* we modify this construction order by moving points 3, 5 and 4
* to the front.  Modifying a construction order would typically only
* be considered when using quasi-random numbers */
move = 3;
move = 5;
move = 4;

/* nag_rand_bb_make_bridge_order (g05xec). Creates a Brownian bridge
* construction order out of a set of input times */
nag_rand_bb_make_bridge_order(Nag_RLRoundDown, t0, tend, ntimes, intime,
nmove, move, times, &fail);
CHECK_FAIL("nag_rand_bb_make_bridge_order",fail);

/* g05xac. Initializes the Brownian bridge generator   */
nag_rand_bb_init(t0, tend, times, ntimes, rcomm, &fail);
CHECK_FAIL("nag_rand_bb_init", fail);

/* We want the following covariance matrix*/
C( 1,1 ) = 6.0;
C( 2,1 ) = 1.0;
C( 3,1 ) = -0.2;
C( 1,2 ) = 1.0;
C( 2,2 ) = 5.0;
C( 3,2 ) = 0.3;
C( 1,3 ) = -0.2;
C( 2,3 ) = 0.3;
C( 3,3 ) = 4.0;
/* g05xbc works with the Cholesky factorization of the covariance matrix C */

/* f07fdc. Cholesky factorization of real positive definite matrix */
nag_dpotrf(Nag_ColMajor, Nag_Lower, d, c, pdc, &fail);
CHECK_FAIL("nag_dpotrf",fail);

/* Generate the random numbers */
if( get_z(order, ntimes, d, a, npaths, z, pdz) != 0)
{
printf("Error generating random numbers\n");
exit_status = -1;
goto END;
}

for(i=0; i<d; i++) start[i] = 0.0;
/*  g05xbc. Generate paths for a free or non-free Wiener process using the */
/*  Brownian bridge algorithm   */
nag_rand_bb(order, npaths, d, start, a, term, z, pdz, c, pdc, b, pdb,
rcomm, &fail);
CHECK_FAIL("nag_rand_bb",fail);

/* Display the results*/
display_results(order, npaths, ntimes, d, b, pdb);
END:
;
NAG_FREE(b);
NAG_FREE(c);
NAG_FREE(intime);
NAG_FREE(rcomm);
NAG_FREE(start);
NAG_FREE(term);
NAG_FREE(times);
NAG_FREE(z);
NAG_FREE(move);
return exit_status;
}

int get_z(Nag_OrderType order, Integer ntimes, Integer d, Integer a,
Integer npaths, double * z, Integer pdz)
{
NagError fail;
Integer lseed, lstate, seed, idim, liref, *iref=0, state, i;
Integer exit_status = 0;
double * xmean=0, *stdev=0;
lstate = 80;
lseed = 1;
INIT_FAIL(fail);
idim = d*(ntimes + 1 - a);
liref = 32*idim + 7;
if (
!( iref = NAG_ALLOC((liref), Integer)) ||
!( xmean = NAG_ALLOC((idim), double)) ||
!( stdev = NAG_ALLOC((idim), double)) )
{
printf("Allocation failure in get_z\n");
exit_status = -1;
goto END;
}

/* We now need to generate the input pseudorandom numbers */
seed = 1023401;
/* g05kfc. Initializes a pseudorandom number generator */
/* to give a repeatable sequence */
nag_rand_init_repeatable(Nag_MRG32k3a,0,seed, lseed, state, &lstate, &fail);
CHECK_FAIL("nag_rand_init_repeatable", fail);

/* g05ync. Initializes a scrambled quasi-random number generator */
nag_quasi_init_scrambled(Nag_QuasiRandom_Sobol, Nag_FaureTezuka, idim,
iref, liref, 0, 32, state, &fail);
CHECK_FAIL("nag_quasi_init_scrambled",fail);

for(i=0; i<idim; i++) {
xmean[i] = 0.0;
stdev[i] = 1.0;
}
/* g05yjc. Generates a Normal quasi-random number sequence */
nag_quasi_rand_normal(order, xmean, stdev, npaths, z, pdz, iref, &fail);
CHECK_FAIL("nag_quasi_rand_normal",fail);

END:
NAG_FREE(iref);
NAG_FREE(xmean);
NAG_FREE(stdev);
return exit_status;
}

void display_results(Nag_OrderType order, Integer npaths, Integer  ntimes,
Integer  d, double  *b, Integer pdb)
{
#define B(I,J) (order==Nag_RowMajor ? b[(I-1)*pdb+J-1]:b[(J-1)*pdb+I-1])

Integer i,p,k;
printf("nag_rand_bb_make_bridge_order (g05xec) Example Program Results\n\n");
for ( p=1; p<=npaths; p++)
{
printf("%s ","Wiener Path ");
printf("%1ld ", p);
printf("%s ",", ");
printf("%1ld ",  ntimes + 1);
printf("%s "," time steps, ");
printf("%1ld ",  d);
printf("%s "," dimensions");
printf("\n");

for ( k=1; k<= d; k++)
{
printf("%10ld ", k);
}
printf("\n");

for (i=1; i<= ntimes+1; i++)
{
printf("%2ld ", i);
for (k=1; k<=d; k++)
{
printf("%10.4f", B(p, k + (i-1)*d));

}
printf("\n");

}
printf("\n");
}
}
```