# 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. If `hi` or `lo` are nonzero, create a `NaN` with a payload.
- `MPD_TRIPLE_SNAN`: `exp` must be 0. If `hi` or `lo` are nonzero, create an `sNaN` with a payload.
- `MPD_TRIPLE_INF`: `exp`, `hi` and `lo` must be zero.
- `MPD_TRIPLE_NORMAL`: `MPD_MIN_ETINY + 38 < exp < MPD_MAX_EMAX - 38`. `hi` and `lo` 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 give 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`. Depending on the guarantees of the system’s `localeconv`, calls to `mpd_qformat` may require a lock.

All other format specifiers are thread-safe.

### 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.