十进制胶囊API¶
只要API已经初始化,就可以以与常规库函数相同的方式使用capsuleapi函数。
初始化¶
通常,使用decimal API的C扩展模块将在其init函数中执行以下步骤:
#include "pydecimal.h"
static int decimal_initialized = 0;
if (!decimal_initialized) {
if (import_decimal() < 0) {
return NULL;
}
decimal_initialized = 1;
}
类型检查、谓词、访问器¶
-
int PyDec_IsSpecial(const PyObject *dec)¶
返回1如果
dec是NaN,sNaN或Infinity,否则为0。设置TypeError并返回-1 if
dec不是十进制。可以保证这是唯一的故障模式,因此如果dec已进行类型检查,不会出现错误,并且可以将函数视为简单谓词。
-
int PyDec_IsNaN(const PyObject *dec)¶
返回1如果
dec是NaN或sNaN,否则为0。设置TypeError并返回-1 if
dec不是十进制。可以保证这是唯一的故障模式,因此如果dec已进行类型检查,不会出现错误,并且可以将函数视为简单谓词。
小数与本原C类型的精确转换¶
此API支持系数高达38位的小数的转换。
数据结构¶
转换函数使用以下状态代码和数据结构:
/* status cases for getting a triple */
enum mpd_triple_class {
MPD_TRIPLE_NORMAL,
MPD_TRIPLE_INF,
MPD_TRIPLE_QNAN,
MPD_TRIPLE_SNAN,
MPD_TRIPLE_ERROR,
};
typedef struct {
enum mpd_triple_class tag;
uint8_t sign;
uint64_t hi;
uint64_t lo;
int64_t exp;
} mpd_uint128_triple_t;
状态案例解释如下。 sign 0表示正,1表示负。 ((uint128_t)hi << 64) + lo 是系数, exp 是指数。
数据结构被称为“三元组”,因为十进制三元组(sign、coeff、exp)是一个既定的术语,并且 (hi , lo )表示单个 uint128_t 系数。
功能¶
-
mpd_uint128_triple_t PyDec_AsUint128Triple(const PyObject *dec)¶
把十进制数转换成三元组。如上所述,可以保证Python唯一的失败模式是TypeError,如果知道类型,则可以省略检查。
为了简单起见,函数的用法和所有特殊情况都以代码形式和注释进行了说明:
triple = PyDec_AsUint128Triple(dec);
switch (triple.tag) {
case MPD_TRIPLE_QNAN:
/*
* Success: handle a quiet NaN.
* 1) triple.sign is 0 or 1.
* 2) triple.exp is always 0.
* 3) If triple.hi or triple.lo are nonzero, the NaN has a payload.
*/
break;
case MPD_TRIPLE_SNAN:
/*
* Success: handle a signaling NaN.
* 1) triple.sign is 0 or 1.
* 2) triple.exp is always 0.
* 3) If triple.hi or triple.lo are nonzero, the sNaN has a payload.
*/
break;
case MPD_TRIPLE_INF:
/*
* Success: handle Infinity.
* 1) triple.sign is 0 or 1.
* 2) triple.exp is always 0.
* 3) triple.hi and triple.lo are always zero.
*/
break;
case MPD_TRIPLE_NORMAL:
/* Success: handle a finite value. */
break;
case MPD_TRIPLE_ERROR:
/* TypeError check: can be omitted if the type of dec is known. */
if (PyErr_Occurred()) {
return NULL;
}
/* Too large for conversion. PyDec_AsUint128Triple() does not set an
exception so applications can choose themselves. Typically this
would be a ValueError. */
PyErr_SetString(PyExc_ValueError,
"value out of bounds for a uint128 triple");
return NULL;
}
-
PyObject *PyDec_FromUint128Triple(const mpd_uint128_triple_t *triple)¶
从三元组创建十进制数。初始化三元组时必须遵守以下规则:
triple.sign必须始终为0(表示正)或1(表示负)。MPD_TRIPLE_QNAN:triple.exp必须是0。如果triple.hi或triple.lo非零,创建一个NaN有效载荷。MPD_TRIPLE_SNAN:triple.exp必须是0。如果triple.hi或triple.lo非零,创建一个sNaN有效载荷。MPD_TRIPLE_INF:triple.exp,triple.hi和triple.lo必须是零。MPD_TRIPLE_NORMAL:MPD_MIN_ETINY + 38 < triple.exp < MPD_MAX_EMAX - 38.triple.hi和triple.lo可以自由选择。MPD_TRIPLE_ERROR:设置此标记总是错误的。
如果不满足上述条件之一,函数将返回
NaN如果InvalidOperation线程本地上下文中未设置陷阱。否则,它将设置InvalidOperation异常并返回NULL。此外,虽然不太可能给出较小的分配大小,但函数可以设置
MemoryError然后返回NULL.
高级API¶
此API允许使用 libmpdec 功能。因为Python是用隐藏符号编译的,所以API需要一个外部libmpdec和 mpdecimal.h 标题。