Files
Run-Sun3-SunOS-4.1.1/tme-0.8_up/ic/ieee754/ieee754-misc-auto.c
Amberelle Mason ac30ff9032 Initial import
Initial import of SunOS 4.1.1 and TME 0.8
2023-05-01 12:16:40 -04:00

2404 lines
89 KiB
C

/* automatically generated by ieee754-misc-auto.sh, do not edit! */
#include <tme/common.h>
_TME_RCSID("$Id: ieee754-misc-auto.sh,v 1.6 2007/08/24 01:05:43 fredette Exp $");
#include <tme/ic/ieee754.h>
#include "softfloat-tme.h"
#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
/* this converts a value from IEEE 754 single precision format
to the builtin C type that is the best match for that format: */
tme_ieee754_single_builtin_t
tme_ieee754_single_value_to_builtin(const tme_uint32_t *x_ieee754)
{
tme_ieee754_single_builtin_t x_builtin;
tme_uint32_t exponent;
tme_uint32_t sign;
tme_uint32_t chunk;
tme_uint32_t fracor;
/* get x's biased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU((*x_ieee754), ((tme_uint32_t) 0x7f800000));
/* convert the fraction one 16-bit chunk at a time, and track
a bitwise-or of all of the fraction bits: */
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754), 0x007f0000);
fracor = chunk;
/* if the exponent is nonzero, add the implicit integer bit: */
if (exponent != 0) chunk |= ((0x007f0000 / _TME_FIELD_MASK_FACTOR(0x007f0000)) + 1);
x_builtin = chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754), 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
/* get x's sign bit: */
sign = ((*x_ieee754) & (((tme_uint32_t) 0x7f800000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000))));
/* if the exponent is the biased maximum, x is either an infinity or a NaN: */
if (exponent == (((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000)))) {
/* if the fraction is nonzero, x is a NaN. x must not be a NaN,
because we were supposed to catch this earlier: */
assert (fracor == 0);
/* x is an infinity. construct a builtin infinity: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_infinity_float
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_infinity_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_infinity_long_double
#endif
(sign);
}
/* if the exponent is the biased minimum and the fraction is
all-bits-zero, x is a zero: */
else if (exponent == 0
&& fracor == 0) {
/* construct a builtin zero: */
x_builtin =
(sign ?
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_negative_zero_float()
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_negative_zero_double()
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_negative_zero_long_double()
#endif
: 0.0);
}
/* otherwise, x is an in-range value that needs to be converted: */
else {
/* scale the result by the unbiased exponent, adjusted by the
number of fraction bits (which are currently to the left of the
floating point in x_builtin): */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, (exponent - ((((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000))) >> 1)) - 23);
if (sign) {
x_builtin = 0 - x_builtin;
}
}
/* done: */
return (x_builtin);
}
/* this converts a value from the builtin C type that is the best
match for the IEEE 754 single precision format, to that
format: */
const tme_uint32_t *
tme_ieee754_single_value_from_builtin(tme_ieee754_single_builtin_t x_builtin, tme_uint32_t *x_ieee754)
{
tme_int32_t exponent;
tme_uint32_t chunk;
tme_ieee754_single_builtin_t x_builtin_buffer;
const tme_ieee754_single_builtin_t pzero_builtin = +0.0;
/* x must not be a NaN or an infinity: */
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
assert (!isnanf(x_builtin));
assert (!isinff(x_builtin));
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#endif
/* get the mantissa and exponent of x: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_mantissa_exponent_float
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_mantissa_exponent_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_mantissa_exponent_long_double
#endif
(x_builtin, &exponent);
/* zero the IEEE 754 version: */
memset((char *) x_ieee754, 0, sizeof((*x_ieee754)));
/* if x is positive or negative zero: */
if (x_builtin == 0
|| -x_builtin == 0) {
/* set x's sign bit if x is not positive zero: */
memcpy((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin));
x_builtin_buffer = x_builtin;
if (x_builtin < 0
|| memcmp((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin)) != 0) {
(*x_ieee754) |= (((tme_uint32_t) 0x7f800000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000)));
}
/* return the zero: */
return (x_ieee754);
}
/* set x's sign bit: */
if (x_builtin < 0) {
(*x_ieee754) |= (((tme_uint32_t) 0x7f800000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000)));
x_builtin = -x_builtin;
}
/* bias the exponent: */
exponent += ((((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000))) >> 1);
/* if the biased exponent is greater than or equal to the biased
maximum, we must represent x as an infinity: */
if (exponent >= (tme_int32_t) (((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000)))) {
/* we do this by just setting the biased exponent to the biased
maximum: */
exponent = (((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000)));
}
/* otherwise, x will be either a normalized number, a denormalized
number, or possibly a zero: */
else {
/* if the biased exponent is less than or equal to the biased
minimum, x will be a denormalized number (possibly so
denormalized that it becomes a zero): */
if (exponent <= 0) {
/* scale x into a denormalized number: */
assert (x_builtin >= 1);
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, exponent - 1);
assert (x_builtin < 1);
exponent = 0;
}
/* convert the mantissa, one 16-bit chunk at a time: */
/* remove any implicit integer bit: */
if (x_builtin >= 1) {
x_builtin -= 1;
}
x_builtin = x_builtin * ((0x007f0000 / _TME_FIELD_MASK_FACTOR(0x007f0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754), 0x007f0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754), 0x0000ffff, chunk);
}
/* set x's biased exponent: */
TME_FIELD_MASK_DEPOSITU((*x_ieee754), ((tme_uint32_t) 0x7f800000), exponent);
/* done: */
return (x_ieee754);
}
/* this does a NaN check for an IEEE 754 single precision monadic function: */
int
tme_ieee754_single_check_nan_monadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, struct tme_float *dst)
{
const tme_uint32_t *nan0;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_single_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_SINGLE);
nan0 = &src0->tme_float_value_ieee754_single;
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_single)
(ieee754_ctl, nan0, nan0, &dst->tme_float_value_ieee754_single);
return (TRUE);
}
return (FALSE);
}
/* this does a NaN check for an IEEE 754 single precision dyadic function: */
int
tme_ieee754_single_check_nan_dyadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
const tme_uint32_t *nan0;
const tme_uint32_t *nan1;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_single_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_SINGLE);
nan0 = &src0->tme_float_value_ieee754_single;
}
nan1 = nan0;
if (tme_ieee754_single_is_nan(src1)) {
assert (src1->tme_float_format == TME_FLOAT_FORMAT_IEEE754_SINGLE);
nan1 = &src1->tme_float_value_ieee754_single;
if (nan0 == NULL) {
nan0 = nan1;
}
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_single)
(ieee754_ctl, nan0, nan1, &dst->tme_float_value_ieee754_single);
return (TRUE);
}
return (FALSE);
}
/* this converts a tme_uint32_t to a single: */
void
tme_ieee754_single_from_int32(tme_uint32_t src, struct tme_float *dst)
{
_tme_ieee754_single_value_set(dst, float32, int32_to_float32(src));
}
#if defined(TME_HAVE_INT64_T)
/* this converts a tme_uint64_t to a single: */
void
tme_ieee754_single_from_int64(tme_uint64_t src, struct tme_float *dst)
{
_tme_ieee754_single_value_set(dst, float32, int64_to_float32(src));
}
#endif /* defined(TME_HAVE_INT64_T) */
/* this converts an in-range IEEE 754 single precision value into its
radix 2 mantissa and exponent. the mantissa is either zero, or
in the range [1,2): */
void
tme_ieee754_single_radix2_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_single_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_single_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
_mantissa->tme_float_value_ieee754_single = ieee754_ctl->tme_ieee754_ctl_default_nan_single;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* extract the unbiased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU(src->tme_float_value_ieee754_single, ((tme_uint32_t) 0x7f800000));
exponent -= ((((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000))) >> 1);
/* the mantissa is the source with a biased zero for the exponent: */
*_mantissa = *src;
TME_FIELD_MASK_DEPOSITU(_mantissa->tme_float_value_ieee754_single, ((tme_uint32_t) 0x7f800000), ((((tme_uint32_t) 0x7f800000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7f800000))) >> 1));
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_single_value_set(_exponent, float32, int32_to_float32(exponent));
}
}
/* this scales an IEEE 754 single precision value by adding n to its
radix 2 exponent: */
void
tme_ieee754_single_radix2_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
tme_uint32_t src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
float32 * const value = (float32 *) &dst->tme_float_value_ieee754_single;
struct tme_float constant_buffer;
const float32 * const constant = (float32 *) &constant_buffer.tme_float_value_ieee754_single;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_single_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_single_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
dst->tme_float_value_ieee754_single = ieee754_ctl->tme_ieee754_ctl_default_nan_single;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_single_is_zero(src1)
|| tme_ieee754_single_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = float32_to_int32(*((const float32 *) tme_ieee754_single_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 single format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix2_scale_float(tme_ieee754_single_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix2_scale_double(tme_ieee754_single_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix2_scale_long_double(tme_ieee754_single_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_single_value_set(dst, *tme_ieee754_single_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_single_constant_2e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_2e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float32_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_2e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float32_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_2e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts an in-range IEEE 754 single precision value into its
radix 10 mantissa and exponent. the mantissa is either zero, or
in the range [1,10): */
void
tme_ieee754_single_radix10_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0)
tme_uint32_t value_ieee754_buffer;
struct tme_float value_buffer;
struct tme_float zero_buffer;
struct tme_float one_buffer;
struct tme_float constant_buffer;
struct tme_float radix_buffer;
float32 * const value = (float32 *) &value_buffer.tme_float_value_ieee754_single;
const float32 * const zero = (float32 *) &zero_buffer.tme_float_value_ieee754_single;
const float32 * const one = (float32 *) &one_buffer.tme_float_value_ieee754_single;
const float32 * const constant = (float32 *) &constant_buffer.tme_float_value_ieee754_single;
const float32 * const radix = (float32 *) &radix_buffer.tme_float_value_ieee754_single;
tme_uint32_t exponent_bit;
int negate;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_single_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_single_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
_mantissa->tme_float_value_ieee754_single = ieee754_ctl->tme_ieee754_ctl_default_nan_single;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if a builtin type matches the IEEE 754 single format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_single_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_mantissa_exponent_float(tme_ieee754_single_value_builtin_get(src), &exponent));
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_single_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_mantissa_exponent_double(tme_ieee754_single_value_builtin_get(src), &exponent));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_single_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_mantissa_exponent_long_double(tme_ieee754_single_value_builtin_get(src), &exponent));
#else
/* get this value and some constants: */
tme_ieee754_single_value_set(&value_buffer, *tme_ieee754_single_value_get(src, &value_ieee754_buffer));
tme_ieee754_single_value_set_constant(&zero_buffer, &tme_ieee754_single_constant_zero);
tme_ieee754_single_value_set_constant(&one_buffer, &tme_ieee754_single_constant_one);
tme_ieee754_single_value_set_constant(&radix_buffer, &tme_ieee754_single_constant_10e2ex[0]);
/* take the magnitude of the value, but remember if it was negative: */
negate = float32_lt(*value, *zero);
if (negate) {
*value = float32_sub(*zero, *value);
}
/* start with an exponent of zero: */
exponent = 0;
/* if the value is nonzero: */
if (!float32_eq(*value, *zero)) {
/* while the value is less than one: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_single_constant_10e_minus_2ex) - 1;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e_minus_2ex[exponent_bit]);
for (; float32_lt(*value, *one); ) {
/* if value is less than or equal to 10^-(2^exponent_bit),
divide value by 10^-(2^exponent_bit), and subtract 2^exponent_bit
from exponent: */
if (float32_le(*value, *constant)
|| exponent_bit == 0) {
*value = float32_div(*value, *constant);
exponent -= (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e_minus_2ex[exponent_bit]);
}
}
/* while the value is greater than 10: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_single_constant_10e2ex) - 1;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e2ex[exponent_bit]);
for (; !(float32_le(*value, *radix)) ; ) {
/* if value is greater than or equal to 10^(2^exponent_bit),
divide value by 10^(2^exponent_bit), and add 2^exponent_bit
to exponent: */
if (!(float32_lt(*value, *constant))
|| exponent_bit == 0) {
*value = float32_div(*value, *constant);
exponent += (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e2ex[exponent_bit]);
}
}
/* if the value was originally negative, negate the mantissa: */
if (negate) {
*value = float32_sub(*zero, *value);
}
/* return the mantissa: */
_tme_ieee754_single_value_set(_mantissa, float32, *value);
}
#endif
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_single_value_set(_exponent, float32, int32_to_float32(exponent));
}
}
/* this scales an IEEE 754 single precision value by adding n to its
radix 10 exponent: */
void
tme_ieee754_single_radix10_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
tme_uint32_t src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
float32 * const value = (float32 *) &dst->tme_float_value_ieee754_single;
struct tme_float constant_buffer;
const float32 * const constant = (float32 *) &constant_buffer.tme_float_value_ieee754_single;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_SINGLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_single_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_single_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
dst->tme_float_value_ieee754_single = ieee754_ctl->tme_ieee754_ctl_default_nan_single;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_single_is_zero(src1)
|| tme_ieee754_single_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = float32_to_int32(*((const float32 *) tme_ieee754_single_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 single format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_scale_float(tme_ieee754_single_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_scale_double(tme_ieee754_single_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_SINGLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_single_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_scale_long_double(tme_ieee754_single_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_single_value_set(dst, *tme_ieee754_single_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_single_constant_10e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float32_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float32_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_single_value_set_constant(&constant_buffer, &tme_ieee754_single_constant_10e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts a value from IEEE 754 double precision format
to the builtin C type that is the best match for that format: */
tme_ieee754_double_builtin_t
tme_ieee754_double_value_to_builtin(const union tme_value64 *x_ieee754)
{
tme_ieee754_double_builtin_t x_builtin;
tme_uint32_t exponent;
tme_uint32_t sign;
tme_uint32_t chunk;
tme_uint32_t fracor;
/* get x's biased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_value64_uint32_hi, ((tme_uint32_t) 0x7ff00000));
/* convert the fraction one 16-bit chunk at a time, and track
a bitwise-or of all of the fraction bits: */
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_value64_uint32_hi, 0x000f0000);
fracor = chunk;
/* if the exponent is nonzero, add the implicit integer bit: */
if (exponent != 0) chunk |= ((0x000f0000 / _TME_FIELD_MASK_FACTOR(0x000f0000)) + 1);
x_builtin = chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_value64_uint32_hi, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_value64_uint32_lo, 0xffff0000);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_value64_uint32_lo, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
/* get x's sign bit: */
sign = ((*x_ieee754).tme_value64_uint32_hi & (((tme_uint32_t) 0x7ff00000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000))));
/* if the exponent is the biased maximum, x is either an infinity or a NaN: */
if (exponent == (((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000)))) {
/* if the fraction is nonzero, x is a NaN. x must not be a NaN,
because we were supposed to catch this earlier: */
assert (fracor == 0);
/* x is an infinity. construct a builtin infinity: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_infinity_float
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_infinity_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_infinity_long_double
#endif
(sign);
}
/* if the exponent is the biased minimum and the fraction is
all-bits-zero, x is a zero: */
else if (exponent == 0
&& fracor == 0) {
/* construct a builtin zero: */
x_builtin =
(sign ?
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_negative_zero_float()
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_negative_zero_double()
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_negative_zero_long_double()
#endif
: 0.0);
}
/* otherwise, x is an in-range value that needs to be converted: */
else {
/* scale the result by the unbiased exponent, adjusted by the
number of fraction bits (which are currently to the left of the
floating point in x_builtin): */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, (exponent - ((((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000))) >> 1)) - 52);
if (sign) {
x_builtin = 0 - x_builtin;
}
}
/* done: */
return (x_builtin);
}
/* this converts a value from the builtin C type that is the best
match for the IEEE 754 double precision format, to that
format: */
const union tme_value64 *
tme_ieee754_double_value_from_builtin(tme_ieee754_double_builtin_t x_builtin, union tme_value64 *x_ieee754)
{
tme_int32_t exponent;
tme_uint32_t chunk;
tme_ieee754_double_builtin_t x_builtin_buffer;
const tme_ieee754_double_builtin_t pzero_builtin = +0.0;
/* x must not be a NaN or an infinity: */
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
assert (!isnanf(x_builtin));
assert (!isinff(x_builtin));
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#endif
/* get the mantissa and exponent of x: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_mantissa_exponent_float
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_mantissa_exponent_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_mantissa_exponent_long_double
#endif
(x_builtin, &exponent);
/* zero the IEEE 754 version: */
memset((char *) x_ieee754, 0, sizeof((*x_ieee754)));
/* if x is positive or negative zero: */
if (x_builtin == 0
|| -x_builtin == 0) {
/* set x's sign bit if x is not positive zero: */
memcpy((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin));
x_builtin_buffer = x_builtin;
if (x_builtin < 0
|| memcmp((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin)) != 0) {
(*x_ieee754).tme_value64_uint32_hi |= (((tme_uint32_t) 0x7ff00000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000)));
}
/* return the zero: */
return (x_ieee754);
}
/* set x's sign bit: */
if (x_builtin < 0) {
(*x_ieee754).tme_value64_uint32_hi |= (((tme_uint32_t) 0x7ff00000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000)));
x_builtin = -x_builtin;
}
/* bias the exponent: */
exponent += ((((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000))) >> 1);
/* if the biased exponent is greater than or equal to the biased
maximum, we must represent x as an infinity: */
if (exponent >= (tme_int32_t) (((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000)))) {
/* we do this by just setting the biased exponent to the biased
maximum: */
exponent = (((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000)));
}
/* otherwise, x will be either a normalized number, a denormalized
number, or possibly a zero: */
else {
/* if the biased exponent is less than or equal to the biased
minimum, x will be a denormalized number (possibly so
denormalized that it becomes a zero): */
if (exponent <= 0) {
/* scale x into a denormalized number: */
assert (x_builtin >= 1);
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, exponent - 1);
assert (x_builtin < 1);
exponent = 0;
}
/* convert the mantissa, one 16-bit chunk at a time: */
/* remove any implicit integer bit: */
if (x_builtin >= 1) {
x_builtin -= 1;
}
x_builtin = x_builtin * ((0x000f0000 / _TME_FIELD_MASK_FACTOR(0x000f0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_value64_uint32_hi, 0x000f0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_value64_uint32_hi, 0x0000ffff, chunk);
x_builtin = x_builtin * ((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_value64_uint32_lo, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_value64_uint32_lo, 0x0000ffff, chunk);
}
/* set x's biased exponent: */
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_value64_uint32_hi, ((tme_uint32_t) 0x7ff00000), exponent);
/* done: */
return (x_ieee754);
}
/* this does a NaN check for an IEEE 754 double precision monadic function: */
int
tme_ieee754_double_check_nan_monadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, struct tme_float *dst)
{
const union tme_value64 *nan0;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_double_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_DOUBLE);
nan0 = &src0->tme_float_value_ieee754_double;
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_double)
(ieee754_ctl, nan0, nan0, &dst->tme_float_value_ieee754_double);
return (TRUE);
}
return (FALSE);
}
/* this does a NaN check for an IEEE 754 double precision dyadic function: */
int
tme_ieee754_double_check_nan_dyadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
const union tme_value64 *nan0;
const union tme_value64 *nan1;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_double_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_DOUBLE);
nan0 = &src0->tme_float_value_ieee754_double;
}
nan1 = nan0;
if (tme_ieee754_double_is_nan(src1)) {
assert (src1->tme_float_format == TME_FLOAT_FORMAT_IEEE754_DOUBLE);
nan1 = &src1->tme_float_value_ieee754_double;
if (nan0 == NULL) {
nan0 = nan1;
}
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_double)
(ieee754_ctl, nan0, nan1, &dst->tme_float_value_ieee754_double);
return (TRUE);
}
return (FALSE);
}
/* this converts a tme_uint32_t to a double: */
void
tme_ieee754_double_from_int32(tme_uint32_t src, struct tme_float *dst)
{
_tme_ieee754_double_value_set(dst, float64, int32_to_float64(src));
}
#if defined(TME_HAVE_INT64_T)
/* this converts a tme_uint64_t to a double: */
void
tme_ieee754_double_from_int64(tme_uint64_t src, struct tme_float *dst)
{
_tme_ieee754_double_value_set(dst, float64, int64_to_float64(src));
}
#endif /* defined(TME_HAVE_INT64_T) */
/* this converts an in-range IEEE 754 double precision value into its
radix 2 mantissa and exponent. the mantissa is either zero, or
in the range [1,2): */
void
tme_ieee754_double_radix2_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_double_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_double_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
_mantissa->tme_float_value_ieee754_double = ieee754_ctl->tme_ieee754_ctl_default_nan_double;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* extract the unbiased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU(src->tme_float_value_ieee754_double.tme_value64_uint32_hi, ((tme_uint32_t) 0x7ff00000));
exponent -= ((((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000))) >> 1);
/* the mantissa is the source with a biased zero for the exponent: */
*_mantissa = *src;
TME_FIELD_MASK_DEPOSITU(_mantissa->tme_float_value_ieee754_double.tme_value64_uint32_hi, ((tme_uint32_t) 0x7ff00000), ((((tme_uint32_t) 0x7ff00000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7ff00000))) >> 1));
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_double_value_set(_exponent, float64, int32_to_float64(exponent));
}
}
/* this scales an IEEE 754 double precision value by adding n to its
radix 2 exponent: */
void
tme_ieee754_double_radix2_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
union tme_value64 src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
float64 * const value = (float64 *) &dst->tme_float_value_ieee754_double;
struct tme_float constant_buffer;
const float64 * const constant = (float64 *) &constant_buffer.tme_float_value_ieee754_double;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_double_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_double_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
dst->tme_float_value_ieee754_double = ieee754_ctl->tme_ieee754_ctl_default_nan_double;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_double_is_zero(src1)
|| tme_ieee754_double_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = float64_to_int32(*((const float64 *) tme_ieee754_double_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 double format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix2_scale_float(tme_ieee754_double_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix2_scale_double(tme_ieee754_double_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix2_scale_long_double(tme_ieee754_double_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_double_value_set(dst, *tme_ieee754_double_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_double_constant_2e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_2e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float64_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_2e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float64_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_2e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts an in-range IEEE 754 double precision value into its
radix 10 mantissa and exponent. the mantissa is either zero, or
in the range [1,10): */
void
tme_ieee754_double_radix10_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0)
union tme_value64 value_ieee754_buffer;
struct tme_float value_buffer;
struct tme_float zero_buffer;
struct tme_float one_buffer;
struct tme_float constant_buffer;
struct tme_float radix_buffer;
float64 * const value = (float64 *) &value_buffer.tme_float_value_ieee754_double;
const float64 * const zero = (float64 *) &zero_buffer.tme_float_value_ieee754_double;
const float64 * const one = (float64 *) &one_buffer.tme_float_value_ieee754_double;
const float64 * const constant = (float64 *) &constant_buffer.tme_float_value_ieee754_double;
const float64 * const radix = (float64 *) &radix_buffer.tme_float_value_ieee754_double;
tme_uint32_t exponent_bit;
int negate;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_double_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_double_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
_mantissa->tme_float_value_ieee754_double = ieee754_ctl->tme_ieee754_ctl_default_nan_double;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if a builtin type matches the IEEE 754 double format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_double_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_mantissa_exponent_float(tme_ieee754_double_value_builtin_get(src), &exponent));
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_double_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_mantissa_exponent_double(tme_ieee754_double_value_builtin_get(src), &exponent));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_double_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_mantissa_exponent_long_double(tme_ieee754_double_value_builtin_get(src), &exponent));
#else
/* get this value and some constants: */
tme_ieee754_double_value_set(&value_buffer, *tme_ieee754_double_value_get(src, &value_ieee754_buffer));
tme_ieee754_double_value_set_constant(&zero_buffer, &tme_ieee754_double_constant_zero);
tme_ieee754_double_value_set_constant(&one_buffer, &tme_ieee754_double_constant_one);
tme_ieee754_double_value_set_constant(&radix_buffer, &tme_ieee754_double_constant_10e2ex[0]);
/* take the magnitude of the value, but remember if it was negative: */
negate = float64_lt(*value, *zero);
if (negate) {
*value = float64_sub(*zero, *value);
}
/* start with an exponent of zero: */
exponent = 0;
/* if the value is nonzero: */
if (!float64_eq(*value, *zero)) {
/* while the value is less than one: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_double_constant_10e_minus_2ex) - 1;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e_minus_2ex[exponent_bit]);
for (; float64_lt(*value, *one); ) {
/* if value is less than or equal to 10^-(2^exponent_bit),
divide value by 10^-(2^exponent_bit), and subtract 2^exponent_bit
from exponent: */
if (float64_le(*value, *constant)
|| exponent_bit == 0) {
*value = float64_div(*value, *constant);
exponent -= (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e_minus_2ex[exponent_bit]);
}
}
/* while the value is greater than 10: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_double_constant_10e2ex) - 1;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e2ex[exponent_bit]);
for (; !(float64_le(*value, *radix)) ; ) {
/* if value is greater than or equal to 10^(2^exponent_bit),
divide value by 10^(2^exponent_bit), and add 2^exponent_bit
to exponent: */
if (!(float64_lt(*value, *constant))
|| exponent_bit == 0) {
*value = float64_div(*value, *constant);
exponent += (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e2ex[exponent_bit]);
}
}
/* if the value was originally negative, negate the mantissa: */
if (negate) {
*value = float64_sub(*zero, *value);
}
/* return the mantissa: */
_tme_ieee754_double_value_set(_mantissa, float64, *value);
}
#endif
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_double_value_set(_exponent, float64, int32_to_float64(exponent));
}
}
/* this scales an IEEE 754 double precision value by adding n to its
radix 10 exponent: */
void
tme_ieee754_double_radix10_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
union tme_value64 src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
float64 * const value = (float64 *) &dst->tme_float_value_ieee754_double;
struct tme_float constant_buffer;
const float64 * const constant = (float64 *) &constant_buffer.tme_float_value_ieee754_double;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_DOUBLE) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_double_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_double_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
dst->tme_float_value_ieee754_double = ieee754_ctl->tme_ieee754_ctl_default_nan_double;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_double_is_zero(src1)
|| tme_ieee754_double_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = float64_to_int32(*((const float64 *) tme_ieee754_double_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 double format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_scale_float(tme_ieee754_double_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_scale_double(tme_ieee754_double_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_DOUBLE == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_double_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_scale_long_double(tme_ieee754_double_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_double_value_set(dst, *tme_ieee754_double_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_double_constant_10e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float64_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = float64_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_double_value_set_constant(&constant_buffer, &tme_ieee754_double_constant_10e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts a value from IEEE 754 extended80 precision format
to the builtin C type that is the best match for that format: */
tme_ieee754_extended80_builtin_t
tme_ieee754_extended80_value_to_builtin(const struct tme_float_ieee754_extended80 *x_ieee754)
{
tme_ieee754_extended80_builtin_t x_builtin;
tme_uint32_t exponent;
tme_uint32_t sign;
tme_uint32_t chunk;
tme_uint32_t fracor;
/* get x's biased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_extended80_sexp, ((tme_uint32_t) 0x7fff));
/* convert the fraction one 16-bit chunk at a time, and track
a bitwise-or of all of the fraction bits: */
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_hi, 0xffff0000);
fracor = chunk;
/* if the exponent is the biased maximum, clear the explicit integer bit: */
if (exponent == (((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)))) fracor &= ~_TME_FIELD_MASK_MSBIT(0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000));
x_builtin = chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_hi, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_lo, 0xffff0000);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_lo, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
/* get x's sign bit: */
sign = ((*x_ieee754).tme_float_ieee754_extended80_sexp & (((tme_uint32_t) 0x7fff) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff))));
/* if the exponent is the biased maximum, x is either an infinity or a NaN: */
if (exponent == (((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)))) {
/* if the fraction is nonzero, x is a NaN. x must not be a NaN,
because we were supposed to catch this earlier: */
assert (fracor == 0);
/* x is an infinity. construct a builtin infinity: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_infinity_float
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_infinity_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_infinity_long_double
#endif
(sign);
}
/* if the exponent is the biased minimum and the fraction is
all-bits-zero, x is a zero: */
else if (exponent == 0
&& fracor == 0) {
/* construct a builtin zero: */
x_builtin =
(sign ?
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_negative_zero_float()
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_negative_zero_double()
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_negative_zero_long_double()
#endif
: 0.0);
}
/* otherwise, x is an in-range value that needs to be converted: */
else {
/* scale the result by the unbiased exponent, adjusted by the
number of fraction bits (which are currently to the left of the
floating point in x_builtin): */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, (exponent - ((((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff))) >> 1)) - 63);
if (sign) {
x_builtin = 0 - x_builtin;
}
}
/* done: */
return (x_builtin);
}
/* this converts a value from the builtin C type that is the best
match for the IEEE 754 extended80 precision format, to that
format: */
const struct tme_float_ieee754_extended80 *
tme_ieee754_extended80_value_from_builtin(tme_ieee754_extended80_builtin_t x_builtin, struct tme_float_ieee754_extended80 *x_ieee754)
{
tme_int32_t exponent;
tme_uint32_t chunk;
tme_ieee754_extended80_builtin_t x_builtin_buffer;
const tme_ieee754_extended80_builtin_t pzero_builtin = +0.0;
/* x must not be a NaN or an infinity: */
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
assert (!isnanf(x_builtin));
assert (!isinff(x_builtin));
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#endif
/* get the mantissa and exponent of x: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_mantissa_exponent_float
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_mantissa_exponent_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_mantissa_exponent_long_double
#endif
(x_builtin, &exponent);
/* zero the IEEE 754 version: */
memset((char *) x_ieee754, 0, sizeof((*x_ieee754)));
/* if x is positive or negative zero: */
if (x_builtin == 0
|| -x_builtin == 0) {
/* set x's sign bit if x is not positive zero: */
memcpy((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin));
x_builtin_buffer = x_builtin;
if (x_builtin < 0
|| memcmp((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin)) != 0) {
(*x_ieee754).tme_float_ieee754_extended80_sexp |= (((tme_uint32_t) 0x7fff) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)));
}
/* return the zero: */
return (x_ieee754);
}
/* set x's sign bit: */
if (x_builtin < 0) {
(*x_ieee754).tme_float_ieee754_extended80_sexp |= (((tme_uint32_t) 0x7fff) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)));
x_builtin = -x_builtin;
}
/* bias the exponent: */
exponent += ((((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff))) >> 1);
/* if the biased exponent is greater than or equal to the biased
maximum, we must represent x as an infinity: */
if (exponent >= (tme_int32_t) (((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)))) {
/* we do this by just setting the biased exponent to the biased
maximum: */
exponent = (((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff)));
}
/* otherwise, x will be either a normalized number, a denormalized
number, or possibly a zero: */
else {
/* if the biased exponent is less than or equal to the biased
minimum, x will be a denormalized number (possibly so
denormalized that it becomes a zero): */
if (exponent <= 0) {
/* scale x into a denormalized number: */
assert (x_builtin >= 1);
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, exponent - 1);
assert (x_builtin < 1);
exponent = 0;
}
/* convert the mantissa, one 16-bit chunk at a time: */
x_builtin = x_builtin * (((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1) / 2);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_hi, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_hi, 0x0000ffff, chunk);
x_builtin = x_builtin * ((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_lo, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_extended80_significand.tme_value64_uint32_lo, 0x0000ffff, chunk);
}
/* set x's biased exponent: */
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_extended80_sexp, ((tme_uint32_t) 0x7fff), exponent);
/* done: */
return (x_ieee754);
}
/* this does a NaN check for an IEEE 754 extended80 precision monadic function: */
int
tme_ieee754_extended80_check_nan_monadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, struct tme_float *dst)
{
const struct tme_float_ieee754_extended80 *nan0;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_extended80_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
nan0 = &src0->tme_float_value_ieee754_extended80;
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_extended80)
(ieee754_ctl, nan0, nan0, &dst->tme_float_value_ieee754_extended80);
return (TRUE);
}
return (FALSE);
}
/* this does a NaN check for an IEEE 754 extended80 precision dyadic function: */
int
tme_ieee754_extended80_check_nan_dyadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
const struct tme_float_ieee754_extended80 *nan0;
const struct tme_float_ieee754_extended80 *nan1;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_extended80_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
nan0 = &src0->tme_float_value_ieee754_extended80;
}
nan1 = nan0;
if (tme_ieee754_extended80_is_nan(src1)) {
assert (src1->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
nan1 = &src1->tme_float_value_ieee754_extended80;
if (nan0 == NULL) {
nan0 = nan1;
}
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_extended80)
(ieee754_ctl, nan0, nan1, &dst->tme_float_value_ieee754_extended80);
return (TRUE);
}
return (FALSE);
}
/* this converts a tme_uint32_t to a extended80: */
void
tme_ieee754_extended80_from_int32(tme_uint32_t src, struct tme_float *dst)
{
_tme_ieee754_extended80_value_set(dst, floatx80, int32_to_floatx80(src));
}
#if defined(TME_HAVE_INT64_T)
/* this converts a tme_uint64_t to a extended80: */
void
tme_ieee754_extended80_from_int64(tme_uint64_t src, struct tme_float *dst)
{
_tme_ieee754_extended80_value_set(dst, floatx80, int64_to_floatx80(src));
}
#endif /* defined(TME_HAVE_INT64_T) */
/* this converts an in-range IEEE 754 extended80 precision value into its
radix 2 mantissa and exponent. the mantissa is either zero, or
in the range [1,2): */
void
tme_ieee754_extended80_radix2_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_extended80_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_extended80_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
_mantissa->tme_float_value_ieee754_extended80 = ieee754_ctl->tme_ieee754_ctl_default_nan_extended80;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* extract the unbiased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU(src->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp, ((tme_uint32_t) 0x7fff));
exponent -= ((((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff))) >> 1);
/* the mantissa is the source with a biased zero for the exponent: */
*_mantissa = *src;
TME_FIELD_MASK_DEPOSITU(_mantissa->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp, ((tme_uint32_t) 0x7fff), ((((tme_uint32_t) 0x7fff) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff))) >> 1));
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_extended80_value_set(_exponent, floatx80, int32_to_floatx80(exponent));
}
}
/* this scales an IEEE 754 extended80 precision value by adding n to its
radix 2 exponent: */
void
tme_ieee754_extended80_radix2_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
struct tme_float_ieee754_extended80 src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
floatx80 * const value = (floatx80 *) &dst->tme_float_value_ieee754_extended80;
struct tme_float constant_buffer;
const floatx80 * const constant = (floatx80 *) &constant_buffer.tme_float_value_ieee754_extended80;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_extended80_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
dst->tme_float_value_ieee754_extended80 = ieee754_ctl->tme_ieee754_ctl_default_nan_extended80;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_extended80_is_zero(src1)
|| tme_ieee754_extended80_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = floatx80_to_int32(*((const floatx80 *) tme_ieee754_extended80_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 extended80 format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix2_scale_float(tme_ieee754_extended80_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix2_scale_double(tme_ieee754_extended80_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix2_scale_long_double(tme_ieee754_extended80_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_extended80_value_set(dst, *tme_ieee754_extended80_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_extended80_constant_2e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_2e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = floatx80_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_2e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = floatx80_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_2e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts an in-range IEEE 754 extended80 precision value into its
radix 10 mantissa and exponent. the mantissa is either zero, or
in the range [1,10): */
void
tme_ieee754_extended80_radix10_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
{
tme_int32_t exponent;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0)
struct tme_float_ieee754_extended80 value_ieee754_buffer;
struct tme_float value_buffer;
struct tme_float zero_buffer;
struct tme_float one_buffer;
struct tme_float constant_buffer;
struct tme_float radix_buffer;
floatx80 * const value = (floatx80 *) &value_buffer.tme_float_value_ieee754_extended80;
const floatx80 * const zero = (floatx80 *) &zero_buffer.tme_float_value_ieee754_extended80;
const floatx80 * const one = (floatx80 *) &one_buffer.tme_float_value_ieee754_extended80;
const floatx80 * const constant = (floatx80 *) &constant_buffer.tme_float_value_ieee754_extended80;
const floatx80 * const radix = (floatx80 *) &radix_buffer.tme_float_value_ieee754_extended80;
tme_uint32_t exponent_bit;
int negate;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_extended80_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if this is an infinity: */
if (tme_ieee754_extended80_is_inf(src)) {
/* return a NaN: */
_mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
_mantissa->tme_float_value_ieee754_extended80 = ieee754_ctl->tme_ieee754_ctl_default_nan_extended80;
if (_exponent != NULL) {
*_exponent = *_mantissa;
}
return;
}
/* if a builtin type matches the IEEE 754 extended80 format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_extended80_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_mantissa_exponent_float(tme_ieee754_extended80_value_builtin_get(src), &exponent));
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_extended80_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_mantissa_exponent_double(tme_ieee754_extended80_value_builtin_get(src), &exponent));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_extended80_value_builtin_set
(_mantissa,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_mantissa_exponent_long_double(tme_ieee754_extended80_value_builtin_get(src), &exponent));
#else
/* get this value and some constants: */
tme_ieee754_extended80_value_set(&value_buffer, *tme_ieee754_extended80_value_get(src, &value_ieee754_buffer));
tme_ieee754_extended80_value_set_constant(&zero_buffer, &tme_ieee754_extended80_constant_zero);
tme_ieee754_extended80_value_set_constant(&one_buffer, &tme_ieee754_extended80_constant_one);
tme_ieee754_extended80_value_set_constant(&radix_buffer, &tme_ieee754_extended80_constant_10e2ex[0]);
/* take the magnitude of the value, but remember if it was negative: */
negate = floatx80_lt(*value, *zero);
if (negate) {
*value = floatx80_sub(*zero, *value);
}
/* start with an exponent of zero: */
exponent = 0;
/* if the value is nonzero: */
if (!floatx80_eq(*value, *zero)) {
/* while the value is less than one: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_extended80_constant_10e_minus_2ex) - 1;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e_minus_2ex[exponent_bit]);
for (; floatx80_lt(*value, *one); ) {
/* if value is less than or equal to 10^-(2^exponent_bit),
divide value by 10^-(2^exponent_bit), and subtract 2^exponent_bit
from exponent: */
if (floatx80_le(*value, *constant)
|| exponent_bit == 0) {
*value = floatx80_div(*value, *constant);
exponent -= (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e_minus_2ex[exponent_bit]);
}
}
/* while the value is greater than 10: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_extended80_constant_10e2ex) - 1;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e2ex[exponent_bit]);
for (; !(floatx80_le(*value, *radix)) ; ) {
/* if value is greater than or equal to 10^(2^exponent_bit),
divide value by 10^(2^exponent_bit), and add 2^exponent_bit
to exponent: */
if (!(floatx80_lt(*value, *constant))
|| exponent_bit == 0) {
*value = floatx80_div(*value, *constant);
exponent += (1 << exponent_bit);
}
/* otherwise, move to the next exponent bit: */
else {
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e2ex[exponent_bit]);
}
}
/* if the value was originally negative, negate the mantissa: */
if (negate) {
*value = floatx80_sub(*zero, *value);
}
/* return the mantissa: */
_tme_ieee754_extended80_value_set(_mantissa, floatx80, *value);
}
#endif
/* return the exponent: */
if (_exponent != NULL) {
_tme_ieee754_extended80_value_set(_exponent, floatx80, int32_to_floatx80(exponent));
}
}
/* this scales an IEEE 754 extended80 precision value by adding n to its
radix 10 exponent: */
void
tme_ieee754_extended80_radix10_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
struct tme_float_ieee754_extended80 src_buffer;
tme_int8_t rounding_mode;
tme_int32_t _n;
#if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0)
tme_int32_t exponent;
tme_uint32_t exponent_bit, n;
floatx80 * const value = (floatx80 *) &dst->tme_float_value_ieee754_extended80;
struct tme_float constant_buffer;
const floatx80 * const constant = (floatx80 *) &constant_buffer.tme_float_value_ieee754_extended80;
#endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_EXTENDED80) == 0) */
/* check for a NaN operand: */
if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
return;
}
/* if the exponent is an infinity: */
if (tme_ieee754_extended80_is_inf(src1)) {
/* return a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
dst->tme_float_value_ieee754_extended80 = ieee754_ctl->tme_ieee754_ctl_default_nan_extended80;
return;
}
/* if the operand is a zero or an infinity: */
if (tme_ieee754_extended80_is_zero(src1)
|| tme_ieee754_extended80_is_inf(src1)) {
/* return the operand unchanged: */
*dst = *src0;
return;
}
/* truncate the exponent to an integer, using the round-to-zero mode: */
rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
_n = floatx80_to_int32(*((const floatx80 *) tme_ieee754_extended80_value_get(src1, &src_buffer)));
ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
/* if a builtin type matches the IEEE 754 extended80 format exactly,
use the corresponding mantissa-exponent function: */
#if (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_FLOAT)
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_FLOAT,
tme_float_radix10_scale_float(tme_ieee754_extended80_value_builtin_get(src0), _n));
#elif (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_DOUBLE)
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_DOUBLE,
tme_float_radix10_scale_double(tme_ieee754_extended80_value_builtin_get(src0), _n));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_EXTENDED80 == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_ieee754_extended80_value_builtin_set
(dst,
TME_FLOAT_FORMAT_LONG_DOUBLE,
tme_float_radix10_scale_long_double(tme_ieee754_extended80_value_builtin_get(src0), _n));
#else
/* start this value: */
tme_ieee754_extended80_value_set(dst, *tme_ieee754_extended80_value_get(src0, &src_buffer));
/* start with the most significant exponent bit: */
exponent_bit = TME_ARRAY_ELS(tme_ieee754_extended80_constant_10e2ex) - 1;
exponent = (1 << exponent_bit);
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e2ex[exponent_bit]);
/* if n is negative: */
if (_n < 0) {
for (n = 0 - _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = floatx80_div(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e2ex[exponent_bit]);
}
}
}
/* otherwise, n is positive: */
else {
for (n = _n; n > 0;) {
if (n >= exponent || exponent == 1) {
*value = floatx80_mul(*value, *constant);
n -= exponent;
}
else {
exponent >>= 1;
exponent_bit--;
tme_ieee754_extended80_value_set_constant(&constant_buffer, &tme_ieee754_extended80_constant_10e2ex[exponent_bit]);
}
}
}
#endif
}
/* this converts a value from IEEE 754 quad precision format
to the builtin C type that is the best match for that format: */
tme_ieee754_quad_builtin_t
tme_ieee754_quad_value_to_builtin(const struct tme_float_ieee754_quad *x_ieee754)
{
tme_ieee754_quad_builtin_t x_builtin;
tme_uint32_t exponent;
tme_uint32_t sign;
tme_uint32_t chunk;
tme_uint32_t fracor;
/* get x's biased exponent: */
exponent = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi, ((tme_uint32_t) 0x7fff0000));
/* convert the fraction one 16-bit chunk at a time, and track
a bitwise-or of all of the fraction bits: */
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi, 0x0000ffff);
fracor = chunk;
/* if the exponent is nonzero, add the implicit integer bit: */
if (exponent != 0) chunk |= ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
x_builtin = chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_lo, 0xffff0000);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_lo, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_hi, 0xffff0000);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_hi, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_lo, 0xffff0000);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_lo, 0x0000ffff);
fracor |= chunk;
x_builtin = (x_builtin * 65536) + chunk;
/* get x's sign bit: */
sign = ((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi & (((tme_uint32_t) 0x7fff0000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000))));
/* if the exponent is the biased maximum, x is either an infinity or a NaN: */
if (exponent == (((tme_uint32_t) 0x7fff0000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000)))) {
/* if the fraction is nonzero, x is a NaN. x must not be a NaN,
because we were supposed to catch this earlier: */
assert (fracor == 0);
/* x is an infinity. construct a builtin infinity: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_infinity_float
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_infinity_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_infinity_long_double
#endif
(sign);
}
/* if the exponent is the biased minimum and the fraction is
all-bits-zero, x is a zero: */
else if (exponent == 0
&& fracor == 0) {
/* construct a builtin zero: */
x_builtin =
(sign ?
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_negative_zero_float()
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_negative_zero_double()
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_negative_zero_long_double()
#endif
: 0.0);
}
/* otherwise, x is an in-range value that needs to be converted: */
else {
/* scale the result by the unbiased exponent, adjusted by the
number of fraction bits (which are currently to the left of the
floating point in x_builtin): */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, (exponent - ((((tme_uint32_t) 0x7fff0000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000))) >> 1)) - 112);
if (sign) {
x_builtin = 0 - x_builtin;
}
}
/* done: */
return (x_builtin);
}
/* this converts a value from the builtin C type that is the best
match for the IEEE 754 quad precision format, to that
format: */
const struct tme_float_ieee754_quad *
tme_ieee754_quad_value_from_builtin(tme_ieee754_quad_builtin_t x_builtin, struct tme_float_ieee754_quad *x_ieee754)
{
tme_int32_t exponent;
tme_uint32_t chunk;
tme_ieee754_quad_builtin_t x_builtin_buffer;
const tme_ieee754_quad_builtin_t pzero_builtin = +0.0;
/* x must not be a NaN or an infinity: */
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
assert (!isnanf(x_builtin));
assert (!isinff(x_builtin));
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
assert (!isnan(x_builtin));
assert (!isinf(x_builtin));
#endif
/* get the mantissa and exponent of x: */
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_mantissa_exponent_float
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_mantissa_exponent_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_mantissa_exponent_long_double
#endif
(x_builtin, &exponent);
/* zero the IEEE 754 version: */
memset((char *) x_ieee754, 0, sizeof((*x_ieee754)));
/* if x is positive or negative zero: */
if (x_builtin == 0
|| -x_builtin == 0) {
/* set x's sign bit if x is not positive zero: */
memcpy((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin));
x_builtin_buffer = x_builtin;
if (x_builtin < 0
|| memcmp((char *) &x_builtin_buffer, (char *) &pzero_builtin, sizeof(pzero_builtin)) != 0) {
(*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi |= (((tme_uint32_t) 0x7fff0000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000)));
}
/* return the zero: */
return (x_ieee754);
}
/* set x's sign bit: */
if (x_builtin < 0) {
(*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi |= (((tme_uint32_t) 0x7fff0000) + _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000)));
x_builtin = -x_builtin;
}
/* bias the exponent: */
exponent += ((((tme_uint32_t) 0x7fff0000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000))) >> 1);
/* if the biased exponent is greater than or equal to the biased
maximum, we must represent x as an infinity: */
if (exponent >= (tme_int32_t) (((tme_uint32_t) 0x7fff0000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000)))) {
/* we do this by just setting the biased exponent to the biased
maximum: */
exponent = (((tme_uint32_t) 0x7fff0000) / _TME_FIELD_MASK_FACTOR(((tme_uint32_t) 0x7fff0000)));
}
/* otherwise, x will be either a normalized number, a denormalized
number, or possibly a zero: */
else {
/* if the biased exponent is less than or equal to the biased
minimum, x will be a denormalized number (possibly so
denormalized that it becomes a zero): */
if (exponent <= 0) {
/* scale x into a denormalized number: */
assert (x_builtin >= 1);
x_builtin =
#if (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
tme_float_radix2_scale_float
#elif (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
tme_float_radix2_scale_double
#elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_QUAD_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
tme_float_radix2_scale_long_double
#endif
(x_builtin, exponent - 1);
assert (x_builtin < 1);
exponent = 0;
}
/* convert the mantissa, one 16-bit chunk at a time: */
/* remove any implicit integer bit: */
if (x_builtin >= 1) {
x_builtin -= 1;
}
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi, 0x0000ffff, chunk);
x_builtin = x_builtin * ((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_lo, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_lo, 0x0000ffff, chunk);
x_builtin = x_builtin * ((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_hi, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_hi, 0x0000ffff, chunk);
x_builtin = x_builtin * ((0xffff0000 / _TME_FIELD_MASK_FACTOR(0xffff0000)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_lo, 0xffff0000, chunk);
x_builtin = x_builtin * ((0x0000ffff / _TME_FIELD_MASK_FACTOR(0x0000ffff)) + 1);
chunk = x_builtin;
chunk -= (chunk > x_builtin);
x_builtin -= chunk;
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_lo.tme_value64_uint32_lo, 0x0000ffff, chunk);
}
/* set x's biased exponent: */
TME_FIELD_MASK_DEPOSITU((*x_ieee754).tme_float_ieee754_quad_hi.tme_value64_uint32_hi, ((tme_uint32_t) 0x7fff0000), exponent);
/* done: */
return (x_ieee754);
}
/* this does a NaN check for an IEEE 754 quad precision monadic function: */
int
tme_ieee754_quad_check_nan_monadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, struct tme_float *dst)
{
const struct tme_float_ieee754_quad *nan0;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_quad_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_QUAD);
nan0 = &src0->tme_float_value_ieee754_quad;
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_QUAD;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_quad)
(ieee754_ctl, nan0, nan0, &dst->tme_float_value_ieee754_quad);
return (TRUE);
}
return (FALSE);
}
/* this does a NaN check for an IEEE 754 quad precision dyadic function: */
int
tme_ieee754_quad_check_nan_dyadic(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
{
const struct tme_float_ieee754_quad *nan0;
const struct tme_float_ieee754_quad *nan1;
/* check for a NaN operand: */
nan0 = NULL;
if (tme_ieee754_quad_is_nan(src0)) {
assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_QUAD);
nan0 = &src0->tme_float_value_ieee754_quad;
}
nan1 = nan0;
if (tme_ieee754_quad_is_nan(src1)) {
assert (src1->tme_float_format == TME_FLOAT_FORMAT_IEEE754_QUAD);
nan1 = &src1->tme_float_value_ieee754_quad;
if (nan0 == NULL) {
nan0 = nan1;
}
}
/* if we have a NaN operand: */
if (__tme_predict_false(nan0 != NULL)) {
/* propagate a NaN: */
dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_QUAD;
(*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_quad)
(ieee754_ctl, nan0, nan1, &dst->tme_float_value_ieee754_quad);
return (TRUE);
}
return (FALSE);
}
/* this converts a tme_uint32_t to a quad: */
void
tme_ieee754_quad_from_int32(tme_uint32_t src, struct tme_float *dst)
{
_tme_ieee754_quad_value_set(dst, float128, int32_to_float128(src));
}
#if defined(TME_HAVE_INT64_T)
/* this converts a tme_uint64_t to a quad: */
void
tme_ieee754_quad_from_int64(tme_uint64_t src, struct tme_float *dst)
{
_tme_ieee754_quad_value_set(dst, float128, int64_to_float128(src));
}
#endif /* defined(TME_HAVE_INT64_T) */