2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #define cat_(a, b) a##b
20 #define cat(a, b) cat_(a, b)
21 #define cat3(a, b, c) cat(a, cat(b, c))
22 #define cat4(a, b, c, d) cat(a, cat(b, cat(c, d)))
23 #define cat5(a, b, c, d, e) cat(a, cat(b, cat(c, cat(d, e))))
24 #define cat6(a, b, c, d, e, f) cat(a, cat(b, cat(c, cat(d, cat(e, f)))))
25 #define cat7(a, b, c, d, e, f, g) cat(a, cat(b, cat(c, cat(d, cat(e, cat(f, g))))))
27 #define n_array_elements(a) (sizeof(a) / sizeof(a[0]))
30 static const int zero
= 0;
32 static inline int zero_(void)
36 #define zero (zero_())
38 #define uzero ((unsigned)zero)
40 #define round_down(x, y) ((x) & ~((y) - 1 + 0 * (x)))
41 #define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1 + 0 * (x)))
43 #define minimum(x, y) ((x) < (y) ? (x) : (y))
44 #define maximum(x, y) ((x) >= (y) ? (x) : (y))
45 #define maximum_maybe0(x, y) ((x) >= (y) + zero ? (x) : (y))
47 #define sign_bit(type) ((type)(-((type)1 << (8 * sizeof(type) - 2)) * 2))
48 #define signed_maximum(type) (~sign_bit(type))
49 #define is_unsigned(type) ((type)-1 >= 1)
51 #define is_power_of_2(x) ((x) && !((x) & ((x) - 1)))
53 static const size_t attr_unused size_t_limit
= (size_t)-1; /* use const to avoid warning */
56 #define ajla_assert(x, msg) ((void)zero)
58 #define ajla_assert(x, msg) (likely(x) ? (void)0 : internal msg)
61 #ifndef DEBUG_LOW_OVERHEAD
62 #define ajla_assert_lo(x, msg) ((void)zero)
64 #define ajla_assert_lo(x, msg) (likely(x) ? (void)0 : internal msg)
67 #define for_all_fixed0x_(macro)
68 #define for_all_fixed1x_(macro) for_all_fixed0x_(macro) macro(0, int8_t, uint8_t, 1, 8)
69 #define for_all_fixed2x_(macro) for_all_fixed1x_(macro) macro(1, int16_t, uint16_t, 2, 16)
70 #define for_all_fixed3x_(macro) for_all_fixed2x_(macro) macro(2, int32_t, uint32_t, 4, 32)
71 #define for_all_fixed4x_(macro) for_all_fixed3x_(macro) macro(3, int64_t, uint64_t, 8, 64)
72 #define for_all_fixed5x_(macro) for_all_fixed4x_(macro) macro(4, int128_t, uint128_t, 16, 128)
73 #define for_all_fixed(macro) cat3(for_all_fixed,TYPE_FIXED_N,x_)(macro)
75 #define for_all_empty(n, t)
78 #define for_all_int1x_(m, mn) m(0, int8_t, uint8_t, 1, 8)
80 #define for_all_int1x_(m, mn) mn(0, int8_t)
83 #define for_all_int2x_(m, mn) for_all_int1x_(m, mn) m(1, int16_t, uint16_t, 2, 16)
85 #define for_all_int2x_(m, mn) for_all_int1x_(m, mn) mn(1, int16_t)
88 #define for_all_int3x_(m, mn) for_all_int2x_(m, mn) m(2, int32_t, uint32_t, 4, 32)
90 #define for_all_int3x_(m, mn) for_all_int2x_(m, mn) mn(2, int32_t)
93 #define for_all_int4x_(m, mn) for_all_int3x_(m, mn) m(3, int64_t, uint64_t, 8, 64)
95 #define for_all_int4x_(m, mn) for_all_int3x_(m, mn) mn(3, int64_t)
98 #define for_all_int5x_(m, mn) for_all_int4x_(m, mn) m(4, int128_t, uint128_t, 16, 128)
100 #define for_all_int5x_(m, mn) for_all_int4x_(m, mn) mn(4, int128_t)
102 #define for_all_int(m, mn) cat3(for_all_int,TYPE_INT_N,x_)(m, mn)
104 #define for_all_real0x_(m, mn)
106 #define for_all_real1x_(m, mn) for_all_real0x_(m, mn) m(0, real16_t, native_real16_t, pack_real16_t, unpack_real16_t)
108 #define for_all_real1x_(m, mn) for_all_real0x_(m, mn) mn(0, real16_t)
111 #define for_all_real2x_(m, mn) for_all_real1x_(m, mn) m(1, real32_t, native_real32_t, pack_real32_t, unpack_real32_t)
113 #define for_all_real2x_(m, mn) for_all_real1x_(m, mn) mn(1, real32_t)
116 #define for_all_real3x_(m, mn) for_all_real2x_(m, mn) m(2, real64_t, native_real64_t, pack_real64_t, unpack_real64_t)
118 #define for_all_real3x_(m, mn) for_all_real2x_(m, mn) mn(2, real64_t)
121 #define for_all_real4x_(m, mn) for_all_real3x_(m, mn) m(3, real80_t, native_real80_t, pack_real80_t, unpack_real80_t)
123 #define for_all_real4x_(m, mn) for_all_real3x_(m, mn) mn(3, real80_t)
126 #define for_all_real5x_(m, mn) for_all_real4x_(m, mn) m(4, real128_t, native_real128_t, pack_real128_t, unpack_real128_t)
128 #define for_all_real5x_(m, mn) for_all_real4x_(m, mn) mn(4, real128_t)
130 #define for_all_real(m, mn) cat3(for_all_real,TYPE_REAL_N,x_)(m, mn)
133 static inline unsigned low_bit(unsigned x
)
135 #if defined(HAVE_BUILTIN_CTZ)
136 return __builtin_ctz(x
);
137 #elif defined(HAVE_FFS)
151 static inline unsigned high_bit(unsigned x
)
153 #if defined(HAVE_BUILTIN_CLZ)
154 return sizeof(unsigned) * 8 - 1 - __builtin_clz(x
);
155 #elif defined(HAVE_FLS)
158 unsigned ret
= (unsigned)-1;
167 static inline unsigned log_2(unsigned x
)
169 ajla_assert(is_power_of_2(x
), (file_line
, "log_2: value %u is not a power of 2", x
));
173 static inline int pop_count(unsigned x
)
175 #if defined(HAVE_BUILTIN_POPCOUNT)
176 return __builtin_popcount(x
);
186 #define assert_alignment(ptr, align) \
187 (ajla_assert(is_power_of_2(align), (file_line, "assert_alignment: value %" PRIuMAX " is not a power of 2", (uintmax_t)(align))),\
188 ajla_assert(!((uintptr_t)(ptr) & ((align) - 1)), (file_line, "assert_alignment: pointer %p is not aligned on %" PRIuMAX "", (void *)(ptr), (uintmax_t)(align))),\
189 __builtin_assume_aligned(ptr, align))
191 #define assert_alignment(ptr, align) (__builtin_assume_aligned(ptr, align))
194 #define get_struct_(ptr, str, entry) (cast_ptr(str *, (cast_ptr(char *, (ptr)) - offsetof(str, entry))))
195 #define get_struct(ptr, str, entry) ((void)sizeof(&get_struct_(ptr, str, entry)->entry == (ptr)), get_struct_(ptr, str, entry))
197 static inline uintptr_t ptr_to_num(const void *ptr
)
199 return (uintptr_t)ptr
;
202 static inline void *num_to_ptr(uintptr_t num
)
207 #define binary_search(t, n, result, equal, less, not_found) \
212 t diff_ = end_ - start_; \
213 if (unlikely(!diff_)) { \
218 (result) = start_ + (diff_ >> 1); \
219 if (unlikely(equal)) { \
223 start_ = (result) + 1; \