/*
	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: dk3ma.ctr
*/

/*
Copyright (C) 2011-2014, 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 dk3ma.c The dk3ma module.
*/


#line 1045 "dk3ma.ctr"

#include "dk3all.h"
#include "dk3ma.h"
#include <float.h>





#line 1052 "dk3ma.ctr"


/**	Choose object size to multiple of 16.
*/
#define	ALIGN(x) (16 * (((x) / 16) + 2))


#if (DK3_SIZEOF_DOUBLE == 8) && (DK3_HAVE_IEEE_754_DOUBLE)
/**	Type to construct double value from binary (hex) data.
*/
typedef union {
  unsigned char c[sizeof(double)];	/**< Bytes to specify hex. */
  double d; 				/**< Double value to retrieve. */
} __dk3ma_max_double_t;

/**	Maximum double value.
*/
__dk3ma_max_double_t const __dk3ma_max_double = {
#if DK3_WORDS_BIGENDIAN
  { 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
#else
  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F }
#endif
};
/**	Maximum double value for internal use.
*/
#define	dk3ma_i_max_double	__dk3ma_max_double.d
#else
/**	Maximum double value for internal use.
*/
#define	dk3ma_i_max_double	DK3_MAX_DOUBLE
#endif




/* ************************************************************************ */
/* *                                                                      * */
/* * Unsigned long                                                        * */
/* *                                                                      * */
/* ************************************************************************ */


#line 1091 "dk3ma.ctr"


unsigned long
dk3ma_ul_add_ok(unsigned long a, unsigned long b, int *ec)
{
  if(ec) {
    if((DK3_UL_MAX - a) < b) {*ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return(a + b);
}



unsigned long
dk3ma_ul_sub_ok(unsigned long a, unsigned long b, int *ec)
{
  if(ec) {
    if(b > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return(a - b);
}



unsigned long
dk3ma_ul_mul_ok(unsigned long a, unsigned long b, int *ec)
{
  if(ec) {
    if(a) {
      if((DK3_UL_MAX / a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  }
  return(a * b);
}



unsigned long
dk3ma_ul_div_ok(unsigned long a, unsigned long b, int *ec)
{
  if(b) {
    return(a / b);
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(0UL);
  }
}



unsigned long
dk3ma_ul_gcd(unsigned long a, unsigned long b)
{
  unsigned long h = 0UL;
  while(b > 0UL) {
    h = a % b;
    a = b;
    b = h;
  }
  if(0UL == a) a = 1UL;
  return a;
}



int
dk3ma_ul_to_c8_string(char *rb, size_t sz, unsigned long va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
    sprintf(buffer, "%lu", va);
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_ul_to_string(dkChar *rb, size_t sz, unsigned long va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
    dk3sf_sprintf3(buffer, dkT("%lu"), va);
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_ul_to_hex_string(dkChar *rb, size_t sz, unsigned long va)
{
  dkChar	buffer[ALIGN(1 + 2 * DK3_SIZEOF_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_SIZEOF_LONG == 4
    dk3sf_sprintf3(buffer, dkT("%08lx"), va);
#else
#if DK3_SIZEOF_LONG == 8
    dk3sf_sprintf3(buffer, dkT("%016lx"), va);
#else
#error	"Size of long is not 4 or 8!"
#endif
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_ul(unsigned long *rp, char const *str)
{
  unsigned long	ul;
  int		back	= 0;
  if((rp) && (str)) {
    if(sscanf(str, "%lu", &ul) == 1) {
      *rp = ul;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_ul(unsigned long *rp, dkChar const *str)
{
  unsigned long	ul;
  int		back	= 0;
  if((rp) && (str)) {
    if(dk3sf_sscanf3(str, dkT("%lu"), &ul)) {
      *rp = ul;
      back = 1;
    }
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert double to unsigned long.
	@param	x	Value to convert, must be in range.
	@return	Conversion result.
*/
static
unsigned long
dk3ma_i_d_to_ul(double x)
{
  double		tv	= DK3_UL_FIRST_BIT_AS_DOUBLE;
  unsigned long		tb	= DK3_UL_FIRST_BIT;
  unsigned long		back	= 0UL;
  size_t		i;
  for(i = 0; i < (8 * DK3_SIZEOF_LONG); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / 2UL;
  }
  return back;
}
#endif

unsigned long
dk3ma_d_to_ul_ok(double x, int *ec)
{
  unsigned long		back = 0UL;
  

#line 1277 "dk3ma.ctr"
  if(0.0 <= x) {
    if(DK3_UL_MAX_AS_DOUBLE <= x) {
      back = DK3_UL_MAX;
      if(DK3_UL_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (unsigned long)x;
#else
      back = dk3ma_i_d_to_ul(x);
#endif
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  } 

#line 1293 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert unsigned long to double.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
dk3ma_i_ul_to_d(unsigned long x)
{
  double	tv	= 1.0;
  double	back	= 0.0;
  unsigned long	tb	= 1UL;
  size_t	i;
  for(i = 0; i < (8 * DK3_SIZEOF_LONG); i++) {
    if(x & tb) {
      back = back + tv;
    }
    tb = tb * 2UL;
    tv = tv * 2.0;
  }
  return back;
}
#endif

double
dk3ma_ul_to_d(unsigned long x)
{
  double back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  back = dk3ma_i_ul_to_d(x);
#endif
  return back;
}



/* ************************************************************************ */
/* *                                                                      * */
/* * Long                                                                 * */
/* *                                                                      * */
/* ************************************************************************ */


#line 1339 "dk3ma.ctr"



long
dk3ma_l_abs(long l)
{
#if DK3_HAVE_LABS
  return(labs(l));
#else
  return((0L <= l) ? (l) : (0L - l));
#endif
}



long
dk3ma_l_add_ok(long a, long b, int *ec)
{
  if(ec) {
    if((0L < a) && (0L < b)) {
      if((DK3_L_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0L > a) && (0L > b)) {
        if(DK3_L_MIN == a) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_L_MIN - a) > b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    }
  }
  return(a + b);
}



long
dk3ma_l_sub_ok(long a, long b, int *ec)
{
  if(ec) {
    if((0L < a) && (0L > b)) {
      if((DK3_L_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0L > a) && (0L < b)) {
	if((DK3_L_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    }
  }
  return(a - b);
}



long
dk3ma_l_mul_ok(long a, long b, int *ec)
{
  if(ec) {
    if((a) && (b)) {
      if((DK3_L_MIN == a) && (1L != b)) {
        *ec = DK3_ERROR_MATH_OVERFLOW;
      } else {
        if((DK3_L_MIN == b) && (1L != a)) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_L_MAX / dk3ma_l_abs(a)) < dk3ma_l_abs(b)) {
	    *ec = DK3_ERROR_MATH_OVERFLOW;
	  }
	}
      }
    }
  }
  return(a * b);
}



long
dk3ma_l_div_ok(long a, long b, int *ec)
{
  if(b) {
    if((DK3_L_MIN == a) && (-1L == b)) {
      if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
      return(0L);
    } else {
      return(a / b);
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(0L);
  }
}



long
dk3ma_l_gcd_ok(long a, long b, int *ec)
{
  long h;
  if(DK3_L_MIN == a) {
    a = 0L;
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  } else {
    if(DK3_L_MIN == b) {
      a = 0L;
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      a = dk3ma_l_abs(a);
      b = dk3ma_l_abs(b);
      while(0L < b) {
        h = a % b;
	a = b;
	b = h;
      }
      if(0L == a) { a = 1L; }
    }
  }
  return(a);
}



int
dk3ma_l_to_c8_string(char *rb, size_t sz, long va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
    sprintf(buffer, "%ld", va);
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_l_to_string(dkChar *rb, size_t sz, long va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
    dk3sf_sprintf3(buffer, dkT("%ld"), va);
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_l(long *rp, char const *str)
{
  long		l;
  int		back = 0;
  if((rp) && (str)) {
    if(sscanf(str, "%ld", &l) == 1) {
      *rp = l;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_l(long *rp, dkChar const *str)
{
  long	l;
  int	back	= 0;
  if((rp) && (str)) {
    if(dk3sf_sscanf3(str, dkT("%ld"), &l)) {
      *rp = l;
      back = 1;
    }
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
static
long
dk3ma_i_d_to_l(double x)
{
  double	tv	= DK3_L_FIRST_BIT_AS_DOUBLE;
  long		tb	= DK3_L_FIRST_BIT;
  long		back	= 0L;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_LONG) - 1); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / 2L;
  }
  return back;
}
#endif

long
dk3ma_d_to_l_ok(double x, int *ec)
{
  long back;
  

#line 1552 "dk3ma.ctr"
  if(DK3_L_MIN_AS_DOUBLE >= x) {
    back = DK3_L_MIN;
    if(DK3_L_MIN_AS_DOUBLE > x) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(DK3_L_MAX_AS_DOUBLE <= x) {
      back = DK3_L_MAX;
      if(DK3_L_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (long)x;
#else
      if(0.0 <= x) {
        back = dk3ma_i_d_to_l(x);
      } else {
        back = 0L - dk3ma_i_d_to_l(0.0 - x);
      }
#endif
    }
  } 

#line 1575 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert long to double.
	@param	x	Value to convert, must be non-negative.
	@return	Conversion result.
*/
static
double
dk3ma_i_l_to_d(long x)
{
  double	tv	= 1.0;
  double	back	= 0.0;
  long		tb	= 1L;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_LONG) - 1); i++) {
    if(x & tb) { back = back + tv; }
    tb = tb * 2L;
    tv = tv * 2.0;
  }
  return back;
}
#endif

double
dk3ma_l_to_d(long x)
{
  double	back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  if(0L <= x) {
    back = dk3ma_i_l_to_d(x);
  } else {
    if(DK3_L_MIN == x) {
      back = DK3_L_MIN_AS_DOUBLE;
    } else {
      back = 0.0 - dk3ma_i_l_to_d(0L - x);
    }
  }
#endif
  return back;
}



#if DK3_HAVE_LONG_LONG

/* ************************************************************************ */
/* *                                                                      * */
/* * unsigned long long                                                   * */
/* *                                                                      * */
/* ************************************************************************ */


#line 1629 "dk3ma.ctr"

unsigned long long
dk3ma_ull_add_ok(unsigned long long a, unsigned long long b, int *ec)
{
  if(ec) {
    if((DK3_ULL_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return(a + b);
}



unsigned long long
dk3ma_ull_sub_ok(unsigned long long a, unsigned long long b, int *ec)
{
  if(ec) {
    if(b > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return(a - b);
}



unsigned long long
dk3ma_ull_mul_ok(unsigned long long a, unsigned long long b, int *ec)
{
  if(ec) {
    if(a) {
      if((DK3_ULL_MAX / a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  }
  return(a * b);
}



unsigned long long
dk3ma_ull_div_ok(unsigned long long a, unsigned long long b, int *ec)
{
  if(b) {
    return(a / b);
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(0ULL);
  }
}



unsigned long long
dk3ma_ull_gcd(unsigned long long a, unsigned long long b)
{
  unsigned long long	h = 0ULL;
  while(0ULL < b) {
    h = a % b;
    a = b;
    b = h;
  }
  if(0ULL == a) { a = 1ULL; }
  return(a);
}



int
dk3ma_ull_to_c8_string(char *rb, size_t sz, unsigned long long va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64u", va);
#else
    sprintf(buffer, "%llu", va);
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_ull_to_string(dkChar *rb, size_t sz, unsigned long long va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG_LONG)];
  int		back = 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    dk3sf_sprintf3(buffer, dkT("%I64u"), va);
#else
    dk3sf_sprintf3(buffer, dkT("%llu"), va);
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_ull_to_hex_string(dkChar *rb, size_t sz, unsigned long long va)
{
  dkChar	buffer[ALIGN(1 + 2 * DK3_SIZEOF_LONG_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_SIZEOF_LONG_LONG == 4
#if DK3_ON_WINDOWS
#error	"On Windows we can not handle long long with size not 8!"
    dk3sf_sprintf3(buffer, dkT("%08I32x"), va);
#else
    dk3sf_sprintf3(buffer, dkT("%08llx"), va);
#endif
#else
#if DK3_SIZEOF_LONG_LONG == 8
#if DK3_ON_WINDOWS
    dk3sf_sprintf3(buffer, dkT("%016I64x"), va);
#else
    dk3sf_sprintf3(buffer, dkT("%016llx"), va);
#endif
#else
#error	"Size of long long is not 4 or 8!"
#endif
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_ull(unsigned long long *rp, char const *str)
{
  unsigned long long	ul;
  int			back = 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
    if(sscanf(str, "%I64u", &ul) == 1)
#else
    if(sscanf(str, "%llu", &ul) == 1)
#endif
    {
      *rp = ul;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_ull(unsigned long long *rp, dkChar const *str)
{
  unsigned long long	ul;
  int			back = 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
    if(dk3sf_sscanf3(str, dkT("%I64u"), &ul))
#else
    if(dk3sf_sscanf3(str, dkT("%llu"), &ul))
#endif
    {
      *rp = ul;
      back = 1;
    }
  }
  return back;
}


#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert double to unsigned long long.
	@param	x	Value to convert, must be in range.
	@return	Conversion result.
*/
static
unsigned long long
dk3ma_i_d_to_ull(double x)
{
  double		tv	= DK3_ULL_FIRST_BIT_AS_DOUBLE;
  unsigned long long	tb	= DK3_ULL_FIRST_BIT;
  unsigned long long	back	= 0ULL;
  size_t		i;
  for(i = 0; i < (8 * DK3_SIZEOF_LONG_LONG); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / 2ULL;
  }
  return back;
}
#endif

unsigned long long
dk3ma_d_to_ull_ok(double x, int *ec)
{
  unsigned long long back;
  

#line 1840 "dk3ma.ctr"
  if(0.0 >= x) {
    back = 0ULL;
    if(0.0 > x) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(DK3_ULL_MAX_AS_DOUBLE <= x) {
      back = DK3_ULL_MAX;
      if(DK3_ULL_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (unsigned long long)x;
#else
      back = dk3ma_i_d_to_ull(x);
#endif
    }
  } 

#line 1859 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert unsigned long long to double.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
dk3ma_i_ull_to_d(unsigned long long x)
{
  double		back	= 0.0;
  double		tv	= 1.0;
  unsigned long long	tb	= 1ULL;
  size_t		i;
  for(i = 0; i < (8 * DK3_SIZEOF_LONG_LONG); i++) {
    if(x & tb) { back = back + tv; }
    tb = tb * 2ULL;
    tv = tv * 2.0;
  }
  return back;
}
#endif

double
dk3ma_ull_to_d(unsigned long long x)
{
  double	back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  back = dk3ma_i_ull_to_d(x);
#endif
  return back;
}



/* ************************************************************************ */
/* *                                                                      * */
/* * long long                                                            * */
/* *                                                                      * */
/* ************************************************************************ */


#line 1903 "dk3ma.ctr"



long long
dk3ma_ll_abs(long long l)
{
#if DK3_HAVE_LLABS
  return(llabs(l));
#else
  return((0LL <= l) ? (l) : (0LL - l));
#endif
}



long long
dk3ma_ll_add_ok(long long a, long long b, int *ec)
{
  if(ec) {
    if((0LL < a) && (0LL < b)) {
      if((DK3_LL_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0LL > a) && (0LL > b)) {
        if(DK3_LL_MIN == a) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_LL_MIN - a) > b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    }
  }
  return(a + b);
}



long long
dk3ma_ll_sub_ok(long long a, long long b, int *ec)
{
  if(ec) {
    if((0LL < a) && (0LL > b)) {
      if((DK3_LL_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0LL > a) && (0LL < b)) {
        if(DK3_LL_MIN == a) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_LL_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    }
  }
  return(a - b);
}



long long
dk3ma_ll_mul_ok(long long a, long long b, int *ec)
{
  if(ec) {
    if((a) && (b)) {
      if((DK3_LL_MIN == a) && (1LL != b)) {
        *ec = DK3_ERROR_MATH_OVERFLOW;
      } else {
        if((DK3_LL_MIN == b) && (1LL != a)) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_LL_MAX / dk3ma_ll_abs(a)) < dk3ma_ll_abs(b)) {
	    *ec = DK3_ERROR_MATH_OVERFLOW;
	  }
	}
      }
    }
  }
  return(a * b);
}



long long
dk3ma_ll_div_ok(long long a, long long b, int *ec)
{
  if(b) {
    if((DK3_LL_MIN == a) && (-1LL == b)) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      return(0LL);
    } else {
      return(a / b);
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(0LL);
  }
}



long long
dk3ma_ll_gcd_ok(long long a, long long b, int *ec)
{
  long long	h;
  if(DK3_LL_MIN == a) {
    a = 0LL;
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  } else {
    if(DK3_LL_MIN == b) {
      a = 0LL;
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      a = dk3ma_ll_abs(a);
      b = dk3ma_ll_abs(b);
      while(0LL < b) {
        h = a % b;
	a = b;
	b = h;
      }
      if(0LL == a) { a = 1LL; }
    }
  }
  return(a);
}



int
dk3ma_ll_to_c8_string(char *rb, size_t sz, long long va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64d", va);
#else
    sprintf(buffer, "%lld", va);
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_ll_to_string(dkChar *rb, size_t sz, long long va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_LONG_LONG)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    dk3sf_sprintf3(buffer, dkT("%I64d"), va);
#else
    dk3sf_sprintf3(buffer, dkT("%lld"), va);
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_ll(long long *rp, char const *str)
{
  long long	l;
  int		back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
    if(sscanf(str, "%I64d", &l) == 1)
#else
    if(sscanf(str, "%lld", &l) == 1)
#endif
    {
      *rp = l;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_ll(long long *rp, dkChar const *str)
{
  long long	l;
  int		back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
    if(dk3sf_sscanf3(str, dkT("%I64d"), &l))
#else
    if(dk3sf_sscanf3(str, dkT("%lld"), &l))
#endif
    {
      *rp = l;
      back = 1;
    }
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert double to long long.
	@param	x	Value to convert, must be non-negative and in range
			from 0.0 to DK3_LL_MAX_AS_DOUBLE.
	@return	Conversion result.
*/
static
long long
dk3ma_i_d_to_ll(double x)
{
  long long	tb	= DK3_LL_FIRST_BIT;
  long long	back	= 0LL;
  double	tv	= DK3_LL_FIRST_BIT_AS_DOUBLE;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_LONG_LONG) - 1); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / 2LL;
  }
  return back;
}
#endif

long long
dk3ma_d_to_ll_ok(double x, int *ec)
{
  long long	back;
  

#line 2143 "dk3ma.ctr"
  if(DK3_LL_MIN_AS_DOUBLE >= x) {
    back = DK3_LL_MIN;
    if(DK3_LL_MIN_AS_DOUBLE > x) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(DK3_LL_MAX_AS_DOUBLE <= x) {
      back = DK3_LL_MAX;
      if(DK3_LL_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (long long)x;
#else
      if(0.0 <= x) {
        back = dk3ma_i_d_to_ll(x);
      } else {
        back = 0LL - dk3ma_i_d_to_ll(0.0 - x);
      }
#endif
    }
  } 

#line 2166 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert long long to double.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
dk3ma_i_ll_to_d(long long x)
{
  long long	tb	= 1LL;
  double	tv	= 1.0;
  double	back	= 0.0;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_LONG_LONG) - 1); i++) {
    if(x & tb) { back = back + tv; }
    tv = tv * 2.0;
    tb = tb * 2LL;
  }
  return back;
}
#endif

double
dk3ma_ll_to_d(long long x)
{
  double	back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  if(0LL <= x) {
    back = dk3ma_i_ll_to_d(x);
  } else {
    if(DK3_LL_MIN == x) {
      back = DK3_LL_MIN_AS_DOUBLE;
    } else {
      back = 0.0 - dk3ma_i_ll_to_d(0LL - x);
    }
  }
#endif
  return back;
}

#endif



#if DK3_HAVE_INTMAX_T

/* ************************************************************************ */
/* *                                                                      * */
/* * uintmax_t                                                            * */
/* *                                                                      * */
/* ************************************************************************ */


#line 2222 "dk3ma.ctr"

uintmax_t
dk3ma_uintmax_t_add_ok(uintmax_t a, uintmax_t b, int *ec)
{
  if(ec) {
    if((DK3_UINTMAX_T_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  } 
  return(a + b);
}



uintmax_t
dk3ma_uintmax_t_sub_ok(uintmax_t a, uintmax_t b, int *ec)
{
  if(ec) {
    if(b > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return(a - b);
}



uintmax_t
dk3ma_uintmax_t_mul_ok(uintmax_t a, uintmax_t b, int *ec)
{
  if(ec) {
    if(a) {
      if((DK3_UINTMAX_T_MAX / a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  }
  return(a * b);
}



uintmax_t
dk3ma_uintmax_t_div_ok(uintmax_t a, uintmax_t b, int *ec)
{
  if(b) {
    return(a / b);
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(DK3_UINTMAX_T_0);
  }
}



uintmax_t
dk3ma_uintmax_t_gcd(uintmax_t a, uintmax_t b)
{
  uintmax_t	h = DK3_UINTMAX_T_0;
  while(DK3_UINTMAX_T_0 < b) {
    h = a % b;
    a = b;
    b = h;
  }
  if(DK3_UINTMAX_T_0 == a) { a = DK3_UINTMAX_T_1; }
  return(a);
}



int
dk3ma_uintmax_t_to_c8_string(char *rb, size_t sz, uintmax_t va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_INTMAX_T)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    sprintf(buffer, "%I64u", (unsigned long long)va);
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    sprintf(buffer, "%lu", (unsigned long)va);
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    sprintf(buffer, "%ju", va);
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_uintmax_t_to_string(dkChar *rb, size_t sz, uintmax_t va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_INTMAX_T)];
  int		back = 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    dk3sf_sprintf3(buffer, dkT("%I64u"), (unsigned long long)va);
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    dk3sf_sprintf3(buffer, dkT("%lu"), (unsigned long)va);
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    dk3sf_sprintf3(buffer, dkT("%ju"), va);
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_uintmax_t_to_hex_string(dkChar *rb, size_t sz, uintmax_t va)
{
  dkChar	buffer[ALIGN(1 + 2 * DK3_SIZEOF_INTMAX_T)];
  int		back	= 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS

#if DK3_SIZEOF_INTMAX_T == 8
    dk3sf_sprintf3(buffer, dkT("%016I64x"), (unsigned long long)va);
#else
#error	"Size of intmax_t is not 8!"
#endif

#else

#if DK3_SIZEOF_INTMAX_T == 4
    dk3sf_sprintf3(buffer, dkT("%08jx"), va);
#else
#if DK3_SIZEOF_INTMAX_T == 8
    dk3sf_sprintf3(buffer, dkT("%016jx"), va);
#else
#error	"Size of intmax_t is not 4 or 8!"
#endif
#endif

#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_uintmax_t(uintmax_t *rp, char const *str)
{
  uintmax_t		uim;
  int			back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    if(sscanf(str, "%I64u", &uim) == 1)
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    if(sscanf(str, "%lu", &uim) == 1)
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    if(sscanf(str, "%ju", &uim) == 1)
#endif
    {
      *rp = uim;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_uintmax_t(uintmax_t *rp, dkChar const *str)
{
  uintmax_t	uim;
  int		back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    if(dk3sf_sscanf3(str, dkT("%I64u"), &uim))
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    if(dk3sf_sscanf3(str, dkT("%lu"), &uim))
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    if(dk3sf_sscanf3(str, dkT("%ju"), &uim))
#endif
    {
      *rp = uim;
      back = 1;
    }
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert from double to uintmax_t.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
uintmax_t
dk3ma_i_d_to_uintmax_t(double x)
{
  double	tv	= DK3_UINTMAX_T_FIRST_BIT_AS_DOUBLE;
  uintmax_t	tb	= DK3_UINTMAX_T_FIRST_BIT;
  uintmax_t	back	= DK3_UINTMAX_T_0;
  size_t	i;
  for(i = 0; i < (8 * DK3_SIZEOF_INTMAX_T); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / DK3_UINTMAX_T_2;
  }
  return back;
}
#endif

uintmax_t
dk3ma_d_to_uintmax_t_ok(double x, int *ec)
{
  uintmax_t	back;
  

#line 2469 "dk3ma.ctr"
  if(0.0 >= x) {
    back = DK3_UINTMAX_T_0;
    if(0.0 > x) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(DK3_UINTMAX_T_MAX_AS_DOUBLE <= x) {
      back = DK3_UINTMAX_T_MAX;
      if(DK3_UINTMAX_T_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (uintmax_t)x;
#else
      back = dk3ma_i_d_to_uintmax_t(x);
#endif
    }
  } 

#line 2488 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert from uintmax_t to double.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
dk3ma_i_uintmax_t_to_d(uintmax_t x)
{
  double	tv	= 1.0;
  double	back	= 0.0;
  uintmax_t	tb	= DK3_UINTMAX_T_1;
  size_t	i;
  for(i = 0; i < (8 * DK3_SIZEOF_INTMAX_T); i++) {
    if(x & tb) { back = back + tv; }
    tb = tb * DK3_UINTMAX_T_2;
    tv = tv * 2.0;
  }
  return back;
}
#endif

double
dk3ma_uintmax_t_to_d(uintmax_t x)
{
  double	back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  back = dk3ma_i_uintmax_t_to_d(x);
#endif
  return back;
}



/* ************************************************************************ */
/* *                                                                      * */
/* * intmax_t                                                             * */
/* *                                                                      * */
/* ************************************************************************ */


#line 2532 "dk3ma.ctr"

intmax_t
dk3ma_intmax_t_abs(intmax_t x)
{
#if DK3_HAVE_IMAXABS
  return(imaxabs(x));
#else
  return((DK3_INTMAX_T_0 <= x) ? (x) : (DK3_INTMAX_T_0 - x));
#endif
}



intmax_t
dk3ma_intmax_t_add_ok(intmax_t a, intmax_t b, int *ec)
{
  if(ec) {
    if((DK3_INTMAX_T_0 < a) && (DK3_INTMAX_T_0 < b)) {
      if((DK3_INTMAX_T_MAX - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((DK3_INTMAX_T_0 > a) && (DK3_INTMAX_T_0 > b)) {
        if(DK3_INTMAX_T_MIN == a) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_INTMAX_T_MIN - a) > b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    }
  }
  return(a + b);
}



intmax_t
dk3ma_intmax_t_sub_ok(intmax_t a, intmax_t b, int *ec)
{
  if(ec) {
    if((DK3_INTMAX_T_0 < a) && (DK3_INTMAX_T_0 > b)) {
      if((DK3_INTMAX_T_MAX + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((DK3_INTMAX_T_0 < a) && (DK3_INTMAX_T_0 > b)) {
        if((DK3_INTMAX_T_MIN + b) > a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    }
  }
  return(a - b);
}



intmax_t
dk3ma_intmax_t_mul_ok(intmax_t a, intmax_t b, int *ec)
{
  if(ec) {
    if((a) && (b)) {
      if((DK3_INTMAX_T_MIN == a) && (DK3_INTMAX_T_1 != b)) {
        *ec = DK3_ERROR_MATH_OVERFLOW;
      } else {
        if((DK3_INTMAX_T_MIN == b) && (DK3_INTMAX_T_1 != a)) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	} else {
	  if((DK3_INTMAX_T_MAX / dk3ma_intmax_t_abs(a)) < dk3ma_intmax_t_abs(b))
	  {
	    *ec = DK3_ERROR_MATH_OVERFLOW;
	  }
	}
      }
    }
  }
  return(a * b);
}



intmax_t
dk3ma_intmax_t_div_ok(intmax_t a, intmax_t b, int *ec)
{
  if(b) {
    if((DK3_INTMAX_T_MIN == a) && (DK3_INTMAX_T_MINUS_1 == b)) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      return(DK3_INTMAX_T_0);
    } else {
      return(a / b);
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    return(DK3_INTMAX_T_0);
  }
}



intmax_t
dk3ma_intmax_t_gcd_ok(intmax_t a, intmax_t b, int *ec)
{
  intmax_t	h;
  if(DK3_INTMAX_T_MIN == a) {
    a = DK3_INTMAX_T_0;
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  } else {
    if(DK3_INTMAX_T_MIN == b) {
      a = DK3_INTMAX_T_0;
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      a = dk3ma_intmax_t_abs(a);
      b = dk3ma_intmax_t_abs(b);
      while(DK3_INTMAX_T_0 < b) {
        h = a % b;
	a = b;
	b = h;
      }
      if(DK3_INTMAX_T_0 == a) { a = DK3_INTMAX_T_1; }
    }
  }
  return(a);
}



int
dk3ma_intmax_t_to_c8_string(char *rb, size_t sz, intmax_t va)
{
  char		buffer[ALIGN(1 + 4 * DK3_SIZEOF_INTMAX_T)];
  int		back = 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    sprintf(buffer, "%I64d", va);
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    sprintf(buffer, "%ld", va);
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    sprintf(buffer, "%jd", va);
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy_not_overlapped(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_intmax_t_to_string(dkChar *rb, size_t sz, intmax_t va)
{
  dkChar	buffer[ALIGN(1 + 4 * DK3_SIZEOF_INTMAX_T)];
  int		back = 0;
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    dk3sf_sprintf3(buffer, dkT("%I64d"), va);
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    dk3sf_sprintf3(buffer, dkT("%ld"), va);
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    dk3sf_sprintf3(buffer, dkT("%jd"), va);
#endif
    if(dk3str_len(buffer) < sz) {
      dk3str_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_c8_string_to_intmax_t(intmax_t *rp, char const *str)
{
  intmax_t	im;
  int		back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    if(sscanf(str, "%I64d", &im) == 1)
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    if(sscanf(str, "%ld", &im) == 1)
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    if(sscanf(str, "%jd", &im) == 1)
#endif
    {
      *rp = im;
      back = 1;
    }
  }
  return back;
}



int
dk3ma_string_to_intmax_t(intmax_t *rp, dkChar const *str)
{
  intmax_t	im;
  int		back	= 0;
  if((rp) && (str)) {
#if DK3_ON_WINDOWS
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG_LONG
    if(dk3sf_sscanf3(str, dkT("%I64d"), &im))
#else
#if DK3_SIZEOF_INTMAX_T == DK3_SIZEOF_LONG
    if(dk3sf_sscanf3(str, dkT("%ld"), &im))
#else
#error	"Size of intmax_t does not match size of long long or long!"
#endif
#endif
#else
    if(dk3sf_sscanf3(str, dkT("%jd"), &im))
#endif
    {
      *rp = im;
      back = 1;
    }
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert double to intmax_t.
	@param	x	Value to convert, must be non-negative and in range.
	@return	Conversion result.
*/
static
intmax_t
dk3ma_i_d_to_intmax_t_ok(double x, int *ec)
{
  intmax_t	tb	= DK3_INTMAX_T_FIRST_BIT;
  intmax_t	back	= DK3_INTMAX_T_0;
  double	tv	= DK3_INTMAX_T_FIRST_BIT_AS_DOUBLE;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_INTMAX_T) - 1); i++) {
    if(x >= tv) {
      x = x - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / DK3_INTMAX_T_2;
  }
  return back;
}
#endif

intmax_t
dk3ma_d_to_intmax_t_ok(double x, int *ec)
{
  intmax_t	back;
  

#line 2798 "dk3ma.ctr"
  if(DK3_INTMAX_T_MIN_AS_DOUBLE >= x) {
    back = DK3_INTMAX_T_MIN;
    if(DK3_INTMAX_T_MIN_AS_DOUBLE > x) {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(DK3_INTMAX_T_MAX_AS_DOUBLE <= x) {
      back = DK3_INTMAX_T_MAX;
      if(DK3_INTMAX_T_MAX_AS_DOUBLE < x) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (intmax_t)x;
#else
      if(0.0 <= x) {
        back = dk3ma_i_d_to_intmax_t_ok(x, ec);
      } else {
        back = DK3_INTMAX_T_0 - dk3ma_i_d_to_intmax_t_ok((0.0 - x), ec);
      }
#endif
    }
  } 

#line 2821 "dk3ma.ctr"
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
/**	Convert intmax_t to double.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
dk3ma_i_intmax_t_to_d(intmax_t x)
{
  double	tv	= 1.0;
  double	back	= 0.0;
  intmax_t	tb	= DK3_INTMAX_T_1;
  size_t	i;
  for(i = 0; i < ((8 * DK3_SIZEOF_INTMAX_T) - 1); i++) {
    if(x & tb) { back = back + tv; }
    tv = tv * 2.0;
    tb = tb * DK3_INTMAX_T_2;
  }
  return back;
}
#endif

double
dk3ma_intmax_t_to_d(intmax_t x)
{
  double back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  if(DK3_INTMAX_T_0 <= x) {
    back = dk3ma_i_intmax_t_to_d(x);
  } else {
    if(DK3_INTMAX_T_MIN == x) {
      back = DK3_INTMAX_T_MIN_AS_DOUBLE;
    } else {
      back = 0.0 - dk3ma_i_intmax_t_to_d(DK3_INTMAX_T_0 - x);
    }
  }
#endif
  return back;
}


#endif




/* double */

double
dk3ma_d_abs(double x)
{
#if DK3_HAVE_FABS
  return(fabs(x));
#else
  return((0.0 <= x) ? (x) : (0.0 - x));
#endif
}



double
dk3ma_d_add_ok(double a, double b, int *ec)
{
  if(ec) {
    if((0.0 < a) && (0.0 < b)) {
      if((dk3ma_i_max_double - a) < b) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0.0 > a) && (0.0 > b)) {
        if(((-1.0 * dk3ma_i_max_double) - a) > b) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	}
      }
    }
  }
  return(a + b);
}



double
dk3ma_d_sub_ok(double a, double b, int *ec)
{
  if(ec) {
    if((0.0 < a) && (0.0 > b)) {
      if((dk3ma_i_max_double + b) < a) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    } else {
      if((0.0 > a) && (0.0 < b)) {
        if(((-1.0 * dk3ma_i_max_double) + b) > a) {
	  *ec = DK3_ERROR_MATH_OVERFLOW;
	}
      }
    }
  }
  return(a - b);
}



double
dk3ma_d_mul_ok(double a, double b, int *ec)
{
  if(ec) {
    if(dk3ma_d_abs(a) > 1.0) {
      if((dk3ma_i_max_double / dk3ma_d_abs(a)) < dk3ma_d_abs(b)) {
        *ec = DK3_ERROR_MATH_OVERFLOW;
      }
    }
  }
  return(a * b);
}



double
dk3ma_d_div_ok(double a, double b, int *ec)
{
#if DK3_HAVE_FPCLASSIFY && defined(FP_ZERO)
  if(FP_ZERO == fpclassify(b)) {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
    if(FP_ZERO == fpclassify(a)) {
      return(NAN);
    } else {
      if(0.0 <= a) {
        return(INFINITY);
      } else {
        return(-INFINITY);
      }
    }
  } else {
    if(dk3ma_d_abs(b) >= 1.0) {
      return(a / b);
    } else {
      if((dk3ma_i_max_double * dk3ma_d_abs(b)) < dk3ma_d_abs(a)) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	if(((0.0 <= a) && (0.0 <= b)) || ((0.0 > a) && (0.0 > b))) {
	  return(INFINITY);
	} else {
	  return(-INFINITY);
	}
      } else {
        return(a / b);
      }
    }
  }
#else
#if DK3_ON_WINDOWS
  switch(_fpclass(b)) {
    case _FPCLASS_NZ:
    case _FPCLASS_PZ: {
      if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
      switch(_fpclass(a)) {
        case _FPCLASS_NZ:
	case _FPCLASS_PZ: {
#if defined(NAN)
	  return(NAN);
#else
	  return(dk3ma_i_max_double);
#endif
	} break;
	default: {
	  if(0.0 <= a) {
	    return(HUGE_VAL);
	  } else {
	    return(-HUGE_VAL);
	  }
	} break;
      }
    } break;
    default: {
      if(dk3ma_d_abs(b) >= 1.0) {
        return(a / b);
      } else {
        if((dk3ma_i_max_double * dk3ma_d_abs(b)) < dk3ma_d_abs(a)) {
	  if(((0.0 <= a) && (0.0 <= b)) || ((0.0 > a) && (0.0 > b))) {
	    return(HUGE_VAL);
	  } else {
	    return(-HUGE_VAL);
	  }
	} else {
	  return(a / b);
	}
      }
    } break;
  }
#else
  if(dk3ma_d_abs(b) >= 1.0) {
    return(a / b);
  } else {
    if((dk3ma_i_max_double * dk3ma_d_abs(b)) < dk3ma_d_abs(a)) {
      if(((0.0 <= a) && (0.0 <= b)) || ((0.0 > a) && (0.0 > b))) {
#ifdef INFINITY
	return(INFINITY);
#else
#ifdef HUGE_VAL
	return(HUGE_VAL);
#else
	return(dk3ma_i_max_double);
#endif
#endif
      } else {
#ifdef INFINITY
	return(-INFINITY);
#else
#ifdef HUGE_VAL
	return(-HUGE_VAL);
#else
	return(-1.0 * dk3ma_i_max_double);
#endif
#endif
      }
    } else {
      return(a / b);
    }
  }
#endif
#endif
}



double
dk3ma_rint(double x)
{
#if DK3_HAVE_RINT
  return(rint(x));
#else
  return(floor(x + 0.5));
#endif
}


size_t
dk3ma_sz_add_ok(size_t a, size_t b, int *ec)
{
  size_t back = 0;
  back = a + b;
  if(b >= (DK3_SIZE_T_MAX - a)) {
    back = 0;
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return back;
}



size_t
dk3ma_sz_mul_ok(size_t a, size_t b, int *ec)
{
  size_t back = 0;
  if((a) && (b)) {
    if(b < (DK3_SIZE_T_MAX / a)) {
      back = a * b;
    } else {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  }
  return back;
}



double
dk3ma_atan2(double y, double x)
{
#if DK3_HAVE_ATAN2
  double		 back;
  

#line 3095 "dk3ma.ctr"
  back = atan2(y, x);	

#line 3096 "dk3ma.ctr"
  while(back < 0.0) { back += (2.0 * M_PI); }
  while(back > (2.0 * M_PI)) { back -= (2.0 * M_PI); }
  

#line 3099 "dk3ma.ctr"
  return back;
#else
  double		 back = -5.0 * M_PI;
  double		 v;
  

#line 3104 "dk3ma.ctr"
  v = dk3ma_d_div_ok(y, x, &mec);
  if(mec) {			

#line 3106 "dk3ma.ctr"
    if(y < 0.0) {		

#line 3107 "dk3ma.ctr"
      back = 1.5 * M_PI;
    } else {			

#line 3109 "dk3ma.ctr"
      back = 0.5 * M_PI;
    }
  } else {			

#line 3112 "dk3ma.ctr"
    back = atan(v);
    if(x < 0.0) {		

#line 3114 "dk3ma.ctr"
      back += M_PI;
    }
  }	

#line 3117 "dk3ma.ctr"
  while(back < 0.0) { back += (2.0 * M_PI); }
  while(back > (2.0 * M_PI)) { back -= (2.0 * M_PI); }
  

#line 3120 "dk3ma.ctr"
  return back;
#endif
}



int
dk3ma_d_equal(double a, double b, double epsilon)
{
  int		 back = 0;
  int		 ec = 0;
  if(fabs(dk3ma_d_sub_ok(a, b, &ec)) < epsilon) {
    back = 1;
    if(ec) {
      back = 0;
    }
  }
  return back;
}



double
dk3ma_d_square_ok(double x, int *ec)
{
  double	back;
  back = dk3ma_d_mul_ok(x, x, ec);
  return back;
}



double
dk3ma_restrict_digits(double x, size_t n)
{
  double	back;
  double	newval;
  size_t	i;
  size_t	mult;
  int		ec	= 0;

  back = x;
  mult = 0;
  /*	Multiplications
  */
  for(i = 0; ((0 == ec) && (i < n)); i++) {
    newval = dk3ma_d_mul_ok(back, 10.0, &ec);
    if(0 == ec) {
      back = newval;
      mult++;
    }
  }
  /*	Rounding
  */
  back = dk3ma_rint(back);
  /*	Divisions
  */
  for(i = 0; i < mult; i++) {
    back = back / 10.0;
  }
  return back;
}



double
dk3ma_restrict_digits_ceil(double x, size_t n)
{
  double	back;
  double	newval;
  size_t	i;
  size_t	mult;
  int		ec	= 0;

  back = x;
  mult = 0;
  /*	Multiplications
  */
  for(i = 0; ((0 == ec) && (i < n)); i++) {
    newval = dk3ma_d_mul_ok(back, 10.0, &ec);
    if(0 == ec) {
      back = newval;
      mult++;
    }
  }
  /*	Rounding
  */
  back = ceil(back);
  /*	Divisions
  */
  for(i = 0; i < mult; i++) {
    back = back / 10.0;
  }
  return back;
}



double
dk3ma_restrict_digits_floor(double x, size_t n)
{
  double	back;
  double	newval;
  size_t	i;
  size_t	mult;
  int		ec	= 0;

  back = x;
  mult = 0;
  /*	Multiplications
  */
  for(i = 0; ((0 == ec) && (i < n)); i++) {
    newval = dk3ma_d_mul_ok(back, 10.0, &ec);
    if(0 == ec) {
      back = newval;
      mult++;
    }
  }
  /*	Rounding
  */
  back = floor(back);
  /*	Divisions
  */
  for(i = 0; i < mult; i++) {
    back = back / 10.0;
  }
  return back;
}



#if !DK3_HAVE_COMPILER_CONVERSIONS
static
size_t
dk3ma_i_d_to_sz(double v)
{
  double	tv	= DK3_SIZE_T_FIRST_BIT_AS_DOUBLE;
  size_t	tb	= DK3_SIZE_T_FIRST_BIT;
  size_t	back = 0;
  size_t	i;
  for(i = 0; i < (8 * DK3_SIZEOF_SIZE_T); i++) {
    if(v >= tv) {
      v = v - tv;
      back |= tb;
    }
    tv = tv / 2.0;
    tb = tb / 2U;
  }
  return back;
}
#endif



size_t
dk3ma_d_to_sz_ok(double v, int *ec)
{
  size_t	back = 0;
  if(0.0 <= v) {
    if(DK3_SIZE_T_MAX_AS_DOUBLE >= v) {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (size_t)v;
#else
      back = dk3ma_i_d_to_sz(v);
#endif
    } else {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return back;
}



void
dk3ma_print_double_c8_str_no_sci(FILE *of, char *buffer)
{
  char		*start;		/* Start of string. */
  char		*eptr;		/* Start of exponent substring. */
  char		*ptr;		/* Traverse string. */
  size_t	 lgt;		/* String length. */
  int		 dp;		/* Decimal dot position. */
  int		 exponent;	/* Exponent. */
  int		 i;		/* Traverse the string. */
  

#line 3307 "dk3ma.ctr"
  if((of) && (buffer)) {
    eptr = NULL;
    start = buffer;
    /*
    	Print sign.
    */
    switch(*start) {
      case '-': {
        fputc('-', of);
	start++;
      } break;
      case '+': {
        start++;
      } break;
    }
    /*
    	Find exponent substring and exponent.
    */
    eptr = NULL;
    ptr = start;
    while(*ptr) {
      switch(*ptr) {
        case 'e': case 'E': {
	  eptr = ptr;
	} break;
      }
      ptr++;
    }
    if(eptr) {
      *(eptr++) = '\0';
      if(sscanf(eptr, "%d", &exponent) != 1) {
        exponent = 0;
      }
    } else {
      exponent = 0;
    }
    /*
            Find decimal dot.
    */
    eptr = strchr(start, '.');
    if(eptr) {
      /*
              Keep dot position in dp, squeeze string.
      */
      *eptr = '\0';
      dp = (int)strlen(start);
      *eptr = '.';
      while(*eptr) {
        eptr[0] = eptr[1];
        eptr++;
      }
    } else {
      /*
              Dot position is after the string.
      */
      dp = (int)strlen(start);
    }
    /*
            Correct dot position.
    */
    dp = dp + exponent;
    /*
            Remove leading zeroes (if any).
    */
    while('0' == *start) {
      start++; dp--;
    }
    /*
            Remove trailing zeroes (if any).
    */
    eptr = NULL;
    ptr = start;
    while(*ptr) {
      if('0' == *ptr) {
        if(!(eptr)) { eptr = ptr; }
      } else {
        eptr = NULL;
      }
      ptr++;
    }
    if(eptr) { *eptr = '\0'; }
    lgt = strlen(start);
    if(0 < lgt) {
      if(dp >= (int)lgt) {
        /*
                Decimal dot is at end or after string.
        */
        fputs(start, of);
        /*
                Decimal dot is after the string.
        */
        for(i = 0; i < (dp - (int)lgt); i++) {
          fputc('0', of);
        }
      } else {
        if(dp <= 0) {
          /*
                  Decimal dot is before the string.
          */
          fputc('0', of);
          fputc('.', of);
          while(dp++ < 0) {
            fputc('0', of);
          }
          fputs(start, of);
        } else {
          /*
                  Decimal dot is in the string.
          */
          for(i = 0; i < (int)lgt; i++) {
            if(dp == i) {
              fputc('.', of);
            }
            fputc(start[i], of);
          }
        }
      }
    } else {
      /*
              No non-zero digits in string.
      */
      fputc('0', of);
    }
  } 

#line 3431 "dk3ma.ctr"
}



void
dk3ma_print_double_c8_no_sci(FILE *of, double x)
{
  char		 buffer[64];
  

#line 3440 "dk3ma.ctr"
  if(of) {
    sprintf(buffer, "%lg", x);
    dk3ma_print_double_c8_str_no_sci(of, buffer);
  } 

#line 3444 "dk3ma.ctr"
}



unsigned
dk3ma_u_add_ok(unsigned a, unsigned b, int *ec)
{
  if (ec) {
    if (b > (DK3_U_MAX - a)) {
      *ec = DK3_ERROR_MATH_OVERFLOW;
    }
  }
  return (a + b);
}



unsigned
dk3ma_u_sub_ok(unsigned a, unsigned b, int *ec)
{
  if (ec) {
    if (b > a) {
      *ec = DK3_ERROR_MATH_OVERFLOW;
    }
  }
  return (a - b);
}



unsigned
dk3ma_u_mul_ok(unsigned a, unsigned b, int *ec)
{
  if (ec) {
    if (a) {
      if (b > (DK3_U_MAX / a)) {
        *ec = DK3_ERROR_MATH_OVERFLOW;
      }
    }
  }
  return (a * b);
}



unsigned
dk3ma_u_div_ok(unsigned a, unsigned b, int *ec)
{
  if (b) {
    return (a / b);
  } else {
    if (ec) {
      *ec = DK3_ERROR_MATH_DIVZERO;
    }
    return 0;
  }
}



dk3_um_t
dk3ma_um_add_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_add_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_add_ok(a, b, ec));
#else
  return(dk3ma_ul_add_ok(a, b, ec));
#endif
#endif
}



dk3_um_t
dk3ma_um_sub_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_sub_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_sub_ok(a, b, ec));
#else
  return(dk3ma_ul_sub_ok(a, b, ec));
#endif
#endif
}



dk3_um_t
dk3ma_um_mul_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_mul_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_mul_ok(a, b, ec));
#else
  return(dk3ma_ul_mul_ok(a, b, ec));
#endif
#endif
}



dk3_um_t
dk3ma_um_div_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_div_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_div_ok(a, b, ec));
#else
  return(dk3ma_ul_div_ok(a, b, ec));
#endif
#endif
}



dk3_um_t
dk3ma_um_gcd(dk3_um_t a, dk3_um_t b)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_gcd(a, b));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_gcd(a, b));
#else
  return(dk3ma_ul_gcd(a, b));
#endif
#endif
}



int
dk3ma_um_to_c8_string(char *rb, size_t sz, dk3_um_t va)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_to_c8_string(rb, sz, va)); 
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_to_c8_string(rb, sz, va));
#else
  return(dk3ma_ul_to_c8_string(rb, sz, va));
#endif
#endif
}



int
dk3ma_um_to_string(dkChar *rb, size_t sz, dk3_um_t va)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_to_string(rb, sz, va));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_to_string(rb, sz, va));
#else
  return(dk3ma_ul_to_string(rb, sz, va));
#endif
#endif
}



int
dk3ma_um_to_hex_string(dkChar *rb, size_t sz, dk3_um_t va)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_to_hex_string(rb, sz, va));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_to_hex_string(rb, sz, va));
#else
  return(dk3ma_ul_to_hex_string(rb, sz, va));
#endif
#endif
}



int
dk3ma_c8_string_to_um(dk3_um_t *rp, char const *str)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_c8_string_to_uintmax_t(rp, str));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_c8_string_to_ull(rp, str));
#else
  return(dk3ma_c8_string_to_ul(rp, str));
#endif
#endif
}



int
dk3ma_string_to_um(dk3_um_t *rp, dkChar const *str)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_string_to_uintmax_t(rp, str)); 
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_string_to_ull(rp, str));
#else
  return(dk3ma_string_to_ul(rp, str));
#endif
#endif
}



dk3_um_t
dk3ma_d_to_um_ok(double x, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_d_to_uintmax_t_ok(x, ec)); 
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_d_to_ull_ok(x, ec));
#else
  return(dk3ma_d_to_ul_ok(x, ec));
#endif
#endif
}



double
dk3ma_um_to_d(dk3_um_t x)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_uintmax_t_to_d(x)); 
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ull_to_d(x));
#else
  return(dk3ma_ul_to_d(x));
#endif
#endif
}



dk3_im_t
dk3ma_im_add_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_add_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_add_ok(a, b, ec));
#else
  return(dk3ma_l_add_ok(a, b, ec));
#endif
#endif
}



dk3_im_t
dk3ma_im_sub_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_sub_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_sub_ok(a, b, ec));
#else
  return(dk3ma_l_sub_ok(a, b, ec));
#endif
#endif
}



dk3_im_t
dk3ma_im_mul_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_mul_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_mul_ok(a, b, ec));
#else
  return(dk3ma_l_mul_ok(a, b, ec));
#endif
#endif
}



dk3_im_t
dk3ma_im_div_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_div_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_div_ok(a, b, ec));
#else
  return(dk3ma_l_div_ok(a, b, ec));
#endif
#endif
}



dk3_im_t
dk3ma_im_gcd_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_gcd_ok(a, b, ec));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_gcd_ok(a, b, ec));
#else
  return(dk3ma_l_gcd_ok(a, b, ec));
#endif
#endif
}



int
dk3ma_im_to_c8_string(char *rb, size_t sz, dk3_im_t va)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_to_c8_string(rb, sz, va));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_to_c8_string(rb, sz, va));
#else
  return(dk3ma_l_to_c8_string(rb, sz, va));
#endif
#endif
}



int
dk3ma_im_to_string(dkChar *rb, size_t sz, dk3_im_t va)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_to_string(rb, sz, va));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_to_string(rb, sz, va));
#else
  return(dk3ma_l_to_string(rb, sz, va));
#endif
#endif
}



int
dk3ma_c8_string_to_im(dk3_im_t *rp, char const *str)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_c8_string_to_intmax_t(rp, str));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_c8_string_to_ll(rp, str));
#else
  return(dk3ma_c8_string_to_l(rp, str));
#endif
#endif
}



int
dk3ma_string_to_im(dk3_im_t *rp, dkChar const *str)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_string_to_intmax_t(rp, str));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_string_to_ll(rp, str));
#else
  return(dk3ma_string_to_l(rp, str));
#endif
#endif
}



dk3_im_t
dk3ma_d_to_im_ok(double x, int *ec)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_d_to_intmax_t_ok(x, ec)); 
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_d_to_ll_ok(x, ec));
#else
  return(dk3ma_d_to_l_ok(x, ec));
#endif
#endif
}



double
dk3ma_im_to_d(dk3_im_t x)
{
#if DK3_HAVE_INTMAX_T
  return(dk3ma_intmax_t_to_d(x));
#else
#if DK3_HAVE_LONG_LONG
  return(dk3ma_ll_to_d(x));
#else
  return(dk3ma_l_to_d(x));
#endif
#endif
}



size_t
dk3ma_um_to_sz(dk3_um_t u, int *ec)
{
  size_t	back;
  back = (size_t)u;
#if DK3_SIZEOF_SIZE_T < DK3_SIZEOF_DK3_IM_T
  if (u > ((dk3_um_t)(DK3_SIZE_T_MAX))) {
    back = 0;
    if (ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
#endif
  return back;
}




/* vim: set ai sw=2 : */

