reactos/sdk/lib/crt/math/arm/__fto64.h
Roman Masanin be3c532bf4
[ARM/CRT] Refactor several functions (#3865)
- Make __fto64 function more readable
- Call worker function directly for __rt_sdiv/udiv
- Adapt __rt_sdiv64/udiv64 asm shims accordingly
- Add header files to CMake source list

CORE-17607 CORE-17614 CORE-17703 CORE-17604

Addendum to f2bc1f0e, e448094e and 54406bf4.
2021-07-31 11:24:03 +03:00

105 lines
2.2 KiB
C

/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Float to integer conversion (__dtoi64/dtou64/stoi64/stou64)
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#ifdef _USE_64_BITS_
typedef double FLOAT_TYPE;
typedef unsigned long long FINT_TYPE;
#define FRACTION_LEN 52
#define EXPONENT_LEN 11
#else
typedef float FLOAT_TYPE;
typedef unsigned int FINT_TYPE;
#define FRACTION_LEN 23
#define EXPONENT_LEN 8
#endif
typedef
#ifndef _USE_SIGNED_
unsigned
#endif
long long FTO64_RESULT;
typedef union _FTO64_UNION
{
FLOAT_TYPE value;
FINT_TYPE raw;
} FTO64_UNION;
#define SIGN_MASK (((FINT_TYPE)1) << (FRACTION_LEN + EXPONENT_LEN))
#define FRACTION_ONE (((FINT_TYPE)1) << FRACTION_LEN)
#define FRACTION_MASK ((FRACTION_ONE) - 1)
#define EXPONENT_MASK ((1 << EXPONENT_LEN) - 1)
#define EXPONENT_ZERO ((1 << (EXPONENT_LEN - 1)) - 1)
#ifdef _USE_SIGNED_
#define EXPONENT_MAX 62
#define INTNAN 0x8000000000000000ULL
#else
#define EXPONENT_MAX 63
#define INTNAN 0xFFFFFFFFFFFFFFFFULL
#endif
#define EXPONENT_INFINITY EXPONENT_MASK
#define NEGATE(x) (~(x) + 1)
FTO64_RESULT
__fto64(FLOAT_TYPE fvalue)
{
FTO64_UNION u = { .value = fvalue };
FINT_TYPE value = u.raw;
int exponent;
FTO64_RESULT fraction;
exponent = (int)(value >> FRACTION_LEN);
exponent &= EXPONENT_MASK;
/* infinity and other NaNs */
if (exponent == EXPONENT_INFINITY)
return INTNAN;
/* subnormals and signed zeros */
if (exponent == 0)
return 0;
exponent -= EXPONENT_ZERO;
/* number is less then one */
if (exponent < 0)
return 0;
/* number is too big */
if (exponent > EXPONENT_MAX)
return INTNAN;
#ifndef _USE_SIGNED_
if (value & SIGN_MASK)
return INTNAN;
#endif
fraction = value & FRACTION_MASK;
fraction |= FRACTION_ONE;
exponent -= FRACTION_LEN;
if (exponent != 0)
{
if (exponent < 0)
fraction = fraction >> NEGATE(exponent);
else
fraction = fraction << exponent;
}
#ifdef _USE_SIGNED_
if (value & SIGN_MASK)
fraction = NEGATE(fraction);
#endif
return fraction;
}