2 * Copyright © 2017 Google, Inc.
3 * Copyright © 2019 Facebook, Inc.
5 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
25 * Google Author(s): Behdad Esfahbod
26 * Facebook Author(s): Behdad Esfahbod
35 #include "hb-number.hh"
38 #include <initializer_list>
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... :(.
51 * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
54 # pragma warning(disable:4200)
55 # pragma warning(disable:4800)
57 #define HB_MARK_AS_FLAG_T(T) \
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 unsigned operator ~ (T r) { return (~(unsigned) 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; } \
67 static_assert (true, "")
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)))
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)
81 * Big-endian integers.
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); }
90 #ifndef HB_FAST_INT_ACCESS
91 #if defined(__OPTIMIZE__) && \
92 defined(__BYTE_ORDER) && \
93 (__BYTE_ORDER == __BIG_ENDIAN || \
94 (__BYTE_ORDER == __LITTLE_ENDIAN && \
95 hb_has_builtin(__builtin_bswap16) && \
96 hb_has_builtin(__builtin_bswap32)))
97 #define HB_FAST_INT_ACCESS 1
99 #define HB_FAST_INT_ACCESS 0
103 template <typename Type, int Bytes = sizeof (Type)>
105 template <typename Type>
106 struct BEInt<Type, 1>
110 constexpr BEInt (Type V) : v {uint8_t (V)} {}
111 constexpr operator Type () const { return v; }
114 template <typename Type>
115 struct BEInt<Type, 2>
117 struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
123 #if HB_FAST_INT_ACCESS
124 #if __BYTE_ORDER == __LITTLE_ENDIAN
125 { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); }
126 #else /* __BYTE_ORDER == __BIG_ENDIAN */
127 { ((packed_uint16_t *) v)->v = V; }
130 : v {uint8_t ((V >> 8) & 0xFF),
131 uint8_t ((V ) & 0xFF)} {}
134 constexpr operator Type () const {
135 #if HB_FAST_INT_ACCESS
136 #if __BYTE_ORDER == __LITTLE_ENDIAN
137 return __builtin_bswap16 (((packed_uint16_t *) v)->v);
138 #else /* __BYTE_ORDER == __BIG_ENDIAN */
139 return ((packed_uint16_t *) v)->v;
146 private: uint8_t v[2];
148 template <typename Type>
149 struct BEInt<Type, 3>
151 static_assert (!std::is_signed<Type>::value, "");
154 constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
155 uint8_t ((V >> 8) & 0xFF),
156 uint8_t ((V ) & 0xFF)} {}
158 constexpr operator Type () const { return (v[0] << 16)
161 private: uint8_t v[3];
163 template <typename Type>
164 struct BEInt<Type, 4>
166 struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
172 #if HB_FAST_INT_ACCESS
173 #if __BYTE_ORDER == __LITTLE_ENDIAN
174 { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); }
175 #else /* __BYTE_ORDER == __BIG_ENDIAN */
176 { ((packed_uint32_t *) v)->v = V; }
179 : v {uint8_t ((V >> 24) & 0xFF),
180 uint8_t ((V >> 16) & 0xFF),
181 uint8_t ((V >> 8) & 0xFF),
182 uint8_t ((V ) & 0xFF)} {}
185 constexpr operator Type () const {
186 #if HB_FAST_INT_ACCESS
187 #if __BYTE_ORDER == __LITTLE_ENDIAN
188 return __builtin_bswap32 (((packed_uint32_t *) v)->v);
189 #else /* __BYTE_ORDER == __BIG_ENDIAN */
190 return ((packed_uint32_t *) v)->v;
199 private: uint8_t v[4];
204 /* We want our rounding towards +infinity. */
206 _hb_roundf (float x) { return floorf (x + .5f); }
207 #define roundf(x) _hb_roundf(x)
210 /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
211 * values will be truncated / overlap, and might not decode exactly. */
212 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
213 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
214 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
215 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
217 /* Custom encoding used by hb-ucd. */
218 #define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
219 #define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
220 #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
221 #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
226 /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
227 template <typename T> constexpr auto
228 operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
230 HB_FUNCOBJ (hb_identity);
233 /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
234 template <typename T> constexpr T&
235 operator () (T& v) const { return v; }
237 template <typename T> constexpr hb_remove_reference<T>
238 operator () (T&& v) const { return v; }
240 HB_FUNCOBJ (hb_lidentity);
243 /* Like identity(), but always returns rvalue. */
244 template <typename T> constexpr hb_remove_reference<T>
245 operator () (T&& v) const { return v; }
247 HB_FUNCOBJ (hb_ridentity);
251 template <typename T> constexpr bool
252 operator () (T&& v) const { return bool (std::forward<T> (v)); }
254 HB_FUNCOBJ (hb_bool);
259 Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
261 Permission is hereby granted, free of charge, to any person
262 obtaining a copy of this software and associated documentation
263 files (the "Software"), to deal in the Software without
264 restriction, including without limitation the rights to use, copy,
265 modify, merge, publish, distribute, sublicense, and/or sell copies
266 of the Software, and to permit persons to whom the Software is
267 furnished to do so, subject to the following conditions:
269 The above copyright notice and this permission notice shall be
270 included in all copies or substantial portions of the Software.
272 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
273 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
274 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
275 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
276 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
277 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
278 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
283 // Compression function for Merkle-Damgard construction.
284 // This function is generated using the framework provided.
286 (void) ((h) ^= (h) >> 23), \
287 (void) ((h) *= 0x2127599bf4325c37ULL), \
290 static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
292 struct __attribute__((packed)) packed_uint64_t { uint64_t v; };
293 const uint64_t m = 0x880355f21e6d1965ULL;
294 const packed_uint64_t *pos = (const packed_uint64_t *)buf;
295 const packed_uint64_t *end = pos + (len / 8);
296 const unsigned char *pos2;
297 uint64_t h = seed ^ (len * m);
300 #ifndef HB_OPTIMIZE_SIZE
301 if (((uintptr_t) pos & 7) == 0)
305 #pragma GCC diagnostic push
306 #pragma GCC diagnostic ignored "-Wcast-align"
307 v = * (const uint64_t *) (pos++);
308 #pragma GCC diagnostic pop
324 pos2 = (const unsigned char*)pos;
328 case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH;
329 case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH;
330 case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH;
331 case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH;
332 case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
333 case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH;
334 case 1: v ^= (uint64_t)pos2[0];
342 static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
344 // the following trick converts the 64-bit hashcode to Fermat
345 // residue, which shall retain information from both the higher
346 // and lower parts of hashcode.
347 uint64_t h = fasthash64(buf, len, seed);
348 return h - (h >> 32);
355 template <typename T> constexpr auto
356 impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
358 // Horrible: std:hash() of integers seems to be identity in gcc / clang?!
359 // https://github.com/harfbuzz/harfbuzz/pull/4228
361 // For performance characteristics see:
362 // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537
363 template <typename T,
364 hb_enable_if (std::is_integral<T>::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto
365 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) v * 2654435761u /* Knuh's multiplicative hash */)
366 template <typename T,
367 hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
368 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
370 template <typename T,
371 hb_enable_if (std::is_floating_point<T>::value)> constexpr auto
372 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, fasthash32 (std::addressof (v), sizeof (T), 0xf437ffe6))
374 template <typename T> constexpr auto
375 impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
379 template <typename T> constexpr auto
380 operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
382 HB_FUNCOBJ (hb_hash);
389 /* Pointer-to-member-function. */
390 template <typename Appl, typename T, typename ...Ts> auto
391 impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
392 ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
394 /* Pointer-to-member. */
395 template <typename Appl, typename T> auto
396 impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
397 ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
400 template <typename Appl, typename ...Ts> auto
401 impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
402 (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
406 template <typename Appl, typename ...Ts> auto
407 operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
409 impl (std::forward<Appl> (a),
411 std::forward<Ts> (ds)...)
414 HB_FUNCOBJ (hb_invoke);
416 template <unsigned Pos, typename Appl, typename V>
419 hb_partial_t (Appl a, V v) : a (a), v (v) {}
421 static_assert (Pos > 0, "");
423 template <typename ...Ts,
425 hb_enable_if (P == 1)> auto
426 operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
430 return hb_invoke (std::forward<Appl> (a),
432 std::forward<Ts> (ds)...);
434 template <typename T0, typename ...Ts,
436 hb_enable_if (P == 2)> auto
437 operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
442 return hb_invoke (std::forward<Appl> (a),
443 std::forward<T0> (d0),
445 std::forward<Ts> (ds)...);
449 hb_reference_wrapper<Appl> a;
452 template <unsigned Pos=1, typename Appl, typename V>
453 auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
454 (( hb_partial_t<Pos, Appl, V> (a, v) ))
456 /* The following, HB_PARTIALIZE, macro uses a particular corner-case
457 * of C++11 that is not particularly well-supported by all compilers.
458 * What's happening is that it's using "this" in a trailing return-type
459 * via decltype(). Broken compilers deduce the type of "this" pointer
460 * in that context differently from what it resolves to in the body
463 * One probable cause of this is that at the time of trailing return
464 * type declaration, "this" points to an incomplete type, whereas in
465 * the function body the type is complete. That doesn't justify the
466 * error in any way, but is probably what's happening.
468 * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
469 * which deduces the type from the actual return statement. For gcc 4.8
470 * we use "+this" instead of "this" which produces an rvalue that seems
471 * to be deduced as the same type with this particular compiler, and seem
472 * to be fine as default code path as well.
475 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
476 #define HB_PARTIALIZE(Pos) \
477 template <typename _T> \
478 decltype(auto) operator () (_T&& _v) const \
479 { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
480 static_assert (true, "")
482 /* https://github.com/harfbuzz/harfbuzz/issues/1724 */
483 #define HB_PARTIALIZE(Pos) \
484 template <typename _T> \
485 auto operator () (_T&& _v) const HB_AUTO_RETURN \
486 (hb_partial<Pos> (+this, std::forward<_T> (_v))) \
487 static_assert (true, "")
495 template <typename Pred, typename Val> auto
496 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
498 hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
501 template <typename Pred, typename Val> auto
502 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
504 hb_invoke (std::forward<Pred> (p),
505 std::forward<Val> (v))
510 template <typename Pred, typename Val> auto
511 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
512 impl (std::forward<Pred> (p),
513 std::forward<Val> (v),
523 template <typename Pred, typename Val> auto
524 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
526 hb_has (std::forward<Pred> (p),
527 std::forward<Val> (v))
530 template <typename Pred, typename Val> auto
531 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
533 std::forward<Pred> (p) == std::forward<Val> (v)
538 template <typename Pred, typename Val> auto
539 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
540 impl (std::forward<Pred> (p),
541 std::forward<Val> (v),
545 HB_FUNCOBJ (hb_match);
551 template <typename Proj, typename Val> auto
552 impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
554 hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
557 template <typename Proj, typename Val> auto
558 impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
560 hb_invoke (std::forward<Proj> (f),
561 std::forward<Val> (v))
564 template <typename Proj, typename Val> auto
565 impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
567 std::forward<Proj> (f)[std::forward<Val> (v)]
572 template <typename Proj, typename Val> auto
573 operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
575 impl (std::forward<Proj> (f),
576 std::forward<Val> (v),
586 template <typename T1, typename T2> auto
587 impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
589 std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
592 template <typename T1, typename T2> auto
593 impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
595 std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
598 template <typename T1, typename T2> auto
599 impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
601 std::forward<T1> (v1) == std::forward<T2> (v2)
604 template <typename T1, typename T2> auto
605 impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
607 std::forward<T2> (v2) == std::forward<T1> (v1)
612 template <typename T1, typename T2> auto
613 operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
615 impl (std::forward<T1> (v1),
616 std::forward<T2> (v2),
620 HB_FUNCOBJ (hb_equal);
624 template <typename T> void
625 operator () (T& a, T& b) const
627 using std::swap; // allow ADL
631 HB_FUNCOBJ (hb_swap);
634 template <typename T1, typename T2>
639 typedef hb_pair_t<T1, T2> pair_t;
641 template <typename U1 = T1, typename U2 = T2,
642 hb_enable_if (std::is_default_constructible<U1>::value &&
643 std::is_default_constructible<U2>::value)>
644 hb_pair_t () : first (), second () {}
645 hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
647 template <typename Q1, typename Q2,
648 hb_enable_if (hb_is_convertible (T1, Q1) &&
649 hb_is_convertible (T2, Q2))>
650 operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
652 hb_pair_t<T1, T2> reverse () const
653 { return hb_pair_t<T1, T2> (second, first); }
655 bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
656 bool operator != (const pair_t& o) const { return !(*this == o); }
657 bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
658 bool operator >= (const pair_t& o) const { return !(*this < o); }
659 bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
660 bool operator <= (const pair_t& o) const { return !(*this > o); }
662 static int cmp (const void *pa, const void *pb)
664 pair_t *a = (pair_t *) pa;
665 pair_t *b = (pair_t *) pb;
667 if (a->first < b->first) return -1;
668 if (a->first > b->first) return +1;
669 if (a->second < b->second) return -1;
670 if (a->second > b->second) return +1;
674 friend void swap (hb_pair_t& a, hb_pair_t& b)
676 hb_swap (a.first, b.first);
677 hb_swap (a.second, b.second);
684 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
685 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
687 typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
691 template <typename Pair> constexpr typename Pair::first_t
692 operator () (const Pair& pair) const { return pair.first; }
694 HB_FUNCOBJ (hb_first);
698 template <typename Pair> constexpr typename Pair::second_t
699 operator () (const Pair& pair) const { return pair.second; }
701 HB_FUNCOBJ (hb_second);
703 /* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
704 * However, that would silently convert between different-signedness integers.
705 * Instead we accept two different types, such that compiler can err if
706 * comparing integers of different signedness. */
709 template <typename T, typename T2> constexpr auto
710 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
716 template <typename T, typename T2> constexpr auto
717 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
723 template <typename T, typename T2, typename T3> constexpr auto
724 operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
725 (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
727 HB_FUNCOBJ (hb_clamp);
733 /* Return the number of 1 bits in v. */
734 template <typename T>
735 static inline unsigned int
738 #if hb_has_builtin(__builtin_popcount)
739 if (sizeof (T) <= sizeof (unsigned int))
740 return __builtin_popcount (v);
743 #if hb_has_builtin(__builtin_popcountl)
744 if (sizeof (T) <= sizeof (unsigned long))
745 return __builtin_popcountl (v);
748 #if hb_has_builtin(__builtin_popcountll)
749 if (sizeof (T) <= sizeof (unsigned long long))
750 return __builtin_popcountll (v);
757 y = (v >> 1) &033333333333;
758 y = v - y - ((y >>1) & 033333333333);
759 return (((y + (y >> 3)) & 030707070707) % 077);
764 uint64_t y = (uint64_t) v;
765 y -= ((y >> 1) & 0x5555555555555555ull);
766 y = (y & 0x3333333333333333ull) + (y >> 2 & 0x3333333333333333ull);
767 return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0full) * 0x101010101010101ull >> 56;
770 if (sizeof (T) == 16)
772 unsigned int shift = 64;
773 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
777 return 0; /* Shut up stupid compiler. */
780 /* Returns the number of bits needed to store number */
781 template <typename T>
782 static inline unsigned int
785 if (unlikely (!v)) return 0;
787 #if hb_has_builtin(__builtin_clz)
788 if (sizeof (T) <= sizeof (unsigned int))
789 return sizeof (unsigned int) * 8 - __builtin_clz (v);
792 #if hb_has_builtin(__builtin_clzl)
793 if (sizeof (T) <= sizeof (unsigned long))
794 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
797 #if hb_has_builtin(__builtin_clzll)
798 if (sizeof (T) <= sizeof (unsigned long long))
799 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
802 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
803 if (sizeof (T) <= sizeof (unsigned int))
806 _BitScanReverse (&where, v);
813 _BitScanReverse64 (&where, v);
822 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
823 const unsigned int S[] = {1, 2, 4, 8, 16};
825 for (int i = 4; i >= 0; i--)
836 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
837 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
839 for (int i = 5; i >= 0; i--)
847 if (sizeof (T) == 16)
849 unsigned int shift = 64;
850 return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
851 hb_bit_storage<uint64_t> ((uint64_t) v);
855 return 0; /* Shut up stupid compiler. */
858 /* Returns the number of zero bits in the least significant side of v */
859 template <typename T>
860 static inline unsigned int
863 if (unlikely (!v)) return 8 * sizeof (T);
865 #if hb_has_builtin(__builtin_ctz)
866 if (sizeof (T) <= sizeof (unsigned int))
867 return __builtin_ctz (v);
870 #if hb_has_builtin(__builtin_ctzl)
871 if (sizeof (T) <= sizeof (unsigned long))
872 return __builtin_ctzl (v);
875 #if hb_has_builtin(__builtin_ctzll)
876 if (sizeof (T) <= sizeof (unsigned long long))
877 return __builtin_ctzll (v);
880 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
881 if (sizeof (T) <= sizeof (unsigned int))
884 _BitScanForward (&where, v);
891 _BitScanForward64 (&where, v);
903 if (v & 0x0000FFFF) c -= 16;
904 if (v & 0x00FF00FF) c -= 8;
905 if (v & 0x0F0F0F0F) c -= 4;
906 if (v & 0x33333333) c -= 2;
907 if (v & 0x55555555) c -= 1;
914 v &= - (int64_t) (v);
916 if (v & 0x00000000FFFFFFFFULL) c -= 32;
917 if (v & 0x0000FFFF0000FFFFULL) c -= 16;
918 if (v & 0x00FF00FF00FF00FFULL) c -= 8;
919 if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
920 if (v & 0x3333333333333333ULL) c -= 2;
921 if (v & 0x5555555555555555ULL) c -= 1;
924 if (sizeof (T) == 16)
926 unsigned int shift = 64;
927 return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
928 hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
932 return 0; /* Shut up stupid compiler. */
940 /* ASCII tag/character handling */
941 static inline bool ISALPHA (unsigned char c)
942 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
943 static inline bool ISALNUM (unsigned char c)
944 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
945 static inline bool ISSPACE (unsigned char c)
946 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
947 static inline unsigned char TOUPPER (unsigned char c)
948 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
949 static inline unsigned char TOLOWER (unsigned char c)
950 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
951 static inline bool ISHEX (unsigned char c)
952 { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
953 static inline unsigned char TOHEX (uint8_t c)
954 { return (c & 0xF) <= 9 ? (c & 0xF) + '0' : (c & 0xF) + 'a' - 10; }
955 static inline uint8_t FROMHEX (unsigned char c)
956 { return (c >= '0' && c <= '9') ? c - '0' : TOLOWER (c) - 'a' + 10; }
958 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
959 { return (a + (b - 1)) / b; }
963 template <typename Type, unsigned int n>
964 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
965 /* A const version, but does not detect erratically being called on pointers. */
966 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
970 hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
972 /* It's illegal to pass 0 as size to memcpy. */
973 if (unlikely (!len)) return dst;
974 return memcpy (dst, src, len);
978 hb_memcmp (const void *a, const void *b, unsigned int len)
980 /* It's illegal to pass NULL to memcmp(), even if len is zero.
982 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
983 if (unlikely (!len)) return 0;
984 return memcmp (a, b, len);
988 hb_memset (void *s, int c, unsigned int n)
990 /* It's illegal to pass NULL to memset(), even if n is zero. */
991 if (unlikely (!n)) return s;
992 return memset (s, c, n);
995 static inline unsigned int
996 hb_ceil_to_4 (unsigned int v)
998 return ((v - 1) | 3) + 1;
1001 template <typename T> static inline bool
1002 hb_in_range (T u, T lo, T hi)
1004 static_assert (!std::is_signed<T>::value, "");
1006 /* The casts below are important as if T is smaller than int,
1007 * the subtract results will become a signed int! */
1008 return (T)(u - lo) <= (T)(hi - lo);
1010 template <typename T> static inline bool
1011 hb_in_ranges (T u, T lo1, T hi1)
1013 return hb_in_range (u, lo1, hi1);
1015 template <typename T, typename ...Ts> static inline bool
1016 hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
1018 return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
1023 * Overflow checking.
1027 hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
1029 #if hb_has_builtin(__builtin_mul_overflow)
1030 unsigned stack_result;
1032 result = &stack_result;
1033 return __builtin_mul_overflow (count, size, result);
1037 *result = count * size;
1038 return (size > 0) && (count >= ((unsigned int) -1) / size);
1046 template <typename K, typename V, typename ...Ts>
1048 _hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
1050 const K& key = * (const K*) pkey;
1051 const V& val = * (const V*) pval;
1053 return val.cmp (key, ds...);
1056 template <typename V, typename K, typename ...Ts>
1058 hb_bsearch_impl (unsigned *pos, /* Out */
1060 V* base, size_t nmemb, size_t stride,
1061 int (*compar)(const void *_key, const void *_item, Ts... _ds),
1064 /* This is our *only* bsearch implementation. */
1066 int min = 0, max = (int) nmemb - 1;
1069 int mid = ((unsigned int) min + (unsigned int) max) / 2;
1070 #pragma GCC diagnostic push
1071 #pragma GCC diagnostic ignored "-Wcast-align"
1072 V* p = (V*) (((const char *) base) + (mid * stride));
1073 #pragma GCC diagnostic pop
1074 int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
1089 template <typename V, typename K>
1091 hb_bsearch (const K& key, V* base,
1092 size_t nmemb, size_t stride = sizeof (V),
1093 int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
1096 #pragma GCC diagnostic push
1097 #pragma GCC diagnostic ignored "-Wcast-align"
1098 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
1099 (V*) (((const char *) base) + (pos * stride)) : nullptr;
1100 #pragma GCC diagnostic pop
1102 template <typename V, typename K, typename ...Ts>
1104 hb_bsearch (const K& key, V* base,
1105 size_t nmemb, size_t stride,
1106 int (*compar)(const void *_key, const void *_item, Ts... _ds),
1110 #pragma GCC diagnostic push
1111 #pragma GCC diagnostic ignored "-Wcast-align"
1112 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
1113 (V*) (((const char *) base) + (pos * stride)) : nullptr;
1114 #pragma GCC diagnostic pop
1118 /* From https://github.com/noporpoise/sort_r
1119 Feb 5, 2019 (c8c65c1e)
1120 Modified to support optional argument using templates */
1122 /* Isaac Turner 29 April 2014 Public Domain */
1125 hb_qsort function to be exported.
1127 base is the array to be sorted
1128 nel is the number of elements in the array
1129 width is the size in bytes of each element of the array
1130 compar is the comparison function
1131 arg (optional) is a pointer to be passed to the comparison function
1133 void hb_qsort(void *base, size_t nel, size_t width,
1134 int (*compar)(const void *_a, const void *_b, [void *_arg]),
1138 #define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
1141 /* a and b must not be equal! */
1142 static inline void sort_r_swap(char *__restrict a, char *__restrict b,
1145 char tmp, *end = a+w;
1146 for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
1149 /* swap a, b iff a>b */
1150 /* a and b must not be equal! */
1151 /* __restrict is same as restrict but better support on old machines */
1152 template <typename ...Ts>
1153 static inline int sort_r_cmpswap(char *__restrict a,
1154 char *__restrict b, size_t w,
1155 int (*compar)(const void *_a,
1160 if(compar(a, b, ds...) > 0) {
1161 sort_r_swap(a, b, w);
1168 Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
1169 with the smallest swap so that the blocks are in the opposite order. Blocks may
1170 be internally re-ordered e.g.
1175 static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
1177 if(na > 0 && nb > 0) {
1178 if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
1179 else { sort_r_swap(ptr, ptr+nb, na); }
1183 /* Implement recursive quicksort ourselves */
1184 /* Note: quicksort is not stable, equivalent values may be swapped */
1185 template <typename ...Ts>
1186 static inline void sort_r_simple(void *base, size_t nel, size_t w,
1187 int (*compar)(const void *_a,
1192 char *b = (char *)base, *end = b + nel*w;
1194 /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1198 /* Insertion sort for arbitrarily small inputs */
1200 for(pi = b+w; pi < end; pi += w) {
1201 for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
1206 /* nel > 9; Quicksort */
1209 char *pl, *ple, *pr, *pre, *pivot;
1210 char *last = b+w*(nel-1), *tmp;
1213 Use median of second, middle and second-last items as pivot.
1214 First and last may have been swapped with pivot and therefore be extreme
1221 /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
1223 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1224 if(compar(l[1],l[2],ds...) > 0) {
1225 SORT_R_SWAP(l[1], l[2], tmp);
1226 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1229 /* swap mid value (l[1]), and last element to put pivot as last element */
1230 if(l[1] != last) { sort_r_swap(l[1], last, w); }
1233 pl is the next item on the left to be compared to the pivot
1234 pr is the last item on the right that was compared to the pivot
1235 ple is the left position to put the next item that equals the pivot
1236 ple is the last right position where we put an item that equals the pivot
1237 v- end (beyond the array)
1238 EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
1239 ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
1240 Pivot comparison key:
1241 E = equal, L = less than, u = unknown, G = greater than, E = equal
1249 Loop into the list from the left and right at the same time to find:
1250 - an item on the left that is greater than the pivot
1251 - an item on the right that is less than the pivot
1252 Once found, they are swapped and the loop continues.
1253 Meanwhile items that are equal to the pivot are moved to the edges of the
1257 /* Move left hand items which are equal to the pivot to the far left.
1258 break when we find an item that is greater than the pivot */
1259 for(; pl < pr; pl += w) {
1260 cmp = compar(pl, pivot, ds...);
1261 if(cmp > 0) { break; }
1263 if(ple < pl) { sort_r_swap(ple, pl, w); }
1267 /* break if last batch of left hand items were equal to pivot */
1268 if(pl >= pr) { break; }
1269 /* Move right hand items which are equal to the pivot to the far right.
1270 break when we find an item that is less than the pivot */
1272 pr -= w; /* Move right pointer onto an unprocessed item */
1273 cmp = compar(pr, pivot, ds...);
1276 if(pr < pre) { sort_r_swap(pr, pre, w); }
1279 if(pl < pr) { sort_r_swap(pl, pr, w); }
1286 pl = pr; /* pr may have gone below pl */
1289 Now we need to go from: EEELLLGGGGEEEE
1291 Pivot comparison key:
1292 E = equal, L = less than, u = unknown, G = greater than, E = equal
1294 sort_r_swap_blocks(b, ple-b, pl-ple);
1295 sort_r_swap_blocks(pr, pre-pr, end-pre);
1297 /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1300 sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
1301 sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
1306 hb_qsort (void *base, size_t nel, size_t width,
1307 int (*compar)(const void *_a, const void *_b))
1309 #if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
1310 qsort (base, nel, width, compar);
1312 sort_r_simple (base, nel, width, compar);
1317 hb_qsort (void *base, size_t nel, size_t width,
1318 int (*compar)(const void *_a, const void *_b, void *_arg),
1321 #ifdef HAVE_GNU_QSORT_R
1322 qsort_r (base, nel, width, compar, arg);
1324 sort_r_simple (base, nel, width, compar, arg);
1329 template <typename T, typename T2, typename T3 = int> static inline void
1330 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
1332 static_assert (hb_is_trivially_copy_assignable (T), "");
1333 static_assert (hb_is_trivially_copy_assignable (T3), "");
1335 for (unsigned int i = 1; i < len; i++)
1338 while (j && compar (&array[j - 1], &array[i]) > 0)
1342 /* Move item i to occupy place for item j, shift what's in between. */
1345 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
1351 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
1357 static inline hb_bool_t
1358 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
1362 const char *end = p + len;
1363 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base)))
1375 template <typename T> constexpr auto
1376 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
1378 HB_FUNCOBJ (hb_bitwise_and);
1381 template <typename T> constexpr auto
1382 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
1384 HB_FUNCOBJ (hb_bitwise_or);
1387 template <typename T> constexpr auto
1388 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
1390 HB_FUNCOBJ (hb_bitwise_xor);
1393 template <typename T> constexpr auto
1394 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
1396 HB_FUNCOBJ (hb_bitwise_lt);
1399 template <typename T> constexpr auto
1400 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
1402 HB_FUNCOBJ (hb_bitwise_gt); // aka sub
1405 template <typename T> constexpr auto
1406 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
1408 HB_FUNCOBJ (hb_bitwise_le);
1411 template <typename T> constexpr auto
1412 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
1414 HB_FUNCOBJ (hb_bitwise_ge);
1417 template <typename T> constexpr auto
1418 operator () (const T &a) const HB_AUTO_RETURN (~a)
1420 HB_FUNCOBJ (hb_bitwise_neg);
1424 template <typename T, typename T2> constexpr auto
1425 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
1427 HB_FUNCOBJ (hb_add);
1430 template <typename T, typename T2> constexpr auto
1431 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
1433 HB_FUNCOBJ (hb_sub);
1436 template <typename T, typename T2> constexpr auto
1437 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
1439 HB_FUNCOBJ (hb_rsub);
1442 template <typename T, typename T2> constexpr auto
1443 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
1445 HB_FUNCOBJ (hb_mul);
1448 template <typename T, typename T2> constexpr auto
1449 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
1451 HB_FUNCOBJ (hb_div);
1454 template <typename T, typename T2> constexpr auto
1455 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
1457 HB_FUNCOBJ (hb_mod);
1460 template <typename T> constexpr auto
1461 operator () (const T &a) const HB_AUTO_RETURN (+a)
1463 HB_FUNCOBJ (hb_pos);
1466 template <typename T> constexpr auto
1467 operator () (const T &a) const HB_AUTO_RETURN (-a)
1469 HB_FUNCOBJ (hb_neg);
1472 template <typename T> constexpr auto
1473 operator () (T &a) const HB_AUTO_RETURN (++a)
1475 HB_FUNCOBJ (hb_inc);
1478 template <typename T> constexpr auto
1479 operator () (T &a) const HB_AUTO_RETURN (--a)
1481 HB_FUNCOBJ (hb_dec);
1484 /* Adapted from kurbo implementation with extra parameters added,
1485 * and finding for a particular range instead of 0.
1487 * For documentation and implementation see:
1489 * [ITP method]: https://en.wikipedia.org/wiki/ITP_Method
1490 * [An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality]: https://dl.acm.org/doi/10.1145/3423597
1491 * https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
1492 * https://github.com/linebender/kurbo/blob/fd839c25ea0c98576c7ce5789305822675a89938/src/common.rs#L162-L248
1494 template <typename func_t>
1495 double solve_itp (func_t f,
1498 double min_y, double max_y,
1499 double &ya, double &yb, double &y)
1501 unsigned n1_2 = (unsigned) (hb_max (ceil (log2 ((b - a) / epsilon)) - 1.0, 0.0));
1502 const unsigned n0 = 1; // Hardwired
1503 const double k1 = 0.2 / (b - a); // Hardwired.
1504 unsigned nmax = n0 + n1_2;
1505 double scaled_epsilon = epsilon * double (1llu << nmax);
1506 double _2_epsilon = 2.0 * epsilon;
1507 while (b - a > _2_epsilon)
1509 double x1_2 = 0.5 * (a + b);
1510 double r = scaled_epsilon - 0.5 * (b - a);
1511 double xf = (yb * a - ya * b) / (yb - ya);
1512 double sigma = x1_2 - xf;
1514 // This has k2 = 2 hardwired for efficiency.
1515 double b_a_k2 = b_a * b_a;
1516 double delta = k1 * b_a_k2;
1517 int sigma_sign = sigma >= 0 ? +1 : -1;
1518 double xt = delta <= fabs (x1_2 - xf) ? xf + delta * sigma_sign : x1_2;
1519 double xitp = fabs (xt - x1_2) <= r ? xt : x1_2 - r * sigma_sign;
1520 double yitp = f (xitp);
1526 else if (yitp < min_y)
1536 scaled_epsilon *= 0.5;
1538 return 0.5 * (a + b);
1542 #endif /* HB_ALGS_HH */