BSON-XS
view release on metacpan or search on metacpan
bson/bson-decimal128.c view on Meta::CPAN
*/
static void
_bson_uint128_divide1B (_bson_uint128_t value, /* IN */
_bson_uint128_t *quotient, /* OUT */
uint32_t *rem) /* OUT */
{
const uint32_t DIVISOR = 1000 * 1000 * 1000;
uint64_t _rem = 0;
int i = 0;
if (!value.parts[0] && !value.parts[1] &&
!value.parts[2] && !value.parts[3]) {
*quotient = value;
*rem = 0;
return;
}
for (i = 0; i <= 3; i++) {
_rem <<= 32; /* Adjust remainder to match value of next dividend */
_rem += value.parts[i]; /* Add the divided to _rem */
value.parts[i] = (uint32_t)(_rem / DIVISOR);
_rem %= DIVISOR; /* Store the remainder */
}
*quotient = value;
*rem = _rem;
}
/**
*------------------------------------------------------------------------------
*
* bson_decimal128_to_string --
*
* This function converts a BID formatted decimal128 value to string,
* accepting a &bson_decimal128_t as @dec. The string is stored at @str.
*
* @dec : The BID formatted decimal to convert.
* @str : The output decimal128 string. At least %BSON_DECIMAL128_STRING characters.
*
* Returns:
* None.
*
* Side effects:
* None.
*
*------------------------------------------------------------------------------
*/
void
bson_decimal128_to_string (const bson_decimal128_t *dec, /* IN */
char *str) /* OUT */
{
uint32_t COMBINATION_MASK = 0x1f; /* Extract least significant 5 bits */
uint32_t EXPONENT_MASK = 0x3fff; /* Extract least significant 14 bits */
uint32_t COMBINATION_INFINITY = 30; /* Value of combination field for Inf */
uint32_t COMBINATION_NAN = 31; /* Value of combination field for NaN */
uint32_t EXPONENT_BIAS = 6176; /* decimal128 exponent bias */
char *str_out = str; /* output pointer in string */
char significand_str[35]; /* decoded significand digits */
/* Note: bits in this routine are referred to starting at 0, */
/* from the sign bit, towards the coefficient. */
uint32_t high; /* bits 0 - 31 */
uint32_t midh; /* bits 32 - 63 */
uint32_t midl; /* bits 64 - 95 */
uint32_t low; /* bits 96 - 127 */
uint32_t combination; /* bits 1 - 5 */
uint32_t biased_exponent; /* decoded biased exponent (14 bits) */
uint32_t significand_digits = 0; /* the number of significand digits */
uint32_t significand[36] = { 0 }; /* the base-10 digits in the significand */
uint32_t *significand_read = significand; /* read pointer into significand */
int32_t exponent; /* unbiased exponent */
int32_t scientific_exponent; /* the exponent if scientific notation is
* used */
bool is_zero = false; /* true if the number is zero */
uint8_t significand_msb; /* the most signifcant significand bits (50-46) */
_bson_uint128_t significand128; /* temporary storage for significand decoding */
size_t i; /* indexing variables */
int j, k;
memset (significand_str, 0, sizeof (significand_str));
if ((int64_t)dec->high < 0) { /* negative */
*(str_out++) = '-';
}
low = (uint32_t)dec->low,
midl = (uint32_t)(dec->low >> 32),
midh = (uint32_t)dec->high,
high = (uint32_t)(dec->high >> 32);
/* Decode combination field and exponent */
combination = (high >> 26) & COMBINATION_MASK;
if (BSON_UNLIKELY ((combination >> 3) == 3)) {
/* Check for 'special' values */
if (combination == COMBINATION_INFINITY) { /* Infinity */
strcpy (str_out, "Inf");
return;
} else if (combination == COMBINATION_NAN) { /* NaN */
/* str, not str_out, to erase the sign */
strcpy (str, "NaN");
/* we don't care about the NaN payload. */
return;
} else {
biased_exponent = (high >> 15) & EXPONENT_MASK;
significand_msb = 0x8 + ((high >> 14) & 0x1);
}
} else {
significand_msb = (high >> 14) & 0x7;
biased_exponent = (high >> 17) & EXPONENT_MASK;
}
exponent = biased_exponent - EXPONENT_BIAS;
/* Create string of significand digits */
/* Convert the 114-bit binary number represented by */
/* (high, midh, midl, low) to at most 34 decimal */
/* digits through modulo and division. */
significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
significand128.parts[1] = midh;
significand128.parts[2] = midl;
significand128.parts[3] = low;
if (significand128.parts[0] == 0 && significand128.parts[1] == 0 &&
significand128.parts[2] == 0 && significand128.parts[3] == 0) {
is_zero = true;
( run in 1.195 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )