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

Reply via email to