Parcourir la source

Added SDL_modf() and SDL_modff()

This function is useful for accumulating relative mouse motion if you want to only handle whole pixel movement.
e.g.
static float dx_frac, dy_frac;
float dx, dy;

/* Accumulate new motion with previous sub-pixel motion */
dx = event.motion.xrel + dx_frac;
dy = event.motion.yrel + dy_frac;

/* Split the integral and fractional motion, dx and dy will contain whole pixel deltas */
dx_frac = SDL_modff(dx, &dx);
dy_frac = SDL_modff(dy, &dy);
if (dx != 0.0f || dy != 0.0f) {
    ...
}
Sam Lantinga il y a 2 ans
Parent
commit
7f23d71b6a

+ 2 - 2
CMakeLists.txt

@@ -962,8 +962,8 @@ if(SDL_LIBC)
             _stricmp _strnicmp sscanf
             acos acosf asin asinf atan atanf atan2 atan2f ceil ceilf
             copysign copysignf cos cosf exp expf fabs fabsf floor floorf fmod fmodf
-            log logf log10 log10f lround lroundf pow powf round roundf scalbn scalbnf
-            sin sinf sqrt sqrtf tan tanf trunc truncf)
+            log logf log10 log10f lround lroundf modf modff pow powf round roundf
+            scalbn scalbnf sin sinf sqrt sqrtf tan tanf trunc truncf)
       string(TOUPPER ${_FN} _UPPER)
       set(HAVE_${_UPPER} 1)
     endforeach()

+ 1 - 0
VisualC-GDK/SDL/SDL.vcxproj

@@ -666,6 +666,7 @@
     <ClCompile Include="..\..\src\libm\s_cos.c" />
     <ClCompile Include="..\..\src\libm\s_fabs.c" />
     <ClCompile Include="..\..\src\libm\s_floor.c" />
+    <ClCompile Include="..\..\src\libm\s_modf.c" />
     <ClCompile Include="..\..\src\libm\s_scalbn.c" />
     <ClCompile Include="..\..\src\libm\s_sin.c" />
     <ClCompile Include="..\..\src\libm\s_tan.c" />

+ 3 - 0
VisualC-GDK/SDL/SDL.vcxproj.filters

@@ -976,6 +976,9 @@
     <ClCompile Include="..\..\src\libm\s_floor.c">
       <Filter>libm</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\libm\s_modf.c">
+      <Filter>libm</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\libm\s_scalbn.c">
       <Filter>libm</Filter>
     </ClCompile>

+ 1 - 0
VisualC/SDL/SDL.vcxproj

@@ -546,6 +546,7 @@
     <ClCompile Include="..\..\src\libm\s_cos.c" />
     <ClCompile Include="..\..\src\libm\s_fabs.c" />
     <ClCompile Include="..\..\src\libm\s_floor.c" />
+    <ClCompile Include="..\..\src\libm\s_modf.c" />
     <ClCompile Include="..\..\src\libm\s_scalbn.c" />
     <ClCompile Include="..\..\src\libm\s_sin.c" />
     <ClCompile Include="..\..\src\libm\s_tan.c" />

+ 3 - 0
VisualC/SDL/SDL.vcxproj.filters

@@ -964,6 +964,9 @@
     <ClCompile Include="..\..\src\libm\s_floor.c">
       <Filter>libm</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\libm\s_modf.c">
+      <Filter>libm</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\libm\s_scalbn.c">
       <Filter>libm</Filter>
     </ClCompile>

+ 1 - 0
WhatsNew.txt

@@ -19,3 +19,4 @@ General:
 * Added SDL_GetTicksNS() to return the number of nanoseconds since the SDL library initialized
 * Added SDL_DelayNS() to specify a delay in nanoseconds, to the highest precision the system will support
 * The timestamp member of the SDL_Event structure is now in nanoseconds, filled in with the time the event was generated, or the time it was queued if that's not available
+* Added SDL_modf() and SDL_modff() to separate the whole and fractional portions of a floating point number

+ 2 - 0
include/SDL3/SDL_stdinc.h

@@ -580,6 +580,8 @@ extern DECLSPEC double SDLCALL SDL_log(double x);
 extern DECLSPEC float SDLCALL SDL_logf(float x);
 extern DECLSPEC double SDLCALL SDL_log10(double x);
 extern DECLSPEC float SDLCALL SDL_log10f(float x);
+extern DECLSPEC double SDLCALL SDL_modf(double x, double *y);
+extern DECLSPEC float SDLCALL SDL_modff(float x, float *y);
 extern DECLSPEC double SDLCALL SDL_pow(double x, double y);
 extern DECLSPEC float SDLCALL SDL_powf(float x, float y);
 extern DECLSPEC double SDLCALL SDL_round(double x);

+ 2 - 0
include/build_config/SDL_build_config.h.cmake

@@ -171,6 +171,8 @@
 #cmakedefine HAVE_LOG10F 1
 #cmakedefine HAVE_LROUND 1
 #cmakedefine HAVE_LROUNDF 1
+#cmakedefine HAVE_MODF 1
+#cmakedefine HAVE_MODFF 1
 #cmakedefine HAVE_POW 1
 #cmakedefine HAVE_POWF 1
 #cmakedefine HAVE_ROUND 1

+ 1 - 0
include/build_config/SDL_build_config_android.h

@@ -120,6 +120,7 @@
 #define HAVE_LOG10F 1
 #define HAVE_LROUND 1
 #define HAVE_LROUNDF 1
+#define HAVE_MODF   1
 #define HAVE_POW    1
 #define HAVE_POWF   1
 #define HAVE_ROUND  1

+ 1 - 0
include/build_config/SDL_build_config_ios.h

@@ -114,6 +114,7 @@
 #define HAVE_LOG10F 1
 #define HAVE_LROUND 1
 #define HAVE_LROUNDF 1
+#define HAVE_MODF   1
 #define HAVE_POW    1
 #define HAVE_POWF   1
 #define HAVE_ROUND  1

+ 1 - 0
include/build_config/SDL_build_config_macos.h

@@ -116,6 +116,7 @@
 #define HAVE_LOG10F 1
 #define HAVE_LROUND 1
 #define HAVE_LROUNDF 1
+#define HAVE_MODF   1
 #define HAVE_POW    1
 #define HAVE_POWF   1
 #define HAVE_ROUND  1

+ 1 - 0
include/build_config/SDL_build_config_winrt.h

@@ -134,6 +134,7 @@
 #define HAVE_LOG10F 1
 #define HAVE_LROUND 1
 #define HAVE_LROUNDF 1
+#define HAVE_MODF   1
 #define HAVE_POW    1
 #define HAVE_POWF   1
 #define HAVE_ROUND 1

+ 2 - 0
src/dynapi/SDL_dynapi.sym

@@ -859,6 +859,8 @@ SDL3_0.0.0 {
     SDL_wcsncasecmp;
     SDL_wcsncmp;
     SDL_wcsstr;
+    SDL_modf;
+    SDL_modff;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 2 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -887,3 +887,5 @@
 #define SDL_wcsstr SDL_wcsstr_REAL
 
 /* New API symbols are added at the end */
+#define SDL_modf SDL_modf_REAL
+#define SDL_modff SDL_modff_REAL

+ 2 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -932,3 +932,5 @@ SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(
 SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return)
 
 /* New API symbols are added at the end */
+SDL_DYNAPI_PROC(double,SDL_modf,(double a, double *b),(a,b),return)
+SDL_DYNAPI_PROC(float,SDL_modff,(float a, float *b),(a,b),return)

+ 6 - 5
src/libm/math_libm.h

@@ -27,16 +27,17 @@
 /* Math routines from uClibc: http://www.uclibc.org */
 
 double SDL_uclibc_atan(double x);
-double SDL_uclibc_atan2(double y, double x);    
-double SDL_uclibc_copysign(double x, double y);       
-double SDL_uclibc_cos(double x);         
+double SDL_uclibc_atan2(double y, double x);
+double SDL_uclibc_copysign(double x, double y);
+double SDL_uclibc_cos(double x);
 double SDL_uclibc_exp(double x);
-double SDL_uclibc_fabs(double x);        
+double SDL_uclibc_fabs(double x);
 double SDL_uclibc_floor(double x);
 double SDL_uclibc_fmod(double x, double y);
 double SDL_uclibc_log(double x);
 double SDL_uclibc_log10(double x);
-double SDL_uclibc_pow(double x, double y);    
+double SDL_uclibc_modf(double x, double *y);
+double SDL_uclibc_pow(double x, double y);
 double SDL_uclibc_scalbn(double x, int n);
 double SDL_uclibc_sin(double x);
 double SDL_uclibc_sqrt(double x);

+ 1 - 0
src/libm/math_private.h

@@ -40,6 +40,7 @@ typedef unsigned int u_int32_t;
 #define __ieee754_fmod  SDL_uclibc_fmod
 #define __ieee754_log   SDL_uclibc_log
 #define __ieee754_log10 SDL_uclibc_log10
+#define modf            SDL_uclibc_modf
 #define __ieee754_pow   SDL_uclibc_pow
 #define scalbln         SDL_uclibc_scalbln
 #define scalbn          SDL_uclibc_scalbn

+ 68 - 0
src/libm/s_modf.c

@@ -0,0 +1,68 @@
+#include "SDL_internal.h"
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *	Bit twiddling.
+ *
+ * Exception:
+ *	No exception.
+ */
+
+#include "math_libm.h"
+#include "math_private.h"
+
+static const double one = 1.0;
+
+double modf(double x, double *iptr)
+{
+	int32_t i0,i1,_j0;
+	u_int32_t i;
+	EXTRACT_WORDS(i0,i1,x);
+	_j0 = ((i0>>20)&0x7ff)-0x3ff;	/* exponent of x */
+	if(_j0<20) {			/* integer part in high x */
+	    if(_j0<0) {			/* |x|<1 */
+	        INSERT_WORDS(*iptr,i0&0x80000000,0);	/* *iptr = +-0 */
+		return x;
+	    } else {
+		i = (0x000fffff)>>_j0;
+		if(((i0&i)|i1)==0) {		/* x is integral */
+		    *iptr = x;
+		    INSERT_WORDS(x,i0&0x80000000,0);	/* return +-0 */
+		    return x;
+		} else {
+		    INSERT_WORDS(*iptr,i0&(~i),0);
+		    return x - *iptr;
+		}
+	    }
+	} else if (_j0>51) {		/* no fraction part */
+	    *iptr = x*one;
+	    /* We must handle NaNs separately.  */
+	    if (_j0 == 0x400 && ((i0 & 0xfffff) | i1))
+	      return x*one;
+	    INSERT_WORDS(x,i0&0x80000000,0);	/* return +-0 */
+	    return x;
+	} else {			/* fraction part in low x */
+	    i = ((u_int32_t)(0xffffffff))>>(_j0-20);
+	    if((i1&i)==0) { 		/* x is integral */
+		*iptr = x;
+		INSERT_WORDS(x,i0&0x80000000,0);	/* return +-0 */
+		return x;
+	    } else {
+	        INSERT_WORDS(*iptr,i0,i1&(~i));
+		return x - *iptr;
+	    }
+	}
+}
+libm_hidden_def(modf)

+ 22 - 0
src/stdlib/SDL_stdlib.c

@@ -322,6 +322,28 @@ float SDL_log10f(float x)
 #endif
 }
 
+double
+SDL_modf(double x, double *y)
+{
+#if defined(HAVE_MODF)
+    return modf(x, y);
+#else
+    return SDL_uclibc_modf(x, y);
+#endif
+}
+
+float SDL_modff(float x, float *y)
+{
+#if defined(HAVE_MODFF)
+    return modff(x, y);
+#else
+    double double_result, double_y;
+    double_result = SDL_modf((double)x, &double_y);
+    *y = (float)double_y;
+    return (float)double_result;
+#endif
+}
+
 double
 SDL_pow(double x, double y)
 {

+ 27 - 0
test/testautomation_math.c

@@ -1272,6 +1272,24 @@ log10_regularCases(void *args)
     return helper_dtod_inexact("Log10", SDL_log10, regular_cases, SDL_arraysize(regular_cases));
 }
 
+/* SDL_modf tests functions */
+
+static int
+modf_baseCases(void *args)
+{
+    double fractional, integral;
+
+    fractional = SDL_modf(1.25, &integral);
+    SDLTest_AssertCheck(integral == 1.0,
+                        "modf(%f), expected integral %f, got %f",
+                        1.25, 1.0, integral);
+    SDLTest_AssertCheck(fractional == 0.25,
+                        "modf(%f), expected fractional %f, got %f",
+                        1.25, 0.25, fractional);
+
+    return TEST_COMPLETED;
+}
+
 /* SDL_pow tests functions */
 
 /* Tests with positive and negative infinities as exponents */
@@ -3004,6 +3022,13 @@ static const SDLTest_TestCaseReference log10TestRegular = {
     "Checks a set of regular values", TEST_ENABLED
 };
 
+/* SDL_modf test cases */
+
+static const SDLTest_TestCaseReference modfTestBase = {
+    (SDLTest_TestCaseFp)modf_baseCases, "modf_baseCases",
+    "Checks the base cases", TEST_ENABLED
+};
+
 /* SDL_pow test cases */
 
 static const SDLTest_TestCaseReference powTestExpInf1 = {
@@ -3315,6 +3340,8 @@ static const SDLTest_TestCaseReference *mathTests[] = {
     &log10TestLimit, &log10TestNan,
     &log10TestBase, &log10TestRegular,
 
+    &modfTestBase,
+
     &powTestExpInf1, &powTestExpInf2, &powTestExpInf3,
     &powTestBaseInf1, &powTestBaseInf2,
     &powTestNan1, &powTestNan2, &powTestNan3, &powTestNan4,