math.c (2167B)
1 // uncrustify:off 2 #include <math.h> 3 // uncrustify:on 4 #include <limits.h> 5 #include <stdint.h> 6 #include <string.h> 7 8 #ifdef HAVE_BITSCANFORWARD64 9 # include <intrin.h> // Required for _BitScanForward64 10 #endif 11 12 #include "nvim/math.h" 13 #include "nvim/vim_defs.h" 14 15 #include "math.c.generated.h" 16 17 int xfpclassify(double d) 18 FUNC_ATTR_CONST 19 { 20 uint64_t m; 21 22 memcpy(&m, &d, sizeof(m)); 23 int e = 0x7ff & (m >> 52); 24 m = 0xfffffffffffffULL & m; 25 26 switch (e) { 27 default: 28 return FP_NORMAL; 29 case 0x000: 30 return m ? FP_SUBNORMAL : FP_ZERO; 31 case 0x7ff: 32 return m ? FP_NAN : FP_INFINITE; 33 } 34 } 35 36 int xisinf(double d) 37 FUNC_ATTR_CONST 38 { 39 return FP_INFINITE == xfpclassify(d); 40 } 41 42 int xisnan(double d) 43 FUNC_ATTR_CONST 44 { 45 return FP_NAN == xfpclassify(d); 46 } 47 48 /// Count trailing zeroes at the end of bit field. 49 int xctz(uint64_t x) 50 { 51 // If x == 0, that means all bits are zeroes. 52 if (x == 0) { 53 return 8 * sizeof(x); 54 } 55 56 // Use compiler builtin if possible. 57 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 4)) 58 return __builtin_ctzll(x); 59 #elif defined(HAVE_BITSCANFORWARD64) 60 unsigned long index; 61 _BitScanForward64(&index, x); 62 return (int)index; 63 #else 64 int count = 0; 65 // Set x's trailing zeroes to ones and zero the rest. 66 x = (x ^ (x - 1)) >> 1; 67 68 // Increment count until there are just zero bits remaining. 69 while (x) { 70 count++; 71 x >>= 1; 72 } 73 74 return count; 75 #endif 76 } 77 78 /// Count number of set bits in bit field. 79 unsigned xpopcount(uint64_t x) 80 { 81 // Use compiler builtin if possible. 82 #if defined(__NetBSD__) 83 return popcount64(x); 84 #elif defined(__clang__) || defined(__GNUC__) 85 return (unsigned)__builtin_popcountll(x); 86 #else 87 unsigned count = 0; 88 for (; x != 0; x >>= 1) { 89 if (x & 1) { 90 count++; 91 } 92 } 93 return count; 94 #endif 95 } 96 97 /// For overflow detection, add a digit safely to an int value. 98 int vim_append_digit_int(int *value, int digit) 99 { 100 int x = *value; 101 if (x > ((INT_MAX - digit) / 10)) { 102 return FAIL; 103 } 104 *value = x * 10 + digit; 105 return OK; 106 } 107 108 /// Return something that fits into an int. 109 int trim_to_int(int64_t x) 110 { 111 return x > INT_MAX ? INT_MAX : x < INT_MIN ? INT_MIN : (int)x; 112 }