/************************ Using C routines in Gauss under OS/2 Author: Richard Stanton Date: 3 Sep 1996 Provided without guarantees for public non-commercial use. I recently spent a while working out how to compile C code into a DLL file using the emx/gcc compiler under OS/2, and how to use the result with GAUSS. Doing this for just one small routine resulted in a 7-fold speedup in my program. 1) Here is the C code itself, rhs.c. It contains just one routine, tribksub1, which I use for repeatedly solving the equation Ax = d, for different values of the vector d, and where A is tridiagonal. For those who are interested, I have previously calculated the LU decomposition of A, and this routine now performs forward/backward substitution to calculate x. Since each value affects the next, it has to be done as a loop, which is why it's so slow in GAUSS. ***************************************************************/ /* rhs.c (emx+gcc) DLL for GAUSS */ int tribksub1(double n[], double a[], double beta[], double gamma[], double d[], double x[]) /* * Solve equation A x = d using output of routine TRILU (beta, gamma). * Suited for multiple RHS, since no divisions are performed in this routine. */ { int i; /* * Forward substitution */ x[0] = d[0] * beta[0]; for (i=1; i=0; i--) { x[i] -= gamma[i+1] * x[i+1]; } return 0; } /***************************************************************** 2) Here's the file rhs.def, which tells the compiler what function names to export, and some other stuff which I don't know or care about. It works, so here it is: ******************************************************************/ ; ; rhs.def ; LIBRARY RHS INITINSTANCE TERMINSTANCE DESCRIPTION 'rhs' DATA MULTIPLE NONSHARED EXPORTS tribksub1 @1 /************************************************************* 3) To create the file rhs.dll, use the command gcc -Zdll -Zomf -Zso -Zsys rhs.c rhs.def 4) Here's the section of GAUSS code that calls the function: dlibrary e:\gauss\dlib\rhs.dll; dllcall tribksub1(ny1, a, lu1, lu2, dL, prices); The output is stored in the vector prices. There are a couple of things to be aware of: 1) As Ron S pointed out, Gauss now has built-in functions to solve equations of the type I was solving, which would probably be even faster. 2) My function doesn't take the actual LU decomposition, but at least one of the vectors has all its elements inverted, or something similar, so that when I do the substitutions to solve the equation, I only use multiplication, and no division (which is typically a slower operation). The above provides an example of how to use DLLs with GAUSS under OS/2. If you actually want it to be usable, here is the function trilu, which calculates the (modified) LU decomposition used as input to tribksub1. Richard Stanton *************************************************************************/ /* * Calculate modified LU decomposition of tridiagonal matrix * as input for TRIBKSUB, solution of tridiagonal simultaneous equ. * Key to parameters passed: * a: array of left of diagonal entries. (Must include a[1] = .0) * b: array of diagonal entries. * c: array of right of diagonal entries. (Must include c[n] = .0) * * Call as {lu1, lu2} = trilu(a,b,c) * * lu1, lu2: outputs of routine, used with a as subsequent input for * TRIBKSUB. */ proc (2) = trilu(a, b, c); local i, n, lu1, lu2, temp; if b[1] == .0; errorlog "Error 1 in TRILU"; end; endif; n = rows(a); lu1 = zeros(n,1); lu2 = zeros(n,1); lu1[1] = 1.0 / b[1]; lu2[1] = 0.0; i = 2; do while i <= n; lu2[i] = c[i-1] * lu1[i-1]; temp = b[i] - a[i] * lu2[i]; if temp == 0.0; errorlog "Error 2 in TRILU"; end; endif; lu1[i] = 1.0 / temp; i = i+1; endo; retp(lu1, lu2); endp;