QtBase  v6.3.1
hb-algs.hh
Go to the documentation of this file.
1 /*
2  * Copyright © 2017 Google, Inc.
3  * Copyright © 2019 Facebook, Inc.
4  *
5  * This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Google Author(s): Behdad Esfahbod
26  * Facebook Author(s): Behdad Esfahbod
27  */
28 
29 #ifndef HB_ALGS_HH
30 #define HB_ALGS_HH
31 
32 #include "hb.hh"
33 #include "hb-meta.hh"
34 #include "hb-null.hh"
35 #include "hb-number.hh"
36 
37 #include <algorithm>
38 #include <initializer_list>
39 #include <functional>
40 #include <new>
41 
42 /*
43  * Flags
44  */
45 
46 /* Enable bitwise ops on enums marked as flags_t */
47 /* To my surprise, looks like the function resolver is happy to silently cast
48  * one enum to another... So this doesn't provide the type-checking that I
49  * originally had in mind... :(.
50  *
51  * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
52  */
53 #ifdef _MSC_VER
54 # pragma warning(disable:4200)
55 # pragma warning(disable:4800)
56 #endif
57 #define HB_MARK_AS_FLAG_T(T) \
58  extern "C++" { \
59  static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
60  static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
61  static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
62  static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
63  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
64  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
65  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
66  } \
67  static_assert (true, "")
68 
69 /* Useful for set-operations on small enums.
70  * For example, for testing "x ∈ {x1, x2, x3}" use:
71  * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
72  */
73 #define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
74 #define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
75 #define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x))
76 #define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
77 #define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
78 
79 
80 /*
81  * Big-endian integers.
82  */
83 
84 /* Endian swap, used in Windows related backends */
85 static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
86 { return (v >> 8) | (v << 8); }
87 static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
88 { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
89 
90 template <typename Type, int Bytes = sizeof (Type)>
91 struct BEInt;
92 template <typename Type>
93 struct BEInt<Type, 1>
94 {
95  public:
96  BEInt () = default;
97  constexpr BEInt (Type V) : v {uint8_t (V)} {}
98  constexpr operator Type () const { return v; }
99  private: uint8_t v;
100 };
101 template <typename Type>
102 struct BEInt<Type, 2>
103 {
104  public:
105  BEInt () = default;
106  constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
107  uint8_t ((V ) & 0xFF)} {}
108 
109  struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
110  constexpr operator Type () const
111  {
112 #if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
113  defined(__BYTE_ORDER) && \
114  (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
115  /* Spoon-feed the compiler a big-endian integer with alignment 1.
116  * https://github.com/harfbuzz/harfbuzz/pull/1398 */
117 #if __BYTE_ORDER == __LITTLE_ENDIAN
118  return __builtin_bswap16 (((packed_uint16_t *) this)->v);
119 #else /* __BYTE_ORDER == __BIG_ENDIAN */
120  return ((packed_uint16_t *) this)->v;
121 #endif
122 #else
123  return (v[0] << 8)
124  + (v[1] );
125 #endif
126  }
127  private: uint8_t v[2];
128 };
129 template <typename Type>
130 struct BEInt<Type, 3>
131 {
132  static_assert (!std::is_signed<Type>::value, "");
133  public:
134  BEInt () = default;
135  constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
136  uint8_t ((V >> 8) & 0xFF),
137  uint8_t ((V ) & 0xFF)} {}
138 
139  constexpr operator Type () const { return (v[0] << 16)
140  + (v[1] << 8)
141  + (v[2] ); }
142  private: uint8_t v[3];
143 };
144 template <typename Type>
145 struct BEInt<Type, 4>
146 {
147  public:
148  BEInt () = default;
149  constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
150  uint8_t ((V >> 16) & 0xFF),
151  uint8_t ((V >> 8) & 0xFF),
152  uint8_t ((V ) & 0xFF)} {}
153  constexpr operator Type () const { return (v[0] << 24)
154  + (v[1] << 16)
155  + (v[2] << 8)
156  + (v[3] ); }
157  private: uint8_t v[4];
158 };
159 
160 /* Floats. */
161 
162 /* We want our rounding towards +infinity. */
163 static inline float
164 _hb_roundf (float x) { return floorf (x + .5f); }
165 #define roundf(x) _hb_roundf(x)
166 
167 
168 /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
169  * values will be truncated / overlap, and might not decode exactly. */
170 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
171 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
172 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
173 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
174 
175 /* Custom encoding used by hb-ucd. */
176 #define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
177 #define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
178 #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
179 #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
180 
181 
182 struct
183 {
184  /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
185  template <typename T> constexpr auto
186  operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
187 }
188 HB_FUNCOBJ (hb_identity);
189 struct
190 {
191  /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
192  template <typename T> constexpr T&
193  operator () (T& v) const { return v; }
194 
195  template <typename T> constexpr hb_remove_reference<T>
196  operator () (T&& v) const { return v; }
197 }
198 HB_FUNCOBJ (hb_lidentity);
199 struct
200 {
201  /* Like identity(), but always returns rvalue. */
202  template <typename T> constexpr hb_remove_reference<T>
203  operator () (T&& v) const { return v; }
204 }
205 HB_FUNCOBJ (hb_ridentity);
206 
207 struct
208 {
209  template <typename T> constexpr bool
210  operator () (T&& v) const { return bool (std::forward<T> (v)); }
211 }
212 HB_FUNCOBJ (hb_bool);
213 
214 template <typename T>
215 static inline
216 T hb_coerce (const T v) { return v; }
217 template <typename T, typename V,
219 static inline
220 T hb_coerce (const V v) { return *v; }
221 
222 struct
223 {
224  private:
225 
226  template <typename T> constexpr auto
227  impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
228 
229  template <typename T> constexpr auto
230  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
231 
232  template <typename T,
233  hb_enable_if (std::is_integral<T>::value)> constexpr auto
235  (
236  /* Knuth's multiplicative method: */
237  (uint32_t) v * 2654435761u
238  )
239 
240  public:
241 
242  template <typename T> constexpr auto
243  operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
244 }
245 HB_FUNCOBJ (hb_hash);
246 
247 
248 struct
249 {
250  private:
251 
252  /* Pointer-to-member-function. */
253  template <typename Appl, typename T, typename ...Ts> auto
254  impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
255  ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
256 
257  /* Pointer-to-member. */
258  template <typename Appl, typename T> auto
259  impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
260  ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
261 
262  /* Operator(). */
263  template <typename Appl, typename ...Ts> auto
264  impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
265  (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
266 
267  public:
268 
269  template <typename Appl, typename ...Ts> auto
270  operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
271  (
272  impl (std::forward<Appl> (a),
274  std::forward<Ts> (ds)...)
275  )
276 }
277 HB_FUNCOBJ (hb_invoke);
278 
279 template <unsigned Pos, typename Appl, typename V>
281 {
282  hb_partial_t (Appl a, V v) : a (a), v (v) {}
283 
284  static_assert (Pos > 0, "");
285 
286  template <typename ...Ts,
287  unsigned P = Pos,
288  hb_enable_if (P == 1)> auto
289  operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
290  hb_declval (V),
291  hb_declval (Ts)...))
292  {
293  return hb_invoke (std::forward<Appl> (a),
294  std::forward<V> (v),
295  std::forward<Ts> (ds)...);
296  }
297  template <typename T0, typename ...Ts,
298  unsigned P = Pos,
299  hb_enable_if (P == 2)> auto
300  operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
301  hb_declval (T0),
302  hb_declval (V),
303  hb_declval (Ts)...))
304  {
305  return hb_invoke (std::forward<Appl> (a),
306  std::forward<T0> (d0),
307  std::forward<V> (v),
308  std::forward<Ts> (ds)...);
309  }
310 
311  private:
313  V v;
314 };
315 template <unsigned Pos=1, typename Appl, typename V>
318 
319 /* The following, HB_PARTIALIZE, macro uses a particular corner-case
320  * of C++11 that is not particularly well-supported by all compilers.
321  * What's happening is that it's using "this" in a trailing return-type
322  * via decltype(). Broken compilers deduce the type of "this" pointer
323  * in that context differently from what it resolves to in the body
324  * of the function.
325  *
326  * One probable cause of this is that at the time of trailing return
327  * type declaration, "this" points to an incomplete type, whereas in
328  * the function body the type is complete. That doesn't justify the
329  * error in any way, but is probably what's happening.
330  *
331  * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
332  * which deduces the type from the actual return statement. For gcc 4.8
333  * we use "+this" instead of "this" which produces an rvalue that seems
334  * to be deduced as the same type with this particular compiler, and seem
335  * to be fine as default code path as well.
336  */
337 #ifdef _MSC_VER
338 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
339 #define HB_PARTIALIZE(Pos) \
340  template <typename _T> \
341  decltype(auto) operator () (_T&& _v) const \
342  { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
343  static_assert (true, "")
344 #else
345 /* https://github.com/harfbuzz/harfbuzz/issues/1724 */
346 #define HB_PARTIALIZE(Pos) \
347  template <typename _T> \
348  auto operator () (_T&& _v) const HB_AUTO_RETURN \
349  (hb_partial<Pos> (+this, std::forward<_T> (_v))) \
350  static_assert (true, "")
351 #endif
352 
353 
354 struct
355 {
356  private:
357 
358  template <typename Pred, typename Val> auto
359  impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
360  (
361  hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
362  )
363 
364  template <typename Pred, typename Val> auto
365  impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
366  (
367  hb_invoke (std::forward<Pred> (p),
368  std::forward<Val> (v))
369  )
370 
371  public:
372 
373  template <typename Pred, typename Val> auto
374  operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
375  impl (std::forward<Pred> (p),
376  std::forward<Val> (v),
378  )
379 }
380 HB_FUNCOBJ (hb_has);
381 
382 struct
383 {
384  private:
385 
386  template <typename Pred, typename Val> auto
387  impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
388  (
389  hb_has (std::forward<Pred> (p),
390  std::forward<Val> (v))
391  )
392 
393  template <typename Pred, typename Val> auto
394  impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
395  (
396  std::forward<Pred> (p) == std::forward<Val> (v)
397  )
398 
399  public:
400 
401  template <typename Pred, typename Val> auto
402  operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
403  impl (std::forward<Pred> (p),
404  std::forward<Val> (v),
406  )
407 }
408 HB_FUNCOBJ (hb_match);
409 
410 struct
411 {
412  private:
413 
414  template <typename Proj, typename Val> auto
415  impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
416  (
417  hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
418  )
419 
420  template <typename Proj, typename Val> auto
421  impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
422  (
423  hb_invoke (std::forward<Proj> (f),
424  std::forward<Val> (v))
425  )
426 
427  template <typename Proj, typename Val> auto
428  impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
429  (
430  std::forward<Proj> (f)[std::forward<Val> (v)]
431  )
432 
433  public:
434 
435  template <typename Proj, typename Val> auto
436  operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
437  (
438  impl (std::forward<Proj> (f),
439  std::forward<Val> (v),
441  )
442 }
443 HB_FUNCOBJ (hb_get);
444 
445 struct
446 {
447  private:
448 
449  template <typename T1, typename T2> auto
450  impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
451  (
452  std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
453  )
454 
455  template <typename T1, typename T2> auto
456  impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
457  (
458  std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
459  )
460 
461  template <typename T1, typename T2> auto
462  impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
463  (
464  std::forward<T1> (v1) == std::forward<T2> (v2)
465  )
466 
467  template <typename T1, typename T2> auto
468  impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
469  (
470  std::forward<T2> (v2) == std::forward<T1> (v1)
471  )
472 
473  public:
474 
475  template <typename T1, typename T2> auto
476  operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
477  (
478  impl (std::forward<T1> (v1),
479  std::forward<T2> (v2),
481  )
482 }
483 HB_FUNCOBJ (hb_equal);
484 
485 
486 template <typename T1, typename T2>
487 struct hb_pair_t
488 {
489  typedef T1 first_t;
490  typedef T2 second_t;
492 
493  template <typename U1 = T1, typename U2 = T2,
496  hb_pair_t () : first (), second () {}
497  hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
498 
499  template <typename Q1, typename Q2,
501  hb_is_convertible (T2, Q2))>
502  operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
503 
505  { return hb_pair_t<T1, T2> (second, first); }
506 
507  bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
508  bool operator != (const pair_t& o) const { return !(*this == o); }
509  bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
510  bool operator >= (const pair_t& o) const { return !(*this < o); }
511  bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
512  bool operator <= (const pair_t& o) const { return !(*this > o); }
513 
516 };
517 #define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
518 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
519 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
520 
521 struct
522 {
523  template <typename Pair> constexpr typename Pair::first_t
524  operator () (const Pair& pair) const { return pair.first; }
525 }
526 HB_FUNCOBJ (hb_first);
527 
528 struct
529 {
530  template <typename Pair> constexpr typename Pair::second_t
531  operator () (const Pair& pair) const { return pair.second; }
532 }
533 HB_FUNCOBJ (hb_second);
534 
535 /* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
536  * However, that would silently convert between different-signedness integers.
537  * Instead we accept two different types, such that compiler can err if
538  * comparing integers of different signedness. */
539 struct
540 {
541  template <typename T, typename T2> constexpr auto
542  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
543  (a <= b ? std::forward<T> (a) : std::forward<T2> (b))
544 }
545 HB_FUNCOBJ (hb_min);
546 struct
547 {
548  template <typename T, typename T2> constexpr auto
549  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
550  (a >= b ? std::forward<T> (a) : std::forward<T2> (b))
551 }
552 HB_FUNCOBJ (hb_max);
553 struct
554 {
555  template <typename T, typename T2, typename T3> constexpr auto
556  operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
557  (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
558 }
559 HB_FUNCOBJ (hb_clamp);
560 
561 struct
562 {
563  template <typename T> void
564  operator () (T& a, T& b) const
565  {
566  using std::swap; // allow ADL
567  swap (a, b);
568  }
569 }
570 HB_FUNCOBJ (hb_swap);
571 
572 /*
573  * Bithacks.
574  */
575 
576 /* Return the number of 1 bits in v. */
577 template <typename T>
578 static inline unsigned int
579 hb_popcount (T v)
580 {
581 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
582  if (sizeof (T) <= sizeof (unsigned int))
583  return __builtin_popcount (v);
584 
585  if (sizeof (T) <= sizeof (unsigned long))
586  return __builtin_popcountl (v);
587 
588  if (sizeof (T) <= sizeof (unsigned long long))
589  return __builtin_popcountll (v);
590 #endif
591 
592  if (sizeof (T) <= 4)
593  {
594  /* "HACKMEM 169" */
595  uint32_t y;
596  y = (v >> 1) &033333333333;
597  y = v - y - ((y >>1) & 033333333333);
598  return (((y + (y >> 3)) & 030707070707) % 077);
599  }
600 
601  if (sizeof (T) == 8)
602  {
603  unsigned int shift = 32;
604  return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
605  }
606 
607  if (sizeof (T) == 16)
608  {
609  unsigned int shift = 64;
610  return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
611  }
612 
613  assert (0);
614  return 0; /* Shut up stupid compiler. */
615 }
616 
617 /* Returns the number of bits needed to store number */
618 template <typename T>
619 static inline unsigned int
620 hb_bit_storage (T v)
621 {
622  if (unlikely (!v)) return 0;
623 
624 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
625  if (sizeof (T) <= sizeof (unsigned int))
626  return sizeof (unsigned int) * 8 - __builtin_clz (v);
627 
628  if (sizeof (T) <= sizeof (unsigned long))
629  return sizeof (unsigned long) * 8 - __builtin_clzl (v);
630 
631  if (sizeof (T) <= sizeof (unsigned long long))
632  return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
633 #endif
634 
635 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
636  if (sizeof (T) <= sizeof (unsigned int))
637  {
638  unsigned long where;
639  _BitScanReverse (&where, v);
640  return 1 + where;
641  }
642 # if defined(_WIN64)
643  if (sizeof (T) <= 8)
644  {
645  unsigned long where;
646  _BitScanReverse64 (&where, v);
647  return 1 + where;
648  }
649 # endif
650 #endif
651 
652  if (sizeof (T) <= 4)
653  {
654  /* "bithacks" */
655  const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
656  const unsigned int S[] = {1, 2, 4, 8, 16};
657  unsigned int r = 0;
658  for (int i = 4; i >= 0; i--)
659  if (v & b[i])
660  {
661  v >>= S[i];
662  r |= S[i];
663  }
664  return r + 1;
665  }
666  if (sizeof (T) <= 8)
667  {
668  /* "bithacks" */
669  const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
670  const unsigned int S[] = {1, 2, 4, 8, 16, 32};
671  unsigned int r = 0;
672  for (int i = 5; i >= 0; i--)
673  if (v & b[i])
674  {
675  v >>= S[i];
676  r |= S[i];
677  }
678  return r + 1;
679  }
680  if (sizeof (T) == 16)
681  {
682  unsigned int shift = 64;
683  return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
684  hb_bit_storage<uint64_t> ((uint64_t) v);
685  }
686 
687  assert (0);
688  return 0; /* Shut up stupid compiler. */
689 }
690 
691 /* Returns the number of zero bits in the least significant side of v */
692 template <typename T>
693 static inline unsigned int
694 hb_ctz (T v)
695 {
696  if (unlikely (!v)) return 8 * sizeof (T);
697 
698 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
699  if (sizeof (T) <= sizeof (unsigned int))
700  return __builtin_ctz (v);
701 
702  if (sizeof (T) <= sizeof (unsigned long))
703  return __builtin_ctzl (v);
704 
705  if (sizeof (T) <= sizeof (unsigned long long))
706  return __builtin_ctzll (v);
707 #endif
708 
709 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
710  if (sizeof (T) <= sizeof (unsigned int))
711  {
712  unsigned long where;
713  _BitScanForward (&where, v);
714  return where;
715  }
716 # if defined(_WIN64)
717  if (sizeof (T) <= 8)
718  {
719  unsigned long where;
720  _BitScanForward64 (&where, v);
721  return where;
722  }
723 # endif
724 #endif
725 
726  if (sizeof (T) <= 4)
727  {
728  /* "bithacks" */
729  unsigned int c = 32;
730  v &= - (int32_t) v;
731  if (v) c--;
732  if (v & 0x0000FFFF) c -= 16;
733  if (v & 0x00FF00FF) c -= 8;
734  if (v & 0x0F0F0F0F) c -= 4;
735  if (v & 0x33333333) c -= 2;
736  if (v & 0x55555555) c -= 1;
737  return c;
738  }
739  if (sizeof (T) <= 8)
740  {
741  /* "bithacks" */
742  unsigned int c = 64;
743  v &= - (int64_t) (v);
744  if (v) c--;
745  if (v & 0x00000000FFFFFFFFULL) c -= 32;
746  if (v & 0x0000FFFF0000FFFFULL) c -= 16;
747  if (v & 0x00FF00FF00FF00FFULL) c -= 8;
748  if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
749  if (v & 0x3333333333333333ULL) c -= 2;
750  if (v & 0x5555555555555555ULL) c -= 1;
751  return c;
752  }
753  if (sizeof (T) == 16)
754  {
755  unsigned int shift = 64;
756  return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
757  hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
758  }
759 
760  assert (0);
761  return 0; /* Shut up stupid compiler. */
762 }
763 
764 
765 /*
766  * Tiny stuff.
767  */
768 
769 /* ASCII tag/character handling */
770 static inline bool ISALPHA (unsigned char c)
771 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
772 static inline bool ISALNUM (unsigned char c)
773 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
774 static inline bool ISSPACE (unsigned char c)
775 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
776 static inline unsigned char TOUPPER (unsigned char c)
777 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
778 static inline unsigned char TOLOWER (unsigned char c)
779 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
780 static inline bool ISHEX (unsigned char c)
781 { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
782 static inline unsigned char TOHEX (uint8_t c)
783 { return (c & 0xF) <= 9 ? (c & 0xF) + '0' : (c & 0xF) + 'a' - 10; }
784 static inline uint8_t FROMHEX (unsigned char c)
785 { return (c >= '0' && c <= '9') ? c - '0' : TOLOWER (c) - 'a' + 10; }
786 
787 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
788 { return (a + (b - 1)) / b; }
789 
790 
791 #undef ARRAY_LENGTH
792 template <typename Type, unsigned int n>
793 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
794 /* A const version, but does not detect erratically being called on pointers. */
795 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
796 
797 
798 static inline void *
799 hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
800 {
801  /* It's illegal to pass 0 as size to memcpy. */
802  if (unlikely (!len)) return dst;
803  return memcpy (dst, src, len);
804 }
805 
806 static inline int
807 hb_memcmp (const void *a, const void *b, unsigned int len)
808 {
809  /* It's illegal to pass NULL to memcmp(), even if len is zero.
810  * So, wrap it.
811  * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
812  if (unlikely (!len)) return 0;
813  return memcmp (a, b, len);
814 }
815 
816 static inline void *
817 hb_memset (void *s, int c, unsigned int n)
818 {
819  /* It's illegal to pass NULL to memset(), even if n is zero. */
820  if (unlikely (!n)) return 0;
821  return memset (s, c, n);
822 }
823 
824 static inline unsigned int
825 hb_ceil_to_4 (unsigned int v)
826 {
827  return ((v - 1) | 3) + 1;
828 }
829 
830 template <typename T> static inline bool
831 hb_in_range (T u, T lo, T hi)
832 {
833  static_assert (!std::is_signed<T>::value, "");
834 
835  /* The casts below are important as if T is smaller than int,
836  * the subtract results will become a signed int! */
837  return (T)(u - lo) <= (T)(hi - lo);
838 }
839 template <typename T> static inline bool
840 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
841 {
842  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
843 }
844 template <typename T> static inline bool
845 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
846 {
847  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
848 }
849 
850 
851 /*
852  * Overflow checking.
853  */
854 
855 /* Consider __builtin_mul_overflow use here also */
856 static inline bool
857 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
858 {
859  return (size > 0) && (count >= ((unsigned int) -1) / size);
860 }
861 
862 
863 /*
864  * Sort and search.
865  */
866 
867 template <typename K, typename V, typename ...Ts>
868 static int
869 _hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
870 {
871  const K& key = * (const K*) pkey;
872  const V& val = * (const V*) pval;
873 
874  return val.cmp (key, ds...);
875 }
876 
877 template <typename V, typename K, typename ...Ts>
878 static inline bool
879 hb_bsearch_impl (unsigned *pos, /* Out */
880  const K& key,
881  V* base, size_t nmemb, size_t stride,
882  int (*compar)(const void *_key, const void *_item, Ts... _ds),
883  Ts... ds)
884 {
885  /* This is our *only* bsearch implementation. */
886 
887  int min = 0, max = (int) nmemb - 1;
888  while (min <= max)
889  {
890  int mid = ((unsigned int) min + (unsigned int) max) / 2;
891 #pragma GCC diagnostic push
892 #pragma GCC diagnostic ignored "-Wcast-align"
893  V* p = (V*) (((const char *) base) + (mid * stride));
894 #pragma GCC diagnostic pop
895  int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
896  if (c < 0)
897  max = mid - 1;
898  else if (c > 0)
899  min = mid + 1;
900  else
901  {
902  *pos = mid;
903  return true;
904  }
905  }
906  *pos = min;
907  return false;
908 }
909 
910 template <typename V, typename K>
911 static inline V*
912 hb_bsearch (const K& key, V* base,
913  size_t nmemb, size_t stride = sizeof (V),
914  int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
915 {
916  unsigned pos;
917 #pragma GCC diagnostic push
918 #pragma GCC diagnostic ignored "-Wcast-align"
919  return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
920  (V*) (((const char *) base) + (pos * stride)) : nullptr;
921 #pragma GCC diagnostic pop
922 }
923 template <typename V, typename K, typename ...Ts>
924 static inline V*
925 hb_bsearch (const K& key, V* base,
926  size_t nmemb, size_t stride,
927  int (*compar)(const void *_key, const void *_item, Ts... _ds),
928  Ts... ds)
929 {
930  unsigned pos;
931 #pragma GCC diagnostic push
932 #pragma GCC diagnostic ignored "-Wcast-align"
933  return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
934  (V*) (((const char *) base) + (pos * stride)) : nullptr;
935 #pragma GCC diagnostic pop
936 }
937 
938 
939 /* From https://github.com/noporpoise/sort_r
940  Feb 5, 2019 (c8c65c1e)
941  Modified to support optional argument using templates */
942 
943 /* Isaac Turner 29 April 2014 Public Domain */
944 
945 /*
946 hb_qsort function to be exported.
947 Parameters:
948  base is the array to be sorted
949  nel is the number of elements in the array
950  width is the size in bytes of each element of the array
951  compar is the comparison function
952  arg (optional) is a pointer to be passed to the comparison function
953 
954 void hb_qsort(void *base, size_t nel, size_t width,
955  int (*compar)(const void *_a, const void *_b, [void *_arg]),
956  [void *arg]);
957 */
958 
959 #define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
960 
961 /* swap a and b */
962 /* a and b must not be equal! */
963 static inline void sort_r_swap(char *__restrict a, char *__restrict b,
964  size_t w)
965 {
966  char tmp, *end = a+w;
967  for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
968 }
969 
970 /* swap a, b iff a>b */
971 /* a and b must not be equal! */
972 /* __restrict is same as restrict but better support on old machines */
973 template <typename ...Ts>
974 static inline int sort_r_cmpswap(char *__restrict a,
975  char *__restrict b, size_t w,
976  int (*compar)(const void *_a,
977  const void *_b,
978  Ts... _ds),
979  Ts... ds)
980 {
981  if(compar(a, b, ds...) > 0) {
982  sort_r_swap(a, b, w);
983  return 1;
984  }
985  return 0;
986 }
987 
988 /*
989 Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
990 with the smallest swap so that the blocks are in the opposite order. Blocks may
991 be internally re-ordered e.g.
992  12345ab -> ab34512
993  123abc -> abc123
994  12abcde -> deabc12
995 */
996 static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
997 {
998  if(na > 0 && nb > 0) {
999  if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
1000  else { sort_r_swap(ptr, ptr+nb, na); }
1001  }
1002 }
1003 
1004 /* Implement recursive quicksort ourselves */
1005 /* Note: quicksort is not stable, equivalent values may be swapped */
1006 template <typename ...Ts>
1007 static inline void sort_r_simple(void *base, size_t nel, size_t w,
1008  int (*compar)(const void *_a,
1009  const void *_b,
1010  Ts... _ds),
1011  Ts... ds)
1012 {
1013  char *b = (char *)base, *end = b + nel*w;
1014 
1015  /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1016  printf("\n"); */
1017 
1018  if(nel < 10) {
1019  /* Insertion sort for arbitrarily small inputs */
1020  char *pi, *pj;
1021  for(pi = b+w; pi < end; pi += w) {
1022  for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
1023  }
1024  }
1025  else
1026  {
1027  /* nel > 9; Quicksort */
1028 
1029  int cmp;
1030  char *pl, *ple, *pr, *pre, *pivot;
1031  char *last = b+w*(nel-1), *tmp;
1032 
1033  /*
1034  Use median of second, middle and second-last items as pivot.
1035  First and last may have been swapped with pivot and therefore be extreme
1036  */
1037  char *l[3];
1038  l[0] = b + w;
1039  l[1] = b+w*(nel/2);
1040  l[2] = last - w;
1041 
1042  /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
1043 
1044  if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1045  if(compar(l[1],l[2],ds...) > 0) {
1046  SORT_R_SWAP(l[1], l[2], tmp);
1047  if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1048  }
1049 
1050  /* swap mid value (l[1]), and last element to put pivot as last element */
1051  if(l[1] != last) { sort_r_swap(l[1], last, w); }
1052 
1053  /*
1054  pl is the next item on the left to be compared to the pivot
1055  pr is the last item on the right that was compared to the pivot
1056  ple is the left position to put the next item that equals the pivot
1057  ple is the last right position where we put an item that equals the pivot
1058  v- end (beyond the array)
1059  EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
1060  ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
1061  Pivot comparison key:
1062  E = equal, L = less than, u = unknown, G = greater than, E = equal
1063  */
1064  pivot = last;
1065  ple = pl = b;
1066  pre = pr = last;
1067 
1068  /*
1069  Strategy:
1070  Loop into the list from the left and right at the same time to find:
1071  - an item on the left that is greater than the pivot
1072  - an item on the right that is less than the pivot
1073  Once found, they are swapped and the loop continues.
1074  Meanwhile items that are equal to the pivot are moved to the edges of the
1075  array.
1076  */
1077  while(pl < pr) {
1078  /* Move left hand items which are equal to the pivot to the far left.
1079  break when we find an item that is greater than the pivot */
1080  for(; pl < pr; pl += w) {
1081  cmp = compar(pl, pivot, ds...);
1082  if(cmp > 0) { break; }
1083  else if(cmp == 0) {
1084  if(ple < pl) { sort_r_swap(ple, pl, w); }
1085  ple += w;
1086  }
1087  }
1088  /* break if last batch of left hand items were equal to pivot */
1089  if(pl >= pr) { break; }
1090  /* Move right hand items which are equal to the pivot to the far right.
1091  break when we find an item that is less than the pivot */
1092  for(; pl < pr; ) {
1093  pr -= w; /* Move right pointer onto an unprocessed item */
1094  cmp = compar(pr, pivot, ds...);
1095  if(cmp == 0) {
1096  pre -= w;
1097  if(pr < pre) { sort_r_swap(pr, pre, w); }
1098  }
1099  else if(cmp < 0) {
1100  if(pl < pr) { sort_r_swap(pl, pr, w); }
1101  pl += w;
1102  break;
1103  }
1104  }
1105  }
1106 
1107  pl = pr; /* pr may have gone below pl */
1108 
1109  /*
1110  Now we need to go from: EEELLLGGGGEEEE
1111  to: LLLEEEEEEEGGGG
1112  Pivot comparison key:
1113  E = equal, L = less than, u = unknown, G = greater than, E = equal
1114  */
1115  sort_r_swap_blocks(b, ple-b, pl-ple);
1116  sort_r_swap_blocks(pr, pre-pr, end-pre);
1117 
1118  /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1119  printf("\n");*/
1120 
1121  sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
1122  sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
1123  }
1124 }
1125 
1126 static inline void
1127 hb_qsort (void *base, size_t nel, size_t width,
1128  int (*compar)(const void *_a, const void *_b))
1129 {
1130 #if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
1131  qsort (base, nel, width, compar);
1132 #else
1133  sort_r_simple (base, nel, width, compar);
1134 #endif
1135 }
1136 
1137 static inline void
1138 hb_qsort (void *base, size_t nel, size_t width,
1139  int (*compar)(const void *_a, const void *_b, void *_arg),
1140  void *arg)
1141 {
1142 #ifdef HAVE_GNU_QSORT_R
1143  qsort_r (base, nel, width, compar, arg);
1144 #else
1145  sort_r_simple (base, nel, width, compar, arg);
1146 #endif
1147 }
1148 
1149 
1150 template <typename T, typename T2, typename T3> static inline void
1151 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
1152 {
1153  for (unsigned int i = 1; i < len; i++)
1154  {
1155  unsigned int j = i;
1156  while (j && compar (&array[j - 1], &array[i]) > 0)
1157  j--;
1158  if (i == j)
1159  continue;
1160  /* Move item i to occupy place for item j, shift what's in between. */
1161  {
1162  T t = array[i];
1163  memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
1164  array[j] = t;
1165  }
1166  if (array2)
1167  {
1168  T3 t = array2[i];
1169  memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
1170  array2[j] = t;
1171  }
1172  }
1173 }
1174 
1175 template <typename T> static inline void
1176 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
1177 {
1178  hb_stable_sort (array, len, compar, (int *) nullptr);
1179 }
1180 
1181 static inline hb_bool_t
1182 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
1183 {
1184  unsigned int v;
1185  const char *p = s;
1186  const char *end = p + len;
1187  if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base)))
1188  return false;
1189 
1190  *out = v;
1191  return true;
1192 }
1193 
1194 
1195 /* Operators. */
1196 
1197 struct
1198 { HB_PARTIALIZE(2);
1199  template <typename T> constexpr auto
1200  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
1201 }
1202 HB_FUNCOBJ (hb_bitwise_and);
1203 struct
1204 { HB_PARTIALIZE(2);
1205  template <typename T> constexpr auto
1206  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
1207 }
1208 HB_FUNCOBJ (hb_bitwise_or);
1209 struct
1210 { HB_PARTIALIZE(2);
1211  template <typename T> constexpr auto
1212  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
1213 }
1214 HB_FUNCOBJ (hb_bitwise_xor);
1215 struct
1216 { HB_PARTIALIZE(2);
1217  template <typename T> constexpr auto
1218  operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
1219 }
1220 HB_FUNCOBJ (hb_bitwise_lt);
1221 struct
1222 { HB_PARTIALIZE(2);
1223  template <typename T> constexpr auto
1224  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
1225 }
1226 HB_FUNCOBJ (hb_bitwise_gt); // aka sub
1227 struct
1228 { HB_PARTIALIZE(2);
1229  template <typename T> constexpr auto
1230  operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
1231 }
1232 HB_FUNCOBJ (hb_bitwise_le);
1233 struct
1234 { HB_PARTIALIZE(2);
1235  template <typename T> constexpr auto
1236  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
1237 }
1238 HB_FUNCOBJ (hb_bitwise_ge);
1239 struct
1240 {
1241  template <typename T> constexpr auto
1242  operator () (const T &a) const HB_AUTO_RETURN (~a)
1243 }
1244 HB_FUNCOBJ (hb_bitwise_neg);
1245 
1246 struct
1247 { HB_PARTIALIZE(2);
1248  template <typename T, typename T2> constexpr auto
1249  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
1250 }
1251 HB_FUNCOBJ (hb_add);
1252 struct
1253 { HB_PARTIALIZE(2);
1254  template <typename T, typename T2> constexpr auto
1255  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
1256 }
1257 HB_FUNCOBJ (hb_sub);
1258 struct
1259 { HB_PARTIALIZE(2);
1260  template <typename T, typename T2> constexpr auto
1261  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
1262 }
1263 HB_FUNCOBJ (hb_rsub);
1264 struct
1265 { HB_PARTIALIZE(2);
1266  template <typename T, typename T2> constexpr auto
1267  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
1268 }
1269 HB_FUNCOBJ (hb_mul);
1270 struct
1271 { HB_PARTIALIZE(2);
1272  template <typename T, typename T2> constexpr auto
1273  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
1274 }
1275 HB_FUNCOBJ (hb_div);
1276 struct
1277 { HB_PARTIALIZE(2);
1278  template <typename T, typename T2> constexpr auto
1279  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
1280 }
1281 HB_FUNCOBJ (hb_mod);
1282 struct
1283 {
1284  template <typename T> constexpr auto
1285  operator () (const T &a) const HB_AUTO_RETURN (+a)
1286 }
1287 HB_FUNCOBJ (hb_pos);
1288 struct
1289 {
1290  template <typename T> constexpr auto
1291  operator () (const T &a) const HB_AUTO_RETURN (-a)
1292 }
1293 HB_FUNCOBJ (hb_neg);
1294 struct
1295 {
1296  template <typename T> constexpr auto
1297  operator () (T &a) const HB_AUTO_RETURN (++a)
1298 }
1299 HB_FUNCOBJ (hb_inc);
1300 struct
1301 {
1302  template <typename T> constexpr auto
1303  operator () (T &a) const HB_AUTO_RETURN (--a)
1304 }
1305 HB_FUNCOBJ (hb_dec);
1306 
1307 
1308 /* Compiler-assisted vectorization. */
1309 
1310 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
1311  * basically a fixed-size bitset. */
1312 template <typename elt_t, unsigned int byte_size>
1314 {
1315  elt_t& operator [] (unsigned int i) { return v[i]; }
1316  const elt_t& operator [] (unsigned int i) const { return v[i]; }
1317 
1318  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
1319 
1320  template <typename Op>
1322  {
1324  for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1325  r.v[i] = op (v[i]);
1326  return r;
1327  }
1328  template <typename Op>
1330  {
1332  for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1333  r.v[i] = op (v[i], o.v[i]);
1334  return r;
1335  }
1337  { return process (hb_bitwise_or, o); }
1339  { return process (hb_bitwise_and, o); }
1341  { return process (hb_bitwise_xor, o); }
1343  { return process (hb_bitwise_neg); }
1344 
1345  private:
1346  static_assert (0 == byte_size % sizeof (elt_t), "");
1347  elt_t v[byte_size / sizeof (elt_t)];
1348 };
1349 
1350 
1351 #endif /* HB_ALGS_HH */
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
template< typename Enum > bool operator!=(Enum lhs, QFlags< Enum > rhs)
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
bool operator<=(const QUuid &lhs, const QUuid &rhs)
Definition: quuid.h:216
bool operator>=(const QUuid &lhs, const QUuid &rhs)
Definition: quuid.h:218
Definition: base.h:37
#define T(x)
Definition: main.cpp:42
ush Pos
Definition: deflate.h:92
QHash< int, QWidget * > hash
[35multi]
double pi
[0]
auto hb_partial(Appl &&a, V &&v) HB_AUTO_RETURN((hb_partial_t< Pos
struct hb_partial_t HB_FUNCOBJ
#define SORT_R_SWAP(a, b, tmp)
Definition: hb-algs.hh:959
#define HB_PARTIALIZE(Pos)
auto V(a, v))) struct
Definition: hb-algs.hh:317
constexpr T & operator()(T &v) const
Definition: hb-algs.hh:2
auto Appl
Definition: hb-algs.hh:317
auto it unsigned count const
Definition: hb-iter.hh:848
#define hb_declval(T)
Definition: hb-meta.hh:90
hb_remove_const< hb_remove_reference< T > > hb_decay
Definition: hb-meta.hh:116
#define hb_enable_if(Cond)
Definition: hb-meta.hh:65
#define hb_is_convertible(From, To)
Definition: hb-meta.hh:118
#define hb_prioritize
Definition: hb-meta.hh:81
typename hb_match_reference< T >::type hb_remove_reference
Definition: hb-meta.hh:99
#define HB_AUTO_RETURN(E)
Definition: hb-meta.hh:76
#define HB_RETURN(Ret, E)
Definition: hb-meta.hh:75
bool hb_parse_uint(const char **pp, const char *end, unsigned *pv, bool whole_buffer, int base)
Definition: hb-number.cc:64
#define __attribute__(x)
Definition: hb.hh:256
#define unlikely(expr)
Definition: hb.hh:251
#define ISALNUM(off)
Definition: md4c.c:316
#define ISALPHA(off)
Definition: md4c.c:313
Definition: qfloat16.h:381
void swap(SimpleVector< T > &v1, SimpleVector< T > &v2)
Definition: simplevector.h:331
void *PRIV() memmove(void *d, const void *s, size_t n)
set set set set set set set macro pixldst1 op
#define assert
Definition: qcborcommon_p.h:63
EGLOutputLayerEXT EGLint EGLAttrib value
constexpr bool operator>(const QFixed &f, int i)
Definition: qfixed_p.h:182
#define ARRAY_LENGTH(a)
Definition: qkmsdevice.cpp:52
bool int shift
GLint GLfloat GLfloat GLfloat v2
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum src
const void GLsizei GLsizei stride
GLint GLsizei width
GLenum GLenum dst
GLint GLfloat GLfloat v1
GLint first
GLfloat n
GLint y
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLfloat * val
Definition: qopenglext.h:1513
GLenum array
Definition: qopenglext.h:7028
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
Definition: qopenglext.h:9781
SSL_CTX int(*) void arg)
HB_BEGIN_DECLS typedef int hb_bool_t
Definition: hb-common.h:97
uint32_t hb_codepoint_t
Definition: hb-common.h:106
QString base
QTextStream out(stdout)
[7]
this swap(other)
http get(QUrl::toPercentEncoding("/index.html"))
QDBusVariant Type
constexpr BEInt(Type V)
Definition: hb-algs.hh:97
constexpr BEInt(Type V)
Definition: hb-algs.hh:135
constexpr BEInt(Type V)
Definition: hb-algs.hh:149
Definition: hb-algs.hh:91
Definition: main.cpp:38
Definition: moc.h:48
hb_pair_t(T1 a, T2 b)
Definition: hb-algs.hh:497
T2 second_t
Definition: hb-algs.hh:490
hb_pair_t< T1, T2 > pair_t
Definition: hb-algs.hh:491
hb_pair_t< T1, T2 > reverse() const
Definition: hb-algs.hh:504
T2 second
Definition: hb-algs.hh:515
hb_pair_t()
Definition: hb-algs.hh:496
T1 first
Definition: hb-algs.hh:514
T1 first_t
Definition: hb-algs.hh:489
hb_partial_t(Appl a, V v)
Definition: hb-algs.hh:282
auto operator()(Ts &&...ds) -> decltype(hb_invoke(hb_declval(Appl), hb_declval(V), hb_declval(Ts)...))
Definition: hb-algs.hh:289
elt_t & operator[](unsigned int i)
Definition: hb-algs.hh:1315
hb_vector_size_t operator|(const hb_vector_size_t &o) const
Definition: hb-algs.hh:1336
hb_vector_size_t operator^(const hb_vector_size_t &o) const
Definition: hb-algs.hh:1340
hb_vector_size_t operator~() const
Definition: hb-algs.hh:1342
hb_vector_size_t operator&(const hb_vector_size_t &o) const
Definition: hb-algs.hh:1338
void clear(unsigned char v=0)
Definition: hb-algs.hh:1318
hb_vector_size_t process(const Op &op, const hb_vector_size_t &o) const
Definition: hb-algs.hh:1329
hb_vector_size_t process(const Op &op) const
Definition: hb-algs.hh:1321