@@ -276,4 +276,69 @@ SECP256K1_GNUC_EXT typedef __int128 int128_t;
276
276
# endif
277
277
#endif
278
278
279
+ #ifndef __has_builtin
280
+ #define __has_builtin (x ) 0
281
+ #endif
282
+
283
+ /* Determine the number of trailing zero bits in a (non-zero) 32-bit x.
284
+ * This function is only intended to be used as fallback for
285
+ * secp256k1_ctz32_var, but permits it to be tested separately. */
286
+ static SECP256K1_INLINE int secp256k1_ctz32_var_debruijn (uint32_t x ) {
287
+ static const uint8_t debruijn [32 ] = {
288
+ 0x00 , 0x01 , 0x02 , 0x18 , 0x03 , 0x13 , 0x06 , 0x19 , 0x16 , 0x04 , 0x14 , 0x0A ,
289
+ 0x10 , 0x07 , 0x0C , 0x1A , 0x1F , 0x17 , 0x12 , 0x05 , 0x15 , 0x09 , 0x0F , 0x0B ,
290
+ 0x1E , 0x11 , 0x08 , 0x0E , 0x1D , 0x0D , 0x1C , 0x1B
291
+ };
292
+ return debruijn [((x & - x ) * 0x04D7651F ) >> 27 ];
293
+ }
294
+
295
+ /* Determine the number of trailing zero bits in a (non-zero) 64-bit x.
296
+ * This function is only intended to be used as fallback for
297
+ * secp256k1_ctz64_var, but permits it to be tested separately. */
298
+ static SECP256K1_INLINE int secp256k1_ctz64_var_debruijn (uint64_t x ) {
299
+ static const uint8_t debruijn [64 ] = {
300
+ 0 , 1 , 2 , 53 , 3 , 7 , 54 , 27 , 4 , 38 , 41 , 8 , 34 , 55 , 48 , 28 ,
301
+ 62 , 5 , 39 , 46 , 44 , 42 , 22 , 9 , 24 , 35 , 59 , 56 , 49 , 18 , 29 , 11 ,
302
+ 63 , 52 , 6 , 26 , 37 , 40 , 33 , 47 , 61 , 45 , 43 , 21 , 23 , 58 , 17 , 10 ,
303
+ 51 , 25 , 36 , 32 , 60 , 20 , 57 , 16 , 50 , 31 , 19 , 15 , 30 , 14 , 13 , 12
304
+ };
305
+ return debruijn [((x & - x ) * 0x022FDD63CC95386D ) >> 58 ];
306
+ }
307
+
308
+ /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */
309
+ static SECP256K1_INLINE int secp256k1_ctz32_var (uint32_t x ) {
310
+ VERIFY_CHECK (x != 0 );
311
+ #if (__has_builtin (__builtin_ctz ) || SECP256K1_GNUC_PREREQ (3 ,4 ))
312
+ /* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */
313
+ if (((unsigned )UINT32_MAX ) == UINT32_MAX ) {
314
+ return __builtin_ctz (x );
315
+ }
316
+ #endif
317
+ #if (__has_builtin (__builtin_ctzl ) || SECP256K1_GNUC_PREREQ (3 ,4 ))
318
+ /* Otherwise consider __builtin_ctzl (the unsigned long type is always at least 32 bits). */
319
+ return __builtin_ctzl (x );
320
+ #else
321
+ /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */
322
+ return secp256k1_ctz32_var_debruijn (x );
323
+ #endif
324
+ }
325
+
326
+ /* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */
327
+ static SECP256K1_INLINE int secp256k1_ctz64_var (uint64_t x ) {
328
+ VERIFY_CHECK (x != 0 );
329
+ #if (__has_builtin (__builtin_ctzl ) || SECP256K1_GNUC_PREREQ (3 ,4 ))
330
+ /* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */
331
+ if (((unsigned long )UINT64_MAX ) == UINT64_MAX ) {
332
+ return __builtin_ctzl (x );
333
+ }
334
+ #endif
335
+ #if (__has_builtin (__builtin_ctzll ) || SECP256K1_GNUC_PREREQ (3 ,4 ))
336
+ /* Otherwise consider __builtin_ctzll (the unsigned long long type is always at least 64 bits). */
337
+ return __builtin_ctzll (x );
338
+ #else
339
+ /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */
340
+ return secp256k1_ctz64_var_debruijn (x );
341
+ #endif
342
+ }
343
+
279
344
#endif /* SECP256K1_UTIL_H */
0 commit comments