1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#include "./blapi-build_p.h"
8#include "./blsupport_p.h"
9
10// ============================================================================
11// [BLScopedAllocator]
12// ============================================================================
13
14void* BLScopedAllocator::alloc(size_t size, size_t alignment) noexcept {
15 // First try to allocate from the local memory pool.
16 uint8_t* p = blAlignUp(poolPtr, alignment);
17 size_t remain = size_t(blUSubSaturate((uintptr_t)poolEnd, (uintptr_t)p));
18
19 if (remain >= size) {
20 poolPtr = p + size;
21 return p;
22 }
23
24 // Bail to malloc of local pool was either not provided or didn't have the
25 // required capacity.
26 size_t sizeWithOverhead = size + sizeof(Link) + (alignment - 1);
27 p = static_cast<uint8_t*>(malloc(sizeWithOverhead));
28
29 if (p == nullptr)
30 return nullptr;
31
32 reinterpret_cast<Link*>(p)->next = links;
33 links = reinterpret_cast<Link*>(p);
34
35 return blAlignUp(p + sizeof(Link), alignment);
36}
37
38void BLScopedAllocator::reset() noexcept {
39 Link* link = links;
40 while (link) {
41 Link* next = link->next;
42 free(link);
43 link = next;
44 }
45
46 links = nullptr;
47 poolPtr = poolMem;
48}
49
50// ============================================================================
51// [BLSupport - Unit Tests]
52// ============================================================================
53
54#ifdef BL_TEST
55template<typename T>
56BL_INLINE bool testIsConsecutiveBitMask(T x) {
57 if (x == 0)
58 return false;
59
60 T m = x;
61 while ((m & 0x1) == 0)
62 m >>= 1;
63 return ((m + 1) & m) == 0;
64}
65
66static void testAlignment() noexcept {
67 INFO("blIsAligned()");
68 EXPECT(blIsAligned<size_t>(0xFFFF, 4) == false);
69 EXPECT(blIsAligned<size_t>(0xFFF4, 4) == true);
70 EXPECT(blIsAligned<size_t>(0xFFF8, 8) == true);
71 EXPECT(blIsAligned<size_t>(0xFFF0, 16) == true);
72
73 INFO("blAlignUp()");
74 EXPECT(blAlignUp<size_t>(0xFFFF, 4) == 0x10000);
75 EXPECT(blAlignUp<size_t>(0xFFF4, 4) == 0x0FFF4);
76 EXPECT(blAlignUp<size_t>(0xFFF8, 8) == 0x0FFF8);
77 EXPECT(blAlignUp<size_t>(0xFFF0, 16) == 0x0FFF0);
78 EXPECT(blAlignUp<size_t>(0xFFF0, 32) == 0x10000);
79
80 INFO("blAlignUpDiff()");
81 EXPECT(blAlignUpDiff<size_t>(0xFFFF, 4) == 1);
82 EXPECT(blAlignUpDiff<size_t>(0xFFF4, 4) == 0);
83 EXPECT(blAlignUpDiff<size_t>(0xFFF8, 8) == 0);
84 EXPECT(blAlignUpDiff<size_t>(0xFFF0, 16) == 0);
85 EXPECT(blAlignUpDiff<size_t>(0xFFF0, 32) == 16);
86
87 INFO("blAlignUpPowerOf2()");
88 EXPECT(blAlignUpPowerOf2<size_t>(0x0000) == 0x00000);
89 EXPECT(blAlignUpPowerOf2<size_t>(0xFFFF) == 0x10000);
90 EXPECT(blAlignUpPowerOf2<size_t>(0xF123) == 0x10000);
91 EXPECT(blAlignUpPowerOf2<size_t>(0x0F00) == 0x01000);
92 EXPECT(blAlignUpPowerOf2<size_t>(0x0100) == 0x00100);
93 EXPECT(blAlignUpPowerOf2<size_t>(0x1001) == 0x02000);
94}
95
96static void testBitUtils() noexcept {
97 uint32_t i;
98
99 INFO("blBitShl() / blBitShr()");
100 EXPECT(blBitShl<int32_t >(0x00001111 , 16) == 0x11110000 );
101 EXPECT(blBitShl<uint32_t>(0x00001111 , 16) == 0x11110000 );
102 EXPECT(blBitShr<int32_t >(0x11110000u, 16) == 0x00001111u);
103 EXPECT(blBitShr<uint32_t>(0x11110000u, 16) == 0x00001111u);
104 EXPECT(blBitSar<uint32_t>(0xFFFF0000u, 16) == 0xFFFFFFFFu);
105
106 INFO("blBitRol() / blBitRor()");
107 EXPECT(blBitRol<int32_t >(0x00100000 , 16) == 0x00000010 );
108 EXPECT(blBitRol<uint32_t>(0x00100000u, 16) == 0x00000010u);
109 EXPECT(blBitRor<int32_t >(0x00001000 , 16) == 0x10000000 );
110 EXPECT(blBitRor<uint32_t>(0x00001000u, 16) == 0x10000000u);
111
112 INFO("blBitCtz()");
113 EXPECT(blBitCtz(1u) == 0);
114 EXPECT(blBitCtz(2u) == 1);
115 EXPECT(blBitCtz(3u) == 0);
116 EXPECT(blBitCtz(0x80000000u) == 31);
117 EXPECT(blBitCtzStatic(1u) == 0);
118 EXPECT(blBitCtzStatic(2u) == 1);
119 EXPECT(blBitCtzStatic(3u) == 0);
120 EXPECT(blBitCtzStatic(0x80000000u) == 31);
121
122 INFO("blIsPowerOf2()");
123 for (i = 0; i < 64; i++) {
124 EXPECT(blIsPowerOf2(uint64_t(1) << i) == true);
125 EXPECT(blIsPowerOf2((uint64_t(1) << i) ^ 0x001101) == false);
126 }
127
128 INFO("blIsBitMaskConsecutive()");
129 i = 0;
130 for (;;) {
131 bool result = blIsBitMaskConsecutive(i);
132 bool expect = testIsConsecutiveBitMask(i);
133 EXPECT(result == expect);
134
135 if (i == 0xFFFFu)
136 break;
137 i++;
138 }
139}
140
141static void testIntUtils() noexcept {
142 uint32_t i;
143
144 INFO("blByteSwap()");
145 EXPECT(blByteSwap16(int16_t(0x0102)) == int16_t(0x0201));
146 EXPECT(blByteSwap16(uint16_t(0x0102)) == uint16_t(0x0201));
147 EXPECT(blByteSwap24(int32_t(0x00010203)) == int32_t(0x00030201));
148 EXPECT(blByteSwap24(uint32_t(0x00010203)) == uint32_t(0x00030201));
149 EXPECT(blByteSwap32(int32_t(0x01020304)) == int32_t(0x04030201));
150 EXPECT(blByteSwap32(uint32_t(0x01020304)) == uint32_t(0x04030201));
151 EXPECT(blByteSwap64(uint64_t(0x0102030405060708)) == uint64_t(0x0807060504030201));
152
153 INFO("blClamp()");
154 EXPECT(blClamp<int>(-1, 100, 1000) == 100);
155 EXPECT(blClamp<int>(99, 100, 1000) == 100);
156 EXPECT(blClamp<int>(1044, 100, 1000) == 1000);
157 EXPECT(blClamp<double>(-1.0, 100.0, 1000.0) == 100.0);
158 EXPECT(blClamp<double>(99.0, 100.0, 1000.0) == 100.0);
159 EXPECT(blClamp<double>(1044.0, 100.0, 1000.0) == 1000.0);
160
161 INFO("blClampToByte()");
162 EXPECT(blClampToByte(-1) == 0);
163 EXPECT(blClampToByte(42) == 42);
164 EXPECT(blClampToByte(255) == 0xFF);
165 EXPECT(blClampToByte(256) == 0xFF);
166 EXPECT(blClampToByte(0x7FFFFFFF) == 0xFF);
167 EXPECT(blClampToByte(0x7FFFFFFFu) == 0xFF);
168 EXPECT(blClampToByte(0xFFFFFFFFu) == 0xFF);
169
170 INFO("blClampToWord()");
171 EXPECT(blClampToWord(-1) == 0);
172 EXPECT(blClampToWord(42) == 42);
173 EXPECT(blClampToWord(0xFFFF) == 0xFFFF);
174 EXPECT(blClampToWord(0x10000) == 0xFFFF);
175 EXPECT(blClampToWord(0x10000u) == 0xFFFF);
176 EXPECT(blClampToWord(0x7FFFFFFF) == 0xFFFF);
177 EXPECT(blClampToWord(0x7FFFFFFFu) == 0xFFFF);
178 EXPECT(blClampToWord(0xFFFFFFFFu) == 0xFFFF);
179
180 INFO("blUdiv255()");
181 for (i = 0; i < 255 * 255; i++) {
182 uint32_t result = blUdiv255(i);
183 uint32_t j = i + 128;
184
185 // This version doesn't overflow 16 bits.
186 uint32_t expected = (j + (j >> 8)) >> 8;
187
188 EXPECT(result == expected, "blUdiv255(%u) -> %u (Expected %u)", i, result, expected);
189 }
190}
191
192static void testSafeArith() noexcept {
193 INFO("blAddOverflow()");
194 BLOverflowFlag of = 0;
195
196 EXPECT(blAddOverflow<int32_t>(0, 0, &of) == 0 && !of);
197 EXPECT(blAddOverflow<int32_t>(0, 1, &of) == 1 && !of);
198 EXPECT(blAddOverflow<int32_t>(1, 0, &of) == 1 && !of);
199
200 EXPECT(blAddOverflow<int32_t>(2147483647, 0, &of) == 2147483647 && !of);
201 EXPECT(blAddOverflow<int32_t>(0, 2147483647, &of) == 2147483647 && !of);
202 EXPECT(blAddOverflow<int32_t>(2147483647, -1, &of) == 2147483646 && !of);
203 EXPECT(blAddOverflow<int32_t>(-1, 2147483647, &of) == 2147483646 && !of);
204
205 EXPECT(blAddOverflow<int32_t>(-2147483647, 0, &of) == -2147483647 && !of);
206 EXPECT(blAddOverflow<int32_t>(0, -2147483647, &of) == -2147483647 && !of);
207 EXPECT(blAddOverflow<int32_t>(-2147483647, -1, &of) == -2147483647 - 1 && !of);
208 EXPECT(blAddOverflow<int32_t>(-1, -2147483647, &of) == -2147483647 - 1 && !of);
209
210 blAddOverflow<int32_t>(2147483647, 1, &of); EXPECT(of); of = 0;
211 blAddOverflow<int32_t>(1, 2147483647, &of); EXPECT(of); of = 0;
212 blAddOverflow<int32_t>(-2147483647, -2, &of); EXPECT(of); of = 0;
213 blAddOverflow<int32_t>(-2, -2147483647, &of); EXPECT(of); of = 0;
214
215 EXPECT(blAddOverflow<uint32_t>(0u, 0u, &of) == 0 && !of);
216 EXPECT(blAddOverflow<uint32_t>(0u, 1u, &of) == 1 && !of);
217 EXPECT(blAddOverflow<uint32_t>(1u, 0u, &of) == 1 && !of);
218
219 EXPECT(blAddOverflow<uint32_t>(2147483647u, 1u, &of) == 2147483648u && !of);
220 EXPECT(blAddOverflow<uint32_t>(1u, 2147483647u, &of) == 2147483648u && !of);
221 EXPECT(blAddOverflow<uint32_t>(0xFFFFFFFFu, 0u, &of) == 0xFFFFFFFFu && !of);
222 EXPECT(blAddOverflow<uint32_t>(0u, 0xFFFFFFFFu, &of) == 0xFFFFFFFFu && !of);
223
224 blAddOverflow<uint32_t>(0xFFFFFFFFu, 1u, &of); EXPECT(of); of = 0;
225 blAddOverflow<uint32_t>(1u, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
226
227 blAddOverflow<uint32_t>(0x80000000u, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
228 blAddOverflow<uint32_t>(0xFFFFFFFFu, 0x80000000u, &of); EXPECT(of); of = 0;
229 blAddOverflow<uint32_t>(0xFFFFFFFFu, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
230
231 INFO("blSubOverflow()");
232 EXPECT(blSubOverflow<int32_t>(0, 0, &of) == 0 && !of);
233 EXPECT(blSubOverflow<int32_t>(0, 1, &of) == -1 && !of);
234 EXPECT(blSubOverflow<int32_t>(1, 0, &of) == 1 && !of);
235 EXPECT(blSubOverflow<int32_t>(0, -1, &of) == 1 && !of);
236 EXPECT(blSubOverflow<int32_t>(-1, 0, &of) == -1 && !of);
237
238 EXPECT(blSubOverflow<int32_t>(2147483647, 1, &of) == 2147483646 && !of);
239 EXPECT(blSubOverflow<int32_t>(2147483647, 2147483647, &of) == 0 && !of);
240 EXPECT(blSubOverflow<int32_t>(-2147483647, 1, &of) == -2147483647 - 1 && !of);
241 EXPECT(blSubOverflow<int32_t>(-2147483647, -1, &of) == -2147483646 && !of);
242 EXPECT(blSubOverflow<int32_t>(-2147483647 - 0, -2147483647 - 0, &of) == 0 && !of);
243 EXPECT(blSubOverflow<int32_t>(-2147483647 - 1, -2147483647 - 1, &of) == 0 && !of);
244
245 blSubOverflow<int32_t>(-2, 2147483647, &of); EXPECT(of); of = 0;
246 blSubOverflow<int32_t>(-2147483647, 2, &of); EXPECT(of); of = 0;
247
248 blSubOverflow<int32_t>(-2147483647 , 2147483647, &of); EXPECT(of); of = 0;
249 blSubOverflow<int32_t>(-2147483647 - 1, 2147483647, &of); EXPECT(of); of = 0;
250
251 blSubOverflow<int32_t>(2147483647, -2147483647 - 0, &of); EXPECT(of); of = 0;
252 blSubOverflow<int32_t>(2147483647, -2147483647 - 1, &of); EXPECT(of); of = 0;
253
254 EXPECT(blSubOverflow<uint32_t>(0, 0, &of) == 0 && !of);
255 EXPECT(blSubOverflow<uint32_t>(1, 0, &of) == 1 && !of);
256
257 EXPECT(blSubOverflow<uint32_t>(0xFFFFFFFFu, 0u, &of) == 0xFFFFFFFFu && !of);
258 EXPECT(blSubOverflow<uint32_t>(0xFFFFFFFFu, 0xFFFFFFFFu, &of) == 0u && !of);
259
260 blSubOverflow<uint32_t>(0u, 1u, &of); EXPECT(of); of = 0;
261 blSubOverflow<uint32_t>(1u, 2u, &of); EXPECT(of); of = 0;
262
263 blSubOverflow<uint32_t>(0u, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
264 blSubOverflow<uint32_t>(1u, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
265
266 blSubOverflow<uint32_t>(0u, 0x7FFFFFFFu, &of); EXPECT(of); of = 0;
267 blSubOverflow<uint32_t>(1u, 0x7FFFFFFFu, &of); EXPECT(of); of = 0;
268
269 blSubOverflow<uint32_t>(0x7FFFFFFEu, 0x7FFFFFFFu, &of); EXPECT(of); of = 0;
270 blSubOverflow<uint32_t>(0xFFFFFFFEu, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
271
272 INFO("blMulOverflow()");
273 EXPECT(blMulOverflow<int32_t>(0, 0, &of) == 0 && !of);
274 EXPECT(blMulOverflow<int32_t>(0, 1, &of) == 0 && !of);
275 EXPECT(blMulOverflow<int32_t>(1, 0, &of) == 0 && !of);
276
277 EXPECT(blMulOverflow<int32_t>( 1, 1, &of) == 1 && !of);
278 EXPECT(blMulOverflow<int32_t>( 1, -1, &of) == -1 && !of);
279 EXPECT(blMulOverflow<int32_t>(-1, 1, &of) == -1 && !of);
280 EXPECT(blMulOverflow<int32_t>(-1, -1, &of) == 1 && !of);
281
282 EXPECT(blMulOverflow<int32_t>( 32768, 65535, &of) == 2147450880 && !of);
283 EXPECT(blMulOverflow<int32_t>( 32768, -65535, &of) == -2147450880 && !of);
284 EXPECT(blMulOverflow<int32_t>(-32768, 65535, &of) == -2147450880 && !of);
285 EXPECT(blMulOverflow<int32_t>(-32768, -65535, &of) == 2147450880 && !of);
286
287 EXPECT(blMulOverflow<int32_t>(2147483647, 1, &of) == 2147483647 && !of);
288 EXPECT(blMulOverflow<int32_t>(1, 2147483647, &of) == 2147483647 && !of);
289
290 EXPECT(blMulOverflow<int32_t>(-2147483647 - 1, 1, &of) == -2147483647 - 1 && !of);
291 EXPECT(blMulOverflow<int32_t>(1, -2147483647 - 1, &of) == -2147483647 - 1 && !of);
292
293 blMulOverflow<int32_t>( 65535, 65535, &of); EXPECT(of); of = 0;
294 blMulOverflow<int32_t>( 65535, -65535, &of); EXPECT(of); of = 0;
295 blMulOverflow<int32_t>(-65535, 65535, &of); EXPECT(of); of = 0;
296 blMulOverflow<int32_t>(-65535, -65535, &of); EXPECT(of); of = 0;
297
298 blMulOverflow<int32_t>( 2147483647 , 2147483647 , &of); EXPECT(of); of = 0;
299 blMulOverflow<int32_t>( 2147483647 , -2147483647 - 1, &of); EXPECT(of); of = 0;
300 blMulOverflow<int32_t>(-2147483647 - 1, 2147483647 , &of); EXPECT(of); of = 0;
301 blMulOverflow<int32_t>(-2147483647 - 1, -2147483647 - 1, &of); EXPECT(of); of = 0;
302
303 EXPECT(blMulOverflow<uint32_t>(0, 0, &of) == 0 && !of);
304 EXPECT(blMulOverflow<uint32_t>(0, 1, &of) == 0 && !of);
305 EXPECT(blMulOverflow<uint32_t>(1, 0, &of) == 0 && !of);
306 EXPECT(blMulOverflow<uint32_t>(1, 1, &of) == 1 && !of);
307
308 EXPECT(blMulOverflow<uint32_t>(0x10000000u, 15, &of) == 0xF0000000u && !of);
309 EXPECT(blMulOverflow<uint32_t>(15, 0x10000000u, &of) == 0xF0000000u && !of);
310
311 EXPECT(blMulOverflow<uint32_t>(0xFFFFFFFFu, 1, &of) == 0xFFFFFFFFu && !of);
312 EXPECT(blMulOverflow<uint32_t>(1, 0xFFFFFFFFu, &of) == 0xFFFFFFFFu && !of);
313
314 blMulOverflow<uint32_t>(0xFFFFFFFFu, 2, &of); EXPECT(of); of = 0;
315 blMulOverflow<uint32_t>(2, 0xFFFFFFFFu, &of); EXPECT(of); of = 0;
316
317 blMulOverflow<uint32_t>(0x80000000u, 2, &of); EXPECT(of); of = 0;
318 blMulOverflow<uint32_t>(2, 0x80000000u, &of); EXPECT(of); of = 0;
319
320 EXPECT(blMulOverflow<int64_t>(0, 0, &of) == 0 && !of);
321 EXPECT(blMulOverflow<int64_t>(0, 1, &of) == 0 && !of);
322 EXPECT(blMulOverflow<int64_t>(1, 0, &of) == 0 && !of);
323
324 EXPECT(blMulOverflow<int64_t>( 1, 1, &of) == 1 && !of);
325 EXPECT(blMulOverflow<int64_t>( 1, -1, &of) == -1 && !of);
326 EXPECT(blMulOverflow<int64_t>(-1, 1, &of) == -1 && !of);
327 EXPECT(blMulOverflow<int64_t>(-1, -1, &of) == 1 && !of);
328
329 EXPECT(blMulOverflow<int64_t>( 32768, 65535, &of) == 2147450880 && !of);
330 EXPECT(blMulOverflow<int64_t>( 32768, -65535, &of) == -2147450880 && !of);
331 EXPECT(blMulOverflow<int64_t>(-32768, 65535, &of) == -2147450880 && !of);
332 EXPECT(blMulOverflow<int64_t>(-32768, -65535, &of) == 2147450880 && !of);
333
334 EXPECT(blMulOverflow<int64_t>(2147483647, 1, &of) == 2147483647 && !of);
335 EXPECT(blMulOverflow<int64_t>(1, 2147483647, &of) == 2147483647 && !of);
336
337 EXPECT(blMulOverflow<int64_t>(-2147483647 - 1, 1, &of) == -2147483647 - 1 && !of);
338 EXPECT(blMulOverflow<int64_t>(1, -2147483647 - 1, &of) == -2147483647 - 1 && !of);
339
340 EXPECT(blMulOverflow<int64_t>( 65535, 65535, &of) == int64_t(4294836225) && !of);
341 EXPECT(blMulOverflow<int64_t>( 65535, -65535, &of) == -int64_t(4294836225) && !of);
342 EXPECT(blMulOverflow<int64_t>(-65535, 65535, &of) == -int64_t(4294836225) && !of);
343 EXPECT(blMulOverflow<int64_t>(-65535, -65535, &of) == int64_t(4294836225) && !of);
344
345 EXPECT(blMulOverflow<int64_t>( 2147483647 , 2147483647 , &of) == int64_t(4611686014132420609) && !of);
346 EXPECT(blMulOverflow<int64_t>( 2147483647 , -2147483647 - 1, &of) == -int64_t(4611686016279904256) && !of);
347 EXPECT(blMulOverflow<int64_t>(-2147483647 - 1, 2147483647 , &of) == -int64_t(4611686016279904256) && !of);
348 EXPECT(blMulOverflow<int64_t>(-2147483647 - 1, -2147483647 - 1, &of) == int64_t(4611686018427387904) && !of);
349
350 EXPECT(blMulOverflow<int64_t>(int64_t(0x7FFFFFFFFFFFFFFF), int64_t(1), &of) == int64_t(0x7FFFFFFFFFFFFFFF) && !of);
351 EXPECT(blMulOverflow<int64_t>(int64_t(1), int64_t(0x7FFFFFFFFFFFFFFF), &of) == int64_t(0x7FFFFFFFFFFFFFFF) && !of);
352
353 blMulOverflow<int64_t>(int64_t(0x7FFFFFFFFFFFFFFF), int64_t(2), &of); EXPECT(of); of = 0;
354 blMulOverflow<int64_t>(int64_t(2), int64_t(0x7FFFFFFFFFFFFFFF), &of); EXPECT(of); of = 0;
355
356 blMulOverflow<int64_t>(int64_t( 0x7FFFFFFFFFFFFFFF), int64_t( 0x7FFFFFFFFFFFFFFF), &of); EXPECT(of); of = 0;
357 blMulOverflow<int64_t>(int64_t( 0x7FFFFFFFFFFFFFFF), int64_t(-0x7FFFFFFFFFFFFFFF), &of); EXPECT(of); of = 0;
358 blMulOverflow<int64_t>(int64_t(-0x7FFFFFFFFFFFFFFF), int64_t( 0x7FFFFFFFFFFFFFFF), &of); EXPECT(of); of = 0;
359 blMulOverflow<int64_t>(int64_t(-0x7FFFFFFFFFFFFFFF), int64_t(-0x7FFFFFFFFFFFFFFF), &of); EXPECT(of); of = 0;
360
361 EXPECT(blMulOverflow<uint64_t>(0, 0, &of) == 0 && !of);
362 EXPECT(blMulOverflow<uint64_t>(0, 1, &of) == 0 && !of);
363 EXPECT(blMulOverflow<uint64_t>(1, 0, &of) == 0 && !of);
364 EXPECT(blMulOverflow<uint64_t>(1, 1, &of) == 1 && !of);
365
366 EXPECT(blMulOverflow<uint64_t>(0x1000000000000000u, 15, &of) == 0xF000000000000000u && !of);
367 EXPECT(blMulOverflow<uint64_t>(15, 0x1000000000000000u, &of) == 0xF000000000000000u && !of);
368
369 EXPECT(blMulOverflow<uint64_t>(0xFFFFFFFFFFFFFFFFu, 1, &of) == 0xFFFFFFFFFFFFFFFFu && !of);
370 EXPECT(blMulOverflow<uint64_t>(1, 0xFFFFFFFFFFFFFFFFu, &of) == 0xFFFFFFFFFFFFFFFFu && !of);
371
372 blMulOverflow<uint64_t>(0xFFFFFFFFFFFFFFFFu, 2, &of); EXPECT(of); of = 0;
373 blMulOverflow<uint64_t>(2, 0xFFFFFFFFFFFFFFFFu, &of); EXPECT(of); of = 0;
374
375 blMulOverflow<uint64_t>(0x8000000000000000u, 2, &of); EXPECT(of); of = 0;
376 blMulOverflow<uint64_t>(2, 0x8000000000000000u, &of); EXPECT(of); of = 0;
377}
378
379static void testReadWrite() noexcept {
380 INFO("blMemRead() / blMemWrite()");
381 {
382 uint8_t arr[32] = { 0 };
383
384 blMemWriteU16uBE(arr + 1, 0x0102u);
385 blMemWriteU16uBE(arr + 3, 0x0304u);
386 EXPECT(blMemReadU32uBE(arr + 1) == 0x01020304u);
387 EXPECT(blMemReadU32uLE(arr + 1) == 0x04030201u);
388 EXPECT(blMemReadU32uBE(arr + 2) == 0x02030400u);
389 EXPECT(blMemReadU32uLE(arr + 2) == 0x00040302u);
390
391 blMemWriteU32uLE(arr + 5, 0x05060708u);
392 EXPECT(blMemReadU64uBE(arr + 1) == 0x0102030408070605u);
393 EXPECT(blMemReadU64uLE(arr + 1) == 0x0506070804030201u);
394
395 blMemWriteU64uLE(arr + 7, 0x1122334455667788u);
396 EXPECT(blMemReadU32uBE(arr + 8) == 0x77665544u);
397 }
398}
399
400UNIT(blend2d_support) {
401 testAlignment();
402 testBitUtils();
403 testIntUtils();
404 testSafeArith();
405 testReadWrite();
406}
407#endif
408