1) Prepare libmpdec for the 2.4.0 release. None of the following changes affects

_decimal:

      o Make all "mpd_t to C integer" conversion functions available in both the
        64-bit and the 32-bit versions.

      o Make all mixed mpd_t/C integer arithmetic functions available in the
        32-bit version.

      o Better handling of __STDC_LIMIT_MACROS for C++ users.

      o Add struct tags (at the request of C++ users).

2) Check for libmpdec.so.2 if --with-system-libmpdec is used.
This commit is contained in:
Stefan Krah 2013-11-24 19:44:57 +01:00
parent cdac302af3
commit 45059eb1d0
6 changed files with 331 additions and 39 deletions

View File

@ -140,6 +140,7 @@ __all__ = [
__version__ = '1.70' # Highest version of the spec this complies with
# See http://speleotrove.com/decimal/
__libmpdec_version__ = "2.4.0" # compatible libmpdec version
import copy as _copy
import math as _math

View File

@ -4150,6 +4150,7 @@ class CheckAttributes(unittest.TestCase):
self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
self.assertEqual(C.__version__, P.__version__)
self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
x = dir(C)
y = [s for s in dir(P) if '__' in s or not s.startswith('_')]

View File

@ -39,6 +39,11 @@
#include "memory.h"
#if MPD_MAJOR_VERSION != 2
#error "libmpdec major version 2 required"
#endif
/*
* Type sizes with assertions in mpdecimal.h and pyport.h:
* sizeof(size_t) == sizeof(Py_ssize_t)
@ -5731,6 +5736,7 @@ PyInit__decimal(void)
/* Add specification version number */
CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
return m;

View File

@ -97,6 +97,8 @@ static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a,
mpd_ssize_t exp);
static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);
static int _mpd_cmp_abs(const mpd_t *a, const mpd_t *b);
static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status);
static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
@ -110,6 +112,17 @@ static inline void _mpd_qpow_uint(mpd_t *result, const mpd_t *base,
static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
/******************************************************************************/
/* Version */
/******************************************************************************/
const char *
mpd_version(void)
{
return MPD_VERSION;
}
/******************************************************************************/
/* Performance critical inline functions */
/******************************************************************************/
@ -1345,6 +1358,91 @@ mpd_qget_ssize(const mpd_t *a, uint32_t *status)
return MPD_SSIZE_MAX;
}
#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
/*
* Quietly get a uint64_t from a decimal. If the operation is impossible,
* MPD_Invalid_operation is set.
*/
static uint64_t
_c32_qget_u64(int use_sign, const mpd_t *a, uint32_t *status)
{
MPD_NEW_STATIC(tmp,0,0,20,3);
mpd_context_t maxcontext;
uint64_t ret;
tmp_data[0] = 709551615;
tmp_data[1] = 446744073;
tmp_data[2] = 18;
if (mpd_isspecial(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (mpd_iszero(a)) {
return 0;
}
if (use_sign && mpd_isnegative(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (!_mpd_isint(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (_mpd_cmp_abs(a, &tmp) > 0) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
mpd_maxcontext(&maxcontext);
mpd_qrescale(&tmp, a, 0, &maxcontext, &maxcontext.status);
maxcontext.status &= ~MPD_Rounded;
if (maxcontext.status != 0) {
*status |= (maxcontext.status|MPD_Invalid_operation); /* GCOV_NOT_REACHED */
return UINT64_MAX; /* GCOV_NOT_REACHED */
}
ret = 0;
switch (tmp.len) {
case 3:
ret += (uint64_t)tmp_data[2] * 1000000000000000000ULL;
case 2:
ret += (uint64_t)tmp_data[1] * 1000000000ULL;
case 1:
ret += tmp_data[0];
break;
default:
abort(); /* GCOV_NOT_REACHED */
}
return ret;
}
static int64_t
_c32_qget_i64(const mpd_t *a, uint32_t *status)
{
uint64_t u;
int isneg;
u = _c32_qget_u64(0, a, status);
if (*status&MPD_Invalid_operation) {
return INT64_MAX;
}
isneg = mpd_isnegative(a);
if (u <= INT64_MAX) {
return isneg ? -((int64_t)u) : (int64_t)u;
}
else if (isneg && u+(INT64_MIN+INT64_MAX) == INT64_MAX) {
return INT64_MIN;
}
*status |= MPD_Invalid_operation;
return INT64_MAX;
}
#endif /* CONFIG_32 && !LEGACY_COMPILER */
#ifdef CONFIG_64
/* quietly get a uint64_t from a decimal */
uint64_t
@ -1359,7 +1457,57 @@ mpd_qget_i64(const mpd_t *a, uint32_t *status)
{
return mpd_qget_ssize(a, status);
}
/* quietly get a uint32_t from a decimal */
uint32_t
mpd_qget_u32(const mpd_t *a, uint32_t *status)
{
uint64_t x = mpd_qget_uint(a, status);
if (*status&MPD_Invalid_operation) {
return UINT32_MAX;
}
if (x > UINT32_MAX) {
*status |= MPD_Invalid_operation;
return UINT32_MAX;
}
return (uint32_t)x;
}
/* quietly get an int32_t from a decimal */
int32_t
mpd_qget_i32(const mpd_t *a, uint32_t *status)
{
int64_t x = mpd_qget_ssize(a, status);
if (*status&MPD_Invalid_operation) {
return INT32_MAX;
}
if (x < INT32_MIN || x > INT32_MAX) {
*status |= MPD_Invalid_operation;
return INT32_MAX;
}
return (int32_t)x;
}
#else
#ifndef LEGACY_COMPILER
/* quietly get a uint64_t from a decimal */
uint64_t
mpd_qget_u64(const mpd_t *a, uint32_t *status)
{
return _c32_qget_u64(1, a, status);
}
/* 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);
}
#endif
/* quietly get a uint32_t from a decimal */
uint32_t
mpd_qget_u32(const mpd_t *a, uint32_t *status)
@ -3386,6 +3534,34 @@ mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
{
mpd_qadd_uint(result, a, b, ctx, status);
}
#elif !defined(LEGACY_COMPILER)
/* Add decimal and int64_t. */
void
mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qadd(result, a, &bb, ctx, status);
mpd_del(&bb);
}
/* Add decimal and uint64_t. */
void
mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qadd(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
/* Subtract int32_t from decimal. */
@ -3420,6 +3596,34 @@ mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
{
mpd_qsub_uint(result, a, b, ctx, status);
}
#elif !defined(LEGACY_COMPILER)
/* Subtract int64_t from decimal. */
void
mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qsub(result, a, &bb, ctx, status);
mpd_del(&bb);
}
/* Subtract uint64_t from decimal. */
void
mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qsub(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
@ -3871,6 +4075,34 @@ mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
{
mpd_qdiv_uint(result, a, b, ctx, status);
}
#elif !defined(LEGACY_COMPILER)
/* Divide decimal by int64_t. */
void
mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qdiv(result, a, &bb, ctx, status);
mpd_del(&bb);
}
/* Divide decimal by uint64_t. */
void
mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qdiv(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
/* Pad the result with trailing zeros if it has fewer digits than prec. */
@ -5664,6 +5896,34 @@ mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
{
mpd_qmul_uint(result, a, b, ctx, status);
}
#elif !defined(LEGACY_COMPILER)
/* Multiply decimal and int64_t. */
void
mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qmul(result, a, &bb, ctx, status);
mpd_del(&bb);
}
/* Multiply decimal and uint64_t. */
void
mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qmul(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
/* Like the minus operator. */

View File

@ -32,7 +32,6 @@
#ifdef __cplusplus
extern "C" {
#define __STDC_LIMIT_MACROS
#endif
@ -56,12 +55,18 @@ extern "C" {
#define MPD_HIDE_SYMBOLS_END
#define EXTINLINE extern inline
#else
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#undef __STDC_LIMIT_MACROS
#else
#include <stdint.h>
#endif
#endif
#ifndef __GNUC_STDC_INLINE__
#define __GNUC_STDC_INLINE__ 1
#endif
@ -99,6 +104,19 @@ MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
#endif
/******************************************************************************/
/* Version */
/******************************************************************************/
#define MPD_MAJOR_VERSION 2
#define MPD_MINOR_VERSION 4
#define MPD_MICRO_VERSION 0
#define MPD_VERSION "2.4.0"
const char *mpd_version(void);
/******************************************************************************/
/* Configuration */
/******************************************************************************/
@ -241,7 +259,7 @@ extern const char *mpd_round_string[MPD_ROUND_GUARD];
extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
typedef struct {
typedef struct mpd_context_t {
mpd_ssize_t prec; /* precision */
mpd_ssize_t emax; /* max positive exp */
mpd_ssize_t emin; /* min negative exp */
@ -353,7 +371,7 @@ void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
/* mpd_t */
typedef struct {
typedef struct mpd_t {
uint8_t flags;
mpd_ssize_t exp;
mpd_ssize_t digits;
@ -371,7 +389,7 @@ typedef unsigned char uchar;
/******************************************************************************/
/* format specification */
typedef struct {
typedef struct mpd_spec_t {
mpd_ssize_t min_width; /* minimum field width */
mpd_ssize_t prec; /* fraction digits or significant digits */
char type; /* conversion specifier */
@ -437,6 +455,12 @@ mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
#ifndef LEGACY_COMPILER
int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
#endif
/* quiet functions */
int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
@ -528,6 +552,17 @@ void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_
void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
#ifndef LEGACY_COMPILER
void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
#endif
size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
@ -571,6 +606,12 @@ void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
#ifndef LEGACY_COMPILER
int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
#endif
void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
@ -641,31 +682,7 @@ void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
/******************************************************************************/
/* Configuration specific */
/******************************************************************************/
#ifdef CONFIG_64
void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
#ifndef LEGACY_COMPILER
void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
@ -674,11 +691,18 @@ void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
#else
int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
#endif
/******************************************************************************/
/* Configuration specific */
/******************************************************************************/
#ifdef CONFIG_64
void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
#endif

View File

@ -1945,7 +1945,7 @@ class PyBuildExt(build_ext):
undef_macros = []
if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
include_dirs = []
libraries = ['mpdec']
libraries = [':libmpdec.so.2']
sources = ['_decimal/_decimal.c']
depends = ['_decimal/docstrings.h']
else: