Assignment, Conversions, I/O¶
Create Decimal¶
From String¶
void mpd_qset_string(mpd_t *result, const char *s, const mpd_context_t *ctx,
uint32_t *status);
void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
Set result from s. The context is respected. This means that rounding, overflow
etc. can take place. If the string is not valid, the MPD_Conversion_syntax
condition is added to status and result is set to NaN.
void mpd_qset_string_exact(mpd_t *result, const char *s, uint32_t *status);
Set result from s. The conversion is exact. If internal limits prevent exact
conversion, the MPD_Invalid_operation
condition is added to status
and result is set to NaN.
New in version 2.5.0.
From Integer¶
void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qset_u32(mpd_t *result, uint32_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_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
Set result from a C integer type. The context is respected.
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);
Set result from a C integer type. The conversion is exact. If exact conversion
is not possible, the MPD_Invalid_operation
condition is added to status
and result is set to NaN.
New in version 2.5.0.
From Special Values¶
void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
Set result to NaN, with the error condition passed in flags. The error condition is added to status. This is a convenience function intended to be used inside quiet functions.
void mpd_setspecial(mpd_t *result, uint8_t sign, uint8_t type);
Set result to a special number. sign must be one of {MPD_POS
, MPD_NEG
},
type one of {MPD_INF
, MPD_NAN
, MPD_SNAN
}.
void mpd_zerocoeff(mpd_t *result);
Set the coefficient of result to zero. This function cannot fail.
void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx,
uint32_t *status);
void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
Set the coefficient of result to the maximum value allowed by ctx->prec.
The function can fail with MPD_Malloc_error
.
From 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; /* 0 for positive and 1 for negative */
uint64_t hi; /* ((uint128_t)hi << 64) + lo is the coefficient */
uint64_t lo;
int64_t exp; /* exponent */
} mpd_uint128_triple_t;
int mpd_from_uint128_triple(mpd_t *result, const mpd_uint128_triple_t *triple, uint32_t *status);
Create a decimal from a triple. The following rules must be observed for initializing the triple:
sign
must always be 0 (for positive) or 1 (for negative).MPD_TRIPLE_QNAN
:exp
must be 0. Ifhi
orlo
are nonzero, create aNaN
with a payload.MPD_TRIPLE_SNAN
:exp
must be 0. Ifhi
orlo
are nonzero, create ansNaN
with a payload.MPD_TRIPLE_INF
:exp
,hi
andlo
must be zero.MPD_TRIPLE_NORMAL
:MPD_MIN_ETINY + 38 < exp < MPD_MAX_EMAX - 38
.hi
andlo
can be chosen freely.MPD_TRIPLE_ERROR
: It is always an error to set this tag.
If one of the above conditions is not met, the function sets
MPD_Invalid_operation
and result is NaN
.
Additionally, though extremely unlikely given the small allocation sizes,
the function can set MPD_Malloc_error
.
New in version 2.5.1.
Create Static Decimal¶
From Integer¶
void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,
uint32_t *status);
void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
/* 64-bit build only */
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);
Set result from a C integer type. The context is respected. result must be a static decimal, see section Advanced Memory Handling.
Convert Decimal¶
To String¶
char *mpd_to_sci(const mpd_t *dec, int fmt);
char *mpd_to_eng(const mpd_t *dec, int fmt);
mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
Return the scientific or engineering string representation of a decimal.
This operation is not context sensitive. If fmt is zero, the exponent
character is lower case, otherwise it is upper case. If allocating memory
for the string fails, NULL
is returned.
New in version 2.4.0: mpd_to_sci_size
and mpd_to_eng_size
additionally return the
size of the result string, without counting the terminating NUL.
The goal is to avoid an unnecessary call to strlen
.
char *mpd_qformat(const mpd_t *dec, const char *fmt,
const mpd_context_t *ctx, uint32_t *status);
char *mpd_format(const mpd_t *dec, const char *fmt,
mpd_context_t *ctx);
Return the string representation of a decimal according to format string fmt.
The format string syntax is the same as in Python PEP 3101 (See Standard Format
Specifiers) and is quite similar to the syntax used for floating point numbers
the C fprintf
function. The fill character may be a UTF-8 character,
the rest of the format string must be ASCII.
The function can fail with MPD_Invalid_operation
for an invalid format
string or MPD_Malloc_error
. In both cases, the return value is
NULL
.
If the “n” format specifier is used, the function calls localeconv
.
Two cases must be considered:
The locale is set at the start of the program and does not change. In this case, calls to
localeconv
should be thread-safe.setlocale
is called after threads are started. In this case, depending on the guarantees of the system’slocaleconv
, the entire sequence ofsetlocale
andmpd_qformat
requires a lock.
All other format specifiers are thread-safe.
New in version 4.0.0: Support for the “z” format specifier, which coerces negative zeros to positive.
To Integer¶
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_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);
int32_t mpd_qget_i32(const mpd_t *a, uint32_t *status);
uint32_t mpd_qget_u32(const mpd_t *a, 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);
uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
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);
Convert a decimal to a C integer type. If the decimal is not an integer or
its value is outside the range of the C type, MPD_SSIZE_MAX
is
returned for signed types and MPD_UINT_MAX
for unsigned types. In
this case, the status is set to MPD_Invalid_operation
. Since a
decimal can have the values MPD_SSIZE_MAX
or MPD_UINT_MAX
,
the only reliable way to check for errors is to check the status.
mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
Return the absolute of numbers in the range [-MPD_UINT_MAX
, MPD_UINT_MAX
].
Error handling as above.
New in version 2.4.0: All functions are available in both the 64-bit and the 32-bit builds.
To 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; /* 0 for positive and 1 for negative */
uint64_t hi; /* ((uint128_t)hi << 64) + lo is the coefficient */
uint64_t lo;
int64_t exp; /* exponent */
} mpd_uint128_triple_t;
mpd_uint128_triple_t mpd_as_uint128_triple(const mpd_t *a);
Convert a decimal with up to 38 decimal digits to a triple.
For simplicity, the usage of the function and all special cases are explained in code form and comments:
triple = mpd_as_uint128_triple(dec);
switch (triple.tag) {
case MPD_TRIPLE_QNAN:
/*
* Success: handle a quiet NaN.
* 1) sign is 0 or 1.
* 2) exp is always 0.
* 3) If hi or lo are nonzero, the NaN has a payload.
*/
break;
case MPD_TRIPLE_SNAN:
/*
* Success: handle a signaling NaN.
* 1) sign is 0 or 1.
* 2) exp is always 0.
* 3) If hi or lo are nonzero, the sNaN has a payload.
*/
break;
case MPD_TRIPLE_INF:
/*
* Success: handle Infinity.
* 1) sign is 0 or 1.
* 2) exp is always 0.
* 3) hi and lo are always zero.
*/
break;
case MPD_TRIPLE_NORMAL:
/* Success: handle a finite value. */
break;
case MPD_TRIPLE_ERROR:
/* The coefficient is too large for conversion. Handle the error. */
break;
}
New in version 2.5.1.
Copy Decimal¶
int mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status);
void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
Set result to the value of a and return 1 for success. On failure,
return 0 and add MPD_Malloc_error
to status.
mpd_t *mpd_qncopy(const mpd_t *a);
Return a pointer to a fresh copy of a, NULL
on failure.
int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
Set result to the value of a with the sign set to 0. If successful,
return 1. Otherwise, return 0 and add MPD_Malloc_error
to status.
int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
Set result to the value of a with the sign inverted. If successful,
return 1. Otherwise, return 0 and add MPD_Malloc_error
to status.
int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b,
uint32_t *status);
void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b,
mpd_context_t *ctx);
Set result to the value of a, using the sign of b. If successful,
return 1. Otherwise, return 0 and add MPD_Malloc_error
to status.
Print Decimal¶
void mpd_fprint(FILE *file, const mpd_t *dec);
void mpd_print(const mpd_t *dec);
Print a decimal with a trailing newline to FILE or to stdout. These functions are mostly useful for debugging.
Print Status Flags¶
int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags,
const char *flag_string[]);
int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags,
const char *signal_string[]);
mpd_snprint_flags
prints the conditions contained in flags
- separated by spaces - to the buffer dest with size nmemb. nmemb
must be at least MPD_MAX_FLAG_STRING
.
mpd_lsnprint_flags
prints the conditions contained in flags as
a comma separated list to the buffer dest with size nmemb. nmemb
must be at least MPD_MAX_FLAG_LIST
.
mpd_lsnprint_signals
prints signals contained in flags as
a comma separated list to the buffer dest with size nmemb. nmemb
must be at least MPD_MAX_SIGNAL_LIST
.
The result string is always NUL
terminated. The return value of
both functions is the number of characters printed, without the NUL
terminator. On failure, -1 is returned.