Math Lib: clamped rounding utility functions

This commit is contained in:
Campbell Barton 2017-09-18 21:03:10 +10:00
parent a6b156bf57
commit c4fc9c4a8e
Notes: blender-bot 2023-02-14 06:17:15 +01:00
Referenced by issue #53683, 2.79a release
2 changed files with 48 additions and 0 deletions

View 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);

View 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)