Implicit thread local context

extern Context context_template;  /* template for new thread local contexts */

#if defined(__OpenBSD__) || defined(__sun) || defined(_MSC_VER) && defined(_DLL)
/* Each translation unit gets its own static reference to the thread local
   context.  The semantics should be identical to the regular C++11 extern
   thread local context below. */
IMPORTEXPORT Context& getcontext();
static thread_local Context& context{getcontext()};
extern thread_local Context context;  /* thread local context */

Most functions use a context. If the context is not passed explicitly as an argument, the implicit thread local context is used.

For new threads context is initialized automatically from context_template. context_template itself can be set to user defined values at program startup.

Context class

class Context
Context(mpd_ssize_t prec=context_template.prec(),
        mpd_ssize_t emax=context_template.emax(),
        mpd_ssize_t emin=context_template.emin(),
        int round=context_template.round(),
        uint32_t traps=context_template.traps(),
        int clamp=context_template.clamp(),
        int allcr=context_template.allcr());

Default constructor. Values that are not explicitly given are initialized from context_template.

Context(const Context& c) noexcept;

Copy constructor. This is just C struct assignment.

Context(const Context&& c) noexcept;

Move constructor. This is just C struct assignment.

explicit Context(const mpd_context_t &c) noexcept;

Construct from an mpd_t context.

Context& operator= (const Context& c) noexcept;

Copy the context. This is just C struct assignment.

Context& operator= (const Context&& c) noexcept;

Move the context. This is just C struct assignment.

bool operator== (const Context& other) const noexcept;

Determine if self == other.

bool operator!= (const Context& other) const noexcept;

Determine if self != other.

mpd_context_t *get();

Return a pointer to the underlying mpd_t context.

const mpd_context_t *getconst() const;

Return a const pointer to the underlying mpd_t context.

mpd_ssize_t prec() const;

Return the internal prec field.

mpd_ssize_t emax() const;

Return the internal emax field.

mpd_ssize_t emin() const;

Return the internal emin field.

int round() const;

Return the internal round field.

uint32_t status() const;

Return the internal status field.

uint32_t traps() const;

Return the internal traps field.

int clamp() const;

Return the internal clamp field.

int allcr() const;

Return the internal allcr field.

void prec(mpd_ssize_t v);

Set the internal prec field.

void emax(mpd_ssize_t v);

Set the internal emax field.

void emin(mpd_ssize_t v);

Set the internal emin field.

void round(int v);

Set the internal round field.

void status(uint32_t v);

Set the internal status field.

void traps(uint32_t v);

Set the internal traps field.

void clamp(int v);

Set the internal clamp field.

void allcr(int v);

Set the internal allcr field.

void raise(uint32_t flags);

Add flags to the internal status field and raise a signal if the respective traps are set.

void add_status(uint32_t flags);

Add selected flags to the status. This is only used when working with several temporary contexts and the flags need to be merged into a single one.

void clear_status();

Clear all status flags.

void clear_status(uint32_t flags);

Clear the selected status flags.

void add_traps(uint32_t flags);

Add the selected traps.

void clear_traps();

Clear all traps.

void clear_traps(uint32_t flags);

Clear the selected traps.

std::string repr() const;

Return a human readable representation of the context.

friend std::ostream& operator<<(std::ostream& os, const Context& c);

The stream operator uses repr.

Factory functions

Context MaxContext();

Return a context with maximum values for emax, emin and prec. Used when computations must be exact and unrounded under all circumstances.

You still need to check for DecRounded and DecInexact or set the respective traps.

/* common arguments */
constexpr int DECIMAL32 = MPD_DECIMAL32;
constexpr int DECIMAL64 = MPD_DECIMAL64;
constexpr int DECIMAL128 = MPD_DECIMAL128;

/* maximum argument value */

IEEEContext(int bits);

Return a context initialized to the proper values for one of the IEEE interchange formats. The argument must be a multiple of 32 and less than IEEE_CONTEXT_MAX_BITS. For the most common values, the constants DECIMAL32, DECIMAL64 and DECIMAL128 are provided.

TLS context caveats

These TLS issues are not specific to libmpdec++, but deserve to be mentioned.

Main thread

On Linux/FreeBSD/OpenBSD automatic initialization of context on first access also works for the main thread. However, this is not guaranteed by the standard, so context should be initialized explicitly if it is used in the main thread.