// Black-Scholes formula for both call and put HEMI_KERNEL(BlackScholes) (float *callResult, float *putResult, const float *stockPrice, const float *optionStrike, const float *optionYears, float Riskfree, float Volatility, int optN) { int offset = hemiGetElementOffset(); int stride = hemiGetElementStride(); for(int opt = offset; opt < optN; opt += stride) { float S = stockPrice[opt]; float X = optionStrike[opt]; float T = optionYears[opt]; float R = Riskfree; float V = Volatility; float sqrtT = sqrtf(T); float d1 = (logf(S / X) + (R + 0.5f * V * V) * T) / (V * sqrtT); float d2 = d1 - V * sqrtT; float CNDD1 = CND(d1); float CNDD2 = CND(d2); //Calculate Call and Put simultaneously float expRT = expf(- R * T); callResult[opt] = S * CNDD1 - X * expRT * CNDD2; putResult[opt] = X * expRT * (1.0f - CNDD2) - S * (1.0f - CNDD1); } }
__global__ void init_device_rngs(int nthreads, unsigned long long seed, curandStateXORWOW* state) { int idx = hemiGetElementOffset(); if (idx >= nthreads) { return; } curand_init(seed, idx, 0, &state[idx]); }
HEMI_DEV_CALLABLE_INLINE void pick_new_vector_device(int nthreads, RNGState* rng, const float* sigma, const double* current_vector, double* proposed_vector) { int offset = hemiGetElementOffset(); int stride = hemiGetElementStride(); for (int i=offset; i<(int)nthreads; i+=stride) { #ifdef HEMI_DEV_CODE double u = curand_normal(&rng[i]); proposed_vector[i] = current_vector[i] + sigma[i] * u; #else double u = gRandom->Gaus(current_vector[i], sigma[i]); proposed_vector[i] = u; #endif } }
// append all steps to jump buffer int count = counter[0]; for (unsigned i=0; i<nparameters; i++) { jump_buffer[count * (nparameters + 1) + i] = v_current[i]; } jump_buffer[count * (nparameters + 1) + nparameters] = nll_current[0]; counter[0] = count + 1; } HEMI_KERNEL(nll_event_chunks)(const float* __restrict__ lut, const int* __restrict__ dataweights, const double* __restrict__ pars, const size_t ne, const size_t ns, double* sums) { int offset = hemiGetElementOffset(); int stride = hemiGetElementStride(); double sum = 0; for (int i=offset; i<(int)ne; i+=stride) { double s = 0; for (size_t j=0; j<ns; j++) { float v = lut[j * ne + i]; s += pars[j] * (!isnan(v) ? v : 0); // handle nans from empty hists } sum += log(s)*dataweights[i]; } if (!isnan(sum)) { sums[offset] = sum; } }