/** * \file decInfinite.h * \author Lifepillar * \copyright Copyright (c) 2019 Lifepillar. * This program is free software; you can redistribute it and/or * modify it under the terms of the Simplified BSD License (also * known as the "2-Clause License" or "FreeBSD License".) * \copyright This program is distributed in the hope that it will be useful, * but without any warranty; without even the implied warranty of * merchantability or fitness for a particular purpose. * * \brief Decimal Infinite public interface */ #include "autoconfig.h" #if !defined(DECINFINITE) #define DECINFINITE #define DECINF_NAME "decInfinite" /**< Short name. */ #define DECINF_FULLNAME "Decimal Infinite Module" /**< Full name. */ #define DECINF_AUTHOR "Lifepillar" /**< Who to bl… praise. */ #if HAVE_LITTLE_ENDIAN #define DECLITEND 1 /**< 1=little-endian, 0=big-endian. */ #else #define DECLITEND 0 #endif #ifndef DECNUMDIGITS /** * \brief Maximum number of digits that a decNumber can have. * * \note #DECNUMDIGITS **must** be a multiple of three, because before * encoding a decNumber its digits may be shifted towards the most * significant unit (and, correspondingly, trailing zeroes may be added) * so that each #Unit contains three digits. * * \note According to decNumber's manual, the theoretical upper limit for this * constant is 999,999,999. Given the way #DECINF_MAXSIZE is defined, * however, the maximum allowed value is "only" 99,999,999. */ #define DECNUMDIGITS 39 #endif #if DECNUMDIGITS < 3 #error DECNUMDIGITS must be at least 3 #endif #if DECNUMDIGITS % 3 != 0 #error DECNUMDIGITS must be a multiple of 3 #endif #ifndef DECINF_EXPSIZE /** * \brief Maximum size of the absolute value of an adjusted exponent, in bits. * * This must be at least 5 and no greater than 30. The lower bound is * determined by the fact that this implementation must be able to pack at * least those exponents that fit in one byte (i.e., 5 bits, once the bits for * the sign and padding are factored out). The upper limit depends on the fact * that the adjusted exponent of a decNumber must be in * [-999,999,999,999,999,999]. */ #define DECINF_EXPSIZE 30 #endif #if DECINF_EXPSIZE < 5 #error DECINF_EXPSIZE must be at least 5 #endif /** * \brief Maximum size of a Decimal Infinite encoded number, in bytes. * * The encoding consists of: * * - `2` bits for the sign; * - `1` bit of padding (unused); * - At most `2 * #DECINF_EXPSIZE - 1` bits for the encoded exponent (sign and * value); * - At most `10 * #DECNUMDIGITS / 3` bits for the mantissa. * * The number is rounded up to the nearest integer. */ #define DECINF_MAXSIZE (1 + (2 + 1 + (2 * DECINF_EXPSIZE - 1) + (10 * DECNUMDIGITS / 3) - 1) / 8) #include "decNumber/decNumber.h" #include "decNumber/decNumberLocal.h" #if DECDPUN != 3 #error decInfinite assumes DECDPUN == 3 #endif /** * \brief Encodes a decNumber into a stream of bytes. * * \param len The length of the output stream of bytes * \param result The output stream of bytes * \param decnum The input number * * \return The size of the result, in bytes * * \note This function does not check for buffer overflows; rather, it assumes * that the output buffer is large enough to hold the encoded number. * The maximum space an encoded number can use is #DECINF_MAXSIZE * bytes. This function also assumes that the exponent of the input * number is within the valid range (adjusted exponent in * [-999,999,999,999,999,999]). * * \note The input number is **modified** by this function. If you need to use * the number after invoking this function, **make a copy first.** */ size_t decInfiniteFromNumber(size_t len, uint8_t result[len], decNumber* decnum); /** * \brief Decodes a Decimal Infinite byte stream into a \c decNumber. * * \param len The number of bytes of the encoded number * \param bytes The encoded number * \param decnum The output decNumber * * \return \a decnum unless a decoding error occurs, in which case the returned * value is `0`. */ decNumber* decInfiniteToNumber(size_t len, uint8_t const bytes[len], decNumber* decnum); /** * \brief Determines whether an encoded number is special. * * A special number is any of `-Inf`, `+Inf`, or `NaN`. * * \param len The number of bytes of the encoded number * \param bytes The encoded number * * \return `1` if the number is recognized as a special number; `0` otherwise. */ int decInfiniteIsSpecial(size_t len, uint8_t const bytes[len]); /** * \brief Returns the sign of an encoded decimal. * * The sign is returned also for special numbers. * * \param bytes A non-null pointer to the encoded number * * \return `1` if the sign is positive, `-1` if the sign is negative. */ int decInfiniteSign(uint8_t const* bytes); /** * \brief Returns the exponent of a decimal. * * \param len The number of bytes of the encoded decimal number * \param bytes The encoded decimal number * * \return The adjusted exponent of the decimal, i.e., the exponent of the * number when expressed in scientific notation. If the decimal is * a special number (`-NaN`, `-Inf`, `+Inf`, `+NaN`), the returned * value is `-2^#DECINF_EXPSIZE` or `+2^#DECINF_EXPSIZE` (i.e., an * out-of-range exponent). * */ int32_t decInfiniteExponent(size_t len, uint8_t const bytes[len]); /** * \brief Returns the significand of a decimal as a string. * * \param len The number of bytes of the encoded number * \param bytes The encoded number * \param significand The output buffer: this is assumed to have enough space * to hold the coefficient, i.e., at most `#DECNUMDIGITS + 2` bytes * (#DECNUMDIGITS digits, a dot, the string terminator). * * \return \a significand, or `0` if a decoding error occurs. * * TODO: return the mantissa as a decInfinite integer instead? */ char* decInfiniteCoefficient(size_t len, uint8_t const bytes[len], char* significand); /** * \brief Returns an encoded number as a hexadecimal string. * * This function is meant mostly for debugging (or for fun). * * \param len The number of bytes of the encoded number * \param bytes The encoded number * \param hexes A non-null pointer to a buffer for the output string. This * function asssumes that the buffer has enough space, which is at * most `3 * #DECINF_MAXSIZE` bytes. * * \return \a hexes unless \a len exceeds #DECINF_MAXSIZE, in which case the * returned value is `0`. */ char* decInfiniteToBytes(size_t len, uint8_t const bytes[len], char* hexes); /** * \brief Returns an encoded number as a formatted string of bits. * * This function is meant mostly for debugging (or for fun). * * \param len The number of bytes of the encoded number * \param bytes The encoded number * \param bitstring A non-null pointer to a buffer for the output string. This * must have enough space for the output string, which is at most * (approximately) `#DECINF_MAXSIZE * 9 + 1` bytes. * * \return \a bitstring unless \a len exceeds #DECINF_MAXSIZE, in which case * the returned value is `0`. */ char* decInfiniteToBits(size_t len, uint8_t const bytes[len], char* bitstring); #endif