Implement RtlGetBaseExponent() routine for getting base(10) exponent of a given floating point value

This commit is contained in:
Rafal Kupiec 2024-02-14 00:02:04 +01:00
parent c096c5d6df
commit 55fb9e2eb1
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
6 changed files with 126 additions and 0 deletions

View File

@ -17,6 +17,11 @@
#define GUID_STRING_LENGTH 38
#define PARTUUID_STRING_LENGTH 13
/* Floating point definitions */
#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL
#define DOUBLE_EXPONENT_SHIFT 0x34
#define DOUBLE_EXPONENT_BIAS 0x3FF
/* Runtime Library routine callbacks */
typedef VOID (*PWRITE_CHARACTER)(IN CHAR Character);
typedef VOID (*PWRITE_WIDE_CHARACTER)(IN WCHAR Character);

View File

@ -163,6 +163,18 @@ typedef struct _FLOAT128
LONGLONG HighPart;
} FLOAT128, *PFLOAT128;
/* 64-bit floating point union */
typedef union _LARGE_DOUBLE
{
struct
{
ULONG LowPart;
ULONG HighPart;
} u;
DOUBLE DoublePart;
ULONGLONG QuadPart;
} LARGE_DOUBLE, *PLARGE_DOUBLE;
/* 64-bit signed integer union */
typedef union _LARGE_INTEGER
{

View File

@ -41,6 +41,7 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/po/idle.c
${XTOSKRNL_SOURCE_DIR}/rtl/atomic.c
${XTOSKRNL_SOURCE_DIR}/rtl/byteswap.c
${XTOSKRNL_SOURCE_DIR}/rtl/globals.c
${XTOSKRNL_SOURCE_DIR}/rtl/guid.c
${XTOSKRNL_SOURCE_DIR}/rtl/ioreg.c
${XTOSKRNL_SOURCE_DIR}/rtl/math.c

View File

@ -255,6 +255,11 @@ RtlDivideUnsigned64(IN ULONGLONG Dividend,
IN ULONGLONG Divisor,
OUT PULONGLONG Remainder);
XTAPI
LONG
RtlGetBaseExponent(IN DOUBLE Value,
OUT PDOUBLE PowerOfTen);
XTCDECL
VOID
RtlInitializeListHead(IN PLIST_ENTRY ListHead);

13
xtoskrnl/rtl/globals.c Normal file
View File

@ -0,0 +1,13 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/rtl/globals.c
* DESCRIPTION: Kernel runtime library global variables
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtos.h>
/* This is required for floating numbers to keep LLVM happy */
int _fltused = 0xFEEDBULL;

View File

@ -510,6 +510,96 @@ RtlDivideLargeInteger(IN LARGE_INTEGER Dividend,
return LargeInt;
}
/**
* Gets the base exponent of a given floating point value.
*
* @param Value
* Supplies the floating point value to get the base exponent of.
*
* @param PowerOfTen
* Supplies a pointer that receives the power of ten associated with the base exponent.
*
* @return This routine returns the base exponent value.
*
* @since XT 1.0
*/
XTAPI
LONG
RtlGetBaseExponent(IN DOUBLE Value,
OUT PDOUBLE PowerOfTen)
{
LONG BaseExponent, CurrentExponent, Exponent;
ULONG ExponentShift, ExponentMask;
LARGE_DOUBLE Parts;
DOUBLE Power;
/* Calculate the exponent mask and shift */
ExponentMask = DOUBLE_EXPONENT_MASK >> (sizeof(ULONG) * BITS_PER_BYTE);
ExponentShift = DOUBLE_EXPONENT_SHIFT - (sizeof(ULONG) * BITS_PER_BYTE);
/* Check if value is zero */
if(Value == 0.0)
{
/* Return the power of ten and the exponent */
*PowerOfTen = 1.0;
return 0;
}
/* Get the parts of the value and calculate the exponent by multiplying by log10(2) */
Parts.DoublePart = Value;
BaseExponent = ((Parts.u.HighPart & ExponentMask) >> ExponentShift) - DOUBLE_EXPONENT_BIAS;
Exponent = (LONG)((DOUBLE)BaseExponent * 0.30102999566) + 1;
/* Set the initial values and calculate the exponent */
CurrentExponent = 0;
Power = 1.0;
if(Exponent > 0)
{
/* Calculate the exponent */
while(CurrentExponent + 10 <= Exponent)
{
Power *= 0.0000000001;
CurrentExponent += 10;
}
while(CurrentExponent + 1 <= Exponent)
{
Power *= 0.1;
CurrentExponent += 1;
}
}
else
{
/* Calculate the exponent */
while(CurrentExponent - 10 >= Exponent)
{
Power *= 10000000000;
CurrentExponent -= 10;
}
while(CurrentExponent - 1 >= Exponent)
{
Power *= 10.0;
CurrentExponent -= 1;
}
}
/* Normalize input value */
Value *= Power;
/* Remove all leading zeros, if any */
while((Value != 0.0) && ((LONG)Value == 0))
{
Value *= 10.0;
Exponent -= 1;
Power *= 10.0;
}
/* Return the power of ten and the exponent */
*PowerOfTen = Power;
return Exponent;
}
/**
* Multiplies a signed large integer by a signed integer.
*