/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dk3md.ctr
*/

/*
Copyright (C) 2013, Dirk Krause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above opyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**	@file */

#ifndef DK3MD_H_INCLUDED
/** Avoid multiple inclusions. */
#define DK3MD_H_INCLUDED 1


#line 9 "dk3md.ctr"

#include <dk3conf.h>
#include <dk3types.h>

#if DK3_HAVE_LONG_DOUBLE && (DK3_SIZEOF_LONG_DOUBLE > DK3_SIZEOF_DOUBLE)

/*	Long double	(start)
*/


/**	Calculate sin(x).
*/
#if DK3_HAVE_SINL
#define	dk3md_sin(x)	sinl(x)
#else
#define	dk3md_sin(x)	(long double)sin((double)(x))
#endif

/**	Calculate cos(x).
*/
#if DK3_HAVE_COSL
#define	dk3md_cos(x)	cosl(x)
#else
#define	dk3md_cos(x)	(long double)cos((double)(x))
#endif

/**	Calculate tan(x).
*/
#if DK3_HAVE_TANL
#define	dk3md_tan(x)	tanl(x)
#else
#define	dk3md_tan(x)	(long double)tan((double)(x))
#endif

/**	Calculate asin(x).
*/
#if DK3_HAVE_ASINL
#define	dk3md_asin(x)	asinl(x)
#else
#define	dk3md_asin(x)	(long double)asin((double)(x))
#endif

/**	Calculate acos(x).
*/
#if DK3_HAVE_ACOSL
#define	dk3md_acos(x)	acosl(x)
#else
#define	dk3md_acos(x)	(long double)acos((double)(x))
#endif

/**	Calculate atan(x).
*/
#if DK3_HAVE_ATANL
#define	dk3md_atan(x)	atanl(x)
#else
#define	dk3md_atan(x)	(long double)atan((double)(x))
#endif

/**	Calculate atan of y and x.
*/
#if DK3_HAVE_ATAN2L
#define	dk3md_atan2(y,x)	atan2l(y,x)
#else
#if DK3_HAVE_ATAN2
#define dk3md_atan2(y,x)	(long double)atans((double)(y), (double)(x))
#else
#define	dk3md_atan2(y,x)	dk3ma_d_atan2(y,x)
#endif
#endif

/**	Calculate absolute value.
*/
#if DK3_HAVE_FABSL
#define	dk3md_fabs(x)	fabsl(x)
#else
#define	dk3md_fabs(x)	(long double)fabs((double)(x))
#endif

/**	Next smaller integer.
*/
#if DK3_HAVE_FLOORL
#define	dk3md_floor(x)	floorl(x)
#else
#define	dk3md_floor(x)	(long double)floor((double)(x))
#endif

/**	Next higher integer.
*/
#if DK3_HAVE_CEILL
#define	dk3md_ceil(x)	ceill(x)
#else
#define	dk3md_ceil(x)	(long double)ceil((double)(x))
#endif

/**	Rounding.
*/
#if DK3_HAVE_RINTL
#define	dk3md_rint(x)	rintl(x)
#else
#if DK3_HAVE_FLOORL
#define	dk3md_rint(x)	floorl((x) + 0.5L)
#else
#if DK3_HAVE_RINT
#define	dk3md_rint(x)	(long double)rint((double)(x))
#else
#if DK3_HAVE_FLOOR
#define	dk3md_rint(x)	(long double)floor((double)(x) + 0.5)
#else
#define	dk3md_rint(x)	dk3ma_rint(x)
#endif
#endif
#endif
#endif

/**	Calculate exp(x).
*/
#if DK3_HAVE_EXPL
#define	dk3md_exp(x)	expl(x)
#else
#define	dk3md_exp(x)	(long double)exp((double)(x))
#endif

/**	Calculate logarithm.
*/
#if DK3_HAVE_LOGL
#define	dk3md_log(x)	logl(x)
#else
#define	dk3md_log(x)	(long double)log((double)(x))
#endif

/**	Calculate square root.
*/
#if DK3_HAVE_SQRTL
#define	dk3md_sqrt(x)	sqrtl(x)
#else
#define	dk3md_sqrt(x)	(long double)sqrt((double)(x))
#endif

/**	Calculate sinh(x).
*/
#if DK3_HAVE_SINHL
#define	dk3md_sinh(x)	sinhl(x)
#else
#define	dk3md_sinh(x)	(long double)sinh((double)(x))
#endif

/**	Calculate cosh(x).
*/
#if DK3_HAVE_COSHL
#define	dk3md_cosh(x)	coshl(x)
#else
#define	dk3md_cosh(x)	(long double)cosh((double)(x))
#endif

/**	Calculate tanh(x).
*/
#if DK3_HAVE_TANHL
#define	dk3md_tanh(x)	tanhl(x)
#else
#define	dk3md_tanh(x)	(long double)tanh((double)(x))
#endif

#if (DK3_HAVE_ASINHL) && (DK3_HAVE_ACOSHL) && (DK3_HAVE_ATANHL)

/**	Caluclate arcus sinh(x).
*/
#define	dk3md_asinh(x)	asinhl(x)

/**	Calculate arcus cosh(x).
*/
#define	dk3md_acosh(x)	acoshl(x)

/**	Calculate arcus tanh(x).
*/
#define	dk3md_atanh(x)	atanhl(x)

#else
/* if (DK3_HAVE_ASINHL) && (DK3_HAVE_ACOSHL) && (DK3_HAVE_ATANHL) */

#if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH)

/**	Caluclate arcus sinh(x).
*/
#define	dk3md_asinh(x)	(long double)asinh((double)(x))

/**	Calculate arcus cosh(x).
*/
#define	dk3md_acosh(x)	(long double)acosh((double)(x))

/**	Calculate arcus tanh(x).
*/
#define	dk3md_atanh(x)	(long double)atanh((double)(x))

#else
/* if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH) */

#if (DK3_NEED_ASINH) || (DK3_NEED_ACOSH) || (DK3_NEED_ATANH)
#error	"No asinh/acosh/atanh function in math library!"
#endif

#endif
/* if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH) */

#endif
/* if (DK3_HAVE_ASINHL) && (DK3_HAVE_ACOSHL) && (DK3_HAVE_ATANHL) */

/**	Calculate summary of a and b.
*/
#define	dk3md_add(a,b)	dk3md_add_ok(a,b,NULL)

/**	Calculate difference of a and b.
*/
#define	dk3md_sub(a,b)	dk3md_sub_ok(a,b,NULL)

/**	Calculate product of a and b.
*/
#define	dk3md_mul(a,b)	dk3md_mul_ok(a,b,NULL)

/**	Calculate division of a and b.
*/
#define	dk3md_div(a,b)	dk3md_div_ok(a,b,NULL)

#ifdef __cplusplus
extern "C" {
#endif

/**	Addition of double or long double.
	@param	a	Left operand.
	@param	b	Right operand.
	@param	ec	Pointer to error code variable.
	@return	Operation result.
*/
dk3_double_t
dk3md_add_ok(dk3_double_t a, dk3_double_t b, int *ec);

/**	Substraction of double or long double.
	@param	a	Left operand.
	@param	b	Right operand.
	@param	ec	Pointer to error code variable.
	@return	Operation result.
*/
dk3_double_t
dk3md_sub_ok(dk3_double_t a, dk3_double_t b, int *ec);

/**	Multiplication of double or long double.
	@param	a	Left operand.
	@param	b	Right operand.
	@param	ec	Pointer to error code variable.
	@return	Operation result.
*/
dk3_double_t
dk3md_mul_ok(dk3_double_t a, dk3_double_t b, int *ec);

/**	Division of double or long double.
	@param	a	Left operand.
	@param	b	Right operand.
	@param	ec	Pointer to error code variable.
	@return	Operation result.
*/
dk3_double_t
dk3md_div_ok(dk3_double_t a, dk3_double_t b, int *ec);

/**	Obtain format string for conversions.
	@param	c	Key character 'e', 'f', or 'g'.
	@return	Conversion format string.
*/
dkChar const *
dk3md_format(char c);

/**	Obtain format string for conversions.
	@param	c	Key character 'e', 'f', or 'g'.
	@return	Conversion format string.
*/
char const *
dk3md_c8_format(char c);

/**	Check availability of long double.
	@return	1 for long double available, 0 for fallback to double.
*/
int
dk3md_have_long_double(void);

#ifdef __cplusplus
}
#endif

/*	Long double	(end)
*/

#else
/* DK3_HAVE_LONG_DOUBLE && (DK3_SIZEOF_LONG_DOUBLE > DK3_SIZEOF_DOUBLE) */

/*	Normal double	(start)
*/

/**	Calculate summary of a and b, set error code if necessary.
*/
#define	dk3md_add_ok(a,b,ec)	dk3ma_d_add_ok(a,b,ec)

/**	Calculate difference of a and b, set error code if necessary.
*/
#define	dk3md_sub_ok(a,b,ec)	dk3ma_d_sub_ok(a,b,ec)

/**	Calculate product of a and b, set error code if necessary.
*/
#define	dk3md_mul_ok(a,b,ec)	dk3ma_d_mul_ok(a,b,ec)

/**	Calculate division of a and b, set error code if necessary.
*/
#define	dk3md_div_ok(a,b,ec)	dk3ma_d_div_ok(a,b,ec)

/**	Calculate summary of a and b.
*/
#define	dk3md_add(a,b)		dk3ma_d_add(a,b)

/**	Calculate difference of a and b.
*/
#define	dk3md_sub(a,b)		dk3ma_d_sub(a,b)

/**	Calculate product of a and b.
*/
#define	dk3md_mul(a,b)		dk3ma_d_mul(a,b)

/**	Calculate division of a and b.
*/
#define	dk3md_div(a,b)		dk3ma_d_div(a,b)

/**	Calculate sin(x).
*/
#define	dk3md_sin(x)		sin(x)

/**	Calculate cos(x).
*/
#define	dk3md_cos(x)		cos(x)

/**	Calculate tan(x).
*/
#define	dk3md_tan(x)		tan(x)

/**	Calculate asin(x).
*/
#define	dk3md_asin(x)		asin(x)

/**	Calculate acos(x).
*/
#define	dk3md_acos(x)		acos(x)

/**	Calculate atan(x).
*/
#define	dk3md_atan(x)		atan(x)

/**	Calculate atan of y and x.
*/
#define	dk3md_atan2(y,x)	atan2(y,x)

/**	Calculate absolute value.
*/
#define	dk3md_fabs(x)		fabs(x)

/**	Next smaller integer.
*/
#define	dk3md_floor(x)		floor(x)

/**	Next higher integer.
*/
#define	dk3md_ceil(x)		ceil(x)

/**	Rounding.
*/
#define	dk3md_rint(x)		rint(x)

/**	Calculate exp(x).
*/
#define	dk3md_exp(x)		exp(x)

/**	Calculate logarithm.
*/
#define	dk3md_log(x)		log(x)

/**	Calculate square root.
*/
#define	dk3md_sqrt(x)		sqrt(x)

/**	Calculate sinh(x).
*/
#define	dk3md_sinh(x)		sinh(x)

/**	Calculate cosh(x).
*/
#define	dk3md_cosh(x)		cosh(x)

/**	Calculate tanh(x).
*/
#define	dk3md_tanh(x)		tanh(x)

#if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH)

/**	Caluclate arcus sinh(x).
*/
#define	dk3md_asinh(x)		asinh(x)

/**	Calculate arcus cosh(x).
*/
#define	dk3md_acosh(x)		acosh(x)

/**	Calculate arcus tanh(x).
*/
#define	dk3md_atanh(x)		atanh(x)

#else
/* if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH) */

#if (DK3_NEED_ASINH) || (DK3_NEED_ACOSH) || (DK3_NEED_ATANH)
#error	"No asinh/acosh/atanh function in math library!"
#endif

#endif
/* if (DK3_HAVE_ASINH) && (DK3_HAVE_ACOSH) && (DK3_HAVE_ATANH) */

#ifdef	__cplusplus
extern "C" {
#endif

/**	Obtain format string for conversions.
	@param	c	Key character 'e', 'f', or 'g'.
	@return	Conversion format string.
*/
dkChar const *
dk3md_format(char c);

/**	Obtain format string for conversions.
	@param	c	Key character 'e', 'f', or 'g'.
	@return	Conversion format string.
*/
char const *
dk3md_c8_format(char c);

/**	Check availability of long double.
	@return	1 for long double available, 0 for fallback to double.
*/
int
dk3md_have_long_double(void);

#ifdef	__cplusplus
}
#endif

/*	Normal double	(end)
*/

#endif


#endif
