project('gsl', 'c', version : '2.4')


cc = meson.get_compiler('c')


# --
# -- Generate the config.h by analysing the system.
# --
conf = configuration_data()
conf.set_quoted('VERSION', '2.4')

# -- Check IEEE comparisons, whether "x != x" is true for NaNs
result = cc.run('''
	#include <math.h>
	int main (void) 
	{ 
 		int status; double inf, nan;
 		inf = exp(1.0e10);
 		nan = inf / inf ;
 		status = (nan == nan);
 		exit (status);
	}
''')
if (not result.compiled()) or result.returncode() == 0
	conf.set('HAVE_IEEE_COMPARISONS', 1)
endif

#TODO: This does not belong in config.h because it does not depend on configuration.
conf.set('', '''XYZ
/* Define a rounding function which moves extended precision values
   out of registers and rounds them to double-precision. This should
   be used *sparingly*, in places where it is necessary to keep
   double-precision rounding for critical expressions while running in
   extended precision. For example, the following code should ensure
   exact equality, even when extended precision registers are in use,

      double q = GSL_COERCE_DBL(3.0/7.0) ;
      if (q == GSL_COERCE_DBL(3.0/7.0)) { ... } ;

   It carries a penalty even when the program is running in double
   precision mode unless you compile a separate version of the
   library with HAVE_EXTENDED_PRECISION_REGISTERS turned off. */

#if HAVE_EXTENDED_PRECISION_REGISTERS
#define GSL_COERCE_DBL(x) (gsl_coerce_double(x))
#else
#define GSL_COERCE_DBL(x) (x)
#endif

#ifdef __GNUC__
#define DISCARD_POINTER(p) do { ; } while(p ? 0 : 0);
#else
#define DISCARD_POINTER(p) /* ignoring discarded pointer */
#endif
''')

#TODO: This does not belong in config.h because it does not depend on configuration.
conf.set('RETURN_IF_NULL(x)', 'if (!x) { return ; }')

configure_file(output : 'config.h', configuration : conf)


# --
# -- Build the sublibraries.
# --
gsl_tests = [] # Test registry.
#subdir('gsl')
subdir('utils')
subdir('sys')
subdir('test')
subdir('err')
subdir('const')
subdir('complex')
subdir('cheb')
subdir('block') 
subdir('vector')
subdir('matrix') 
subdir('permutation') 
subdir('combination')
subdir('multiset')
subdir('sort')
subdir('ieee-utils')
subdir('cblas')
subdir('blas')
subdir('linalg')
subdir('eigen')
subdir('specfunc')
subdir('dht')
subdir('qrng')
subdir('rng')
subdir('randist')
subdir('fft')
subdir('poly')
subdir('fit')
subdir('multifit')
subdir('multifit_nlinear')
subdir('multilarge')
subdir('multilarge_nlinear')
subdir('rstat')
subdir('statistics')
subdir('siman')
subdir('sum')
subdir('integration')
subdir('interpolation')
subdir('histogram')
subdir('ode-initval')
subdir('ode-initval2')
subdir('roots')
subdir('multiroots')
subdir('min')
subdir('multimin')
subdir('monte')
subdir('ntuple')
subdir('diff')
subdir('deriv')
subdir('cdf')
subdir('wavelet')
subdir('bspline')
subdir('spblas')
subdir('spmatrix')
subdir('splinalg')
#subdir('doc')


gsl_lib = static_library('gsl', 'version.c', 
	dependencies : [
		gslutils_dep, gslsys_dep, gsltest_dep, gslerr_dep, gslcomplex_dep, gslcheb_dep,
		gslblock_dep, gslvector_dep, gslmatrix_dep, gslpermutation_dep, gslcombination_dep,
		gslmultiset_dep, gslsort_dep, gslieeeutils_dep, gslcblas_dep, gslblas_dep,
		gsllinalg_dep, gsleigen_dep, gslspecfunc_dep, gsldht_dep, gslqrng_dep, 
		gslrng_dep, gslrandist_dep, gslfft_dep, gslpoly_dep, gslintegration_dep, 
		gslfit_dep, gslmultifit_dep, gslstatistics_dep, gslrstat_dep,
		gslmultifit_nlinear_dep, gslmultilarge_dep, gslmultilarge_nlinear_dep,
		gslsiman_dep, gslsum_dep, gslinterpolation_dep, gslhistogram_dep,
		gslodeiv_dep, gslodeiv2_dep, gslroots_dep, gslmultiroots_dep, gslmin_dep,
		gslmultimin_dep, gslmonte_dep, gslntuple_dep, gsldiff_dep, gslderiv_dep,
		gslcdf_dep, gslwavelet_dep, gslbspline_dep, gslspblas_dep, gslspmatrix_dep,
		gslsplinalg_dep
	]
)


# --
# -- Generate the selftests, which have been registered by the sublibraries.
# --
foreach p : gsl_tests
	selftest = executable(p[0], p[1], link_with : gsl_lib)
	test(p[0], selftest)
endforeach
