/*
 *  Mathlib : A C Library of Special Functions
 *  Copyright (C) 1998-2016  The R Core Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, a copy is available at
 *  https://www.R-project.org/Licenses/
 */

/* Private header file for use during compilation of Mathlib */
#ifndef MATHLIB_H
#define MATHLIB_H

#include "config.h"
#include "const.h"
#  define LDOUBLE double

#ifdef NFINITE
double isfinitefn(double x);
double isnanfn(double x);
#define isfinite(x) (isfinitefn(x))
#define isnan(x) (isnanfn(x))
#endif

#ifdef Z80CC
enum RbooleanX {FALSE=0, TRUE=1};
typedef int Rboolean;
#else
typedef enum Rboolean {FALSE=0, TRUE=1} Rboolean;
#endif


/* Used internally only */
double  Rf_d1mach(int);
double  Rf_gamma_cody(double);

#ifndef NAN
#define NAN (0.0/0.0)
#endif

/* possibly needed for debugging */


/* Mathlib standalone */

#include <stdio.h>
#include <stdlib.h> /* for exit */
#define MATHLIB_ERROR(fmt,x)    { printf(fmt,x); exit(1); }
#define MATHLIB_WARNING(fmt,x)          printf(fmt,x)
#define MATHLIB_WARNING2(fmt,x,x2)      printf(fmt,x,x2)
#define MATHLIB_WARNING3(fmt,x,x2,x3)   printf(fmt,x,x2,x3)
#define MATHLIB_WARNING4(fmt,x,x2,x3,x4) printf(fmt,x,x2,x3,x4)
#define MATHLIB_WARNING5(fmt,x,x2,x3,x4,x5) printf(fmt,x,x2,x3,x4,x5)

#define ISNAN(x) (isnan(x)!=0)
/* Arith.h defines it */
/* isfinite is defined in <math.h> according to C99 */
# define R_FINITE(x)    isfinite(x)

#define ML_POSINF       (1.0 / 0.0)
#define ML_NEGINF       ((-1.0) / 0.0)
#define ML_NAN          (0.0 / 0.0)

#define _(String) String

#define ML_VALID(x)     (!ISNAN(x))

#define ME_NONE         0
/*      no error */
#define ME_DOMAIN       1
/*      argument out of domain */
#define ME_RANGE        2
/*      value out of range */
#define ME_NOCONV       4
/*      process did not converge */
#define ME_PRECISION    8
/*      does not have "full" precision */
#define ME_UNDERFLOW    16
/*      and underflow occured (important for IEEE)*/

#define ML_ERR_return_NAN { ML_ERROR(ME_DOMAIN, ""); return ML_NAN; }

/* For a long time prior to R 2.3.0 ML_ERROR did nothing.
   We don't report ME_DOMAIN errors as the callers collect ML_NANs into
   a single warning.
 */
#define ML_ERROR(x, s) { \
   if(x > ME_DOMAIN) { \
       char *msg = ""; \
       switch(x) { \
       case ME_DOMAIN: \
           msg = _("argument out of domain in '%s'\n"); \
           break; \
       case ME_RANGE: \
           msg = _("value out of range in '%s'\n");     \
           break; \
       case ME_NOCONV: \
           msg = _("convergence failed in '%s'\n");     \
           break; \
       case ME_PRECISION: \
           msg = _("full precision may not have been achieved in '%s'\n"); \
           break; \
       case ME_UNDERFLOW: \
           msg = _("underflow occurred in '%s'\n");     \
           break; \
       } \
       MATHLIB_WARNING(msg, s); \
   } \
}

# define attribute_hidden



/* From toms708.c */
void attribute_hidden bratio(double a, double b, double x, double y,
                             double *w, double *w1, int *ierr);
struct midptestcontext {
	double x,n,q;
};
double midptest(double p, void *info);

double zeroin(			/* An estimate of the root */
    double ax,				/* Left border | of the range	*/
    double bx,				/* Right border| the root is seeked*/
    void *info,				/* Add'l info passed on to f	*/
    double *Tol);			/* Acceptable tolerance		*/

#endif /* MATHLIB_H */
