/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+
#include <assert.h>
+#include <stdio.h>
+
+#include "basearith.h"
#include "constants.h"
#include "typearith.h"
-#include "basearith.h"
/*********************************************************************/
/* D2: loop */
for (j=m; j != MPD_SIZE_MAX; j--) {
+ assert(2 <= j+n && j+n <= nplusm); /* annotation for scan-build */
/* D3: calculate qhat and rhat */
rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
return rem;
}
-
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef BASEARITH_H
-#define BASEARITH_H
+#ifndef LIBMPDEC_BASEARITH_H_
+#define LIBMPDEC_BASEARITH_H_
#include "mpdecimal.h"
-#include <stdio.h>
#include "typearith.h"
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif /* BASEARITH_H */
-
-
-
+#endif /* LIBMPDEC_BASEARITH_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef BITS_H
-#define BITS_H
+#ifndef LIBMPDEC_BITS_H_
+#define LIBMPDEC_BITS_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Check if n is a power of 2. */
#endif /* BSR/BSF */
-#endif /* BITS_H */
-
-
-
+#endif /* LIBMPDEC_BITS_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
#include "constants.h"
"CLAMP_DEFAULT",
"CLAMP_IEEE_754"
};
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef CONSTANTS_H
-#define CONSTANTS_H
+#ifndef LIBMPDEC_CONSTANTS_H_
+#define LIBMPDEC_CONSTANTS_H_
#include "mpdecimal.h"
+#include <stdint.h>
+
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif /* CONSTANTS_H */
-
-
-
+#endif /* LIBMPDEC_CONSTANTS_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
+
+#include <signal.h>
#include <stdio.h>
#include <string.h>
-#include <signal.h>
void
-mpd_dflt_traphandler(mpd_context_t *ctx UNUSED)
+mpd_dflt_traphandler(mpd_context_t *ctx)
{
+ (void)ctx;
raise(SIGFPE);
}
mpd_traphandler(ctx);
}
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
#include "bits.h"
#include "constants.h"
+#include "convolute.h"
#include "fnt.h"
#include "fourstep.h"
#include "numbertheory.h"
#include "sixstep.h"
#include "umodarith.h"
-#include "convolute.h"
/* Bignum: Fast convolution using the Number Theoretic Transform. Used for
return 1;
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef CONVOLUTE_H
-#define CONVOLUTE_H
+#ifndef LIBMPDEC_CONVOLUTE_H_
+#define LIBMPDEC_CONVOLUTE_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_CONVOLUTE_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
+
#include <assert.h>
+
+#include "constants.h"
+#include "crt.h"
#include "numbertheory.h"
#include "umodarith.h"
-#include "crt.h"
+#include "typearith.h"
/* Bignum: Chinese Remainder Theorem, extends the maximum transform length. */
assert(carry[0] == 0 && carry[1] == 0 && carry[2] == 0);
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef CRT_H
-#define CRT_H
+#ifndef LIBMPDEC_CRT_H_
+#define LIBMPDEC_CRT_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_CRT_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
+
#include <assert.h>
+
#include "bits.h"
+#include "constants.h"
+#include "difradix2.h"
#include "numbertheory.h"
#include "umodarith.h"
-#include "difradix2.h"
/* Bignum: The actual transform routine (decimation in frequency). */
bitreverse_permute(a, n);
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef DIF_RADIX2_H
-#define DIF_RADIX2_H
+#ifndef LIBMPDEC_DIFRADIX2_H_
+#define LIBMPDEC_DIFRADIX2_H_
#include "mpdecimal.h"
-#include <stdio.h>
#include "numbertheory.h"
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_DIFRADIX2_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
-#include <stdlib.h>
+
#include <assert.h>
+#include <stdio.h>
+
#include "bits.h"
#include "difradix2.h"
-#include "numbertheory.h"
#include "fnt.h"
+#include "numbertheory.h"
/* Bignum: Fast transform for medium-sized coefficients. */
mpd_free(tparams);
return 1;
}
-
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef FNT_H
-#define FNT_H
+#ifndef LIBMPDEC_FNT_H_
+#define LIBMPDEC_FNT_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
-
+#endif /* LIBMPDEC_FNT_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
+
#include <assert.h>
+
+#include "constants.h"
+#include "fourstep.h"
#include "numbertheory.h"
#include "sixstep.h"
-#include "transpose.h"
#include "umodarith.h"
-#include "fourstep.h"
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix. */
+ #include "transpose.h"
transpose_3xpow2(a, R, C);
#endif
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix, producing an R*C matrix. */
+ #include "transpose.h"
transpose_3xpow2(a, C, R);
#endif
return 1;
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef FOUR_STEP_H
-#define FOUR_STEP_H
+#ifndef LIBMPDEC_FOURSTEP_H_
+#define LIBMPDEC_FOURSTEP_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_FOURSTEP_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
+
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
+#include <limits.h>
#include <locale.h>
-#include "bits.h"
-#include "constants.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "typearith.h"
#include "io.h"
}
}
- digits = end - coeff;
+ digits = end - coeff;
if (dpoint) {
size_t fracdigits = end-dpoint-1;
if (dpoint > coeff) digits--;
mpd_seterror(dec, MPD_Conversion_syntax, status);
}
+/* convert a character string to a decimal, use a maxcontext for conversion */
+void
+mpd_qset_string_exact(mpd_t *dec, const char *s, uint32_t *status)
+{
+ mpd_context_t maxcontext;
+
+ mpd_maxcontext(&maxcontext);
+ mpd_qset_string(dec, s, &maxcontext, status);
+
+ if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
+ /* we want exact results */
+ mpd_seterror(dec, MPD_Invalid_operation, status);
+ }
+ *status &= MPD_Errors;
+}
+
/* Print word x with n decimal digits to string s. dot is either NULL
or the location of a decimal point. */
#define EXTRACT_DIGIT(s, x, d, dot) \
dplace = -1 + mod_mpd_ssize_t(dec->exp+2, 3);
}
else { /* ldigits-1 is the adjusted exponent, which
- * should be divisible by three. If not, move
- * dplace one or two places to the right. */
+ * should be divisible by three. If not, move
+ * dplace one or two places to the right. */
dplace += mod_mpd_ssize_t(ldigits-1, 3);
}
}
}
if (isupper((uchar)type)) {
- type = tolower((uchar)type);
+ type = (char)tolower((uchar)type);
flags |= MPD_FMT_UPPER;
}
if (spec->sign == ' ') {
stackspec.align = '>';
spec = &stackspec;
}
+ assert(strlen(spec->fill) == 1); /* annotation for scan-build */
if (type == '%') {
flags |= MPD_FMT_PERCENT;
}
fputs("mpd_fprint: output error\n", stderr); /* GCOV_NOT_REACHED */
}
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef IO_H
-#define IO_H
+#ifndef LIBMPDEC_IO_H_
+#define LIBMPDEC_IO_H_
-#include <errno.h>
#include "mpdecimal.h"
+#include <stdint.h>
+
#if SIZE_MAX == MPD_SIZE_MAX
#define mpd_strtossize _mpd_strtossize
#else
+#include <errno.h>
+
static inline mpd_ssize_t
mpd_strtossize(const char *s, char **end, int base)
{
#endif
-#endif
+#endif /* LIBMPDEC_IO_H_ */
#
-# Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+# Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
-(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
+(* Copyright (c) 2011-2020 Stefan Krah. All rights reserved. *)
The Matrix Fourier Transform:
-(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
+(* Copyright (c) 2011-2020 Stefan Krah. All rights reserved. *)
==========================================================================
-(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
+(* Copyright (c) 2011-2020 Stefan Krah. All rights reserved. *)
========================================================================
-(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
+(* Copyright (c) 2011-2020 Stefan Krah. All rights reserved. *)
The Six Step Transform:
;
-; Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+; Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
(defthmd addmod-correct
(implies (and (< 0 m) (< m base)
- (< a m) (<= b m)
+ (< a m) (<= b m)
(natp m) (natp base)
(natp a) (natp b))
(equal (addmod a b m base)
(defthmd submod-correct
(implies (and (< 0 m) (< m base)
- (< a m) (<= b m)
+ (< a m) (<= b m)
(natp m) (natp base)
(natp a) (natp b))
(equal (submod a b m base)
(defthm submod-2-correct
(implies (and (< 0 m) (< m base)
- (< a m) (<= b m)
+ (< a m) (<= b m)
(natp m) (natp base)
(natp a) (natp b))
(equal (submod-2 a b m base)
(defthmd ext-submod-ext-submod-2-equal
(implies (and (< 0 m) (< m base)
- (< a (* 2 m)) (< b (* 2 m))
+ (< a (* 2 m)) (< b (* 2 m))
(natp m) (natp base)
(natp a) (natp b))
(equal (ext-submod a b m base)
(defthmd ext-submod-2-correct
(implies (and (< 0 m) (< m base)
- (< a (* 2 m)) (< b (* 2 m))
+ (< a (* 2 m)) (< b (* 2 m))
(natp m) (natp base)
(natp a) (natp b))
(equal (ext-submod-2 a b m base)
(defthmd dw-reduce-correct
(implies (and (< 0 m) (< m base)
- (< hi base) (< lo base)
+ (< hi base) (< lo base)
(natp m) (natp base)
(natp hi) (natp lo))
(equal (dw-reduce hi lo m base)
(defthmd dw-submod-correct
(implies (and (< 0 m) (< m base)
(natp a) (< a m)
- (< hi base) (< lo base)
+ (< hi base) (< lo base)
(natp m) (natp base)
(natp hi) (natp lo))
(equal (dw-submod a hi lo m base)
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
+
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include "typearith.h"
+#include <string.h>
+
#include "mpalloc.h"
+#include "typearith.h"
#if defined(_MSC_VER)
return 1;
}
+/*
+ * Input: 'result' is a static mpd_t with a static coefficient.
+ * Assumption: 'nwords' >= result->alloc.
+ *
+ * Resize the static coefficient to a larger dynamic one and copy the
+ * existing data.
+ *
+ * On failure the value of 'result' is unchanged.
+ */
+int
+mpd_switch_to_dyn_cxx(mpd_t *result, mpd_ssize_t nwords)
+{
+ assert(nwords >= result->alloc);
+
+ mpd_uint_t *data = mpd_alloc(nwords, sizeof *result->data);
+ if (data == NULL) {
+ return 0;
+ }
+
+ memcpy(data, result->data, result->alloc * (sizeof *result->data));
+ result->data = data;
+ result->alloc = nwords;
+ mpd_set_dynamic_data(result);
+ return 1;
+}
+/*
+ * Input: 'result' is a static or a dynamic mpd_t with a dynamic coefficient.
+ * Resize the coefficient to length 'nwords':
+ * Case nwords > result->alloc:
+ * If realloc is successful:
+ * 'result' has a larger coefficient but the same value. Return 1.
+ * Otherwise:
+ * 'result' has a the same coefficient. Return 0.
+ * Case nwords < result->alloc:
+ * If realloc is successful:
+ * 'result' has a smaller coefficient. result->len is undefined. Return 1.
+ * Otherwise (unlikely):
+ * 'result' is unchanged. Reuse the now oversized coefficient. Return 1.
+ */
+int
+mpd_realloc_dyn_cxx(mpd_t *result, mpd_ssize_t nwords)
+{
+ uint8_t err = 0;
+
+ mpd_uint_t *p = mpd_realloc(result->data, nwords, sizeof *result->data, &err);
+ if (!err) {
+ result->data = p;
+ result->alloc = nwords;
+ }
+ else if (nwords > result->alloc) {
+ return 0;
+ }
+
+ return 1;
+}
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef MPALLOC_H
-#define MPALLOC_H
+#ifndef LIBMPDEC_MPALLOC_H_
+#define LIBMPDEC_MPALLOC_H_
#include "mpdecimal.h"
+#include <stdint.h>
+
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
-
-MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+int mpd_switch_to_dyn_cxx(mpd_t *result, mpd_ssize_t size);
+int mpd_realloc_dyn_cxx(mpd_t *result, mpd_ssize_t size);
-#endif
-
+MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+#endif /* LIBMPDEC_MPALLOC_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
-#include <math.h>
+
#include "basearith.h"
#include "bits.h"
+#include "constants.h"
#include "convolute.h"
#include "crt.h"
#include "mpalloc.h"
#include "typearith.h"
-#include "umodarith.h"
#ifdef PPRO
#if defined(_MSC_VER)
}
/* Coefficient size needed to store 'digits' */
-ALWAYS_INLINE mpd_ssize_t
+mpd_ssize_t
mpd_digits_to_size(mpd_ssize_t digits)
{
mpd_ssize_t q, r;
/* Canonical */
ALWAYS_INLINE int
-mpd_iscanonical(const mpd_t *dec UNUSED)
+mpd_iscanonical(const mpd_t *dec)
{
+ (void)dec;
return 1;
}
return mpd_realloc_dyn(result, nwords, status);
}
+/* Same as mpd_qresize, but do not set the result no NaN on failure. */
+static ALWAYS_INLINE int
+mpd_qresize_cxx(mpd_t *result, mpd_ssize_t nwords)
+{
+ assert(!mpd_isconst_data(result)); /* illegal operation for a const */
+ assert(!mpd_isshared_data(result)); /* illegal operation for a shared */
+ assert(MPD_MINALLOC <= result->alloc);
+
+ nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;
+ if (nwords == result->alloc) {
+ return 1;
+ }
+ if (mpd_isstatic_data(result)) {
+ if (nwords > result->alloc) {
+ return mpd_switch_to_dyn_cxx(result, nwords);
+ }
+ return 1;
+ }
+
+ return mpd_realloc_dyn_cxx(result, nwords);
+}
+
/* Same as mpd_qresize, but the complete coefficient (including the old
* memory area!) is initialized to zero. */
ALWAYS_INLINE int
result->data[i] = w[i];
}
- mpd_set_sign(result, sign);
+ mpd_set_flags(result, sign);
result->exp = 0;
result->len = len;
mpd_setdigits(result);
#endif
}
+/* quietly set a decimal from an int64_t, use a maxcontext for conversion */
+void
+mpd_qset_i64_exact(mpd_t *result, int64_t a, uint32_t *status)
+{
+ mpd_context_t maxcontext;
+
+ mpd_maxcontext(&maxcontext);
+#ifdef CONFIG_64
+ mpd_qset_ssize(result, a, &maxcontext, status);
+#else
+ _c32_qset_i64(result, a, &maxcontext, status);
+#endif
+
+ if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
+ /* we want exact results */
+ mpd_seterror(result, MPD_Invalid_operation, status);
+ }
+ *status &= MPD_Errors;
+}
+
/* quietly set a decimal from a uint64_t */
void
mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
_c32_qset_u64(result, a, ctx, status);
#endif
}
-#endif /* !LEGACY_COMPILER */
+/* quietly set a decimal from a uint64_t, use a maxcontext for conversion */
+void
+mpd_qset_u64_exact(mpd_t *result, uint64_t a, uint32_t *status)
+{
+ mpd_context_t maxcontext;
+
+ mpd_maxcontext(&maxcontext);
+#ifdef CONFIG_64
+ mpd_qset_uint(result, a, &maxcontext, status);
+#else
+ _c32_qset_u64(result, a, &maxcontext, status);
+#endif
+
+ if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
+ /* we want exact results */
+ mpd_seterror(result, MPD_Invalid_operation, status);
+ }
+ *status &= MPD_Errors;
+}
+#endif /* !LEGACY_COMPILER */
/*
* Quietly get an mpd_uint_t from a decimal. Assumes
mpd_ssize_t
mpd_qget_ssize(const mpd_t *a, uint32_t *status)
{
+ uint32_t workstatus = 0;
mpd_uint_t u;
int isneg;
- u = mpd_qabs_uint(a, status);
- if (*status&MPD_Invalid_operation) {
+ u = mpd_qabs_uint(a, &workstatus);
+ if (workstatus&MPD_Invalid_operation) {
+ *status |= workstatus;
return MPD_SSIZE_MAX;
}
uint32_t
mpd_qget_u32(const mpd_t *a, uint32_t *status)
{
- uint64_t x = mpd_qget_uint(a, status);
+ uint32_t workstatus = 0;
+ uint64_t x = mpd_qget_uint(a, &workstatus);
- if (*status&MPD_Invalid_operation) {
+ if (workstatus&MPD_Invalid_operation) {
+ *status |= workstatus;
return UINT32_MAX;
}
if (x > UINT32_MAX) {
int32_t
mpd_qget_i32(const mpd_t *a, uint32_t *status)
{
- int64_t x = mpd_qget_ssize(a, status);
+ uint32_t workstatus = 0;
+ int64_t x = mpd_qget_ssize(a, &workstatus);
- if (*status&MPD_Invalid_operation) {
+ if (workstatus&MPD_Invalid_operation) {
+ *status |= workstatus;
return INT32_MAX;
}
if (x < INT32_MIN || x > INT32_MAX) {
uint64_t
mpd_qget_u64(const mpd_t *a, uint32_t *status)
{
- return _c32_qget_u64(1, a, status);
+ uint32_t workstatus = 0;
+ uint64_t x = _c32_qget_u64(1, a, &workstatus);
+ *status |= workstatus;
+ return x;
}
/* quietly get an int64_t from a decimal */
int64_t
mpd_qget_i64(const mpd_t *a, uint32_t *status)
{
- return _c32_qget_i64(a, status);
+ uint32_t workstatus = 0;
+ int64_t x = _c32_qget_i64(a, &workstatus);
+ *status |= workstatus;
+ return x;
}
#endif
return 1;
}
+/* Same as mpd_qcopy, but do not set the result to NaN on failure. */
+int
+mpd_qcopy_cxx(mpd_t *result, const mpd_t *a)
+{
+ if (result == a) return 1;
+
+ if (!mpd_qresize_cxx(result, a->len)) {
+ return 0;
+ }
+
+ mpd_copy_flags(result, a);
+ result->exp = a->exp;
+ result->digits = a->digits;
+ result->len = a->len;
+ memcpy(result->data, a->data, a->len * (sizeof *result->data));
+
+ return 1;
+}
+
/*
* Copy to a decimal with a static buffer. The caller has to make sure that
* the buffer is big enough. Cannot fail.
mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{
- _mpd_qdiv(SET_IDEAL_EXP, q, a, b, ctx, status);
+ MPD_NEW_STATIC(aa,0,0,0,0);
+ MPD_NEW_STATIC(bb,0,0,0,0);
+ uint32_t xstatus = 0;
- if (*status & MPD_Malloc_error) {
+ if (q == a) {
+ if (!mpd_qcopy(&aa, a, status)) {
+ mpd_seterror(q, MPD_Malloc_error, status);
+ goto out;
+ }
+ a = &aa;
+ }
+
+ if (q == b) {
+ if (!mpd_qcopy(&bb, b, status)) {
+ mpd_seterror(q, MPD_Malloc_error, status);
+ goto out;
+ }
+ b = &bb;
+ }
+
+ _mpd_qdiv(SET_IDEAL_EXP, q, a, b, ctx, &xstatus);
+
+ if (xstatus & (MPD_Malloc_error|MPD_Division_impossible)) {
/* Inexact quotients (the usual case) fill the entire context precision,
- * which can lead to malloc() failures for very high precisions. Retry
+ * which can lead to the above errors for very high precisions. Retry
* the operation with a lower precision in case the result is exact.
*
* We need an upper bound for the number of digits of a_coeff / b_coeff
* We arrive at a total upper bound:
*
* maxdigits(a_coeff') + maxdigits(1 / b_coeff') <=
- * a->digits + log2(b_coeff) =
- * a->digits + log10(b_coeff) / log10(2) <=
+ * log10(a_coeff) + log2(b_coeff) =
+ * log10(a_coeff) + log10(b_coeff) / log10(2) <=
* a->digits + b->digits * 4;
*/
- uint32_t workstatus = 0;
mpd_context_t workctx = *ctx;
+ uint32_t ystatus = 0;
+
workctx.prec = a->digits + b->digits * 4;
if (workctx.prec >= ctx->prec) {
- return; /* No point in retrying, keep the original error. */
+ *status |= (xstatus&MPD_Errors);
+ goto out; /* No point in retrying, keep the original error. */
}
- _mpd_qdiv(SET_IDEAL_EXP, q, a, b, &workctx, &workstatus);
- if (workstatus == 0) { /* The result is exact, unrounded, normal etc. */
- *status = 0;
- return;
+ _mpd_qdiv(SET_IDEAL_EXP, q, a, b, &workctx, &ystatus);
+ if (ystatus != 0) {
+ ystatus = *status | ((ystatus|xstatus)&MPD_Errors);
+ mpd_seterror(q, ystatus, status);
}
-
- mpd_seterror(q, *status, status);
}
+ else {
+ *status |= xstatus;
+ }
+
+
+out:
+ mpd_del(&aa);
+ mpd_del(&bb);
}
/* Internal function. */
}
if (b->len == 1) {
+ assert(b->data[0] != 0); /* annotation for scan-build */
if (a->len == 1) {
_mpd_div_word(&q->data[0], &r->data[0], a->data[0], b->data[0]);
}
workctx.round = MPD_ROUND_HALF_EVEN;
workctx.clamp = 0;
if (mpd_isnegative(exp)) {
+ uint32_t workstatus = 0;
workctx.prec += 1;
- mpd_qdiv(&tbase, &one, base, &workctx, status);
- if (*status&MPD_Errors) {
+ mpd_qdiv(&tbase, &one, base, &workctx, &workstatus);
+ *status |= workstatus;
+ if (workstatus&MPD_Errors) {
mpd_setspecial(result, MPD_POS, MPD_NAN);
goto finish;
}
mpd_ssize_t expdiff, qdigits;
int cmp, isodd, allnine;
+ assert(r != NULL); /* annotation for scan-build */
+
if (mpd_isspecial(a) || mpd_isspecial(b)) {
if (mpd_qcheck_nans(r, a, b, ctx, status)) {
return;
mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{
+ if (mpd_isspecial(a)) {
+ mpd_seterror(result, MPD_Invalid_operation, status);
+ return;
+ }
+
(void)_mpd_qround_to_integral(TO_INT_TRUNC, result, a, ctx, status);
}
uint32_t *status)
{
mpd_context_t workctx = *ctx;
+
+ if (mpd_isspecial(a)) {
+ mpd_seterror(result, MPD_Invalid_operation, status);
+ return;
+ }
+
workctx.round = MPD_ROUND_FLOOR;
(void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,
&workctx, status);
uint32_t *status)
{
mpd_context_t workctx = *ctx;
+
+ if (mpd_isspecial(a)) {
+ mpd_seterror(result, MPD_Invalid_operation, status);
+ return;
+ }
+
workctx.round = MPD_ROUND_CEILING;
(void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,
&workctx, status);
mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{
- _mpd_qsqrt(result, a, ctx, status);
+ MPD_NEW_STATIC(aa,0,0,0,0);
+ uint32_t xstatus = 0;
+
+ if (result == a) {
+ if (!mpd_qcopy(&aa, a, status)) {
+ mpd_seterror(result, MPD_Malloc_error, status);
+ goto out;
+ }
+ a = &aa;
+ }
+
+ _mpd_qsqrt(result, a, ctx, &xstatus);
- if (*status & (MPD_Malloc_error|MPD_Division_impossible)) {
+ if (xstatus & (MPD_Malloc_error|MPD_Division_impossible)) {
/* The above conditions can occur at very high context precisions
* if intermediate values get too large. Retry the operation with
* a lower context precision in case the result is exact.
*
* NOTE: sqrt(40e9) = 2.0e+5 /\ digits(40e9) = digits(2.0e+5) = 2
*/
- uint32_t workstatus = 0;
+ uint32_t ystatus = 0;
mpd_context_t workctx = *ctx;
- workctx.prec = a->digits;
+ workctx.prec = a->digits;
if (workctx.prec >= ctx->prec) {
- return; /* No point in repeating this, keep the original error. */
+ *status |= (xstatus|MPD_Errors);
+ goto out; /* No point in repeating this, keep the original error. */
}
- _mpd_qsqrt(result, a, &workctx, &workstatus);
- if (workstatus == 0) {
- *status = 0;
- return;
+ _mpd_qsqrt(result, a, &workctx, &ystatus);
+ if (ystatus != 0) {
+ ystatus = *status | ((xstatus|ystatus)&MPD_Errors);
+ mpd_seterror(result, ystatus, status);
}
-
- mpd_seterror(result, *status, status);
}
+ else {
+ *status |= xstatus;
+ }
+
+out:
+ mpd_del(&aa);
}
{
double x;
size_t digits;
+ double upper_bound;
assert(mpd_isinteger(a));
assert(base >= 2);
if (digits > 2711437152599294ULL) {
return SIZE_MAX;
}
+
+ upper_bound = (double)((1ULL<<53)-1);
+#else
+ upper_bound = (double)(SIZE_MAX-1);
#endif
x = (double)digits / log10(base);
- return (x > SIZE_MAX-1) ? SIZE_MAX : (size_t)x + 1;
+ return (x > upper_bound) ? SIZE_MAX : (size_t)x + 1;
}
/* Space needed to import a base 'base' integer of length 'srclen'. */
_mpd_importsize(size_t srclen, uint32_t base)
{
double x;
+ double upper_bound;
assert(srclen > 0);
assert(base >= 2);
if (srclen > (1ULL<<53)) {
return MPD_SSIZE_MAX;
}
+
+ assert((1ULL<<53) <= MPD_MAXIMPORT);
+ upper_bound = (double)((1ULL<<53)-1);
+#else
+ upper_bound = MPD_MAXIMPORT-1;
#endif
x = (double)srclen * (log10(base)/MPD_RDIGITS);
- return (x >= MPD_MAXIMPORT) ? MPD_SSIZE_MAX : (mpd_ssize_t)x + 1;
+ return (x > upper_bound) ? MPD_SSIZE_MAX : (mpd_ssize_t)x + 1;
}
static uint8_t
mpd_qresize(result, result->len, status);
mpd_qfinalize(result, ctx, status);
}
-
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef MPDECIMAL_H
-#define MPDECIMAL_H
+#ifndef LIBMPDEC_MPDECIMAL_H_
+#define LIBMPDEC_MPDECIMAL_H_
+#ifndef _MSC_VER
+ #include "pyconfig.h"
+#endif
+
#ifdef __cplusplus
+ #include <cinttypes>
+ #include <climits>
+ #include <cstdint>
+ #include <cstdio>
+ #include <cstdlib>
extern "C" {
- #ifndef __STDC_LIMIT_MACROS
- #define __STDC_LIMIT_MACROS
- #define MPD_CLEAR_STDC_LIMIT_MACROS
- #endif
+#else
+ #include <inttypes.h>
+ #include <limits.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
#endif
-#ifndef _MSC_VER
- #include "pyconfig.h"
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
+ defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER)
+ #define MPD_PRAGMA(x) _Pragma(x)
+ #define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)"
+ #define MPD_HIDE_SYMBOLS_END "GCC visibility pop"
+#else
+ #define MPD_PRAGMA(x)
+ #define MPD_HIDE_SYMBOLS_START
+ #define MPD_HIDE_SYMBOLS_END
#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdint.h>
-#include <inttypes.h>
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+ #define UNUSED __attribute__((unused))
+#else
+ #define UNUSED
+#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
#include "vccompat.h"
- #ifndef UNUSED
- #define UNUSED
- #endif
- #define MPD_PRAGMA(x)
- #define MPD_HIDE_SYMBOLS_START
- #define MPD_HIDE_SYMBOLS_END
#define EXTINLINE extern inline
#else
- #ifndef __GNUC_STDC_INLINE__
- #define __GNUC_STDC_INLINE__ 1
- #endif
- #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
- #define UNUSED __attribute__((unused))
- #else
- #define UNUSED
- #endif
- #if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
- defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER)
- #define MPD_PRAGMA(x) _Pragma(x)
- #define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)"
- #define MPD_HIDE_SYMBOLS_END "GCC visibility pop"
- #else
- #define MPD_PRAGMA(x)
- #define MPD_HIDE_SYMBOLS_START
- #define MPD_HIDE_SYMBOLS_END
- #endif
#define EXTINLINE
#endif
/******************************************************************************/
#define MPD_MAJOR_VERSION 2
-#define MPD_MINOR_VERSION 4
-#define MPD_MICRO_VERSION 2
+#define MPD_MINOR_VERSION 5
+#define MPD_MICRO_VERSION 0
-#define MPD_VERSION "2.4.2"
+#define MPD_VERSION "2.5.0"
#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
(MPD_MINOR_VERSION << 16) | \
/* assignment from a string */
void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_string_exact(mpd_t *dec, const char *s, uint32_t *status);
/* set to NaN with error flags */
void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
#ifndef LEGACY_COMPILER
void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_i64_exact(mpd_t *result, int64_t a, uint32_t *status);
+void mpd_qset_u64_exact(mpd_t *result, uint64_t a, uint32_t *status);
#endif
/* quietly assign a C integer type to an mpd_t with a static coefficient */
const char *mpd_class(const mpd_t *a, const mpd_context_t *ctx);
-int mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status);
+int mpd_qcopy_cxx(mpd_t *result, const mpd_t *a);
mpd_t *mpd_qncopy(const mpd_t *a);
int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
EXTINLINE mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
EXTINLINE int mpd_exp_digits(mpd_ssize_t exp);
-EXTINLINE int mpd_iscanonical(const mpd_t *dec UNUSED);
+EXTINLINE int mpd_iscanonical(const mpd_t *dec);
EXTINLINE int mpd_isfinite(const mpd_t *dec);
EXTINLINE int mpd_isinfinite(const mpd_t *dec);
EXTINLINE int mpd_isinteger(const mpd_t *dec);
#ifdef __cplusplus
- #ifdef MPD_CLEAR_STDC_LIMIT_MACROS
- #undef MPD_CLEAR_STDC_LIMIT_MACROS
- #undef __STDC_LIMIT_MACROS
- #endif
} /* END extern "C" */
#endif
-#endif /* MPDECIMAL_H */
-
-
-
+#endif /* LIBMPDEC_MPDECIMAL_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdlib.h>
+
#include <assert.h>
+#include <stdlib.h>
+
#include "bits.h"
-#include "umodarith.h"
#include "numbertheory.h"
+#include "umodarith.h"
/* Bignum: Initialize the Number Theoretic Transform. */
w3table[1] = kernel;
w3table[2] = POWMOD(kernel, 2);
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef NUMBER_THEORY_H
-#define NUMBER_THEORY_H
+#ifndef LIBMPDEC_NUMBERTHEORY_H_
+#define LIBMPDEC_NUMBERTHEORY_H_
-#include "constants.h"
#include "mpdecimal.h"
+#include "constants.h"
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
-
-
+#endif /* LIBMPDEC_NUMBERTHEORY_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
-#include <stdio.h>
-#include <stdlib.h>
+
#include <assert.h>
+#include <stdio.h>
+
#include "bits.h"
+#include "constants.h"
#include "difradix2.h"
#include "numbertheory.h"
+#include "sixstep.h"
#include "transpose.h"
#include "umodarith.h"
-#include "sixstep.h"
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
return 1;
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef SIX_STEP_H
-#define SIX_STEP_H
+#ifndef LIBMPDEC_SIXSTEP_H_
+#define LIBMPDEC_SIXSTEP_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_SIXSTEP_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "mpdecimal.h"
+
+#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
-#include <assert.h>
+
#include "bits.h"
#include "constants.h"
-#include "typearith.h"
#include "transpose.h"
+#include "typearith.h"
#define BUFSIZE 4096
return 1;
}
-
-
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef TRANSPOSE_H
-#define TRANSPOSE_H
+#ifndef LIBMPDEC_TRANSPOSE_H_
+#define LIBMPDEC_TRANSPOSE_H_
#include "mpdecimal.h"
-#include <stdio.h>
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
-#endif
+#endif /* LIBMPDEC_TRANSPOSE_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef TYPEARITH_H
-#define TYPEARITH_H
+#ifndef LIBMPDEC_TYPEARITH_H_
+#define LIBMPDEC_TYPEARITH_H_
#include "mpdecimal.h"
+#include <assert.h>
+
/*****************************************************************************/
/* Low level native arithmetic on basic types */
}
-#endif /* TYPEARITH_H */
-
-
-
+#endif /* LIBMPDEC_TYPEARITH_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef UMODARITH_H
-#define UMODARITH_H
+#ifndef LIBMPDEC_UMODARITH_H_
+#define LIBMPDEC_UMODARITH_H_
-#include "constants.h"
#include "mpdecimal.h"
+
+#include "constants.h"
#include "typearith.h"
#endif /* CONFIG_32 */
-#endif /* UMODARITH_H */
-
-
-
+#endif /* LIBMPDEC_UMODARITH_H_ */
/*
- * Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+ * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
-#ifndef VCCOMPAT_H
-#define VCCOMPAT_H
+#ifndef LIBMPDEC_VCCOMPAT_H_
+#define LIBMPDEC_VCCOMPAT_H_
/* Visual C fixes: no snprintf ... */
#ifdef _MSC_VER
- #undef inline
- #define inline __inline
+ #ifndef __cplusplus
+ #undef inline
+ #define inline __inline
+ #endif
#undef random
#define random rand
#undef srandom
#endif
-#endif /* VCCOMPAT_H */
-
-
-
+#endif /* LIBMPDEC_VCCOMPAT_H_ */
;
-; Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
+; Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
_mpd_div_words ENDP
_TEXT ENDS
END
-
-