defmodule CPSolver.BitUtils do
import Bitwise
@all_ones_mask (1 <<< 64) - 1
## Find least significant bit for given number
def lsb(n, method \\ :debruijn)
def lsb(0, _method) do
nil
end
def lsb(n, :shift) do
lsb_impl(n, 0)
end
def lsb(n, :debruijn) do
sequence = 0x022FDD63CC95386D
## Complement, multiply and normalize to 64-bit
normalized = (n &&& -n) * sequence &&& @all_ones_mask
## Use first 6 bits to locate in index table
## || lsb(n, :shift)
deBruijnTable(sequence, normalized >>> 58)
end
defp lsb_impl(1, idx) do
idx
end
defp lsb_impl(n, idx) do
((n &&& 1) == 1 && idx) ||
lsb_impl(n >>> 1, idx + 1)
end
## Find most significant bit for given number
def msb(n, method \\ :debruijn)
def msb(0, _method), do: nil
def msb(n, :debruijn) do
sequence = 0x03F79D71B4CB0A89
if n > 0 do
n = n ||| n >>> 1
n = n ||| n >>> 2
n = n ||| n >>> 4
n = n ||| n >>> 8
n = n ||| n >>> 16
n = n ||| n >>> 32
normalized = (n * sequence) &&& @all_ones_mask
deBruijnTable(sequence, normalized >>> 58)
end
end
def msb(n, :log2) do
if n > 0 do
n = n ||| n >>> 1
n = n ||| n >>> 2
n = n ||| n >>> 4
n = n ||| n >>> 8
n = n ||| n >>> 16
n = n ||| n >>> 32
log2(n - (n >>> 1))
end
end
def bit_count(0) do
0
end
def bit_count(n) do
n = (n &&& 0x5555555555555555) + (n >>> 1 &&& 0x5555555555555555)
n = (n &&& 0x3333333333333333) + (n >>> 2 &&& 0x3333333333333333)
n = (n &&& 0x0F0F0F0F0F0F0F0F) + (n >>> 4 &&& 0x0F0F0F0F0F0F0F0F)
n = (n &&& 0x00FF00FF00FF00FF) + (n >>> 8 &&& 0x00FF00FF00FF00FF)
n = (n &&& 0x0000FFFF0000FFFF) + (n >>> 16 &&& 0x0000FFFF0000FFFF)
(n &&& 0x00000000FFFFFFFF) + (n >>> 32 &&& 0x00000000FFFFFFFF)
end
## Precompiled log2 values for powers of 2
defp log2(1), do: 0
defp log2(2), do: 1
defp log2(4), do: 2
defp log2(8), do: 3
defp log2(16), do: 4
defp log2(32), do: 5
defp log2(64), do: 6
defp log2(128), do: 7
defp log2(256), do: 8
defp log2(512), do: 9
defp log2(1024), do: 10
defp log2(2048), do: 11
defp log2(4096), do: 12
defp log2(8192), do: 13
defp log2(16384), do: 14
defp log2(32768), do: 15
defp log2(65536), do: 16
defp log2(131_072), do: 17
defp log2(262_144), do: 18
defp log2(524_288), do: 19
defp log2(1_048_576), do: 20
defp log2(2_097_152), do: 21
defp log2(4_194_304), do: 22
defp log2(8_388_608), do: 23
defp log2(16_777_216), do: 24
defp log2(33_554_432), do: 25
defp log2(67_108_864), do: 26
defp log2(134_217_728), do: 27
defp log2(268_435_456), do: 28
defp log2(536_870_912), do: 29
defp log2(1_073_741_824), do: 30
defp log2(2_147_483_648), do: 31
defp log2(4_294_967_296), do: 32
defp log2(8_589_934_592), do: 33
defp log2(17_179_869_184), do: 34
defp log2(34_359_738_368), do: 35
defp log2(68_719_476_736), do: 36
defp log2(137_438_953_472), do: 37
defp log2(274_877_906_944), do: 38
defp log2(549_755_813_888), do: 39
defp log2(1_099_511_627_776), do: 40
defp log2(2_199_023_255_552), do: 41
defp log2(4_398_046_511_104), do: 42
defp log2(8_796_093_022_208), do: 43
defp log2(17_592_186_044_416), do: 44
defp log2(35_184_372_088_832), do: 45
defp log2(70_368_744_177_664), do: 46
defp log2(140_737_488_355_328), do: 47
defp log2(281_474_976_710_656), do: 48
defp log2(562_949_953_421_312), do: 49
defp log2(1_125_899_906_842_624), do: 50
defp log2(2_251_799_813_685_248), do: 51
defp log2(4_503_599_627_370_496), do: 52
defp log2(9_007_199_254_740_992), do: 53
defp log2(18_014_398_509_481_984), do: 54
defp log2(36_028_797_018_963_968), do: 55
defp log2(72_057_594_037_927_936), do: 56
defp log2(144_115_188_075_855_872), do: 57
defp log2(288_230_376_151_711_744), do: 58
defp log2(576_460_752_303_423_488), do: 59
defp log2(1_152_921_504_606_846_976), do: 60
defp log2(2_305_843_009_213_693_952), do: 61
defp log2(4_611_686_018_427_387_904), do: 62
defp log2(9_223_372_036_854_775_808), do: 63
## De Bruijn table for sequence 0x022FDD63CC95386D
## Used for LSB
defp deBruijnTable(0x022FDD63CC95386D, 0), do: 0
defp deBruijnTable(0x022FDD63CC95386D, 1), do: 1
defp deBruijnTable(0x022FDD63CC95386D, 2), do: 2
defp deBruijnTable(0x022FDD63CC95386D, 3), do: 53
defp deBruijnTable(0x022FDD63CC95386D, 4), do: 3
defp deBruijnTable(0x022FDD63CC95386D, 5), do: 7
defp deBruijnTable(0x022FDD63CC95386D, 6), do: 54
defp deBruijnTable(0x022FDD63CC95386D, 7), do: 27
defp deBruijnTable(0x022FDD63CC95386D, 8), do: 4
defp deBruijnTable(0x022FDD63CC95386D, 9), do: 38
defp deBruijnTable(0x022FDD63CC95386D, 10), do: 41
defp deBruijnTable(0x022FDD63CC95386D, 11), do: 8
defp deBruijnTable(0x022FDD63CC95386D, 12), do: 34
defp deBruijnTable(0x022FDD63CC95386D, 13), do: 55
defp deBruijnTable(0x022FDD63CC95386D, 14), do: 48
defp deBruijnTable(0x022FDD63CC95386D, 15), do: 28
defp deBruijnTable(0x022FDD63CC95386D, 16), do: 62
defp deBruijnTable(0x022FDD63CC95386D, 17), do: 5
defp deBruijnTable(0x022FDD63CC95386D, 18), do: 39
defp deBruijnTable(0x022FDD63CC95386D, 19), do: 46
defp deBruijnTable(0x022FDD63CC95386D, 20), do: 44
defp deBruijnTable(0x022FDD63CC95386D, 21), do: 42
defp deBruijnTable(0x022FDD63CC95386D, 22), do: 22
defp deBruijnTable(0x022FDD63CC95386D, 23), do: 9
defp deBruijnTable(0x022FDD63CC95386D, 24), do: 24
defp deBruijnTable(0x022FDD63CC95386D, 25), do: 35
defp deBruijnTable(0x022FDD63CC95386D, 26), do: 59
defp deBruijnTable(0x022FDD63CC95386D, 27), do: 56
defp deBruijnTable(0x022FDD63CC95386D, 28), do: 49
defp deBruijnTable(0x022FDD63CC95386D, 29), do: 18
defp deBruijnTable(0x022FDD63CC95386D, 30), do: 29
defp deBruijnTable(0x022FDD63CC95386D, 31), do: 11
defp deBruijnTable(0x022FDD63CC95386D, 32), do: 63
defp deBruijnTable(0x022FDD63CC95386D, 33), do: 52
defp deBruijnTable(0x022FDD63CC95386D, 34), do: 6
defp deBruijnTable(0x022FDD63CC95386D, 35), do: 26
defp deBruijnTable(0x022FDD63CC95386D, 36), do: 37
defp deBruijnTable(0x022FDD63CC95386D, 37), do: 40
defp deBruijnTable(0x022FDD63CC95386D, 38), do: 33
defp deBruijnTable(0x022FDD63CC95386D, 39), do: 47
defp deBruijnTable(0x022FDD63CC95386D, 40), do: 61
defp deBruijnTable(0x022FDD63CC95386D, 41), do: 45
defp deBruijnTable(0x022FDD63CC95386D, 42), do: 43
defp deBruijnTable(0x022FDD63CC95386D, 43), do: 21
defp deBruijnTable(0x022FDD63CC95386D, 44), do: 23
defp deBruijnTable(0x022FDD63CC95386D, 45), do: 58
defp deBruijnTable(0x022FDD63CC95386D, 46), do: 17
defp deBruijnTable(0x022FDD63CC95386D, 47), do: 10
defp deBruijnTable(0x022FDD63CC95386D, 48), do: 51
defp deBruijnTable(0x022FDD63CC95386D, 49), do: 25
defp deBruijnTable(0x022FDD63CC95386D, 50), do: 36
defp deBruijnTable(0x022FDD63CC95386D, 51), do: 32
defp deBruijnTable(0x022FDD63CC95386D, 52), do: 60
defp deBruijnTable(0x022FDD63CC95386D, 53), do: 20
defp deBruijnTable(0x022FDD63CC95386D, 54), do: 57
defp deBruijnTable(0x022FDD63CC95386D, 55), do: 16
defp deBruijnTable(0x022FDD63CC95386D, 56), do: 50
defp deBruijnTable(0x022FDD63CC95386D, 57), do: 31
defp deBruijnTable(0x022FDD63CC95386D, 58), do: 19
defp deBruijnTable(0x022FDD63CC95386D, 59), do: 15
defp deBruijnTable(0x022FDD63CC95386D, 60), do: 30
defp deBruijnTable(0x022FDD63CC95386D, 61), do: 14
defp deBruijnTable(0x022FDD63CC95386D, 62), do: 13
defp deBruijnTable(0x022FDD63CC95386D, 63), do: 12
## De Bruijn table for sequence 0x03F79D71B4CB0A89
## Used for MSB
defp deBruijnTable(0x03F79D71B4CB0A89, 0), do: 0
defp deBruijnTable(0x03F79D71B4CB0A89, 1), do: 47
defp deBruijnTable(0x03F79D71B4CB0A89, 2), do: 1
defp deBruijnTable(0x03F79D71B4CB0A89, 3), do: 56
defp deBruijnTable(0x03F79D71B4CB0A89, 4), do: 48
defp deBruijnTable(0x03F79D71B4CB0A89, 5), do: 27
defp deBruijnTable(0x03F79D71B4CB0A89, 6), do: 2
defp deBruijnTable(0x03F79D71B4CB0A89, 7), do: 60
defp deBruijnTable(0x03F79D71B4CB0A89, 8), do: 57
defp deBruijnTable(0x03F79D71B4CB0A89, 9), do: 49
defp deBruijnTable(0x03F79D71B4CB0A89, 10), do: 41
defp deBruijnTable(0x03F79D71B4CB0A89, 11), do: 37
defp deBruijnTable(0x03F79D71B4CB0A89, 12), do: 28
defp deBruijnTable(0x03F79D71B4CB0A89, 13), do: 16
defp deBruijnTable(0x03F79D71B4CB0A89, 14), do: 3
defp deBruijnTable(0x03F79D71B4CB0A89, 15), do: 61
defp deBruijnTable(0x03F79D71B4CB0A89, 16), do: 54
defp deBruijnTable(0x03F79D71B4CB0A89, 17), do: 58
defp deBruijnTable(0x03F79D71B4CB0A89, 18), do: 35
defp deBruijnTable(0x03F79D71B4CB0A89, 19), do: 52
defp deBruijnTable(0x03F79D71B4CB0A89, 20), do: 50
defp deBruijnTable(0x03F79D71B4CB0A89, 21), do: 42
defp deBruijnTable(0x03F79D71B4CB0A89, 22), do: 21
defp deBruijnTable(0x03F79D71B4CB0A89, 23), do: 44
defp deBruijnTable(0x03F79D71B4CB0A89, 24), do: 38
defp deBruijnTable(0x03F79D71B4CB0A89, 25), do: 32
defp deBruijnTable(0x03F79D71B4CB0A89, 26), do: 29
defp deBruijnTable(0x03F79D71B4CB0A89, 27), do: 23
defp deBruijnTable(0x03F79D71B4CB0A89, 28), do: 17
defp deBruijnTable(0x03F79D71B4CB0A89, 29), do: 11
defp deBruijnTable(0x03F79D71B4CB0A89, 30), do: 4
defp deBruijnTable(0x03F79D71B4CB0A89, 31), do: 62
defp deBruijnTable(0x03F79D71B4CB0A89, 32), do: 46
defp deBruijnTable(0x03F79D71B4CB0A89, 33), do: 55
defp deBruijnTable(0x03F79D71B4CB0A89, 34), do: 26
defp deBruijnTable(0x03F79D71B4CB0A89, 35), do: 59
defp deBruijnTable(0x03F79D71B4CB0A89, 36), do: 40
defp deBruijnTable(0x03F79D71B4CB0A89, 37), do: 36
defp deBruijnTable(0x03F79D71B4CB0A89, 38), do: 15
defp deBruijnTable(0x03F79D71B4CB0A89, 39), do: 53
defp deBruijnTable(0x03F79D71B4CB0A89, 40), do: 34
defp deBruijnTable(0x03F79D71B4CB0A89, 41), do: 51
defp deBruijnTable(0x03F79D71B4CB0A89, 42), do: 20
defp deBruijnTable(0x03F79D71B4CB0A89, 43), do: 43
defp deBruijnTable(0x03F79D71B4CB0A89, 44), do: 31
defp deBruijnTable(0x03F79D71B4CB0A89, 45), do: 22
defp deBruijnTable(0x03F79D71B4CB0A89, 46), do: 10
defp deBruijnTable(0x03F79D71B4CB0A89, 47), do: 45
defp deBruijnTable(0x03F79D71B4CB0A89, 48), do: 25
defp deBruijnTable(0x03F79D71B4CB0A89, 49), do: 39
defp deBruijnTable(0x03F79D71B4CB0A89, 50), do: 14
defp deBruijnTable(0x03F79D71B4CB0A89, 51), do: 33
defp deBruijnTable(0x03F79D71B4CB0A89, 52), do: 19
defp deBruijnTable(0x03F79D71B4CB0A89, 53), do: 30
defp deBruijnTable(0x03F79D71B4CB0A89, 54), do: 9
defp deBruijnTable(0x03F79D71B4CB0A89, 55), do: 24
defp deBruijnTable(0x03F79D71B4CB0A89, 56), do: 13
defp deBruijnTable(0x03F79D71B4CB0A89, 57), do: 18
defp deBruijnTable(0x03F79D71B4CB0A89, 58), do: 8
defp deBruijnTable(0x03F79D71B4CB0A89, 59), do: 12
defp deBruijnTable(0x03F79D71B4CB0A89, 60), do: 7
defp deBruijnTable(0x03F79D71B4CB0A89, 61), do: 6
defp deBruijnTable(0x03F79D71B4CB0A89, 62), do: 5
defp deBruijnTable(0x03F79D71B4CB0A89, 63), do: 63
end