Various Functions

Applying the Context

finalize

void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx,
                   uint32_t *status);
void mpd_finalize(mpd_t *result, mpd_context_t *ctx);

Apply ctx to result. This function performs checks the exponent limits and performs rounding. The following conditions can occur:

MPD_Clamped, MPD_Inexact, MPD_Overflow, MPD_Rounded, MPD_Subnormal, MPD_Underflow

NaN Handling

These functions are convenience functions that take care of the elaborate NaN handling rules. They are meant to be used at the beginning of composite functions.

check-nan

int mpd_qcheck_nan(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
                   uint32_t *status);
int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);

If a is NaN or sNaN, set result to qNaN, copy any payload, apply ctx to the payload and return 1. If a is sNaN, additionally set MPD_Invalid_operation.

Otherwise, result is undefined and the return value is 0.

check-nans

int mpd_qcheck_nans(mpd_t *result, const mpd_t *a, const mpd_t *b,
                    const mpd_context_t *ctx, uint32_t *status);
int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b,
                   mpd_context_t *ctx);

If either operand is NaN or sNaN, apply the precedence rules, set result to qNaN, copy any payload, apply ctx to the payload and return 1. If one of the operands is sNaN, additionally set MPD_Invalid_operation.

Otherwise, result is undefined and the return value is 0.

Shifting and Rotating

shift

void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b,
                const mpd_context_t *ctx, uint32_t *status);
void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b,
               mpd_context_t *ctx);

Set result to a shifted by b places. b must be in the range [-prec, prec]. A negative b indicates a right shift, a positive b a left shift. Digits that do not fit are discarded.

shiftn

void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                 const mpd_context_t *ctx, uint32_t *status);
void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                mpd_context_t *ctx);

Like mpd_qshift, only that the number of places is specified by a C integer type rather than a decimal. This function is not part of the specification.

shiftl

int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                uint32_t *status);
void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                mpd_context_t *ctx);

Set result to a, shifted by n places to the left. a must not be a special number. Digits are never discarded, so the coefficient of result might exceed prec. Return 1 on success. On failure, return 0 and add MPD_Malloc_error to status.

If n is negative or the result would have more than MPD_SSIZE_MAX digits, the behavior is undefined.

If result has more than MPD_MAX_PREC digits, not all functions are guaranteed to handle it correctly. However, there may be legitimate use cases, so mpd_qshiftl makes no attempt to prevent it.

This function is not part of the specification.

shiftr

mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                       uint32_t *status);
mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n,
                      mpd_context_t *ctx);

Set result to a, shifted by n places to the right. a must not be a special number. On success, return the digit relevant for rounding. On failure, return MPD_UINT_MAX and add MPD_Malloc_error to status.

If n is negative, the behavior is undefined.

This function is not part of the specification.

shiftr-inplace

mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n)

Like mpd_qshiftr, but shifts result in place. result must not be a special number. This function cannot fail.

rotate

void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b,
                 const mpd_context_t *ctx, uint32_t *status);
void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b,
                mpd_context_t *ctx);

Set result to a rotated by b places. b must be in the range [-prec, prec]. A negative b indicates a right rotation, a positive b a left rotation.

Logical Operations

Logical operands are finite numbers with a sign of 0, an exponent of 0 and a coefficient consisting only of ones and zeros.

and

void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b,
              const mpd_context_t *ctx, uint32_t *status);
void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b,
             mpd_context_t *ctx);

Set result to the digit-wise logical and of a and b.

or

void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b,
             const mpd_context_t *ctx, uint32_t *status);
void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b,
            mpd_context_t *ctx);

Set result to the digit-wise logical or of a and b.

xor

void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b,
              const mpd_context_t *ctx, uint32_t *status);
void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b,
             mpd_context_t *ctx);

Set result to the digit-wise logical xor of a and b.

invert

void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
                 uint32_t *status);
void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);

Set result to the digit-wise logical inversion of a.

Base Conversions

Functions for converting decimals to multi-precision integers and vice versa. Decimals that are exported must be integers.

Importing

void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata,
                     size_t srclen, uint8_t srcsign, uint32_t srcbase,
                     const mpd_context_t *ctx, uint32_t *status);
void mpd_import_u16(mpd_t *result, const uint16_t *srcdata,
                    size_t srclen, uint8_t srcsign, uint32_t srcbase,
                    mpd_context_t *ctx);

Convert a multi-precision integer at srcdata with base srcbase to a decimal. The least significant word is srcdata[0].

srcsign is MPD_POS for positive and MPD_NEG for negative, srclen the length of srcdata.

Valid bases are in the range 2 <= srcbase <= UINT16_MAX + 1.

void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata,
                     size_t srclen, uint8_t srcsign, uint32_t srcbase,
                     const mpd_context_t *ctx, uint32_t *status);
void mpd_import_u32(mpd_t *result, const uint32_t *srcdata,
                    size_t srclen, uint8_t srcsign, uint32_t base,
                    mpd_context_t *ctx);

Convert a multi-precision integer at srcdata with base srcbase to a decimal. The least significant word is srcdata[0].

srcsign is MPD_POS for positive and MPD_NEG for negative, srclen the length of srcdata.

Valid bases are in the range 2 <= srcbase <= UINT32_MAX.

Exporting

mpd_sizeinbase(const mpd_t *a, uint32_t base);

Return the number of words needed to represent a decimal when converted to base. The decimal must be an integer, results are undefined for non-integers.

size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,
                       const mpd_t *src, uint32_t *status);
size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,
                      const mpd_t *src, mpd_context_t *ctx);

Set *rdata to src, converted to a representation in base rbase. The least significant word of the result is rdata[0]. src must be an integer.

If rdata is NULL, space is allocated by the function and rlen is irrelevant. In case of an error the allocated storage is freed and rdata is set back to NULL.

If rdata is non-NULL, it MUST be allocated by one of libmpdec’s allocation functions and rlen MUST be correct. If necessary, the function will resize rdata. Resizing is slow and should not occur if rlen has been obtained by a call to mpd_sizeinbase. In case of an error the caller must free rdata.

Return value: In case of success, the length of the multi-precision integer in the new base, SIZE_MAX otherwise.

Valid bases are in the range 2 <= rbase <= UINT16_MAX + 1.

Changed in version 2.4.0: rdata is now resized if necessary.

size_t mpd_qexport_u32(uint32_t *rdata, size_t rlen, uint32_t rbase,
                       const mpd_t *src, uint32_t *status);
size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t rbase,
                      const mpd_t *src, mpd_context_t *ctx);

Set *rdata to src, converted to a representation in base rbase. The least significant word of the result is rdata[0]. src must be an integer.

If rdata is NULL, space is allocated by the function and rlen is irrelevant. In case of an error the allocated storage is freed and rdata is set back to NULL.

If rdata is non-NULL, it MUST be allocated by one of libmpdec’s allocation functions and rlen MUST be correct. If necessary, the function will resize rdata. Resizing is slow and should not occur if rlen has been obtained by a call to mpd_sizeinbase. In case of an error the caller must free rdata.

Return value: In case of success, the length of the multi-precision integer in the new base, SIZE_MAX otherwise.

Valid bases are in the range 2 <= rbase <= UINT32_MAX.

Changed in version 2.4.0: rdata is now resized if necessary.

Required Functions

The functions in this section are not needed for this implementation. They are provided for full compliance with the specification.

void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);

Same as mpd_copy.

int mpd_iscanonical(const mpd_t *dec);

Return 1, for compatibility with the standard.

long mpd_radix(void);

Return 10.

Library version

/* Macros defining the components of the version as integers. */
MPD_MAJOR_VERSION
MPD_MINOR_VERSION
MPD_MICRO_VERSION

/* Macro defining the complete version as a string. */
MPD_VERSION

const char *mpd_version(void);

Library version information. mpd_version returns the MPD_VERSION macro from the header that the library was compiled with.

New in version 2.4.0.