/* fallback for the case when the P_ math funcitons are used outside of
   PM_ macros; not thread safe, should be avoided

   Options:

   1. single thread
      a. use PM_BEGIN/PM_ERROR/PM_END
      b. use P_log() and manually check PM_errno after the call
   2. multithread
      a. use PM_BEGIN/PM_ERROR/PM_END
      b. use P_log_() with local variable errno, manually check it after the call

   Doesn't protect against 1/0 - use P_divf() for secure division.
*/

#ifndef MAWK_MATH_WRAP
#define MAWK_MATH_WRAP

#include "num.h"

extern int PM_errno;

#define P_EFPE -1234

#define PM_BEGIN \
	{ \
		int PM_errno = 0; \

#define PM_ERROR \
		; \
		if (PM_errno != 0)

#define PM_END \
		;\
	} \

#define PM_ENDERR(errhandling) \
		; \
		if (PM_errno != 0) { errhandling ; } \
	}


double P_log_(double x, int *perrno);

#define P_log(x)      P_log_(x, &PM_errno)
#define P_divf(x, y)  P_divf_(x, y, &PM_errno)

#ifdef MAWK_NO_FLOAT
/* integer variant - no nan */
#define P_nansafe1(dest, operation, operand) \
	(dest) = (operation); \

#else
#ifdef MAWK_HAVE_SAFE_NAN
	/* proper NAN support - don't do extra checks */
# define P_nansafe1(dest, operation, operand) \
	(dest) = (operation); \

# define P_isnan_manual(x) 0

#else
#include <float.h>
	/* broken or missing NAN support, always have to check manually */
# define P_nansafe1(dest, operation, operand) \
	do { \
		if (P_isnan(operand) || P_isnan(dest)) (dest) = P_nan(); \
		else { \
			(dest) = (operation); \
			if (P_isnan(dest)) \
				(dest) = DBL_MAX; \
		} \
	} while(0)
# define P_isnan_manual P_isnan
#endif


#endif

/* forced check - for both cases */
#define P_nansafe_exp1(exp, operand) (P_isnan(operand) ? P_nan() : (exp))

#endif
