https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3aa3b3af560859ef97e1dfb24d1a2c1d88f3af1b
commit 3aa3b3af560859ef97e1dfb24d1a2c1d88f3af1b Author: Timo Kreuzer <timo.kreu...@reactos.org> AuthorDate: Sat May 29 19:40:30 2021 +0200 Commit: Timo Kreuzer <timo.kreu...@reactos.org> CommitDate: Fri Aug 26 00:44:46 2022 +0200 [CRT] Implement portable ceil/floor --- sdk/lib/crt/math/amd64/ceil.S | 55 ------------------------------- sdk/lib/crt/math/amd64/ceilf.S | 51 ----------------------------- sdk/lib/crt/math/amd64/floor.S | 41 ------------------------ sdk/lib/crt/math/amd64/floorf.S | 41 ------------------------ sdk/lib/crt/math/ceil.c | 65 +++++++++++++++++++++++++++++++++++++ sdk/lib/crt/math/floor.c | 71 +++++++++++++++++++++++++++++++++++++++++ sdk/lib/crt/math/math.cmake | 7 ++-- 7 files changed, 139 insertions(+), 192 deletions(-) diff --git a/sdk/lib/crt/math/amd64/ceil.S b/sdk/lib/crt/math/amd64/ceil.S deleted file mode 100644 index f88403e241c..00000000000 --- a/sdk/lib/crt/math/amd64/ceil.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of ceil - * FILE: lib/sdk/crt/math/amd64/ceil.S - * PROGRAMMER: Timo Kreuzer (timo.kreu...@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.inc> -#include <ksamd64.inc> - -/* CODE **********************************************************************/ -.code64 - -/* ceil(x) = - floor(-x) - */ -PUBLIC ceil -.PROC ceil - sub rsp, 16 - .ENDPROLOG - - /* Duplicate the bits into rax */ - movd rax, xmm0 - - /* Invert the sign bit */ - rol rax, 1 - xor al, 1 - ror rax, 1 - - /* Copy back to xmm0 */ - movd xmm0, rax - - /* Truncate xmm0 to integer (double precision) */ - cvttsd2si rcx, xmm0 - - /* Shift all bits to the right, keeping the sign bit */ - shr rax, 63 - - /* Substract the sign bit from the truncated value, so that - we get the correct result for negative values. */ - sub rcx, rax - - /* Now compensate for the previous negation */ - neg rcx - - /* Convert the result back to xmm0 (double precision) */ - cvtsi2sd xmm0, rcx - - add rsp, 16 - ret -.ENDP - -END diff --git a/sdk/lib/crt/math/amd64/ceilf.S b/sdk/lib/crt/math/amd64/ceilf.S deleted file mode 100644 index 6063ddb1d5e..00000000000 --- a/sdk/lib/crt/math/amd64/ceilf.S +++ /dev/null @@ -1,51 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of tan - * FILE: lib/sdk/crt/math/amd64/ceilf.S - * PROGRAMMER: Timo Kreuzer (timo.kreu...@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.inc> -#include <ksamd64.inc> - -/* CODE **********************************************************************/ -.code64 - -PUBLIC ceilf -FUNC ceilf - sub rsp, 16 - .ENDPROLOG - - /* Duplicate the bits into eax (zero exteneded to rax) */ - movd eax, xmm0 - - /* Invert the sign bit */ - xor eax, HEX(80000000) - - /* Copy back to xmm0 */ - movd xmm0, eax - - /* Truncate xmm0 to integer (single precision) */ - cvttss2si rcx, xmm0 - - /* Shift all bits to the right, keeping the sign bit */ - shr rax, 31 - - /* Add the sign bit from the truncated value, so that - we get the correct result for negative values. */ - add rcx, rax - - /* Now compensate for the previous negation */ - neg ecx - - /* Convert the result back to xmm0 (single precision) */ - cvtsi2ss xmm0, rcx - - add rsp, 16 - ret -ENDFUNC - -END diff --git a/sdk/lib/crt/math/amd64/floor.S b/sdk/lib/crt/math/amd64/floor.S deleted file mode 100644 index 95724686824..00000000000 --- a/sdk/lib/crt/math/amd64/floor.S +++ /dev/null @@ -1,41 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of floor - * FILE: lib/sdk/crt/math/amd64/floor.S - * PROGRAMMER: Timo Kreuzer (timo.kreu...@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.inc> - -/* CODE **********************************************************************/ -.code64 - -PUBLIC floor -FUNC floor - sub rsp, 16 - .ENDPROLOG - - /* Truncate xmm0 to integer (double precision) */ - cvttsd2si rcx, xmm0 - - /* Duplicate the bits into rax */ - movd rax, xmm0 - - /* Shift all bits to the right, keeping the sign bit */ - shr rax, 63 - - /* Substract the sign bit from the truncated value, so that - we get the correct result for negative values. */ - sub rcx, rax - - /* Convert the result back to xmm0 (double precision) */ - cvtsi2sd xmm0, rcx - - add rsp, 16 - ret -ENDFUNC - -END diff --git a/sdk/lib/crt/math/amd64/floorf.S b/sdk/lib/crt/math/amd64/floorf.S deleted file mode 100644 index 176c481ba4f..00000000000 --- a/sdk/lib/crt/math/amd64/floorf.S +++ /dev/null @@ -1,41 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of floorf - * FILE: lib/sdk/crt/math/amd64/floorf.S - * PROGRAMMER: Timo Kreuzer (timo.kreu...@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.inc> - -/* CODE **********************************************************************/ -.code64 - -PUBLIC floorf -FUNC floorf - sub rsp, 16 - .ENDPROLOG - - /* Truncate xmm0 to integer (single precision) */ - cvttss2si rcx, xmm0 - - /* Duplicate the bits into rax */ - movd eax, xmm0 - - /* Shift all bits to the right, keeping the sign bit */ - shr rax, 31 - - /* Substract the sign bit from the truncated value, so that - we get the correct result for negative values. */ - sub rcx, rax - - /* Convert the result back to xmm0 (single precision) */ - cvtsi2ss xmm0, rcx - - add rsp, 16 - ret -ENDFUNC - -END diff --git a/sdk/lib/crt/math/ceil.c b/sdk/lib/crt/math/ceil.c new file mode 100644 index 00000000000..f1b6ff8665d --- /dev/null +++ b/sdk/lib/crt/math/ceil.c @@ -0,0 +1,65 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Portable implementation of ceil + * COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreu...@reactos.org> + */ + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +#ifdef _MSC_VER +#pragma function(ceil) +#endif + +double +__cdecl +ceil(double x) +{ + /* Load the value as uint64 */ + unsigned long long u64 = *(unsigned long long*)&x; + + /* Check for NAN */ + if ((u64 & ~(1ULL << 63)) > 0x7FF0000000000000ull) + { + /* Set error bit */ + u64 |= 0x0008000000000000ull; + return *(double*)&u64; + } + + /* Check if x is positive */ + if ((u64 & (1ULL << 63)) == 0) + { + /* Check if it fits into an int64 */ + if (x < (double)_I64_MAX) + { + /* Cast to int64 to truncate towards 0. If this matches the + input, return it as is, otherwise add 1 */ + double y = (double)(long long)x; + return (x > y) ? y + 1 : y; + } + else + { + /* The exponent is larger than the fraction bits. + This means the number is already an integer. */ + return x; + } + } + else + { + /* Check if it fits into an int64 */ + if (x > (double)_I64_MIN) + { + /* Cast to int64 to truncate towards 0. */ + x = (double)(long long)x; + return (x == 0.) ? -0.0 : x; + } + else + { + /* The exponent is larger than the fraction bits. + This means the number is already an integer. */ + return x; + } + } +} diff --git a/sdk/lib/crt/math/floor.c b/sdk/lib/crt/math/floor.c new file mode 100644 index 00000000000..883105117d4 --- /dev/null +++ b/sdk/lib/crt/math/floor.c @@ -0,0 +1,71 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of floor + * COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreu...@reactos.org> + */ + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +#ifdef _MSC_VER +#pragma function(floor) +#endif + +double +__cdecl +floor(double x) +{ + /* Load the value as uint64 */ + unsigned long long u64 = *(unsigned long long*)&x; + + /* Check for NAN */ + if ((u64 & ~(1ULL << 63)) > 0x7FF0000000000000ull) + { + /* Set error bit */ + u64 |= 0x0008000000000000ull; + return *(double*)&u64; + } + + /* Check if x is positive */ + if ((u64 & (1ULL << 63)) == 0) + { + /* Check if it fits into an int64 */ + if (x < (double)_I64_MAX) + { + /* Just cast to int64, which will truncate towards 0, + which is what we want here.*/ + return (double)(long long)x; + } + else + { + /* The exponent is larger than the fraction bits. + This means the number is already an integer. */ + return x; + } + } + else + { + /* Check if it fits into an int64 */ + if (x > (double)_I64_MIN) + { + /* Check if it is -0 */ + if (x == -0.) + { + return -0.; + } + + /* Cast to int64 to truncate towards 0. If this matches the + input, return it as is, otherwise subtract 1 */ + double y = (double)(long long)x; + return (x == y) ? y : y - 1; + } + else + { + /* The exponent is larger than the fraction bits. + This means the number is already an integer. */ + return x; + } + } +} diff --git a/sdk/lib/crt/math/math.cmake b/sdk/lib/crt/math/math.cmake index 1f4a4d5da2a..7cc7a795447 100644 --- a/sdk/lib/crt/math/math.cmake +++ b/sdk/lib/crt/math/math.cmake @@ -53,18 +53,17 @@ if(ARCH STREQUAL "i386") ) elseif(ARCH STREQUAL "amd64") list(APPEND LIBCNTPR_MATH_SOURCE + math/ceil.c math/cos.c math/sin.c + math/floor.c ) list(APPEND LIBCNTPR_MATH_ASM_SOURCE math/amd64/atan.S math/amd64/atan2.S - math/amd64/ceil.S math/amd64/exp.S math/amd64/fabs.S math/amd64/fabsf.S - math/amd64/floor.S - math/amd64/floorf.S math/amd64/fmod.S math/amd64/ldexp.S math/amd64/log.S @@ -78,7 +77,6 @@ elseif(ARCH STREQUAL "arm") math/cos.c math/fabs.c math/fabsf.c - math/floorf.c math/sin.c math/sqrt.c math/arm/__rt_sdiv.c @@ -131,6 +129,7 @@ if(NOT ARCH STREQUAL "i386") math/cos.c math/coshf.c math/expf.c + math/floorf.c math/fmodf.c math/log10f.c math/modff.c