Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 45059eb

Browse files
author
Stefan Krah
committed
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.
1 parent cdac302 commit 45059eb

6 files changed

Lines changed: 329 additions & 37 deletions

File tree

Lib/decimal.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140

141141
__version__ = '1.70' # Highest version of the spec this complies with
142142
# See http://speleotrove.com/decimal/
143+
__libmpdec_version__ = "2.4.0" # compatible libmpdec version
143144

144145
import copy as _copy
145146
import math as _math

Lib/test/test_decimal.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4150,6 +4150,7 @@ def test_module_attributes(self):
41504150
self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
41514151

41524152
self.assertEqual(C.__version__, P.__version__)
4153+
self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
41534154

41544155
x = dir(C)
41554156
y = [s for s in dir(P) if '__' in s or not s.startswith('_')]

Modules/_decimal/_decimal.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
#include "memory.h"
4040

4141

42+
#if MPD_MAJOR_VERSION != 2
43+
#error "libmpdec major version 2 required"
44+
#endif
45+
46+
4247
/*
4348
* Type sizes with assertions in mpdecimal.h and pyport.h:
4449
* sizeof(size_t) == sizeof(Py_ssize_t)
@@ -5730,7 +5735,8 @@ PyInit__decimal(void)
57305735
}
57315736

57325737
/* Add specification version number */
5733-
CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));
5738+
CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
5739+
CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
57345740

57355741

57365742
return m;

Modules/_decimal/libmpdec/mpdecimal.c

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a,
9797
mpd_ssize_t exp);
9898
static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);
9999

100+
static int _mpd_cmp_abs(const mpd_t *a, const mpd_t *b);
101+
100102
static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
101103
const mpd_context_t *ctx, uint32_t *status);
102104
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,
110112
static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
111113

112114

115+
/******************************************************************************/
116+
/* Version */
117+
/******************************************************************************/
118+
119+
const char *
120+
mpd_version(void)
121+
{
122+
return MPD_VERSION;
123+
}
124+
125+
113126
/******************************************************************************/
114127
/* Performance critical inline functions */
115128
/******************************************************************************/
@@ -1345,6 +1358,91 @@ mpd_qget_ssize(const mpd_t *a, uint32_t *status)
13451358
return MPD_SSIZE_MAX;
13461359
}
13471360

1361+
#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
1362+
/*
1363+
* Quietly get a uint64_t from a decimal. If the operation is impossible,
1364+
* MPD_Invalid_operation is set.
1365+
*/
1366+
static uint64_t
1367+
_c32_qget_u64(int use_sign, const mpd_t *a, uint32_t *status)
1368+
{
1369+
MPD_NEW_STATIC(tmp,0,0,20,3);
1370+
mpd_context_t maxcontext;
1371+
uint64_t ret;
1372+
1373+
tmp_data[0] = 709551615;
1374+
tmp_data[1] = 446744073;
1375+
tmp_data[2] = 18;
1376+
1377+
if (mpd_isspecial(a)) {
1378+
*status |= MPD_Invalid_operation;
1379+
return UINT64_MAX;
1380+
}
1381+
if (mpd_iszero(a)) {
1382+
return 0;
1383+
}
1384+
if (use_sign && mpd_isnegative(a)) {
1385+
*status |= MPD_Invalid_operation;
1386+
return UINT64_MAX;
1387+
}
1388+
if (!_mpd_isint(a)) {
1389+
*status |= MPD_Invalid_operation;
1390+
return UINT64_MAX;
1391+
}
1392+
1393+
if (_mpd_cmp_abs(a, &tmp) > 0) {
1394+
*status |= MPD_Invalid_operation;
1395+
return UINT64_MAX;
1396+
}
1397+
1398+
mpd_maxcontext(&maxcontext);
1399+
mpd_qrescale(&tmp, a, 0, &maxcontext, &maxcontext.status);
1400+
maxcontext.status &= ~MPD_Rounded;
1401+
if (maxcontext.status != 0) {
1402+
*status |= (maxcontext.status|MPD_Invalid_operation); /* GCOV_NOT_REACHED */
1403+
return UINT64_MAX; /* GCOV_NOT_REACHED */
1404+
}
1405+
1406+
ret = 0;
1407+
switch (tmp.len) {
1408+
case 3:
1409+
ret += (uint64_t)tmp_data[2] * 1000000000000000000ULL;
1410+
case 2:
1411+
ret += (uint64_t)tmp_data[1] * 1000000000ULL;
1412+
case 1:
1413+
ret += tmp_data[0];
1414+
break;
1415+
default:
1416+
abort(); /* GCOV_NOT_REACHED */
1417+
}
1418+
1419+
return ret;
1420+
}
1421+
1422+
static int64_t
1423+
_c32_qget_i64(const mpd_t *a, uint32_t *status)
1424+
{
1425+
uint64_t u;
1426+
int isneg;
1427+
1428+
u = _c32_qget_u64(0, a, status);
1429+
if (*status&MPD_Invalid_operation) {
1430+
return INT64_MAX;
1431+
}
1432+
1433+
isneg = mpd_isnegative(a);
1434+
if (u <= INT64_MAX) {
1435+
return isneg ? -((int64_t)u) : (int64_t)u;
1436+
}
1437+
else if (isneg && u+(INT64_MIN+INT64_MAX) == INT64_MAX) {
1438+
return INT64_MIN;
1439+
}
1440+
1441+
*status |= MPD_Invalid_operation;
1442+
return INT64_MAX;
1443+
}
1444+
#endif /* CONFIG_32 && !LEGACY_COMPILER */
1445+
13481446
#ifdef CONFIG_64
13491447
/* quietly get a uint64_t from a decimal */
13501448
uint64_t
@@ -1359,7 +1457,57 @@ mpd_qget_i64(const mpd_t *a, uint32_t *status)
13591457
{
13601458
return mpd_qget_ssize(a, status);
13611459
}
1460+
1461+
/* quietly get a uint32_t from a decimal */
1462+
uint32_t
1463+
mpd_qget_u32(const mpd_t *a, uint32_t *status)
1464+
{
1465+
uint64_t x = mpd_qget_uint(a, status);
1466+
1467+
if (*status&MPD_Invalid_operation) {
1468+
return UINT32_MAX;
1469+
}
1470+
if (x > UINT32_MAX) {
1471+
*status |= MPD_Invalid_operation;
1472+
return UINT32_MAX;
1473+
}
1474+
1475+
return (uint32_t)x;
1476+
}
1477+
1478+
/* quietly get an int32_t from a decimal */
1479+
int32_t
1480+
mpd_qget_i32(const mpd_t *a, uint32_t *status)
1481+
{
1482+
int64_t x = mpd_qget_ssize(a, status);
1483+
1484+
if (*status&MPD_Invalid_operation) {
1485+
return INT32_MAX;
1486+
}
1487+
if (x < INT32_MIN || x > INT32_MAX) {
1488+
*status |= MPD_Invalid_operation;
1489+
return INT32_MAX;
1490+
}
1491+
1492+
return (int32_t)x;
1493+
}
13621494
#else
1495+
#ifndef LEGACY_COMPILER
1496+
/* quietly get a uint64_t from a decimal */
1497+
uint64_t
1498+
mpd_qget_u64(const mpd_t *a, uint32_t *status)
1499+
{
1500+
return _c32_qget_u64(1, a, status);
1501+
}
1502+
1503+
/* quietly get an int64_t from a decimal */
1504+
int64_t
1505+
mpd_qget_i64(const mpd_t *a, uint32_t *status)
1506+
{
1507+
return _c32_qget_i64(a, status);
1508+
}
1509+
#endif
1510+
13631511
/* quietly get a uint32_t from a decimal */
13641512
uint32_t
13651513
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,
33863534
{
33873535
mpd_qadd_uint(result, a, b, ctx, status);
33883536
}
3537+
#elif !defined(LEGACY_COMPILER)
3538+
/* Add decimal and int64_t. */
3539+
void
3540+
mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
3541+
const mpd_context_t *ctx, uint32_t *status)
3542+
{
3543+
mpd_context_t maxcontext;
3544+
MPD_NEW_STATIC(bb,0,0,0,0);
3545+
3546+
mpd_maxcontext(&maxcontext);
3547+
mpd_qset_i64(&bb, b, &maxcontext, status);
3548+
mpd_qadd(result, a, &bb, ctx, status);
3549+
mpd_del(&bb);
3550+
}
3551+
3552+
/* Add decimal and uint64_t. */
3553+
void
3554+
mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
3555+
const mpd_context_t *ctx, uint32_t *status)
3556+
{
3557+
mpd_context_t maxcontext;
3558+
MPD_NEW_STATIC(bb,0,0,0,0);
3559+
3560+
mpd_maxcontext(&maxcontext);
3561+
mpd_qset_u64(&bb, b, &maxcontext, status);
3562+
mpd_qadd(result, a, &bb, ctx, status);
3563+
mpd_del(&bb);
3564+
}
33893565
#endif
33903566

33913567
/* Subtract int32_t from decimal. */
@@ -3420,6 +3596,34 @@ mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
34203596
{
34213597
mpd_qsub_uint(result, a, b, ctx, status);
34223598
}
3599+
#elif !defined(LEGACY_COMPILER)
3600+
/* Subtract int64_t from decimal. */
3601+
void
3602+
mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
3603+
const mpd_context_t *ctx, uint32_t *status)
3604+
{
3605+
mpd_context_t maxcontext;
3606+
MPD_NEW_STATIC(bb,0,0,0,0);
3607+
3608+
mpd_maxcontext(&maxcontext);
3609+
mpd_qset_i64(&bb, b, &maxcontext, status);
3610+
mpd_qsub(result, a, &bb, ctx, status);
3611+
mpd_del(&bb);
3612+
}
3613+
3614+
/* Subtract uint64_t from decimal. */
3615+
void
3616+
mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
3617+
const mpd_context_t *ctx, uint32_t *status)
3618+
{
3619+
mpd_context_t maxcontext;
3620+
MPD_NEW_STATIC(bb,0,0,0,0);
3621+
3622+
mpd_maxcontext(&maxcontext);
3623+
mpd_qset_u64(&bb, b, &maxcontext, status);
3624+
mpd_qsub(result, a, &bb, ctx, status);
3625+
mpd_del(&bb);
3626+
}
34233627
#endif
34243628

34253629

@@ -3871,6 +4075,34 @@ mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
38714075
{
38724076
mpd_qdiv_uint(result, a, b, ctx, status);
38734077
}
4078+
#elif !defined(LEGACY_COMPILER)
4079+
/* Divide decimal by int64_t. */
4080+
void
4081+
mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
4082+
const mpd_context_t *ctx, uint32_t *status)
4083+
{
4084+
mpd_context_t maxcontext;
4085+
MPD_NEW_STATIC(bb,0,0,0,0);
4086+
4087+
mpd_maxcontext(&maxcontext);
4088+
mpd_qset_i64(&bb, b, &maxcontext, status);
4089+
mpd_qdiv(result, a, &bb, ctx, status);
4090+
mpd_del(&bb);
4091+
}
4092+
4093+
/* Divide decimal by uint64_t. */
4094+
void
4095+
mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
4096+
const mpd_context_t *ctx, uint32_t *status)
4097+
{
4098+
mpd_context_t maxcontext;
4099+
MPD_NEW_STATIC(bb,0,0,0,0);
4100+
4101+
mpd_maxcontext(&maxcontext);
4102+
mpd_qset_u64(&bb, b, &maxcontext, status);
4103+
mpd_qdiv(result, a, &bb, ctx, status);
4104+
mpd_del(&bb);
4105+
}
38744106
#endif
38754107

38764108
/* 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,
56645896
{
56655897
mpd_qmul_uint(result, a, b, ctx, status);
56665898
}
5899+
#elif !defined(LEGACY_COMPILER)
5900+
/* Multiply decimal and int64_t. */
5901+
void
5902+
mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
5903+
const mpd_context_t *ctx, uint32_t *status)
5904+
{
5905+
mpd_context_t maxcontext;
5906+
MPD_NEW_STATIC(bb,0,0,0,0);
5907+
5908+
mpd_maxcontext(&maxcontext);
5909+
mpd_qset_i64(&bb, b, &maxcontext, status);
5910+
mpd_qmul(result, a, &bb, ctx, status);
5911+
mpd_del(&bb);
5912+
}
5913+
5914+
/* Multiply decimal and uint64_t. */
5915+
void
5916+
mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
5917+
const mpd_context_t *ctx, uint32_t *status)
5918+
{
5919+
mpd_context_t maxcontext;
5920+
MPD_NEW_STATIC(bb,0,0,0,0);
5921+
5922+
mpd_maxcontext(&maxcontext);
5923+
mpd_qset_u64(&bb, b, &maxcontext, status);
5924+
mpd_qmul(result, a, &bb, ctx, status);
5925+
mpd_del(&bb);
5926+
}
56675927
#endif
56685928

56695929
/* Like the minus operator. */

0 commit comments

Comments
 (0)