Math Lib: clamped rounding utility functions
authorCampbell Barton <ideasman42@gmail.com>
Mon, 18 Sep 2017 11:03:10 +0000 (21:03 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 18 Sep 2017 13:55:41 +0000 (23:55 +1000)
source/blender/blenlib/BLI_math_base.h
source/blender/blenlib/intern/math_base_inline.c

index c44b666faead4523a92d56b56b3905910af4d32a..e7e89a6424a28a8f23590db21d0c96ff1101d2ec 100644 (file)
@@ -153,6 +153,20 @@ MINLINE int iroundf(float a);
 MINLINE int divide_round_i(int a, int b);
 MINLINE int mod_i(int i, int n);
 
+MINLINE signed char    round_fl_to_char_clamp(float a);
+MINLINE unsigned char  round_fl_to_uchar_clamp(float a);
+MINLINE short          round_fl_to_short_clamp(float a);
+MINLINE unsigned short round_fl_to_ushort_clamp(float a);
+MINLINE int            round_fl_to_int_clamp(float a);
+MINLINE unsigned int   round_fl_to_uint_clamp(float a);
+
+MINLINE signed char    round_db_to_char_clamp(double a);
+MINLINE unsigned char  round_db_to_uchar_clamp(double a);
+MINLINE short          round_db_to_short_clamp(double a);
+MINLINE unsigned short round_db_to_ushort_clamp(double a);
+MINLINE int            round_db_to_int_clamp(double a);
+MINLINE unsigned int   round_db_to_uint_clamp(double a);
+
 int pow_i(int base, int exp);
 double double_round(double x, int ndigits);
 
index 5ae2b1a70a7c54e40d9e85eb96231fc00e6476ca..37efe95791c2aba175b866c04838fabf6353b4a7 100644 (file)
@@ -33,6 +33,7 @@
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <limits.h>
 
 #ifdef __SSE2__
 #  include <emmintrin.h>
@@ -181,11 +182,44 @@ MINLINE unsigned power_of_2_min_u(unsigned x)
        return x - (x >> 1);
 }
 
+/* rounding and clamping */
+
 MINLINE int iroundf(float a)
 {
        return (int)floorf(a + 0.5f);
 }
 
+#define _round_clamp_fl_impl(arg, ty, min, max) { \
+       float r = floorf(arg + 0.5f); \
+       if      (UNLIKELY(r <= (float)min)) return (ty)min; \
+       else if (UNLIKELY(r >= (float)max)) return (ty)max; \
+       else return (ty)r; \
+}
+
+#define _round_clamp_db_impl(arg, ty, min, max) { \
+       double r = floor(arg + 0.5); \
+       if      (UNLIKELY(r <= (double)min)) return (ty)min; \
+       else if (UNLIKELY(r >= (double)max)) return (ty)max; \
+       else return (ty)r; \
+}
+
+MINLINE signed char    round_fl_to_char_clamp(float a) { _round_clamp_fl_impl(a, signed char, SCHAR_MIN, SCHAR_MAX) }
+MINLINE unsigned char  round_fl_to_uchar_clamp(float a) { _round_clamp_fl_impl(a, unsigned char, 0, UCHAR_MAX) }
+MINLINE short          round_fl_to_short_clamp(float a) { _round_clamp_fl_impl(a, short, SHRT_MIN, SHRT_MAX) }
+MINLINE unsigned short round_fl_to_ushort_clamp(float a) { _round_clamp_fl_impl(a, unsigned short, 0, USHRT_MAX) }
+MINLINE int            round_fl_to_int_clamp(float a) { _round_clamp_fl_impl(a, int, INT_MIN, INT_MAX) }
+MINLINE unsigned int   round_fl_to_uint_clamp(float a) { _round_clamp_fl_impl(a, unsigned int, 0, UINT_MAX) }
+
+MINLINE signed char    round_db_to_char_clamp(double a) { _round_clamp_db_impl(a, signed char, SCHAR_MIN, SCHAR_MAX) }
+MINLINE unsigned char  round_db_to_uchar_clamp(double a) { _round_clamp_db_impl(a, unsigned char, 0, UCHAR_MAX) }
+MINLINE short          round_db_to_short_clamp(double a) { _round_clamp_db_impl(a, short, SHRT_MIN, SHRT_MAX) }
+MINLINE unsigned short round_db_to_ushort_clamp(double a) { _round_clamp_db_impl(a, unsigned short, 0, USHRT_MAX) }
+MINLINE int            round_db_to_int_clamp(double a) { _round_clamp_db_impl(a, int, INT_MIN, INT_MAX) }
+MINLINE unsigned int   round_db_to_uint_clamp(double a) { _round_clamp_db_impl(a, unsigned int, 0, UINT_MAX) }
+
+#undef _round_clamp_fl_impl
+#undef _round_clamp_db_impl
+
 /* integer division that rounds 0.5 up, particularly useful for color blending
  * with integers, to avoid gradual darkening when rounding down */
 MINLINE int divide_round_i(int a, int b)