/*--------------------------------------------------------------------
 *	$Id: gmt_math.h 10173 2014-01-01 09:52:34Z pwessel $
 *
 *	Copyright (c) 1991-2014 by P. Wessel and W. H. F. Smith
 *	See LICENSE.TXT file for copying and redistribution conditions.
 *
 *	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; version 2 or 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.
 *
 *	Contact info: gmt.soest.hawaii.edu
 *--------------------------------------------------------------------*/
/*
 * This include file contains prototypes of functions that are not part
 * of POSIX but are often distributed anyway as part of ANSI C.  The
 * gmt_notposix.h include file have been generated by configure and tells
 * us which of the required functions are present or not and sets a macro or
 * prototype accordingly.  The purpose is to take advantage of the built-in
 * functions if they exist and provide an alternative definition otherwise.
 *
 * If you must do a manual edit, you should do so in gmt_notposix.h.
 * For non-UNIX platforms you should also look in gmt_notunix.h
 *
 * Version:	4
 */

#ifndef _GMT_MATH_H
#define _GMT_MATH_H

#ifndef SET_IN_NOTUNIX
#include "gmt_notposix.h"
#endif

#ifdef GMT_QSORT
/* Must replace the system qsort with ours which is 64-bit compliant */
#define qsort GMT_qsort
#endif

#ifndef HAVE_COPYSIGN
#define copysign(x,y) ((y) < 0.0 ? -fabs(x) : fabs(x))
#endif

#ifndef HAVE_LOG2
#define log2(x) (log10(x)/0.30102999566398114250631579125183634459972381591796875)
#endif

#ifndef HAVE_LOG1P
#define log1p(x) GMT_log1p(x)
EXTERN_MSC double GMT_log1p(double x);
#endif

#ifndef HAVE_HYPOT
#define hypot(x,y) GMT_hypot(x,y)
EXTERN_MSC double GMT_hypot(double x, double y);
#endif

#ifndef HAVE_ACOSH
#define acosh(x) d_log((x) + (d_sqrt((x) + 1.0)) * (d_sqrt((x) - 1.0)))
#endif

#ifndef HAVE_ASINH
#define asinh(x) d_log((x) + (hypot((x), 1.0)))
#endif

#ifdef HAVE_ATANH
extern double atanh(double x);
#else
#define atanh(x) GMT_atanh(x)
EXTERN_MSC double GMT_atanh(double x);
#endif

#ifdef HAVE_RINT
extern double rint(double x);
#else
#define rint(x) (floor((x)+0.5))
#endif

#ifdef HAVE_IRINT
extern int irint(double x);
#else
#define irint(x) ((int)rint(x))
#endif

/* Misc. ANSI-C math functions used by grdmath and gmtmath.
 * These functions are available on many platforms and we
 * seek to use them.  If not available then we compile in
 * replacements from gmt_stat.c */

#ifndef HAVE_J0
#define j0(x) GMT_j0(x)
EXTERN_MSC double GMT_j0(double x);
#endif

#ifndef HAVE_J1
#define j1(x) GMT_j1(x)
EXTERN_MSC double GMT_j1(double x);
#endif

#if defined(jn)
/* Macro already takes care of jn - probably from BSD */
#elif defined(HAVE_JN)
extern double jn(int n, double x);
#else
#define jn(n, x) GMT_jn(n, x)
EXTERN_MSC double GMT_jn(int n, double x);
#endif

#ifndef HAVE_Y0
#define y0(x) GMT_y0(x)
EXTERN_MSC double GMT_y0(double x);
#endif

#ifndef HAVE_Y1
#define y1(x) GMT_y1(x)
EXTERN_MSC double GMT_y1(double x);
#endif

#ifndef HAVE_YN
#define yn(n, x) GMT_yn(n, x)
EXTERN_MSC double GMT_yn(int n, double x);
#endif

#ifndef HAVE_ERF
#define erf(x) GMT_erf(x)
EXTERN_MSC double GMT_erf(double x);
#endif

#ifndef HAVE_ERFC
#define erfc(x) GMT_erfc(x)
EXTERN_MSC double GMT_erfc(double x);
#endif

#if defined(strdup)
/* Macro already takes care of strdup - probably from BSD */
#elif defined(HAVE_STRDUP)
extern char *strdup(const char *s);
#else
#define strdup(s) GMT_strdup(s)
EXTERN_MSC char *GMT_strdup(const char *s);
#endif

#ifndef HAVE_STRTOD
#define strtod(p, e) GMT_strtod(p, e)
EXTERN_MSC double GMT_strtod(const char *nptr, char **endptr);
#endif

/* On Dec Alpha OSF1 there is a sincos with different syntax.
 * Assembly wrapper provided by Lloyd Parkes (lloyd@geo.vuw.ac.nz)
 * can be used instead.
 */
 
#ifdef HAVE_ALPHASINCOS
#define sincos(x,s,c) alpha_sincos (x, s, c)
extern void alpha_sincos (double x, double *s, double *c);
#elif defined(sincos)
/* Macro already takes care of strtod - probably from BSD */
#elif defined(HAVE_SINCOS)
extern void sincos (double x, double *s, double *c);
#else
EXTERN_MSC void sincos (double x, double *s, double *c);
#endif

#endif /* _GMT_MATH_H */
