blob: 0d4140bd1c750e1ff3d987bc51abf8df687f6a89 [file] [log] [blame]
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "HJM_type.h"
#include "HJM.h"
#include "nr_routines.h"
#ifdef TBB_VERSION
#include <pthread.h>
#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/cache_aligned_allocator.h"
#define PARALLEL_B_GRAINSIZE 8
struct ParallelB {
__volatile__ int l;
FTYPE **pdZ;
FTYPE **randZ;
int BLOCKSIZE;
int iN;
ParallelB(FTYPE **pdZ_, FTYPE **randZ_, int BLOCKSIZE_, int iN_)//:
// pdZ(pdZ_), randZ(randZ_), BLOCKSIZE(BLOCKSIZE_), iN(iN_)
{
pdZ = pdZ_;
randZ = randZ_;
BLOCKSIZE = BLOCKSIZE_;
iN = iN_;
/*fprintf(stderr,"(Construction object) pdZ=0x%08x, randZ=0x%08x\n",
pdZ, randZ);*/
}
void set_l(int l_){l = l_;}
void operator()(const tbb::blocked_range<int> &range) const {
int begin = range.begin();
int end = range.end();
int b,j;
/*fprintf(stderr,"B: Thread %d from %d to %d. l=%d pdZ=0x%08x, BLOCKSIZE=%d, iN=%d\n",
pthread_self(), begin, end, l,(int)pdZ,BLOCKSIZE,iN); */
for(b=begin; b!=end; b++) {
for (j=1;j<=iN-1;++j){
pdZ[l][BLOCKSIZE*j + b]= CumNormalInv(randZ[l][BLOCKSIZE*j + b]); /* 18% of the total executition time */
//fprintf(stderr,"%d (%d, %d): [%d][%d]=%e\n",pthread_self(), begin, end, l,BLOCKSIZE*j+b,pdZ[l][BLOCKSIZE*j + b]);
}
}
}
};
#endif // TBB_VERSION
void serialB(FTYPE **pdZ, FTYPE **randZ, int BLOCKSIZE, int iN, int iFactors)
{
for(int l=0;l<=iFactors-1;++l){
for(int b=0; b<BLOCKSIZE; b++){
for (int j=1;j<=iN-1;++j){
pdZ[l][BLOCKSIZE*j + b]= CumNormalInv(randZ[l][BLOCKSIZE*j + b]); /* 18% of the total executition time */
}
}
}
}
int HJM_SimPath_Forward_Blocking(FTYPE **ppdHJMPath, //Matrix that stores generated HJM path (Output)
int iN, //Number of time-steps
int iFactors, //Number of factors in the HJM framework
FTYPE dYears, //Number of years
FTYPE *pdForward, //t=0 Forward curve
FTYPE *pdTotalDrift, //Vector containing total drift corrections for different maturities
FTYPE **ppdFactors, //Factor volatilities
long *lRndSeed, //Random number seed
int BLOCKSIZE)
{
//This function computes and stores an HJM Path for given inputs
int iSuccess = 0;
int i,j,l; //looping variables
FTYPE **pdZ; //vector to store random normals
FTYPE **randZ; //vector to store random normals
FTYPE dTotalShock; //total shock by which the forward curve is hit at (t, T-t)
FTYPE ddelt, sqrt_ddelt; //length of time steps
ddelt = (FTYPE)(dYears/iN);
sqrt_ddelt = sqrt(ddelt);
pdZ = dmatrix(0, iFactors-1, 0, iN*BLOCKSIZE -1); //assigning memory
randZ = dmatrix(0, iFactors-1, 0, iN*BLOCKSIZE -1); //assigning memory
// =====================================================
// t=0 forward curve stored iN first row of ppdHJMPath
// At time step 0: insert expected drift
// rest reset to 0
for(int b=0; b<BLOCKSIZE; b++){
for(j=0;j<=iN-1;j++){
ppdHJMPath[0][BLOCKSIZE*j + b] = pdForward[j];
for(i=1;i<=iN-1;++i)
{ ppdHJMPath[i][BLOCKSIZE*j + b]=0; } //initializing HJMPath to zero
}
}
// -----------------------------------------------------
// =====================================================
// sequentially generating random numbers
for(int b=0; b<BLOCKSIZE; b++){
for(int s=0; s<1; s++){
for (j=1;j<=iN-1;++j){
for (l=0;l<=iFactors-1;++l){
//compute random number in exact same sequence
randZ[l][BLOCKSIZE*j + b + s] = RanUnif(lRndSeed); /* 10% of the total executition time */
}
}
}
}
// =====================================================
// shocks to hit various factors for forward curve at t
#ifdef TBB_VERSION
ParallelB B(pdZ, randZ, BLOCKSIZE, iN);
for(l=0;l<=iFactors-1;++l){
B.set_l(l);
tbb::parallel_for(tbb::blocked_range<int>(0, BLOCKSIZE, PARALLEL_B_GRAINSIZE),B);
}
#else
/* 18% of the total executition time */
serialB(pdZ, randZ, BLOCKSIZE, iN, iFactors);
#endif
// =====================================================
// Generation of HJM Path1
for(int b=0; b<BLOCKSIZE; b++){ // b is the blocks
for (j=1;j<=iN-1;++j) {// j is the timestep
for (l=0;l<=iN-(j+1);++l){ // l is the future steps
dTotalShock = 0;
for (i=0;i<=iFactors-1;++i){// i steps through the stochastic factors
dTotalShock += ppdFactors[i][l]* pdZ[i][BLOCKSIZE*j + b];
}
ppdHJMPath[j][BLOCKSIZE*l+b] = ppdHJMPath[j-1][BLOCKSIZE*(l+1)+b]+ pdTotalDrift[l]*ddelt + sqrt_ddelt*dTotalShock;
//as per formula
}
}
} // end Blocks
// -----------------------------------------------------
free_dmatrix(pdZ, 0, iFactors -1, 0, iN*BLOCKSIZE -1);
free_dmatrix(randZ, 0, iFactors -1, 0, iN*BLOCKSIZE -1);
iSuccess = 1;
return iSuccess;
}