/*
	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-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 dk3ma.c The dk3ma module.
*/


#line 667 "dk3ma.ctr"

#include "dk3all.h"





#line 672 "dk3ma.ctr"


/**	Bit mask for most significant bit in a maximum size integer.
*/
static dk3_im_t const dk3ma_im_msb = DK3_MAX_INT_MSB;



/**	Check whether a maximum size integer is the most negative value.
	@param	i	Number to check.
	@return	1 for true, 0 for false.
*/
static
int
dk3ma_is_im_msb(dk3_im_t i)
{
  int back = 0;
  if(i == dk3ma_im_msb) { back = 1; }
  return back;
}




/**	Bit mask for most significant bit in an unsigned long value.
*/
static long const dk3ma_l_msb = (long)0x80000000L;



/**	Check whether a long is the most negative value.
	@param	i	Number to check.
	@return	1 for true, 0 for false.
*/
static
int
dk3ma_is_l_msb(long i)
{
  int back = 0;
  if(i == dk3ma_l_msb) { back = 1; }
  return back;
}



dk3_um_t
dk3ma_mu_add_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = a + b;
  if((DK3_MAX_UINTMAX - a) < b) {
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return back;
}


dk3_um_t
dk3ma_mu_sub_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = a - b;
  if(b > a) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
  return back;
}

dk3_um_t
dk3ma_mu_mul_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = a * b;
  if(a) {
    if(b > (DK3_MAX_UINTMAX / a)) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
  }
  return back;
}

dk3_um_t
dk3ma_mu_div_ok(dk3_um_t a, dk3_um_t b, int *ec)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  if(b) {
    back = a / b;
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
  }
  return back;
}

dk3_um_t
dk3ma_mu_add(dk3_um_t a, dk3_um_t b)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = dk3ma_mu_add_ok(a, b, NULL);
  return back;
}


dk3_um_t
dk3ma_mu_sub(dk3_um_t a, dk3_um_t b)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = dk3ma_mu_sub_ok(a, b, NULL);
  return back;
}

dk3_um_t
dk3ma_mu_mul(dk3_um_t a, dk3_um_t b)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = dk3ma_mu_mul_ok(a, b, NULL);
  return back;
}

dk3_um_t
dk3ma_mu_div(dk3_um_t a, dk3_um_t b)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  back = dk3ma_mu_div_ok(a, b, NULL);
  return back;
}


/* Unsigned long */

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

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

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

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

unsigned long
dk3ma_ul_add(unsigned long a, unsigned long b)
{
  unsigned long back = 0UL;
  back = dk3ma_ul_add_ok(a, b, NULL);
  return back;
}

unsigned long
dk3ma_ul_sub(unsigned long a, unsigned long b)
{
  unsigned long back = 0UL;
  back = dk3ma_ul_sub_ok(a, b, NULL);
  return back;
}

unsigned long
dk3ma_ul_mul(unsigned long a, unsigned long b)
{
  unsigned long back = 0UL;
  back = dk3ma_ul_mul_ok(a, b, NULL);
  return back;
}

unsigned long
dk3ma_ul_div(unsigned long a, unsigned long b)
{
  unsigned long back = 0UL;
  back = dk3ma_ul_div_ok(a, b, NULL);
  return back;
}



/* Max signed */

dk3_im_t
dk3ma_mi_abs(dk3_im_t a)
{
  dk3_im_t back;
  if(a >= DK3_MAX_INT_0) { back = a; }
  else { back = DK3_MAX_INT_0 - a; }
  return back;
}


dk3_im_t
dk3ma_mi_add_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
  dk3_im_t back = DK3_MAX_INT_0;
  if(a >= DK3_MAX_INT_0) {
    if(b >= DK3_MAX_INT_0) {
      back = a + b;
      if((DK3_MAX_INTMAX - a) < b) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
      back = a + b;
    }
  } else {
    if(b >= DK3_MAX_INT_0) {
      back = a + b;
    } else {
      if(dk3ma_is_im_msb(a)) {
        back = a + b;
	if(b) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
      } else {
        if(dk3ma_is_im_msb(b)) {
	  back = a + b;
	  if(a) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
	} else {
          back = DK3_MAX_INT_0
	  	 - dk3ma_mi_add_ok(dk3ma_mi_abs(a),dk3ma_mi_abs(b),ec);
	}
      }
    }
  }
  return back;
}

dk3_im_t
dk3ma_mi_sub_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
  dk3_im_t back = DK3_MAX_INT_0;
  if(a >= DK3_MAX_INT_0) {
    if(b >= DK3_MAX_INT_0) {
      back = a - b;
    } else {
      if(dk3ma_is_im_msb(b)) {
        back = a - b;
	if(a) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
      } else {
        back = dk3ma_mi_add_ok(a, dk3ma_mi_abs(b), ec);
      }
    }
  } else {
    if(b >= DK3_MAX_INT_0) {
      if(dk3ma_is_im_msb(a)) {
        back = a - b;
	if(b) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
      } else {
        back = DK3_MAX_INT_0 - dk3ma_mi_add_ok(b, dk3ma_mi_abs(a), ec);
      }
    } else {
      back = a - b;
    }
  }
  return back;
}

dk3_im_t
dk3ma_mi_mul_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
  dk3_im_t back = DK3_MAX_INT_0;
  if(a >= DK3_MAX_INT_0) {
    if(b >= DK3_MAX_INT_0) {
      back = a * b;
      if(a) {
        if((DK3_MAX_INTMAX / a) < b) {
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    } else {
      if(dk3ma_is_im_msb(b)) {
        back = a * b;
	if((a > DK3_MAX_INT_1) || (a < DK3_MAX_INT_MINUS_1)) {
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      } else {
        back = DK3_MAX_INT_0 - dk3ma_mi_mul_ok(a, dk3ma_mi_abs(b), ec);
      }
    }
  } else {
    if(b >= DK3_MAX_INT_0) {
      if(dk3ma_is_im_msb(a)) {
        back = a * b;
	if((b > DK3_MAX_INT_1) || (b < DK3_MAX_INT_MINUS_1)) {
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      } else {
        back = DK3_MAX_INT_0 - dk3ma_mi_mul_ok(dk3ma_mi_abs(a), b, ec);
      }
    } else {
      if(dk3ma_is_im_msb(a)) {
        if(dk3ma_is_im_msb(b)) {
	  back = a * b;
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	} else {
	  back = a * b;
	  if((b > DK3_MAX_INT_1) || (b < DK3_MAX_INT_MINUS_1)) {
	    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	  }
	}
      } else {
        if(dk3ma_is_im_msb(b)) {
	  back = a * b;
	  if((a > DK3_MAX_INT_1) || (a < DK3_MAX_INT_MINUS_1)) {
	    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	  }
	} else {
	  back = dk3ma_mi_mul_ok(dk3ma_mi_abs(a), dk3ma_mi_abs(b), ec);
	}
      }
    }
  }
  return back;
}

dk3_im_t
dk3ma_mi_div_ok(dk3_im_t a, dk3_im_t b, int *ec)
{
  dk3_im_t back = DK3_MAX_INT_0;
  if(b) {
    back = a / b;
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
  }
  return back;
}

dk3_im_t
dk3ma_mi_add(dk3_im_t a, dk3_im_t b)
{
  dk3_im_t back = DK3_MAX_INT_0;
  back = dk3ma_mi_add_ok(a, b, NULL);
  return back;
}

dk3_im_t
dk3ma_mi_sub(dk3_im_t a, dk3_im_t b)
{
  dk3_im_t back = DK3_MAX_INT_0;
  back = dk3ma_mi_sub_ok(a, b, NULL);
  return back;
}

dk3_im_t
dk3ma_mi_mul(dk3_im_t a, dk3_im_t b)
{
  dk3_im_t back = DK3_MAX_INT_0;
  back = dk3ma_mi_mul_ok(a, b, NULL);
  return back;
}

dk3_im_t
dk3ma_mi_div(dk3_im_t a, dk3_im_t b)
{
  dk3_im_t back = DK3_MAX_INT_0;
  back = dk3ma_mi_div_ok(a, b, NULL);
  return back;
}

/* Long */

#if DK3_HAVE_LABS
/**	Use implementation from runtime/math library. */
#define LABS(x) labs(x)
#else
/**	Fallback implementation of labs() for systems without.
	@param	l	Value to obtain absolute value for.
	@return	Absolute value.
*/
static
long
dk3ma_fallback_labs(long l)
{
  long back;
  if(l >= 0UL) back = l;
  else back = 0L - l;
  return back;
}
/**	Use fallback implementation. */
#define LABS(x) dk3ma_fallback_labs(x)
#endif

long
dk3ma_l_add_ok(long a, long b, int *ec)
{
  long back = 0L;
  

#line 1078 "dk3ma.ctr"
  if(a >= 0L) {
    if(b >= 0L) {	

#line 1080 "dk3ma.ctr"
      back = a + b;
      if((0x7FFFFFFFL - a) < b) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {		

#line 1085 "dk3ma.ctr"
      back = a + b;
    }
  } else {
    if(b >= 0L) {	

#line 1089 "dk3ma.ctr"
      back = a + b;
    } else {		

#line 1091 "dk3ma.ctr"
      if(dk3ma_is_l_msb(a)) {
        back = a + b;
	if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      } else {
        if(dk3ma_is_l_msb(b)) {
	  back = a + b;
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	} else {
	  back = 0L - dk3ma_l_add_ok(LABS(a), LABS(b), ec);
	}
      }
    }
  } 

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

long
dk3ma_l_sub_ok(long a, long b, int *ec)
{
  long back = 0L;
  if(a >= 0L) {
    if(b >= 0L) {
      back = a - b;
    } else {
      if(dk3ma_is_l_msb(b)) {
        back = a - b;
	if(a) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
      } else {
        back = dk3ma_l_add_ok(a, LABS(b), ec);
      }
    }
  } else {
    if(b >= 0L) {
      if(dk3ma_is_l_msb(a)) {
        back = a - b;
	if(b) { if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; } }
      } else {
        back = 0L - dk3ma_l_add_ok(b, LABS(a), ec);
      }
    } else {
      back = a - b;
    }
  }
  return back;
}

long
dk3ma_l_mul_ok(long a, long b, int *ec)
{
  long back = 0L;
  if(a >= 0L) {
    if(b >= 0L) {
      back = a * b;
      if(a) {
        if((0x7FFFFFFF / a) < b) {
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    } else {
      if(dk3ma_is_l_msb(b)) {
        back = a * b;
	if((a > 1L) || (a < -1L)) if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      } else {
        back = 0L - dk3ma_l_mul_ok(a, LABS(b), ec);
      }
    }
  } else {
    if(b >= 0L) {
      if(dk3ma_is_l_msb(a)) {
        back = a * b;
	if((b > 1L) || (b < -1L)) if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      } else {
        back = 0L - dk3ma_l_mul_ok(LABS(a), b, ec);
      }
    } else {
      if(dk3ma_is_l_msb(a)) {
        back = a * b;
	if((b > 1L) || (b < -1L)) if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      } else {
        if(dk3ma_is_l_msb(b)) {
	  back = a * b;
	  if((a > 1L) || (a < -1L)) if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	} else {
	  back = dk3ma_l_mul_ok(LABS(a), LABS(b), ec);
	}
      }
    }
  }
  return back;
}

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


long
dk3ma_l_add(long a, long b)
{
  long back = 0L;
  back = dk3ma_l_add_ok(a, b, NULL);
  return back;
}

long
dk3ma_l_sub(long a, long b)
{
  long back = 0L;
  back = dk3ma_l_sub_ok(a, b, NULL);
  return back;
}

long
dk3ma_l_mul(long a, long b)
{
  long back = 0L;
  back = dk3ma_l_mul_ok(a, b, NULL);
  return back;
}

long
dk3ma_l_div(long a, long b)
{
  long back = 0L;
  back = dk3ma_l_div_ok(a, b, NULL);
  return back;
}




/* double */

#if DK3_HAVE_FABS
/**	Use fabs() implementation from runtime/math library.	*/
#define FABS(x) fabs(x)
#else
/**	Fallback implementation of fabs().
	@param	x	Argument.
	@return	Absolute value.
*/
static
double
dk3ma_fallback_fabs(double x)
{
  double back;
  if(x >= 0.0) back = x;
  else back = 0.0 - x;
  return back;
}
/**	Use fallback implementation of fabs(). */
#define FABS(x) dk3ma_fallback_fabs(x)
#endif


double
dk3ma_d_add_ok(double a, double b, int *ec)
{
  double back = 0.0;
  if(a >= 0.0) {
    if(b >= 0.0) {
      back = a + b;
      if((DK3_MAX_DOUBLE - a) < b) {
        if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
      }
    } else {
      back = a + b;
    }
  } else {
    if(b >= 0.0) {
      back = a + b;
    } else {
      back = 0.0 - dk3ma_d_add_ok(FABS(a), FABS(b), ec);
    }
  }
  return back;
}

double
dk3ma_d_sub_ok(double a, double b, int *ec)
{
  double back = 0.0;
  if(a >= 0.0) {
    if(b >= 0.0) {
      back = a - b;
    } else {
      back = dk3ma_d_add_ok(a, FABS(b), ec);
    }
  } else {
    if(b >= 0.0) {
      back = 0.0 - dk3ma_d_add_ok(b, FABS(a), ec);
    } else {
      back = a - b;
    }
  }
  return back;
}

double
dk3ma_d_mul_ok(double a, double b, int *ec)
{
  double back = 0.0;
  if(a >= 0.0) {
    if(b >= 0.0) {
      back = a * b;
      if(a >= 1.0) {
        if((DK3_MAX_DOUBLE / a) < b) {
	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
	}
      }
    } else {
      back = 0.0 - dk3ma_d_mul_ok(a, FABS(b), ec);
    }
  } else {
    if(b >= 0.0) {
      back = 0.0 - dk3ma_d_mul_ok(b, FABS(a), ec);
    } else {
      back = dk3ma_d_mul_ok(FABS(a), FABS(b), ec);
    }
  }
  return back;
}

double
dk3ma_d_div_ok(double a, double b, int *ec)
{
  double back = 0.0;
  if(a >= 0.0) {
    if(b >= 0.0) {
      if(b >= 1.0) {
        back = a / b;
      } else {
        if((b * DK3_MAX_DOUBLE) > a) {
	  back = a / b;
	} else {
	  if(ec) { *ec = DK3_ERROR_MATH_DIVZERO; }
	}
      }
    } else {
      back = 0.0 - dk3ma_d_div_ok(a, FABS(b), ec);
    }
  } else {
    if(b >= 0.0) {
      back = 0.0 - dk3ma_d_div_ok(FABS(a), b, ec);
    } else {
      back = dk3ma_d_div_ok(FABS(a), FABS(b), ec);
    }
  }
  return back;
}

double
dk3ma_d_add(double a, double b)
{
  double back = 0.0;
  back = dk3ma_d_add_ok(a, b, NULL);
  return back;
}

double
dk3ma_d_sub(double a, double b)
{
  double back = 0.0;
  back = dk3ma_d_sub_ok(a, b, NULL);
  return back;
}

double
dk3ma_d_mul(double a, double b)
{
  double back = 0.0;
  back = dk3ma_d_mul_ok(a, b, NULL);
  return back;
}

double
dk3ma_d_div(double a, double b)
{
  double back = 0.0;
  back = dk3ma_d_div_ok(a, b, NULL);
  return back;
}


int
dk3ma_uintmax_to_c8_string(char *rb, size_t sz, dk3_um_t va)
{
  int back = 0;
  char buffer[128];	/* Temporary 8-bit character buffer for result. */
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64u", va);
#else
#if DK3_HAVE_LONG_LONG
    sprintf(buffer, "%llu", va);
#else
    sprintf(buffer, "%lu", (unsigned long)va);
#endif
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_uintmax_to_string(dkChar *rb, size_t sz, dk3_um_t va)
{
  int back = 0;
  char buffer[128];	/* Temporary 8-bit character buffer for result. */
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64u", va);
#else
#if DK3_HAVE_LONG_LONG
    sprintf(buffer, "%llu", va);
#else
    sprintf(buffer, "%lu", (unsigned long)va);
#endif
#endif
    if(dk3str_c8_len(buffer) < sz) {
      back = dk3str_cnv_c8_to_str_app(rb, sz, buffer, NULL);
    }
  }
  return back;
}



int
dk3ma_uintmax_to_hex_string(dkChar *rb, size_t sz, dk3_um_t va)
{
  int back = 0;
  char buffer[128];	/* Temporary 8-bit character buffer for result. */
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%016I64x", va);
#else
#if DK3_HAVE_LONG_LONG
    sprintf(buffer, "%016llx", va);
#else
    sprintf(buffer, "%08lx", (unsigned long)va);
#endif
#endif
    if(dk3str_c8_len(buffer) < sz) {
      back = dk3str_cnv_c8_to_str_app(rb, sz, buffer, NULL);
    }
  }
  return back;
}



int
dk3ma_uintmax_from_c8_string(dk3_um_t *va, char const *s)
{
  int		back = 0;
  char const	*ptr;
  if((va) && (s)) {
    ptr = dk3str_c8_start(s, NULL);
    if(ptr) {
      switch(*ptr) {
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        {
#if DK3_ON_WINDOWS
          if(sscanf(s, "%I64u", va) == 1) {
            back = 1;
          }
#else
#if DK3_HAVE_LONG_LONG
          if(sscanf(s, "%llu", va) == 1) {
            back = 1;
          }
#else
          unsigned long ul;
          if(sscanf(s, "%lu", &ul) == 1) {
            *va = (dk3_um_t)ul; back = 1;
          }
#endif
#endif
        } break;
      }
    }
  }
  return back;
}



int
dk3ma_uintmax_from_string(dk3_um_t *va, dkChar const *s)
{
  int back = 0;
  char buffer[1024];	/* Temporary 8-bit character buffer for conversion. */
  if((va) && (s)) {
    dk3str_string_to_c8_simple_app(buffer, sizeof(buffer), s, NULL);
    back = dk3ma_uintmax_from_c8_string(va, buffer);
  }
  return back;
}



int
dk3ma_intmax_to_c8_string(char *rb, size_t sz, dk3_im_t va)
{
  int back = 0;
  char buffer[128];	/* Temporary 8-bit character buffer for conversion. */
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64d", va);
#else
#if DK3_HAVE_LONG_LONG
    sprintf(buffer, "%lld", va);
#else
    sprintf(buffer, "%ld", (unsigned long)va);
#endif
#endif
    if(dk3str_c8_len(buffer) < sz) {
      dk3str_c8_cpy(rb, buffer);
      back = 1;
    }
  }
  return back;
}



int
dk3ma_intmax_to_string(dkChar *rb, size_t sz, dk3_im_t va)
{
  int back = 0;
  char buffer[128];	/* Temporary 8-bit character buffer for conversion. */
  if((rb) && (sz)) {
#if DK3_ON_WINDOWS
    sprintf(buffer, "%I64d", va);
#else
#if DK3_HAVE_LONG_LONG
    sprintf(buffer, "%lld", va);
#else
    sprintf(buffer, "%ld", (unsigned long)va);
#endif
#endif
    if(dk3str_c8_len(buffer) < sz) {
      back = dk3str_cnv_c8_to_str_app(rb, sz, buffer, NULL);
    }
  }
  return back;
}



int
dk3ma_intmax_from_c8_string(dk3_im_t *va, char const *s)
{
  int		back = 0;
  char const	*ptr;
  if((va) && (s)) {
    ptr = dk3str_c8_start(s, NULL);
    if(ptr) {
      switch(*ptr) {
        case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
	case '-':
	{
#if DK3_ON_WINDOWS
          if(sscanf(s, "%I64d", va) == 1) {
            back = 1;
          }
#else
#if DK3_HAVE_LONG_LONG
          if(sscanf(s, "%lld", va) == 1) {
            back = 1;
          }
#else
          unsigned long ul;
          if(sscanf(s, "%ld", &ul) == 1) {
            *va = (dk3_im_t)ul; back = 1;
          }
#endif
#endif
	} break;
      }
    }
  }
  return back;
}



int
dk3ma_intmax_from_string(dk3_im_t *va, dkChar const *s)
{
  int back = 0;
  char buffer[1024];	/* Temporary 8-bit character buffer for conversion. */
  if((va) && (s)) {
    dk3str_string_to_c8_simple_app(buffer, sizeof(buffer), s, NULL);
    back = dk3ma_intmax_from_c8_string(va, buffer);
  }
  return back;
}



dk3_um_t
dk3ma_mu_gcd(dk3_um_t u1, dk3_um_t u2)
{
  dk3_um_t a	= DK3_MAX_UINT_0;
  dk3_um_t b	= DK3_MAX_UINT_0;
  dk3_um_t h	= DK3_MAX_UINT_0;
  a = u1; b = u2;
  while(b > DK3_MAX_UINT_0) {
    h = a % b;
    a = b;
    b = h;
  }
  if(a == DK3_MAX_UINT_0) a = DK3_MAX_UINT_1;
  return a;
}

dk3_im_t
dk3ma_mi_gcd(dk3_im_t u1, dk3_im_t u2)
{
  dk3_im_t	a	= DK3_MAX_INT_0;
  dk3_im_t	b	= DK3_MAX_INT_0;
  dk3_im_t	h	= DK3_MAX_INT_0;
  if(u1 >= DK3_MAX_INT_0) {
    if(u2 >= DK3_MAX_INT_0) {
      a = u1; b = u2;
      while(b > DK3_MAX_INT_0) {
        h = a % b;
	a = b;
	b = h;
      }
    } else {
      a = dk3ma_mi_gcd(u1, dk3ma_mi_abs(u2));
    }
  } else {
    if(u2 >= DK3_MAX_INT_0) {
      a = dk3ma_mi_gcd(dk3ma_mi_abs(u1), u2);
    } else {
      a = dk3ma_mi_gcd(dk3ma_mi_abs(u1), dk3ma_mi_abs(u2));
    }
  }
  if(a == DK3_MAX_INT_0) a = DK3_MAX_INT_1;
  return a;
}


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


long
dk3ma_l_gcd(long u1, long u2)
{
  long a = 0L;
  long b = 0L;
  long h = 0L;
  if(u1 >= 0L) {
    if(u2 >= 0L) {
      a = u1; b = u2;
      while(b > 0L) {
        h = a % b;
	a = b;
	b = h;
      }
    } else {
      a = dk3ma_l_gcd(u1, LABS(u2));
    }
  } else {
    if(u2 >= 0L) {
      a = dk3ma_l_gcd(LABS(u1), u2);
    } else {
      a = dk3ma_l_gcd(LABS(u1), LABS(u2));
    }
  }
  if(a == 0L) a = 1L;
  return a;
}



double
dk3ma_rint(double x)
{
  double back;
#if DK3_HAVE_RINT
  back = rint(x);
#else
  if(x < 0.0) {
    back = 0.0 - dk3ma_rint(0.0 - x);
  } else {
#if DK3_HAVE_FLOOR
    back = floor(x + 0.5);
#else
#error "Not supported!"
#endif
  }
#endif
  return back;
}


#if !DK3_HAVE_COMPILER_CONVERSIONS

/* untested */
/**	Convert double to long.
	@param	x	Double to convert.
	@return	Conversion result.
*/
static
unsigned long
my_d_to_ul(double x)
{
  unsigned long back = 0UL;
  unsigned long testbit = 0UL;	/* Current bit to test. */
  double	v = 0.0;	/* Remaining value. */
  double	testval = 0.0;	/* Test value. */
  v = x;
  testbit = DK3_UL_FIRST_BIT;
  testval = DK3_UL_FIRST_BIT_AS_DOUBLE;
  while(testbit) {
    if(v >= testval) {
      v = v - testval;
      back |= testbit;
    }
    testbit = testbit / 2UL; testval = testval / 2.0;
  }
  return back;
}



/* untested */
/**	Convert double to long.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
long
my_d_to_l(double x)
{
  long		back = 0L;
  long		testbit = 0L;	/* Bit to test/add. */
  double	v = 0.0;	/* Remaining value. */
  double	testval = 0.0;	/* Test value. */
  v = x;
  testbit = DK3_L_FIRST_BIT; testval = DK3_L_FIRST_BIT_AS_DOUBLE;
  while(testbit) {
    if(v >= testval) {
      v = v - testval;
      back |= testbit;
    }
    testbit = testbit / 2L; testval = testval / 2.0;
  }
  return back;
}



/* untested */
/**	Convert double to maximum length unsigned.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
dk3_um_t
my_d_to_mu(double x)
{
  dk3_um_t	back = DK3_MAX_UINT_0;
  dk3_um_t	testbit = DK3_MAX_UINT_0;	/* Bit to test/add. */
  double	v = 0.0;			/* Remaining value. */
  double	testval = 0.0;			/* Test value. */
  v = x;
  testbit = DK3_MAX_UINT_FIRST_BIT;
  testval = DK3_MAX_UINT_FIRST_BIT_AS_DOUBLE;
  while(testbit) {
    if(v >= testval) {
      v = v - testval;
      back |= testbit;
    }
    testbit = testbit / DK3_MAX_UINT_2; testval = testval / 2.0;
  }
  return back;
}



/* untested */
/**	Convert double to maximum length integer.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
dk3_im_t
my_d_to_mi(double x)
{
  dk3_im_t	back = DK3_MAX_INT_0;
  dk3_im_t	testbit = DK3_MAX_INT_0;	/* Bit to test/add. */
  double	v = 0.0;			/* Remaining value. */
  double	testval = 0.0;			/* Test value. */
  v = x;
  testbit = DK3_MAX_INT_FIRST_BIT;
  testval = DK3_MAX_INT_FIRST_BIT_AS_DOUBLE;
  while(testbit) {
    if(v >=  testval) {
      v = v - testval;
      back |= testbit;
    }
    testbit = testbit / DK3_MAX_INT_2; testval = testval / 2.0;
  }
  return  back;
}



/* untested */
/**	Convert maximum length unsigned to double.
	@param	x	Value to convert.
	@return Conversion result.
*/
static
double
my_mu_to_d(dk3_um_t x)
{
  double back = 0.0;
  dk3_um_t testbit = DK3_MAX_UINT_FIRST_BIT;		/* Bit to test/add. */
  double testval = DK3_MAX_UINT_FIRST_BIT_AS_DOUBLE;	/* Test value. */
  while(testbit) {
    if(x & testbit) {
      back += testval;
    }
    testbit = testbit / DK3_MAX_UINT_2; testval = testval / 2.0;
  }
  return back;
}



/* untested */
/**	Convert maximum length integer to double.
	@param	x	Value to convert.
	@return Conversion result.
*/
static
double
my_mi_to_d(dk3_im_t x)
{
  double back = 0.0;
  dk3_im_t testbit = DK3_MAX_INT_FIRST_BIT;		/* Bit to test/add. */
  double testval = DK3_MAX_UINT_FIRST_BIT_AS_DOUBLE;	/* Test value. */
  if(x >= DK3_MAX_INT_0) {
    while(testbit) {
      if(x & testbit) {
        back += testval;
      }
      testbit = testbit / DK3_MAX_INT_2; testval = testval / 2.0;
    }
  } else {
    back = 0.0 - my_mi_to_d(DK3_MAX_INT_0 - x);
  }
  return back;
}



/* untested */
/**	Convert unsigned long to double.
	@param	x	Value to convert.
	@return Conversion result.
*/
static
double
my_ul_to_d(unsigned long x)
{
  double back = 0.0;
  unsigned long testbit = DK3_UL_FIRST_BIT;	/* Bit to test/add. */
  double testval = 2147483647.0;		/* Test value. */
  while(testbit) {
    if(x & testbit) {
      back += testval;
    }
    testbit = testbit / 2UL; testval = testval / 2.0;
  }
  return back;
}



/* untested */
/**	Convert long to double.
	@param	x	Value to convert.
	@return Conversion result.
*/
static
double
my_l_to_d(long x)
{
  double back = 0.0;
  long testbit = DK3_L_FIRST_BIT;		/* Bit to test/add. */
  double testval = DK3_L_FIRST_BIT_AS_DOUBLE;	/* Test value. */
  if(x >= 0L) {
    while(testbit) {
      if(x & testbit) {
        back += testval;
      }
      testbit = testbit / 2L; testval = testval / 2.0;
    }
  } else {
    back = 0.0 - my_l_to_d(0L - x);
  }
  return back;
}


#endif



/* untested */
unsigned long
dk3ma_d_to_ul_ok(double x, int *ec)
{
  unsigned long back = 0UL;
  double y = 0.0;		/* Rounded value. */
  if(x >= 0.0) {
    y = dk3ma_rint(x);
    if(y > DK3_UL_MAX_AS_DOUBLE) {
      if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (unsigned long)y;
#else
      back = my_d_to_ul(y);
#endif
    }
  } else {
    if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
  }
  return back;
}



/* untested */
long
dk3ma_d_to_l_ok(double x, int *ec)
{
  double y = 0.0;	/* Rounded value. */
  long back = 0L;
  y = dk3ma_rint(x);
  if(y >= 0.0) {
    if(y > DK3_L_MAX_AS_DOUBLE) {
      if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (long)y;
#else
      back = my_d_to_l(y);
#endif
    }
  } else {
    back = 0L - dk3ma_d_to_l_ok(0.0 - x, ec);
  }
  return back;
}



/* untested */
dk3_um_t
dk3ma_d_to_mu_ok(double x, int *ec)
{
  dk3_um_t back = DK3_MAX_UINT_0;
  double y = 0.0;			/* Rounded value. */
  if(x >= 0.0) {
    y = dk3ma_rint(x);
    if(y > DK3_MAX_UINT_AS_DOUBLE) {
      if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (dk3_um_t)y;
#else
      back = my_d_to_mu(y);
#endif
    }
  } else {
    if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
  }
  return back;
}



/* untested */
dk3_im_t
dk3ma_d_to_mi_ok(double x, int *ec)
{
  dk3_im_t back = DK3_MAX_INT_0;
  double y = 0.0;			/* Rounded value. */
  if(x >= 0.0) {
    y = dk3ma_rint(x);
    if(y > DK3_MAX_INT_AS_DOUBLE) {
      if(ec) *ec = DK3_ERROR_MATH_OVERFLOW;
    } else {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (dk3_im_t)y;
#else
      back = my_d_to_mi(y);
#endif
    }
  } else {
    back = DK3_MAX_INT_0 - dk3ma_d_to_mi_ok(0.0 - x, ec);
  }
  return back;
}



double
dk3ma_mu_to_d(dk3_um_t x)
{
  double back;
#if DK3_HAVE_COMPILER_CONVERSIONS
    back = (double)x;
#else
    back = my_mu_to_d(x);
#endif
  return back;
}


double
dk3ma_mi_to_d(dk3_im_t x)
{
  double back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  back = my_mi_to_d(x);
#endif
  return back;
}


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


double
dk3ma_l_to_d(long x)
{
  double back;
#if DK3_HAVE_COMPILER_CONVERSIONS
  back = (double)x;
#else
  back = my_l_to_d(x);
#endif
  return back;
}


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 2125 "dk3ma.ctr"
  back = atan2(y, x);	

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

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

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

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

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

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

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

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

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

#line 2150 "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;
}



size_t
dk3ma_d_to_size_ok(double v, int *ec)
{
  size_t	 back = 0;
  if(0 <= v) {
    if((double)(DK3_SIZE_T_MAX) > v) {
#if DK3_HAVE_COMPILER_CONVERSIONS
      back = (size_t)v;
#else
      back = (size_t)dk3ma_d_to_ul_ok(v, ec);
#endif
    } else {
      if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
    }
  } else {
    if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
  }
  return back;
}



#if VERSION_BEFORE_20130105
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 2315 "dk3ma.ctr"
  if((of) && (buffer)) {
    eptr = NULL;
    start = buffer;
    /*
    	Print sign.
    */
    switch(*start) {
      case '-': {
        fputc('-', of);
	start++;
      } break;
      case '+': {
        start++;
      } break;
    }
    /*
    	Find exponent substring.
    */
    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) {
        if(0 == exponent) {
	  /*
	  	Exponent is 0, print string as is.
	  */
	  fputs(start, of);
	} else {
	  /*
	  	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);
	  }
	}
      } else {
        /*
		Failed to read exponent substring. Print string as is.
	*/
        fputs(start, of);
      }
    } else {
      /*
      	No exponent substring, print string as is.
      */
      fputs(start, of);
    }
  } 

#line 2453 "dk3ma.ctr"
}
#endif



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 2469 "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 2593 "dk3ma.ctr"
}



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

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

#line 2606 "dk3ma.ctr"
}



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

