From 55fb9e2eb179e36dd32a4d05d6d43bdec673e574 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Wed, 14 Feb 2024 00:02:04 +0100 Subject: [PATCH] Implement RtlGetBaseExponent() routine for getting base(10) exponent of a given floating point value --- sdk/xtdk/rtltypes.h | 5 +++ sdk/xtdk/xttypes.h | 12 ++++++ xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/rtli.h | 5 +++ xtoskrnl/rtl/globals.c | 13 ++++++ xtoskrnl/rtl/math.c | 90 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+) create mode 100644 xtoskrnl/rtl/globals.c diff --git a/sdk/xtdk/rtltypes.h b/sdk/xtdk/rtltypes.h index d3fe726..a7a23ec 100644 --- a/sdk/xtdk/rtltypes.h +++ b/sdk/xtdk/rtltypes.h @@ -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); diff --git a/sdk/xtdk/xttypes.h b/sdk/xtdk/xttypes.h index 9388b71..7bf5071 100644 --- a/sdk/xtdk/xttypes.h +++ b/sdk/xtdk/xttypes.h @@ -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 { diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 0fcc90a..8dc9b81 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -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 diff --git a/xtoskrnl/includes/rtli.h b/xtoskrnl/includes/rtli.h index 57f3b57..5408e37 100644 --- a/xtoskrnl/includes/rtli.h +++ b/xtoskrnl/includes/rtli.h @@ -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); diff --git a/xtoskrnl/rtl/globals.c b/xtoskrnl/rtl/globals.c new file mode 100644 index 0000000..c452dd5 --- /dev/null +++ b/xtoskrnl/rtl/globals.c @@ -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 + */ + +#include + + +/* This is required for floating numbers to keep LLVM happy */ +int _fltused = 0xFEEDBULL; diff --git a/xtoskrnl/rtl/math.c b/xtoskrnl/rtl/math.c index 94e6648..37944d0 100644 --- a/xtoskrnl/rtl/math.c +++ b/xtoskrnl/rtl/math.c @@ -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. *