@@ -276,4 +276,69 @@ SECP256K1_GNUC_EXT typedef __int128 int128_t;
276276# endif
277277#endif
278278
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+
279344#endif /* SECP256K1_UTIL_H */
0 commit comments