/**
 * Bit twiddling hacks for JavaScript.
 *
 * Author: Mikola Lysenko
 *
 * Ported from Stanford bit twiddling hack library:
 *    http://graphics.stanford.edu/~seander/bithacks.html
 */

//Number of bits in an integer
var INT_BITS = 32;

//Constants
export const INT_BITS1 = 32;
export const INT_MAX = 0x7fffffff;
export const INT_MIN = -1 << (INT_BITS - 1);

//Computes absolute value of integer
export function abs(v) {
  var mask = v >> (INT_BITS - 1);
  return (v ^ mask) - mask;
}

//Computes minimum of integers x and y
export function min(x, y) {
  return y ^ ((x ^ y) & -(x < y));
}

//Computes maximum of integers x and y
export function max(x, y) {
  return x ^ ((x ^ y) & -(x < y));
}

//Checks if a number is a power of two
export function isPow2(v) {
  return !(v & (v - 1)) && (!!v);
}

//Computes log base 2 of v
export function log2(v) {
  //Ts报错，但实际可运行
  var r, shift;
  r =     Number(v > 0xFFFF) << 4; v >>>= r;
  shift = Number(v > 0xFF  ) << 3; v >>>= shift; r |= shift;
  shift = Number(v > 0xF   ) << 2; v >>>= shift; r |= shift;
  shift = Number(v > 0x3   ) << 1; v >>>= shift; r |= shift;
  return r | (v >> 1);
}

//Computes log base 10 of v
export function log10(v) {
  return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
    (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
      (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
}

//Counts number of bits
export function popCount(v) {
  v = v - ((v >>> 1) & 0x55555555);
  v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
  return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
}

//Counts number of trailing zeros
export function countTrailingZeros(v) {
  var c = 32;
  v &= -v;
  if (v) c--;
  if (v & 0x0000FFFF) c -= 16;
  if (v & 0x00FF00FF) c -= 8;
  if (v & 0x0F0F0F0F) c -= 4;
  if (v & 0x33333333) c -= 2;
  if (v & 0x55555555) c -= 1;
  return c;
};

//Rounds to next power of 2
export function nextPow2(v) {
  v += v === 0;
  --v;
  v |= v >>> 1;
  v |= v >>> 2;
  v |= v >>> 4;
  v |= v >>> 8;
  v |= v >>> 16;
  return v + 1;
}

//Rounds down to previous power of 2
export function prevPow2(v) {
  v |= v >>> 1;
  v |= v >>> 2;
  v |= v >>> 4;
  v |= v >>> 8;
  v |= v >>> 16;
  return v - (v >>> 1);
}

//Computes parity of word
export function parity(v) {
  v ^= v >>> 16;
  v ^= v >>> 8;
  v ^= v >>> 4;
  v &= 0xf;
  return (0x6996 >>> v) & 1;
}

var REVERSE_TABLE = new Array(256);

(function (tab) {
  for (var i = 0; i < 256; ++i) {
    var v = i, r = i, s = 7;
    for (v >>>= 1; v; v >>>= 1) {
      r <<= 1;
      r |= v & 1;
      --s;
    }
    tab[i] = (r << s) & 0xff;
  }
})(REVERSE_TABLE);

//Reverse bits in a 32 bit word
export function reverse(v) {
  return (REVERSE_TABLE[v & 0xff] << 24) |
    (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) |
    (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) |
    REVERSE_TABLE[(v >>> 24) & 0xff];
}

//Interleave bits of 2 coordinates with 16 bits.  Useful for fast quadtree codes
export function interleave2(x, y) {
  x &= 0xFFFF;
  x = (x | (x << 8)) & 0x00FF00FF;
  x = (x | (x << 4)) & 0x0F0F0F0F;
  x = (x | (x << 2)) & 0x33333333;
  x = (x | (x << 1)) & 0x55555555;

  y &= 0xFFFF;
  y = (y | (y << 8)) & 0x00FF00FF;
  y = (y | (y << 4)) & 0x0F0F0F0F;
  y = (y | (y << 2)) & 0x33333333;
  y = (y | (y << 1)) & 0x55555555;

  return x | (y << 1);
}

//Extracts the nth interleaved component
export function deinterleave2(v, n) {
  v = (v >>> n) & 0x55555555;
  v = (v | (v >>> 1)) & 0x33333333;
  v = (v | (v >>> 2)) & 0x0F0F0F0F;
  v = (v | (v >>> 4)) & 0x00FF00FF;
  v = (v | (v >>> 16)) & 0x000FFFF;
  return (v << 16) >> 16;
}


//Interleave bits of 3 coordinates, each with 10 bits.  Useful for fast octree codes
export function interleave3(x, y, z) {
  x &= 0x3FF;
  x = (x | (x << 16)) & 4278190335;
  x = (x | (x << 8)) & 251719695;
  x = (x | (x << 4)) & 3272356035;
  x = (x | (x << 2)) & 1227133513;

  y &= 0x3FF;
  y = (y | (y << 16)) & 4278190335;
  y = (y | (y << 8)) & 251719695;
  y = (y | (y << 4)) & 3272356035;
  y = (y | (y << 2)) & 1227133513;
  x |= (y << 1);

  z &= 0x3FF;
  z = (z | (z << 16)) & 4278190335;
  z = (z | (z << 8)) & 251719695;
  z = (z | (z << 4)) & 3272356035;
  z = (z | (z << 2)) & 1227133513;

  return x | (z << 2);
}

//Extracts nth interleaved component of a 3-tuple
export function deinterleave3(v, n) {
  v = (v >>> n) & 1227133513;
  v = (v | (v >>> 2)) & 3272356035;
  v = (v | (v >>> 4)) & 251719695;
  v = (v | (v >>> 8)) & 4278190335;
  v = (v | (v >>> 16)) & 0x3FF;
  return (v << 22) >> 22;
}

//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
export function nextCombination(v) {
  var t = v | (v - 1);
  return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
}

