doxygen: add newline after \file
[blender.git] / source / blender / blenlib / intern / math_base_inline.c
index 5ae2b1a..1ad0dc6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  *
  * The Original Code is: some of this file.
  *
- * ***** END GPL LICENSE BLOCK *****
  * */
 
-/** \file blender/blenlib/intern/math_base_inline.c
- *  \ingroup bli
+/** \file
+ * \ingroup bli
  */
 
 #ifndef __MATH_BASE_INLINE_C__
@@ -33,6 +30,7 @@
 #include <float.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <limits.h>
 
 #ifdef __SSE2__
 #  include <emmintrin.h>
@@ -181,11 +179,59 @@ MINLINE unsigned power_of_2_min_u(unsigned x)
        return x - (x >> 1);
 }
 
-MINLINE int iroundf(float a)
-{
-       return (int)floorf(a + 0.5f);
+/* rounding and clamping */
+
+#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; \
+}
+
+#define _round_fl_impl(arg, ty) { return (ty)floorf(arg + 0.5f); }
+#define _round_db_impl(arg, ty) { return (ty)floor(arg + 0.5); }
+
+MINLINE signed char    round_fl_to_char(float a) { _round_fl_impl(a, signed char) }
+MINLINE unsigned char  round_fl_to_uchar(float a) { _round_fl_impl(a, unsigned char) }
+MINLINE short          round_fl_to_short(float a) { _round_fl_impl(a, short) }
+MINLINE unsigned short round_fl_to_ushort(float a) { _round_fl_impl(a, unsigned short) }
+MINLINE int            round_fl_to_int(float a) { _round_fl_impl(a, int) }
+MINLINE unsigned int   round_fl_to_uint(float a) { _round_fl_impl(a, unsigned int) }
+
+MINLINE signed char    round_db_to_char(double a) { _round_db_impl(a, signed char) }
+MINLINE unsigned char  round_db_to_uchar(double a) { _round_db_impl(a, unsigned char) }
+MINLINE short          round_db_to_short(double a) { _round_db_impl(a, short) }
+MINLINE unsigned short round_db_to_ushort(double a) { _round_db_impl(a, unsigned short) }
+MINLINE int            round_db_to_int(double a) { _round_db_impl(a, int) }
+MINLINE unsigned int   round_db_to_uint(double a) { _round_db_impl(a, unsigned int) }
+
+#undef _round_fl_impl
+#undef _round_db_impl
+
+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)
@@ -266,10 +312,40 @@ MINLINE int max_iiii(int a, int b, int c, int d)
        return max_ii(max_iii(a, b, c), d);
 }
 
+MINLINE size_t min_zz(size_t a, size_t b)
+{
+       return (a < b) ? a : b;
+}
+MINLINE size_t max_zz(size_t a, size_t b)
+{
+       return (b < a) ? a : b;
+}
+
+MINLINE int clamp_i(int value, int min, int max)
+{
+       return min_ii(max_ii(value, min), max);
+}
+
+MINLINE float clamp_f(float value, float min, float max)
+{
+       if (value > max) {
+               return max;
+       }
+       else if (value < min) {
+               return min;
+       }
+       return value;
+}
+
+MINLINE size_t clamp_z(size_t value, size_t min, size_t max)
+{
+       return min_zz(max_zz(value, min), max);
+}
+
 /**
  * Almost-equal for IEEE floats, using absolute difference method.
  *
- * \param max_diff the maximum absolute difference.
+ * \param max_diff: the maximum absolute difference.
  */
 MINLINE int compare_ff(float a, float b, const float max_diff)
 {
@@ -279,9 +355,9 @@ MINLINE int compare_ff(float a, float b, const float max_diff)
 /**
  * Almost-equal for IEEE floats, using their integer representation (mixing ULP and absolute difference methods).
  *
- * \param max_diff is the maximum absolute difference (allows to take care of the near-zero area,
+ * \param max_diff: is the maximum absolute difference (allows to take care of the near-zero area,
  *                 where relative difference methods cannot really work).
- * \param max_ulps is the 'maximum number of floats + 1' allowed between \a a and \a b to consider them equal.
+ * \param max_ulps: is the 'maximum number of floats + 1' allowed between \a a and \a b to consider them equal.
  *
  * \see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
  */
@@ -289,10 +365,8 @@ MINLINE int compare_ff_relative(float a, float b, const float max_diff, const in
 {
        union {float f; int i;} ua, ub;
 
-#if 0  /* No BLI_assert in INLINE :/ */
        BLI_assert(sizeof(float) == sizeof(int));
        BLI_assert(max_ulps < (1 << 22));
-#endif
 
        if (fabsf(a - b) <= max_diff) {
                return 1;
@@ -339,6 +413,10 @@ MINLINE int integer_digits_d(const double d)
        return (d == 0.0) ? 0 : (int)floor(log10(fabs(d))) + 1;
 }
 
+MINLINE int integer_digits_i(const int i)
+{
+       return (int)log10((double)i) + 1;
+}
 
 /* Internal helpers for SSE2 implementation.
  *
@@ -392,7 +470,7 @@ MALWAYS_INLINE __m128 _bli_math_fastpow24(const __m128 arg)
         */
        /* 0x3F4CCCCD = 4/5 */
        /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */
-       /* error max = 0.17     avg = 0.0018    |avg| = 0.05 */
+       /* error max = 0.17, avg = 0.0018, |avg| = 0.05 */
        __m128 x = _bli_math_fastpow(0x3F4CCCCD, 0x4F55A7FB, arg);
        __m128 arg2 = _mm_mul_ps(arg, arg);
        __m128 arg4 = _mm_mul_ps(arg2, arg2);
@@ -434,4 +512,35 @@ MALWAYS_INLINE __m128 _bli_math_blend_sse(const __m128 mask,
 
 #endif  /* __SSE2__ */
 
+/* Low level conversion functions */
+MINLINE unsigned char unit_float_to_uchar_clamp(float val)
+{
+       return (unsigned char)(((val <= 0.0f) ? 0 : ((val > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * val) + 0.5f))));
+}
+#define unit_float_to_uchar_clamp(val) ((CHECK_TYPE_INLINE(val, float)), unit_float_to_uchar_clamp(val))
+
+MINLINE unsigned short unit_float_to_ushort_clamp(float val)
+{
+       return (unsigned short)((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (val * 65535.0f + 0.5f));
+}
+#define unit_float_to_ushort_clamp(val) ((CHECK_TYPE_INLINE(val, float)), unit_float_to_ushort_clamp(val))
+
+MINLINE unsigned char unit_ushort_to_uchar(unsigned short val)
+{
+       return (unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8);
+}
+#define unit_ushort_to_uchar(val) ((CHECK_TYPE_INLINE(val, unsigned short)), unit_ushort_to_uchar(val))
+
+#define unit_float_to_uchar_clamp_v3(v1, v2) {                                              \
+       (v1)[0] = unit_float_to_uchar_clamp((v2[0]));                                           \
+       (v1)[1] = unit_float_to_uchar_clamp((v2[1]));                                           \
+       (v1)[2] = unit_float_to_uchar_clamp((v2[2]));                                           \
+} ((void)0)
+#define unit_float_to_uchar_clamp_v4(v1, v2) {                                              \
+       (v1)[0] = unit_float_to_uchar_clamp((v2[0]));                                           \
+       (v1)[1] = unit_float_to_uchar_clamp((v2[1]));                                           \
+       (v1)[2] = unit_float_to_uchar_clamp((v2[2]));                                           \
+       (v1)[3] = unit_float_to_uchar_clamp((v2[3]));                                           \
+} ((void)0)
+
 #endif /* __MATH_BASE_INLINE_C__ */