src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh
changeset 54232 7c11a7cc7c1d
parent 50826 f5b95be8b6e2
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
    25  */
    25  */
    26 
    26 
    27 #ifndef HB_DSALGS_HH
    27 #ifndef HB_DSALGS_HH
    28 #define HB_DSALGS_HH
    28 #define HB_DSALGS_HH
    29 
    29 
    30 #include "hb-private.hh"
    30 #include "hb.hh"
    31 
    31 #include "hb-null.hh"
       
    32 
       
    33 
       
    34 /* Void! For when we need a expression-type of void. */
       
    35 typedef const struct _hb_void_t *hb_void_t;
       
    36 #define HB_VOID ((const _hb_void_t *) nullptr)
       
    37 
       
    38 
       
    39 /*
       
    40  * Bithacks.
       
    41  */
       
    42 
       
    43 /* Return the number of 1 bits in v. */
       
    44 template <typename T>
       
    45 static inline HB_CONST_FUNC unsigned int
       
    46 hb_popcount (T v)
       
    47 {
       
    48 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
       
    49   if (sizeof (T) <= sizeof (unsigned int))
       
    50     return __builtin_popcount (v);
       
    51 
       
    52   if (sizeof (T) <= sizeof (unsigned long))
       
    53     return __builtin_popcountl (v);
       
    54 
       
    55   if (sizeof (T) <= sizeof (unsigned long long))
       
    56     return __builtin_popcountll (v);
       
    57 #endif
       
    58 
       
    59   if (sizeof (T) <= 4)
       
    60   {
       
    61     /* "HACKMEM 169" */
       
    62     uint32_t y;
       
    63     y = (v >> 1) &033333333333;
       
    64     y = v - y - ((y >>1) & 033333333333);
       
    65     return (((y + (y >> 3)) & 030707070707) % 077);
       
    66   }
       
    67 
       
    68   if (sizeof (T) == 8)
       
    69   {
       
    70     unsigned int shift = 32;
       
    71     return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
       
    72   }
       
    73 
       
    74   if (sizeof (T) == 16)
       
    75   {
       
    76     unsigned int shift = 64;
       
    77     return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
       
    78   }
       
    79 
       
    80   assert (0);
       
    81   return 0; /* Shut up stupid compiler. */
       
    82 }
       
    83 
       
    84 /* Returns the number of bits needed to store number */
       
    85 template <typename T>
       
    86 static inline HB_CONST_FUNC unsigned int
       
    87 hb_bit_storage (T v)
       
    88 {
       
    89   if (unlikely (!v)) return 0;
       
    90 
       
    91 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
       
    92   if (sizeof (T) <= sizeof (unsigned int))
       
    93     return sizeof (unsigned int) * 8 - __builtin_clz (v);
       
    94 
       
    95   if (sizeof (T) <= sizeof (unsigned long))
       
    96     return sizeof (unsigned long) * 8 - __builtin_clzl (v);
       
    97 
       
    98   if (sizeof (T) <= sizeof (unsigned long long))
       
    99     return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
       
   100 #endif
       
   101 
       
   102 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
       
   103   if (sizeof (T) <= sizeof (unsigned int))
       
   104   {
       
   105     unsigned long where;
       
   106     _BitScanReverse (&where, v);
       
   107     return 1 + where;
       
   108   }
       
   109 # if defined(_WIN64)
       
   110   if (sizeof (T) <= 8)
       
   111   {
       
   112     unsigned long where;
       
   113     _BitScanReverse64 (&where, v);
       
   114     return 1 + where;
       
   115   }
       
   116 # endif
       
   117 #endif
       
   118 
       
   119   if (sizeof (T) <= 4)
       
   120   {
       
   121     /* "bithacks" */
       
   122     const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
       
   123     const unsigned int S[] = {1, 2, 4, 8, 16};
       
   124     unsigned int r = 0;
       
   125     for (int i = 4; i >= 0; i--)
       
   126       if (v & b[i])
       
   127       {
       
   128         v >>= S[i];
       
   129         r |= S[i];
       
   130       }
       
   131     return r + 1;
       
   132   }
       
   133   if (sizeof (T) <= 8)
       
   134   {
       
   135     /* "bithacks" */
       
   136     const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
       
   137     const unsigned int S[] = {1, 2, 4, 8, 16, 32};
       
   138     unsigned int r = 0;
       
   139     for (int i = 5; i >= 0; i--)
       
   140       if (v & b[i])
       
   141       {
       
   142         v >>= S[i];
       
   143         r |= S[i];
       
   144       }
       
   145     return r + 1;
       
   146   }
       
   147   if (sizeof (T) == 16)
       
   148   {
       
   149     unsigned int shift = 64;
       
   150     return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
       
   151                           hb_bit_storage<uint64_t> ((uint64_t) v);
       
   152   }
       
   153 
       
   154   assert (0);
       
   155   return 0; /* Shut up stupid compiler. */
       
   156 }
       
   157 
       
   158 /* Returns the number of zero bits in the least significant side of v */
       
   159 template <typename T>
       
   160 static inline HB_CONST_FUNC unsigned int
       
   161 hb_ctz (T v)
       
   162 {
       
   163   if (unlikely (!v)) return 0;
       
   164 
       
   165 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
       
   166   if (sizeof (T) <= sizeof (unsigned int))
       
   167     return __builtin_ctz (v);
       
   168 
       
   169   if (sizeof (T) <= sizeof (unsigned long))
       
   170     return __builtin_ctzl (v);
       
   171 
       
   172   if (sizeof (T) <= sizeof (unsigned long long))
       
   173     return __builtin_ctzll (v);
       
   174 #endif
       
   175 
       
   176 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
       
   177   if (sizeof (T) <= sizeof (unsigned int))
       
   178   {
       
   179     unsigned long where;
       
   180     _BitScanForward (&where, v);
       
   181     return where;
       
   182   }
       
   183 # if defined(_WIN64)
       
   184   if (sizeof (T) <= 8)
       
   185   {
       
   186     unsigned long where;
       
   187     _BitScanForward64 (&where, v);
       
   188     return where;
       
   189   }
       
   190 # endif
       
   191 #endif
       
   192 
       
   193   if (sizeof (T) <= 4)
       
   194   {
       
   195     /* "bithacks" */
       
   196     unsigned int c = 32;
       
   197     v &= - (int32_t) v;
       
   198     if (v) c--;
       
   199     if (v & 0x0000FFFF) c -= 16;
       
   200     if (v & 0x00FF00FF) c -= 8;
       
   201     if (v & 0x0F0F0F0F) c -= 4;
       
   202     if (v & 0x33333333) c -= 2;
       
   203     if (v & 0x55555555) c -= 1;
       
   204     return c;
       
   205   }
       
   206   if (sizeof (T) <= 8)
       
   207   {
       
   208     /* "bithacks" */
       
   209     unsigned int c = 64;
       
   210     v &= - (int64_t) (v);
       
   211     if (v) c--;
       
   212     if (v & 0x00000000FFFFFFFFULL) c -= 32;
       
   213     if (v & 0x0000FFFF0000FFFFULL) c -= 16;
       
   214     if (v & 0x00FF00FF00FF00FFULL) c -= 8;
       
   215     if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
       
   216     if (v & 0x3333333333333333ULL) c -= 2;
       
   217     if (v & 0x5555555555555555ULL) c -= 1;
       
   218     return c;
       
   219   }
       
   220   if (sizeof (T) == 16)
       
   221   {
       
   222     unsigned int shift = 64;
       
   223     return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
       
   224                           hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
       
   225   }
       
   226 
       
   227   assert (0);
       
   228   return 0; /* Shut up stupid compiler. */
       
   229 }
       
   230 
       
   231 
       
   232 /*
       
   233  * Tiny stuff.
       
   234  */
       
   235 
       
   236 template <typename T>
       
   237 static inline T* hb_addressof (T& arg)
       
   238 {
       
   239 #pragma GCC diagnostic push
       
   240 #pragma GCC diagnostic ignored "-Wcast-align"
       
   241   /* https://en.cppreference.com/w/cpp/memory/addressof */
       
   242   return reinterpret_cast<T*>(
       
   243            &const_cast<char&>(
       
   244               reinterpret_cast<const volatile char&>(arg)));
       
   245 #pragma GCC diagnostic pop
       
   246 }
       
   247 
       
   248 /* ASCII tag/character handling */
       
   249 static inline bool ISALPHA (unsigned char c)
       
   250 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
       
   251 static inline bool ISALNUM (unsigned char c)
       
   252 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
       
   253 static inline bool ISSPACE (unsigned char c)
       
   254 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
       
   255 static inline unsigned char TOUPPER (unsigned char c)
       
   256 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
       
   257 static inline unsigned char TOLOWER (unsigned char c)
       
   258 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
       
   259 
       
   260 #undef MIN
       
   261 template <typename Type>
       
   262 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
       
   263 
       
   264 #undef MAX
       
   265 template <typename Type>
       
   266 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
       
   267 
       
   268 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
       
   269 { return (a + (b - 1)) / b; }
       
   270 
       
   271 
       
   272 #undef  ARRAY_LENGTH
       
   273 template <typename Type, unsigned int n>
       
   274 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
       
   275 /* A const version, but does not detect erratically being called on pointers. */
       
   276 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
       
   277 
       
   278 
       
   279 static inline int
       
   280 hb_memcmp (const void *a, const void *b, unsigned int len)
       
   281 {
       
   282   /* It's illegal to pass NULL to memcmp(), even if len is zero.
       
   283    * So, wrap it.
       
   284    * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
       
   285   if (!len) return 0;
       
   286   return memcmp (a, b, len);
       
   287 }
       
   288 
       
   289 static inline bool
       
   290 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
       
   291 {
       
   292   return (size > 0) && (count >= ((unsigned int) -1) / size);
       
   293 }
       
   294 
       
   295 static inline unsigned int
       
   296 hb_ceil_to_4 (unsigned int v)
       
   297 {
       
   298   return ((v - 1) | 3) + 1;
       
   299 }
       
   300 
       
   301 template <typename T> struct hb_is_signed;
       
   302 /* https://github.com/harfbuzz/harfbuzz/issues/1535 */
       
   303 template <> struct hb_is_signed<int8_t> { enum { value = true }; };
       
   304 template <> struct hb_is_signed<int16_t> { enum { value = true }; };
       
   305 template <> struct hb_is_signed<int32_t> { enum { value = true }; };
       
   306 template <> struct hb_is_signed<int64_t> { enum { value = true }; };
       
   307 template <> struct hb_is_signed<uint8_t> { enum { value = false }; };
       
   308 template <> struct hb_is_signed<uint16_t> { enum { value = false }; };
       
   309 template <> struct hb_is_signed<uint32_t> { enum { value = false }; };
       
   310 template <> struct hb_is_signed<uint64_t> { enum { value = false }; };
       
   311 
       
   312 template <typename T> static inline bool
       
   313 hb_in_range (T u, T lo, T hi)
       
   314 {
       
   315   /* The sizeof() is here to force template instantiation.
       
   316    * I'm sure there are better ways to do this but can't think of
       
   317    * one right now.  Declaring a variable won't work as HB_UNUSED
       
   318    * is unusable on some platforms and unused types are less likely
       
   319    * to generate a warning than unused variables. */
       
   320   static_assert (!hb_is_signed<T>::value, "");
       
   321 
       
   322   /* The casts below are important as if T is smaller than int,
       
   323    * the subtract results will become a signed int! */
       
   324   return (T)(u - lo) <= (T)(hi - lo);
       
   325 }
       
   326 template <typename T> static inline bool
       
   327 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
       
   328 {
       
   329   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
       
   330 }
       
   331 template <typename T> static inline bool
       
   332 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
       
   333 {
       
   334   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
       
   335 }
       
   336 
       
   337 
       
   338 /*
       
   339  * Sort and search.
       
   340  */
       
   341 
       
   342 static inline void *
       
   343 hb_bsearch (const void *key, const void *base,
       
   344             size_t nmemb, size_t size,
       
   345             int (*compar)(const void *_key, const void *_item))
       
   346 {
       
   347   int min = 0, max = (int) nmemb - 1;
       
   348   while (min <= max)
       
   349   {
       
   350     int mid = (min + max) / 2;
       
   351     const void *p = (const void *) (((const char *) base) + (mid * size));
       
   352     int c = compar (key, p);
       
   353     if (c < 0)
       
   354       max = mid - 1;
       
   355     else if (c > 0)
       
   356       min = mid + 1;
       
   357     else
       
   358       return (void *) p;
       
   359   }
       
   360   return nullptr;
       
   361 }
    32 
   362 
    33 static inline void *
   363 static inline void *
    34 hb_bsearch_r (const void *key, const void *base,
   364 hb_bsearch_r (const void *key, const void *base,
    35               size_t nmemb, size_t size,
   365               size_t nmemb, size_t size,
    36               int (*compar)(const void *_key, const void *_item, void *_arg),
   366               int (*compar)(const void *_key, const void *_item, void *_arg),
    37               void *arg)
   367               void *arg)
    38 {
   368 {
    39   int min = 0, max = (int) nmemb - 1;
   369   int min = 0, max = (int) nmemb - 1;
    40   while (min <= max)
   370   while (min <= max)
    41   {
   371   {
    42     int mid = (min + max) / 2;
   372     int mid = ((unsigned int) min + (unsigned int) max) / 2;
    43     const void *p = (const void *) (((const char *) base) + (mid * size));
   373     const void *p = (const void *) (((const char *) base) + (mid * size));
    44     int c = compar (key, p, arg);
   374     int c = compar (key, p, arg);
    45     if (c < 0)
   375     if (c < 0)
    46       max = mid - 1;
   376       max = mid - 1;
    47     else if (c > 0)
   377     else if (c > 0)
    51   }
   381   }
    52   return nullptr;
   382   return nullptr;
    53 }
   383 }
    54 
   384 
    55 
   385 
    56 
   386 /* From https://github.com/noporpoise/sort_r
    57 /* From https://github.com/noporpoise/sort_r */
   387  * With following modifications:
       
   388  *
       
   389  * 10 November 2018:
       
   390  * https://github.com/noporpoise/sort_r/issues/7
       
   391  */
    58 
   392 
    59 /* Isaac Turner 29 April 2014 Public Domain */
   393 /* Isaac Turner 29 April 2014 Public Domain */
    60 
   394 
    61 /*
   395 /*
    62 
   396 
   108   {
   442   {
   109     /* nel > 6; Quicksort */
   443     /* nel > 6; Quicksort */
   110 
   444 
   111     /* Use median of first, middle and last items as pivot */
   445     /* Use median of first, middle and last items as pivot */
   112     char *x, *y, *xend, ch;
   446     char *x, *y, *xend, ch;
   113     char *pl, *pr;
   447     char *pl, *pm, *pr;
   114     char *last = b+w*(nel-1), *tmp;
   448     char *last = b+w*(nel-1), *tmp;
   115     char *l[3];
   449     char *l[3];
   116     l[0] = b;
   450     l[0] = b;
   117     l[1] = b+w*(nel/2);
   451     l[1] = b+w*(nel/2);
   118     l[2] = last;
   452     l[2] = last;
   130 
   464 
   131     pl = b;
   465     pl = b;
   132     pr = last;
   466     pr = last;
   133 
   467 
   134     while(pl < pr) {
   468     while(pl < pr) {
   135       for(; pl < pr; pl += w) {
   469       pm = pl+((pr-pl+1)>>1);
       
   470       for(; pl < pm; pl += w) {
   136         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
   471         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
   137           pr -= w; /* pivot now at pl */
   472           pr -= w; /* pivot now at pl */
   138           break;
   473           break;
   139         }
   474         }
   140       }
   475       }
   141       for(; pl < pr; pr -= w) {
   476       pm = pl+((pr-pl)>>1);
       
   477       for(; pm < pr; pr -= w) {
   142         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
   478         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
   143           pl += w; /* pivot now at pr */
   479           pl += w; /* pivot now at pr */
   144           break;
   480           break;
   145         }
   481         }
   146       }
   482       }
   156                              void *arg)
   492                              void *arg)
   157 {
   493 {
   158     sort_r_simple(base, nel, width, compar, arg);
   494     sort_r_simple(base, nel, width, compar, arg);
   159 }
   495 }
   160 
   496 
       
   497 
       
   498 template <typename T, typename T2> static inline void
       
   499 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
       
   500 {
       
   501   for (unsigned int i = 1; i < len; i++)
       
   502   {
       
   503     unsigned int j = i;
       
   504     while (j && compar (&array[j - 1], &array[i]) > 0)
       
   505       j--;
       
   506     if (i == j)
       
   507       continue;
       
   508     /* Move item i to occupy place for item j, shift what's in between. */
       
   509     {
       
   510       T t = array[i];
       
   511       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
       
   512       array[j] = t;
       
   513     }
       
   514     if (array2)
       
   515     {
       
   516       T2 t = array2[i];
       
   517       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
       
   518       array2[j] = t;
       
   519     }
       
   520   }
       
   521 }
       
   522 
       
   523 template <typename T> static inline void
       
   524 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
       
   525 {
       
   526   hb_stable_sort (array, len, compar, (int *) nullptr);
       
   527 }
       
   528 
       
   529 static inline hb_bool_t
       
   530 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
       
   531 {
       
   532   /* Pain because we don't know whether s is nul-terminated. */
       
   533   char buf[64];
       
   534   len = MIN (ARRAY_LENGTH (buf) - 1, len);
       
   535   strncpy (buf, s, len);
       
   536   buf[len] = '\0';
       
   537 
       
   538   char *end;
       
   539   errno = 0;
       
   540   unsigned long v = strtoul (buf, &end, base);
       
   541   if (errno) return false;
       
   542   if (*end) return false;
       
   543   *out = v;
       
   544   return true;
       
   545 }
       
   546 
       
   547 
       
   548 struct HbOpOr
       
   549 {
       
   550   static constexpr bool passthru_left = true;
       
   551   static constexpr bool passthru_right = true;
       
   552   template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
       
   553 };
       
   554 struct HbOpAnd
       
   555 {
       
   556   static constexpr bool passthru_left = false;
       
   557   static constexpr bool passthru_right = false;
       
   558   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
       
   559 };
       
   560 struct HbOpMinus
       
   561 {
       
   562   static constexpr bool passthru_left = true;
       
   563   static constexpr bool passthru_right = false;
       
   564   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
       
   565 };
       
   566 struct HbOpXor
       
   567 {
       
   568   static constexpr bool passthru_left = true;
       
   569   static constexpr bool passthru_right = true;
       
   570   template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
       
   571 };
       
   572 
       
   573 
       
   574 /* Compiler-assisted vectorization. */
       
   575 
       
   576 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
       
   577  * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
       
   578  * Define that to 0 to disable. */
       
   579 template <typename elt_t, unsigned int byte_size>
       
   580 struct hb_vector_size_t
       
   581 {
       
   582   elt_t& operator [] (unsigned int i) { return u.v[i]; }
       
   583   const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
       
   584 
       
   585   void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
       
   586 
       
   587   template <class Op>
       
   588   hb_vector_size_t process (const hb_vector_size_t &o) const
       
   589   {
       
   590     hb_vector_size_t r;
       
   591 #if HB_VECTOR_SIZE
       
   592     if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
       
   593       for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
       
   594         Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
       
   595     else
       
   596 #endif
       
   597       for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
       
   598         Op::process (r.u.v[i], u.v[i], o.u.v[i]);
       
   599     return r;
       
   600   }
       
   601   hb_vector_size_t operator | (const hb_vector_size_t &o) const
       
   602   { return process<HbOpOr> (o); }
       
   603   hb_vector_size_t operator & (const hb_vector_size_t &o) const
       
   604   { return process<HbOpAnd> (o); }
       
   605   hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
       
   606   { return process<HbOpXor> (o); }
       
   607   hb_vector_size_t operator ~ () const
       
   608   {
       
   609     hb_vector_size_t r;
       
   610 #if HB_VECTOR_SIZE && 0
       
   611     if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
       
   612       for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
       
   613         r.u.vec[i] = ~u.vec[i];
       
   614     else
       
   615 #endif
       
   616     for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
       
   617       r.u.v[i] = ~u.v[i];
       
   618     return r;
       
   619   }
       
   620 
       
   621   private:
       
   622   static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
       
   623   union {
       
   624     elt_t v[byte_size / sizeof (elt_t)];
       
   625 #if HB_VECTOR_SIZE
       
   626     hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
       
   627 #endif
       
   628   } u;
       
   629 };
       
   630 
       
   631 
   161 #endif /* HB_DSALGS_HH */
   632 #endif /* HB_DSALGS_HH */