Wednesday, November 30, 2011

NOTES GSL

Prerequisites
Building using Visual Studio C/C++
GSL Examples
GSL Considerations
Build GSL with MinGW
Running MSVC with minGW-built-GSL
GSL Makefile
General C define macros and typedef
GSL-C-Fortran Framework

Prerequisites
===============
For running on Windows system:

1. mingw (minimalist GNU for Windows)
- go to http://www.mingw.org/
- Download and install both mgw and msys: eg. mingw-get-inst-20110802.exe
- Install and select C++, Fortran and MSYS options

2. gsl (Gnu Scientific Library)
- go to http://www.gnu.org/s/gsl/
- Download from nearest GNU mirror, eg. http://ftpmirror.gnu.org/gsl/.
- Unpack it to a general place like c:\gsl....

Building using Visual Studio C/C++
===================================
http://gladman.plushost.co.uk/oldsite/computing/gnu_scientific_library.php
http://www.quantcode.com/modules/smartfaq/faq.php?faqid=33


The GSL subroutines are grouped according to functionality. For this document, we say that these functionalities are grouped into packages. Each package is a folder containing the source code for that functionality. In this section, we will compile the package called BLAS.

Note that this BLAS is actually gls_blas. It uses the underlying blas implementation called cblas.
cblas is the standard blas for C/C++ and is also available in MKL.
In this example build, we will build the gsl_blas and configure is to use cblas from MKL.

1. Create a Visual Studio C/C++ Project called GSLProj, under the Solution called GSLSoln.
Add New Project - Visual C++ - Win32 - Win32 Project - {DLL, Empty Project}

2. Go to Windows Explorer and copy the blas folder from c:\gsl....
and paste into the GSLProj folder.
Update: The following packages seemed to be a bare minimum and have enabled GSL to be compiled successfully with MSVC 2008 - blas, block, err, ieee-utils, matrix, sys, test, vector.
Update: Second batch of packages to be added:
- cdf, cheb, complex, eigen, integration, linalg, min, multimin, multiroots, permutation, poly, randist, rng, roots, sort, specfun,

3. In Windows Explorer, copy these files from c:\gsl
    config.h , templates_on.h, templates_off.h, build.h
and paste into the GSLProj folder.

4. In Windows Explorer, under c:\gsl...., do a search for gsl_*.h. This will find all the gsl header files in the source code. Copy all of these and paste into a folder called gsl and put this folder under the GSLProj folder.

5. Go back to the Visual Studio GSLProj, go to the Solution Explorer and click on the little icon called "Show All Files" just on top of the Solution tree.

6. In the Solution Explorer, the tree becomes a folder tree view. Go to the branch GSLProj, right click on the blas folder (which appears now) and select "Include in Project". Inlcude any other project as necessary, only include their *.c is OK. All header files do not need to be INCLUDED via Visual Studio because the C compiler will pull the contents of *.h hearder files in.

7. For the ieee-utils package, exclude the files below which are for various different operating systems other than Windows. These files have names like: fp-[OS].c
Including fp.c seems to be OK.

For the matrix package, Include the matrix folder into the project.
Then exclude files: *.h, *.lo, *_source.c
Ensure that normal c files are included:   *.c
Note that the *_source.c files are actually pulled into the base *.c file similar to how header files are included.

Specfun package also has these *.c files to be excluded from compile:
cheb_eval.c, cheb_eval_mode.c
 
In many matrix files, eg copy_source.c, file_source.c, getset_source.c, the copy.c, file.c, getset.c uses the templates_on/off.h which dynamically creates code using Preprocessor Macro definitions. This causes SEVERE problems at the line:
#define SHORT complex
because Microsoft Visual C redefines this in their math.h file as:
#define complex _complex
DO  NOT Put this macro definition /D__cplusplus  which may solve the _complex problem but creates new problems with other MS files like:

Error 1 error C2061: syntax error : identifier 'vc_attributes' c:\program files\microsoft visual studio 9.0\vc\include\codeanalysis\sourceannotations.h 42 VCPP_testDLL01

To solve the _complex problem definition, add this at the top of templates_on.h:
#ifdef complex
#define fixCOMPLEX_ 1
#undef complex
#endif

Also add this at the end of templates_off.h
// ASSUMES that the predefined complex is _complex in Microsoft's VC include\math.h and crt\src\math.h
#if fixCOMPLEX_ == 1
#define complex _complex
#undef fixCOMPLEX_
#endif

8. Right click on the GSLProj icon and select properties. In the Properties configuration, Configuration Properties:
- under C/C++ - Command Line
Add these compiler options: /DGSL_DLL /DDLL_EXPORT
- under C/C++ - General - Additional Include Directories:
      enter the path to the current project folder.
 enter the path to \mkl\include
- under Linker - General - Additional Library Directories:
      enter \fortran\lib\ia32
 enter \mkl\ia32\lib
- under Linker - Input - Additional Dependencies, enter these mkl, openmp libraries
   for 32bit:
mkl_intel_c_dll.lib
mkl_intel_thread_dll.lib
mkl_core_dll.lib
libiomp5md.lib
   for 64bit:
mkl_intel_lp64_dll.lib
mkl_intel_thread_dll.lib
mkl_core_dll.lib
libiomp5md.lib

The setup above enable the project to be linked to MKL's cblas routines.

9. Edit the config file so that the "!" is removed in the following lines:
#if HAVE_DECL_LDEXP
#if HAVE_DECL_FREXP
#if HAVE_DECL_HYPOT
For some reason the use of preprocessor macros does not seem to work well. Hence the config.h file need to be modified as above.

10. Removing cblas from GSL code.
- Exclude the cblas directory from the project
- Exclude the file gsl\gsl_cblas.h
- Remove the line
     #include
  and replace if necessary with
     #include
  for these files:
blas\blas.c
doc\examples\cblas.c    // probably not needed
eigen\francis.c
eigen\nonsymmv.c
gsl_blas_types.h

11. Due to using mkl_cblas.h, these definitions need to be changed.
in gsl_blas_types.h, change to:
typedef  CBLAS_ORDER       CBLAS_ORDER_t;
typedef  CBLAS_TRANSPOSE   CBLAS_TRANSPOSE_t;
typedef  CBLAS_UPLO        CBLAS_UPLO_t;
typedef  CBLAS_DIAG        CBLAS_DIAG_t;
typedef  CBLAS_SIDE        CBLAS_SIDE_t;
... the enum keyword has been removed.

12. Add the following Preprocessor definitions
/P    - only to check the preprocessed intermediate files

13. To add cdf package:
- add this to beta_inc.c
#include
- exclude from project, usually because these files are included in other files and are not really standalone files:
test_auto.c, beta_inc.c

cdf package needs the following packages:
specfun, cheb


14. Various packages of GSL, such as block and matrix, have some files with the same names such as file.c.
But the way MSVC compiles and builds by putting all *.obj files into the same DEBUG or RELEASE folder causes a problem. A simple way is to rename some of the clashing file names. This does not affect the ability to use the GSL-DLL functions, because functions have different names withing files with same names such as file.c

To quickly identify where duplicate filenames exist, go to Solution Explorer and click on the GSLProj project folder.
Near the top of the Solution Explorer panel, click on the icon to switch to Show All Files, such that all *.c files appear under the Source Files folder under your GSLProj project folder. Then rename any duplicate file names *.c.

Alternative - Right-click, Properties, C++, Output Files. Change the Object File Name from $(IntDir)\ to, say, $(IntDir)\block\. You can repeat for the vector file group, etc.

15. Inline functions.
The following packages are affected: cdf
MSVC++ accepts both inline and _inline BUT when the code is *.c and compiled with MSVC, then it only recognize _inline.
Error Messages are like:
Error 1 error C2054: expected '(' to follow 'inline' ...\specfunc\cheb_eval_mode.c
Error 2 error C2085: 'cheb_eval_mode_e' : not in formal parameter list ...\specfunc\cheb_eval_mode.c
Error 3 error C2143: syntax error : missing ';' before '{' ...\specfunc\cheb_eval_mode.c 6
Solution:
In specfun/cheb_eval_mode.c, airy.c , gamma.c, bessel.c, bessel_olver, bessel_zero, coupling.c, ellint.c
erfc.c, legendre_con, trig.c, zeta.c
change from inline to _inline

16. Notes on cdf and specfun packages.
- see 15. for "inline" issue
- Files to be renamed from *.c to *_cdf.c are:
     cdf/beta.c   to avoid clash with specfun/beta.c
- files to be excluded from compile:
cdf/beta_inc.c

 17. Add randist package - needed by cdf
 - inline keyword modified, see note 15; for files:
     binomial_tpe.c, discrete.c, shuffle.c
 - Files to be renamed from *.c to *_randist.c are:
     beta.c, binomial.c, cauchy.c, chisq.c, exponential.c, exppow.c, fdist.c, flat.c, gamma.c,
gauss.c, geometric.c, hyperg.c, laplace.c, logistic.c, lognormal.c, nbinomial.c, pareto.c, pascal.c, poisson.c, rayleigh.c, rdist.c, weibull.c

18. Add rng package - needed by randist
 - inline keyword modified, see note 15; for files:
     ... almost all files ...
 - Files to be renamed from *.c to *_rng.c are:
     file.c

19. Add complex package - needed by specfun
 - Files to be renamed from *.c to *_complex.c are:        
     inline.c

20. Add eigen package - needed by specfun
 - inline keyword modified, see note 15; for files:
     gen.c, francis.c, qrstep.c, jacobi.c,
- Remove           //#include
  and replace by     #include
  in these files:    francis.c, nonsymmv.c
- exclude from project:
      qrstep.c


21. Add linalg package - needed by
 - inline keyword modified, see note 15; for files:
     apply_givens.c, cholesky.c, givens.c, exponential.c
- exclude from project:
     apply_givens.c, givens.c, svdstep.c


22. Add permutation package - needed by linalg
 - inline keyword modified, see note 15; for files:
 - Files to be renamed from *.c to *_permutation.c are:        
      file.c, init.c, inline.c,
- exclude from project:
      permute_source.c


Add integration package - needed by randist
 - inline keyword modified, see note 15; for files:
    append.c, initialise.c, positivity.c, set_initial.c, qpsrt.c, util.c, reset.c, qelg.c,
 - Files to be renamed from *.c to *_integration .c are:        
     
- exclude from project:
     append.c, cquad_const.c, err.c, initialise.c, positivity.c, ptsort.c, qpsrt.c, util.c, reset.c
qelg.c, qc25c.c, qc25f.c, qc25s.c, qpsrt2.c, set_initial.c,

NOTE: if some *.c files which are included by other *.c files are NOT excluded from compile, then errors like these occur:
Error 1 error C2143: syntax error : missing ')' before '*'
Error 2 error C2143: syntax error : missing '{' before '*'
Error 3 error C2059: syntax error : 'type'
Error 4 error C2059: syntax error : ')'


Add sort package - needed by eigen
 - inline keyword modified, see note 15; for files:
     sort.c, sortind.c, sortvec_source.c, sortvecind_source.c,
 - Files to be renamed from *.c to *_sort.c are:        
     
- exclude from project:
     sortvec_source.c, sortvecind_source.c, subset_source.c,  subsetind_source.c,
test_heapsort.c, test_source.c,


Add min package - for minimization routines
-  Add static to these functions:
      min/test.c::my_error_handler()


Add roots package
 - inline keyword modified, see note 15; for files:
 - Files to be renamed from *.c to *_roots.c are:        
      test.c, test_funcs.c
- exclude from project:


Add multimin package
 - inline keyword modified, see note 15; for files:
      simplex2.c
 - Files to be renamed from *.c to *_multimin.c are:
      test.c, test_funcs.c
- exclude from project:
directional_minimize.c, linear_minimize.c, linear_wrapper.c,


Add poly package - needed by multimin
 - inline keyword modified, see note 15; for files:
 - Files to be renamed from *.c to *_multimin.c are:
      test.c, eval.c, deriv.c,
- exclude from project:
 companion.c, balance.c, qr.c,


Add multiroots package
 - inline keyword modified, see note 15; for files:
 - Files to be renamed from *.c to *_multiroots.c are:
      convergence.c, fdfsolver.c, fsolver, newton.c, test_funcs.c, test.c
- exclude from project:
      enorm.c, dogleg.c




23. To make use of GSL's own test, do the following to the selected GSL packages as needed:
cdf, specfunc, rng, randist, min, roots, multimin, poly,

- eg. in cdf/test.c  (which has been renamed to test_cdf.c), rename the function
     main      to    main_cdf.c

- ensure say, cdf/test.c  is now included in the project and compile.

- for the test functions, say: void main_cdf(void)
  put its prototype function in your own driver program using extern, like:
     extern "C" { void main_cdf(void);  }

- in the main functions, say main_cdf(), at the last line of the function, change this:
     exit(gsl_test_summary());
  to this, to return the EXIT_SUCCESS or EXIT_FAILURE code
     return gsl_test_summary();

- in the main functions, say main_sf(), if there are arguments that are not used like this:
     int main_sf(int argc, char * argv[])
  to the following
     int main_sf(void)

- in cdf package ONLY: in file test_cdf.c, change the line from:
     void test_gamma (void)
  to rename it to:
     void test_gamma_cdf (void)
  and in the same file, change the call to the test_gamma function from:
     test_gamma();
  to the new name :
     test_gamma_cdf();
  This is done to prevent clash with a function of the same name test_gamma() in specfunc.

- in randist package only, change the following functions by adding the keyword "static",
  so that other files to not uses these functions. The functions made "static" are:
     test_beta, test_binomial_pdf, test_chisq, test_exponential, test_fdist, test_gamma,
test_ugaussian, test_geometric_pdf, test_hypergeometric2_pdf, test_negative_binomial_pdf,
test_pascal_pdf, test_poisson_pdf

- in roots package only, change the following functions by adding the keyword "static",
  so that other files to not uses these functions. The functions / variables made "static" are:
     test_roots.c: EPSREL, EPSABS, MAX_ITERATIONS, test_f, test_f_e, my_error_handler,
test_funcs_roots.c: create_function, func1, func2, func3, func4

- in multimin package only, change the following functions by adding the keyword "static",
  so that other files to not uses these functions. The functions / variables made "static" are:
     test_fdf, test_f,

- in multiroots package only, change the following functions by adding the keyword "static",
  so that other files to not uses these functions. The functions / variables made "static" are:
     test_multiroots.c: test_fdf, test_f,
     test_funcs_multiroots.c: rosenbrock, rosenbrock_initpt, rosenbrock_f, rosenbrock_df, rosenbrock_fdf,
wood, wood_initpt, wood_f, wood_df, wood_fdf,
     roth, roth_initpt, roth_f, roth_df, roth_fdf,

- Strange reason, the two functions gsl_cdf_logistic_Q and  gsl_cdf_logistic_P are not visible to the test program and cannot be compiled. Typical error messages are:
Error 1  error LNK2001: unresolved external symbol gsl_cdf_logistic_Q test_cdf.obj vcpp_gsl
Error 1  error LNK2019: unresolved external symbol gsl_cdf_logistic_Q test_cdf.obj vcpp_gsl
    to solve this problem, go to the file cdf/logistic.c and copy the two functions of
gsl_cdf_logistic_Q and  gsl_cdf_logistic_P
    and paste it to cdf/test_auto.c and place it above the line:
void test_auto_logistic (void)
    ALTERNATIVE: Better solution is to check no two source files has the same name. This is already described in point 15. When two files have same name, one of them is not compiled and so its functions cannot be found.

- other files where functions are already identified somewhere else in test*.c. The solution is to add the static keyword to these functions:
   test_integration.c: my_error_handler
   test_linalg.c: my_error_handler


Debugging:
Modified test_roots.c: void test_f, test\results.c: void gsl_test()
Completed [12017/12017]
GSL cdf test result is 0
 end of gsl cdf test
Completed [14995/14995]
GSL specfunc test result is 0
 end of gsl specfunc test
-10, 1072693247, 0, 0
FAIL: results.c::gsl_test:: [15003]incorrect precision (%g obs vs %g expected)
-16, 1072693247, -350469331, 1058682594
FAIL: results.c::gsl_test:: [15005]incorrect precision (%g obs vs %g expected)
2142418408, 1061077358, 0, 0
FAIL: results.c::gsl_test:: [15007]incorrect precision (%g obs vs %g expected)
-13, 1072693247, -350469331, 1058682594
FAIL: results.c::gsl_test:: [15020]incorrect precision (%g obs vs %g expected)
2142401953, 1061077358, 0, 0
FAIL: results.c::gsl_test:: [15022]incorrect precision (%g obs vs %g expected)
-10, 1072693247, 0, 0
FAIL: results.c::gsl_test:: [15034]incorrect precision (%g obs vs %g expected)
-13, 1072693247, -350469331, 1058682594
FAIL: results.c::gsl_test:: [15036]incorrect precision (%g obs vs %g expected)
2142401953, 1061077358, 0, 0
FAIL: results.c::gsl_test:: [15038]incorrect precision (%g obs vs %g expected)
FAIL: results.c::gsl_test:: [15064]%s, %s (%g obs vs %g expected)
FAIL: results.c::gsl_test:: [15065]exceeded maximum number of iterations
FAIL: results.c::gsl_test:: [15066]incorrect precision (%g obs vs %g expected)
FAIL: results.c::gsl_test:: [15068]incorrect precision (%g obs vs %g expected)
FAIL: results.c::gsl_test:: [15070]incorrect precision (%g obs vs %g expected)
FAIL: results.c::gsl_test:: [15072]%s, %s
GSL roots test result is 1
 end of gsl roots test




GSL Examples
================
http://apwillis.staff.shef.ac.uk/aco/freesoftware.html  - passing function as argument
http://www.helsinki.fi/~fyl_tlpk/luento/ohj-13-GSL-e.html - passing function as argument
Fortran GSL
http://www.lrz.de/services/software/mathematik/gsl/fortran/index.html
http://uncwddas.googlecode.com/svn/trunk/other/gsl-1.8/gsl.vc/gsl.vc8.readme.txt


GSL Considerations
===================
32-64 bit
cblas replace with blas - can used ATLAS (C) at least


Build GSL with MinGW
========================
MSVC and MinGW Dlls - shows how to build Dll using MinGW that can be used by MSVC
http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs

GSL can be build using MinGW with the following commands:
configure
OR  to just make a dynamic library without static lib;
./configure --enable-static=no
then
  make

In general, to specify on conditions and macro definitions:
env CPPFLAGS="-DGSL_DLL"  ./configure --enable-static=no
./configure --enable-static=no CPPFLAGS="-DGSL_DLL"
Don't need to add GSL_DLL definition - this is just an exmaple.


The result is are the following files:
in [gsl]\cblas\.libs:  libgslcblas.dll.a, libgslcblas.a, libgslcblas-0.dll, libgslcblas.la, libgslcblas.lai
in [gsl]\libs: libgsl.dll.a, libgsl.a, libgsl-0.dll, libgsl.la, libgsl.lai

If there are errors during MAKE, like these:
    infnan.c:98:3: error: #error "cannot define gsl_finite without HAVE_DECL_FINITE or HAVE_IEEE_COMPARISONS"
    infnan.c:115:3: error: #error "cannot define gsl_isnan without HAVE_DECL_ISNAN or HAVE_IEEE_COMPARISONS"
to solve this, go into [gsl]\config.h  and remove the UNDEF lines and add DEFINE lines like:
   //#undef HAVE_DECL_ISFINITE
   #define HAVE_DECL_ISFINITE 1

   //#undef HAVE_DECL_ISNAN
   #define HAVE_DECL_ISNAN 1


To make GSL compatible with MSVC(Microsoft Visual C), then edit gsl_types.h file, to ensure that the following line is defined:


 
Run-Time Check Failure #0 - The value of ESP was not properly saved
across a function call.  This is usually a result of calling a function
declared with one calling convention with a function pointer declared
with a different calling convention.

The message above about calling convention is misleading. The gsl dll may be in the right calling convention already. The caller to the functions in gsl need to specify explicitly
    __cdel(dllimport)
on the prototype for the function they need to call.


Running MSVC with minGW-built-GSL
===================================
First, built the GSL using MinGW as described in "Build GSL with MinGW" section.
Then,
To LINK with MSVC, use the *.dll.a, but rename them to *.lib
To RUN with MSVS, put the *-0.dll files into the runtime path.

Error Message when running
"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."

..... need to check calling conventions.


Aside: To convert MSVC *.lib into *.a for GNU/GCC in MinGW, use the tool called "reimp".


GSL Makefile
=============
some key definitions of the Makefile is below.

$(SHELL) $(top_builddir)/libtool

libgsl.la: $(libgsl_la_OBJECTS) $(libgsl_la_DEPENDENCIES)
$(libgsl_la_LINK) -rpath $(libdir) $(libgsl_la_OBJECTS) $(libgsl_la_LIBADD) $(LIBS)


92:
libgsl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libgsl_la_LDFLAGS) $(LDFLAGS) -o $@
294:
libdir = ${exec_prefix}/lib
343:
libgsl_la_LIBADD = $(SUBLIBS) $(am__append_1)
233:
LIBS = -lm
234:
LIBTOOL = $(SHELL) $(top_builddir)/libtool
112:
CCLD = $(CC)
184:
CFLAGS = -g -O2
344:
libgsl_la_LDFLAGS = -version-info $(GSL_LT_VERSION) $(am__append_2)


90:
am_libgsl_la_OBJECTS = version.lo
libgsl_la_OBJECTS = $(am_libgsl_la_OBJECTS)

88:
libgsl_la_DEPENDENCIES = $(SUBLIBS) $(am__append_1)
43:
am__append_1 = cblas/libgslcblas.la
44:
am__append_2 = -no-undefined
315:
SUBLIBS = block/libgslblock.la blas/libgslblas.la \
bspline/libgslbspline.la complex/libgslcomplex.la \
cheb/libgslcheb.la dht/libgsldht.la diff/libgsldiff.la \
deriv/libgslderiv.la eigen/libgsleigen.la err/libgslerr.la \
fft/libgslfft.la fit/libgslfit.la histogram/libgslhistogram.la \
ieee-utils/libgslieeeutils.la integration/libgslintegration.la \
interpolation/libgslinterpolation.la linalg/libgsllinalg.la \
matrix/libgslmatrix.la min/libgslmin.la monte/libgslmonte.la \
multifit/libgslmultifit.la multimin/libgslmultimin.la \
multiroots/libgslmultiroots.la ntuple/libgslntuple.la \
ode-initval/libgslodeiv.la ode-initval2/libgslodeiv2.la \
permutation/libgslpermutation.la \
combination/libgslcombination.la multiset/libgslmultiset.la \
poly/libgslpoly.la qrng/libgslqrng.la randist/libgslrandist.la \
rng/libgslrng.la roots/libgslroots.la siman/libgslsiman.la \
sort/libgslsort.la specfunc/libgslspecfunc.la \
statistics/libgslstatistics.la sum/libgslsum.la \
sys/libgslsys.la test/libgsltest.la utils/libutils.la \
vector/libgslvector.la cdf/libgslcdf.la \
wavelet/libgslwavelet.la


Sample of actual output in Make:

libtool: link: ln .libs/libgsl.lax/libgslcdf.a/fdist.o .libs/libgsl.lax/lt72-fdist.o || cp .libs/libgsl.lax/libgslcdf.a/fdist.o .libs/libgsl.lax/lt72-fdist.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/flat.o .libs/libgsl.lax/lt73-flat.o || cp .libs/libgsl.lax/libgslcdf.a/flat.o .libs/libgsl.lax/lt73-flat.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/gamma.o .libs/libgsl.lax/lt74-gamma.o || cp .libs/libgsl.lax/libgslcdf.a/gamma.o .libs/libgsl.lax/lt74-gamma.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/gauss.o .libs/libgsl.lax/lt75-gauss.o || cp .libs/libgsl.lax/libgslcdf.a/gauss.o .libs/libgsl.lax/lt75-gauss.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/geometric.o .libs/libgsl.lax/lt76-geometric.o || cp .libs/libgsl.lax/libgslcdf.a/geometric.o .libs/libgsl.lax/lt76-geometric.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/laplace.o .libs/libgsl.lax/lt77-laplace.o || cp .libs/libgsl.lax/libgslcdf.a/laplace.o .libs/libgsl.lax/lt77-laplace.o
libtool: link: ln .libs/libgsl.lax/libgslcdf.a/logistic.o .libs/libgsl.lax/lt78-logistic.o || cp .libs/libgsl.lax/libgslcdf.a/logistic.o .libs/libgsl.lax/lt78-logistic.o



General C define macros and typedef
=====================================
#define [dummy] [real text]
eg.
# define __BEGIN_DECLS extern "C" {

this means whenever the "__BEGIN_DECLS" is used in the code, the pre-processor will replace it with:
extern "C" {


typedef [type] [alias]
eg.

/* type declaration */
typedef struct {
int number;
char *text;
} LINE;


/* Variable declaration */
LINE buffer[MAXLINES];


Note the actual type, like the struct above, is declared first, followed by the last word which is the alias LINE.
BUT, this is reverse for #define where the actual alias or dummy is the first word, then the rest are the real text.

An alternative way to declare a struct using "tag" is:

/* type declaration */
struct templ {
int number;
char *text;
} ;
/* Variable declaration */
struct templ buffer[MAXLINES];


Note that using the tag method for struct, the keyword struct still need to be included in the declaration.



GSL-C-Fortran Framework
=======================
1. Compile the GSL into a library with vcpp_gsl.lib|.bin, see "Building using Visual Studio C/C++"
2. Create a wrapper C++ project, say gslCwrap.
3. Create a header file gslCwrap.h and code file gslCwrap.c
4. In the header file gslCwrap.h
a) prepare to export the wrappers.

extern "C"{
__declspec(dllexport) void cdfGaussP (double x, double *p);
__declspec(dllexport) void fnGamma (double x, double *gamma);
}

b) include reference to GSL header like and call gsl function:

#include "gsl/gsl_cdf.h"
#include "gsl/gsl_sf_gamma.h"
void cdfGaussP (double x, double *p) {      *p =  gsl_cdf_ugaussian_P(x); }// 2 * x;  }
void fnGamma (double x, double *gamma) {    *gamma = gsl_sf_gamma(x); }

the actual gsl function names used here are: gsl_cdf_ugaussian_P, gsl_sf_gamma


5. To call from Fortran, prepare a Fortran interface:

    interface
        SUBROUTINE cdfGauss_P(x, P)  BIND(C, NAME='cdfGaussP')
            USE, INTRINSIC :: ISO_C_BINDING     ! New Fortran 2003 standard
            IMPLICIT NONE
            REAL(C_DOUBLE), VALUE :: x
            REAL(C_DOUBLE) :: P
        END SUBROUTINE cdfGauss_P
        SUBROUTINE fnGamma(x, dGamma)  BIND(C, NAME='fnGamma')
            USE, INTRINSIC :: ISO_C_BINDING     ! New Fortran 2003 standard
            IMPLICIT NONE
            REAL(C_DOUBLE), VALUE :: x
            REAL(C_DOUBLE) :: dGamma
        END SUBROUTINE fnGamma
end interface

6. In the Fortran code, just call the function as specified by the interface.
Eg.
    call fnGamma(vecX(ii), answ)      
call cdfGauss_P(vecQ(ii), answ)      


There are at least 3 projects involved here.
vcpp_gsl - this keeps the gsl code in its own project, so that it is independent of any change in interface or usage.
gslCwrap - this consist of the C wrappers so that it can be used by C code or Fortran code. It also transforms all gsl functions into VOID C functions so that it can be called as Fortran subroutines. Fortran Interface - this is freely linked to the gslCwrap wrapper code. There is no direct reference to the GSL code.  

No comments: