summaryrefslogtreecommitdiff
path: root/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-algs.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-algs.hh88
1 files changed, 80 insertions, 8 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
index e98645e3e3..13587eac01 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-algs.hh
@@ -110,9 +110,10 @@ struct BEInt<Type, 2>
constexpr operator Type () const
{
#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
- (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ (__BYTE_ORDER == __BIG_ENDIAN || \
+ (__BYTE_ORDER == __LITTLE_ENDIAN && \
+ hb_has_builtin(__builtin_bswap16)))
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -155,9 +156,10 @@ struct BEInt<Type, 4>
struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
constexpr operator Type () const {
#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
- ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
- (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ (__BYTE_ORDER == __BIG_ENDIAN || \
+ (__BYTE_ORDER == __LITTLE_ENDIAN && \
+ hb_has_builtin(__builtin_bswap32)))
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -598,13 +600,17 @@ template <typename T>
static inline unsigned int
hb_popcount (T v)
{
-#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+#if hb_has_builtin(__builtin_popcount)
if (sizeof (T) <= sizeof (unsigned int))
return __builtin_popcount (v);
+#endif
+#if hb_has_builtin(__builtin_popcountl)
if (sizeof (T) <= sizeof (unsigned long))
return __builtin_popcountl (v);
+#endif
+#if hb_has_builtin(__builtin_popcountll)
if (sizeof (T) <= sizeof (unsigned long long))
return __builtin_popcountll (v);
#endif
@@ -641,13 +647,17 @@ hb_bit_storage (T v)
{
if (unlikely (!v)) return 0;
-#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+#if hb_has_builtin(__builtin_clz)
if (sizeof (T) <= sizeof (unsigned int))
return sizeof (unsigned int) * 8 - __builtin_clz (v);
+#endif
+#if hb_has_builtin(__builtin_clzl)
if (sizeof (T) <= sizeof (unsigned long))
return sizeof (unsigned long) * 8 - __builtin_clzl (v);
+#endif
+#if hb_has_builtin(__builtin_clzll)
if (sizeof (T) <= sizeof (unsigned long long))
return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
#endif
@@ -715,13 +725,17 @@ hb_ctz (T v)
{
if (unlikely (!v)) return 8 * sizeof (T);
-#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+#if hb_has_builtin(__builtin_ctz)
if (sizeof (T) <= sizeof (unsigned int))
return __builtin_ctz (v);
+#endif
+#if hb_has_builtin(__builtin_ctzl)
if (sizeof (T) <= sizeof (unsigned long))
return __builtin_ctzl (v);
+#endif
+#if hb_has_builtin(__builtin_ctzll)
if (sizeof (T) <= sizeof (unsigned long long))
return __builtin_ctzll (v);
#endif
@@ -875,7 +889,7 @@ hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
static inline bool
hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
{
-#if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && (__clang_major__ >= 8))
+#if hb_has_builtin(__builtin_mul_overflow)
unsigned stack_result;
if (!result)
result = &stack_result;
@@ -1330,4 +1344,62 @@ struct
HB_FUNCOBJ (hb_dec);
+/* Adapted from kurbo implementation with extra parameters added,
+ * and finding for a particular range instead of 0.
+ *
+ * For documentation and implementation see:
+ *
+ * [ITP method]: https://en.wikipedia.org/wiki/ITP_Method
+ * [An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality]: https://dl.acm.org/doi/10.1145/3423597
+ * https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
+ * https://github.com/linebender/kurbo/blob/fd839c25ea0c98576c7ce5789305822675a89938/src/common.rs#L162-L248
+ */
+template <typename func_t>
+double solve_itp (func_t f,
+ double a, double b,
+ double epsilon,
+ double min_y, double max_y,
+ double &ya, double &yb, double &y)
+{
+ unsigned n1_2 = (unsigned) (hb_max (ceil (log2 ((b - a) / epsilon)) - 1.0, 0.0));
+ const unsigned n0 = 1; // Hardwired
+ const double k1 = 0.2 / (b - a); // Hardwired.
+ unsigned nmax = n0 + n1_2;
+ double scaled_epsilon = epsilon * double (1llu << nmax);
+ double _2_epsilon = 2.0 * epsilon;
+ while (b - a > _2_epsilon)
+ {
+ double x1_2 = 0.5 * (a + b);
+ double r = scaled_epsilon - 0.5 * (b - a);
+ double xf = (yb * a - ya * b) / (yb - ya);
+ double sigma = x1_2 - xf;
+ double b_a = b - a;
+ // This has k2 = 2 hardwired for efficiency.
+ double b_a_k2 = b_a * b_a;
+ double delta = k1 * b_a_k2;
+ int sigma_sign = sigma >= 0 ? +1 : -1;
+ double xt = delta <= fabs (x1_2 - xf) ? xf + delta * sigma_sign : x1_2;
+ double xitp = fabs (xt - x1_2) <= r ? xt : x1_2 - r * sigma_sign;
+ double yitp = f (xitp);
+ if (yitp > max_y)
+ {
+ b = xitp;
+ yb = yitp;
+ }
+ else if (yitp < min_y)
+ {
+ a = xitp;
+ ya = yitp;
+ }
+ else
+ {
+ y = yitp;
+ return xitp;
+ }
+ scaled_epsilon *= 0.5;
+ }
+ return 0.5 * (a + b);
+}
+
+
#endif /* HB_ALGS_HH */