neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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 }