using System; using System.Runtime.InteropServices;/* Provides mappings between C# and native code */ namespace NumericalAlgorithmsGroup { class OptNlp { /* Delegate objects, note that: 1) the scalar parameter is 'ref' 2) IntPtr is equivalent to the C void pointer. During a callback Fortran passes a void pointer as the parameter to C#. The memory pointed to by the IntPtr is reclaimed using Marshal.copy */ public delegate void NAG_E04UC_CONFUN (ref int mode, ref int ncnln, ref int n, ref int ldcj, IntPtr needc_ptr, IntPtr x_ptr, IntPtr c_ptr, IntPtr cjac_ptr, ref int nstate, IntPtr iuser_ptr, IntPtr user_ptr); public delegate void NAG_E04UC_OBJFUN (ref int mode, ref int n, IntPtr xc_ptr, ref double objf, IntPtr objgrd, ref int nstate, IntPtr iuser_ptr, IntPtr user_ptr); [DllImport("FLDLL214Z_nag.dll")]/* Import from DLL, the C# compiler provides a rudimentry check of the signature */ public static extern void E04UCA(ref int n, ref int nclin, ref int ncnln, ref int lda, ref int ldcj, ref int ldr, double [,] a, double [] bl, double [] bu, NAG_E04UC_CONFUN confun, NAG_E04UC_OBJFUN objfun, ref int iter, int [] istate, double [] c, double [,] cjac, double [] clamda, ref double objf, double [] objgrd, double [,] r, double [] x, int [] iwork, ref int liwork, double [] work, ref int lwork, int [] iuser, double [] user, int [] lwsav, int [] iwsav, double [] rwsav, ref int ifail); [DllImport("FLDLL214Z_nag.dll")] public static extern void E04WBF(string srname, int lensrname, string cwsav, int lencwsav, ref int lcwsav, int [] lwsav, ref int llwsav, int [] iwsav, ref int liwsav, double [] rwsav, ref int lrwsav, ref int ifail); [DllImport("FLDLL214Z_nag.dll")] public static extern void E04UEA(string option, int lenoption, int [] lwsav, int [] iwsav, double [] rwsav, ref int ifail); public static void Main() { /* Create delegate objects */ NAG_E04UC_CONFUN Confun = new NAG_E04UC_CONFUN(confunex); NAG_E04UC_OBJFUN Objfun = new NAG_E04UC_OBJFUN(objfunex); int n = 4; int nclin = 1; int ncnln = 2; int totalvars=n+nclin+ncnln; double [,] a = new double[nclin,n]; double [] bl = new double[totalvars]; double [] bu = new double[totalvars]; int iter=0; int [] istate = new int[totalvars]; double [] c = new double[ncnln]; double [,] cjac = new double[ncnln, n]; double [] clamda = new double[totalvars]; double objf=0.0; double [] objgrd = new double[n]; double [,] r = new double [n,n]; double [] x = new double[n]; int liwork = 3*n + nclin + 2*ncnln; int [] iwork = new int[liwork]; int lwork; if ( ncnln == 0 && nclin == 0) { lwork = 20*n; } else if (ncnln == 0 && nclin > 0) { lwork = 2*n*n + 20*n + 11*nclin; } else { lwork = 2*n*n + n *nclin + 2*n*ncnln + 20*n +11*nclin + 21*ncnln; } double [] work = new double[lwork]; int i, j; // Console.WriteLine("in main program, calling library via interface"); for (i = 0; i < nclin; ++i) { for (j = 0; j < n; ++j) { a[i,j] = 1.0; } } bl[0] = 1.0; bl[1] = 1.0; bl[2] = 1.0; bl[3] = 1.0; bl[4] = -1.0E+25; bl[5] = -1.0E+25; bl[6] = 25.0; bu[0] = 5.0; bu[1] = 5.0; bu[2] = 5.0; bu[3] = 5.0; bu[4] = 20.0; bu[5] = 40.0; bu[6] = 1.0E+25; x[0] = 1.0; x[1] = 5.0; x[2] = 5.0; x[3] = 1.0; string e04name = new string (' ', 7); e04name="E04UCA"; string cwsav = new string (' ', 81); int lcwsav = 1; int llwsav = 120; int [] lwsav = new int [llwsav]; int liwsav = 610; int [] iwsav = new int [liwsav]; int lrwsav = 475; double [] rwsav = new double [lrwsav]; int ifail = 1; int lene04name=7; int lencwsav=81; E04WBF(e04name, lene04name, cwsav, lencwsav, ref lcwsav, lwsav, ref llwsav, iwsav, ref liwsav, rwsav, ref lrwsav, ref ifail); ifail = 1; double [] ruser = new double[1]; int [] iuser = new int [1]; E04UEA("Print Level = 1", 15, lwsav, iwsav, rwsav, ref ifail); ifail = 1; E04UCA(ref n, ref nclin, ref ncnln, ref nclin, ref ncnln, ref n, a, bl, bu, Confun, Objfun, ref iter, istate, c, cjac, clamda, ref objf, objgrd, r, x, iwork, ref liwork, work, ref lwork, iuser, ruser, lwsav, iwsav, rwsav, ref ifail); } public static void objfunex(ref int mode, ref int n, IntPtr x_ptr, ref double objf, IntPtr objgrd_ptr, ref int nstate, IntPtr iuser, IntPtr ruser) { /* Function Body */ double [] x = new double[n]; Marshal.Copy( x_ptr, x, 0, n ); double [] objgrd = new double[n]; if (mode == 0 || mode == 2) { objf = x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2]; } if (mode == 1 || mode == 2) { objgrd[0] = x[3] * (x[0] * 2.0 + x[1] + x[2]); objgrd[1] = x[0] * x[3]; objgrd[2] = x[0] * x[3] + 1.0; objgrd[3] = x[0] * (x[0] + x[1] + x[2]); } Marshal.Copy( objgrd, 0, objgrd_ptr, n ); } public static void confunex(ref int mode, ref int ncnln, ref int n, ref int ldcj, IntPtr needc_ptr, IntPtr x_ptr, IntPtr c_ptr, IntPtr cjac_ptr, ref int nstate, IntPtr iuser_ptr, IntPtr user_ptr) { int [] needc = new int[ncnln]; Marshal.Copy( needc_ptr, needc, 0, ncnln ); double [] x = new double[n]; Marshal.Copy( x_ptr, x, 0, n ); double [] c = new double[ncnln]; Marshal.Copy( c_ptr, c, 0, ncnln ); double [] cjac = new double[ldcj*n]; /* Marshal.copy does not allow the type of cjac to be [,] */ Marshal.Copy( cjac_ptr, cjac, 0, ldcj*n ); if (nstate == 1) { /* First call to CONFUN. Set all Jacobian elements to zero. */ /* Note that this will only work when 'Derivative Level = 3' */ /* (the default; see Section 11.2). */ for (int j = 0; j < n; ++j) { for (int i = 0; i < ncnln; ++i) { /* Note the expression required to access the elements of sim in column major order*/ cjac[j*ncnln+i] = 0.0; } } } if (needc[0] > 0) { if (mode == 0 || mode == 2) { c[0] = x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3]; } if (mode == 1 || mode == 2) { cjac[0] = x[0] * 2.0; cjac[2] = x[1] * 2.0; cjac[4] = x[2] * 2.0; cjac[6] = x[3] * 2.0; } } if (needc[1] > 0) { if (mode == 0 || mode == 2) { c[1] = x[0] * x[1] * x[2] * x[3]; } if (mode == 1 || mode == 2) { cjac[1] = x[1] * x[2] * x[3]; cjac[3] = x[0] * x[2] * x[3]; cjac[5] = x[0] * x[1] * x[3]; cjac[7] = x[0] * x[1] * x[2]; } } /* cjac and C are output arrays hence the need to copy back */ Marshal.Copy(cjac, 0, cjac_ptr, ldcj*n); Marshal.Copy(c, 0, c_ptr, ncnln); } } }