aboutsummaryrefslogtreecommitdiff
path: root/vim/bundle/tlib_vim/autoload/tlib/bitwise.vim
blob: 54a4258d77c265455672a0516d5e4d672cc9fc82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
" @Author:      Tom Link (mailto:micathom AT gmail com?subject=[vim])
" @License:     GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Revision:    124


function! tlib#bitwise#Num2Bits(num) "{{{3
    if type(a:num) <= 1 || type(a:num) == 5
        let bits = reverse(tlib#number#ConvertBase(a:num, 2, 'list'))
    elseif type(a:num) == 3
        let bits = copy(a:num)
    else
        throw "tlib#bitwise#Num2Bits: Must be number of list: ". string(a:num)
    endif
    return bits
endf


function! tlib#bitwise#Bits2Num(bits, ...) "{{{3
    let base = a:0 >= 1 ? a:1 : 10
    " TLogVAR a:bits
    let num = 0.0
    for i in range(len(a:bits))
        if get(a:bits, i, 0)
            let num += pow(2, i)
        endif
    endfor
    " TLogVAR num
    if base == 10
        if type(base) == 5
            return num
        else
            return float2nr(num)
        endif
    else
        return tlib#number#ConvertBase(num, base)
    endif
endf


function! tlib#bitwise#AND(num1, num2, ...) "{{{3
    let rtype = a:0 >= 1 ? a:1 : 'num'
    return s:BitwiseComparison(a:num1, a:num2, rtype,
                \ 'get(bits1, v:val) && get(bits2, v:val)')
endf


function! tlib#bitwise#OR(num1, num2, ...) "{{{3
    let rtype = a:0 >= 1 ? a:1 : 'num'
    return s:BitwiseComparison(a:num1, a:num2, rtype,
                \ 'get(bits1, v:val) || get(bits2, v:val)')
endf


function! tlib#bitwise#XOR(num1, num2, ...) "{{{3
    let rtype = a:0 >= 1 ? a:1 : 'num'
    return s:BitwiseComparison(a:num1, a:num2, rtype,
                \ 'get(bits1, v:val) ? !get(bits2, v:val) : get(bits2, v:val)')
endf


function! s:BitwiseComparison(num1, num2, rtype, expr) "{{{3
    let bits1 = tlib#bitwise#Num2Bits(a:num1)
    let bits2 = tlib#bitwise#Num2Bits(a:num2)
    let range = range(max([len(bits1), len(bits2)]))
    let bits = map(range, a:expr)
    if a:rtype == 'num' || (a:rtype == 'auto' && type(a:num1) <= 1)
        return tlib#bitwise#Bits2Num(bits)
    else
        return bits
    endif
endf


function! tlib#bitwise#ShiftRight(bits, n) "{{{3
    let bits = a:bits[a:n : -1]
    if empty(bits)
        let bits = [0]
    endif
    return bits
endf


function! tlib#bitwise#ShiftLeft(bits, n) "{{{3
    let bits = repeat([0], a:n) + a:bits
    return bits
endf


function! tlib#bitwise#Add(num1, num2, ...) "{{{3
    let rtype = a:0 >= 1 ? a:1 : 'num'
    let bits1 = tlib#bitwise#Num2Bits(a:num1)
    let bits2 = tlib#bitwise#Num2Bits(a:num2)
    let range = range(max([len(bits1), len(bits2)]))
    " TLogVAR bits1, bits2, range
    let carry = 0
    let bits  = []
    for i in range
        let sum = get(bits1, i) + get(bits2, i) + carry
        if sum == 3
            let bit = 1
            let carry = 1
        elseif sum == 2
            let bit = 0
            let carry = 1
        elseif sum == 1
            let bit = 1
            let carry = 0
        elseif sum == 0
            let bit = 0
            let carry = 0
        endif
        call add(bits, bit)
        " TLogVAR i, bits, bit
    endfor
    if carry == 1
        call add(bits, carry)
    endif
    if rtype == 'num' || (rtype == 'auto' && type(a:num1) <= 1)
        return tlib#bitwise#Bits2Num(bits)
    else
        return bits
    endif
endf


function! tlib#bitwise#Sub(num1, num2, ...) "{{{3
    let rtype = a:0 >= 1 ? a:1 : 'num'
    let bits1 = tlib#bitwise#Num2Bits(a:num1)
    let bits2 = tlib#bitwise#Num2Bits(a:num2)
    let range = range(max([len(bits1), len(bits2)]))
    let bits2 = map(range, '!get(bits2, v:val)')
    let bits2 = tlib#bitwise#Add(bits2, [1], 'bits')
    let bits3 = tlib#bitwise#Add(bits1, bits2, 'bits')
    let bits = bits3[0 : -2]
    if rtype == 'num' || (rtype == 'auto' && type(a:num1) <= 1)
        return tlib#bitwise#Bits2Num(bits)
    else
        return bits
    endif
endf