#pragma once
#ifndef BINARY_C_CODE_OPTIONS_H
#define BINARY_C_CODE_OPTIONS_H
/*
 * The binary_c stellar population nucleosynthesis framework.
 *
 * Contact: r.izzard@surrey.ac.uk or rob.izzard@gmail.com
 *
 * http://personal.ph.surrey.ac.uk/~ri0005/binary_c.html
 * https://gitlab.eps.surrey.ac.uk/ri0005/binary_c
 * https://groups.google.com/forum/#!forum/binary_c-nucsyn-announce
 * https://groups.google.com/forum/#!forum/binary_c-nucsyn-devel
 * https://twitter.com/binary_c_code
 * https://www.facebook.com/groups/149489915089142/
 *
 * Please see the files README, LICENCE and CHANGES,
 * and the doc/ directory for documentation.
 *
 *
 *
 * This file contains the code building options for binary_c
 *
 * These are (generally) compile-time options only, and
 * hence a rebuild is necessary when you change them.
 *
 * There are also compiler-specific options in here, and
 * some stuff for aligned memory allocation, prefecthing etc.
 * which may (or may not) be useful/faster for you.
 *
 * Please note: debugging is in binary_c_debug.h
 */

/* standard library requirements */
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <errno.h>

/*
 * C standards
 */
#if defined(__STDC__)
# define _C89
# if defined(__STDC_VERSION__)
#  define _C90
#  if (__STDC_VERSION__ >= 199409L)
#   define _C94
#  endif
#  if (__STDC_VERSION__ >= 199901L)
#   define _C99
#  endif
#  if (__STDC_VERSION__ >= 201112L)
#   define _C11
#  endif
# endif
#endif

/*
 * Clean up SVN_REVISION
 */
#define __DO_EXPAND(M) M ## 1
#define __EXPAND(M) __DO_EXPAND(M)
#if !defined(SVN_REVISION)
#undef SVN_REVISION
#undef SVN_URL
#endif

/*
 * If __NATIVE_*__ options are set, do not use our overrides
 * for C-library functions. It is not recommended to set
 * the __NATIVE_*__ macros! 
 */

#ifdef __NATIVE_ALL__
#define __NATIVE_MALLOC__
#define __NATIVE_EXIT__
#define __NATIVE_PRINTF__
#endif


#if !defined(__NATIVE_EXIT__)

/*
 * Exit_binary_c : a macro to exit binary_c correctly.
 *
 * Pass on a call to exit_binary_c with the file name and line number.
 * If stardata is not available, use Exit_binary_c_no_stardata defined below.
 *
 * If you might need to return, rather than exit, e.g. when using the 
 * libbinary_c.so shared library for access to binary_c subroutines 
 * from an external source, use Exit_or_return(...) or
 * Exit_or_return_void(...) instead.
 *
 * In case of error, the exit_binary_c function longjmps back to
 * the start after issuing a failure message which can be caught by binary_grid.
 * 
 */


/* 
 * Override stdlib's exit call with a call to Exit_binary_c
 * and tell the code maintainer to use Exit_binary_c
 */
#undef exit
#define exit(A) {                                                       \
        fail;                                                           \
        Exit_binary_c(stardata,                                         \
                      1,                                                \
                      "Exit through C's exit, you should use the Exit_binary_c macro instead!"); \
    }

#else

/* use native exit */
    
#endif

#include "binary_c_exit_macros.h"


/*
 * cache prefetching
 */
#ifdef __GNUC__
#define prefetch(...) /* prefetch: do nothing */
//#define prefetch(...) __builtin_prefetch(__VA_ARGS__)
#else
#define prefetch(...) /* prefetch: do nothing */
#endif // __GNUC__


/*
 * Check and maybe change the stack
 */
//#define STACK_CHECKS

/*
 * Required stack size (MB)
 */
#define STACK_SIZE 100L

/*
 * Show a warning (STACK_WARNING) or try to set the
 * stack if it is too small? (STACK_SET)
 * Or do nothing (STACK_DO_NOTHING)
 */
#define STACK_ACTION STACK_WARNING

/*
 * Assume only GNU compilers have malloc_usable_size and
 * provide it through a macro so it's easily changed on other
 * systems.
 */
#if defined __GNUC__ && defined __HAVE_MALLOC_H__
#define HAVE_MALLOC_USABLE_SIZE
#define Malloc_usable_size(X) malloc_usable_size(X)
#else
#define Malloc_usable_size(X) (-1)
#endif

/*
 * Require X/Open 7 (POSIX 2008)
 */
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif // _XOPEN_SOURCE

/*
 * Some compilers have no execinfo.h and hence no backtrace ability.
 * see e.g. https://www.gnu.org/software/gnulib/manual/html_node/execinfo_002eh.html
 * For now, assume Linux can do this (modern gcc certainly can).
 * (We may need to check the gcc version in here, if this fails
 * with an old gcc.)
 */
#if (                                           \
    defined __GNUC__ &&                         \
    !defined __APPLE__ &&                       \
    !defined __sun &&                           \
    defined LINUX                               \
    )
#define BACKTRACE
#endif

#ifdef BACKTRACE

/*
 * Available backtracing methods.
 */
#define BACKTRACE_METHOD_GNU 0
#define BACKTRACE_METHOD_LOCAL 1
#define BACKTRACE_METHOD_LIBBACKTRACE 2
#define BACKTRACE_METHOD_GNU_BUFFER 3

/*
 * Choose a default backtracing method.
 *
 * GNU : this uses gcc's backtrace_symbols_fd
 *       and sends the output directly to stderr.
 *       This is the safest of all methods, because it
 *       requires no allocation of extra memory, but does
 *       not give line numbers.
 *
 * GNU_BUFFER : this is like GNU but gives line numbers.
 *       It requires extra memory, however, and if the stream
 *       defined at BACKTRACE_GNU_BUFFER_STREAM is broken it 
 *       will itself segfault. Does not give line numbers.
 * 
 * LIBBACKTRACE : this uses libbacktrace which can be downloaded 
 *       from https://github.com/ianlancetaylor/libbacktrace
 *       The configure script should detect if this is available,
 *       define __HAVE_LIBBACKTRACE__ which will enable 
 *       LIBBACKTRACE by default.
 *
 * LOCAL : Uses a hacked version of the replacement for backtrace-sumbols
 *         found at   
 * http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html
 *         Expect this (hacked) code to fail. At the moment it segfaults,
 *         despite my attempts to fix it and replace dangerous calls
 *         (e.g. strcpy with strncpy).
 *
 * Gnu's is likely the most portable,
 * but libbacktrace is better, so use it where possible
 * and Gnu is the fallback.
 * 
 * The local function is a bit hacked and may fail,
 * and required libbfd.
 */

#ifdef __HAVE_LIBBACKTRACE__
#define BACKTRACE_METHOD BACKTRACE_METHOD_LIBBACKTRACE
#else
#define BACKTRACE_METHOD BACKTRACE_METHOD_GNU
#endif // __LIBBACKTRACE__

/*
 * Gnu method with buffer can output to
 * the file stream of your choice (usually
 * stdout or stderr)
 */
#define BACKTRACE_GNU_BUFFER_STREAM stdout

/*
 * Generic macro to print a trace.
 */
void Print_trace(void);
#define Backtrace Print_trace();

#else

/* dummy macro, does nothing */
#define Backtrace /* do nothing */

#endif // BACKTRACE

/*
 * Enable this to get real segfaults (for gdb etc.) or 
 * disable to catch segfaults and report a binary_c-style error
 */
//#define SEGFAULTS

/* use AMD math library? */
#ifdef ACML
#include <acml.h>
#endif

/* override FPU precision? use _FPU_DOUBLE or _FPU_EXTENDED */
#define FPU_PRECISION _FPU_EXTENDED

/* 
 * FPU 1/0, inexacts, undef/overflow and NAN captures?
 * NB INEXACT often fails at roundings which are necessary,e.g. 0.0+3.0.
 * These are not errors.
 */

#define FPU_CAPTURE_INVALID
//#define FPU_CAPTURE_INEXACT
#define FPU_CAPTURE_UNDERFLOWS
#define FPU_CAPTURE_OVERFLOWS
#define FPU_CAPTURE_DIVIDE_BY_ZERO

/*
 * You want to check if isnan works
 */
#define CHECK_ISNAN_WORKS

/* use DUMA (m/c)alloc checking library? */
#ifdef DUMA
#include <string.h>
#include <malloc.h>
#include <duma.h>
#endif

/*
 * STELLAR_TIMESCALES_SANITY checks that the MS timescale is < the BGB
 * timescale. It should be for stars of type TPAGB or earlier.
 * It also checks that tm!=tn in calc_lum_and_evol_time, because
 * it's easy to typo tm <-> tn. Well, I did...
 */
#define STELLAR_TIMESCALES_SANITY

// enable batchmode, or disable it to make the code smaller
#define BATCHMODE


/*
 * The number of seconds til timeout - see reset_binary_c_timeout.c.
 * Ignored if 0.
 *
 * Note: if you set TIMEOUT_SECONDS to be non-zero and do not have 
 *       setitimer available on your system, binary_c will exit because
 *       this is considered a bug. 
 */
#define TIMEOUT_SECONDS 0

/*
 * Provide a longer timeout if using valgrind
 */
#define TIMEOUT_SECONDS_WITH_VALGRIND 3000


/*
 * Catch timeouts and send them to Exit_binary_c
 */
#define CATCH_SIGVTALRM

/* set this to check mallocs, callocs etc. really do allocate memory */
#define ALLOC_CHECKS

// force alloc checks in debug mode
#if DEBUG==1 && !defined ALLOC_CHECKS
#define ALLOC_CHECKS
#endif

// enable this to allow output from the stardata_status function:
// who uses this?
//#define STARDATA_STATUS

/* 
 * use binary_c's internal copy of 
 * librinterpolate if it's not available as 
 * a shared library
 */
#ifndef __HAVE_LIBRINTPOLATE__
#define __HAVE_LIBRINTPOLATE__
#define __HAVE_LIBRINTPOLATE_BINARY_C__
#endif

/* 
 * Compiler specific attribute switches 
 * 
 * See e.g. 
 *
 * https://embarc.org/man-pages/gcc/Common-Function-Attributes.html
 */
#define MAYBE_UNUSED /* */

#ifdef __GNUC__
// GNU C specific options

#if __GNUC__ >= 4

/* gcc 4.x and beyond */

/*
  The hot attribute is used to inform the compiler that a function is a hot spot of the compiled program. The function is optimized more aggressively and on many target it is placed into special subsection of the text section so all hot functions appears close together improving locality. 
 */
#define Hot_function __attribute__((hot))

/*
 * nonnull specifies that some function parameters are non-null
 * pointers. Use either the _all_ form, or the macro form to number them.
 */
#define Nonnull_all_arguments __attribute__((nonnull))
#define Nonnull_some_arguments(...) __attribute__((nonnull(__VA_ARGS__)))
#define RESTRICT __restrict__
#define FASTCALL __attribute__((fastcall))__
#define Constant_function __attribute__ ((const))
#if DEBUG==0
#define Constant_function_if_no_debug __attribute__ ((const))
#endif
#define No_return __attribute__ ((noreturn))

#undef MAYBE_UNUSED
#define MAYBE_UNUSED __attribute__ ((unused)) 

#if (__GNUC__ ==4 && __GNU_MINOR__>=7) || __GNUC__ > 4
/*
 * gcc >= 4.7 has alloc_size and returns_nonnull
 */
#define Alloc_size_first __attribute__((alloc_size(1)))
#define Alloc_size_second __attribute__((alloc_size(2)))
#define Alloc_size_product __attribute__((alloc_size(1,2)))
#define Returns_nonnull __attribute__((returns_nonnull))
#define Malloc_like __attribute__((malloc))
#define Gnu_format_args(...) __attribute__((format (gnu_printf,__VA_ARGS__)))
#endif

#if (__GNUC__ ==4 && __GNU_MINOR__>9) || __GNUC__ > 4
/*
 * gcc >=4.9 has __auto_type and deprecated
 */ 
#define Deprecated(STRING) __attribute__((deprecated(STRING)))
#define Autotype(X) __auto_type
/*
 * Branch prediction: use "likely" and "unlikely"
 */

#define likely(x)      __builtin_expect(!!(x), 1)
#define unlikely(x)    __builtin_expect(!!(x), 0)

#endif // GCC >= 4.9



    
#elif __GNUC__ == 3

// gcc 3.x

#define MAYBE_UNUSED /* nothing */

#if __GNUC_MINOR__>3

// gcc 3.4 or later

// allow restrict pointers (allowed in _C99 specs)
#define RESTRICT __restrict__
#define FASTCALL __attribute__((fastcall))

#else

/* gcc 3.0-3.3 */ 

#endif // GNU_MINOR>3

#else

/* pre gcc 3.0 ... rely on defaults below */

#endif // GCC version check


#else // gcc check

/* other compilers ... rely on defaults below */

#endif

/*
 * manually specify pure functions
 * (only for gcc 2.96+)
 */
#if defined __GNUC__ && __GNUC__ >=3
#define Pure_function __attribute__((pure))
#if DEBUG==0
#define Pure_function_if_no_debug __attribute__((pure))
#endif
#endif


/*
 * Defaults/fallbacks.
 * 
 * If macros are not defined, define to do nothing them here
 */
#ifndef likely
#define likely(x) (x)
#endif
#ifndef unlikely
#define unlikely(x) (x)
#endif

//#undef Pure_function

#ifndef Constant_function
# define Constant_function
#endif
#ifndef Constant_function_if_no_debug
# define Constant_function_if_no_debug
#endif
#ifndef Deprecated
# define Deprecated(STRING)
#endif
#ifndef RESTRICT
# define RESTRICT
#endif
#ifndef FASTCALL
# define FASTCALL
#endif
#ifndef Alloc_size_first
#  define Alloc_size_first
#endif
#ifndef Alloc_size_second
#  define Alloc_size_second
#endif
#ifndef Alloc_size_product
#  define Alloc_size_product
#endif
#ifndef Returns_nonnull
#  define  Returns_nonnull
#endif
#ifndef Nonnull_some_arguments
# define Nonnull_some_arguments(...)
#endif
#ifndef Nonnull_all_arguments
# define Nonnull_all_arguments
#endif
#ifndef Hot_function
# define Hot_function
#endif
#ifndef Autotype
# define Autotype(X) typeof(X)
#endif 
#ifndef MAYBE_UNUSED
# define MAYBE_UNUSED
#endif
#ifndef Pure_function
# define Pure_function
#endif
#ifndef Pure_function_if_no_debug
# define Pure_function_if_no_debug
#endif
#ifndef Malloc_like
# define Malloc_like
#endif
#ifndef Gnu_format_args
# define Gnu_format_args(...) 
#endif
#ifndef No_return
# define No_return
#endif

#ifdef __INTEL_COMPILER
// intel specific options: note icc also defined __GNUC__ as true
#undef Constant_function
#define Constant_function
#define inline
#endif // INTEL CHECK

#ifdef __SUNPRO_C
// Sun CC 
#undef RESTRICT
#define RESTRICT
#undef Constant_function
#define Constant_function
#define inline
#define RESTRICT 
#endif //  __SUNPRO_C


#define USE_ANSI_COLOURS

/*
 * Enable stellar_timescales cache which may speed up the
 * code by up to 10%
 */
//#define STELLAR_TIMESCALES_CACHE

/*
 * The random number seed usually depends on a call to time()
 * which gives you a change every second. However, you might
 * want a change every milli or nanosecond, and enabling
 * MILLISECOND_RANDOMNESS or NANOSECOND_RANDOMNESS
 * gives you that option. Requires ftime().
 *
 * Note, older compilers do not have this feature, so if
 * TIME_UTC is unavailable, we use MILLISECOND_RANDOMNESS
 * instead.
 */

#ifdef TIME_UTC
#define NANOSECOND_RANDOMNESS
#else
#define MILLISECOND_RANDOMNESS
#endif

/*
 * Enable random_seed logging
 */
//#define RANDOM_SEED_LOG

/* choose stdout or stderr */
//#define RANDOM_SEED_LOG_STREAM stderr

/*
 * Enable random_number logging
 * (in the file log)
 */
#define RANDOM_NUMBER_LOG

/* 
 * Enable to generate extra code for NaN checking
 * WARNING: very slow but sometimes necessary
 * e.g. 100 systems without NANCHECKS: 7.22s, with NANCHECKS 9.49s
 * So, disable this for a 25% gain in speed, but fewer checks.
 */
//#define NANCHECKS

/*
 * Use native isnan, or a custom funtion?
 * See nancheck.c for details. Sometimes 
 * a custom function is faster, but maybe not as reliable?
 */
#define USE_NATIVE_ISNAN

/*
 * Use tick timer
 */

#if defined __GNUC__ &&                                                 \
  (defined __i386__ || defined __x86_64__ || defined __ia64__)
#define TIMER
#endif
#define TIMER


#ifdef TIMER
/*
 * Force the use of assembly code to call the timer,
 * otherwise use __rdtsc function 
 */
//#define TIMER_USE_ASM

/*
 * Usually the timer works on the whole run, but perhaps
 * you want per-system stats too? You'll need this to make
 * the tick_counts stuff in binary_grid work 
 */ 
#define TIMER_PER_SYSTEM
#endif

/*
 * Allow systems to be chosen at random if --random_systems is 
 * given as an argument. (Useful with --repeat)
 */
#define RANDOM_SYSTEMS
#ifdef RANDOM_SYSTEMS
#define RANDOM_SYSTEMS_SHOW_ARGS
#define RANDOM_SYSTEMS_SHOW_ARGS_AND_START_TIME
#define RANDOM_SYSTEMS_SHOW_ARGS_STREAM stdout
#endif // RANDOM_SYSTEMS

/* Extensions to the code for cgi script output */
//#define CGI_EXTENSIONS

#ifdef CGI_EXTENSIONS

/* deprecated abundance output */
#define CGI_EXTENSIONS_ABUNDS
/* HRD */
#define CGI_EXTENSIONS_HRD

#endif


/* _printf is always to stdout */
#define _printf(...) fprintf(stdout,__VA_ARGS__)

/* normal printf */
#define printf(...) printf(__VA_ARGS__)

/* capture fflush? */
//#define fflush(...) binary_c_flush(__VA_ARGS__)

/*
 * Enable binary_c API
 */
#define BINARY_C_API

/*
 * Enable the FORTRAN interface
 */
#define BINARY_C_API_FORTRAN

/*
 * Hidden functions
 */
#define binary_c_hidden_function __attribute__ ((visibility("hidden")))

/*
 * API function visibility
 */
#define binary_c_API_function __attribute__ ((visibility("default")))

#ifdef BINARY_C_API

/* redefine structures to avoid namespace clashes */
#define stardata_t libbinary_c_stardata_t
#define star_t libbinary_c_star_t
#define preferences_t libbinary_c_preferences_t
#define store_t libbinary_c_store_t
#define tmpstore_t libbinary_c_tmpstore_t
#define model_t libbinary_c_model_t
#define common_t libbinary_c_common_t

#endif //BINARY_C_API


/*
 * Code timers
 */ 
#define Show_timers final_timing_output(stardata,start_tick,repeat);

/*
 * Use pointers in tight loops where possible?
 */
#define USE_POINTER_LOOPS


/*
 * Enable code to make interpolation tables based on BSE.
 * Only use this if you know what you are doing!
 */
//#define MAKE_BSE_TABLES

/*
 * Bisection options
 */
//#define BISECT_FAIL_EXIT 

/*
 * Enable unit testing
 */
//#define UNIT_TESTS

/* 
 * generic string lengths
 *
 * Note : all strings stored in stardata->preferneces should be of length 
 *        STRING_LENGTH (if they are set by command-line options). 
 */
#define STRING_LENGTH ((size_t)4096)
#define BATCHMODE_STRING_LENGTH STRING_LENGTH

/*
 * Buffer increase ratio: this is the amount
 * by which the main buffer is increased each time it
 * is realloced. If zero, then the realloc is exactly 
 * the size required, but I'd suggest 1.2 or 1.5 for
 * fewer calls to realloc.
 */
#define BUFFERED_PRINTF_INCREASE_RATIO 1.2

/*
 * Maximum buffer size in bytes
 * Default is 100MB (1024*1024*100)
 *
 * NB The size of the buffer must be more than 
 * MAX_BUFFERED_STRING_LENGTH.
 */
#define BUFFERED_PRINTF_MAX_BUFFER_SIZE ((size_t)(1024*1024*250))


/*
 * Size of the error buffer.
 */
#define BUFFERED_PRINTF_ERROR_BUFFER_SIZE ((size_t)(1024))

/*
 * Enable BUFFER_MEMORY_DEBUGGING to output 
 * the memory in the buffer each time it is used.
 */
//#define BUFFER_MEMORY_DEBUGGING

/*
 * Stream for debugging output
 */
#define BUFFER_MEMORY_DEBUGGING_STREAM stdout

/*
 * Warn when the buffer is overrun.
 * binary_c_buffered_printf but will truncate such strings so it 
 * still works but this is likely not really what you want!
 */
#define BUFFERED_STRING_OVERRUN_WARNINGS
#define BUFFERED_STRING_OVERRUN_WARNINGS_STREAM stderr

/*
 * Rate at which we grow the evolution_difflog stack
 */
#define EVOLUTION_DIFFLOG_INCREASE_RATIO 2

/*
 * GSL (Gnu scientific library) options
 *
 * NB for many functions in binary_c, USE_GSL is now required.
 */

#ifdef USE_GSL
#include <gsl/gsl_version.h>
/*
 * GSL provides multiple 1D root finders.
 * Of these, Brent is always the fastest, 
 * and indeed bisection simply failed for me.
 *
 * Choose one of:
 *   gsl_root_fsolver_brent; // 1.76s
 *   gsl_root_fsolver_falsepos; // 3.13s
 *   gsl_root_fsolver_bisection; // very very slow? (failed) 
 *
 * NB 
 * The Brent routine of GSL is about 5 times
 * faster than the Numerical Recipies routine.
 */
#define GSL_ROOT_FSOLVER gsl_root_fsolver_brent

/*
 * As above for the multiroot solver
 *
 * See https://www.gnu.org/software/gsl/doc/html/multiroots.html
 *
 * Choose one of:
 *    gsl_multiroot_fsolver_hybrids // 0.82
 *    gsl_multiroot_fsolver_hybrid // 0.82
 *    gsl_multiroot_fsolver_dnewton // fails
 *    gsl_multiroot_fsolver_broyden // fails
 */
#define GSL_MULTIROOT_FSOLVER_HYBRIDS 1
#define GSL_MULTIROOT_FSOLVER_HYBRID 2
#define GSL_MULTIROOT_FSOLVER_DNEWTON 3
#define GSL_MULTIROOT_FSOLVER_BROYDEN 4


#define GSL_Multiroot_fsolver(S)                                        \
    (                                                                   \
        (S) == GSL_MULTIROOT_FSOLVER_HYBRIDS ? gsl_multiroot_fsolver_hybrids  : \
        (S) == GSL_MULTIROOT_FSOLVER_HYBRID ? gsl_multiroot_fsolver_hybrid  : \
        (S) == GSL_MULTIROOT_FSOLVER_DNEWTON ? gsl_multiroot_fsolver_dnewton  : \
        (S) == GSL_MULTIROOT_FSOLVER_BROYDEN ? gsl_multiroot_fsolver_broyden  : \
        NULL                                                            \
        )

#define GSL_Multiroot_fsolver_string(S)                        \
    (                                                           \
        (S) == GSL_MULTIROOT_FSOLVER_HYBRIDS ? "hybrids"  :     \
        (S) == GSL_MULTIROOT_FSOLVER_HYBRID ? "hybrid"  :       \
        (S) == GSL_MULTIROOT_FSOLVER_DNEWTON ? "dnewton"  :     \
        (S) == GSL_MULTIROOT_FSOLVER_BROYDEN ? "broyden"  :     \
        "Unknown"                                               \
        )

#define GSL_INTEGRATOR_WORKSPACE_SIZE ((size_t)1000)
#define GSL_INTEGRATOR_QAG 1
#define GSL_INTEGRATOR_QNG 2
#define GSL_INTEGRATOR_QAGS 3
#define GSL_INTEGRATOR_CQUAD 4

#define GSL_INTEGRATOR_ABSOLUTE_TOLERANCE 1e-10

#define GSL_Integrator_String(N) (              \
        (N)==GSL_INTEGRATOR_QAG ? "QAG" :       \
        (N)==GSL_INTEGRATOR_QNG ? "QNG" :       \
        (N)==GSL_INTEGRATOR_QAGS ? "QAGS" :     \
        (N)==GSL_INTEGRATOR_CQUAD ? "CQUAD" :   \
        "?" )

#endif //USE_GSL

/*************************************************************
 * Memory alignment options
 *************************************************************/

/*
 * Force array sizes to be larger so they are aligned at 
 * both ends and packed arrays are also aligned. Tends to be slow.
 */
//#define ALIGN_ARRAYS

/*
 * Activate code to check that memcpy calls have
 * aligned pointers. Slower.
 */
//#define CHECK_MEMCPY_ALIGNMENT

/* use native malloc, calloc, realloc : usually it's faster to do so */ 
#define __NATIVE_MALLOC__

/*
 * Define BAN_UNSAFE_FUNCTIONS to prevent the use
 * of some functions which could easily cause buffer
 * overruns and which have better alternatives (e.g. strcpy
 * and strncpy should be replaced by strlcpy).
 */
#define BAN_UNSAFE_FUNCTIONS

#ifdef BAN_UNSAFE_FUNCTIONS
#define ___DUMMY please_do_not_use_this_function_it_may_lead_to_buffer_overruns_and_stack_smashing
#undef strcpy
#define strcpy ___DUMMY
#undef sprintf
#define sprintf ___DUMMY
#undef strcat
#define strcat ___DUMMY
#undef vsprintf
#define vsprintf ___DUMMY
#undef gets
#define gets ___DUMMY
#undef strncpy
#define strncpy ___DUMMY
#undef strncat
#define strncat ___DUMMY
#undef atof
#define strncat ___DUMMY
#undef atoi
#define strncat ___DUMMY
#undef atol
#define strncat ___DUMMY
#endif // BAN_UNSAFE_FUNCTIONS


/*
 * If we don't have libbsd available, instead 
 * use snprintf in place of strlcpy 
 */
#ifndef __HAVE_LIBBSD__
#undef strlcpy
#define strlcpy(d,s,n) snprintf((d),(n),"%s",(s))
#define __STRLCPY_IS_MACRO__
#undef strlcat
#define strlcat(dest,source,size) __local_bsd_strlcat((dest),(source),(size))
#define __STRLCAT_IS_BSD_COPY__
#endif // __HAVE_LIBBSD__

/*
 * If we don't have libbsd or gnu extensions, use binary_c's
 * asprintf function
 */
#if !defined __HAVE_LIBBSD__ &&                 \
    !defined __GNUC__
#define asprintf binary_c_asprintf
#endif // !__HAVE_LIBBSD__ && !__GNUC__

/*
 * Choose a random-number generator.
 * 
 * Only one should be defined.
 */
#define USE_DRAND48_R
//#define USE_MERSENNE_TWISTER


/*
 * Random number setup based on the
 * above choice
 */
#ifdef USE_DRAND48_R


#ifndef __HAVE_DRAND48_R__
/*
 * We don't have drand48 available from the 
 * system glibc, so instead use our own version.
 */
#define BINARY_C_USE_LOCAL_RAND48
#define drand48_r(...) binary_c_drand48_r(__VA_ARGS__)
#define srand48_r(...) binary_c_srand48_r(__VA_ARGS__)
#define drand48_data binary_c_drand48_data

/*
 * Deliberately break any system version
 */
#define erand48_r(...) 
#endif // __HAVE_DRAND48_R__

#endif // USE_DRAND48_R


/*
 * Memoize functions with MEMOIZE.
 */
#define MEMOIZE

/*
 * undefine __HAVE_LIBMEMOIZE__ to force use of 
 * local memoize code even if libmemoize is found 
 */
//#undef __HAVE_LIBMEMOIZE__

#ifdef __HAVE_LIBMEMOIZE__
/*
 * use library memoize and its header files
 */
#define MEMOIZE_HEADER_FILE <memoize.h>

#ifndef MEMOIZE
/*
 * We don't want to use libmemoize if MEMOIZE is not
 * defined, but we DO want to load its header file to 
 * get the fake Memoize macro.
 *
 * This behaviour can be enabled by setting DISABLE_LIBMEMOIZE
 * before loading the header file. 
 */
#define DISABLE_LIBMEMOIZE
#endif // MEMOIZE

#undef USE_LOCAL_MEMOIZE
/* 
 * Note that MEMOIZE_STATS and MEMOIZE_DEBUG
 * do nothing in this case, you should compile
 * binary_c with libmemoize-stats or libmemoize-debug
 * instead.
 */
#else

/*
 * Use local version of libmemoize and its header files.
 *
 * The local version does not set MEMOIZE.
 */
#define USE_LOCAL_MEMOIZE
#define MEMOIZE_HEADER_FILE "memoize/memoize.h"

/*
 * We can apply MEMOIZE_STATS and MEMOIZE_DEBUG directly 
 * when using the local copy of the library.
 */
//#define MEMOIZE_STATS
//#define MEMOIZE_DEBUG

#endif // HAVE_LIBMEMOIZE

/*
 * Use Skywind's experimental fast memcpy
 */
//#define USE_SKYWIND_FAST_MEMCPY

/* 
 * Use Apex' memmove and memcpy
 */
//#define USE_APEX_MEMMOVE

/*
 * Use asmlib?
 */
//#define USE_ASMLIB



/*
 * Use interpolate librinterpolate if it's not
 * available
 */
#ifndef __HAVE_LIBRINTERPOLATE__
#define __HAVE_LIBRINTERPOLATE_BINARY_C__
#endif


/*
 * Activate code statistics : this 
 * counts calls to memcpy, malloc, calloc and realloc
 */
//#define CODESTATS

/*
 * Allow the show_stardata function to work
 */
//#define SHOW_STARDATA

/*
 * Allow the diff_stardata function to work
 */
//#define DIFF_STARDATA


/*
 * If STARDATA_DIFFSTATS is set, we calculate the % difference
 * between stardata and previous_stardata when copying 
 */
//#define STARDATA_DIFFSTATS

/*
 * Improved command-line argument parser: this maps
 * the cmd_line_args array to a set of data indexed by the 
 * first character of each argument. Thus there is a little
 * memory cost, but it takes ~20% of the time to parse
 * arguments IF structures (stardata and preferences) do not
 * change. In a general run, these *can* change, so you 
 * don't buy any speed :(
 */
//#define ALPHA_ARGS

#endif //BINARY_C_CODE_OPTIONS_H