1.c#调用代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Holworth.Utility
{
[StructLayout(LayoutKind.Sequential)]
public class RandomNumberServiceProxy1
{
// //该方式是直接调用C++ DLL内的类的成员函数。 QAEXXZ
// [DllImport("RskCPlusPlusEngine.dll", EntryPoint = "?MyOGREHello@MyOGRE1@@QAEXXZ")]
// //[DllImport("RskCPlusPlusEngine.dll", EntryPoint = "?MyOGREHello@MyOGRE1@@QAEHH@Z", CharSet = CharSet.Auto)]
// public static extern void MyOGREHello();
[DllImport("ModelBank.dll",
// EntryPoint = "?GenerateInverseRandomNumber@RandomNumberService@@QAEXN@Z",CharSet = CharSet.Auto)]
EntryPoint = "?GenerateQuasiRandomNumber@RandomNumberService@@UAENHHPAPAN@Z")]
public static extern unsafe double GenerateQuasiRandomNumber(int M, int S, double** res);
[DllImport("ModelBank.dll",
// EntryPoint = "?GenerateInverseRandomNumber@RandomNumberService@@QAEXN@Z",CharSet = CharSet.Auto)]
EntryPoint = "?GenerateInverseRandomNumber@RandomNumberService@@QAENN@Z")]
public static extern double GenerateInverseRandomNumber(double X);
[DllImport("ModelBank.dll",
// EntryPoint = "?GenerateInverseRandomNumber@RandomNumberService@@QAEXN@Z",CharSet = CharSet.Auto)]
EntryPoint = "?test1@RandomNumberService@@QAEXPAPAPAH@Z")]
public static extern double test1(IntPtr[] res);
}
public class RandomNumberService
{
public double GenerateQuasiRandomNumber(int M, int S, double[][] R)
{
unsafe
{
IntPtr handle = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))*R.Length);// stackalloc double*[R.Length];
double** buffer = (double**)handle;
//double** buffer = stackalloc double*[R.Length];
for (int i = 0; i < R.Length; i++)
{
//从 COM 任务内存分配器分配指定大小的内存块。
//buffer[i] = Marshal.AllocHGlobal(Marshal.SizeOf(R[0][0]) * R[i].Length);
////将数据从一维的托管 32 位有符号整数数组复制到非托管内存指针。
//Marshal.Copy(R[i], 0, buffer[i], R[i].Length);
var s1 = stackalloc double[R[i].Length];
buffer[i] = s1;
for (int j = 0; j < R[i].Length; j++)
{
buffer[i][j] = R[i][j];
}
}
var d= RandomNumberServiceProxy1.GenerateQuasiRandomNumber(M, S, buffer);
Console.WriteLine("d===="+d);
System.Runtime.InteropServices.Marshal.FreeHGlobal(handle);
}
//for (int i = 0; i < R.Length; i++)
//{
// Marshal.Copy(buffer[i], R[i], 0, R[i].Length);
// // Marshal.FreeCoTaskMem(buffer[i]);
//}
return 0;
}
public double GenerateInverseRandomNumber(double X)
{
return RandomNumberServiceProxy1.GenerateInverseRandomNumber(X);
}
public double test1(int[][][] array3)
{
//创建用于封送的表示指针的数组,数组中的每个指针对应三维数组中的一个二维数组
IntPtr[] intPtrSet2 = new IntPtr[array3.Length];
//封装三维数组
for (int i = 0; i < array3.Length; i++)
{
//创建用于封装的表示指针的数组,数组中的每个指针对应二维数组中的一个一维数组
IntPtr[] intPtrSet1 = new IntPtr[array3[i].Length];
//记录二维数组中数据的总个数
int length = 0;
for (int j = 0; j < array3[i].Length; j++)
{
//分配相应大小的内存空间
intPtrSet1[j] = Marshal.AllocCoTaskMem(Marshal.SizeOf(array3[0][0][0]) * array3[i][j].Length);
length += array3[i][j].Length;
//将数据从一维的托管 数组复制到非托管内存指针
Marshal.Copy(array3[i][j], 0, intPtrSet1[j], array3[i][j].Length);
}
//分配相应大小的内存空间
intPtrSet2[i] = Marshal.AllocCoTaskMem(Marshal.SizeOf(array3[0][0][0]) * length);
//将数据从一维托管 IntPtr 数组复制到非托管内存指针
Marshal.Copy(intPtrSet1, 0, intPtrSet2[i], array3[i].Length);
////释放一维托管 IntPtr 数组
//for (int j = 0; j < array3[i].Length; j++)
//{
// Marshal.FreeCoTaskMem(intPtrSet1[j]);
//}
}
RandomNumberServiceProxy1.test1(intPtrSet2);
//////将数据从非托管指针还原在托管三维嵌套数组中
//for (int i = 0; i < array3.Length; i++)
//{
// //创建一维托管 IntPtr 数组
// IntPtr[] intPtrSet1 = new IntPtr[array3[i].Length];
// //将数据从非托管内存指针复制到托管 IntPtr 数组
// Marshal.Copy(intPtrSet2[i], intPtrSet1, 0, array3[i].Length);
// //释放非托管指针
// Marshal.FreeCoTaskMem(intPtrSet2[i]);
// //将数据存储在三维嵌套数组中
// for (int j = 0; j < array3[i].Length; j++)
// {
// Marshal.Copy(intPtrSet1[j], array3[i][j], 0, array3[i][j].Length);
// //Marshal.FreeCoTaskMem(intPtrSet1[j]);
// }
//}
return 0;
}
}
}
2.c++代码
IRandomNumberService.h
#pragma once
#define DLL_CLASS __declspec(dllexport)
#include <array>
#include <vector>
DLL_CLASS class IRandomNumberService
{
public:
virtual double GenerateQuasiRandomNumber(int M, int S, double** R)=0;
virtual double GenerateInverseRandomNumber(double X)=0;
};
RandomNumberService.h
//1.类的函数的内联实现
using namespace std;
#include "IRandomNumberService.h"
#define _USE_MATH_DEFINES
#ifndef ModelBankDll_H_
#define ModelBankDll_H_
#pragma once
#define DLL_EXPORTS
#ifdef DLL_EXPORTS
//#define DLL_API extern "C" __declspec(dllexport)
#define DLL_CLASS __declspec(dllexport)
#else
/*#define DLL_API extern "C" __declspec(dllimport) */
#define DLL_CLASS __declspec(dllimport)
#endif
class DLL_CLASS RandomNumberService :IRandomNumberService
{
public:
RandomNumberService()
{
}
// 通过 IRandomNumberService 继承
double GenerateQuasiRandomNumber(int M, int S, double** R) ;
double GenerateInverseRandomNumber(double X ) ;
double round(double f, int precious);
void test1(int ***r);
};
#endif
RandomNumberService.cpp
#include "stdafx.h"
#include "RandomNumberService.h"
#include <math.h>
#include<iomanip>
#include <iostream>
using namespace std;
//namespace Holworth_Services_Risk
//{
double RandomNumberService::round(double f, int precious)
{
double d = f - (int)f;//取小数部分。
d *= pow(10, precious);//小数点左移。
if (d - (int)d >= 0.5) d += 1; //四舍五入
d = (int)d; //取整数部分。
d /= pow(10, precious);//小数点右移。
d += (int)f;//加上原本的整数部分。
return d;
}
void RandomNumberService::test1(int ***R)
{
cout << "r[0][0][0]=" << R[0][0][0] << endl;
}
// 通过 IRandomNumberService 继承
double RandomNumberService::GenerateQuasiRandomNumber(int M, int S, double **R)
{
char *c = new char[10];
delete[] c;
cout << "r[0][0]======" << R[0][0] << endl;
bool primeVal;
bool flagVal;
double startNum;
double nextNum;
double divNum;
double A, Q, X, Y, Z;
double B = 0.0;
int M1 = 0;
int M2 = 0;
int L = 0;
int coeffNum[100][100] = { 0 };
double E[1000] = { 0.0 };
//S = 2;
//M = SetNum;
//obtain the base prime number which is greater than the number of time steps
if (S <= 2)
B = 2;
else if (S == 3)
B = 3;
else
{
for (int i = S; i <= 100000; i++)
{
primeVal = true;
flagVal = false;
L = i / 2;
for (int j = 2; j <= L; j++)
{
if (i % j == 0)
primeVal = false;
if ((j == L) && (primeVal))
{
B = i;
flagVal = true;
break;
}
}
if (flagVal)
break;
}
}
if (B > 3)
startNum = B * (B - 1) * (B - 2);
else
startNum = pow(B, 3);
M1 = (int)((log(startNum + M) / log(B))) + 1;
//create the coefficient matrix
for (int i = 0; i < M1; i++)
{
for (int j = 0; j < M1; j++)
{
if ((i == 0) || (i == j))
coeffNum[i][j] = 1;
else if (j > i)
coeffNum[i][j] = (int)((coeffNum[i][j - 1] + coeffNum[i - 1][j - 1]) % (int)B);
else
coeffNum[i][j] = 0;
}
}
for (int n = 0; n < M; n++)
{
if (n == 0)
{
nextNum = startNum - 1;
divNum = startNum / B;
M2 = (int)((log(nextNum) / log(B))) + 1;
}
//produce the expansion series
Q = nextNum;
for (int i = 0; i < M2; i++)
{
E[i] = fmod(Q, B);
Q = floor(Q / B);
}
//generate the Faure sequence
for (int i = 0; i < S; i++)
{
X = 0;
if (i == 0)
{
for (int j = 0; j < M2; j++)
{
A = E[M2 - j - 1];
X = A + X / B;
}
X /= B;
}
else
{
Y = 1 / B;
for (int k = 0; k < M2; k++)
{
Z = 0;
for (int j = 0; j < M2; j++)
{
if (j >= k)
Z += E[j] * coeffNum[k][j];
}
A = fmod(Z, B);
E[k] = A;
X += Y * A;
Y /= B;
}
}
//cout << "前置b" << sizeof(R) / sizeof(double) << endl;
////*(*(R + n) + i) = X;
R[n][i] = X;
// cout << "后置b" << sizeof(R) / sizeof(double) << endl;
}
nextNum++;
if (fmod(nextNum, divNum) == 0)
{
divNum *= B;
M2++;
}
}
double d = 123456;
return d;
}
double RandomNumberService::GenerateInverseRandomNumber(double X)
{
cout << X << endl;
//double X = 3.0;
double A1 = 0.31938153;
double A2 = -0.356563782;
double A3 = 1.781477937;
double A4 = -1.821255978;
double A5 = 1.330274429;
double D = 0.2316419;
double K, DK, Y, Z, XX, YY, ZZ;
//CALCULATIONS OF INVERSE OF CUMULATIVE STANDARD NORMAL DISTRIBUTION WITH NEWTON-RAPHSON ALGORITHM
Z = X;
if (Z >= 0.5)
X = 0.5;
else
X = -0.5;
for (int i = 0; i < 10000; i++)
{
if (X >= 0.0)
{
ZZ = exp(-X * X / 2) / sqrt(2 * M_PI);
K = 1 / (1 + D * X);
DK = -D / pow(1 + D * X, 2);
XX = 1 - ZZ * (A1 * K + A2 * K * K + A3 * K * K * K + A4 * pow(K, 4) + A5 * pow(K, 5));
YY = ZZ * (A1 * (K * X - DK) + A2 * K * (K * X - 2 * DK) + A3 * K * K * (K * X - 3 * DK) + A4 * pow(K, 3) * (K * X - 4 * DK) + A5 * pow(K, 4) * (K * X - 5 * DK));
}
else
{
ZZ = exp(-X * X / 2) / sqrt(2 * M_PI);
K = 1 / (1 - D * X);
DK = D / pow(1 - D * X, 2);
XX = ZZ * (A1 * K + A2 * K * K + A3 * K * K * K + A4 * pow(K, 4) + A5 * pow(K, 5));
YY = ZZ * (A1 * (-K * X + DK) + A2 * K * (-K * X + 2 * DK) + A3 * K * K * (-K * X + 3 * DK) + A4 * pow(K, 3) * (-K * X + 4 * DK) + A5 * pow(K, 4) * (-K * X + 5 * DK));
}
Y = X - (XX - Z) / YY;
if (abs(Y - X) <= 0.0001)
break;
X = Y;
}
cout << "1234" << endl;
return round(X, 3);
// return 11111;
}
//}